The Problem
AI agents (LangGraph, CrewAI, AutoGen, Claude) lack persistent memory across runs. Each conversation starts from zero—no shared context, no accumulated decisions, no causal knowledge graph. Teams end up gluing together Redis, Pinecone, and custom code to give agents continuity.
What This Does
mcp-memory-service is a self-hosted memory backend for AI agent pipelines. It exposes a REST API, MCP transport, OAuth 2.0 auth, CLI, and a web dashboard. Agents store decisions, share causal knowledge graphs, and retrieve context in ~5ms. The service supports remote MCP for browser-based claude.ai integration.
The repo is a portfolio of 8 self-contained projects, not a single codebase. The substantial ones: src/ (Python core service), claude-hooks/ (Claude Desktop integration hooks), scripts/ (operational tooling), and video/ (demo content).
How It Is Wired
Execution starts in claude-hooks/core/auto-capture-hook.js at main (reaches 69 functions). The traced path: main → loadConfig → fs.readFile — the hook reads config from the filesystem, then captures conversation transcripts via parseTranscript, extractTextContent, and storeMemory.
The Python server entry points are src/mcp_memory_service/server/__main__.py and src/mcp_memory_service/cli/main.py. main calls runTest 37 times, and runAllTests calls runTest 15 times — the test harness is a first-class citizen.
Highest-blast-radius modules:
src/mcp_memory_service/config.py— 42 modules import it; it's in an import cycle. Changing config ripples everywhere.src/mcp_memory_service/models/memory.py— 41 importers, 0 imports. Pure data model, stable.src/mcp_memory_service/web/app.py— imports 31 modules (instability 0.94); the web layer is a thin adapter over everything else.
Import cycles exist in config.py, storage/base.py, and storage/sqlite_vec.py. Breaking them requires extracting shared types or deferring imports. The cost: any change to these files risks circular-import failures at runtime.
File map:
src/mcp_memory_service/web/static/app.js— 204 functions; the dashboard frontendclaude-hooks/core/auto-capture-hook.js— 6 functions; captures Claude transcripts, writes filesclaude-hooks/utilities/session-tracker.js— 20 functions; session lifecycle, generates secrets, writes filesclaude-hooks/utilities/memory-client.js— 19 functions; connects via MCP or HTTP
The 21 filesystem-touching functions and 1 network call are the only external effects; the rest is internal computation.
How To Use It
Setup (from pyproject.toml):
pip install mcp-memory-service
# or
uv pip install mcp-memory-service
Run the server (from README):
MCP_STREAMABLE_HTTP_MODE=1 \
MCP_SSE_HOST=0.0.0.0 \
MCP_SSE_PORT=8765 \
MCP_OAUTH_ENABLED=true \
python -m mcp_memory_service.server
Configuration: copy .env.example to .env and set storage backend, OAuth credentials, and MCP mode. The service supports SQLite (with vector search) and other backends.
Real-World Use
A LangGraph pipeline where agents share memory:
from mcp_memory_service.client import MemoryClient
client = MemoryClient(base_url="http://localhost:8000")
client.store("user-preferences", {"theme": "dark", "timezone": "UTC"})
context = client.retrieve("user-preferences")
# Pass context into the next agent run
Code Health & Issues
Static analysis found 316 findings (69 high, 245 medium, 2 low) across 7 kinds:
- High — Import cycle members (9):
config.py,storage/base.py,storage/sqlite_vec.py. Circular imports can break at runtime. - High — Deep nesting (28):
models/memory.py,storage/base.py,storage/sqlite_vec.py— max depth 6. - High — Oversized files (8):
config.pyat 782 lines;storage/sqlite_vec.pyandstorage/base.pysimilar. High change-ripple. - High — Hub modules (4):
config.py(42 dependents),models/memory.py(41),storage/base.py(21). Churn here is wide-blast-radius. - Medium — Broad exception handling (9): bare
exceptinstorage/base.py,storage/sqlite_vec.py,__init__.py. - Medium — High branching density:
claude-hooks/utilities/context-formatter.js— 371 branch points / 954 lines. - Medium — File without context manager:
web/oauth/registration.py—open()not wrapped inwith.
SDLC observations from the file structure:
- High — Unpinned GitHub Actions:
.github/workflowsuses@v4/@v6tags, not commit SHAs. Tag-move attacks leak secrets. - High — Committed .env:
archive/configs/.env.sqlite.backupis tracked. Rotate anything it holds. - High —
continue-on-erroron correctness gates:.github/workflows/docker-publish.ymlline 141 — failing tests report green. - Medium — No dependency vulnerability scan in CI;
npm installinstead ofnpm ci; mutable base imagepython:3.12-slim; nopermissionsdeclaration; no non-rootUSERin Dockerfile.
The Bottom Line
The core service is well-structured (tests, CI, lockfile, license all present) but the codebase carries real maintenance debt: import cycles, oversized modules, and a 782-line config file. The claude-hooks layer is the most polished part. Use it if you need self-hosted agent memory without cloud lock-in — but budget time for the refactoring flagged above before scaling it.