MCP server providing code analysis tools using Tree-sitter for syntax-aware parsing across multiple programming languages
Server provides 7 well-named, verb-prefixed tools with detailed descriptions (100-500+ chars each). All tools have input schemas with typed parameters and descriptions. However, output schemas are NOT documented, descriptions mention output keys but no formal schema is provided. Error handling guidance is minimal. Parameter descriptions are thorough but some lack explicit constraints (enums, ranges). No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite several tools being read-only. Descriptions are verbose and include implementation details (pipe-delimited escaping, LSP integration) that could confuse LLM selection. Overall solid foundation but lacks output documentation and polish expected of production tools.
Analyze impact of changes in a file by finding all call sites and usages that would be affected. Returns affected symbols with risk assessment (high/medium/low) based on change type and usage patterns.
Generate hierarchical map of a DIRECTORY (not single file). Returns structure overview of multiple files with functions/classes/types. Detail levels: 'minimal' (names only), 'signatures' (DEFAULT, names + signatures), 'full' (includes code). USE WHEN: ✅ First time exploring unfamiliar codebase ✅ Finding where functionality lives across files ✅ Getting project structure overview ✅ Don't know which file to examine. DON'T USE: ❌ Know specific file → use view_code ❌ Need implementation details → use view_code after identifying files. TOKEN COST: MEDIUM (scales with project size). OPTIMIZATION: Start with detail='minimal' for large projects, use pattern to filter. WORKFLOW: code_map → view_code. COMBINED MODE: Set with_types=true to also extract type definitions (structs, enums, interfaces, etc.) in the same pass - more efficient than calling type_map separately.
Find ALL usages of a symbol (function, variable, class, type) across files. Syntax-aware search, not text search. Returns file locations, code context, usage type (definition, call, type_reference, import, reference). USE WHEN: ✅ Refactoring: see all places that call a function ✅ Impact analysis: checking what breaks if you change signature ✅ Tracing data flow ✅ Before renaming/modifying shared code. DON'T USE: ❌ Need structural changes only → use parse_diff ❌ Want risk assessment → use affected_by_diff ❌ Symbol used >50 places → use affected_by_diff or set max_context_lines=50. TOKEN COST: MEDIUM-HIGH (scales with usage count × context_lines). OPTIMIZATION: Set max_context_lines=50 for frequent symbols, context_lines=1 for locations only. WORKFLOW: find_usages (before changes) → make changes → affected_by_diff (verify)
Output schemas not documented. Tool descriptions mention output keys (e.g., 'p', 'h', 'f', 's', 'c' for view_code) but no formal JSON Schema is provided. LLMs cannot plan downstream tool calls or extract fields reliably without knowing the response structure.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). All 7 tools are read-only but lack explicit readOnlyHint annotation. This prevents agents from understanding which tools are safe to retry and which have side effects.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 58 | <=2025-11-25 | v2 |
Format LSP-provided reference locations into the same compact schema as find_usages. Input accepts `symbol` plus `references` rows using either 1-based `{file,line,col}` / `{file_path,line,column}` or LSP `{uri,range:{start:{line,character}}}`. Output keys: `sym`, `h`, `u`; rows are `file|line|col|type|context|scope|conf|owner` with `conf=high` because locations are assumed to come from precise LSP resolution. USE WHEN: ✅ You already called LSP textDocument/references and need compact context for an LLM ✅ You want scope/context around precise references without rerunning syntax-aware search. DON'T USE: ❌ You need MCP to discover references itself → use find_usages.
Parse structural changes in a file by comparing current state to a git reference. Returns added/removed/modified functions, signature changes, and body changes with line numbers and change types.
Execute a Tree-sitter query pattern on a file or directory. Returns matches with file, line, column, and matched text. Supports all Tree-sitter query syntax including captures, predicates, and alternations.
View file in compact schema (BREAKING). Output keys: `p` (relative path), `h` (header for f/s/c rows), `f` (functions rows), `s` (structs rows), `c` (classes rows), optional deps `deps` (map dep_path -> type rows), plus optional tables: imports `ih`+`im`, trait methods `th`+`tm`, interfaces `ah`+`i`, properties `ph`+`pr`, class implements `ch`+`ci`, class methods `mh`+`cm`, Rust impl methods `bh`+`bm`. Rows are newline-delimited; fields are pipe-delimited and escaped: `\` -> `\\`, ` ` -> `\n`, ` ` -> `\r`, `|` -> `\|`. Meta: `@.t=true` when truncated. DETAIL: 'signatures' (name/line/sig), 'full' (adds doc/code). COMMENTS: `comment_mode="leading"` prepends the contiguous leading comment block to returned code fields. FOCUS: set focus_symbol to keep code only for that symbol. LSP: pass definition_location from textDocument/definition to include the exact dependency type.
Descriptions are verbose and implementation-focused. view_code description (500+ chars) includes pipe-delimited escaping rules, LSP integration details, and compact schema field names ('p', 'h', 'f', 's', 'c'). This buries the core intent and wastes tokens. Descriptions should be 50-200 chars, focusing on WHEN to use the tool, not HOW it encodes output.
Missing parameter constraints. 'detail' parameter accepts 'minimal', 'signatures', 'full' but is not declared as an enum in the schema, it's a free-form string. Same for 'comment_mode' (none|leading). Enums prevent hallucinated values and are self-documenting.
No error handling guidance. Tools lack descriptions of failure modes, recovery steps, or actionable error messages. E.g., what happens if file_path does not exist? Should the agent retry, search for the file, or ask the user?