The ovecc MCP server
ovecc mcp runs a Model Context Protocol server over stdio, exposing every
ovecc command as a tool a coding agent can call — so your agent can ask "is this
export used?", "what's the blast radius of billing?", or "what did this change
introduce?" live, against the deterministic model, instead of guessing from file
contents.
{ "mcpServers": { "ovecc": { "command": "ovecc", "args": ["mcp"] } } }
How it works (read this first)
The server is not a long-running service with its own logic. It is a thin wrapper that re-invokes the ovecc binary for each tool call:
- Transport: newline-delimited JSON-RPC 2.0 over stdin/stdout. No HTTP, no port,
no daemon. The client launches
ovecc mcpas a child process and ends it by closing stdin. - Tools = the CLI: a
tools/callrunsovecc --repo <path> --format json <subcommand>and returns its stdout. Every tool maps 1:1 onto a CLI command described bycapabilities. No analysis lives only in the server. - Stateless between calls: each call is a fresh subprocess; all state lives on
disk in the repo's
.ovecc/database, written byindex. This is why you index before querying. - Deterministic: identical inputs produce byte-identical tool output.
- Tool results automatically omit the repetitive
metablock (--no-meta) to keep payloads small; agents read the definitions once fromovecc_capabilities.
Setup
1. Have the binary and an indexed repo
ovecc --repo /path/to/your-repo index
(Or let the agent do it later via the ovecc_index tool.)
2. Register with your client
Claude Code (CLI):
claude mcp add ovecc -- ovecc mcp
# or with an explicit binary path:
claude mcp add ovecc -- "C:\tools\ovecc\ovecc.exe" mcp
claude mcp list should then show ovecc, and the tools appear as ovecc_*.
Claude Desktop / generic JSON config (claude_desktop_config.json, or a project
.mcp.json):
{
"mcpServers": {
"ovecc": {
"command": "C:\\tools\\ovecc\\ovecc.exe",
"args": ["mcp"]
}
}
}
Cursor and other clients: any client that launches a stdio MCP server works —
command = the ovecc binary path, args = ["mcp"].
Every tool accepts an optional repo argument; when omitted it defaults to the
server's working directory. Either set the client's working directory to the repo
you analyze most, or have the agent pass repo explicitly. Windows paths in JSON
need escaped backslashes (\\) — forward slashes also work.
3. What the agent sees
On initialize, the server introduces itself and instructs the agent:
{
"serverInfo": { "name": "ovecc", "version": "0.1.0" },
"instructions": "Deterministic, offline architecture intelligence. Call ovecc_capabilities first for the full contract (commands, metrics, rules, exit codes). Run ovecc_index once before querying a repository. Every tool accepts an optional `repo` path."
}
Tool catalog
All 27 tools. Every tool takes an optional repo; * marks required arguments.
| Tool | Maps to | Key arguments |
|---|---|---|
ovecc_capabilities | capabilities | — (call first: the full contract) |
ovecc_init | init | force |
ovecc_index | index | path |
ovecc_summary | summary | — |
ovecc_report | report | — |
ovecc_violations | violations | severity, baseline |
ovecc_security | security | severity |
ovecc_audit | audit | — |
ovecc_health | health | — |
ovecc_deadcode | deadcode | — |
ovecc_dupes | dupes | min_tokens |
ovecc_fix | fix | apply (write; default dry-run), rule |
ovecc_diagnose | diagnose | target, severity |
ovecc_advise | advise | target* |
ovecc_metrics | metrics | target |
ovecc_explain | explain | target* |
ovecc_impact | impact | target*, direction, max_depth |
ovecc_query | query | query* (e.g. cycles, deps billing) |
ovecc_context | export context | target* |
ovecc_export_graph | export graph | html |
ovecc_hotspots | hotspots | limit |
ovecc_conventions | conventions | — |
ovecc_review | review | base, head, fail_on (lead with this for PR review) |
ovecc_gate | gate | base, head, fail_on |
ovecc_diff | diff | base, head, fail_on |
ovecc_drift | drift | since |
ovecc_history | history | metric, limit |
Typical agent workflows
Audit a repository:
ovecc_capabilities— learn the commands, metrics, rules, exit codes.ovecc_index— build.ovecc/(once).ovecc_summary/ovecc_report— overall health.ovecc_violations,ovecc_security,ovecc_audit,ovecc_deadcode,ovecc_health— specific findings.ovecc_impact/ovecc_query— blast radius and dependency questions.
Detect what a change introduced (the regression loop):
ovecc_indexon the base — first snapshot.- Make the change;
ovecc_indexagain — second snapshot. ovecc_review— the named new defects, cycles with witness edges, added duplication. This is what the agent reports.ovecc_gatefor a bare verdict;ovecc_difffor the structural deltas behind it.
Before editing a file: ovecc_advise with the file path — every finding
touching it, each with the established fix.
Verify by hand (no agent required)
Pipe JSON-RPC frames straight into the server:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
| ovecc mcp
You should get the initialize result (serverInfo ovecc) followed by a
tools/list result enumerating 27 tools. To exercise a real tool against an indexed
repo:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"ovecc_summary","arguments":{"repo":"/path/to/your-repo"}}}' \
| ovecc mcp
The result's content[0].text is the standard
JSON envelope:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [{
"type": "text",
"text": "{\n \"schema_version\": 1,\n \"tool\": { \"name\": \"ovecc\", ... },\n \"command\": \"summary\",\n \"data\": { \"files\": 11, \"modules\": 5, \"circular_dependencies\": 1, ... }"
}],
"isError": false
}
}
Error semantics
Tool failures are reported in-band, per MCP convention:
| Underlying CLI exit | MCP result |
|---|---|
0 (clean) | normal result, isError: false |
1 (a --fail-on/gate threshold crossed — a signal, not a crash) | normal result, isError: false — a failing gate still returns its verdict payload for the agent to read |
≥ 2 (usage, repo/config, DB, parser, internal) | isError: true with the stderr message |
| Unknown tool / missing required argument | isError: true (the agent can recover without a protocol failure) |
Unparseable JSON-RPC frames are ignored; unknown methods return a JSON-RPC error. Diagnostics go to stderr, never corrupting the protocol stream.
Example — querying a repo that doesn't exist:
{
"result": {
"content": [{ "type": "text", "text": "ovecc exited with code 3: ovecc: repository or configuration error: failed to resolve repository root ..." }],
"isError": true
}
}
Troubleshooting
could not resolve base snapshot 'previous'(fromovecc_gate/ovecc_diff/ovecc_drift): fewer than two snapshots exist. Runovecc_indexagain, or pass an explicitbase/since.- Empty or stale results: the repo was never indexed, or changed since the last
index. Re-run
ovecc_index. isErrorwith little detail: run the CLI directly (ovecc --repo <path> --format json <subcommand>) to see the full error; the server forwards it.- Client shows no tools: confirm the
commandpath is absolute and correct, and thatovecc mcpruns from a terminal (it blocks waiting on stdin — that's expected). - Agent skips indexing: the server's
initializeinstructions say to callovecc_capabilitiesfirst andovecc_indexonce; if your client ignoresinstructions, prompt the agent explicitly.