@tracelanedev/mcp β Tracelane MCP Server

Read-only MCP server exposing Tracelane trace data to any MCP-compatible client β Claude Desktop, Claude Code, Cursor, or any agent using the Model Context Protocol.
On npm since 2026-09-07: npx @tracelanedev/mcp installs the published version; the
config blocks below work as written. From-source is still documented under self-hosting.
The same run submits apps/mcp/server.json to the MCP registry; the name it will be listed under is io.github.tracelane/tracelane-mcp.
Default mode reads through the gateway β the same tenant-scoped /v1/* routes the
dashboard uses β with just TRACELANE_API_KEY and TRACELANE_GATEWAY_URL. That is the
Cloud-tenant path and needs no ClickHouse credentials. Set CLICKHOUSE_URL to
switch to self-host mode, reading ClickHouse directly instead β see
Self-hosting.
Quick start
Cloud (Tracelane-hosted tenant)
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS),
%APPDATA%\Claude\claude_desktop_config.json (Windows), or .mcp.json at your
project root for Claude Code:
{
"mcpServers": {
"tracelane": {
"command": "npx",
"args": ["@tracelanedev/mcp"],
"env": {
"TRACELANE_API_KEY": "tlane_YOUR_KEY",
"TRACELANE_GATEWAY_URL": "https://gateway.tracelane.dev"
}
}
}
}
No CLICKHOUSE_URL β its absence is what selects gateway mode. Every read goes through
the gateway's existing tenant-scoped routes, so a key from another tenant, or one lacking
the read scope, gets a clear tool error rather than an empty result.
Run from a clone
Swap the two launch keys for a path into your clone β every env key is unchanged:
"command": "node",
"args": ["/path/to/tracelane/apps/mcp/dist/index.js"]
Build it first with pnpm install && pnpm --filter @tracelanedev/mcp build.
The Streamable HTTP transport ships in this package (TRACELANE_MCP_TRANSPORT=http,
see Transports) β run it yourself. There is no hosted endpoint:
https://mcp.tracelane.dev does not resolve, so a url-style client entry has
nothing to connect to.
Self-host (ClickHouse)
Set CLICKHOUSE_URL to read ClickHouse directly instead of the gateway β for a
self-hosted or local Tracelane stack:
{
"mcpServers": {
"tracelane": {
"command": "npx",
"args": ["@tracelanedev/mcp"],
"env": {
"TRACELANE_API_KEY": "tlane_YOUR_KEY",
"TRACELANE_GATEWAY_URL": "https://gateway.tracelane.dev",
"CLICKHOUSE_URL": "http://localhost:8123",
"CLICKHOUSE_USER": "default",
"CLICKHOUSE_PASSWORD": "β¦"
}
}
}
}
TRACELANE_GATEWAY_URL is still needed in self-host mode β it is where
TRACELANE_API_KEY is validated (/v1/auth/whoami) even though trace reads go to
ClickHouse instead.
| Tool | Description |
|---|
list_traces | List recent traces for the tenant. Params: limit (default 20), model_filter, has_error |
get_trace | Get all spans for a trace. Params: trace_id |
get_span | Get full details for a span including all LLM GenAI attributes. Params: span_id, trace_id β required in Cloud (gateway) mode (no span-by-id gateway route; the span is picked out of the trace's span list), optional in self-host mode |
search_traces | Free-text search across span names and attributes. Params: query (gateway mode requires β₯4 chars), model_filter?, has_error?, limit. Gateway mode returns content-filtered trace summaries; self-host mode returns per-span match detail (matched_spans, first_match_*) |
explain_guardrail_block | Human-readable explanation of a guardrail signal. Self-host mode: trace_id + span_id (a detection-layer AFT flag on a recorded span). Gateway mode: EITHER correlation_id (from a block's 403 body, for a request blocked pre-flight with no trace) OR trace_id + span_id (same AFT-flag case, still available since spans carry the flag either way) |
list_evals | List every pain-point + fault-tolerance eval id and count, read from the manifest bundled at build time from evals/. Params: none |
get_eval_result | Read a specific eval's assertions. Needs a repo checkout for the source; says so when there is none. Params: eval_id |
replay_trace | Return a recorded trace as-is (ordered spans with LLM/tool attributes) for offline step-through. Read-only β it does not re-execute any model or tool. Params: trace_id, include_tool_calls? |
Example usage in Claude
Once connected, you can ask Claude:
"Show me the last 5 traces that had a guardrail block, and explain what fired."
"Compare the latency of traces using claude-haiku-4-5 vs claude-sonnet-4-6 in the last hour."
"Show me the assertions that eval makes."
Auth
TRACELANE_API_KEY environment variable passed via the MCP env block. The server resolves the tenant from the API key β tenant_id is never accepted as a tool argument.
Transports
| Transport | How to select it | When to use |
|---|
| Stdio | default | Local use β Claude Desktop, Claude Code, Cursor. Zero network exposure. |
| Streamable HTTP | TRACELANE_MCP_TRANSPORT=http TRACELANE_MCP_PORT=8081 | Self-run remote deployments. Every request must carry Authorization: Bearer <jwt-or-tlane-key>; the tenant is resolved per request through the gateway. No hosted endpoint is operated for you. |
Security invariants
- Read-only. No write tools are registered β the tool surface is the eight listed above, all of which only read.
- Tenant isolation. Gateway mode: every read is a tenant-scoped gateway route (
crates/gateway/src/trace_reads.rs) β the tenant comes from the bearer's claims server-side, this server never sends or sees a tenant id. Self-host mode: every ClickHouse query includes WHERE tenant_id = {tenantId: String} (parameter-bound, never string-interpolated).
tenant_id is never a tool parameter in either mode. Stdio resolves it once at startup from TRACELANE_API_KEY via the gateway and refuses to start if the key is rejected; HTTP resolves it per request from the bearer token and binds it through AsyncLocalStorage.
- A non-2xx gateway response is a tool error, never an empty result. A revoked or wrong-tenant key, a key missing the
read scope, or another tenant's trace id all read back as isError: true carrying the gateway's own status and message β not [].
- No eval id reaches the filesystem.
get_eval_result looks the id up in the bundled manifest and uses the manifest's path, so a traversal string cannot name a file.
TRACELANE_GATEWAY_URL is SSRF-checked before any bearer is sent to it, in both modes: https-only outside development, tracelane.dev hosts only, private/CGNAT/IMDS ranges refused.
Operator note: span content is returned as stored. Scope the API key you give this
server to workspaces whose spans you are comfortable handing to the connected model.
Self-hosting
No container image is published for the MCP server β ghcr.io/tracelane/mcp does not
exist. Run it from source or from the npm package.
Stack
@modelcontextprotocol/sdk β official MCP SDK (stdio + Streamable HTTP)
@clickhouse/client β parameter-bound ClickHouse queries
- TypeScript 5.5 strict,
noUncheckedIndexedAccess: true
- Biome for lint + format
License
Apache 2.0 β see LICENSE.