Skip to main content
Glama

repo-graph

repo-graph MCP server

Structural graph memory for AI coding assistants. Map your codebase. Navigate by structure. Read only what matters.

repo-graph gives LLMs a map of your codebase — entities, relationships, and flows — so they can navigate to the right files without reading everything first.

Instead of flooding an LLM's context window with your entire codebase (or hoping it guesses right), repo-graph builds a lightweight graph of what exists, how things connect, and where the entry points are. The LLM queries the graph, finds the minimal set of files it needs, and reads only those.

Demo

https://github.com/user-attachments/assets/a1e4171b-b225-40d4-9210-39453e14b76a

https://github.com/user-attachments/assets/fc3191e5-fc35-4bd7-8372-72af55995883

Same bug, same model, same prompt — the only difference is whether repo-graph is installed.

The task: fix a reversed comparison operator in a Go + Angular monorepo (566 nodes, 620 edges).

Without repo-graph

With repo-graph

Tokens used

75,308

29,838

Time to fix

4m 36s

~30s

Files explored

~15 (grep, read, grep, read...)

2 (flow lookup + handler file)

Outcome

Found and fixed the bug

Found and fixed the bug

2.5x fewer tokens. ~9x faster. Same correct fix.

How the test was run

Both runs used identical conditions to keep the comparison fair:

  • Same model: Claude Opus, 100% (no Haiku routing)

  • Same prompt: "Groups that were created recently are showing as closed, and old groups show as open. This is backwards — new groups should be open for members to join. Find and fix the bug."

  • Fresh context: each run started from /clear with no prior conversation

  • No other tools: CLAUDE.md, plugins, hooks, and all other MCP servers were removed for both runs — the only variable was whether repo-graph was installed

  • No hints: the prompt describes the symptom, not the location — Claude has to find group_controller.go:57 on its own

Without repo-graph, Claude greps for keywords, reads files, greps again, reads more files, and eventually narrows down to the bug. With repo-graph, Claude calls flow("groups"), gets back the exact handler function and file, reads it, and fixes it.

Browse pre-generated examples for FastAPI, Gin, Hono, and NestJS — real graph output you can inspect without installing anything.

Related MCP server: Serena

The problem

LLMs working on code waste most of their context on orientation:

  • Reading files that turn out to be irrelevant

  • Missing connections between components in different languages

  • Not knowing where a feature starts or what it touches

  • Loading 50 files when 5 would do

This is expensive, slow, and gets worse as codebases grow.

How repo-graph solves it

repo-graph scans your codebase once and builds a graph of:

  • Entities: modules, packages, classes, functions, routes, services, components

  • Relationships: imports, calls, handles, defines, contains, cross-stack HTTP

  • Flows: end-to-end paths from entry point to data layer

Then it exposes 13 MCP tools that let the LLM:

  1. Orient — "What languages are in this repo? What are the main features?"

  2. Navigate — "Trace the login flow from route to database" / "What's the shortest path between UserService and the payments API?"

  3. Scope — "How many lines would I need to read to understand this feature?" / "Give me just the files I need for this bug fix"

  4. Assess — "What's the blast radius of changing this function?" / "Which files are the biggest maintenance risks?"

The LLM gets structural context in a few hundred tokens instead of reading thousands of lines.

Supported languages

Language

Detection

What it extracts

Go

go.mod

Packages, functions, HTTP routes (gin/echo/chi/stdlib), imports

Rust

Cargo.toml

Crates, modules, structs, traits, functions, routes (Actix/Rocket/Axum)

TypeScript

tsconfig.json / package.json

Modules, classes, functions, import relationships

React

react in package.json

Components, hooks, context providers, React Router routes, fetch/axios calls, flows

Angular

@angular/core in package.json

Components, services, guards, DI injection, HTTP calls, feature flows

Vue

vue in package.json

SFCs, composables, Vue Router routes, fetch/axios calls

Python

pyproject.toml / setup.py / requirements.txt

Packages, modules, classes, functions, routes (Flask/FastAPI/Django)

Java/Kotlin

pom.xml / build.gradle

Packages, classes, routes (Spring/JAX-RS/Ktor/WebFlux/Micronaut)

Scala

build.sbt

Packages, objects/classes/traits, routes (Play/Akka HTTP/http4s)

Clojure

project.clj / deps.edn

