Skip to main content
The Python SDK instruments servers built with FastMCP (2.x–4.x) and the official MCP Python SDK — both the 1.27+ FastMCP class and the 2.x MCPServer. Python 3.10+.

Install

The base package has no runtime dependencies; the extras pull in the framework you use (fastmcp>=2,<5 or mcp>=1.27,<3).

Set your API key

Copy both values from the dashboard when you mint the key. US workspaces can omit ANALYTICS_INGEST_URL (the SDK defaults to the US endpoint); EU workspaces must set it to https://eu.armature.tech/api/mcp-analytics/ingest. If the key is missing, the SDK quietly no-ops — your server keeps working, and no data is sent.

Instrument your server

Call instrument_fastmcp once, before registering tools:
server.py
Works identically with the official SDK’s FastMCP:
And with the official SDK 2.x, which renamed the server class:
Instrumentation is idempotent — calling instrument_fastmcp twice does not double-count. Sync and async tool handlers are both supported.

Custom dispatcher

If you handle tools/list and tools/call yourself, use the recorder directly:
Using stateless_http=True, or deploying to serverless? Wrap your ASGI app in StatelessHttpSessionMiddleware and set "delivery": "await". Without the middleware, a stateless FastMCP app issues no Mcp-Session-Id at all, so calls arrive with no session identity: Armature falls back to heuristic grouping, separate conversations from the same caller can run together, and Client shows as Unknown. See Stateless & serverless servers.

Configuration

Pass options as a dict under the armature key. Both snake_case and camelCase keys are accepted:

Flush on shutdown

With background delivery, drain pending events before the process exits:

Verify locally

Capture batches in memory instead of sending them:

Troubleshooting

FastMCP builds the advertised schema from your function’s type hints, so the SDK adds a keyword-only telemetry parameter to instrumented functions. If you post-process signatures or schemas yourself, make sure that parameter survives.
The SDK reads the Mcp-Session-Id header, including on FastMCP versions that exclude it from get_http_headers() by default. If you run a custom ASGI stack, make sure the header reaches the app.
Check that ANALYTICS_INGEST_API_KEY is set in the server’s environment (missing keys no-op silently by design), that ANALYTICS_INGEST_URL matches your workspace region — EU keys are rejected by the US endpoint — and pass an on_error hook to surface delivery failures.