Skip to content
opentel-mcp
v0.10.0 — MCP v2 support shipped

OpenTelemetry for MCP servers that actually catches silent failures.

MCP tools can return a successful JSON-RPC envelope with isError: true buried inside. Standard OpenTelemetry never sees it. opentel-mcp does — and marks the span ERROR.

v0.10.0 adds support for MCP v2 (@modelcontextprotocol/server) alongside the original SDK — install whichever you use. v0.9.0 added instanceKey for sharing tracker state across stateless, per-request deployments.

pnpm add opentel-mcp @opentelemetry/api
1. Tool call
{ "method": "tools/call",
"params": { "name": "query_database" } }

1,000+

Total npm downloads since launch.

Currently on v0.10.0.

  • OpenTelemetry
  • Model Context Protocol
  • Node.js 20+
  • TypeScript
  • MIT licensed
  • 748 tests

A tool can fail and your traces will still say it succeeded.

MCP's JSON-RPC 2.0 transport reports success at the envelope level even when the tool itself failed — the failure is nested inside CallToolResult.isError. Standard instrumentation only looks at the envelope.

Silent failure inside a successful JSON-RPC envelopeJSON-RPC 2.0 response — HTTP 200 OKresult.isError = truecontent: [ "Connection timeout" ]⚠ never inspected by standard OTel instrumentation

Built specifically for MCP observability

Silent Failure Detection

Detects CallToolResult.isError = true inside otherwise-successful JSON-RPC responses and marks the span ERROR — no other Node.js MCP library does this.

Deep Failure Fingerprinting

SHA-256 hashes truncated to 16 hex characters group identical failures across traces, without leaking raw payloads into span attributes.

Twelve Metrics Instruments

Ships counters and histograms out of the box — call/error/duration counts, cost and token totals, five Agent Thrash Detection loop instruments, and schema drift detection — ready for Prometheus, SigNoz, or any OTel-compatible backend.

Cost & Token Attribution

LLM-wrapping tools get automatic token counts, model detection, and USD cost estimates. Anthropic, OpenAI, Bedrock, Google, DeepSeek supported by default. v0.5.0.

Never Throws

Every instrumentation path is designed to fail safe. Fingerprinting falls back to a fixed value rather than raising an exception.

Cardinality-Safe Labels

A frozen METRIC_SAFE_ATTRIBUTES array constrains metric attributes, preventing high-cardinality label explosions in your backend.

Agent Thrash Detection

Flags a tool failing with the same fingerprint repeatedly in one session — the pattern an agent produces retrying a call that can't succeed. Channel-aware thresholds set a different bar per failure origin, and wasted tokens and cost for the whole retry loop attribute to one event instead of scattering across N failed spans. v0.6.0, channel-aware thresholds in v0.7.0.

Tool Schema Drift Detection

Watches tools/list and flags when a tool's inputSchema changes between observations, connecting otherwise-inexplicable agent failures back to the schema changing under you. v0.8.0.

Two-Axis Observation Contract

getObservationState() returns toolOutcome (success/failure/unknown counts) and observationIntegrity ('DEGRADED' | 'UNKNOWN') — whether this library's own signal can be trusted right now, separate from whether any tool call failed. Closes the case where instrumentation silently no-ops with no TracerProvider ever registered, making a failing tool indistinguishable from a healthy one. v0.8.0.

Shared Tracker State (instanceKey)

Repeated instrumentMcpServer() calls that pass the same instanceKey share Agent Thrash Detection, budget tracking, schema drift, and the toolOutcome counter's state instead of each call resetting to empty — fixes stateless, per-request deployment shapes. v0.9.0.

MCP v2 Support

Both @modelcontextprotocol/sdk (v1) and @modelcontextprotocol/server (v2, protocol revision 2026-07-28) work with instrumentMcpServer() — two optional peer dependencies, install whichever you use. Spans, fingerprinting, and channel classification all work the same as v1. v0.10.0.

How it works

01

Install

Add opentel-mcp alongside your existing OpenTelemetry SDK setup.

pnpm add opentel-mcp
02

Instrument your server

Wrap your MCP server once — every tools/call gets a span automatically.

import { instrumentMcpServer } from "opentel-mcp";

instrumentMcpServer(server);
03

See silent failures in your traces

Tool calls with isError: true now show up as ERROR spans with a stable fingerprint, in any OTel-compatible backend.

span: tools/call query_database
status: ERROR
fingerprint: a1b2c3d4e5f6a7b8

How opentel-mcp compares

Capabilityopentel-mcp@opentelemetry/api (raw)
Instruments tools/call automatically
Detects isError: true inside a successful response
Deep failure fingerprinting
Built-in mcp.tool.* metrics instruments
LLM cost tracking on tool calls
Detects an agent retrying the same failure repeatedly
Detects a tool's input schema changing between observations
Detects its own instrumentation silently no-op'ing
Cardinality-safe metric attributes, structurally enforced
Never throws into the instrumented handler
Requires manual span code per handler

Raw @opentelemetry/api has no concept of MCP or CallToolResult — that's true by definition, not a knock against it. See the full comparison page for the reasoning behind every row, including why fastmcp and mcp-tracer aren't columns here.

Install in seconds

pnpm add opentel-mcp

After trying opentel-mcp in production MCP servers, developers praised its silent-failure detection for addressing a long-standing gap in MCP observability — something standard OpenTelemetry instrumentation doesn't capture.

Paraphrased from feedback on LinkedIn.

Filed and fixed an upstream fastmcp bug related to error propagation — fastmcp#4549.

Discussed by the community on r/OpenTelemetry.

npm downloads (weekly)Weekly npm downloads for opentel-mcp

Stop shipping silent MCP failures.

Install opentel-mcp and see the first ERROR span it catches that your current setup misses.

pnpm add opentel-mcp
Get started