Summary
Expand the MCP server with 10 missing daemon operations, plus enable agents to auto-configure the MCP integration without manual config editing.
Motivation
Zebra's daemon supports 17 operations, but the MCP server only exposes 7. The remaining 10 — indexing, project management, daemon-level introspection, and DSL graph tools — force agents to either shell out to the CLI or operate blind.
Additionally, agents currently require the developer to manually edit .claude.json, .cursor/mcp.json, .pi/config.toml, etc. An auto-config command would let the agent wire itself up with zero manual steps.
Part 1 — Expand MCP Server Tool Surface
These daemon handlers are already implemented and tested. They need only MCP tool wrappers in crates/apps/zebraindex/src/mcp.rs.
Tier 1 — Project Lifecycle (high impact for agent workflow)
| Handler |
Proposed MCP tool name |
Why agents need it |
index |
indexProject |
Agent can trigger a full or incremental re-index without shelling out. Streaming progress can be rendered as periodic text updates. |
projectStatus |
projectStatus |
Agent can check if a project is indexed, which model, how many chunks/files — needed for self-serve setup flows. |
removeProject |
removeProject |
Agent can clean up stale entries. Low priority but completes the lifecycle. |
Tier 2 — DSL Graph Tools (power tools for deep analysis)
| Handler |
Proposed MCP tool name |
Why agents need it |
dslProjectMap |
projectMap |
Renders a complete symbol map of the project (function/class/struct inventory). Agents can use this to understand project architecture in one call instead of reading files one-by-one. |
dslDepTree |
depTree |
ASCII call-graph tree for a specific symbol (callers or callees direction, configurable depth). The searchDep tool already returns some of this; depTree adds a pure visual tree for quick structural understanding. |
dslSymbolBody |
symbolBody |
Fetch the full source code of a symbol by its internal ID. Agents get symbol IDs from searchDep results and can pull source bodies in follow-up calls. |
dslSymbolBodies |
symbolBodies |
Batch variant — fetch multiple symbol bodies in one round-trip. Reduces chattiness when the agent needs bodies for several symbols at once. |
Tier 3 — Daemon-Level Introspection
| Handler |
Proposed MCP tool name |
Why agents need it |
daemonStatus |
daemonStatus |
Daemon uptime, loaded models, active project count. Useful for auto-diagnosis when tools fail. |
env |
daemonEnv |
Hardware environment: device (CUDA/Metal/CPU), model ID, RAM, CPU count, prefix config. Agents can use this to adapt their behavior (e.g., "this machine is CPU-only, indexing will be slow"). |
Tier 4 — Index Control
| Handler |
Proposed MCP tool name |
Why agents need it |
cancelIndex |
cancelIndex |
Cancel a running index operation. Useful when an agent starts a long index and needs to abort it. |
Implementation notes for each tier
- Tier 1–2 tools follow the existing pattern in
mcp.rs: define a params struct with #[derive(Deserialize, JsonSchema)], add a #[tool] method on ZebraMcpServer, call the corresponding daemon handler.
indexProject is special — the daemon handler is streaming (handle_streaming). The MCP tool should either:
- (Simple) Start the index and return immediately with a status message ("Index started for project X, check back with
projectStatus").
- (Full) Collect streaming progress frames and return a final summary. This blocks the MCP call for the duration of indexing, which may exceed agent timeouts.
- Recommended approach: fire-and-forget +
projectStatus for polling. Simple, predictable, matches how the TUI works.
- DSL tools require the DSL index to be loaded (heavy first call, cached after). Add this note to tool descriptions.
symbolBodies returns structured data (Vec<SymbolBodyEntry>), not a pre-formatted string. The tool should format it into readable text similar to how searchDep returns its body.
Part 2 — Auto-Configuration by Agent (zebraindex setup)
Problem
Today, adding Zebra as an MCP server requires the developer to manually edit a config file:
// Claude Code: ~/.claude.json
{ "mcpServers": { "zebra-mcp": { "command": "zebraindex", "args": ["--mcp"] } } }
// Cursor: .cursor/mcp.json
// Pi: .pi/config.toml
// Codex: ~/.codex/config.toml
// etc.
Proposed solution
Add a zebraindex setup CLI command that:
- Detects which AI agent(s) are present on the system by checking for known config paths.
- Writes the MCP server stanza into the appropriate config file(s).
- Idempotent — won't duplicate if already configured.
# Auto-detect and configure all found agents
zebraindex setup
# Target a specific agent
zebraindex setup --agent pi
zebraindex setup --agent claude
zebraindex setup --agent cursor
zebraindex setup --agent codex
zebraindex setup --agent opencode
# Dry-run (print what would be written, make no changes)
zebraindex setup --dry-run
Config writing strategies per agent:
| Agent |
Config path |
Format |
Write strategy |
| Pi |
.pi/config.toml (project-local) or ~/.pi/config.toml (global) |
TOML [mcp_servers.zebra-mcp] |
Append or create section |
| Claude Code |
~/.claude.json |
JSON "mcpServers": { "zebra-mcp": … } |
Merge into existing object |
| Cursor |
.cursor/mcp.json (project-local) |
JSON "mcpServers": { "zebra-mcp": … } |
Create or merge |
| Codex |
~/.codex/config.toml |
TOML [mcp_servers.zebra-mcp] |
Append or create section |
| opencode |
~/.config/opencode/opencode.json |
JSON "zebra-mcp": { "type": "local", … } |
Merge into existing object |
Detection logic
fn detect_agents() -> Vec<AgentConfig> {
let mut found = Vec::new();
// Check known config paths or binary presence
if which::which("claude").is_ok() || home_config(".claude.json").exists() {
found.push(AgentConfig::Claude);
}
if which::which("pi").is_ok() || cwd_config(".pi/config.toml").exists() {
found.push(AgentConfig::Pi);
}
// ... etc
}
From the agent's perspective
Once zebraindex setup exists, an agent can be instructed to run it:
User: "set up zebra for code search"
Agent runs: zebraindex setup --agent pi --dry-run # Confirm
Agent runs: zebraindex setup --agent pi # Apply
Agent restarts/refreshes its MCP connection → new tools appear
Acceptance Criteria
Part 1 — Expanded MCP Tools
Part 2 — Auto-Configuration
Out of Scope (this issue)
- Auto-starting the daemon from the MCP server on tool invocation (the daemon must already be running)
- Changing the MCP transport from stdio (the stdio transport is fine for agent integration)
- Cross-platform config path differences beyond the documented agent configs
- Auto-upgrading config file formats when agents change their schema
Related
- Current MCP tools:
fileTree, searchQuery, searchPassage, doctor, searchDep, projectList
- MCP server implementation:
crates/apps/zebraindex/src/mcp.rs
- Daemon handlers:
crates/zti-daemon/src/handlers/
- Protocol types:
crates/zti-protocol/src/{request,response}.rs
- README MCP section:
README.md lines ~142–180
Summary
Expand the MCP server with 10 missing daemon operations, plus enable agents to auto-configure the MCP integration without manual config editing.
Motivation
Zebra's daemon supports 17 operations, but the MCP server only exposes 7. The remaining 10 — indexing, project management, daemon-level introspection, and DSL graph tools — force agents to either shell out to the CLI or operate blind.
Additionally, agents currently require the developer to manually edit
.claude.json,.cursor/mcp.json,.pi/config.toml, etc. An auto-config command would let the agent wire itself up with zero manual steps.Part 1 — Expand MCP Server Tool Surface
These daemon handlers are already implemented and tested. They need only MCP tool wrappers in
crates/apps/zebraindex/src/mcp.rs.Tier 1 — Project Lifecycle (high impact for agent workflow)
indexindexProjectprojectStatusprojectStatusremoveProjectremoveProjectTier 2 — DSL Graph Tools (power tools for deep analysis)
dslProjectMapprojectMapdslDepTreedepTreecallersorcalleesdirection, configurable depth). ThesearchDeptool already returns some of this;depTreeadds a pure visual tree for quick structural understanding.dslSymbolBodysymbolBodysearchDepresults and can pull source bodies in follow-up calls.dslSymbolBodiessymbolBodiesTier 3 — Daemon-Level Introspection
daemonStatusdaemonStatusenvdaemonEnvTier 4 — Index Control
cancelIndexcancelIndexImplementation notes for each tier
mcp.rs: define a params struct with#[derive(Deserialize, JsonSchema)], add a#[tool]method onZebraMcpServer, call the corresponding daemon handler.indexProjectis special — the daemon handler is streaming (handle_streaming). The MCP tool should either:projectStatus").projectStatusfor polling. Simple, predictable, matches how the TUI works.symbolBodiesreturns structured data (Vec<SymbolBodyEntry>), not a pre-formatted string. The tool should format it into readable text similar to howsearchDepreturns its body.Part 2 — Auto-Configuration by Agent (
zebraindex setup)Problem
Today, adding Zebra as an MCP server requires the developer to manually edit a config file:
Proposed solution
Add a
zebraindex setupCLI command that:Config writing strategies per agent:
.pi/config.toml(project-local) or~/.pi/config.toml(global)[mcp_servers.zebra-mcp]~/.claude.json"mcpServers": { "zebra-mcp": … }.cursor/mcp.json(project-local)"mcpServers": { "zebra-mcp": … }~/.codex/config.toml[mcp_servers.zebra-mcp]~/.config/opencode/opencode.json"zebra-mcp": { "type": "local", … }Detection logic
From the agent's perspective
Once
zebraindex setupexists, an agent can be instructed to run it:Acceptance Criteria
Part 1 — Expanded MCP Tools
indexProjecttool added — triggers daemon index, returns acknowledgment; progress pollable viaprojectStatusprojectStatustool added — reports chunks, files, model, last-indexed timestampremoveProjecttool added — removes project from indexprojectMaptool added — renders full symbol inventory with filters (language, symbol kind, token cap)depTreetool added — ASCII call-graph tree (callers/callees, configurable depth)symbolBodytool added — fetch single symbol source code by IDsymbolBodiestool added — batch fetch multiple symbol bodiesdaemonStatustool added — uptime, models, project countdaemonEnvtool added — hardware environment infocancelIndextool added — abort running index#[schemars(description = "...")]documentation on every parameterinternal_err()(matching existing pattern)Part 2 — Auto-Configuration
zebraindex setupCLI command implemented (underTopCommand::Setupor similar)setuptwice doesn't duplicate entries--agent <name>flag to target a specific agent--dry-runflag to preview without writingzebraindex setupusage examplesOut of Scope (this issue)
Related
fileTree,searchQuery,searchPassage,doctor,searchDep,projectListcrates/apps/zebraindex/src/mcp.rscrates/zti-daemon/src/handlers/crates/zti-protocol/src/{request,response}.rsREADME.mdlines ~142–180