Batho MCP Server
The Batho MCP (Model Context Protocol) server exposes your codebase's structural intelligence to AI agents. Instead of agents issuing dozens of grep and read calls to understand your code, they query pre-built Arrow IPC artifacts with sub-millisecond latency and minimal token consumption.
What It Does
| Capability | Description |
|---|---|
| Zero-copy reads | Memory-mapped Arrow IPC — no database, no parsing at query time |
| Dual-output | Compact markdown for the model (34–38% fewer tokens) + structured JSON for programmatic use |
| 20 tools total (16 default) | 13 read-only + 3 destructive (default) + 4 admin (opt-in). See Tool Matrix below. |
| Tool gating | Secure-by-default: 4 admin tools disabled. Enable via batho.yaml, --enable-tool flag, or allowlist. See Tool Gating. |
| File watcher engine | Optional per-repo filesystem monitoring with debounced auto-patching. Enable via add_repo(watch=true). See File Watcher. |
| Relationship filtering | symbol_roles, confidence_threshold, and relation_direction filters on graph_query, trace_path, search_entities. See Tools Reference. |
| Community detection | Greedy modularity clustering (networkx) produces architectural summaries at build time |
| Multi-repo registry | Register multiple repos via add_repo tool — one MCP config entry serves all repos. Registry v3 schema with stable IDs, status tracking, and auto-migration. |
| Incremental updates | After batho patch, the server serves the latest generation — no restart needed |
| Token budgeting | 25K token default with automatic truncation and pagination hints |
Architecture
Tool Matrix
Default-Enabled Tools (16)
| Tool | Purpose | Key Parameters |
|---|---|---|
list_repos | List all registered repos with artifact status and entity counts | — |
add_repo | Register a repository in the MCP registry | name, path, watch, debounce_ms |
remove_repo | Remove a repository from the registry | name |
graph_overview | High-level codebase summary: entity counts, relationship breakdown, communities, ambiguous edge count | repo, response_format, max_tokens |
graph_query | Filtered graph query with file/type/name/role/confidence/direction filters | repo, file_path, entity_types, relation_types, symbol_roles, confidence_threshold, relation_direction, name_pattern, limit, offset |
get_entity | Detailed info for a single entity including relationships | entity_id, repo, include_source |
trace_path | Shortest path between two entities via BFS with role/confidence/direction filters | source_entity_id, target_entity_id, repo, max_depth, relation_types, symbol_roles, confidence_threshold, relation_direction |
get_file_graph | All entities and relationships within a file | file_path, repo, include_cross_file_refs |
file_connectivity | File-level dependency connectivity in both directions with external-reference summary | file_path, repo, direction, include_external, min_confidence |
search_entities | Substring/regex search across entity names with optional role filter | query, repo, entity_types, symbol_roles, limit |
get_delta | Incremental changes from the latest patch run | repo, run_id, change_kind, file_path |
batho_status | Artifact and watcher status for one or all repos (read-only) | repo |
batho_list_runs | List patch/build run IDs for a repo (read-only) | repo, limit |
batho_diff | Query node-level changes across runs, entities, or files (read-only) | repo, run_id, entity_id, file_path, since |
batho_patch | Run an incremental patch on an existing artifact (destructive) | repo, max_file_size_kb, graph_backend |
batho_fix | Run integrity verification and repair (destructive) | repo, deep, dry_run, target, phase, parallel |
Admin Tools (4, disabled by default)
| Tool | Purpose | Key Parameters |
|---|---|---|
batho_build | Run a full index build (destructive — deletes artifact) | repo, full, max_workers, max_file_size_kb, graph_backend |
batho_export | Export a JSON view or Pack artifact (destructive — writes files) | repo, view, output, index_id, filter_pattern, category, token_budget, json_mode, include_relationships |
batho_load | Unpack a transport artifact ZIP (destructive — overwrites artifact) | artifact_path, repo, force |
batho_gc | Run garbage collection and maintenance (destructive — may delete runs) | repo, subcommand, run_uuid, older_than |
How It Works
- Build — Run
batho build --root /path/to/repoto create Arrow IPC artifacts in.batho/artifact/ - Start — Run
batho mcpto start the stdio-based MCP server (auto-loads~/.batho/mcp-repos.json) - Connect — Your AI agent (Claude Desktop, Cursor, Windsurf) connects via MCP protocol — one-time config
- Register — The agent calls
add_repo(name, path)to register repos in the registry - Query — The agent calls tools with
repo="name"to explore specific repos without reading raw files
The server reads artifacts using zero-copy memory-mapped I/O. No database process, no network calls, no file parsing at query time. Each tool returns dual output: markdown content for the model and JSON structuredContent for programmatic consumers.
Tool Gating
Batho uses a secure-by-default tool registration model. Of the 20 total tools, 4 administrative tools are disabled by default to keep the agent's tool surface focused on retrieval and diagnostics:
Disabled by default (Tier-3 admin tools):
batho_build— full rebuild (deletes artifact)batho_export— writes export files to diskbatho_load— overwrites artifact directorybatho_gc— may delete old run artifacts
Enabling Admin Tools
Option 1: batho.yaml (blocklist)
mcp:
tools:
disabled: [] # Enable all tools (empty blocklist)
# Or selectively: disabled: ["batho_gc"] # keep gc disabled, enable others
Option 2: batho.yaml (allowlist)
mcp:
tools:
enabled: ["graph_overview", "graph_query", "batho_build"] # ONLY these register
When enabled is set, it takes precedence over disabled — only the allowlisted tools register.
Option 3: CLI flag
batho mcp --enable-tool batho_build --enable-tool batho_export
Why Secure-by-Default?
Admin tools can delete artifacts, overwrite files, or trigger expensive builds. In agent-driven workflows, an AI accidentally calling batho_build --full could wipe a carefully maintained artifact. The default-disabled set ensures agents can only read and diagnose until you explicitly grant write/destructive permissions.
File Watcher Engine
Batho includes an optional file watcher engine (BathoWatcherEngine) that monitors registered repositories for filesystem changes and automatically triggers batho patch runs after a configurable debounce period.
Enabling the Watcher
Enable per-repo at registration time:
add_repo(name="myapp", path="/projects/myapp", watch=true, debounce_ms=2000)
| Parameter | Default | Description |
|---|---|---|
watch | false | Enable filesystem monitoring for this repo |
debounce_ms | 2000 | Milliseconds to wait after last change before patching |
How It Works
- Monitor:
watchdogobserves the repo root (respecting.gitignoreand Batho's ignore spec) - Debounce: Rapid changes (e.g., a multi-file refactor) are batched — the patch only runs after
debounce_msof quiescence - Patch: A
batho patchrun is triggered automatically, producing a new artifact generation - Serve: All connected MCP server processes auto-detect the new generation on their next tool call — no restart needed
Watcher Status
Check watcher state via batho_status:
batho_status(repo="myapp")
Returns watcher state (active/inactive), pending change count, last patch trigger time, and debounce timer status.
When to Use
- Active development: Keep the watcher on so the graph stays fresh as you edit
- CI/CD: Leave the watcher off — let your pipeline control build/patch timing
- Read-only analysis: Leave the watcher off — no need for auto-updates if the codebase is static
Registry v3 Schema
The repo registry (~/.batho/mcp-repos.json) uses a v3 schema with rich metadata per entry:
| Field | Type | Description |
|---|---|---|
id | string (uuid4 hex) | Stable identifier generated on add (used by dashboards and build lifecycle) |
name | string | Repo name (unique key in registry) |
path | string | Absolute path to repository root |
mode | local | github | Repo mode (default: local) |
branch | string | null | Tracked branch (optional) |
status | not_indexed | indexing | ready | stale | error | Artifact status, derived from on-disk state |
last_built_at | string (ISO 8601) | null | Timestamp of last successful build |
created_at | string (ISO 8601) | When the entry was added |
watch | bool | Whether the file watcher is active for this repo |
debounce_ms | int | Debounce interval for file watch events |
max_file_size_kb | int | null | Max file size override for this repo |
Auto-Migration
Older registry entries (v2) are automatically migrated on load:
- Stable
idfields are generated (uuid4) statusis derived from the on-disk artifact (readyif artifact exists,not_indexedotherwise)last_built_atis inferred from the latest run'scompleted_attimestamp- The migration is persisted to disk so IDs remain stable across processes
Next Steps
- Setup Guide — Configure the MCP server for your environment
- Single-Repo Guide — Step-by-step walkthrough for one repository
- Multi-Repo Guide — Working with multiple repositories
- Tools Reference — Complete parameter and response documentation
- CLI Reference —
batho mcpcommand documentation