Skip to main content
Glama

unified-memory-mcp

One MCP server for two memory surfaces: semantic facts (mem0) and a code knowledge graph (codebase-memory) — plus the join between them.

Two MCP servers used to live behind stdio transport. MCP stdio means the client spawns the server, so every editor session and every project directory got its own copy. On one machine that was 13+ processes and ~1 GB of RAM for the same two servers — and the fact store's embedded Qdrant collection is single-process locked, so the extra copies were contending for the same lock instead of adding capacity.

This package serves both surfaces from one process over Streamable HTTP, and adds what merging makes possible: facts can be linked to the symbols they describe, so recall returns the answer and the code.

┌── opencode / claude / cursor …─┐
        memory_add_memory      memory_search_graph
        memory_remember_fact   memory_trace_path
        memory_recall          memory_fact_freshness
        memory_facts_for_symbol memory_fact_impact
        memory_facts_by_project memory_expired_facts
        memory_index_repository …           ← one shared process
└───────────────┬────────────────────────────┘
                │ 127.0.0.1:8777/mcp  (stateless HTTP)
     ┌──────────┴───────────┐
     │  mem0 (facts)        │  codebase-memory (code graph)
     │  Qdrant + history.db │  one warm child, index in RAM
     └──────────────────────┘

Why the join matters

Tool

Question it answers

remember_fact(text, symbols=[…])

Store a fact and pin it to the code it describes — the symbol is resolved to its qualified name + file and kept in the fact's metadata

recall(query)

Give me the answer and the code — one fused call over facts and graph symbols, with facts_linked_to_code calling out the overlap

facts_for_symbol(symbol)

What do we know about this function? — the reverse index

fact_freshness(memory_id)

Is this old fact still true? — re-checks that every linked symbol still exists, that no file moved, and that the fact's TTL has not passed

fact_impact(memory_id)

What breaks if I touch this? — callers/callees of every linked symbol, optionally plus the impact of the current working-tree changes

Facts can also be scoped to a project (project on write and read) so a finding from one project never pollutes another project's recall, tagged with their session (captured automatically from the MCP request _meta), and given a TTL (stale_after_days / stale_after) so facts about code decay instead of being trusted forever.

Related MCP server: baron

Install

pip install unified-memory-mcp

Straight from the tagged GitHub release (no PyPI account needed):

pip install "unified-memory-mcp @ git+https://github.com/tonpai1007/unified-memory-mcp@v0.1.0"

The fact store works standalone (the package builds the same store with mem0ai directly). To instead reuse the upstream local-store mem0 MCP module verbatim — identical store layout, history.db bookkeeping and embedder config — install it from git:

pip install "git+https://github.com/zfy258/mem0-mcp-server.git"

Note: the PyPI distribution mem0-mcp-server (0.2.x) is a hosted-API client with a different contract; this package detects that and falls back to the direct mem0ai path.

The code graph is an optional external dependency — it is not bundled:

# see https://github.com/DeusData/codebase-memory-mcp for install options
codebase-memory-mcp --help

Without it, every fact tool still works; the graph tools return a clear error.

Run

unified-memory-mcp                 # Streamable HTTP on 127.0.0.1:8777/mcp
unified-memory-mcp --stdio         # stdio transport, for clients that need it
unified-memory-mcp --port 9000     # custom port

Keep it alive (it is a shared service, so something should supervise it):

python -m unified_memory.watchdog

The watchdog probes the port every 45 s, restarts the server when it dies (with a grace period, so a booting server is not killed again), and can re-index the graph on a schedule:

export CODEBASE_MEMORY_REFRESH_MINUTES=30
export CODEBASE_MEMORY_REFRESH_TARGETS="MyProject=/path/to/repo"

Client configuration

OpenCode (~/.config/opencode/opencode.jsonc):

{
  "mcp": {
    "servers": {
      "memory": {
        "type": "remote",
        "url": "http://127.0.0.1:8777/mcp"
      }
    }
  }
}

