code-graph · mcp · context-engineering
Why your AI assistant should query your architecture, not your files
File dumps and vector search break down on large C# codebases. A semantic code graph gives an LLM the exact dependency paths a question needs — nothing more.
On this page
Every AI coding assistant faces the same bottleneck: it can only reason about what fits in its context window. On a small project that's a non-issue — paste the repo, ask the question. On a real C# monorepo with thousands of types, it becomes the issue.
The two default strategies, and why they fail
Strategy one: dump the files
The brute-force approach is to hand the model whole files — the one you're editing, plus whatever looks related. It fails in both directions at once:
- Too much: most of every file is irrelevant to the question, so you pay for tokens that add noise, not signal.
- Too little: the behavior you're asking about usually lives between files — an interface here, three implementations there, a decorator registered in a DI container nobody remembers.
Strategy two: vector search
Embeddings retrieve text that looks like the question. But code similarity is not code relevance. The method that breaks when you change an interface doesn't share vocabulary with the interface — it shares a compile-time relationship with it. No embedding captures that reliably, and the index drifts out of date the moment the code changes.
What the compiler already knows
Here's the thing: a complete, precise map of your codebase already exists. The C# compiler builds it on every compilation — every symbol, every type, every call edge, every dependency. It just throws the map away when it's done emitting IL.
GraphSlice keeps that map. It compiles your solution with the same semantic model the compiler uses and materializes the result as a semantic code graph: nodes for solutions, projects, types, and methods; edges for calls, inheritance, references, and package dependencies.
Slices, not searches
A graph you can't fit in a context window is no better than a repo you can't fit in a context window. The unit of delivery matters. GraphSlice serves slices — the minimal subgraph that answers one question:
> what breaks if I change IPaymentProcessor?
IPaymentProcessor (interface, Billing.Core)
├── implemented by StripeProcessor (Billing.Stripe)
├── implemented by InvoiceProcessor (Billing.Invoicing)
├── injected into CheckoutService..ctor (Web.Checkout)
└── mocked in PaymentProcessorTests (Billing.Tests)
That's the whole answer. Four dependency paths, a few hundred tokens — instead of forty files and a prayer.
Why MCP is the right delivery channel
Slices are served over the Model Context Protocol, which means any MCP-compatible assistant can request them as tools:
- The model asks a structural question ("who calls this?", "trace this dependency") instead of a text query.
- The graph does the reasoning about structure, so the model can spend its reasoning budget on intent.
- Your repository is never uploaded or indexed by a third party — the graph runs where your code runs.
The payoff
Correct context, not just nearby context. Smaller windows, flatter costs as the repo grows, and answers grounded in how the software actually fits together. Your AI assistant stops being a very confident text search and starts being an engineer with the blueprints in hand.