memtrace mcp
Runs the Memtrace MCP server so AI coding agents can query the code-intelligence graph — headless stdio by default, attaching to an already-running memtrace start daemon when one exists.
Usage#
memtrace mcp [--ui] [--debug] [--workspace <PATH|NAME>]memtrace mcp runs the Memtrace MCP server so AI coding agents — Claude Code, Claude Desktop, Cursor, Codex, Gemini CLI, and others — can query the code-intelligence graph through 75 registered MCP tools. This is the command your MCP client config launches: command="memtrace", args=["mcp"].
By default it speaks JSON-RPC over stdio and is headless — no UI port is bound unless you ask for one. If a memtrace start workspace runtime is already running for this repo, the MCP process automatically attaches to it (same MemDB, same data dirs) instead of opening its own store.
Setting up a new client? Clients has copy-paste config for each supported agent.
Flags#
| Flag | Description |
|---|---|
--ui | Also start the browser-facing dashboard/API listener on the UI port (default 3030, bound on 0.0.0.0). Without it the server is headless and prints a one-line notice to stderr. If the UI port is already taken — e.g. a running memtrace start — the bind failure is silently ignored: no error, no listener. |
--debug | Maximum tracing to stderr for all Memtrace crates. Equivalent to MEMTRACE_DEBUG=1. Honors RUST_LOG when set. |
--workspace <PATH|NAME> | PATH form hard-overrides MemDB/.memtrace data-dir resolution to PATH and writes a .memtrace-workspace marker there, so MCP children launched inside sibling repos converge on the same MemDB (exits 2 if the marker/dir can't be created). NAME form resolves a Named Workspace from the ~/.memtrace/workspaces/ registry and anchors the data dir there (exits 2 if no such workspace exists). |
Environment variables#
| Variable | Default | Description |
|---|---|---|
MEMTRACE_TRANSPORT | stdio | MCP transport. stdio (default) speaks JSON-RPC over stdio. streamable-http (aliases http, and legacy sse which prints a one-line deprecation hint) serves MCP over HTTP at http://0.0.0.0:<MEMTRACE_PORT>/mcp. Parsing is case-insensitive and whitespace-tolerant; any other value is a fatal error (exit 2) rather than a silent stdio fallback. |
MEMTRACE_PORT | 3000 | HTTP port for the MCP endpoint when transport isn't stdio. A bind failure is a hard error suggesting MEMTRACE_PORT=<free port>. |
MEMTRACE_UI_PORT | 3030 | Dashboard/API port used when --ui / MEMTRACE_MCP_UI=1 is set. When an active memtrace start runtime is detected, its UI port is adopted unless this is explicitly set. |
MEMTRACE_MCP_UI | unset (off) | Truthy value has the same effect as --ui: start the dashboard listener alongside the MCP server. |
MEMTRACE_MEMDB_MODE | local | How this process reaches MemDB: local (loopback memcore-server; aliases sidecar, server), embedded (in-process engine; aliases inprocess, in-process), or external (operator-managed remote gRPC endpoint; aliases hosted, remote). An unset mode with a non-loopback MEMTRACE_MEMDB_ENDPOINT infers external. |
MEMTRACE_MEMDB_ENDPOINT | http://127.0.0.1:50051 | MemDB gRPC endpoint, pinged at startup in local/external mode. Unreachable means the process prints "could not reach MemDB at <endpoint>" and exits 1. |
MEMTRACE_MEMDB_DATA_DIR | <workspace>/.memdb | On-disk MemDB data dir. Also where the workspace-owner state file (daemon-state.json) is looked up for owner attach. Setting it explicitly prevents runtime.json adoption from overriding it. |
MEMTRACE_DATA_DIR | .memtrace | Memtrace's own data dir (FTS indexes, caches). Explicitly setting it opts out of runtime.json adoption for this field. |
MEMTRACE_MEMDB_DB | memtrace | MemDB database name; explicitly setting it opts out of runtime.json adoption for this field. |
MEMTRACE_OWNER_ATTACH | unset (attach enabled) | Set to 0/false/off to disable attaching to an existing workspace runtime owner; the MCP process then uses its own env-derived config instead. |
MEMTRACE_NO_WATCH_RESTORE | unset (restore enabled) | Set to 1 to skip re-arming persisted directory watches from ~/.memtrace/watches.json at MCP startup. |
MEMTRACE_LICENSE_KEY | unset | License key for headless/CI use; checked after config, before the saved credentials file at ~/.config/memtrace/credentials.json. With no key found anywhere, the MCP server refuses to start (exit 1) and tells you to run memtrace auth login. |
MEMTRACE_DEBUG | unset | Truthy value has the same effect as --debug (verbose stderr tracing). |
Attach to owner#
memtrace mcp does not boot its own database in the default local mode. Instead it adopts a running memtrace start runtime in two layers:
- It reads
~/.memtrace/runtime.jsonand, if the writing process is alive and its git root matches the current repo, adopts its MemDB data dir, data dir, database name, and UI port — each skipped when the matchingMEMTRACE_*env var is explicitly set. - It then reads
<memdb_data_dir>/daemon-state.jsonand, if that owner's PID is alive and its loopback endpoint answers within 300ms, attaches to its endpoint/dirs and prints "attaching to existing workspace owner pid <pid>".
Runtime adoption is repo-scoped: ~/.memtrace/runtime.json is ignored when your cwd's git root differs from the one the daemon was started in, so an MCP session in another repo won't hijack that daemon's dirs. External-mode clients only attach to external-mode owners, and local only to local — the modes never silently cross-bind.
If no owner is found and no MemDB answers at MEMTRACE_MEMDB_ENDPOINT (default http://127.0.0.1:50051), the process prints "could not reach MemDB" and exits 1 — so stdio MCP normally rides on an already-running memtrace start daemon or memcore-server. Only embedded mode opens the data dir in-process (also spawning an in-process loopback gRPC server).
memtrace mcp does not spawn the Cortex sidecars (memcortex-daemon/memcortex-mcp) — that bootstrap runs from memtrace start only. The sidecar exposes its own independent MCP server that gets wired up alongside memtrace's; it is not proxied through memtrace's own tool list. See Cortex.
Transports#
The default transport is stdio — plain JSON-RPC over standard input/output, which is what every MCP client config expects. The stdio reader is resilient: one unparseable JSON-RPC line (for example over-deep nesting) gets a -32700 reply and the session keeps serving instead of dying; the process exits 0 when the client closes the stream.
Set MEMTRACE_TRANSPORT=streamable-http (aliases http, and legacy sse) to instead serve MCP over HTTP at http://0.0.0.0:<MEMTRACE_PORT>/mcp, for orchestrators that multiplex many agent sessions through one process. sse prints a deprecation hint but still works. An unrecognized transport value, or a binary built without the streamable-http feature, exits 2 with a listing of valid values rather than silently falling back to stdio.
Tool-result content also adapts per client, keyed on clientInfo.name at initialize: Claude clients get a two-item audience split (a human-readable summary for the transcript, plus compact JSON for the model); Codex and all other/unknown clients get a single plain JSON item, since Codex's strict client rejects content annotations. That's why a bare command="memtrace", args=["mcp"] config works everywhere without a shim.
Account requirement + degraded mode#
memtrace mcp requires a license session. On successful auth it records a telemetry "start" event and spawns session workers — a telemetry flusher, a PR-watch poller, a cloud heartbeat, and a quota forwarder that pushes tool-call billables to the runtime owner every 45 seconds.
Auth is resolved in this order: a config value, then MEMTRACE_LICENSE_KEY, then the saved credentials file at ~/.config/memtrace/credentials.json.
- No license key found anywhere: exits 1, telling you to run
memtrace auth login. - A definitively rejected license: exits 1, pointing at memtrace.io.
- A transient auth failure with a stored license on file: the server still starts in degraded mode and retries auth every 300 seconds in the background instead of dying.
Degraded mode exists specifically so a transient cloud outage doesn't take down every agent session mid-task — the server keeps serving tools while it quietly re-validates in the background.
Gotchas#
--workspace and the documented MEMTRACE_* environment variables apply to memtrace mcp the same way they apply to the rest of the CLI.
--ui binds 0.0.0.0 (not just localhost), and a bind failure — for example memtrace start already owns port 3030 — is silently swallowed: no UI, no error.
In default local mode, if no MemDB answers at MEMTRACE_MEMDB_ENDPOINT, the process exits 1 with "could not reach MemDB" rather than booting its own store. Run memtrace start first, or set MEMTRACE_MEMDB_MODE=embedded to point at a data dir directly.
All diagnostics go to stderr — stdout is reserved for the MCP protocol on stdio. The stderr writer is EPIPE-tolerant, so a host closing the pipe on teardown never crashes the server.
Examples#
$ memtrace mcp # Standard MCP client config entry: command="memtrace", args=["mcp"]. # Stdio, headless, attaches to a running `memtrace start` when present. $ memtrace mcp --ui # Also serve the dashboard/API on port 3030 (or MEMTRACE_UI_PORT) # alongside the MCP server. $ MEMTRACE_TRANSPORT=streamable-http MEMTRACE_PORT=3000 memtrace mcp # One long-lived HTTP MCP endpoint at http://0.0.0.0:3000/mcp for # orchestration platforms multiplexing many agent sessions. $ memtrace mcp --workspace ~/code/monorepo-parent # Anchor MemDB/.memtrace resolution on a multi-repo parent dir so # this MCP session shares the workspace's single graph. $ MEMTRACE_MCP_UI=1 memtrace mcp # Env-var equivalent of --ui, for MCP client configs where adding # args is awkward.
See also memtrace start, memtrace stop, memtrace status, memtrace auth, memtrace index, and memtrace connect.