Install
$ agentstack add mcp-smochan-polycodegraph ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
polycodegraph
[](https://github.com/smochan/polycodegraph/actions/workflows/ci.yml) [](https://pypi.org/project/polycodegraph/) [](https://www.python.org/downloads/) [](LICENSE) [](#mcp-tools-18-total)
> Parse any repo into a queryable code graph. Trace one parameter from a frontend fetch through every layer to the SQL query. Powers Claude Code, Cursor, and Windsurf via MCP — so your AI assistant reads focused context instead of the entire codebase.
Same Claude Sonnet 4.6. Same 10 questions about two real repos (codegraph itself + FastAPI). Only the registered MCP server changes. Reproduce with codegraph bench agent, raw data in [bench/RESULTS_AGENT_LATEST.md](bench/RESULTSAGENTLATEST.md).
Quick start
pip install polycodegraph # the PyPI distribution name
codegraph init # the CLI binary + Python module + MCP server are all `codegraph` (see footnote ↓)
codegraph build # parse repo → .codegraph/graph.db
codegraph serve # web dashboard at http://127.0.0.1:8765
That's it. Three commands and you have a queryable graph, a 3D dashboard, and an MCP server your IDE can talk to.
Languages + frameworks (today)
| | Today (v0.1.0) | Roadmap | |---|---|---| | Languages | Python · TypeScript · JavaScript · TSX / JSX · Go | Java, Rust, C# (v0.3); Ruby, PHP later | | HTTP frameworks | FastAPI · Flask · aiohttp · Express · NestJS | Spring Boot, Django views, ASP.NET, Rails (alongside their language) | | ORMs / DBs | SQLAlchemy · Prisma (partial) | Django ORM, GORM, Diesel, ActiveRecord (alongside their language) | | Frontend fetch | fetch · axios · SWR · React Query · generic apiClient.* | RTK Query, Apollo | | 24 framework decorators | FastAPI · Flask · aiohttp · Celery · pytest · MCP · Click · Typer · Django · SQLAlchemy · NestJS · … | Spring annotations, .NET attributes |
Adding a new language is a single tree-sitter parser module + fixture file (~3 hours — see codegraph/parsers/go.py for the v1 template). PRs welcome.
The MOAT — one graph, everything on top
polycodegraph has exactly one opinion: build the right graph, and every interesting feature falls out for free.
The inputs that feed the graph go beyond imports and call edges. polycodegraph reads tree-sitter parses for Python, TypeScript, JavaScript, and Go; captures every call-site's arguments as text; recognizes 24 framework decorators so FastAPI / Flask / Celery / pytest / Click / MCP / Django / SQLAlchemy handlers are never confused with dead code; detects routes (@app.get("/x")) and frontend fetches (fetch, axios, useSWR, useQuery); and stitches URLs across the stack (/{id} ↔ ${id} ↔ :id) so it can trace a fetch all the way to its handler.
The outputs that come for free once the graph is right:
Decorator-aware dead code, role classification (HANDLER / SERVICE / COMPONENT / REPO), blast radius, cycles, untested-function detection, an end-to-end cross-stack trace with rename annotations, a 3D focus-mode dashboard, a Learn Mode lifecycle modal, local embeddings for semantic + hybrid search, an 18-tool MCP server, and a PR-review CI that graph-diffs the branch against main.
One SQLite file. No daemon. No network. Travels with your git branch.
How it works
┌─────────────────────────────────────────────────────┐
│ tree-sitter parsing │
│ (Python, TS/JS, TSX, JSX, Go) │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ Cross-file resolution (R1, R2, R3) │
│ ✓ per-name imports ✓ relative imports │
│ ✓ constructor calls ✓ decorators │
│ ✓ self.X.Y chains ✓ fresh instances │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ SQLite graph (nodes + edges) │
│ DF0: call-site arguments │
│ DF1: routes (FastAPI, Flask, aiohttp) │
│ DF2: fetches (fetch, axios, SWR, useQuery) │
│ DF3: URL stitching (/{id} ↔ ${id} ↔ :id) │
│ DF4: end-to-end trace (fetch→handler→service→DB) │
└─────────────────────────────────────────────────────┘
↙ ↓ ↘
CLI tools Web dashboard MCP server
(graph, roles, (3D focus view, (18 tools for
cycles, dead architecture, Claude Code,
code, untested) learn mode) Cursor, etc.)
What you can do
| Screenshot | Use case | |:---:|:---| | | 3D focus view — Pick any function, trace its real downstream call tree, expand or collapse ancestors and descendants inline. Shown: build_dashboard_payload with its 15 direct callees — find_dead_code, find_cycles, build_hld, find_hotspots, compute_metrics, and the rest of the analysis stack. | | | Architecture map — Handlers grouped by role (HANDLER, SERVICE, COMPONENT, REPO), infrastructure components (DB, cache, queue), and their connections at a glance. Click a handler → Learn Mode opens a request-lifecycle modal: TCP → TLS → HTTP → query → response. | | | DF4 cross-stack trace — Click any handler in the Architecture view and Learn Mode animates the full request lifecycle: DNS → TCP → TLS → HTTP → middleware → handler → service → SQL → 200 OK. The user_id parameter is highlighted at every hop with rename annotations (userId → user_id → id). One graph query, no log dive. | | | MCP tools your AI assistant calls directly — A real find_symbol("get_user") response from polycodegraph's MCP server. Three results in ~50 tokens, role-classified as HANDLER vs SERVICE, no file reads required. Drop this in alongside Claude Code's grep and the assistant stops dumping whole files into its context window — see the benchmark below. |
Benchmark — same Claude, varying graph MCP
Four configurations. Same Claude Sonnet 4.6. Same 10 questions across two real codebases (polycodegraph itself + FastAPI). All four configs include Claude's native grep + file-reading tools — what every dev gets out of the box in Claude Code or Cursor. The only thing that changes is whether a graph MCP is also registered alongside.
codegraph-self
| Configuration | Correct | Tokens in | Cost (USD) | Avg latency (s) | |---|---:|----:|----:|----:| | claude+grep (no graph MCP) | 5 / 5 | 264,756 | $0.92 | 102 | | + code-review-graph MCP | 2 / 5 | 118,674 | $0.39 | 56 | | + graphify MCP | 3 / 5 | 99,233 | $0.31 | 83 | | + polycodegraph MCP | 4 / 5 | 43,705 | $0.18 | 22 |
fastapi
| Configuration | Correct | Tokens in | Cost (USD) | Avg latency (s) | |---|---:|----:|----:|----:| | claude+grep (no graph MCP) | 3 / 5 | 71,833 | $0.25 | 54 | | + code-review-graph MCP | 1 / 5 | 84,082 | $0.29 | 42 | | + graphify MCP | 2 / 5 | 55,287 | $0.19 | 46 | | + polycodegraph MCP | 3 / 5 | 46,347 | $0.19 | 18 |
The honest read across both repos:
claude+grepalone is the most correct (8/10) — Claude can answer most codebase questions by grepping and reading whole files. But it pays the price: 336k tokens, $1.17, 78s avg latency.- **
+ polycodegraphmatches that within one question (7/10) at 3× lower cost and 4× lower latency (90k tokens, $0.37, 20s).** Because polycodegraph returns small focused subgraphs (~20-50 tokens per call) instead of grep-dumping whole files into Claude's context. - The other graph MCPs are strictly worse than just grepping. code-review-graph: 3/10 at $0.68. graphify: 5/10 at $0.50. They add tool overhead without paying off in correctness.
Reproduce: codegraph bench agent --only claude+grep,claude+grep+polycodegraph,claude+grep+code-review-graph,claude+grep+graphify. Raw per-run JSONL in [bench/agent_raw_latest.jsonl](bench/agentrawlatest.jsonl). Full methodology in [bench/README.md](bench/README.md).
Install & use
From PyPI
pip install polycodegraph
codegraph init
codegraph build
Register as an MCP server
codegraph init writes a project-level .mcp.json in the repo — Claude Code and Cursor auto-pick that up as soon as you open the project. For other clients you currently need to add the server to their global config manually (v0.2 will do this for you).
// Claude Code (global) → ~/.claude.json
// Cursor (global) → ~/.cursor/mcp.json (or .cursor/mcp.json per workspace)
// Windsurf → ~/.windsurf/mcp.json
// OpenAI Codex CLI → ~/.codex/mcp.json
// GitHub Copilot CLI → ~/.config/copilot/mcp.json
// Zed → ~/.config/zed/settings.json under "context_servers"
// Continue → ~/.continue/config.json under "experimental.modelContextProtocolServers"
{
"mcpServers": {
"codegraph": {
"command": "codegraph",
"args": ["mcp", "serve"]
}
}
}
The same five-line JSON snippet works for every client — only the file path changes.
Then ask your assistant questions like:
> "Which HANDLER nodes have no test coverage?" > "Show me all the callers of UserService.login with their arguments." > "Trace GET /api/users/{id} from the frontend fetch all the way to the database." > "What's the blast radius of changing this function?"
All 18 tools return small, focused subgraphs — no context-window flooding.
Optional: local embeddings
pip install 'polycodegraph[embed]'
codegraph embed # chunks the repo, embeds with nomic-ai/CodeRankEmbed
Unlocks the semantic_search and hybrid_search MCP tools. ~140 MB model download, runs locally, no API keys.
Live demo
A small FastAPI + SQLAlchemy + React fixture lives in [examples/cross-stack-demo/](examples/cross-stack-demo/). Run polycodegraph on it to see DF0, DF1, DF1.5, DF2, DF3, and DF4 all light up:
codegraph build --no-incremental --root examples/cross-stack-demo
codegraph dataflow trace "GET /api/users/{user_id}"
See the [demo README](examples/cross-stack-demo/README.md) for expected output.
Limitations (honest list)
What polycodegraph doesn't do yet. Listed here so the benchmark and README claims stay clean.
- Type inference (Mypy / Pyright). DF0 captures argument text, not types. Roadmap v0.3.
- Argument-value identity across hops. DF4 emits ordered hops with rename annotations; full single-value propagation from fetch body → route param → service arg → DB column is deferred (v0.3).
- Docstrings are stored on every node but not yet consumed by analysis. Embeddings use them as fallback body text; dead-code, role classification, and dataflow ignore them. Roadmap v0.3.
- Git-history mining (commit-message semantics, author / touch-frequency signals). Not implemented. Git is used only for the current HEAD SHA and PR-review diff. Roadmap v0.4.
- Per-language resolver parity (v0.1.2). Python ships the full R1/R2/R3 fixes. TypeScript R2 patterns (path aliases, fresh-instance binding, decorator-call edges) are deferred.
- Typer CLI symbols are not tagged HANDLER (v0.1.x). DF1.5 only classifies HTTP framework decorators.
- Async / await visualization (v0.4). DF4 walks the synchronous call graph only.
- Error-path branch rendering (v0.4). Learn Mode shows the happy path.
- Auth middleware as a distinct phase (v0.4). Today auth shows up as a regular CALL node.
- Multi-param simultaneous highlighting (v0.4). Single-param selection only.
- Cross-process traces (v0.4). Can't yet link multiple
.codegraph/graph.dbfiles.
Roadmap
| Version | Status | What's in / what's planned | |---|---|---| | 0.1.0 | Shipping on PyPI today | Parsing (Python, TS/JS, Go), DF0–DF4 tracing, 3D dashboard + Architecture + Learn Mode, decorator-aware dead code, cycles, role classification, local embeddings (semantic + hybrid search), 18 MCP tools, PR-review CI, cross-repo workspace mode. | | 0.1.2 | Planned | TypeScript R2 resolver patterns (path aliases, fresh-instance binding, decorator edges); CLI HANDLER classification for Typer / Click. | | 0.3 | Planned | Type inference (Mypy/Pyright); full single-value arg-flow propagation; docstring-driven analysis hints; multi-param highlighting; more languages (Rust, Java, C#). | | 0.2 | Planned | Rename CLI binary codegraph → polycodegraph (keep codegraph as a deprecated alias for one release); codegraph init writes to every detected client's global MCP config (Claude Code / Cursor / Windsurf / Codex / Copilot / Zed / Continue), not just the project-level .mcp.json. | | 0.4 | Planned | Async / await visualization; error-path branches; auth-middleware phase; cross-process traces; git-history semantics. |
On the self-graph: from 451 dead-code findings to 0
We run polycodegraph on its own source as a regression target. Dead-code findings dropped from 451 → 24+ → 15 → 0 as the resolver hardened, decorator-aware entry-point detection landed, and intentional public-API methods were marked with # pragma: codegraph-public-api.
Current self-graph stats:
- 3,320 nodes (files, classes, functions, imports)
- 7,557 edges (5,245 CALLS, 1,357 DEFINEDIN, 886 IMPORTS, 28 INHERITS, 12 ROUTE, 27 FETCHCALL, 1 READSFROM, 1 WRITESTO)
- 3 cycles, all documented and accepted (dashboard redraw, parser self-recursion, MCP serve/run resolver false positive)
- 0 dead-code findings (with pragma exemptions for public-API methods)
- 637 tests passing (537 Python pytest + 100 Node tests)
Where it fits
| | polycodegraph | GitNexus | code-review-graph | better-code-review-graph | JudiniLabs / mcp-code-graph | RepoMapper | Graphify | |---|:-:|:-:|:-:|:-:|:-:|:-:|:-:| | Local-first, single SQLite, no daemon | ✅ | ✅ | ✅ | ✅ | partial | ✅ | varies | | MCP-native (stdio) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | | Cross-stack end-to-end trace (fetch → SQL) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | Decorator-aware dead code (24 frameworks) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | Role classification (HANDLER/SERVICE/...) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | Argument-level data flow text capture (DF0) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | 3D focus-mode flow tracer | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | partial | | Local embeddings (no API key) | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | | Open source, MIT | ✅ | ❌ (PolyForm NC) | ✅ | ✅ | ✅ | ✅ | varies |
The wedge isn't a fancier graph algorithm — it's that polycodegraph treats trace this argument across the stack as a first-class operation, not a follow-up grep. Embedding-based retrieval tools (code-review-graph, Cursor, Cody) handle prose / docstrings well; the right architecture is graph + embeddings in the same MCP loop, and v0.1.0 ships both.
Full feature reference (16 capabilities)
| Capability | What it does | Example | |---|---|---| | Parsing | tree-sitter walks Python / TypeScript / JavaScript / TSX / JSX / Go at function/method/class granularity. | codegraph build | | Single SQLite store | All graph data in .codegraph/graph.db. No daemon, no DB server, no network. | git commit .codegraph/ | | Cross-file resolution | Per-name imports, relative imports, same-file constructors, decorator-call edges, self.X.Y chains, fresh-instance methods. | from pkg import a, b, c → 3 separate edges | | DF0 call-site arguments | Captures the text of each argument at parse time (no type inference). Powers signature tooltips and edge labels. | func(user_id=42) → edge label shows user_id=42 | | Decorator-aware dead code | 24 framework decorators recognized (Typer, FastAPI, Click, Celery, pytest, MCP, Flask, Django, SQLAlchemy, etc.). Framework-registered handlers never flagged. | @app.get("/x") → handler not dead code | | **Call/import
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: smochan
- Source: smochan/polycodegraph
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.