MCP server
The same read-only query layer is available to IDEs and coding agents over the Model Context Protocol, so the why is one tool call away without shelling out. Install the extra and start a stdio server:.mcp.json, install [mcp] alongside your backend extra.
Register it with a client (Claude Code, Cursor, IDE agents). For Claude Code, add to .mcp.json
at the project root (launch the server from the project root so a --base-style git diff resolves
against your repo):
intent_* tools are exposed: six read-only query tools plus one explicit write tool, each a
thin wrapper over the CLI command of the same name, so a tool result is identical to its CLI
counterpart’s JSON plus one addition: a graph_identity fingerprint (absolute graph path, repo
root, node/edge counts, last-sync timestamp) on every response, so you can always tell which
graph answered. Two related guarantees:
- Fail-closed on an unresolvable graph: if the server’s graph doesn’t resolve at all,
every call returns
status: "graph_missing"(as an error) withgraph_identity: null— the key is always present. The served graph path is named on stderr at startup. - Fail-closed on whyfile’s own graph: a relative
--graphresolves against the server’s launch directory, so a stale user-scoped registration (launched from somewhere other than your project) can resolve to a real graph belonging to a different repository — and a real graph does not trip the check above. If that directory is a whyfile source checkout, every call returnsstatus: "graph_wrong_repo"(as an error) rather than describing whyfile to you. Register the server project-scoped, in your own repo’s.mcp.json, launched from the project root; an absolute--graphis treated as explicit intent and always honored. Whatever your setup,graph_identityon every response is the check that always works — confirm it names your repo. - Worktree-aware: a relative
--graph(e.g. from a committed.mcp.json) that doesn’t exist in the current checkout is retried against the main checkout root (git rev-parse --git-common-dir), so the server works from git worktrees where the gitignored output dir lives only in the main checkout.
The six query tools are read-only, LLM-free, and free at query time (they read the local graph,
make no backend call). Tools that need the enriched graph (
intent_explain, intent_changed,
intent_coverage) are unlocked in seconds by whyfile sync — the deterministic, zero-LLM build
of records + attested intent — so no reconstruction run is ever required to use them. intent_capture is the one write tool (B5): it is explicit (a distinctly
named tool, never a mode on a read tool), schema-validated, and scoped to capturing a decision, so
the read-only guarantee of the others is unchanged. Results carry both a JSON body and MCP
structuredContent; a real failure sets
isError, while a missing intent layer returns a graceful no_intent_layer result rather than an
error. The server only reads a local graph: no mutations, no pipeline runs, no secrets, safe to
hand to any agent. See ADR-0018 for the design.