Note
Native agent tools (regex search, path matching, file reading) handle targeted lookups well. code-analyze-mcp handles the mechanical, non-AI work: mapping directory structure, extracting symbols, and tracing call graphs. Offloading this to a dedicated tool reduces token usage and speeds up coding with better accuracy.
code-analyze-mcp is a Model Context Protocol server that analyzes code structure across 5 programming languages. It exposes four tools: analyze_directory (file tree with metrics), analyze_file (functions, classes, imports from a single file), analyze_module (lightweight function/import index, ~75% smaller than analyze_file), and analyze_symbol (call graph for a named symbol). It integrates with any MCP-compatible orchestrator (Claude Code, Kiro, Fast-Agent, MCP-Agent, and others), minimizing token usage while giving the LLM precise structural context.
brew install clouatre-labs/tap/code-analyze-mcpUpdate: brew upgrade code-analyze-mcp
cargo binstall code-analyze-mcpcargo install code-analyze-mcpcargo build --releaseThe binary is at target/release/code-analyze-mcp.
After installation via brew or cargo, register with the Claude Code CLI:
claude mcp add --transport stdio code-analyze -- code-analyze-mcpIf you built from source, use the binary path directly:
claude mcp add --transport stdio code-analyze -- /path/to/repo/target/release/code-analyze-mcpstdio is intentional: this server runs locally and processes files directly on disk. The low-latency, zero-network-overhead transport matches the use case. Streamable HTTP adds a network hop with no benefit for a local tool.
Or add manually to .mcp.json at your project root (shared with your team via version control):
{
"mcpServers": {
"code-analyze": {
"command": "code-analyze-mcp",
"args": []
}
}
}All optional parameters may be omitted. Shared optional parameters for analyze_directory, analyze_file, and analyze_symbol (analyze_module does not support these):
| Parameter | Type | Default | Description |
|---|---|---|---|
summary |
boolean | auto | Compact output; auto-triggers above 50K chars |
cursor |
string | -- | Pagination cursor from a previous response's next_cursor |
page_size |
integer | 100 | Items per page |
force |
boolean | false | Bypass output size warning |
verbose |
boolean | false | true = full output with section headers and imports (Markdown-style); false = compact one-line-per-item format |
Walks a directory tree, counts lines of code, functions, and classes per file. Respects .gitignore rules.
Required: path (string) -- directory to analyze
Additional optional: max_depth (integer, default unlimited) -- recursion limit; use 2-3 for large monorepos
Example output:
src/ [328 LOC | F:28 C:5]
main.rs [18 LOC | F:1 C:0]
lib.rs [156 LOC | F:12 C:3]
parser.rs [89 LOC | F:8 C:2]
formatter.rs [65 LOC | F:7 C:0]
languages/ [142 LOC | F:19 C:5]
mod.rs [45 LOC | F:5 C:2]
rust.rs [97 LOC | F:14 C:3]
Total: 4 files, 328 LOC, 28 functions, 5 classes
analyze_directory path: /path/to/project
analyze_directory path: /path/to/project max_depth: 2
analyze_directory path: /path/to/project summary: trueExtracts functions, classes, imports, and type references from a single file.
Required: path (string) -- file to analyze
Additional optional: ast_recursion_limit (integer, default 256) -- tree-sitter recursion cap for stack safety
Example output:
FILE: src/lib.rs [156 LOC | F:12 C:3]
CLASSES:
CodeAnalyzer:20
SemanticExtractor:45
FUNCTIONS:
new:27
analyze:35
extract:52
format_content:78
build_index:89
IMPORTS:
rmcp (3)
serde (2)
tree_sitter (4)
thiserror (1)
REFERENCES:
methods: [analyze, extract, format_content]
types: [AnalysisResult, SemanticData, ParseError]
fields: [path, mode, language]
analyze_file path: /path/to/file.rs
analyze_file path: /path/to/file.rs page_size: 50
analyze_file path: /path/to/file.rs cursor: eyJvZmZzZXQiOjUwfQ==Extracts a minimal function/import index from a single file. ~75% smaller output than analyze_file. Use when you need function names and line numbers or the import list, without signatures, types, call graphs, or references.
Required: path (string) -- file to analyze
Example output:
FILE: analyze.rs (510L, 3F, 2I)
F:
analyze_directory:174, analyze_file:200, analyze_module_file:460
I:
crate::formatter:format_file_details; std::path:Path, PathBuf
analyze_module path: /path/to/file.rsBuilds a call graph for a named symbol across all files in a directory. Uses sentinel values <module> (top-level calls) and <reference> (type references). Functions called >3 times show (•N) notation.
Required:
path(string) -- directory to searchsymbol(string) -- symbol name, case-sensitive exact-match
Additional optional:
follow_depth(integer, default 1) -- call graph traversal depthmax_depth(integer, default unlimited) -- directory recursion limitast_recursion_limit(integer, default 256) -- tree-sitter recursion cap for stack safetymatch_mode(string, default exact) -- Symbol lookup strategy:exact: Case-sensitive exact match (default)insensitive: Case-insensitive exact matchprefix: Case-insensitive prefix match; returns an error listing candidates when multiple symbols matchcontains: Case-insensitive substring match; returns an error listing candidates when multiple symbols match All non-exact modes return an error with candidate names when the match is ambiguous; use the listed candidates to refine to a unique match.
Example output:
FOCUS: analyze
DEPTH: 2
FILES: 12 analyzed
DEFINED:
src/lib.rs:35
CALLERS (incoming):
main -> analyze [src/main.rs:12]
<module> -> analyze [src/lib.rs:40]
process_request -> analyze [src/handler.rs:88]
CALLEES (outgoing):
analyze -> determine_mode [src/analyze.rs:44]
analyze -> format_output [src/formatter.rs:12] (•2)
analyze -> validate_params [src/validation.rs:5]
determine_mode -> is_directory [src/utils.rs:23]
analyze_symbol path: /path/to/project symbol: my_function
analyze_symbol path: /path/to/project symbol: my_function follow_depth: 3
analyze_symbol path: /path/to/project symbol: my_function max_depth: 3 follow_depth: 2For large codebases, two mechanisms prevent context overflow:
Pagination
analyze_file and analyze_symbol append a NEXT_CURSOR: line when output is truncated. Pass the token back as cursor to fetch the next page.
# Response ends with:
NEXT_CURSOR: eyJvZmZzZXQiOjUwfQ==
# Fetch next page:
analyze_symbol path: /my/project symbol: my_function cursor: eyJvZmZzZXQiOjUwfQ==
Summary Mode
When output exceeds 50K chars, the server auto-compacts results using aggregate statistics. Override with summary: true (force compact) or summary: false (disable).
# Force summary for large project
analyze_directory path: /huge/codebase summary: true
# Disable summary (get full details, may be large)
analyze_directory path: /project summary: falseIn single-pass subagent sessions, prompt caches are written but never reused. Benchmarks showed MCP responses writing ~2x more to cache than native-only workflows, adding cost with no quality gain. Set DISABLE_PROMPT_CACHING=1 (or DISABLE_PROMPT_CACHING_HAIKU=1 for Haiku-specific pipelines) to avoid this overhead.
| Language | Extensions | Status |
|---|---|---|
| Rust | .rs |
Implemented |
| Python | .py |
Implemented |
| TypeScript | .ts, .tsx |
Implemented |
| Go | .go |
Implemented |
| Java | .java |
Implemented |
- ARCHITECTURE.md - Design goals, module map, data flow, language handler system, caching strategy
- MCP, Agents, and Orchestration - Best practices for agentic loops, orchestration patterns, MCP tool design, memory management, and safety controls
- CONTRIBUTING.md - Development workflow, commit conventions, PR checklist
- SECURITY.md - Security policy and vulnerability reporting
Apache-2.0. See LICENSE for details.