EngramGraph ships a Model Context Protocol server (stdio transport) so any MCP-capable coding assistant can use it as a code + knowledge graph memory. It is a thin adapter over the existing, tested query functions — zero LLM, deterministic, no Docker.
The server runs as a local subprocess the assistant spawns over stdio; there is no network service, no container, no API key.
The server binary is egr-mcp (equivalently egr mcp). It reads the
graph DB from ENGRAM_DB (default ./.engram/graph.db).
# From an installed package:
claude mcp add egr -- npx egr-mcp
# Or point at a local checkout's built bin:
claude mcp add egr -- node /abs/path/to/EngramGraph/dist/mcp/stdio.jsTo pin the graph location, pass the env var:
claude mcp add egr --env ENGRAM_DB=/abs/path/.engram/graph.db -- npx egr-mcpVerify with claude mcp list → egr … ✓ Connected.
Add a stdio server to the client's MCP config. The shape varies per client, but the command/args/env are the same:
| Tool | Input | Returns |
|---|---|---|
index_code |
files: { path, source }[] |
Indexes source into the code graph (cross-file CALLS). Counts of files/functions/classes/calls (+ ambiguous/unresolved). |
index_docs |
docs: { content, fallbackId? }[] |
Indexes front-matter markdown into the knowledge graph. Counts of specs/decisions/impacts/supersedes. |
call_chain |
symbol, direction? (callers|callees|both), depth? |
Who calls / is called by a function symbol. "What breaks if I change X?" |
impact_analysis |
nodeId, maxHops? |
Decisions in a spec's impact chain (IMPACTS + multi-hop SUPERSEDES). |
ingest_feedback |
nodeId, type, nodeLabel? (Function|Spec|Decision|Doc), weight? |
Evolve a node's SAGE confidence from a feedback event (test_fail/test_pass/human_fix). |
implementers |
specId |
Files declaring // implements <specId> and the functions they define. "Which code implements this spec?" Reads IMPLEMENTS(Module→Spec) + DEFINES. |
implemented_specs |
moduleId |
Specs a file declares it implements. "Which spec governs this code?" moduleId is the file's indexed path. Reads IMPLEMENTS(Module→Spec). |
related |
seedId, depth?, limit? |
Structurally important nodes around a seed id (seeded PageRank over all edge types, crosses Function/Spec/Module/Decision). "What's connected to X?" Refused over stdio — see below. |
blindspots |
— | Files that parsed partially or failed, from the parse-health manifest — where the graph may be missing nodes/edges. Use after a query reports indexHealth.possiblyIncomplete to find out WHAT is missing. manifestPresent distinguishes "nothing wrong" from "never measured". |
signatures |
— | The same files grouped by root cause instead of listed individually — turns "584 files" into "1 problem". Use when blindspots returns a long list. |
doctor |
— | Which languages are available and why any are not, what was compiled on this machine, which commands need network. Does not open the graph, so it answers when indexing itself is what is broken. |
Every tool returns a text content block of JSON; on failure it returns
error: <message> with isError: true.
The stdio server holds the graph read-only. The engine is single-writer,
and the server is long-lived — it is open for as long as your editor is. If it
held a write handle, every egr command you ran in a terminal meanwhile would
contend with it, and two writers on this engine do not merely refuse the loser:
they corrupt the database.
So four tools are refused here, each naming the command that does the job:
| Tool | Run instead |
|---|---|
index_code |
egr index <dir> |
index_docs |
egr index <dir> --docs |
ingest_feedback |
egr feedback <type> <node-id> |
related |
egr related <seed-id> |
The server sees the result on its next query — no restart needed.
related is the surprising one: it reads, from a caller's point of view. But
ranking requires installing the algo extension and building a projected graph,
and both are writes. It is listed here rather than removed because the
capability is real; only this transport cannot provide it.
- Index the repo: the assistant calls
index_codewith the project's source files, andindex_docswith its spec/decision markdown. - Ask "what calls
execute?" →call_chainwith{ symbol: "execute", direction: "callers", depth: 2 }returns the callers. - Ask "which decisions sit behind SPEC-001?" →
impact_analysiswith{ nodeId: "SPEC-001" }returns e.g.[ADR-001, ADR-002]. - Record an outcome: after a test fails for a function,
ingest_feedbackwith{ nodeId, type: "test_fail" }lowers that node's confidence, so the next ranked query surfaces the more-reinforced nodes first.
- The connection is long-lived; EngramGraph never closes it per call (a kuzu + tree-sitter teardown caveat — see CONTRIBUTING.md).
- The graph is shared with the
egrCLI and the REST server: index once via any mode, query from another. - Confidence semantics (
STEP0.25, floor 0.1) and the full DDL are in API.md.
{ "mcpServers": { "egr": { "command": "npx", "args": ["egr-mcp"], "env": { "ENGRAM_DB": "/abs/path/.engram/graph.db" } } } }