repo2graph
This MCP server lets a coding agent explore an indexed repository structurally — cited, token-bounded answers built from a prebuilt code graph, with no LLM and no network calls.
Get oriented —
repo_mapreturns languages, hub files and entry points, flagging a stale index.Search code —
repo_searchruns BM25 ranking plus graph-neighbour expansion, returning[cite: path:start-end]blocks under a hard token ceiling (default 6,000, max 12,000).Walk the graph —
repo_neighbourslists a symbol's callers, callees, base classes and defining file, with per-edge confidence and optional JSON output.Resolve names to IDs —
repo_find_symbolmaps a name, or apath+line, to anode_idwithout a search round trip.Read source —
repo_readreturns a widened window around a citation straight from the index, so it works with no shared filesystem and respects secret-file exclusion.Trace connections —
repo_path_betweenfinds bounded call/import paths between two nodes and reports the minimum confidence along each.Assess impact —
repo_blast_radiusdoes reverse reachability: callers of callers, subclasses, importers and historically co-edited files.Page and monitor — cursor-based paging on search and neighbours;
repo_cache_statsreports cache hit rates andrepo_build_statuspolls an async index build.Scoped safely — secret files excluded, paths outside the repo refused, every tool idempotent and read-only.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@repo2graphFind the functions involved in user login and list their callers, callees, and neighbours."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
repo2graph
Cited, token-bounded answers about a codebase, for coding agents and CI.
Ask a repository a question and get back the source that answers it. Every block is headed
[cite: path:start-end], and the whole reply fits under a token ceiling that the tool enforces.
One tree-sitter pass records who calls whom, who imports what, and which files keep changing
together in git. Retrieval starts from BM25 matches and follows those links.
It needs no model, no API key, no language server and no database. Building, querying and the
MCP server make no network calls; the only exceptions are rag --answer (opt-in, sends the pack
to an LLM), repo2graph github and a rag/query target given as a GitHub spec (both clone a
repository), and --vectors/embed (download the embedding model on first use). Parsers are part of that promise:
tree-sitter-language-pack is pinned below 1.0 so every grammar arrives compiled into the
installed wheel, rather than being downloaded on first parse — see
SECURITY.md. Use it from the CLI, as an MCP server in Claude Code or Cursor, or as a GitHub Action.
Try it
uvx repo2graph demo # bundled example repo, five questions answered
uvx repo2graph build . -o .r2g # index your own code
uvx repo2graph rag "how does routing work" -o .r2g # a cited, budget-bounded context packGive an agent the same thing over MCP:
claude mcp add repo2graph -- uvx --from "repo2graph[mcp]" repo2graph-mcp .Cursor, Claude Desktop and other clients: docs/mcp.md. Step-by-step with expected
output: demo in docs/cli.md. What it produces on
thirteen well-known repositories — Django, FastAPI, React, Kubernetes, Linux and others, each at a
pinned commit with the command to reproduce it: examples/.
In VS Code, the extension in editors/vscode/ (a preview, built from
source) shows the callers, callees, base classes and co-changed files of the symbol at the cursor,
through the same MCP server.
Related MCP server: RepoGraph
Is it better than grep?
On cross-file structural questions, yes. On single-file lexical queries, no — grep is the
better tool. Both halves are measured on 40 lexical and 40 structural questions about Flask,
requests, FastAPI and Hono that repo2graph was not tuned against, scored against the
definitions that answer them, every retriever held to the same token budget
(method, full tables and diagnosis; raw rows in
results_holdout_final.json).
Where repo2graph wins: cross-file structural questions
grep structurally cannot traverse dependency edges, compute reverse call closures, or follow cross-module delegation. On questions whose evidence provably spans a cross-file graph edge:
Budget | repo2graph | lexical search alone | grep, then read around hits |
2,000 tokens | 29% | 24% | 14% |
4,000 tokens | 60% | 48% | 21% |
8,000 tokens | 79% | 55% | 38% |
The graph is what does it, and that is the comparison that matters: expansion adds +5/+12/+24 pp over the same retriever with expansion switched off. Against grep the margin is +15/+39/+41 pp — it widens with budget rather than closing, because grep has no edge to follow however much room it is given. It also gets there for fewer tokens than grep at every budget, by 7, 7 and 398 mean tokens, because a cited definition is a smaller thing to return than a window around every textual hit.
Where grep wins: single-file lexical questions
Budget | repo2graph | grep, then read around hits |
2,000 tokens | 17% | 28% |
4,000 tokens | 29% | 48% |
8,000 tokens | 45% | 59% |
On purely lexical questions where the evidence sits in a single file, text search is grep's
optimum, and this gap is real: −11/−19/−14 pp. We have not closed it. The remaining cause looks
like vocabulary mismatch rather than ranking — a question that says "datetime" does not match
code that says "timestamp" — which is why the
dense-vector path closes it to −2 pp at 8,000
tokens and more BM25 tuning has not. That path needs a downloaded model, so it is opt-in
(pip install "repo2graph[rag]") and the zero-dependency default stays the default.
That extra pulls PyTorch, which on Linux brings the NVIDIA CUDA wheels (several GB); the model is
fetched from Hugging Face on first use and its own licence and training data are yours to review
before you adopt it. Once it is cached, set HF_HUB_OFFLINE=1 so later runs make no request.
If that is too much to carry — on a CI runner, say — pip install "repo2graph[rag-static]" and
--embed-backend static get dense retrieval without torch: model2vec is a token→vector table
plus mean pooling, so inference is numpy, and it costs ~60 MB of packages and a ~31 MB model.
It is a different model (256-dim against 384), not a cheaper way to run the same one, so expect
it to retrieve differently — the figures above are the rag backend's. Pass the same
--embed-backend on the query side as you did to embed: the recorded model id is prefixed per
backend, so a mismatch is refused rather than silently fused.
Where repo2graph wins for agents: fewer turns
In simulated agent workflows (search → read → answer, via scripts/agent_eval.py). No
model is in the loop — the "agent" is a deterministic policy over real ripgrep and a real index:
Task set | Method | Success | Mean turns | Mean tokens | Precision per read |
Structural (40) | repo2graph | 40% | 1.9 | 2,590 | 12.0% |
Structural (40) | ripgrep | 10% | 2.5 | 586 | 29.0% |
Lexical (40) | repo2graph | 20% | 1.4 | 2,070 | 21.7% |
Lexical (40) | ripgrep | 18% | 3.0 | 740 | 89.1% |
Four times the structural success rate, and it reaches an answer in one or two turns where grep needs three. The turn count is the number that moved most — structural went 3.1 to 1.9 — because sharper seed ranking puts the answer in the first pack more often, and a turn saved is worth more to an agent than a token saved. It is not cheap: 4.4× grep's tokens on the structural set and 2.8× on the lexical one, and grep wins precision per read on both. repo2graph buys recall and turns with context; the budget-matched comparison is the single-shot tables above.
For completeness, the 35+10 question set this page used to report — visible since the first version of these tables and therefore a regression set, not evidence — now reads 44/63/80% lexical against grep's 35/61/72%, and 60/80/100% structural against grep's 20/20/70%. Those are the better-looking numbers, which is exactly why the held-out set is the one quoted above.
What it does do that grep doesn't:
Relationships in one hop.
repo_neighboursreturns a symbol's callers, callees, base classes and defining file, each with a line number. Every edge carries aconfidence: a name that could mean several definitions is markedambiguousand priced at1/n, not guessed.A hard ceiling. The pack is measured, clamped and re-measured before it's returned (12k tokens max over MCP), so an agent can't flood its own context through this tool.
Reverse closures from the graph.
repo_blast_radiuswalks what depends on a symbol, bounded by hop count and visit cap, with a citation per edge.
How it compares with Serena, Aider's repo map, CodeGraphContext, code-graph-rag, Sourcegraph, Cursor's index and Claude Code's own search, and with the dependency-graph tools Madge, dependency-cruiser and CodeSee, including when to use those instead: docs/comparison.md. Looking for a Sourcetrail alternative? It is not a drop-in replacement — there is no interactive desktop UI — and the comparison says what it does instead.
Five questions to start with
Ask your repo | What the graph adds |
| the guard itself, plus the routes that call it ( |
| CALLS edges into it, each with a confidence score |
| IMPORTS edges from the test module back to the code under test |
| the definition, then its direct callers from the CALLS edges into it (explain node) |
| the handler and its callees one hop at a time, each block cited to file and line |
GitHub Action
- uses: actions/checkout@v4
with: { fetch-depth: 0 } # full history, so CO_CHANGE edges are meaningful
- uses: Srinivasan-78/repo2graph@v4
with:
git-history: "500"
commit-branch: graph # optional: publish graph.html to a browsable branch@v4 follows every 4.x release; pin an exact tag (@v4.1.0) to upgrade by hand. The Action never
calls an LLM. Inputs and outputs: docs/cli.md.
Commands
Command | Does |
| Parse a repo into a graph and chunks ( |
| BM25 search plus one graph hop |
| Budget-bounded, cited context pack ( |
| Why an edge exists, or why a block was retrieved |
| Fetch, build and clean up without a local clone |
| Index a bundled example and answer the five questions above |
| Re-render |
| What changed structurally between two builds: symbols added, removed and renamed, edges, and whose callers changed |
| Diagnose setup, build a privacy-safe bug bundle, say why a path is (not) indexed, shell completion |
| stdio MCP server: |
Full flags: docs/cli.md. Python API: docs/python-api.md. Build cost up to 50,000 files: benchmarks/perf/README.md.
What it can't do
Resolve calls by type. Calls are matched by name, scoped by class, file, imports and directory.
x.get()on a receiver of unknown type is recorded as a low-confidence guess, not a fact. For exact references, use a language-server tool, or handbuild --scip index.scipa SCIP index (fromscip-python,scip-typescript, ...) to make the calls and bases it covers exact; see docs/architecture.md.See dynamic dispatch, reflection or computed imports. A missing edge doesn't prove that no call exists.
Cross language boundaries (Python calling C++ through bindings).
See a route that is registered by a call.
build --framework-edgeslinks decorator-declared routes to their handlers (FastAPI, Flask, Starlette, Sanic, NestJS) and adds a node per endpoint, soGET /users/{id}is a thing you can ask about. Express, Hono and Django'surlpatternsregister with a call instead —app.get("/x", handler)— where the handler is an argument and often an inline function, and those get no edge.
Symbols, calls and classes are extracted for Python, JS, TS, TSX, Go, Rust, Java, Ruby, C, C++,
C#, PHP, Kotlin, Swift, Scala, Bash, Lua, Objective-C and HCL (Terraform), plus the <script> blocks
of Vue and Svelte components and the code cells of Jupyter notebooks. Every other file is still
indexed as text. The
specific cases that defeat it — reflection dispatch, string-keyed registries, barrel re-exports —
are pinned as known failures in the
synthetic regression suite, and
per-language coverage is scored, unevenly, in
docs/architecture.md §4.
Two of those nineteen are benchmarked on real repositories: Python (Flask, requests, FastAPI) and TypeScript (Hono). Treat the rest as parsed-and-unmeasured. That is not a formality — the retrieval benchmark found two parse gaps in the one TypeScript repository as soon as it looked, one of which was hiding Hono's entire public API, and neither would have been visible without a real repository to ask questions about.
Status
The 3.x CLI, MCP tools and output schema follow semver. Default paths run locally, send no telemetry and exclude secrets from agent replies unconditionally (what never leaves your machine, how credential files are excluded, reporting a vulnerability). A Dockerfile for read-only, non-root local builds is provided (.github/SECURITY.md).
Platform & Environment Requirements
Environment | Status | Details |
Python | 3.10 – 3.14 | Tested across Linux, macOS, and Windows in CI (15 cells). Python 3.15+ is untested. Note that 3.10 reached end of life in October 2026; it remains the supported floor, but upgrading is recommended. |
Linux (glibc) | Supported (glibc ≥ 2.34) | Precompiled |
Legacy Linux | Unsupported wheels | RHEL 8, CentOS 8, Amazon Linux 2, Debian 11, and Ubuntu 20.04 ship glibc < 2.34. Wheels fail to load; use a glibc 2.34+ container or compile grammars from source. |
Alpine / musl | Unsupported wheels | Precompiled grammar wheels are not distributed for musl libc. Use a glibc container or build with a C toolchain. |
macOS / Windows | Fully supported | Tested on macOS 12+ (Apple Silicon & Intel) and Windows 10/11 (UTF-8 & CP1252 codepages). |
Run repo2graph doctor to diagnose environment and platform support.
Security & Maintenance Posture
Single maintainer: repo2graph is developed and maintained by a single author (@Srinivasan-78).
Automated gates: Pull requests must pass automated CI checks (ruff, mypy, multi-OS test matrix, synthetic regression benchmarks).
Review policy: Pull requests require 0 third-party review approvals to merge to
main.Commit signing: Commit signing is not currently enforced on
main.Integrity: Releases are published to PyPI with provenance attestations.
uv.lockpins every dependency by hash for CI and contributors (uv sync --frozen); a plainpip install repo2graphresolves its own versions within the ranges inpyproject.tomland does not read it.
Contributing
git clone https://github.com/Srinivasan-78/repo2graph && cd repo2graph
python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
make lint format-check typecheck testBranch from develop. Start with .github/CONTRIBUTING.md and
docs/architecture.md. The most useful contribution right now is new
questions for the retrieval benchmark, especially on repositories
you know well. All docs: architecture, CLI,
MCP, Python API, comparison.
MIT licensed.
Available Tools
9 toolsrepo_blast_radiusAIdempotent
Reverse reachability from a node_id: callers of callers, subclasses of subclasses, importers of importers of its file, and historically co-edited files, by hop distance -- the blast radius of changing it. Read-only, deterministic, zero side effects, secret files excluded. When to use: use before editing a symbol to see what depends on it, or to answer 'what is the blast radius of changing X'. When NOT to use: do not use for open-ended search (use repo_search) or to read a symbol's own body (use repo_read). Output: JSON object with callers, subclasses, importers, cochange, and a summary.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum rows per section (default 40, max 50). | |
| node_id | Yes | Graph node id to analyze (e.g. from repo_find_symbol or a repo_search citation). | |
| max_hops | No | Reverse-closure depth (default 3, max 6). | |
| include_cochange | No | Include historically co-edited files (default true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description asserts 'Read-only, deterministic, zero side effects', but the annotations declare readOnlyHint=false, which signals the tool may mutate state. This is a direct contradiction between prose and structured metadata and is the most consequential thing an agent needs to resolve before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core semantic, then a when-to-use/when-not-to-use block and an output summary. Dense but each sentence carries routing or behavioral information; the output line earns its place since no output schema exists.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a graph-analysis tool with no output schema, the description supplies the return shape (callers, subclasses, importers, cochange, summary), usage routing, and semantics. It would be complete were it not for the unresolved read-only claim, which leaves the tool's actual safety profile ambiguous.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so node_id, limit, max_hops, and include_cochange are all documented in the schema with defaults and maxima. The description adds only loose framing (hop distance, co-edited files) and no format or syntax detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a precise verb+resource with scope: 'Reverse reachability from a node_id' enumerating callers, subclasses, importers, and co-edited files by hop distance. It is immediately distinguishable from siblings like repo_search and repo_read, which it names explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use ('before editing a symbol', 'what is the blast radius of changing X') and when-NOT-to-use with named alternatives ('do not use for open-ended search (use repo_search) or to read a symbol's own body (use repo_read)'). This is exactly the routing guidance an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
repo_build_statusARead-onlyIdempotent
Query progress and status of a background index build task under --async-build. Read-only check of in-memory background worker. When to use: use when polling build progress after an async index build was started. When NOT to use: do not use when building synchronously or when queries already succeed. Once completed, use repo_search or repo_map to query code. Output: JSON object with task_id, status, parsed file progress, and error details.
| Name | Required | Description | Default |
|---|---|---|---|
| task_id | Yes | Task ID string returned by a previous tool call when an asynchronous build was initiated. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false. The description adds useful behavioral context beyond annotations by stating it is a read-only check of an in-memory background worker and by specifying the output fields (task_id, status, parsed file progress, error details). This goes beyond what the annotations alone provide, though it does not disclose edge cases like unknown task IDs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized with clear sections for usage, non-usage, follow-up, and output. Every sentence contributes useful information without redundancy, and the most important scoping detail (--async-build) is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter read-only tool with strong annotations, the description is complete: it explains the operation, when to call it, what not to do, what the output contains, and what to use afterward. The absence of an output schema is compensated by listing the expected JSON fields.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the task_id parameter is already well documented as the ID returned by a previous async build call. The description does not add significant meaning beyond the schema, so the baseline score of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as a status/progress query for a background index build task under --async-build, with a specific verb and resource. It also distinguishes itself from sibling tools by explicitly mentioning repo_search and repo_map as the post-completion alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance (polling after an async build was started) and when-not-to-use guidance (synchronous builds or when queries already succeed). It also names the correct follow-up tools, making the decision boundary unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
repo_cache_statsAIdempotent
Retrieve runtime diagnostic counters for the tool result cache (hits, misses, size, max_size, ttl_s). Read-only, in-memory diagnostics, zero side effects. When to use: use when evaluating cache hit rate or debugging server performance. When NOT to use: do not use to search repository contents or inspect code structure; use repo_map or repo_search instead. Output: JSON object with cache metrics.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description asserts 'Read-only, in-memory diagnostics, zero side effects,' but the annotations declare readOnlyHint=false and openWorldHint=true, directly conflicting with that claim. An agent relying on the prose would misjudge the safety profile of this tool. This is a genuine annotation contradiction rather than ordinary missing context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well front-loaded and organized with labeled 'When to use', 'When NOT to use', and 'Output' segments; each sentence is short and purposeful. Slight redundancy in piling 'Read-only, in-memory diagnostics, zero side effects' on top of annotations that already cover mutability, and that stacking is what creates the conflict.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no parameters and no output schema, the description supplies what an agent needs: what the tool reports, the named metrics, and where the sibling tools handle repo searching. The only real gap is that it does not reconcile its read-only framing with the annotation-declared openWorldHint/readOnlyHint values.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so per the baseline the schema carries no semantics to explain. The description instead names the metric fields it returns (hits, misses, size, max_size, ttl_s), which is extra useful detail even though it is about output rather than input.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — 'Retrieve runtime diagnostic counters for the tool result cache' — and enumerates the counters (hits, misses, size, max_size, ttl_s). It is clearly distinguishable from siblings like repo_map and repo_search, which it explicitly names as not-this.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit 'When to use' (evaluating cache hit rate, debugging server performance) and 'When NOT to use' (searching repository contents or inspecting code structure) with named alternatives (repo_map, repo_search). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
repo_find_symbolAIdempotent
Look up a symbol or file's node_id by name, or by path and line (the symbols enclosing that line, innermost first, then the file), for feeding into repo_neighbours, repo_read, repo_path_between or repo_blast_radius. Read-only, deterministic, zero side effects, secret files (.env) excluded. A name matches exactly first, then case-insensitively, then as a qualname's last segment; an ambiguous name returns every candidate, with its path. When to use: you know a name (from a traceback, a grep, a review comment) or a file position and want its node_id with no repo_search round trip. When NOT to use: not for open-ended text search (use repo_search) or for repo layout (use repo_map). Output: JSON array of {node_id, name, qualname, kind, path, start_line, end_line, lang}.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Optional exact node kind filter (e.g. 'function', 'class', 'method'). | |
| line | No | Optional 1-based line in `path` (min 1): only the symbols whose span contains it, innermost first, then the file node. | |
| name | No | Symbol or file name to look up (e.g. 'validate_token'). May be omitted when `path` and `line` are given. | |
| path | No | Optional exact repo-relative file path (e.g. 'pkg/mod.py'): only nodes in that file. | |
| limit | No | Maximum candidates returned (default 20, min 1, max 50). | |
| path_prefix | No | Optional path prefix filter, e.g. 'pkg/'. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description asserts 'Read-only, deterministic, zero side effects', but the annotations declare readOnlyHint=false. This is a direct conflict an agent cannot reconcile when deciding whether the call is safe. The genuine added context (secret files such as .env excluded, name-matching order, ambiguity behavior) is real, but the annotations-vs-description contradiction dominates.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One dense, well-structured block: purpose first, then lookup semantics, then when/when-not, then output shape. Every sentence carries information, though the run-on first sentence packs several distinct ideas and could be split for faster scanning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by enumerating the return shape ({node_id, name, qualname, kind, path, start_line, end_line, lang}). Combined with sibling routing and the .env exclusion, an agent has nearly everything it needs; only the unresolved readOnlyHint conflict leaves a residual gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3, and the description earns an extra point for match-resolution semantics the schema does not state: exact match first, then case-insensitive, then qualname's last segment, with every candidate plus its path returned on ambiguity, and line lookups returning enclosing symbols innermost-first.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb+resource (look up a symbol or file's node_id) plus the two input modes (by name, or by path+line) and the downstream consumers (repo_neighbours, repo_read, repo_path_between, repo_blast_radius). It is clearly distinguishable from repo_search and repo_map, which it names explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Contains explicit 'When to use' (known name from a traceback/grep/review comment, or a file position, avoiding a repo_search round trip) and 'When NOT to use' (open-ended text search → repo_search; repo layout → repo_map) sections naming the alternatives. Routing is fully determined.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
repo_mapAIdempotent
Retrieve a high-level structural map of the repository: languages, hub files, and top entry points. Read-only, deterministic, zero side effects. When to use: call this first at session start to understand codebase layout and identify entry points before detailed queries. Use when deciding where to investigate. When NOT to use: do not use to search code (use repo_search) or inspect call graphs (use repo_neighbours). Output: markdown summary of languages, hub files, and entry points, prefixed with a staleness note when the indexed working tree has changed since the index was built -- treat citations as suspect until rebuilt.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description asserts 'Read-only, deterministic, zero side effects,' but the annotations declare readOnlyHint=false. This directly contradicts the structured safety signal an agent relies on, so the behavioral disclosure is untrustworthy rather than merely incomplete.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then usage, then output, in a logical order with no filler. It is somewhat dense and the staleness caveat is long, but every sentence carries actionable content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema present, the description supplies the return shape ('markdown summary of languages, hub files, and entry points') plus a staleness caveat about changed working trees. That is exactly the context needed to call and interpret the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; baseline 4 applies. The description correctly implies no inputs are required.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Retrieve a high-level structural map of the repository') and enumerates the content (languages, hub files, entry points). It is clearly distinguishable from siblings like repo_search and repo_neighbours, which it explicitly names.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use ('call this first at session start... before detailed queries'), explicit when-not-to-use with named alternatives ('do not use to search code (use repo_search) or inspect call graphs (use repo_neighbours)'). Routing is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
repo_neighboursAIdempotent
Traverse code graph relationships from a known symbol or file node_id (callers, callees, base classes, definitions). Read-only, deterministic traversal, no side effects. When to use: use with a specific node_id (e.g. from repo_search citations) to inspect callers (CALLS in), callees (CALLS out), inheritance, definitions, or the tests that reach a symbol through calls (TESTS in). When NOT to use: do not use for text search across code (use repo_search) or repo overview (use repo_map). Output: markdown list formatted as - <EDGE_TYPE> <in|out>: <name> (<path:line>) [<node_id>], or with format="json" the same rows as JSON plus co-changed files. To page past limit, pass cursor="" then each next_cursor: token from the reply's last line.
| Name | Required | Description | Default |
|---|---|---|---|
| hops | No | Traversal depth from node_id (default 1, max 4). | |
| limit | No | Maximum neighbor rows to return (default 20, min 1, max 50). | |
| cursor | No | Opt-in paging. Omit for one unpaged answer. Pass "" for the first page of limit rows; while more remain the reply ends with a `next_cursor: <token>` line (also _meta.nextCursor). Pass that token back, other arguments unchanged, for the next page. | |
| format | No | Output format (default markdown). json returns {node, neighbours, cochange, truncated}: each neighbour row with its edge, direction, path and lines, and the files co-edited with the node's file -- for programs such as editors. | |
| node_id | Yes | Target graph node identifier to expand from (e.g. 'sym:pkg/mod.py::func', 'file:pkg/mod.py', 'dir:pkg'). | |
| min_confidence | No | Drop CALLS and TESTS edges below this confidence, 0..1 (default 0.0: keep everything, marking ambiguous edges). 1.0 keeps only unambiguous ones. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description asserts 'Read-only, deterministic traversal, no side effects', but the annotations declare readOnlyHint=false, which tells the agent this tool may modify state. That is a direct conflict on the single most important behavioral attribute, and the calibration rubric scores a description that contradicts its annotations as 1 regardless of other detail. The otherwise useful extras (deterministic ordering, paging protocol) cannot offset a contradiction about mutability.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The content is dense but front-loaded: purpose, then use/not-use, then output and paging. Every clause carries information, though the final sentence on cursor handling is long enough to be slightly cumbersome and partially duplicates the cursor schema description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter read-style traversal with no output schema, the description covers edge types, direction notation, the exact markdown row format, the json alternative including co-change data, and the paging continuation token. An agent has everything needed to call and interpret it, aside from the mutability inconsistency noted above.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so hops, limit, node_id, format and min_confidence semantics are already documented in the schema; baseline is 3. The description adds only marginal value beyond that: the cursor paging handshake and the json payload shape (neighbours plus co-changed files), with no extra detail on hops or min_confidence thresholds.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('traverse code graph relationships from a known symbol or file node_id') and enumerates the edge kinds traversed (callers, callees, base classes, definitions, TESTS). It explicitly distinguishes itself from the siblings repo_search and repo_map, so an agent can pick it without opening sibling schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Contains explicit 'When to use' and 'When NOT to use' sections that name the alternatives (repo_search for text search, repo_map for overview) and the triggering input (a node_id from repo_search citations). Routing is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
repo_path_betweenAIdempotent
Find a bounded, bidirectional path between two node_ids over CALLS/DEFINES/IMPORTS edges (CO_CHANGE only if named explicitly), reporting the minimum confidence along each path. Read-only, deterministic traversal, no side effects. When to use: use for 'how does X reach Y' questions a text search cannot answer, e.g. the call chain from an HTTP handler to a database write. When NOT to use: do not use for one-hop neighbours (use repo_neighbours) or open-ended search (use repo_search). Output: JSON array of paths, each an ordered array of {node_id, path, start_line, end_line, via_edge, confidence}.
| Name | Required | Description | Default |
|---|---|---|---|
| to_id | Yes | Target graph node id. | |
| from_id | Yes | Starting graph node id. | |
| max_hops | No | Maximum path length in hops (default 6, max 8). | |
| max_paths | No | Maximum distinct paths returned (default 3, max 10). | |
| edge_types | No | Edge types to traverse (default ['CALLS', 'DEFINES', 'IMPORTS']). CO_CHANGE is a statistical correlation, not a call/definition path, and is only followed when named here explicitly. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description asserts 'Read-only, deterministic traversal, no side effects,' but the annotations declare readOnlyHint=false, which tells an agent the opposite. These two signals directly conflict and an agent cannot tell whether invoking this tool may mutate state. The conflict is flaggable under the contradiction rule even though other behavioral details (bounded traversal, min-confidence reporting) are otherwise informative.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the operation, then clearly delimited 'When to use', 'When NOT to use', and 'Output' segments. Dense but every sentence carries information an agent needs; no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly supplies the return shape (JSON array of ordered {node_id, path, start_line, end_line, via_edge, confidence} objects), plus traversal bounds and default edge types. An agent has everything needed to call and interpret results — the only defect is the safety-signal conflict noted above.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% — every parameter, default, and the CO_CHANGE caveat is documented in the schema itself. The description only restates the CO_CHANGE rule already present in the edge_types field, adding no new syntax or format guidance. Baseline 3 applies when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource+scope: find a bounded bidirectional path between two node_ids over named edge types, reporting minimum confidence per path. It distinguishes itself from siblings by explicitly naming repo_neighbours and repo_search as the wrong tools for adjacent tasks.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'When to use' with a concrete example (HTTP handler to database write) and an explicit 'When NOT to use' that routes to the correct alternatives (repo_neighbours for one hop, repo_search for open-ended search). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
repo_readAIdempotent
Read a widened window of source text around a citation, from the indexed chunks rather than the filesystem -- works with no shared filesystem between client and server, because chunks have already passed secret-path exclusion and redaction. Read-only, deterministic, zero side effects. When to use: use after repo_search or repo_neighbours to see more lines around a [cite: path:start-end] citation, with optional context lines each side. When NOT to use: do not use for a path never indexed, or an absolute or '..' path (both are refused); use repo_search or repo_find_symbol to find a valid path first. Output: [cite: path:start-end] header plus the text, bounded in size.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Repo-relative path exactly as it appears in a [cite: path:start-end] header. Absolute paths and '..' segments are refused. | |
| context | No | Extra lines of context on each side of the range (default 0, max 500). | |
| end_line | No | Last line to read (default: start_line). | |
| start_line | No | First line to read (default 1). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description asserts 'Read-only, deterministic, zero side effects', but the annotations declare readOnlyHint=false, directly contradicting that claim. It does add real context beyond the annotations (indexed-chunk source, secret-path exclusion and redaction, absolute/'..' paths refused, bounded output), but the explicit read-only claim conflicts with the declared safety profile, which is the exact condition for a 1 here.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is on the long side but tightly structured and front-loaded: purpose, then security rationale, then when/when-not, then output. Each sentence carries information, though the read-only/deterministic/zero-side-effects claim partly duplicates annotation territory and turns out to be unreliable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description does explain the return shape ('`[cite: path:start-end]` header plus the text, bounded in size') and covers security and indexing constraints. It is nearly complete, but the unresolved contradiction with readOnlyHint leaves an agent unsure how much to trust the tool's stated safety properties.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters and their defaults/limits are already documented in the schema. The description reinforces the refusal rule for absolute and '..' paths and restates the optional `context` behavior, but adds no syntax or semantics the schema lacks; baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence names a specific verb and resource ('Read a widened window of source text around a citation') and adds crucial scope: it reads from indexed chunks, not the filesystem. It cleanly separates itself from repo_search/repo_neighbours by explaining the citation-centered window concept, so an agent can choose it without opening a sibling schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides explicit 'When to use' and 'When NOT to use' sections, names the exact trigger ('after repo_search or repo_neighbours' to widen a `[cite: path:start-end]`), and routes invalid paths to repo_search or repo_find_symbol. This is textbook when/when-not/alternative guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
repo_searchAIdempotent
Search repository code for answers to questions using BM25 lexical ranking expanded with graph neighbours. Read-only, no side effects, secret files (.env) excluded. When to use: use for open-ended queries, locating implementations, or finding error strings. When NOT to use: do not use when you already have a symbol node_id and want callers/callees (use repo_neighbours); do not use for broad repo layout (use repo_map). Output: markdown citation blocks [cite: path:start-end] bounded by budget_tokens. To page, pass cursor="" then each next_cursor: token from the reply's last line.
| Name | Required | Description | Default |
|---|---|---|---|
| k | No | Number of initial seed chunks retrieved via BM25 lexical scoring (default 8, max 50). | |
| hops | No | Graph traversal depth around seed chunks (default 1, max 4; 0 returns seeds only). | |
| query | Yes | Natural language question, search terms, or symbol identifier to search for (e.g. 'pack_context' or 'how does export work'). | |
| cursor | No | Opt-in paging. Omit for one unpaged answer. Pass "" for the first page of k seed results; while more remain the reply ends with a `next_cursor: <token>` line (also _meta.nextCursor). Pass that token back, other arguments unchanged, for the next page. | |
| budget_tokens | No | Maximum token ceiling for returned markdown pack (default 6000, max 12000; zero or negative uses the default). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description asserts "Read-only, no side effects," but the annotations declare readOnlyHint=false, a direct conflict about whether this tool mutates state. Although the description usefully adds secret-file exclusion and pagination mechanics, the contradiction with structured safety metadata forces a 1 under the scoring rule.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose, then cleanly segmented into when-to-use, when-not-to-use, output, and paging. Dense but every sentence carries routing or behavioral information; no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description supplies the return format (markdown `[cite: path:start-end]` blocks), the budget_tokens bounding behavior, and the full cursor paging loop including the `next_cursor:` token location. That is complete enough for an agent to invoke and iterate correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so k, hops, query, cursor, and budget_tokens are already documented at the field level (baseline 3). The description restates the budget and cursor paging behavior but adds no format, range, or interaction detail beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ("Search repository code") plus the retrieval mechanism (BM25 lexical ranking expanded with graph neighbours), which is enough to distinguish it from repo_map and repo_neighbours. An agent knows exactly what class of operation this is before opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly enumerates when to use (open-ended queries, locating implementations, finding error strings) and when NOT to use, naming the correct sibling for each excluded case (repo_neighbours for callers/callees from a node_id, repo_map for broad layout). This is textbook routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v4.0.0- Changed
repo_find_symbol4 fields changed- added
Input schema / properties / lineAdded value: +{ + "description": "Optional 1-based line in `path` (min 1): only the symbols whose span contains it, innermost first, then the file node.", + "type": "integer" +} - changed
Input schema / properties / name / descriptionPrevious value: -"Symbol or file name to look up (e.g. 'validate_token')."New value: +"Symbol or file name to look up (e.g. 'validate_token'). May be omitted when `path` and `line` are given." - added
Input schema / properties / pathAdded value: +{ + "description": "Optional exact repo-relative file path (e.g. 'pkg/mod.py'): only nodes in that file.", + "type": "string" +} - changed
Input schema / requiredPrevious value: -[ - "name" -]New value: +[]
- Changed
repo_neighbours3 fields changed- added
Input schema / properties / cursorAdded value: +{ + "description": "Opt-in paging. Omit for one unpaged answer. Pass \"\" for the first page of limit rows; while more remain the reply ends with a `next_cursor: <token>` line (also _meta.nextCursor). Pass that token back, other arguments unchanged, for the next page.", + "type": "string" +} - added
Input schema / properties / formatAdded value: +{ + "description": "Output format (default markdown). json returns {node, neighbours, cochange, truncated}: each neighbour row with its edge, direction, path and lines, and the files co-edited with the node's file -- for programs such as editors.", + "enum": [ + "markdown", + "json" + ], + "type": "string" +} - added
Input schema / properties / min_confidenceAdded value: +{ + "description": "Drop CALLS and TESTS edges below this confidence, 0..1 (default 0.0: keep everything, marking ambiguous edges). 1.0 keeps only unambiguous ones.", + "type": "number" +}
- Changed
repo_search1 field changed- added
Input schema / properties / cursorAdded value: +{ + "description": "Opt-in paging. Omit for one unpaged answer. Pass \"\" for the first page of k seed results; while more remain the reply ends with a `next_cursor: <token>` line (also _meta.nextCursor). Pass that token back, other arguments unchanged, for the next page.", + "type": "string" +}
7 tool updates
v3.0.0- Added
repo_blast_radius - Added
repo_find_symbol - Removed
repo_impact - Changed
repo_neighbours1 field changed- changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum neighbor rows to return (default 20, max 50)."New value: +"Maximum neighbor rows to return (default 20, min 1, max 50)."
- Added
repo_path_between - Added
repo_read - Changed
repo_search1 field changed- changed
Input schema / properties / budget_tokens / descriptionPrevious value: -"Maximum token ceiling for returned markdown pack (default 6000, max 12000)."New value: +"Maximum token ceiling for returned markdown pack (default 6000, max 12000; zero or negative uses the default)."
1 tool update
v2.2.0- Added
repo_impact
3 tool updates
v1.5.1- Changed
repo_build_status1 field changed- changed
Input schema / properties / task_id / descriptionPrevious value: -"the id a previous call returned"New value: +"Task ID string returned by a previous tool call when an asynchronous build was initiated."
- Changed
repo_neighbours3 fields changed- changed
Input schema / properties / hops / descriptionPrevious value: -"graph hops (default 1, max 4)"New value: +"Traversal depth from node_id (default 1, max 4)." - changed
Input schema / properties / limit / descriptionPrevious value: -"neighbours (default 20, max 50)"New value: +"Maximum neighbor rows to return (default 20, max 50)." - changed
Input schema / properties / node_id / descriptionPrevious value: -"e.g. sym:pkg/a.py::run"New value: +"Target graph node identifier to expand from (e.g. 'sym:pkg/mod.py::func', 'file:pkg/mod.py', 'dir:pkg')."
- Changed
repo_search4 fields changed- changed
Input schema / properties / budget_tokens / descriptionPrevious value: -"max 12000"New value: +"Maximum token ceiling for returned markdown pack (default 6000, max 12000)." - changed
Input schema / properties / hops / descriptionPrevious value: -"graph hops (default 1, max 4)"New value: +"Graph traversal depth around seed chunks (default 1, max 4; 0 returns seeds only)." - changed
Input schema / properties / k / descriptionPrevious value: -"seed chunks (default 8, max 50)"New value: +"Number of initial seed chunks retrieved via BM25 lexical scoring (default 8, max 50)." - changed
Input schema / properties / query / descriptionPrevious value: -"the question"New value: +"Natural language question, search terms, or symbol identifier to search for (e.g. 'pack_context' or 'how does export work')."
5 tool updates
v0.1.0- First observed
repo_build_status - First observed
repo_cache_stats - First observed
repo_map - First observed
repo_neighbours - First observed
repo_search
TDQS
Scored across 9 tools
Each tool has a sharply distinct purpose, and descriptions explicitly cross-reference alternatives with 'When NOT to use' clauses (e.g., repo_search vs repo_neighbours vs repo_map). Even the three graph-traversal tools (neighbours, blast_radius, path_between) are cleanly separated by scope (one-hop, reverse-reachability, bounded path).
All tools share a consistent `repo_` prefix and snake_case form, which is highly predictable. There is minor stylistic drift between verb-led names (repo_search, repo_read, repo_find_symbol) and noun-led names (repo_map, repo_neighbours, repo_path_between), but this stays readable and conventional.
Nine tools is well-scoped for a read-only code-graph navigation server, with each tool earning its place across discovery, traversal, reading, and diagnostics. No redundant or filler tools are present.
The surface covers discovery (map, search, find_symbol), inspection (read, neighbours), and impact analysis (blast_radius, path_between) plus operational status. Minor gaps exist, such as explicit file/directory listing, but core read-only navigation workflows are well covered.
Maintenance
Related MCP Connectors
Hosted code graph over MCP: exact callers, dependencies, and cross-repo blast radius for AI agents.
Repository knowledge graph MCP server for codebase understanding and debugging.
Search GitHub, npm, PyPI, StackOverflow, ArXiv from one MCP — built for coding agents.
Search and inspect source-pinned agent skills, plugins and tools through a free public MCP.
Related MCP Servers
- AlicenseBqualityAmaintenanceAn MCP code-intelligence server for AI agents with pre-indexed AST cache, 62 MCP tools, and TOON-compressed output, enabling token-efficient code analysis and project health grading entirely locally.91,170 PyPI61MIT
- FlicenseNot gradedqualityCmaintenanceEnables coding agents to query a local-first code intelligence graph of Python repositories—covering functions, classes, modules, and their relationships—via MCP, supporting subgraph retrieval, caller lookup, and impact analysis without re-reading the codebase.-
- AlicenseNot gradedqualityBmaintenanceEnables coding agents to query a local, multi-repo code graph for symbol exploration, blast radius analysis, co-change mining, and durable code-anchored memory via MCP tools.288 npm14Business Source 1.1
- AlicenseNot gradedqualityCmaintenanceEnables AI coding agents to navigate and understand entire codebases through symbol-aware semantic retrieval and relational call graph traversal, supporting structural impact analysis and code modification workflows over MCP.Apache 2.0