Namespaces, defn/defprotocol/defrecord, routes (Compojure/Reitit)

C#/.NET

.csproj / .sln

Namespaces, classes, routes (ASP.NET/Minimal API)

Ruby

Gemfile / .gemspec

Files, classes, modules, Rails routes

PHP

composer.json

Namespaces, classes, interfaces, routes (Laravel/Symfony)

Swift

Package.swift / .xcodeproj

Files, types (class/struct/enum/protocol/actor), Vapor routes

C/C++

CMakeLists.txt / Makefile / meson.build

Sources, headers, classes, structs, enums, namespaces, includes

Dart/Flutter

pubspec.yaml

Modules, classes, widgets, go_router/shelf routes

Elixir/Phoenix

mix.exs

Modules, functions, Phoenix router scopes + routes

Solidity

.sol files / foundry.toml / hardhat.config.*

Contracts, interfaces, libraries, events, inheritance

Terraform

.tf files

Modules, resources, variables, outputs, module sources

SCSS

.scss files present

File-level bloat analysis

Cross-cutting extractors (work across all languages):

  • Data sources — DB/cache/queue/blob/search/email client detection

  • CLI entrypoints — Python click, JS commander/yargs, Go cobra, Rust clap

  • gRPC — service/method definitions from .proto files

  • Queue consumers — Celery, Dramatiq, BullMQ, Sidekiq, Oban, NATS

  • Cross-stack HTTP — frontend fetch/axios calls linked to backend routes

Multiple languages can match one repo (e.g., Go backend + Angular frontend + SCSS). Each contributes its nodes and edges into a single unified graph.

Install

pip install mcp-repo-graph

Python 3.11+. Installs two packages: mcp-repo-graph (the MCP server) and repo-graph-py (the Rust engine, as a prebuilt wheel).

Quick start

1. Initialise the target repo

repo-graph-init --repo /path/to/your/project

This generates the graph, writes .mcp.json and CLAUDE.md instructions, and gets your AI assistant ready to use repo-graph.

2. Connect to your AI assistant

If you skipped repo-graph-init, add this to your MCP configuration manually:

Claude Code (~/.claude/claude_code_config.json or project .mcp.json):

{
  "mcpServers": {
    "repo-graph": {
      "command": "repo-graph",
      "args": ["--repo", "/path/to/your/project"]
    }
  }
}

With environment variable:

{
  "mcpServers": {
    "repo-graph": {
      "command": "repo-graph",
      "env": { "REPO_GRAPH_REPO": "/path/to/your/project" }
    }
  }
}

3. Use it

The AI assistant now has access to all 13 tools. Example queries it can answer:

  • "What does this codebase do?"status tool

  • "Trace the checkout flow"flow tool

  • "What would break if I change UserService?"impact tool

  • "What files do I need for this bug?"minimal_read tool

  • "This file is too big, how should I split it?"split_plan tool

  • "Show me the auth flow visually"graph_view tool

Add a call to generate via your MCP client to a pre-commit hook so the graph stays up to date automatically — no LLM context spent on regeneration:

# .git/hooks/pre-commit (or add to your existing hook)
#!/bin/sh
repo-graph --repo . --regenerate
git add .ai/repo-graph/
chmod +x .git/hooks/pre-commit

Every commit keeps the graph current. The LLM always has a fresh map without wasting a single token on generate.

Tip: If you don't want graph data in version control, add .ai/repo-graph/ to .gitignore and skip the git add line — the graph will just live locally.

MCP tools reference

Generation

Tool

Parameters

Description

generate

(none)

Scan the codebase from scratch, rebuild the graph, and reload

reload

(none)

Reload graph data from disk (after external regeneration)

Navigation

Tool

Parameters

Description

status

(none)

Repo overview: git state, detected languages, entity counts, available flows

flow

feature

End-to-end flow for a feature — from entry point through service layer to data

trace

from_id, to_id

Shortest path between any two nodes in the graph

impact

node_id, direction (upstream/downstream), depth

Fan out from a node to see what it affects or depends on

neighbours

node_id

All direct connections to and from a node

Context budgeting

Tool

Parameters

Description

cost

feature

Total line count for all files in a feature's flow

hotspots

top_n

Files ranked by size * connections — maintenance risk indicators

minimal_read

feature, task_hint

Smallest file set needed for a specific task within a feature

Health analysis

