io.github.Srinivasan-78/repo2graph
It is an MCP server that lets AI agents inspect a code repository's pre-built graph index and answer questions with cited code, without calling an LLM itself.
repo_map: Get a stable overview of the repository — languages, hub files, and top entry points.repo_search: Ask a natural-language question and retrieve cited code chunks plus their graph neighbours (seed chunks, k/hops/budget-token controls).repo_neighbours: Start from a specific node id (e.g.sym:pkg/a.py::run) and hop through callers, callees, base classes, and defining files.repo_cache_stats: Inspect result-cache diagnostics (hits, misses, size, TTL).repo_build_status: Check progress of an async background index build by task id.Built-in safeguards: secrets are excluded, output is capped at 12,000 tokens, and k/hops are clamped to protect the shared event loop.
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., "@io.github.Srinivasan-78/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
Interactive code-graph maps & zero-dependency GraphRAG for AI agents and humans
A complete project map drawn by repo2graph. Each dot is a folder, file, function, or library; each arrow is a real code connection.
repo2graph reads a folder full of code and draws you a map of it — then uses that map to answer questions about the code, with citations. Agents can ask it questions directly over MCP.
The idea
Imagine you get handed a big box of Lego that someone else already built things with. You want to know what connects to what. You could look at every brick one at a time, or someone could hand you a map.
Code is like that box. A project has hundreds of files, and the files use each other in ways you cannot see by looking at one file at a time.
repo2graph makes the map. On the map:
Every thing is a dot. A folder is a dot. A file is a dot. A function (a small named piece of code that does a job) is a dot. We call these dots nodes.
Every connection is an arrow. "This file is inside that folder." "This function uses that function." "This file borrows code from that library." We call these arrows edges.
Dots joined by arrows are called a graph. That is the whole idea.
Related MCP server: Lore MCP Server
Why a map helps
If you search a project for the word "login", you get every file that happens to say "login", including comments and typos.
The map is better, because it knows which function actually does the login work, and it also knows which functions call it and which functions it calls. So you get the real answer plus its neighbours.
That matters most when a chatbot or AI helper is reading the code for you. Giving it the right piece of code plus the pieces around it is usually what it was missing.
How it works, in three steps
flowchart LR
A[your code] --> B[tree-sitter<br/>reads the code]
B --> C[graph<br/>dots + arrows]
C --> D[graph.html<br/>the picture]
C --> E[overview.md<br/>the words]
C --> F[chunks.jsonl<br/>pieces for an AI]
C --> G[graph.graphml / graph.cypher<br/>other tools, Neo4j]It reads the code. It uses tree-sitter, the same tool code editors use to colour your code. So it understands real code structure instead of guessing from words. It needs no setup and works on a project it has never seen.
It builds the map. Folders, files, functions, classes and imports become dots. "contains", "defines", "calls", "imports", "inherits" become arrows.
It cuts the code into small pieces. Roughly one piece per function or class. Each piece gets a few lines at the top saying who calls this function, what it calls, and what its description says. Those little pieces are what you feed to an AI when you want it to answer questions about the code.
No graph library is involved: degree counting, layout and GraphML generation are pure Python, with no NetworkX.
Install
You need Python 3.10 or newer.
pip install repo2graphTwo optional extras, neither needed for the core:
pip install "repo2graph[rag]" # sentence-transformers + numpy, for meaning-based search
pip install "repo2graph[mcp]" # the MCP SDK, for serving the map to an agentTo run it without installing anything — which is how most people wire up the MCP server — use uv:
uvx repo2graph build . -o .r2g
uvx --from "repo2graph[mcp]" repo2graph-mcp /path/to/projectOr from a checkout, if you want to change it:
git clone https://github.com/Srinivasan-78/repo2graph
cd repo2graph
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"Use it
1. Make the map
repo2graph build /path/to/your/project -o .r2g --git-history 200That is it. It walks the project, reads it, and puts everything in a folder called .r2g. A medium
project takes seconds. A very big one takes a minute or two.
--git-history 200 is optional. It looks at the last 200 saves (commits) in the project's history
and adds links between files that keep getting changed together. Those links are a good clue about
which files secretly depend on each other.
No copy on your machine? Point it at GitHub instead — it downloads, maps, and tidies up after itself:
repo2graph github psf/requests -o out/requests --git-history 2002. Look at the map
open .r2g/human/graph.html # the picture
cat .r2g/human/overview.md # the same thing written out in words
repo2graph stats -o .r2g # how many dots, arrows and functions there aregraph.html is one single file. No internet needed, nothing to install. Open it in a browser and
you get the picture: drag to move around, scroll to zoom, drag a dot to pin it in place, click a
dot to see what that function looks like and everything it is connected to.
Interactive Canvas (Zoomed) | Filter & Inspector Controls |
Zoom in to inspect symbol call paths, imports, and definitions | Toggle node types, relationships, and filter on screen |
By default the picture shows the 300 busiest dots, and hides calls that go out to other people's
code, because those triple the number of arrows and tell you little about your own project. Tick
external and CALLS_EXTERNAL in the side panel to show them. Want a simpler picture? Redraw it
with fewer dots: repo2graph map -o .r2g --viz-nodes 80.
3. Ask it questions
A search tool and a GraphRAG context packer are built in. Neither needs an AI account.
repo2graph query "how does routing match a path" -o .r2g # find the code
repo2graph rag "how does the pack stay inside its budget" -o .r2g # pack it for an LLMquery finds the best matching pieces and follows the arrows one step out, so the functions around
each answer come along too. rag does the same and then assembles a budget-bounded markdown pack,
repo map on top, every block stamped with an exact citation header:
### [cite: repo2graph/cli.py:22-28] `parse_formats` (CALLS out of cmd_build)
# file: repo2graph/cli.py
# function: parse_formats (lines 22-28, python)
# called by: repo2graph/cli.py::cmd_build, repo2graph/cli.py::cmd_github
def parse_formats(spec: str) -> set[str]:
...The (CALLS out of cmd_build) part is the reason the block is in the pack: either seed (the
search found it) or the arrow that dragged it in.
Word matching misses code that says the same thing in different words, so you can add meaning-based search on top — vectors are computed once, then blended into every ranking:
pip install "repo2graph[rag]" # sentence-transformers + numpy
repo2graph embed -o .r2g # compute vectors, once
repo2graph rag "how is a request routed" -o .r2g --vectorsembed writes agent/vectors.npy and agent/vectors.meta.json next to the rest of the index, and
reuses every vector whose chunk text is unchanged, so re-running it after a rebuild is cheap. The
model is --embed-model (default: a small MiniLM); rag --model is a different thing entirely, the
LLM used by --answer.
Dense search is opt-in on purpose. Without --vectors nothing is loaded and no model is downloaded,
because the only promised dependency of build/rag is tree-sitter and a 90 MB model fetch has no
business happening unasked.
Check it is actually on. Dense retrieval has a failure mode where every surface reports success
and the ranking is still purely lexical — the index carries vectors, but a chunks.jsonl rebuilt
without re-running embed leaves some chunks unvectorised, and fusion is all-or-nothing:
repo2graph embed -o .r2g --verify-rag{
"vectors_present": true,
"model_id": "sentence-transformers/all-MiniLM-L6-v2",
"dim": 384,
"chunks": 812,
"unvectorised_chunks": 0,
"embedder_model_id": "sentence-transformers/all-MiniLM-L6-v2",
"embedder_dim": 384,
"ok": true,
"error": null
}It exits non-zero with an actionable error if vectors are missing, if the active embedder's model
id or width disagrees with the index's, or if any chunk lacks a vector. If fusion ever does switch
itself off mid-query, that is no longer silent either — a rag_fusion_disabled JSON line goes to
stderr naming the reason, and stdout still carries a usable lexical answer.
repo2graph rag --answer will also send the pack to an LLM and stream back a grounded answer. It is
the one command that puts your source code on the network — read
the warning first.
Full flag tables, budget accounting and how retrieval works: docs/cli.md.
4. Hand the map to an agent over MCP
repo2graph-mcp is a stdio MCP server, so an agent can ask the
map questions itself instead of you pasting a pack into a chat window.
Point it at a project and it serves it. Nothing to install and no setup step: if no map exists yet, the first question builds one and answers from it.
claude mcp add repo2graph -- uvx --from "repo2graph[mcp]" repo2graph-mcp /path/to/projectFor Claude Desktop, Cursor and generic clients, the JSON block is the same four lines:
{
"mcpServers": {
"repo2graph": {
"command": "uvx",
"args": ["--from", "repo2graph[mcp]", "repo2graph-mcp", "/path/to/project"]
}
}
}Three tools, deliberately:
Tool | Arguments | What comes back |
| none | Languages, hub files and top entry points. Stable across calls, so it caches. |
|
| Seed chunks plus their graph neighbours, each headed |
|
| One graph hop from a symbol: callers, callees, base classes, defining file. The thing grep cannot do. |
The server keeps three promises the CLI leaves to you: secrets are always excluded, output is
hard-capped at 12 000 tokens and re-measured before it is returned, and k/hops are clamped so no
single call can wedge the event loop every client shares. It never calls an LLM itself.
Auto-build writes only what the tools read, and only into a directory you pointed it at. Build ahead
with repo2graph build if you want the first question to be fast or want the picture too, and pass
--no-auto-build to require an index that already exists.
Client configs, which directory gets indexed, and the full contract: docs/mcp.md.
5. Or run it in CI
repo2graph is on the GitHub Marketplace, so a fresh map can live next to your code:
- uses: actions/checkout@v4
with: { fetch-depth: 0 } # full history, so CO_CHANGE edges are meaningful
- uses: Srinivasan-78/repo2graph@v1
with:
path: .
git-history: "500"
artifact-name: repo-graphAll inputs and outputs: docs/github-action.md.
What you get in .r2g
The output is split in two, because people and programs want different things.
.r2g/
├── human/ overview.md graph.html graph.graphml
└── agent/ overview.md manifest.json chunks.jsonl
nodes.jsonl edges.jsonl graph.cypher stats.jsonagent/manifest.json is the instruction sheet: what every other file is, what the dots and arrows
mean, how names are built, and where the code starts. A program needs nothing else to make sense of
the folder.
chunks.jsonl is the file you hand to an AI system. Each piece already carries its neighbours in
the header, which is what makes the answers good. If you use a vector database, keep each piece's
node_id — that is the handle that lets you jump back onto the map after a search.
Every file, every node and edge kind, the chunk format: docs/reference.md.
Using it from Python
from pathlib import Path
from repo2graph import build, iter_chunks
from repo2graph.export import dump_all
from repo2graph.query import Index
g = build(Path("."), git_history=200)
dump_all(g, chunks=iter_chunks(g), outdir=Path(".r2g"),
formats={"jsonl", "overview", "html"}, viz_nodes=300)
pack = Index(".r2g").pack_context("how does session auth work?", k=8, hops=1,
budget_chars=24000)
print(pack["markdown"])Index is the same object the CLI, the Action and the MCP server all call.
Streaming exports, expanding your own vector hits, loading into Neo4j: docs/python-api.md.
Languages
Python, JavaScript, TypeScript and TSX, Go, Rust, Java, Ruby, C, C++, C#, PHP, Kotlin, Swift, Scala
and Bash get the full treatment: functions, classes and calls. Files in any other language still
appear on the map as files in their folders, so nothing goes missing. Teaching it a new language
means adding one entry to LANG_CFG in repo2graph/langs.py.
Where it guesses
The map is very good, but it is not perfect. Worth knowing before you trust it:
It matches calls by name, not by type. If two functions share a name, repo2graph draws up to 5 possible arrows and marks each one
1/nsure. If you need certainty, keep only the arrows whereconfidenceis1.0.Some files are skipped: pictures and other non-text files, anything bigger than 1.5 MB, and the usual vendor and build folders. In a git checkout,
.gitignoreis respected.No arrow does not prove no call. Code that decides while running which function to call is invisible to a reader like this one.
The rest, including how imports are resolved per language.
Contributing
.venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytestSee .github/CONTRIBUTING.md. Source files carry an @authormark
watermark header — read AGENTS.md before editing one.
Licence
MIT. See LICENSE.
Available Tools
5 toolsrepo_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_statsARead-onlyIdempotent
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?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds meaningful context beyond those: the data is in-memory, runtime diagnostics, and has zero side effects, which clarifies that the values are ephemeral and the call cannot influence server state.
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 front-loaded with the action and metric list, and each remaining sentence adds distinct value: side-effect declaration, when to use, when not to use, and expected output. It is concise enough for a zero-parameter tool while providing genuinely useful routing information.
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?
Given zero parameters, no output schema, and rich annotations, the description covers everything an agent needs: what the tool does, which metrics it returns, the side-effect profile, and explicit alternatives. The output format is also stated ('JSON object with cache metrics'), so no critical information is missing.
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 has zero parameters, and the schema description coverage is effectively 100% (empty schema), so there are no parameter semantics for the description to add. The baseline for zero-parameter tools is 4, and the description appropriately emphasizes that the tool is a straightforward read of counters without needing inputs.
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 opens with a specific verb and resource: 'Retrieve runtime diagnostic counters for the tool result cache' and enumerates the exact metrics returned. It also explicitly contrasts with sibling tools by stating that repo_map and repo_search are for repository contents and structure, making differentiation clear.
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 (evaluating cache hit rate or debugging server performance) and explicit 'When NOT to use' guidance with named alternatives (repo_map or repo_search for repository content/code structure). This is the strongest possible usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
repo_mapARead-onlyIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, and the description reinforces this with 'Read-only, deterministic, zero side effects.' It adds useful context beyond annotations by specifying the output format ('markdown summary') and the intended session-start usage, which provide extra behavioral clarity.
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 front-loaded with the core purpose, then safety, then usage guidance, and ends with output format. Every sentence adds value; the structure is clear and easy to scan. There is minimal redundancy beyond reinforcing the read-only nature.
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 parameterless tool with no output schema, the description is complete: it states the artifact produced, the timing of use, the exclusions, and the alternatives. An agent has everything needed to select and invoke 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 has zero parameters, so the schema carries no burden and there is nothing to document. The description compensates by clarifying what the tool returns ('markdown summary'), which is the relevant semantic context for a parameterless tool.
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 opens with a specific verb and resource: 'Retrieve a high-level structural map of the repository' and lists the content (languages, hub files, top entry points). It also distinguishes itself from siblings by explicitly naming repo_search and repo_neighbours as alternatives for other 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?
Provides explicit guidance on when to use it ('call this first at session start', 'Use when deciding where to investigate') and when not to use it, naming the correct sibling tools for search and call-graph inspection. This fully routes an agent to the right tool with no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
repo_neighboursARead-onlyIdempotent
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, or definitions. 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>].
| Name | Required | Description | Default |
|---|---|---|---|
| hops | No | Traversal depth from node_id (default 1, max 4). | |
| limit | No | Maximum neighbor rows to return (default 20, max 50). | |
| node_id | Yes | Target graph node identifier to expand from (e.g. 'sym:pkg/mod.py::func', 'file:pkg/mod.py', 'dir:pkg'). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description states 'Read-only, deterministic traversal, no side effects' and describes the output format as a markdown list with edge types. Annotations already convey read-only/idempotent/destructive hints, but the addition of 'deterministic traversal' and the exact output layout adds value beyond annotations.
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 front-loads the core purpose, then gives usage guidance, exclusions, and output format in compact sentences. Every sentence earns its place; no redundant filler or restating of schema fields.
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 tool with no output schema and moderate complexity, the description covers invocation context, parameter source, exclusions, and output format. It could enumerate all possible edge types, but the format example plus 'callers, callees, base classes, definitions' is sufficient for an agent to use it 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 coverage is 100% with clear descriptions and examples for node_id, hops, and limit. The description adds the hint that node_id typically comes from repo_search citations, but this is contextual rather than necessary to parse the parameters. Baseline 3 is appropriate since the schema already handles semantics.
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 uses a specific verb ('Traverse') and clearly identifies the resource ('code graph relationships') and scope ('from a known symbol or file node_id'). It also names the sibling tools it is not ('do not use for text search ... use repo_search') which solidifies differentiation.
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' and 'When NOT to use' sections give concrete conditions and name alternatives (repo_search, repo_map). It also advises pairing with a node_id from repo_search citations, which is actionable guidance agents can follow directly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
repo_searchARead-onlyIdempotent
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.
| 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'). | |
| budget_tokens | No | Maximum token ceiling for returned markdown pack (default 6000, max 12000). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds genuinely useful behavioral context beyond annotations: secret files (.env) are excluded, the output format is markdown citation blocks, and results are bounded by budget_tokens. No contradiction with annotations.
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 dense but every sentence earns its place: purpose, safety, when-to-use, when-not-to-use, and output format. It is front-loaded with the core purpose and the exclusions are clearly separated, making it easy for an agent to parse quickly.
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 tool with rich annotations and 100% parameter schema coverage, the description covers everything an agent needs to decide when to call it, what it does, what it returns, and how to avoid misuse. The sibling alternatives are named, the output format is specified, and the safety profile is already in annotations. No critical gap remains.
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 the schema fully documents all four parameters. The description does not add significant parameter-level meaning beyond what the schema already provides, though it does clarify that output is citation blocks bounded by budget_tokens, which is consistent with the schema's description. Baseline 3 is appropriate.
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 opens with a specific verb and resource: 'Search repository code for answers to questions.' It also names the search technique (BM25 lexical ranking expanded with graph neighbours) and explicitly contrasts with sibling tools in the usage section, making the tool's distinct role clear.
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 ('open-ended queries, locating implementations, or finding error strings') and explicit when-not-to-use guidance with named alternatives (repo_neighbours for callers/callees, repo_map for broad layout). An agent can reliably route to the correct tool without further inference.
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
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 5 tools
Each tool targets a separate concern: repo_map for layout, repo_search for lexical/semantic search, repo_neighbours for graph traversal, and the two diagnostic tools for caching and build status. The descriptions explicitly state when not to use each tool, making misselection very unlikely.
All tools consistently use the repo_ prefix with lowercase snake_case, and the second token clearly indicates the action or concern: map, search, neighbours, cache_stats, build_status. This is a predictable and uniform naming scheme.
Five tools is well-scoped for a repository exploration and diagnostics server: three core query modes plus two operational status/diagnostic tools. Each tool has a distinct purpose and none feels redundant.
The core exploration workflow is well covered: orientation via repo_map, discovery via repo_search, and relationship traversal via repo_neighbours. A minor gap is the lack of a direct full-file content retrieval tool, since search returns bounded citations and graph traversal requires a starting node_id.
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.
Codebase graphs, caller impact analysis, and recorded project context for AI coding agents.
Related MCP Servers
- AlicenseAqualityAmaintenanceAn 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,144 PyPI50MIT
- AlicenseNot gradedqualityBmaintenanceEnables LLM agents to query a codebase's structural knowledge (symbols, imports, call graphs, etc.) via MCP, reducing tokens and improving correctness compared to raw file access.216 npm7MIT
- FlicenseNot gradedqualityAmaintenanceEnables agents to build and query code knowledge graphs for repositories in a folder — finding shortest paths between concepts, explaining concepts with neighbours and community context, and visualizing per-repo graphs through MCP tools.-
- 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.-