Claude Desktop / Cursor / any stdio client:

{
  "mcpServers": {
    "memory": {
      "command": "unified-memory-mcp",
      "args": ["--stdio"]
    }
  }
}

Environment

Variable

Default

Meaning

MEM0_DIR

~/.amadeus-memory

fact store root (Qdrant + history.db)

MEM0_HOST / MEM0_PORT

127.0.0.1 / 8777

HTTP bind address

CODEBASE_MEMORY_EXE

auto-detected

path to the codebase-memory binary

CODEBASE_MEMORY_PROJECT

auto (CWD's project)

default project for graph queries

CODEBASE_MEMORY_REFRESH_MINUTES

0 (off)

scheduled graph refresh interval

CODEBASE_MEMORY_REFRESH_TARGETS

–

name=/path pairs to re-index

OPENAI_API_KEY

ignored

deliberately unset: the store is 512-dim FastEmbed and must not flip to OpenAI embeddings

Design notes

  • Stateless HTTP. Each POST is self-contained, so a server restart does not invalidate the MCP session ids held by connected clients. With session state enabled, clients keep posting a stale id and get HTTP 400 with no auto-reconnect.

  • One warm graph child. The graph child lives in a dedicated thread with its own event loop. It cannot be owned by a request handler — anyio's stdio_client raises "Attempted to exit a cancel scope in a different task than it was entered in" — and stateless HTTP makes every request its own task. Spawning the CLI per call instead reloads the whole index every time (7.4–8.5 s measured, versus tens of milliseconds warm).

  • Client-side scoping. Upstream mem0 filters only on user_id/agent_id, so project scoping and TTL flags are applied here (over-fetch, then filter) rather than in the store.

Releasing

  1. Bump version in pyproject.toml and add a CHANGELOG.md entry.

  2. Tag and push: git tag -a vX.Y.Z -m "…" && git push origin vX.Y.Z → release.yml builds, runs twine check, creates the GitHub release and publishes to PyPI.

  3. Publishing to PyPI needs a publisher registered for this repository:

    • Trusted publishing (recommended) — on PyPI: Account → Publishing → Add a new publisher → GitHub, owner tonpai1007, repository unified-memory-mcp, workflow release.yml. The workflow requests an OIDC token (id-token: write) and PyPI exchanges it.

    • API token — create a token on PyPI and add it as the repository secret PYPI_API_TOKEN; the workflow uses it when present.

Both paths work with the same workflow; with neither configured the GitHub release is still created and only the PyPI step fails.

Licence

Apache-2.0 — see LICENSE.

This package builds on mem0 (Apache-2.0) and can optionally use the upstream mem0-mcp-server module (Apache-2.0) verbatim; see NOTICE. The code graph comes from the separate codebase-memory-mcp project, which is an optional runtime dependency and is not redistributed here.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables coding agents to keep a local knowledge graph across sessions and checkpoints, restoring project context after tabs or model changes, and to ground every answer with an explicit verdict from the graph. Runs entirely on the user's machine over MCP/stdio or local JSON-RPC with no third-party runtime dependencies.
      13
      Apache 2.0
    • A
      license
      Not graded
      quality
      B
      maintenance
      Serves a repository's code knowledge graph over stdio (MCP) so coding agents can look up symbols, trace callers and callees, compute blast radius, list file symbols, run hybrid lexical-plus-graph search, and get citation-grounded answers from file:line evidence instead of guessing from text chunks. All tools work offline straight from the graph, with prose synthesis only when an OpenAI-compatible LLM endpoint is configured.
      16
      MIT
    • A
      license
      Not graded
      quality
      A
      maintenance
      Serves focused context from a local SQLite structural code graph so agents can find relevant entities and relationships before reading whole files. It also carries recorded project memory and mistakes into later sessions via CLI, hooks, and an authenticated local dashboard.
      28 npm
      MIT