MCP integration

Spanlens ships an official MCP server so the agent inside Cursor, Claude Desktop, or Continue can answer questions like "what's our OpenAI spend this week?", "any cost anomalies?", or "walk me through traceX" against your live workspace. The server is also listed on the MCP Registry as io.github.spanlens/mcp-server.

1. Issue a public-scope key

Public-scope keys (sl_live_pub_*) can only read dashboard data — they cannot trigger LLM proxy spend or write ingest rows. The MCP server refuses to start with a full-access sl_live_* key, because the credential lives in a plaintext config file in your IDE.

Create one from the Public Keys card at the top of spanlens.io/projects+ New public key. Copy the sl_live_pub_…value when it's shown (it's only displayed once).

2. Add the server to your IDE

The same JSON shape works for every stdio-based MCP client. Pick yours:

Cursor

Edit ~/.cursor/mcp.json (or workspace .cursor/mcp.json):

{
  "mcpServers": {
    "spanlens": {
      "command": "npx",
      "args": ["-y", "@spanlens/mcp-server"],
      "env": { "SPANLENS_API_KEY": "sl_live_pub_..." }
    }
  }
}
json

Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "spanlens": {
      "command": "npx",
      "args": ["-y", "@spanlens/mcp-server"],
      "env": { "SPANLENS_API_KEY": "sl_live_pub_..." }
    }
  }
}
json

Continue

Edit ~/.continue/config.yaml:

mcpServers:
  - name: spanlens
    command: npx
    args: ['-y', '@spanlens/mcp-server']
    env:
      SPANLENS_API_KEY: sl_live_pub_...
yaml

3. Reload your IDE and start asking

The agent discovers seven tools and uses them automatically when the question matches.

Available tools

ToolWhat it returns
get_statsAggregate cost, request count, token usage, latency, error rate. Optional groupBy for per-model or per-provider breakdown.
query_requestsIndividual LLM requests with filters: model, provider, status (success / error / 4xx /5xx), userId, since, limit.
list_tracesAgent traces matching status / since / query. Returns trace IDs to feed into get_trace.
get_traceFull span tree for one trace — every LLM / tool / retrieval span with timing, tokens, cost.
get_anomaliesCost / latency / error-rate anomalies with optional severity filter.
get_savingsModel-swap recommendations with projected monthly savings and adoption status.
get_user_analyticsPer-end-user usage breakdown — total cost, request count, models touched, recent calls.

Safety

Two layers keep a leaked IDE config from causing damage:

  1. Boot-time scope check. The server calls /api/v1/me/key-info on startup and refuses to start if the response carries scope="full". The error message points back at the Public Keys card so it's obvious how to fix.
  2. API-layer enforcement. Even if a public key leaks, it cannot call /proxy/* or /ingest/* — the Spanlens server returns 403 + PUBLIC_KEY_WRITE_FORBIDDEN. The blast radius of a leak is "competitor sees my usage stats", not "competitor runs up my OpenAI bill".

Self-hosted Spanlens

Point the server at your own deployment by setting SPANLENS_BASE_URL. Trailing slashes are normalised.

{
  "mcpServers": {
    "spanlens": {
      "command": "npx",
      "args": ["-y", "@spanlens/mcp-server"],
      "env": {
        "SPANLENS_API_KEY": "sl_live_pub_...",
        "SPANLENS_BASE_URL": "https://spanlens.your-company.com"
      }
    }
  }
}
json