octop-memory-server
English | 简体中文
A batteries-included, multi-tenant HTTP server wrapping octop-memory (Tencent Cloud's open-source long-term memory system for AI agents). One command gives you:
/mcp/— an MCP service (streamable HTTP) exposing 6 memory tools to agents/dashboard— a visual management console: browse / search / save memories- API key authentication — both entry points are protected by
X-API-Key - Physical isolation — each API key maps to its own tenant directory and its own SQLite database file; tenants never touch each other's data
┌────────────────────────────────────────────┐
Agent (MCP client)──▶│ /mcp/ X-API-Key ──▶ tenant=alice │
Browser (console)──▶ │ /dashboard X-API-Key ──▶ tenant=alice │──┐
Another agent ──▶ │ /mcp/ X-API-Key ──▶ tenant=bob │ │
└────────────────────────────────────────────┘ │
▼
data/tenants/
├── alice/memory.sqlite ← alice only
└── bob/memory.sqlite ← bob only
1. Quick Start
1.1 Install
pip install octop-memory-server # Python ≥ 3.12; dependencies (incl. octop-memory) pulled automatically
From source (development):
git clone <this-repo> octop-memory-server && cd octop-memory-server
pip install -e .
1.2 Configure API keys
Copy api_keys.json.example to api_keys.json and replace the keys:
{
"keys": {
"oag-paste-a-random-long-string-alice": { "tenant": "alice" },
"oag-another-random-string-bob": {
"tenant": "bob",
"llm": { "base_url": "http://localhost:11434/v1", "model": "qwen3:8b" }
}
}
}
Generate a random key: python -c "import secrets; print('oag-' + secrets.token_urlsafe(24))"
Edits to this file take effect immediately (hot reload) — no restart needed.
1.3 Start (CLI)
octop-memory-server # defaults to 127.0.0.1:8600
octop-memory-server --host 0.0.0.0 --port 8600 # serve externally
octop-memory-server --data-dir /srv/mem --keys-file /srv/mem/api_keys.json
octop-memory-server --llm-endpoint http://localhost:11434/v1 --llm-model qwen3:8b
octop-memory-server --reload # dev hot reload
octop-memory-server --version / --help
| Option | Default | Description |
|---|---|---|
--host |
127.0.0.1 |
Listen address |
--port |
8600 |
Listen port |
--data-dir |
./data |
Root directory for tenant data |
--keys-file |
./api_keys.json |
Path to the key manifest |
--llm-endpoint / --llm-model |
from env | Global default LLM (per-key config wins) |
Prefer plain uvicorn? uvicorn octop_memory_server.app:app --host 0.0.0.0 --port 8600.
- Dashboard:
http://localhost:8600/dashboard(paste your API key on first open) - MCP endpoint:
http://localhost:8600/mcp/ - Health check (no auth):
http://localhost:8600/health
2. Physical Isolation Design
Each API key maps 1:1 to a tenant, isolated at three layers:
| Layer | Mechanism | Notes |
|---|---|---|
| Directory | data/tenants/<tenant>/ |
Per-tenant directory; set OS permissions and back up independently |
| File | Own memory.sqlite |
SQLite WAL mode — zero sharing, zero lock contention between tenants |
| In-database | namespace t_<tenant> |
Table prefixes differ even if a db file were misconfigured — belt and suspenders |
Hard security guarantees (enforced in code):
- The db path and namespace are resolved server-side only from the API key; no REST/MCP endpoint ever accepts them from the client;
- Dashboard list queries use read-only connections (
file:...?mode=ro); - Table names are built solely from the normalized namespace
(
re.sub(r"[^a-z0-9_]", "_", ns)), ruling out SQL injection; - Keys are compared with
hmac.compare_digest(timing-safe); logs only record a 12-char SHA-256 fingerprint of each key.
⚠️
api_keys.jsoncurrently stores keys in plain text. On multi-admin machines, consider storing SHA-256 hashes instead (KeyEntryalready has fingerprint plumbing; the change toApiKeyStore.reload_if_neededis under ten lines).
3. /mcp/ — MCP Service
3.1 Client setup
MCP client configuration (e.g. the mcp.json of WorkBuddy / Claude Desktop / Cursor):
{
"mcpServers": {
"octop-memory": {
"url": "http://your-host:8600/mcp/",
"headers": { "X-API-Key": "oag-xxxx-alice" }
}
}
}
Issue one key per agent / user and you get "agents can't see each other's memories" for free.
3.2 Tools
| Tool | Description | Needs LLM |
|---|---|---|
memory_save(content, topic?) |
Explicitly save a long-term memory (fact / preference / decision) | No |
memory_recall(query, thread_id?, limit?) |
Recall and return a markdown block ready to inject into a prompt | No |
memory_search(query, max_results?, corpus?) |
Multi-source search (incl. the raw conversation layer), structured hits | No |
memory_get(path) |
Read source by virtual path: atom/<id>.md, raw/<date>/<id>.md, page/<entity>.md |
No |
memory_capture(user?, assistant?, session_id?) |
Capture one conversation turn as L0 raw events (privacy filtering applies) | No |
memory_extract(session_id) |
Distill a session's raw events into long-term memory (L0→L1→L2→L3) | Yes |
3.3 Recommended agent-side usage
In the agent loop: call memory_capture (non-blocking) at the end of each turn,
memory_extract on session end or when idle, and memory_recall while
assembling the system prompt. No capture, no raw material for extract.
4. /dashboard — Visual Management Console
A dependency-free single-page app (static/index.html). Paste your API key on
first open (stored in localStorage); it reconnects automatically afterwards.
| Tab | What it shows |
|---|---|
| Overview | Tenant info, db size, per-layer counts (L0/L1/L2/entities/digests/journal), recent-memory timeline |
| Atoms | Atom list with keyword search, deprecated filter, verbatim quotes, confidence/importance |
| Candidates | Review view (filter by promoted / needs_review / conflict / duplicate) |
| Raw events | L0 RawEvent browser, filterable by session |
| Tools | Manual memory save / recall test (preview the injected block) / session extract (needs LLM) |
REST API (all require X-API-Key, prefix /dashboard/api):
GET /tenant tenant & db info
GET /overview stats + recent memories
GET /atoms?q&include_deprecated&limit&offset
GET /atoms/{id} atom detail (source excerpt)
GET /candidates?status&limit&offset
GET /raw_events?session_id&event_type&limit&offset
POST /memory {"content","topic"} save
POST /recall {"query","limit","thread_id"} recall test
POST /extract {"session_id"} session extract (needs LLM, else 409)
Review actions (candidate promote/reject, gc, db slim) are deliberately not exposed to the dashboard/MCP — they are destructive or decision-making operations. Use the upstream CLI on the host when needed (
octop-memory --db data/tenants/<tenant>/memory.sqlite --namespace t_<tenant> candidate ...).
5. LLM Configuration (optional)
| Where | Priority | Scope |
|---|---|---|
Per-key llm field in api_keys.json |
High | A single tenant |
Env vars OCTOP_LLM_ENDPOINT / OCTOP_LLM_MODEL / OCTOP_LLM_MODEL_HEAVY |
Low | All tenants without their own config |
Without an LLM: save / recall / search / get / capture all work; only
extract (automatic distillation) and page regeneration are unavailable.
The endpoint can be any OpenAI-compatible API (OpenAI / Ollama / vLLM / etc.).
Other environment variables:
| Variable | Default | Description |
|---|---|---|
OCTOP_GW_DATA_DIR |
./data |
Root directory for tenant data |
OCTOP_GW_KEYS_FILE |
./api_keys.json |
Path to the key manifest |
OCTOP_GW_HOST |
octop-memory-server |
Host label written into RawEvents |
6. Deployment Notes
- Process: single uvicorn process,
--workers 1(SQLite has a single-writer model; for multi-worker writes switch to the PostgreSQL backend — see octop-memory'spostgresextra). - HTTPS: API keys travel in plain headers; put the service behind a TLS reverse proxy (nginx/caddy) for anything public-facing.
- Backup: just back up the
data/tenants/directory, or use the upstreamoctop-memory export/portable(.hmpkg) for cross-host migration. - Maintenance: run gc / consolidate / page regeneration via the upstream CLI on a scheduler during idle windows (aligns with upstream ADR-027):
octop-memory --db data/tenants/alice/memory.sqlite --namespace t_alice gc
octop-memory --db data/tenants/alice/memory.sqlite --namespace t_alice consolidate
- Monitoring: probe
/health; every tenant operation is logged with its tenant id and can be aggregated per directory.
7. Known Limitations
- Upstream octop-memory 1.0.0 is Alpha: the PostgreSQL backend and vector search (chroma/qdrant) are not verified with real integrations; this server uses the SQLite backend only (also the cleanest form of isolation).
- MCP's
memory_extractis synchronous; distilling a long session may exceed MCP client timeouts. Prefer running extraction from an external scheduler via the upstream CLI (candidate extract); keep MCP for reads/writes. - The dashboard shows candidates read-only; approve/reject actions require
upstream promotion internals — extend
dashboard_api.pyas needed.
8. Testing
pip install -e .
python smoke_test.py # 15 end-to-end checks: 401 auth, MCP handshake, cross-tenant isolation, dashboard REST
9. License & Acknowledgements
- This project is released under the MIT License.
- The core capability comes from Tencent Cloud's open-source octop-memory (MIT License). This project is a serving wrapper only (multi-tenant HTTP server / MCP / Dashboard) and does not modify upstream code. Report upstream issues to the original repository.
Metadata
Release files for octop-memory-server 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| octop_memory_server-0.1.0.tar.gz | 43.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| octop_memory_server-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 83.4 kB
Release files / octop_memory_server-0.1.0.tar.gz
| Download URL | octop_memory_server-0.1.0.tar.gz |
|---|---|
| Size | 43.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a6ff50a273ffa3e862789f6b4814ead8dc65bc72da79e74e60a215d6fac6512c
|
|
BLAKE2b-256 checksum How to use checksums |
ab704a946a48f77a1f6f552ff54bd2fe6538147d0ce41c644702684dd093819d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / octop_memory_server-0.1.0-py3-none-any.whl
| Download URL | octop_memory_server-0.1.0-py3-none-any.whl |
|---|---|
| Size | 40.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
04a32969aa88d1e64c184ba79cb90b655671f1d0d2c8ee39cba0e90bfc5a5f55
|
|
BLAKE2b-256 checksum How to use checksums |
b46ade12c77b0998dfc44ec1349beb6e5c92ba6b3915eab9f41e58eecbbe87f9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|