Tool

Parameters

Description

bloat_report

file_path

Internal structure of a file: functions/methods ranked by size, type counts

split_plan

file_path

Concrete suggestions for splitting an oversized file, grouped by responsibility

graph_view

feature or node, depth

Visual ASCII map of a feature flow, node neighbourhood, or full graph overview

How it works

mcp-repo-graph is a thin Python MCP server that wraps glia, a Rust engine.

  1. Parse — per-language tree-sitter parsers extract raw nodes and unresolved references

  2. Extract — cross-cutting extractors layer on HTTP routes, data sources, CLI entrypoints, gRPC services, queue consumers

  3. Resolve — graph builder resolves intra-repo references; cross-graph resolvers link stacks (frontend HTTP calls → backend routes, etc.)

  4. Store — merged graph lands in .ai/repo-graph/ as a zero-copy .gmap (rkyv + mmap) plus JSON projections for portability

  5. Serve — the MCP server loads the graph into memory and exposes the 13 tools

The Rust engine will split into its own glia repo post-v0.4.12. mcp-repo-graph will remain the MCP-facing thin wrapper.

Config (optional escape hatch)

If auto-detection misses a weird layout, drop .ai/repo-graph/config.yaml in the target repo:

skip:
  - legacy       # directory basenames excluded from the walk
  - scratch

roots:           # explicit roots heuristics miss — added on top of auto-detection
  - path: apps/weird-layout
    kind: python
  - path: services/custom
    kind: go

kind values: go, rust, python, typescript, react, vue, angular, java, scala, clojure, csharp, ruby, php, swift, c_cpp, dart, elixir, solidity, terraform. config.json works too if you prefer.

Graph data format

