codetree
Stop feeding entire files to your AI agent.
codetree is an MCP server that gives coding agents structured code understanding via tree-sitter — so they ask precise questions instead of reading thousands of lines. 30 tools, 10 languages, ~1 second startup. No vector DB, no embedding model, no config.
Quick Start
Prerequisite: Install uv if you don't have it (curl -LsSf https://astral.sh/uv/install.sh | sh).
Then cd into any project and run:
claude mcp add codetree -- uvx --from mcp-server-codetree codetree --root .
That's it. The . means "this project." Your agent now has structured code understanding.
Not using Claude Code? See Editor Setup for Cursor, VS Code, Windsurf, and Claude Desktop.
Before / After
Before codetree — agent reads the raw file:
$ cat calculator.py
import math
from typing import Optional
class Calculator:
"""A scientific calculator with memory."""
def __init__(self):
self.memory = 0
self.history = []
def add(self, a: float, b: float) -> float:
"""Add two numbers."""
result = a + b
self.history.append(('add', a, b, result))
return result
def divide(self, a: float, b: float) -> Optional[float]:
"""Divide a by b, returns None on zero division."""
if b == 0:
return None
result = a / b
self.history.append(('divide', a, b, result))
return result
# ... 200 more lines of methods ...
Tokens consumed: ~2,000+ for the full file
After codetree — agent asks for the skeleton:
class Calculator → line 4
"A scientific calculator with memory."
def __init__(self) (in Calculator) → line 7
def add(self, a: float, b: float) (in Calculator) → line 11
"Add two numbers."
def divide(self, a: float, b: float) (in Calculator) → line 17
"Divide a by b, returns None on zero division."
def sqrt(self, x: float) (in Calculator) → line 24
"Square root using math.sqrt."
Tokens consumed: ~80. That's a 25x reduction.
The agent sees every class, method, and docstring — with line numbers — without reading a single function body. When it needs the full source of divide, it calls get_symbol("calculator.py", "divide") and gets just those 6 lines.
30 Tools
Understand Structure
| Tool | Purpose |
|---|---|
get_file_skeleton(file_path) | Classes, functions, methods with line numbers + doc comments |
get_symbol(file_path, symbol_name) | Full source of a function or class |
get_skeletons(file_paths) | Batch skeletons for multiple files |
get_symbols(symbols) | Batch source for multiple symbols |
get_imports(file_path) | Import statements with line numbers |
Navigate Relationships
| Tool | Purpose |
|---|---|
find_references(symbol_name) | All usages of a symbol across the repo |
get_call_graph(file_path, function_name) | What a function calls + what calls it |
get_blast_radius(file_path, symbol_name) | Transitive impact — what breaks if you change this |
rank_symbols(top_n?, file_path?) | PageRank importance — which symbols matter most |
Analyze Quality
| Tool | Purpose |
|---|---|
get_complexity(file_path, function_name) | Cyclomatic complexity breakdown |
find_dead_code(file_path?) | Symbols defined but never referenced |
detect_clones(file_path?, min_lines?) | Duplicate / near-duplicate functions |
Inspect & Search
| Tool | Purpose |
|---|---|
search_symbols(query?, type?, parent?) | Flexible symbol search with filters |
get_ast(file_path, symbol_name?, max_depth?) | Raw AST as S-expression |
find_tests(file_path, symbol_name) | Find test functions for a symbol |
get_variables(file_path, function_name) | Local variables and parameters |
Onboarding & Graph
| Tool | Purpose |
|---|---|
index_status() | Graph index freshness and stats |
get_repository_map(max_items?) | Compact repo overview: languages, entry points, hotspots |
resolve_symbol(query, kind?, path_hint?) | Disambiguate short name into ranked qualified matches |
search_graph(query?, kind?, file_pattern?) | Graph search with degree filters and pagination |
Change & Dataflow
| Tool | Purpose |
|---|---|
get_change_impact(symbol_query?, diff_scope?) | Impact analysis via symbol or git diff, with risk levels |
get_dataflow(file_path, function_name) | Intra-function variable dataflow tracing |
get_taint_paths(file_path, function_name) | Security taint analysis: untrusted sources to dangerous sinks |
get_cross_function_taint(file_path, function_name, depth?) | Cross-file taint tracing through call boundaries |
Visualization & History
| Tool | Purpose |
|---|---|
find_hot_paths(top_n?) | High-complexity × high-call-count optimization targets |
get_dependency_graph(file_path?, format?) | File-level dependency graph as Mermaid or list |
get_blame(file_path) | Per-line git blame with author summary |
get_churn(top_n?, since?) | Most-changed files by commit count |
get_change_coupling(file_path?, top_n?, min_commits?) | Files that change together (temporal coupling) |
suggest_docs(file_path?, symbol_name?) | Find undocumented functions with context for doc generation |
get_file_skeleton,get_skeletons, andsearch_symbolsacceptformat="compact"for even fewer tokens.
Supported Languages
| Language | Extensions |
|---|---|
| Python | .py |
| JavaScript | .js, .jsx |
| TypeScript | .ts |
| TSX | .tsx |
| Go | .go |
| Rust | .rs |
| Java | .java |
| C | .c, .h |
| C++ | .cpp, .cc, .cxx, .hpp, .hh |
| Ruby | .rb |
Editor Setup
The --root flag tells codetree which project to analyze. Use . for the current directory, or a full path.
Claude Code
cd into your project, then:
claude mcp add codetree -- uvx --from mcp-server-codetree codetree --root .
Cursor
Add to .cursor/mcp.json in your project:
{
"mcpServers": {
"codetree": {
"command": "uvx",
"args": ["--from", "mcp-server-codetree", "codetree", "--root", "${workspaceFolder}"]
}
}
}
VS Code (Copilot)
Add to .vscode/mcp.json in your project:
{
"servers": {
"codetree": {
"command": "uvx",
"args": ["--from", "mcp-server-codetree", "codetree", "--root", "${workspaceFolder}"]
}
}
}
Windsurf
Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"codetree": {
"command": "uvx",
"args": ["--from", "mcp-server-codetree", "codetree", "--root", "${workspaceFolder}"]
}
}
}
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"codetree": {
"command": "uvx",
"args": ["--from", "mcp-server-codetree", "codetree", "--root", "/path/to/your/project"]
}
}
}
Claude Desktop doesn't support
${workspaceFolder}, so use a full path here.
Why codetree?
| Alternative | Limitation | codetree |
|---|---|---|
| Reading files directly | Burns tokens, no structure, no relationships | 25x token reduction, structured output |
| grep / ripgrep | Text only, no AST awareness, no call graphs | Understands code structure, not just text |
| LSP servers | Heavyweight, stateful, language-specific setup | One command, 10 languages, stateless MCP |
| SCIP / LSIF indexers | Slow builds, complex setup, huge indexes | ~1s startup, JSON cache, zero config |
| AST-only tools | Raw trees are verbose and hard for agents | Pre-structured output designed for agents |
Architecture
Agent (Claude, Copilot, Cursor, etc.)
│ MCP (stdio)
▼
codetree server (FastMCP)
│
├── Indexer → LanguagePlugin → tree-sitter → structured results
│ Cache (.codetree/index.json, mtime-based)
│
└── Graph Layer → SQLite (.codetree/graph.db)
Persistent symbols + edges, incremental updates
Change impact, dataflow, taint analysis
| Module | Responsibility |
|---|---|
server.py | FastMCP server — defines all 30 tools |
indexer.py | File discovery, plugin dispatch, definition index |
cache.py | Skeleton cache with mtime invalidation |
registry.py | Maps file extensions to language plugins |
languages/ | One plugin per language (Python, JS, TS, Go, Rust, Java, C, C++, Ruby) |
graph/store.py | SQLite persistence for symbols and edges |
graph/builder.py | Incremental graph builder (sha256 change detection) |
graph/queries.py | Repository map, symbol resolution, change impact, hot paths, dependency graph, doc suggestions |
graph/dataflow.py | Intra- and cross-function dataflow and taint analysis |
graph/git_analysis.py | Git blame, churn, change coupling analysis |
Adding a Language
pip install tree-sitter-LANGand add topyproject.toml- Copy
src/codetree/languages/_template.pytolanguages/yourlang.py - Implement the abstract methods
- Register extensions in
registry.py - Add tests
Development
git clone https://github.com/ThinkyMiner/codeTree.git
cd codeTree
python -m venv .venv
source .venv/bin/activate
pip install -e .
pip install pytest
# Run all tests (~1070 tests, ~35s)
pytest
# Run a single test file
pytest tests/languages/test_python.py -v
Contributing
Contributions welcome! See CONTRIBUTING.md for setup instructions and guidelines.