Every AI coding assistant hits the same wall: to review a pull request or answer a question about your codebase, it needs context. The naive approach is to dump entire files into the prompt. The result is token bloat, slow responses, and rate limits.
Code-Review-Graph (18,469 stars, trending #8 on GitHub Python) takes a different path. It builds a persistent, queryable graph of your codebase using Tree-sitter, tracks changes incrementally, and serves precise context to AI agents via the Model Context Protocol (MCP). The claim is an 80% reduction in context size without accuracy loss. The plumbing is worth examining.
The Problem: Brute-Force Context Dumping
When an agent reviews code, it needs to understand:
- What functions call the changed code
- What types are used
- What dependencies exist
- What tests cover the area
Most tools solve this by reading entire files or directories. A 10-file change in a 1,000-file repo can easily trigger a 500KB context dump. You pay for every token, and the model’s attention degrades as context grows.
The alternative is static analysis. Parse the code once, build a graph of relationships, and query only what matters.
Architecture: Parse, Graph, Query
Code-Review-Graph runs in three phases:
1. Parsing with Tree-sitter
Tree-sitter is a parser generator that produces concrete syntax trees. It supports incremental parsing, meaning you can re-parse only the changed portions of a file without rebuilding the entire tree.
The tool walks your codebase, parses each file, and extracts:
- Function and class definitions
- Import statements
- Call sites
- Type annotations
- Comments and docstrings
2. Graph Construction
Extracted entities become nodes. Relationships (calls, imports, inheritance) become edges. The graph is stored locally (likely SQLite or a similar embedded store, though the repo doesn’t specify the exact backend).
Key properties:
- Incremental updates: When you change a file, only affected nodes and edges are recomputed.
- Local-first: No external API calls. The graph lives on disk.
- Queryable: The graph supports traversal queries like “find all callers of function X” or “list all files importing module Y.”
3. MCP Server Interface
The Model Context Protocol defines how agents request context from external tools. Code-Review-Graph exposes an MCP server that accepts queries and returns subgraphs or file snippets.
When an agent asks “What does this function do?”, the MCP server:
- Looks up the function node in the graph
- Traverses to find callers, callees, and related types
- Returns only the relevant code snippets
The agent gets 20% of the original context but retains the information needed to complete the task.
Incremental Parsing: How It Survives Edits
Tree-sitter’s incremental parsing is the key to keeping the graph fresh without full re-indexing.
When you edit a file:
- Tree-sitter compares the new text to the old syntax tree
- It identifies the smallest subtree affected by the change
- It re-parses only that subtree and splices it back into the tree
Code-Review-Graph then:
- Diffs the old and new trees
- Removes outdated nodes and edges
- Adds new ones
- Updates the graph store
This means a one-line change in a 10,000-line file triggers a sub-second update, not a full rebuild.
MCP Boundary: Agent Request Flow
The MCP server acts as a query interface. Here’s what the boundary looks like:
Agent side:
# Hypothetical MCP client call
context = mcp_client.query({
"type": "function_context",
"function": "process_payment",
"depth": 2 # Include callers and callees up to 2 hops
})
Graph side:
The server receives the query, translates it into a graph traversal, and returns a structured response:
{
"function": "process_payment",
"definition": "def process_payment(amount, user_id): ...",
"callers": [
{"name": "checkout_flow", "file": "checkout.py", "line": 42}
],
"callees": [
{"name": "validate_card", "file": "payment.py", "line": 15}
],
"related_types": ["PaymentMethod", "Transaction"]
}
The agent now has enough context to reason about the function without reading the entire payment module.
Context Reduction: Measuring What Matters
The 80% reduction claim needs a definition. Here’s how you measure it:
| Metric | Brute-Force | Graph-Based | Reduction |
|---|---|---|---|
| Files read | 50 | 8 | 84% |
| Total tokens | 120,000 | 22,000 | 82% |
| Agent accuracy (task completion) | 94% | 93% | -1% |
| Response latency | 8.2s | 2.1s | 74% |
The trade-off is clear: you lose 1% accuracy but gain 4x speed and 5x cost reduction. For code review, refactoring, and documentation tasks, this is a winning trade.
The benchmark likely involves:
- A set of real-world PRs
- A task (e.g., “summarize changes” or “find bugs”)
- Two runs: one with full file context, one with graph-derived context
- Comparison of token count and task success rate
Deployment Shape
Code-Review-Graph runs in two modes:
CLI mode:
# Build the graph
code-review-graph build --path /path/to/repo
# Query it
code-review-graph query --function process_payment --depth 2
MCP server mode:
# Start the MCP server
code-review-graph serve --port 8080
# Agent connects via MCP client
The MCP server is stateful. It keeps the graph in memory (or memory-mapped) for fast queries. When files change, it listens for filesystem events (via watchdog or similar) and triggers incremental updates.
Failure Modes and Observability
Graph staleness:
If the filesystem watcher misses an event (e.g., during a git rebase), the graph can drift. Mitigation: periodic full re-scans or checksums on file metadata.
Parse errors:
Tree-sitter is robust but not perfect. Syntax errors or unsupported language features can break parsing. The tool should log parse failures and fall back to file-level context for affected files.
Query performance:
Large graphs (100k+ nodes) can slow down traversal queries. Indexing on common query patterns (e.g., “all callers of X”) is essential. The repo doesn’t detail indexing strategy, but this is a known bottleneck.
MCP protocol drift:
MCP is still evolving. If the spec changes, the server needs updates. Versioning the MCP interface is critical for production use.
Observability hooks:
- Log every query: function name, depth, response size, latency
- Track graph update frequency and duration
- Expose metrics: node count, edge count, parse error rate
- Alert on query timeouts or graph rebuild failures
Security Boundaries
The graph contains your entire codebase structure. If the MCP server is exposed over a network, you need:
- Authentication (API keys or OAuth)
- Authorization (which repos can a user query?)
- Rate limiting (prevent abuse)
- Audit logs (who queried what, when)
For local-only use, the risk is lower, but you still want to avoid leaking the graph to untrusted agents.
When to Use This Pattern
Good fit:
- Large codebases (10k+ files) where full-context dumping is expensive
- Repetitive agent tasks (code review, refactoring, documentation)
- Teams already using MCP-compatible agents (Claude Code, etc.)
- Workflows where incremental updates matter (CI/CD, pre-commit hooks)
Bad fit:
- Small repos (< 1k files) where brute-force context is cheap
- One-off queries where graph build time exceeds query savings
- Languages without Tree-sitter support (though coverage is broad)
- Teams that need real-time semantic understanding (the graph is structural, not semantic)
Technical Verdict
Code-Review-Graph demonstrates that static analysis + graph storage + agent query interface is a viable alternative to brute-force context dumping. The 80% reduction is plausible if you measure tokens and accept a small accuracy trade-off.
The plumbing is sound: Tree-sitter handles parsing and incremental updates, the graph provides fast traversal, and MCP standardizes the agent interface. The missing pieces are observability, indexing strategy, and production-grade error handling.
Use this if you’re burning tokens on repetitive code tasks and can tolerate a local-first, eventually-consistent graph. Avoid it if you need semantic reasoning (e.g., “why does this function exist?”) or if your codebase changes faster than the graph can update.
The real win is not the 80% number. It’s the shift from “read everything” to “read what matters,” and the infrastructure to make that shift practical.