mcp-trace

Agents that can debug themselves. An MCP server that exposes your agent runs β stored as plain OpenTelemetry JSONL span files β as queryable tools: runs, span trees, slow spans, human-approval logs, token/cost usage.
The idea: observability shouldn't be a dashboard you read after the fact. It should be tools your agent can call mid-run β "why was I slow yesterday?", "what did the human deny me last time?", "which tool keeps timing out?" β or query interactively from Claude Desktop / pi / any MCP client.
Pairs with agent-harness (which writes the traces), but the reader is format-simple: any JSONL of OTel-shaped spans works.
Install & run
The mcp-trace name is occupied on PyPI by an unrelated project, so this server is published as abhishekash-mcp-trace; it exposes both the abhishekash-mcp-trace and mcp-trace commands.
uvx abhishekash-mcp-trace --trace-dir ./traces
git clone https://github.com/abhishekash/mcp-trace
cd mcp-trace && uv pip install -e .
mcp-trace --trace-dir ./traces
The package is published on PyPI, and the validated server.json is live in the official MCP Registry.
Client configuration
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"agent-traces": {
"command": "uvx",
"args": ["abhishekash-mcp-trace", "--trace-dir", "/path/to/traces"]
}
}
}
pi (~/.pi/agent/settings.json):
{
"mcpServers": {
"agent-traces": {
"command": "uvx",
"args": ["abhishekash-mcp-trace", "--trace-dir", "/path/to/traces"]
}
}
}
agent-harness (mounted as gated tools):
harness run "Why was my last run slow?" --mcp "uvx abhishekash-mcp-trace --trace-dir ./traces"
| Tool | Use it when |
|---|
list_runs | Starting out β recent runs with task, model, duration, cost, decision counts |
run_summary | One run at a glance (accepts trace-id prefix) |
span_tree | "What did the agent actually do?" β nested shape of the run |
slowest_spans | "Why was it slow?" β top-k spans by duration |
approval_log | HITL audit β every approve/deny/edit, who decided, and the rationale |
token_usage | Cost questions β aggregated across runs or per-run |
search_spans | Find spans by tool name, file path, "denied", β¦ |
Tool descriptions are written as prompts (when-to-use, not just what-it-does) β descriptions are the interface for agent-called tools.
Example session (real fixture trace)
> list_runs
[{ "trace_id": "f920798dd255β¦", "task": "Summarize the workspace's notesβ¦",
"tool_calls": 4, "human_decisions": 2, "stopped_reason": "completed" }]
> approval_log
[{ "tool": "write_file", "decision": "approve", "approver": "auto", β¦ },
{ "tool": "run_shell", "decision": "approve", "approver": "auto", β¦ }]
Design
traces/*.jsonl βββΆ mcp_trace.core (pure query functions, zero deps)
β
mcp_trace.server (thin MCPServer adapter, mcp 2.x)
β
stdio (NDJSON JSON-RPC)
- core/server split: all logic is pure functions over parsed spans; the MCP layer only parses args and JSON-encodes results. Tests hit both layers.
- trace_id prefixes: agents fumble full 32-char hex ids; every tool accepts prefixes.
- The demo fixture (
examples/example_trace.jsonl) is a real agent-harness run, not hand-written.
Honest limitations
- stdio transport only (no Streamable HTTP yet)
- non-recursive trace-dir scan; very large dirs should use per-file loading
- no span streaming/watching β snapshots at call time
- v0.1: read-only tools; trace mutation (annotations) is roadmap
License
MIT