codetopo
Registry identity: mcp-name: io.github.nrupala/codetopo
See your codebase the way an agent sees it. codetopo turns a sourcerepository into a queryable code graph — symbols, calls, references, andstructure — with JSON answers an AI coding agent can act on directly.
codetopo holds the OpenSSF Best Practices Passing badge — 100% of 67 criteria.
You are here because an agent just touched your codebase and you want toanswer structural questions fast: what calls this function? what breaks ifI change this? how are these two modules connected? codetopo indexes thetree once and answers those questions as data — counts first, full listsonly when asked — over a CLI, an HTTP API, or the MCP tools your agentalready speaks.
It is deliberately domain-blind: no scoring, no rankings, no opinions aboutwhat the code means. It answers structural questions about source trees, andonly that. Domain meaning belongs to the agents and teams composing on top.
Live demo: codetopo.aimlds.org — codetopo's real map of this repository, drawn by codetopo itself and refreshed on every push to main.
60-second quickstart
Requires a stable Rust toolchain (install via rustup).
# Install the four binaries: codetopo (CLI), codetopo-server (HTTP API),
# codetopo-mcp (stdio MCP server), codetopo-acp (stdio ACP agent).
# The packages must be named — a bare install URL fails because the
# repository contains multiple binary packages.
cargo install --git https://github.com/nrupala/codetopo codetopo-cli codetopo-server codetopo-mcp codetopo-acp
# Index a repository (Rust and TypeScript/JavaScript are parsed via tree-sitter)
codetopo index ~/my-project --db graph.db
# Find a symbol's id by name (every surface has this discovery step)
codetopo search connect --db graph.db
# Ask what calls what (the package prefix is your directory's name,
# exactly as indexed — hyphen included)
codetopo descendants my-project::net::Client::connect --db graph.db --expand
That's the whole loop: index once, query as data. Aggregate-firstoutput — totals before lists — keeps token budgets and pipes sane bydefault; --expand brings the full list when you want it.
Example queries
Against the fixture repository used in the project's own end-to-endverification (docs/phase-2-verification.md) — output shown is the realoutput of the CLI:
$ codetopo index crates/codetopo-server/tests/fixture-repo --db graph.db
files indexed: 3
files failed: 0
symbols: 6
nodes: 15
edges: 23
diagnostics: 2
$ codetopo stats --db graph.db
nodes: 15
package: 1
module: 3
file: 3
function: 6
external: 2
edges: 23
calls: 5
contains: 12
reads: 6
$ codetopo descendants fixture-repo::alpha::entry --db graph.db --expand
2 descendants of fixture-repo::alpha::entry
fixture-repo::alpha::helper_a
fixture-repo::alpha::helper_b
A few more things you can ask (same engine, same data):
codetopo ancestors <node-id> --db graph.db # what depends on this node
codetopo blast-radius <node-id> --db graph.db # what a failure here would take with it
codetopo path <from-id> <to-id> --db graph.db # shortest typed path between two nodes
codetopo verify --db graph.db # verify the hash-chained audit log
codetopo snapshot --db graph.db --out g.json # portable frozen JSON export of the whole graph
codetopo restore --snapshot g.json --db g2.db # restore a snapshot into a fresh database
The path answer renders as typed steps, e.g. a --calls--> x --imports--> b(illustrative; exact ids depend on your index).
Giving it to your agent
HTTP API (codetopo-server)
The same queries over JSON, behind Bearer API-key auth, with per-requestmetering — one transport for any client, any language:
echo "demo-key:change-me" > api_keys && chmod 600 api_keys
codetopo-server # listens on 127.0.0.1:8080 by default
curl -H "Authorization: Bearer demo-key:change-me" -X POST localhost:8080/v1/index \
-H 'Content-Type: application/json' -d '{"repo_path": "~/my-project"}'
# {"index_id": "<uuid>", "files_indexed": 3, "files_failed": 0, "nodes": 15, "edges": 23, "diagnostics": 2}
curl -H "Authorization: Bearer demo-key:change-me" \
"localhost:8080/v1/graphs/<uuid>/descendants?node=<node-id>&expand=true"
Eight endpoints under /v1, one index operation plus seven read-onlyqueries: POST /v1/index, GET /v1/graphs/{id}/{descendants, ancestors, blast-radius, path, stats, verify, snapshot, neighborhood, symbol, search}, GET /v1/schema. Full contract inschemas/openapi.yaml (OpenAPI 3.1.0), env knobs(CODETOPO_BIND, CODETOPO_DATA_DIR, CODETOPO_KEYS_FILE,CODETOPO_METERING_LOG) documented in schemas/README.md.
MCP (codetopo-mcp)
A stdio JSON-RPC server exposing the same handler layer as twelve tools —the eight query/integrity tools (codetopo_index, codetopo_descendants,codetopo_ancestors, codetopo_blast_radius, codetopo_path,codetopo_stats, codetopo_verify, codetopo_snapshot) plus discovery(codetopo_search_symbols, codetopo_get_symbol,codetopo_neighborhood, codetopo_describe_schema) — so an in-processagent learns one surface and gets both. MCP answers are identical to the HTTP answers byconstruction: both call the same codetopo-core queries.
{ "mcpServers": { "codetopo": { "command": "codetopo-mcp" } } }
ACP (codetopo-acp)
A stdio agent speaking the Agent Client Protocol — for editors and clientsthat converse with agents instead of calling tools. Open a session on aworking directory and ask code-structure questions in plain language:
→ {"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
← {"jsonrpc":"2.0","id":1,"result":{"agent":"codetopo","protocolVersion":"1.0",
"agentCapabilities":{"read_only":true,"code_structure":true},"agentInfo":{"name":"codetopo"}}}
→ {"jsonrpc":"2.0","id":2,"method":"session/new","params":{"cwd":"/path/to/repo"}}
→ {"jsonrpc":"2.0","id":3,"method":"session/prompt",
"params":{"sessionId":"<id>","prompt":"blast radius of auth::login"}}
← {"jsonrpc":"2.0","id":3,"result":{"answer":"Blast radius of 'auth::login': 14 nodes — …"}}
Deterministic intent routing (descendants / ancestors / blast-radius / path /stats / snapshot / verify) straight to the same codetopo-core queries —no LLM, no network, no file writes. Edit requests get an honest read-onlyrefusal. stdout carries only protocol frames; diagnostics go to stderr.
Architecture
┌─────────────┐ tree-sitter ┌──────────────┐
│ source tree │ ───────────────► │ codetopo- │ extract symbols,
└─────────────┘ Rust, TS/JS │ extract │ calls, references
└──────┬───────┘
▼
┌──────────────┐
│ codetopo-core│ graph model:
│ │ nodes, edges,
│ │ traversal queries
└──────┬───────┘
▼
┌──────────────┐
│ codetopo- │ SQLite store +
│ store │ hash-chained
│ │ audit log
└──────┬───────┘
│
┌──────────────────────────────────┼─────────────────────────────┐
▼ ▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ codetopo │ │ codetopo- │ Bearer auth │ codetopo- │ stdio │ codetopo- │ stdio
│ (CLI) │ │ server │ JSONL │ mcp │ JSON-RPC │ acp │ ACP
└──────────────┘ └──────────────┘ metering └──────────────┘ └──────────────┘
| Crate | Role |
|---|---|
codetopo-core |
Graph model, node/edge kinds, all traversal queries, snapshots |
codetopo-extract |
tree-sitter extractors (Rust, TypeScript/JavaScript) |
codetopo-store |
SQLite persistence + tamper-evident, hash-chained audit log |
codetopo-cli |
codetopo headless CLI — the reference query surface |
codetopo-server |
codetopo-server axum HTTP API (thin adapter over core) |
codetopo-mcp |
codetopo-mcp stdio MCP server (thin adapter over core) |
codetopo-acp |
codetopo-acp stdio ACP agent — conversational sessions over the Agent Client Protocol (thin adapter over core) |
The CLI, HTTP, MCP, and ACP surfaces are all thin adapters over the samehandlers — they cannot disagree. schemas/ keeps the machine-readablecontracts (OpenAPI 3.1, MCP tool catalogue) checked against the runningservers. The store's audit log follows the trust-primitive pattern usedacross this product line: a hash-chained, append-only record, verified bycodetopo verify / GET …/verify.
Docs
docs/render.md— deterministic render: the frozen layout spec (JSON) + SVG rules behindcodetopo renderdocs/protocol-proof.md— MCP/ACP conformance evidence: strict stdio clients + official-schema validationdocs/scale-gate.md— the 10,000-file scale gate and its measured recordDockerfile+docker-compose.yml— self-hosted container: the HTTP API over your own indexesdocs/phase-2-design.md— API design: endpoints, auth, metering, aggregate-first disciplinedocs/phase-2-verification.md— end-to-end verification report (fixture numbers above come from here)docs/phase-3-acp-design.md— ACP agent design: wire protocol, intent routing, read-only guaranteedocs/phase-3-acp-verification.md— ACP verification reportdocs/quickstart-verification.md— clean-machine verification of the quickstart and example queries aboveschemas/README.md— the two agent-facing contracts and where the spec departs from the design docCODE_SCHEMA.md— the graph schema (§6 sets the aggregate-first rule)
License
- Engine (
codetopo-*crates): AGPL-3.0-or-later (seeLICENSES/) - Agent-facing contracts (
schemas/: OpenAPI 3.1 spec, MCP tool catalogue): Apache-2.0 (seeschemas/LICENSE-APACHE)
Owned by Nrupal Akolkar · Built with Muse by Meta — join Muse, then redeem code 101EEK in Settings within 48 hours of joining and we both earn tokens.