Generated files live in .ai/repo-graph/ inside the target repo:

  • nodes.json[{id, type, name, file_path, confidence, ...}, ...]

  • edges.json[{from, to, type}, ...]

  • flows/*.yaml — named feature flows with ordered step sequences and kind (http/page/cli/grpc/queue)

  • state.md — human-readable snapshot for quick orientation

Common edge types: imports, defines, contains, uses, calls, handles, handled_by, exports, includes, tests, cross-stack HTTP links.

License

MIT

Support

If repo-graph saved you time, consider buying me a coffee.

Available Tools

6 tools
findA
Read-only

Turn any text into the ranked nodes that matter — the on-ramp to the graph. A symbol or keyword returns matching nodes; a pasted stacktrace / failing-test id / diff is resolved to the code it implicates and ranked by relevance. Set expand=true to fan out to the surrounding neighbourhood (spreading activation). Every row carries path:line, so read the top hits directly — no grep.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNoForce the signal type: 'symbol', 'stacktrace', 'test', 'diff', or 'auto' (sniff the shape).auto
queryYesWhat to locate: a symbol/keyword (e.g. `User`, `checkout`), OR a failure signal — paste a raw stacktrace, a failing-test id (path::test), or a unified diff / changed-file list.
top_kNoMax results. Default 20.
budgetNoMax chars in the result. 0 = no cap.
expandNoReturn the relevant neighbourhood (Personalized-PageRank ranked) around the matches, not just the matches themselves. Use to discover what surrounds a seed.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only provide readOnlyHint=true, while the description adds rich behavioral detail: ranking by relevance, resolving different input types (stacktrace, diff), neighborhood expansion via spreading activation, and output format (path:line). This goes well beyond the minimal annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (4-5 sentences) yet packs substantial information. It front-loads the core purpose and covers key variations. Every sentence contributes value, avoiding redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (5 parameters, output schema exists), the description covers the primary use cases and output characteristics (path:line). It does not need to restate the output schema, but provides enough context for effective use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

All 5 parameters are described in the schema (100% coverage), but the description adds meaningful context: examples for 'query' (paste raw stacktrace, test id), explanation of 'expand' (Personalized-PageRank), and 'kind' auto-detect behavior. This enhances understanding beyond schema defaults.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool transforms text into ranked graph nodes, serving as an on-ramp to the graph. It specifies that it handles symbols, keywords, stacktraces, test IDs, and diffs, but does not explicitly differentiate from sibling tools like 'trace' or 'orient', though it mentions 'read' for subsequent steps.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context: use for initial search or failure resolution, with 'expand=true' for neighborhood exploration. It suggests reading top hits via 'read', but lacks explicit when-not-to-use guidelines or comparisons with sibling tools like 'impact' or 'trace'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

impactA
Read-only

Blast radius in one call: fan out from one or more nodes to everything they affect (forward) or depend on / are used by (backward), returned as a complete, deduped, Personalized-PageRank-ranked, located closure. Each row carries path:line, the edge via reason it's in scope, and a when the engine finds it unreachable from any entry point (likely dead). Structural import/containment fan-out is excluded — no noise. Depth-1 in both directions is a node's immediate neighbours. Pass several comma-separated nodes to assess a whole diff at once.

ParametersJSON Schema
NameRequiredDescriptionDefault
depthNoHow many hops to fan out. Default 4.
nodesYesOne or more node names/qnames, comma-separated. A diff touching N symbols is one call.
top_kNoCap the ranked result. 0 = no cap.
budgetNoMax chars in the result. 0 = no cap.
directionNo'forward' (what it affects), 'backward' (what it depends on / who uses it), or 'both'. (Aliases: downstream=forward, upstream=backward.)both
live_onlyNoDrop nodes not reachable from any entry point (likely-dead code). Default False = show all, marking dead ones ⊘.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint annotation, the description reveals key behaviors: ranking algorithm (Personalized PageRank), result fields (path:line, via, dead marker), exclusion of structural edges, depth meaning, and handling of multiple nodes. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single dense paragraph that front-loads the core functionality. Every sentence contributes meaningful detail, with no wasted words. It efficiently communicates complex behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity and rich parameters/output, the description fully covers result structure, filtering, ranking, and exclusive behavior. It matches the needed detail without relying on output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage, the baseline is 3. The description adds value by explaining node usage for whole diffs, aliases for direction, and the meaning of depth-1. This enriches the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: computing blast radius/impact from nodes in forward or backward directions. It distinguishes itself from siblings like trace and find by emphasizing its comprehensive, deduped, ranked closure and exclusion of structural edges.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use this tool (assessing impact of changes, whole diff) and even hints at what it excludes (structural fan-out). However, it doesn't explicitly compare to alternatives or state when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

orientA
Read-only

Get the lay of the land — ALWAYS the first call on a codebase. With no arguments: a counts + entry-points overview plus a blind spots note flagging which (language, edge-kind) extractions are partial so you know where to fall back to grep. With seed=<node>: the dense structural map scoped to that node's neighbourhood. With full=true: the whole-repo dense map (the full context dump). Orient first, then find to jump to nodes, impact for blast radius, trace for flows.

ParametersJSON Schema
NameRequiredDescriptionDefault
fullNoWith no seed: return the whole-repo dense structural map instead of the counts overview. Ignored when seed is given.
seedNoOptional node/qname to scope the map around (its activated neighbourhood). Blank = repo overview.
budgetNoMax chars in the result. 0 = default cap (~50k for the full map, uncapped otherwise).

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so the description doesn't need to repeat that. It meaningfully adds context about output types (counts, entry-points, blind spots, structural maps) and the budget parameter, which are not covered by annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured. The critical instruction 'ALWAYS the first call on a codebase' is front-loaded, and each sentence serves a purpose: explaining modes, blind spots, and sibling tool ordering.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (three modes, multiple output types, sibling tools), the description is remarkably complete. It covers each mode's output, mentions limitations (blind spots), and provides a recommended workflow. The presence of an output schema reduces the need to detail return values.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage, the baseline is 3. The description adds value by explaining the behavioral differences of each parameter combination (no args vs. seed vs. full) and clarifying the budget default behavior, going beyond what the schema alone provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly specifies the tool's purpose: getting an overview of a codebase. It details three distinct modes (no args, seed, full) and explicitly contrasts with sibling tools (find, impact, trace), making it easy for an agent to select the right tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidance: 'ALWAYS the first call on a codebase' and explains when to use each variant. It also tells when to fall back to grep for blind spots and names alternative tools for subsequent steps.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

readA
Read-only

Return the source code for one or more nodes, sliced from their files by the graph's line spans. Use after find/impact to read the exact code without grepping — comma-separate several node names to read the whole ranked set in a single call. Each node is a code block headed by its qname and path:start-end, plus a context: footer with structural facts the source alone doesn't show: HTTP method, cross-stack callers, covering tests, and intent/decision/constraint cells when present.

ParametersJSON Schema
NameRequiredDescriptionDefault
nodeYesNode name or qname to read. Comma-separate several (e.g. the top-ranked nodes from `find`/`impact`) to slice them all in one call.
budgetNoMax chars in the result (shared across all nodes when several are given). 0 = no cap.
context_linesNoLines of padding above and below the node's span. Default 0.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true, and description adds that it slices from files and returns structured blocks with qname, path, and a context footer. 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.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single paragraph with good front-loading of purpose. It is information-dense but not overly verbose. Could potentially be broken into shorter sentences for readability, but no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the read-only nature and existing annotations, the description fully explains what the tool does, when to use it, how to use parameters, and what the output contains (including structural facts). No gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but description adds valuable context: comma-separating nodes, budget shared across nodes, context_lines as padding. Also ties parameters to use case (after find/impact).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly describes returning source code for nodes, sliced by line spans. Distinguishes itself from sibling tools like find/impact by stating it should be used after those to read code, not to find it.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says to use after find/impact, and gives usage example like comma-separating node names. Could be more explicit about when not to use (e.g., for non-code files), but the context is clear enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

refreshA

(Re)build the structural graph with tree-sitter AST parsing across 20 languages, running the cross-stack resolvers (HTTP, gRPC, GraphQL, WebSocket, queues, events, CLI). Incremental by default — only changed files re-parse — so it's cheap to call after edits; set full=true to force a clean reparse. Accepts a local path or a git URL (cloned on demand). Call after a major refactor; routine edits are picked up automatically by the file watcher.

ParametersJSON Schema
NameRequiredDescriptionDefault
fullNoForce a full reparse instead of reusing the per-file parse cache. Default False (incremental — only changed files re-parse, so this is cheap after edits).
repo_pathNoPath or git URL to (re)scan. Blank = the repo the server is serving. A different path/URL retargets the server at it.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (readOnlyHint=false, openWorldHint=true), the description adds behavioral details: incremental re-parsing by default, cheap after edits, full=true for clean reparse, and support for local path or git URL with on-demand cloning. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (under 100 words), front-loaded with the tool's primary purpose, and each sentence adds value. Well-structured for quick understanding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (graph rebuilding, 20 languages, multiple resolvers) and that an output schema exists, the description adequately covers core behavior, parameters, and usage context. Could be more detailed about output, but output schema fills that gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description rephrases schema info for both parameters (full and repo_path) but does not add significant new meaning beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool rebuilds a structural graph using tree-sitter AST parsing across 20 languages and runs cross-stack resolvers. It distinguishes from siblings like find and trace by focusing on graph regeneration after major refactors.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly advises calling after a major refactor and notes that routine edits are handled automatically by the file watcher. It does not explicitly mention when not to use or list alternative sibling tools, but provides clear usage context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

traceA
Read-only

Follow the code across boundaries. One argument: trace a feature end-to-end — the ordered path from entry through the stack, each hop labelled with its mechanism (call / HTTP / queue / event / data), crossing service boundaries (frontend→backend). Two arguments: the shortest path between two specific nodes, hop by hop. This is where the graph beats reading many files — it knows the cross-stack links grep can't see.

ParametersJSON Schema
NameRequiredDescriptionDefault
depthNoMax hops for the cross-stack feature trace. Default 6.
budgetNoMax chars in the result. 0 = no cap.
to_nodeNoOptional target node. Given → shortest path from_node→to_node. Blank → trace `from_node` as a feature across the stack.
from_nodeYesA feature/keyword to trace end-to-end (one arg), OR the start node when tracing a path to `to_node`.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true, so the agent knows it's a read operation. The description adds behavioral detail: the tool traverses service boundaries, labels mechanisms (call/HTTP/queue/event/data), and behaves differently with one vs two arguments. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise: four sentences, front-loaded with the purpose, each sentence adding value (action, mode distinction, justification). No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 4 parameters, an output schema, and moderate complexity, the description covers the core behavior and use cases. It does not detail node types or mechanism labels, but provides enough for an agent to select the tool appropriately.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, baseline 3. The description adds meaning by explaining the dual behavior of from_node (feature or start node) and to_node (target node for shortest path), which complements the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool traces code across boundaries, explains one-argument (feature end-to-end) and two-argument (shortest path) modes, and distinguishes from siblings like find and impact by emphasizing cross-stack links that grep cannot see.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains that the tool is used for tracing features end-to-end or finding paths between nodes, and contrasts with reading files/grep. It does not explicitly state when not to use it versus specific siblings, but the context is clear enough.

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.

  1. 15 tool updatesv0.4.20
    • Removedactivate
    • Removeddense_text
    • Changedfind4 fields changed
      • addedInput schema / properties / expand
        Added value: +{
        +  "default": false,
        +  "description": "Return the relevant neighbourhood (Personalized-PageRank ranked) around the matches, not just the matches themselves. Use to discover what surrounds a seed.",
        +  "title": "Expand",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / kind
        Added value: +{
        +  "default": "auto",
        +  "description": "Force the signal type: 'symbol', 'stacktrace', 'test', 'diff', or 'auto' (sniff the shape).",
        +  "title": "Kind",
        +  "type": "string"
        +}
      • changedInput schema / properties / query / description
        Previous value: -"Node name or qname pattern to search for. Supports partial matching."New value: +"What to locate: a symbol/keyword (e.g. `User`, `checkout`), OR a failure signal — paste a raw stacktrace, a failing-test id (path::test), or a unified diff / changed-file list."
      • addedInput schema / properties / top_k
        Added value: +{
        +  "default": 20,
        +  "description": "Max results. Default 20.",
        +  "maximum": 100,
        +  "minimum": 1,
        +  "title": "Top K",
        +  "type": "integer"
        +}
    • Removedflow
    • Removedgenerate
    • Removedgraph_view
    • Changedimpact8 fields changed
      • changedInput schema / properties / depth / default
        Previous value: -3New value: +4
      • changedInput schema / properties / depth / description
        Previous value: -"How many hops to traverse. Default 3."New value: +"How many hops to fan out. Default 4."
      • changedInput schema / properties / direction / default
        Previous value: -"downstream"New value: +"both"
      • changedInput schema / properties / direction / description
        Previous value: -"'downstream' (what it affects) or 'upstream' (what it depends on)."New value: +"'forward' (what it affects), 'backward' (what it depends on / who uses it), or 'both'. (Aliases: downstream=forward, upstream=backward.)"
      • addedInput schema / properties / live_only
        Added value: +{
        +  "default": false,
        +  "description": "Drop nodes not reachable from any entry point (likely-dead code). Default False = show all, marking dead ones ⊘.",
        +  "title": "Live Only",
        +  "type": "boolean"
        +}
      • removedInput schema / properties / mode
        Removed value: -{
        -  "default": "table",
        -  "description": "'table' (tiered list) or 'prose' (primed prose for LLM context).",
        -  "title": "Mode",
        -  "type": "string"
        -}
      • changedInput schema / properties / nodes / description
        Previous value: -"One or more node names/qnames, comma-separated. A diff touching N files is one call."New value: +"One or more node names/qnames, comma-separated. A diff touching N symbols is one call."
      • addedInput schema / properties / top_k
        Added value: +{
        +  "default": 0,
        +  "description": "Cap the ranked result. 0 = no cap.",
        +  "maximum": 200,
        +  "minimum": 0,
        +  "title": "Top K",
        +  "type": "integer"
        +}
    • Removedlocate
    • Removedneighbours
    • Addedorient
    • Changedread2 fields changed
      • changedInput schema / properties / budget / description
        Previous value: -"Max chars in the result. 0 = no cap."New value: +"Max chars in the result (shared across all nodes when several are given). 0 = no cap."
      • changedInput schema / properties / node / description
        Previous value: -"Node name or qname to read the source for."New value: +"Node name or qname to read. Comma-separate several (e.g. the top-ranked nodes from `find`/`impact`) to slice them all in one call."
    • Addedrefresh
    • Removedreload
    • Removedstatus
    • Changedtrace6 fields changed
      • addedInput schema / properties / budget
        Added value: +{
        +  "default": 0,
        +  "description": "Max chars in the result. 0 = no cap.",
        +  "minimum": 0,
        +  "title": "Budget",
        +  "type": "integer"
        +}
      • addedInput schema / properties / depth
        Added value: +{
        +  "default": 6,
        +  "description": "Max hops for the cross-stack feature trace. Default 6.",
        +  "maximum": 12,
        +  "minimum": 1,
        +  "title": "Depth",
        +  "type": "integer"
        +}
      • changedInput schema / properties / from_node / description
        Previous value: -"Starting node name or qname pattern."New value: +"A feature/keyword to trace end-to-end (one arg), OR the start node when tracing a path to `to_node`."
      • addedInput schema / properties / to_node / default
        Added value: +""
      • changedInput schema / properties / to_node / description
        Previous value: -"Target node name or qname pattern."New value: +"Optional target node. Given → shortest path from_node→to_node. Blank → trace `from_node` as a feature across the stack."
      • changedInput schema / required
        Previous value: -[
        -  "from_node",
        -  "to_node"
        -]New value: +[
        +  "from_node"
        +]
  2. 10 tool updatesv0.4.19
    • Changedactivate3 fields changed
      • addedInput schema / properties / budget
        Added value: +{
        +  "default": 0,
        +  "description": "Max chars in the result. 0 = no cap.",
        +  "minimum": 0,
        +  "title": "Budget",
        +  "type": "integer"
        +}
      • addedInput schema / properties / mode
        Added value: +{
        +  "default": "table",
        +  "description": "'table' (ranked list) or 'prose' (primed prose for LLM context).",
        +  "title": "Mode",
        +  "type": "string"
        +}
      • addedInput schema / properties / profile
        Added value: +{
        +  "default": "default",
        +  "description": "Edge-weight preset: 'default', 'repair' (up-weights call/data), 'review', or 'onboard' (up-weights entry/module).",
        +  "title": "Profile",
        +  "type": "string"
        +}
    • Changeddense_text2 fields changed
      • addedInput schema / properties / budget
        Added value: +{
        +  "default": 0,
        +  "description": "Max chars in the result. 0 = default cap (~50k, or REPO_GRAPH_DENSE_MAX_CHARS).",
        +  "minimum": 0,
        +  "title": "Budget",
        +  "type": "integer"
        +}
      • addedInput schema / properties / seed
        Added value: +{
        +  "default": "",
        +  "description": "Optional node/qname to scope the map around (its activated neighbourhood). Blank = whole graph.",
        +  "title": "Seed",
        +  "type": "string"
        +}
    • Changedfind1 field changed
      • addedInput schema / properties / budget
        Added value: +{
        +  "default": 0,
        +  "description": "Max chars in the result. 0 = no cap.",
        +  "minimum": 0,
        +  "title": "Budget",
        +  "type": "integer"
        +}
    • Changedflow1 field changed
      • addedInput schema / properties / budget
        Added value: +{
        +  "default": 0,
        +  "description": "Max chars in the result. 0 = no cap.",
        +  "minimum": 0,
        +  "title": "Budget",
        +  "type": "integer"
        +}
    • Changedgenerate1 field changed
      • addedInput schema / properties / incremental
        Added value: +{
        +  "default": true,
        +  "description": "Reuse the per-file parse cache so unchanged files skip re-parsing (default True). Set False to force a full reparse.",
        +  "title": "Incremental",
        +  "type": "boolean"
        +}
    • Changedimpact6 fields changed
      • addedInput schema / properties / budget
        Added value: +{
        +  "default": 0,
        +  "description": "Max chars in the result. 0 = no cap.",
        +  "minimum": 0,
        +  "title": "Budget",
        +  "type": "integer"
        +}
      • changedInput schema / properties / direction / description
        Previous value: -"'downstream' or 'upstream'."New value: +"'downstream' (what it affects) or 'upstream' (what it depends on)."
      • addedInput schema / properties / mode
        Added value: +{
        +  "default": "table",
        +  "description": "'table' (tiered list) or 'prose' (primed prose for LLM context).",
        +  "title": "Mode",
        +  "type": "string"
        +}
      • removedInput schema / properties / node
        Removed value: -{
        -  "description": "Node name or qname pattern to analyze.",
        -  "title": "Node",
        -  "type": "string"
        -}
      • addedInput schema / properties / nodes
        Added value: +{
        +  "description": "One or more node names/qnames, comma-separated. A diff touching N files is one call.",
        +  "title": "Nodes",
        +  "type": "string"
        +}
      • changedInput schema / required
        Previous value: -[
        -  "node"
        -]New value: +[
        +  "nodes"
        +]
    • Addedlocate
    • Changedneighbours1 field changed
      • addedInput schema / properties / budget
        Added value: +{
        +  "default": 0,
        +  "description": "Max chars in the result. 0 = no cap.",
        +  "minimum": 0,
        +  "title": "Budget",
        +  "type": "integer"
        +}
    • Addedread
    • Changedreload1 field changed
      • addedInput schema / properties / incremental
        Added value: +{
        +  "default": true,
        +  "description": "Reuse the per-file parse cache so unchanged files skip re-parsing (default True). Set False to force a full reparse.",
        +  "title": "Incremental",
        +  "type": "boolean"
        +}
  3. 14 tool updatesv0.1.3
    • Addedactivate
    • Removedbloat_report
    • Removedcost
    • Addeddense_text
    • Addedfind
    • Changedflow1 field changed
      • addedInput schema / properties / feature / description
        Added value: +"Feature name or keyword to match against entry points. Case-insensitive, supports partial matching."
    • Changedgenerate1 field changed
      • addedInput schema / properties / repo_path / description
        Added value: +"Absolute path to the repository to scan. Defaults to the repo the server was started with."
    • Changedgraph_view5 fields changed
      • addedInput schema / properties / depth / description
        Added value: +"Tree depth. Default 2."
      • addedInput schema / properties / depth / maximum
        Added value: +5
      • addedInput schema / properties / depth / minimum
        Added value: +1
      • removedInput schema / properties / feature
        Removed value: -{
        -  "default": "",
        -  "title": "Feature",
        -  "type": "string"
        -}
      • addedInput schema / properties / node / description
        Added value: +"Node name or qname to render as a tree. Leave blank for full overview."
    • Removedhotspots
    • Changedimpact5 fields changed
      • addedInput schema / properties / depth / description
        Added value: +"How many hops to traverse. Default 3."
      • addedInput schema / properties / depth / maximum
        Added value: +10
      • addedInput schema / properties / depth / minimum
        Added value: +1
      • addedInput schema / properties / direction / description
        Added value: +"'downstream' or 'upstream'."
      • addedInput schema / properties / node / description
        Added value: +"Node name or qname pattern to analyze."
    • Removedminimal_read
    • Changedneighbours1 field changed
      • addedInput schema / properties / node / description
        Added value: +"Node name or qname pattern to inspect."
    • Removedsplit_plan
    • Changedtrace2 fields changed
      • addedInput schema / properties / from_node / description
        Added value: +"Starting node name or qname pattern."
      • addedInput schema / properties / to_node / description
        Added value: +"Target node name or qname pattern."
  4. 13 tool updatesv0.1.2
    • First observedbloat_report
    • First observedcost
    • First observedflow
    • First observedgenerate
    • First observedgraph_view
    • First observedhotspots
    • First observedimpact
    • First observedminimal_read
    • First observedneighbours
    • First observedreload
    • First observedsplit_plan
    • First observedstatus
    • First observedtrace

TDQS

A4.4/5.0

Scored across 6 tools

Disambiguation5/5

Each tool has a distinct purpose: find resolves text to nodes, impact shows dependency blast radius, orient provides overviews, read retrieves source code, refresh rebuilds the graph, and trace follows cross-boundary flows. There is no overlap in functionality.

Naming Consistency5/5

All tool names are single-word, lowercase imperatives (find, impact, orient, read, refresh, trace) following a consistent verb pattern without any mixing of conventions.

Tool Count5/5

With 6 tools, the server covers all necessary operations for code graph analysis—build, explore, search, read, and trace—without being excessive or insufficient.

Completeness5/5

The tool set covers the full lifecycle: building the graph (refresh), getting oriented (orient), finding nodes (find), reading code (read), analyzing impact (impact), and tracing flows (trace). There are no obvious gaps.

Maintenance

ActivityStale
ResponsivenessSlow

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    A fully featured coding agent that uses symbolic operations (enabled by language servers) and works well even in large code bases. Essentially a free to use alternative to Cursor and Windsurf Agents, Cline, Roo Code and others.
    29
    42,914 PyPI
    29,226
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that transforms codebases into knowledge graphs using Neo4J, enabling AI assistants to understand code structure, relationships, and metrics for more context-aware assistance.
    28
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to understand and navigate codebases through structural analysis. Provides code mapping, symbol search, and impact analysis using ast-grep for accurate parsing of Python, JavaScript, TypeScript, and Go projects.
    4
    52
    MIT