Find where the failure started.
Spoor is an open-source MCP server for VictoriaMetrics, VictoriaLogs and VictoriaTraces. Your AI agent asks what changed. Spoor answers in a few hundred tokens, with the cause on top and the echoes labelled.
Every caller of a broken service lights up. Spoor tells them apart.
With only raw query tools, an agent has to decide what to query, work out what normal looks like, page through results and guess which red service is the cause. It burns tool calls and often blames the loudest symptom, or an error that was always there.
Spoor does that work in plain, deterministic Go and hands the agent a short ranked answer it can check.
Across all three signals
Request rate, error rate, latency, CPU, memory and consumer lag; new and spiking error logs; slower and failing spans. All for the same window, against the same baseline.
Cause, not echo
Trace trees show where failures start and where latency is added. Callers that only suffer are labelled "originates in payment" and moved down.
Honest about gaps
Errors that were already there are listed as steady, not new. If a backend had no data, the answer says so. "No change" never stands in for "no data".
Measured, not promised.
Claude Code, run headless on six incidents (five faults and one where nothing is wrong), five times each. Once with the official VictoriaMetrics MCP servers alone, once with Spoor added. Claude Haiku, 60 isolated sessions.
| Official servers only | With Spoor | |
|---|---|---|
| Correct root cause, fault scenarios | 19 / 25 | 25 / 25 |
| Correct answer, including "nothing is wrong" | 23 / 30 | 30 / 30 |
| Median tool calls per investigation | 24 | 10 |
| Median time | 55 s | 23 s |
| Total cost | $0.60 | $0.19 |
Synthetic incidents and one small model, so treat it as a first data point. On real production logs, a 466-token answer stood in for about 296,000 tokens of raw evidence. Method, per-scenario results and caveats are in the benchmark write-up.
Set it up in three steps.
-
Install
One static binary for macOS, Linux and Windows. No runtime to install.
OS=$(uname -s | tr A-Z a-z) ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') curl -fsSL "https://github.com/asinha07/spoor/releases/download/v0.2.1/spoor_0.2.1_${OS}_${ARCH}.tar.gz" | tar -xz spoor sudo mv spoor /usr/local/bin/ spoor versionNeeds Go 1.25 or newer. Installs into
$(go env GOPATH)/bin.go install github.com/asinha07/spoor/cmd/spoor@latestThe image speaks MCP over stdio by default. Inside Docker,
localhostis the container, so usehost.docker.internalfor backends on your machine.docker run -i --rm \ -e SPOOR_METRICS_URL=http://host.docker.internal:8428 \ -e SPOOR_LOGS_URL=http://host.docker.internal:9428 \ -e SPOOR_TRACES_URL=http://host.docker.internal:10428 \ ghcr.io/asinha07/spoor:0.2.1git clone https://github.com/asinha07/spoor && cd spoor make build # ./bin/spoor ./bin/spoor versionDownload
spoor_0.2.1_windows_amd64.zip(orarm64) from the releases page, unzip it and putspoor.exeon yourPATH. -
Point it at your backends
Set the three URLs, then run
doctor. It samples each backend, reports what Spoor can and can't see, and suggests a config for logs that don't follow OpenTelemetry naming.export SPOOR_METRICS_URL=http://victoriametrics:8428 export SPOOR_LOGS_URL=http://victorialogs:9428 export SPOOR_TRACES_URL=http://victoriatraces:10428 spoor doctor --since 15m spoor what-changed --since 30m --prettyFor anything beyond URLs, put a
spoor.yamlnext to it and pass--configor setSPOOR_CONFIG. Keep passwords and tokens in environment variables such asSPOOR_LOGS_PASSWORD, not in the file. Every option is in the configuration guide.No stack to try it on?
make it-up && make demo-datain the repo starts empty backends and loads six incidents with known answers. -
Connect your agent
Most clients start Spoor as a subprocess and talk to it over stdio. Use absolute paths: clients don't start servers from your shell.
claude mcp add -s user spoor \ -e SPOOR_METRICS_URL=http://localhost:8428 \ -e SPOOR_LOGS_URL=http://localhost:9428 \ -e SPOOR_TRACES_URL=http://localhost:10428 \ -- /usr/local/bin/spoor serve claude mcp list # spoor should show as connectedcodex mcp add spoor \ --env SPOOR_CONFIG=$HOME/spoor.yaml \ -- /usr/local/bin/spoor serveOr in
~/.codex/config.toml. A full scan of a busy system can take half a minute, so raise the tool timeout:[mcp_servers.spoor] command = "/usr/local/bin/spoor" args = ["serve"] tool_timeout_sec = 120 [mcp_servers.spoor.env] SPOOR_METRICS_URL = "http://localhost:8428" SPOOR_LOGS_URL = "http://localhost:9428" SPOOR_TRACES_URL = "http://localhost:10428"In
~/.cursor/mcp.json, or.cursor/mcp.jsonfor one project:{ "mcpServers": { "spoor": { "command": "/usr/local/bin/spoor", "args": ["serve"], "env": { "SPOOR_METRICS_URL": "http://localhost:8428", "SPOOR_LOGS_URL": "http://localhost:9428", "SPOOR_TRACES_URL": "http://localhost:10428" } } } }In
claude_desktop_config.json(Settings, Developer, Edit config), then restart Claude Desktop:{ "mcpServers": { "spoor": { "command": "/usr/local/bin/spoor", "args": ["serve"], "env": { "SPOOR_METRICS_URL": "http://localhost:8428", "SPOOR_LOGS_URL": "http://localhost:9428", "SPOOR_TRACES_URL": "http://localhost:10428" } } } }In
.vscode/mcp.json:{ "servers": { "spoor": { "type": "stdio", "command": "/usr/local/bin/spoor", "args": ["serve"], "env": { "SPOOR_METRICS_URL": "http://localhost:8428", "SPOOR_LOGS_URL": "http://localhost:9428", "SPOOR_TRACES_URL": "http://localhost:10428" } } } }Run one Spoor for the whole team over streamable HTTP, with a bearer token,
/healthzand Prometheus/metrics. Ready-made manifests for Kubernetes, Docker Compose and systemd are in deploy/.export SPOOR_HTTP_TOKEN=$(openssl rand -hex 32) spoor serve --http :8080 # MCP endpoint: http://<host>:8080/mcp # each teammate: claude mcp add --transport http spoor http://<host>:8080/mcp \ --header "Authorization: Bearer $SPOOR_HTTP_TOKEN"Then ask: "Checkout errors went up in the last 30 minutes. What changed, and where did it start?"
Spoor is also listed in the MCP registry as
io.github.asinha07/spoorand on Glama.
Four tools. Start with the first.
Every tool takes service, since, until, baseline (previous, 1d or 7d) and budget_tokens, which caps the answer at 200 to 4,000 tokens. All are read-only. The CLI has the same four as commands.
what_changedRanked changes across metrics, logs and traces, with cause and echo attribution, for one service or all of them.
new_errorsError logs that are new or spiking, with counts, first-seen time and one redacted example line.
trace_diffSpan names that got slower or started failing, with each span's share of the added latency and an example trace ID.
list_servicesServices seen in the window and which signals have data for each.
Keep your raw query tools connected too. Spoor tells the agent where to look; the raw tools let it look closer. That combination is what the benchmark measures.