Spanly Docs

Troubleshooting

Common setup issues and how to diagnose them.

If you've followed the quickstart and nothing is showing up in the dashboard, walk through these checks in order.

Nothing appears in the dashboard

1. Is the API key set?

echo $SPANLY_API_KEY

If empty, the SDK / CLI silently won't send anything. Set it:

export SPANLY_API_KEY=spanly_us_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx

For the Python SDK, the constructor raises ValueError if neither api_key= nor SPANLY_API_KEY is set – so a missing key is loud, not silent.

2. Is the prefix correct?

The region is encoded in the prefix:

  • spanly_us_…https://ingest.us.spanly.com
  • spanly_eu_…https://ingest.eu.spanly.com

Any other prefix raises Invalid API key format (Python) or silently drops packets (TypeScript). Generate a fresh key in the dashboard if unsure.

3. Is the SDK call before connect() / run()?

// ✓ correct
spanly.monitor(mcpServer);
await mcpServer.connect(transport);
// ✗ wrong – initialize handshake is missed
await mcpServer.connect(transport);
spanly.monitor(mcpServer);

For Python, client.monitor(server) must come before server.run(...) for the same reason.

4. Is anything actually being called?

Run any MCP client request – tools/list, a tools/call, a prompts/get. If nothing is exercised, nothing shows up. The dashboard updates within a few seconds of the first request.

5. Is the network egress allowed?

The SDK / CLI POST to https://ingest.<region>.spanly.com. If your host is behind a strict egress firewall:

  • Allow outbound HTTPS to ingest.us.spanly.com and / or ingest.eu.spanly.com.
  • The SDK never opens inbound connections.

For diagnostic visibility, enable the SDK error hook:

spanly.monitor(mcpServer, {
  onError: (err) => console.error('spanly:', err),
});
SpanlyClient().monitor(server, MonitorOptions(
    on_error=lambda e: print('spanly:', e),
))

6. Is a CLI wrapper actually proxying?

When using spanly run --port 3000, the wrapper takes port 3000 and the child gets a random port. If you accidentally point the MCP client directly at the child port, the wrapper is bypassed and nothing is captured.

Confirm the child's port via the CLI logs (it prints the assigned port at startup), then verify your MCP client is on the wrapper port.

Requests appear but serverName is empty

Spanly reads serverName / serverVersion from the MCP initialize response. If monitor() was called too late, the handshake was forwarded without being parsed, and subsequent requests show up with no server identity.

Fix: call monitor() before connect() / run(). Restart any in-flight client sessions.

Duration looks wrong (always 0 ms, or huge)

The CLI computes duration as response timestamp - request timestamp using local monotonic clocks. If you see 0:

  • The request/response pair may not have been correctly matched by JSON-RPC id. Notifications don't have a response and report as 0.
  • For SSE streams, each data: frame is its own packet, so what you see is per-frame time-to-first-byte, not the lifetime of the stream.

"queue-overflow" warnings

The SDK has a bounded in-memory queue (default 10,000 packets). If you see queue-overflow warnings (TS) or matching log lines (Python), the backend is unreachable or too slow.

  • Check the SDK / CLI onError for the underlying network error.
  • If the upstream is healthy and you're still overflowing, you can raise the buffer in the CLI with --buffer-size. The TS / Python SDKs use a fixed buffer in the current version.

CLI: HTTP mode doesn't work behind nginx/Caddy/Envoy

SSE responses stall in the front proxy's response buffer. Disable buffering on the relevant route. See Production deploy → SSE pass-through for sample configs.

Spanly MCP returns 401

The bearer token is the same spanly_* API key the SDK and CLI use.

  • Verify the header is exactly Authorization: Bearer spanly_us_….
  • Confirm the key is not from a deleted project (the dashboard will show it as inactive).
  • If you rotated the key recently, restart your MCP client so it picks up the new value from the environment.

Still stuck?

On this page