Install
@modelcontextprotocol/sdk (>=1.20 <2) for the package root, the /mastra subpath, and the doctor CLI; @modelcontextprotocol/server 2.x for the /v2 subpath. If your tools use Zod 4 raw-shape schemas, use MCP SDK 1.29 or later — 1.20 silently drops fields added to Zod 4 raw shapes.
Set your API key
The SDK reads your configuration from the environment: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.
Wrap your server
If you build your server in a factory function, wrap the factory withcreateMcpAnalyticsServer. Every tool registered inside is instrumented automatically:
server.ts
Other server shapes
Existing server + tool registry
Existing server + tool registry
If you already have an
McpServer instance and a list of tool definitions, instrument them in place:Custom dispatcher
Custom dispatcher
If you handle
tools/list and tools/call yourself, use the recorder directly:Mastra
Mastra
Wrap a Mastra tool map with the dedicated adapter:The adapter reads MCP request context from
context.mcp.extra or context.requestContext.get("mcp.extra") automatically.fastmcp (punkpeye/fastmcp)
fastmcp (punkpeye/fastmcp)
Wrap each tool with the adapter from the dedicated subpath:On an
httpStream server, keep transport: "httpStream" in the options — without it, anonymous HTTP sessions collapse onto one process-scoped session id. instrumentFastMCP(server, options) wraps every tool at once and detects httpStream on its own. fastmcp validates schemas before execute, so telemetry schema decoration is off by default — opt in with declareTelemetry: true, a top-level key next to armature. The shutdown flush is unnecessary with delivery: "await" or a schedule hook. Details in the SDK README.Vercel mcp-handler
Vercel mcp-handler
mcp-handler runs your initialize callback per request with a real official-SDK
McpServer, so wrap the server inside the callback and the handler outside it:MCP SDK v2 (@modelcontextprotocol/server 2.x)
MCP SDK v2 (@modelcontextprotocol/server 2.x)
Servers on the v2 package family use the dedicated
/v2 subpath — the package root still targets the 1.x SDK:wrapMcpHandler is strongly recommended: without it, clients on the pre-2026-07-28 protocol silently lose session identity through v2’s stateless legacy leg. The v2 adapter doesn’t decorate tool schemas with the telemetry field by default — restore that with declareTelemetry: true in the adapter options, the third argument: instrumentedFactory(buildServer, analyticsConfig, { declareTelemetry: true }). It is not a key of analyticsConfig. Details in the SDK README.Running on serverless or stateless HTTP? See Stateless & serverless servers for session handling, and set
delivery: "await" so events are sent before the function freezes.Configuration
Pass options under thearmature key:
Flush on shutdown
With background delivery, drain pending events before the process exits:Troubleshooting
`Mixed Zod versions detected in object shape`
`Mixed Zod versions detected in object shape`
Fixed in current releases — update the SDK. Older versions crashed when a tool declared a Zod 4 raw-shape schema while the SDK injected its telemetry field with Zod 3.
Sessions show up but telemetry fields are empty
Sessions show up but telemetry fields are empty
Make sure
@modelcontextprotocol/sdk is 1.29+. Version 1.20 silently drops fields the SDK adds to Zod 4 raw-shape schemas, so agents never see them.No data arrives
No data arrives
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 search the server log for [mcp-analytics] telemetry emit failed:, the SDK’s default delivery-failure warning. Add an onError handler to route those failures to your own logger.
