ast-mcp
AST-MCP is a read-only MCP server that gives agents structural, symbol-level access to a codebase instead of whole-file reads.
Outline any file with bodies elided (
file_outline), or get just names, lines, and counts withmode="names".Fetch a single definition by symbol name, key path, or heading slug (
get_symbol), withsource,signature, ordocmodes and ambiguity handling.Search definitions, key paths, and headings across the repo by name, filtered by kind, language, group, or path glob (
search_symbols).Retrieve docstrings without bodies, from a file or a list of symbols (
get_docstrings).List a file's imports and exports (
list_imports).Run raw tree-sitter S-expression queries as an escape hatch (
ast_query).Handle code, config, data, and docs across 26 languages using four extraction profiles: symbols, defs, schema, and outline.
Keep responses fresh by stat-checking every cited path and reparsing changed files — no stale cache.
Save tokens by serving outlines and definitions instead of whole files, with optional savings tracking; the server never writes to your source.
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., "@ast-mcpshow me the definition of parse_config"
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.
AST_MCP
Structural code retrieval over MCP. Parses source with tree-sitter and serves
symbols instead of files, so an agent asking "what does parse_config do"
gets 40 lines rather than 2000.
Read-only. The server never writes to your source — the only file it writes is
its own index at .ast_mcp/index.db.
Install
uv tool install ast-mcpOr run it without installing anything:
uvx ast-mcp --versionRequires Python 3.11 or newer.
Related MCP server: CodeGraphMCPServer
Wire it into Claude Code
From the repository you want indexed:
ast-mcp initThat writes an ast-mcp stanza into <repo>/.mcp.json, adds .ast_mcp/ to
.gitignore, writes a short retrieval-routing block into CLAUDE.md, and
builds the index. Claude Code reads .mcp.json at startup, so the next
session in that directory has the tools already connected — no per-session
step.
The CLAUDE.md block is what makes the agent actually reach for the tools;
registration alone tends to leave them idle. It is about thirty lines and says
one thing: name a symbol, key path or heading → these tools; describe
behaviour you cannot name → your semantic retriever; about to edit a file, or
need it byte-for-byte → Read. --no-claude-md skips it.
init merges. Every other server in .mcp.json is left exactly as it was,
and a file it cannot parse is reported rather than overwritten. Re-running it
is a no-op. Pass --dry-run to see the change first.
The stanza it writes carries no absolute paths, so it is safe to commit:
{
"mcpServers": {
"ast-mcp": { "command": "ast-mcp", "args": ["serve"] }
}
}If ast-mcp is not permanently on PATH it records uvx ast-mcp serve
instead. Override either with --command "uv run ast-mcp serve".
CLI
command | what it does |
| register in |
| build or refresh the index; |
| file/symbol counts, index size, freshness, registration |
| tokens served vs. what reading those files whole would have cost |
| the language registry — 26 rows, their extensions and profiles |
| the MCP server over stdio; what Claude Code launches |
Every command takes --root PATH. Root resolution is --root, else
AST_MCP_ROOT, else the working directory. Bare ast-mcp means ast-mcp serve.
Only init writes anything outside .ast_mcp/, and only .mcp.json,
.gitignore and CLAUDE.md. The server itself never writes to your source.
Not every language gets the same treatment
A .py file has functions with signatures and docstrings. A
docker-compose.yml has none of that — it has a shape. A README.md has a
heading tree. Forcing all three through one symbol model produces garbage for
two of them, so there are four extraction profiles:
profile | payload key | what you get | languages |
|
| signature, docstring, nesting, imports | python, javascript, typescript, tsx, go, lua |
|
| same shape, weaker guarantees — docstrings often | ruby, perl, r, bash, zsh, css, scss, sql, graphql, proto, terraform, dockerfile |
|
| key paths + inferred value types, not funcdefs | json, json5, yaml, toml, xml, csv |
|
| heading / section tree | markdown, html |
26 languages across six groups: core, web, scripting, data, devops,
docs. Every response declares its profile and group before the
payload — read that field, don't assume symbols exists.
Kinds never lie about fidelity. A schema node's kind is a value type
(object, array, string); an outline node's kind is a document structure
(heading, code_block). Nothing outside the symbols/defs profiles ever
claims to be a function or a class.
Tools
tool | use it for |
| the |
| one definition. |
| find things by name across the repo |
| docs without bodies |
| dependency edges out of a file, plus exports where the language has them |
| raw tree-sitter S-expression — the escape hatch |
Every tool takes max_tokens (default 4000). An over-budget response is
trimmed, flagged truncated: true, and tells you which argument narrows it.
Nothing is dropped silently.
get_symbol never guesses. A name matching several symbols returns
ambiguous: true with candidates; pass path or a qualified name to resolve.
Alongside a semantic retriever (optional)
AST_MCP stands alone. Nothing it tells the agent assumes another retrieval tool is registered, and a repo running only this server is a supported setup.
If you also run CCE, --with-cce adds one paragraph to the server's
instructions so the agent knows how to split the work:
ast-mcp init --with-cce # records the flag in .mcp.jsoncontext_search(CCE) — fuzzy semantic retrieval over embedded chunks. For "how does auth work?", "where is rate limiting handled?" — you know the concept but not the name.AST_MCP — exact structural retrieval by name, kind and range. For "show me
TokenStore.refresh", "what's in this config file?", "list everyCREATE TABLEin the repo" — you know the name but not the location.
Rough rule: describing behaviour → context_search. Naming a thing →
AST_MCP. A context_search hit hands you a name; get_symbol turns it into
the exact definition.
Without the flag nothing changes and no CCE mention reaches the agent. Plain
ast-mcp init prints a hint if it notices context-engine in .mcp.json;
it never switches modes for you.
One block, not two
CCE writes its own CLAUDE.md instructions, and they say to use
context_search instead of reading files — with no mention of this server, so
a named symbol gets routed to the semantic retriever too. Two blocks means two
contradictory rules, and the loud one wins.
So init replaces that block rather than adding a second one. It reuses CCE's
own <!-- cce-block-version: N --> markers and keeps the value of N it finds
on disk. CCE decides whether to rewrite by testing for its current tag, so a
later cce init sees a match and leaves the file alone. Run cce init first,
then ast-mcp init.
If CCE later bumps that version and reclaims the slot, ast-mcp status says
so — re-run ast-mcp init to take it back. Nothing outside the marked block
is touched, at any point.
What it costs
The saving grows with file size — the response envelope is fixed cost, so small files benefit least. Measured on this codebase:
file | lines | full read | outline | saving |
| 94 | 789 tok | 352 tok | 2.2x |
| 428 | 3994 tok | 967 tok | 4.1x |
| 457 | 3882 tok | 690 tok | 5.6x |
Below roughly 100 lines it is about break-even against Read. Above that it
pays, and get_symbol on a single definition pays regardless.
A 5000-row CSV or JSON array costs the same as a 3-row one: homogeneous
repeats collapse to one node carrying children_count. The collapse says how
far to trust it — uniformity is uniform, mixed, or unverified (over
5000 elements), checked across the element key sets. No value from inside a
collection comes back with it, so asking a 1.3 MB ban_list.json for its
record shape returns the shape and none of the records.
Measure it on your own repo
Every tool response is logged to .ast_mcp/savings.db — what it served, and
what a whole-file read of every file it cited would have cost.
$ ast-mcp savings
root /home/you/project · 5 queries · last query 2m ago
▰▰▰▰▰▰▰▰▰▱ 90% of a whole-file read saved
whole-file reads 38.5k tokens
served by ast-mcp 3.9k tokens
──────────────────────────────────────
saved 34.6k tokens $0.52
~6.9k tokens / query ~$0.10 / query
by tool:
search_symbols 62% ▰▰▰▰▰▰▱▱▱▱ 21.5k $0.32 · 1 call
file_outline 21% ▰▰▱▱▱▱▱▱▱▱ 7.3k $0.11 · 2 calls--json for the same numbers machine-readably, --reset to start the count
over. Pricing is Opus input ($15/1M); set AST_MCP_PRICE_PER_MTOK for another
model, or AST_MCP_NO_STATS=1 to record nothing at all.
Freshness
The SQLite index is a cache, never an oracle. Every path in a response was
stat-checked against its recorded (mtime_ns, size) during that same call,
and reparsed if it moved. There is no watcher daemon and no stale window.
Development
git clone https://github.com/matthew-brough/AST_MCP && cd AST_MCP
uv sync --all-groups
uv run --group dev pytest -qThe suite runs on 3.11 through 3.14. uv build produces the wheel; the
.scm query files ship inside it, and CI fails the build if any are missing.
SPEC.md is the contract: §V invariants, §I interfaces, §T tasks, §B the log
of what went wrong and what changed because of it.
Available Tools
6 toolsast_queryA
Run a raw tree-sitter S-expression query against one file.
The escape hatch for anything the five typed tools flatten away.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| query | Yes | ||
| captures | No | ||
| max_tokens | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full behavioral disclosure burden. It only says what the tool does, not whether it is read-only, what the output looks like, whether the file can be modified, or any error/edge-case behavior. The word 'query' hints at a read operation, but this is not explicit.
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?
Two sentences with no fluff. The primary action is front-loaded, and the second sentence adds valuable positioning as an escape hatch. Every word earns its place.
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 no output schema, no annotations, and 0% schema description coverage, the description is insufficient for a 4-parameter tool. It does not mention return format, capture behavior, token limits, or how this low-level query relates to the typed tools beyond being a fallback. Agents would likely need extra probing 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 description coverage is 0%, so the description must compensate. It indirectly explains 'path' ('against one file') and 'query' ('raw tree-sitter S-expression query'), but gives no guidance on 'captures' or 'max_tokens' semantics, defaults, or usage. With 4 parameters and no schema descriptions, this leaves significant ambiguity.
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 action: 'Run a raw tree-sitter S-expression query against one file.' This clearly identifies the verb, resource, and scope. It also differentiates itself from siblings by calling itself 'the escape hatch for anything the five typed tools flatten away,' signaling it is the lower-level fallback.
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 clear context by positioning the tool as an escape hatch, implying it should be used when the five typed tools (search_symbols, get_docstrings, file_outline, get_symbol, list_imports) cannot express the desired query. It does not name specific sibling alternatives or give explicit when-not-to-use conditions, but the context is actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_outlineA
Outline one file: definitions, key paths or headings, bodies elided.
Use this instead of reading a file to find out what is in it.
mode: "full" (default) or "names" — names, lines and counts only, for
enumerating what a file defines.
On a data file this answers record count and field types without returning
any value from inside a collection: each collection carries
children_count and uniformity ("uniform" — every element has element
0's keys; "mixed" — they differ; "unverified" — too many to check).
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | full | |
| path | Yes | ||
| max_depth | No | ||
| max_tokens | No | ||
| include_docstrings | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it discloses the surprising behaviors: bodies are elided, 'names' mode returns only names/lines/counts, and data-file output avoids returning collection contents while supplying `children_count` and `uniformity` with all three possible values defined. Minor gaps remain around error behavior and what happens on unparseable files.
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?
Roughly 100 words, front-loaded with the core purpose, then usage guidance, then mode semantics. The uniformity/children_count explanation is dense but earns its place since it describes non-obvious output; there is no redundancy.
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 no annotations, the description covers mode and data-file behavior well, but the general return structure for code files stays vague ('definitions, key paths or headings') and three parameter semantics are undocumented. An agent would still have to guess at max_tokens truncation and max_depth behavior.
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 0%, so the description must compensate, and it does for `mode` ('full' default, 'names' for enumerating definitions). But `max_depth`, `max_tokens`, and `include_docstrings` are entirely unexplained, which matters because `max_tokens` affects truncation and `include_docstrings` interacts with the elision behavior. Only partial compensation.
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 — 'Outline one file' — and spells out the output shape: 'definitions, key paths or headings, bodies elided.' This distinguishes it from siblings like get_symbol or search_symbols even without naming them, and the contrast with reading a file sharpens what the tool is for.
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?
Gives an explicit decision rule: 'Use this instead of reading a file to find out what is in it.' That is clear, actionable context. It stops short of a 5 because it never names alternatives or states when not to use it (e.g., when full bodies or docstrings are actually needed).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_docstringsB
Documentation without bodies. Pass exactly one of path or symbols.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | ||
| symbols | No | ||
| max_tokens | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral disclosure burden. It does reveal the key output trait ('without bodies') and a strict input requirement, but it does not explain what happens if both path and symbols are provided, how max_tokens affects results, or what the return structure looks like.
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 short, front-loaded, and free of filler, which is good. However, the brevity crosses into under-specification: two sentence fragments cannot adequately cover three parameters, the mutual-exclusion rule, and tool-selection context.
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 three parameters, no annotations, and no output schema, the description is incomplete. It does not explain accepted path or symbol formats, mention max_tokens at all, or describe the output beyond 'documentation,' so an agent must infer too much to invoke the tool confidently.
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 0%, so the description must compensate for missing parameter meaning. It adds the useful 'exactly one of path or symbols' constraint, but it never defines what path should point to, what symbols should contain, or what max_tokens controls. This leaves significant semantic ambiguity for three parameters.
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 phrase 'Documentation without bodies' combined with the tool name get_docstrings identifies a specific resource (docstrings) and a distinctive scope (no function bodies), which helps distinguish it from sibling tools like get_symbol or file_outline. It stops short of an explicit imperative statement such as 'Returns docstrings for a path or symbols,' so clarity is good but not maximal.
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 instruction 'Pass exactly one of path or symbols' is a clear invocation rule and implies the tool is for retrieving documentation rather than symbol bodies. However, the description never names alternative tools or states explicit when-to-use versus when-not-to-use conditions, leaving sibling differentiation mostly implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_symbolB
Fetch definitions by name, key path, or heading slug.
mode: "source" (default) returns the body, "signature" and "doc" omit it. A name matching several different symbols returns candidates rather than guessing. A name matching several definitions of the same thing — many Lua listeners on one event — returns all of them in "symbols". line: pick one definition by the start_line a candidate reported.
| Name | Required | Description | Default |
|---|---|---|---|
| line | No | ||
| mode | No | source | |
| name | Yes | ||
| path | No | ||
| max_tokens | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the behavioral burden and does substantial work: it explains mode behavior ('source' returns the body, 'signature' and 'doc' omit it), ambiguity resolution (returns candidates rather than guessing), and line-based disambiguation by start_line. It does not cover errors, permissions, or max_tokens effects, but the core selection behavior is transparent.
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 compact and front-loaded with the main purpose. The mode and line notes are dense but scannable. It avoids filler, though the ambiguity discussion could be tightened slightly without losing value.
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 moderate-complexity tool with five parameters and no output schema, the description covers the primary ambiguity-handling behavior and mode semantics. It does not explain max_tokens, the exact meaning of path, or how the returned candidates/symbols are structured. It is adequate for basic use but incomplete for full confident invocation.
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 0%, so the description must add parameter meaning. It explains mode values and the line parameter, and mentions lookup by name, key path, or heading slug. However, it does not map 'key path' and 'heading slug' to specific parameters, and it leaves max_tokens entirely undocumented. Partial compensation, but with real gaps.
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 states a clear action and resource: 'Fetch definitions by name, key path, or heading slug.' It conveys the tool's core function and gives some sense of the lookup keys. It does not explicitly contrast with sibling tools like search_symbols, but the specificity of fetching definitions rather than searching or outlining is enough to distinguish it.
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?
No explicit guidance is given about when to prefer get_symbol over siblings such as search_symbols, get_docstrings, or ast_query. The mode and line details are usage-related, but they explain how to call the tool, not when it should be selected. The description leaves alternatives and exclusions to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_importsC
Dependency edges out of one file, plus exports where the language has them.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| max_tokens | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the transparency burden. It does reveal that the result is scoped to a single file and that exports are included only when the language supports them. It does not state whether the operation is read-only, what the result shape is, or how max_tokens affects output.
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 one short sentence with no filler, and the core scope is front-loaded. The language-conditioned export clause is efficient, though slightly cryptic.
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 annotations and no output schema, this definition is too thin. An agent is not told what the result looks like, how language detection works, or how max_tokens influences the output, leaving the tool minimally viable at best.
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 0%, so the description must compensate for missing parameter details. It clarifies that 'path' refers to a single file, but it does not describe 'max_tokens,' its truncation behavior, or the expected path format.
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 identifies the resource ('dependency edges out of one file') and adds an export edge case, which differentiates it from sibling tools like search_symbols or ast_query. It lacks an explicit verb such as 'lists' or 'returns,' but the tool name and phrasing make the action reasonably 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?
No guidance is given for when to use this tool rather than file_outline, ast_query, or search_symbols. There are no conditions, exclusions, or alternative tool mentions, so an agent must infer the correct usage from the name and the bare description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_symbolsC
Find definitions, key paths and headings by name across the repository.
group is one of core, web, scripting, data, devops, docs.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | ||
| lang | No | ||
| group | No | ||
| limit | No | ||
| query | Yes | ||
| path_glob | No | ||
| max_tokens | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It does not mention whether the operation is read-only, how results are returned, matching semantics, pagination, or any other runtime behavior.
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 brief and front-loaded with the primary purpose. The second sentence about group adds a useful constraint without padding, so each sentence earns its place. It is concise, though sparse.
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 7 parameters, no annotations, and no output schema, this description is not complete enough for an agent to confidently invoke the tool. It lacks information about required query semantics, available filter values for kind and lang, result shape, and how the various filters interact.
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 0%, yet the description only explains one parameter: group. It provides no semantics for query, kind, lang, limit, path_glob, or max_tokens, leaving most of the parameter surface undocumented.
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 states a specific action and resource: 'Find definitions, key paths and headings by name across the repository.' This identifies what the tool does and its scope. However, it does not explicitly differentiate from siblings like get_symbol or file_outline, which may overlap in function.
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 gives no guidance about when to use search_symbols versus alternatives such as get_symbol, file_outline, or ast_query. The only usage-related hint is the group value enumeration, which is parameter guidance rather than tool-selection 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.
1 tool update
v0.6.0- Changed
file_outline1 field changed- added
Input schema / properties / modeAdded value: +{ + "default": "full", + "title": "Mode", + "type": "string" +}
6 tool updates
v0.1.0- First observed
ast_query - First observed
file_outline - First observed
get_docstrings - First observed
get_symbol - First observed
list_imports - First observed
search_symbols
TDQS
Scored across 6 tools
Most tools target clearly distinct operations: repository search, single-file outline, raw AST query, imports/exports, and symbol lookup. The main ambiguity is between get_docstrings and get_symbol with mode 'doc', which could serve similar documentation-retrieval purposes.
All names are readable snake_case, but the pattern is mixed: get_docstrings and get_symbol use 'get_', while file_outline, ast_query, list_imports, and search_symbols each start with a different noun or verb. There is no single consistent verb_noun convention, though the names are still predictable enough to navigate.
Six tools is a well-scoped size for an AST/source-analysis server. Each tool covers a meaningful slice of the domain without redundancy or bloat, and ast_query exists as an intentional escape hatch rather than a loosely-scoped extra.
The set covers documentation extraction, file outlining, symbol lookup and search, imports/exports, and raw AST querying, which forms a coherent lifecycle for source exploration. The ast_query escape hatch explicitly fills any gap left by the typed tools, so agents can handle cases outside the common patterns.
Maintenance
Related MCP Connectors
Repository knowledge graph MCP server for codebase understanding and debugging.
The official Svelte MCP server providing docs and autofixing tools for Svelte development
Hosted code graph over MCP: exact callers, dependencies, and cross-repo blast radius for AI agents.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceStandalone MCP server for code structure analysis using tree-sitter. Directory trees, symbol definitions, and call graphs without reading raw source files. Supports Rust, Python, Go, Java, TypeScript, Fortran, JavaScript, C/C++, and C#. Benchmarked up to 68% fewer tokens vs native tools.6Apache 2.0
- AlicenseNot gradedqualityDmaintenanceA lightweight, zero-configuration MCP server for source code analysis with GraphRAG capabilities, enabling structural understanding and efficient code completion from MCP-compatible AI tools.32 PyPI13MIT
- 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.37 npm7MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server that indexes your codebase using tree-sitter AST parsing and gives AI tools instant access to structural intelligence like dependency graphs, call trees, and dead code detection from a local SQLite database.MIT