Code Graph (MCP)
@ttsc/graph gives a coding agent a map of your TypeScript project, over MCP.
It runs ttscgraph, a native binary that type-checks your project once and keeps it in memory. Every query is answered from that warm checker, not a fresh parse.
So every relationship it reports is the compilerโs own answer, not a guess from reading text.
Why an agent needs it
Ask an agent how something works and, without a map, it reconstructs the picture by hand: open a file, follow an import, open the next, and repeat. That is slow, it spends tokens, and the relationships it infers are guesses from whatever text it happened to read.
The graph hands it the answer up front. In one call the agent gets a symbolโs source, what it calls, what calls it, the types it touches, and how far a change would reach, so it stops fanning out across files.
On a public agent-cost benchmark a Claude agent answers reading zero files, cutting tokens by 77% to 86% and tool calls by 94% to 95%. See the Benchmark for the numbers and method.
One graph, two questions
Most tools answer only one of these. This one answers both, from the same graph:
- What calls what. The static structure: what a symbol calls, what depends on it, the types it touches, its heritage.
- What is broken, and how far it spreads. The live diagnostics, fused onto that structure.
That fusion is the point. query_nodes shows a symbolโs own errors, and how many of the things that depend on it are already broken.
So before you change a symbol, you can see the reach of the change over what is currently failing. That is fix-safety, not just a cheaper way to read code.
No other tool fuses all three. A tree-sitter graph has no types and no errors. An editorโs language server has errors but no structure graph. A linter is separate again. Only a graph built on the real checker holds the structure, the diagnostics, and the affected set in one place.
What only the compiler can resolve
A text search or a tree-sitter parse stops where the syntax stops. A real type checker does not. So these edges are correct where a text tool can only guess:
- pnpm / workspace monorepos. A
workspace:*dependency is followed into the sibling packageโs real source. A call across packages lands on the true declaration, not the barrel it passed through. - Path aliases. A
@app/*import fromtsconfigis resolved to the real file, so the edge is right where a text tool sees only the alias string. - Barrel re-exports. An
index.tsthat only re-exports is unwrapped to the file that actually declares the symbol. - Your code vs the world. Anything in
node_modulesor a.d.tsis reported as an outside boundary, not walked into. The graph stays your code. - Generated code stays out of the way. A source file your
.gitignorecovers, such as a Prisma client or other codegen emitted as.ts, is de-ranked: it never dominates a broad or keyword match, though it stays reachable as an edge target and by its exact name. The graph surfaces what you wrote, not what a generator did.
Get started
@ttsc/graph resolves the native binary from the ttsc platform package, so install ttsc alongside it.
npm install -D ttsc @ttsc/graph typescript@rcAdd the server to your MCP client. For Claude Code, a .mcp.json in your project root:
{
"mcpServers": {
"ttsc-graph": {
"command": "npx",
"args": ["-y", "@ttsc/graph"]
}
}
}Start the agent from your project root so the server finds your tsconfig.json, or point it at a project explicitly with --cwd and --tsconfig. The server never writes into your CLAUDE.md, AGENTS.md, or any other agent config file, so installing it has no side effects on your repository.
Your agent picks the tools up from the MCP handshake and calls them when it needs to. The full setup walk-through is in Setup.