Dev ToolsΒ·
advanced
Β·12 min readΒ·Jul 9, 2026

Implementing OpenTelemetry, Metrics, and Distributed Tracing in MCP Servers

Instrument your custom MCP servers with OpenTelemetry. Track tool performance latency, monitor request volumes, and configure distributed tracing pipelines.

OpenTelemetrytracingmetricsobservabilityPrometheusarchitecture
Interactive Tool
1-Click Export

Generate & Validate Multi-Client MCP Config

One-click export with environment variables & path locators for Claude Desktop, Cursor, Windsurf, and OpenAI Codex CLI.

Open in Generator

OpenTelemetry, Metrics, and Distributed Tracing in MCP Servers

When MCP servers run inside production pipelines, tracking tool execution times, monitoring JSON-RPC latency, and recording request volumes becomes critical. OpenTelemetry standardizes how logs, traces, and metrics are emitted from your Node.js MCP server to downstream observability platforms like Prometheus, Jaeger, or Datadog.

Prerequisites

  1. β–ΈAn observability backend running locally or in the cloud (e.g., Jaeger for traces, Prometheus for metrics).
  2. β–ΈThe @opentelemetry/api and @opentelemetry/sdk-node npm packages installed in your custom MCP server.

Architecture Diagram

code
[MCP Client] --(JSON-RPC Tool Call)--> [MCP Server]
                                           | (Instrumented with OpenTelemetry SDK)
                                           +---> [Metrics Collector (Prometheus)]
                                           +---> [Distributed Tracing (Jaeger)]

Implementing OpenTelemetry Tracing

By wrapping your tool execution blocks in an Active Span, you can measure exactly how long your AI agent's requested operations take to complete.

typescript
import { trace, context } from '@opentelemetry/api';
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';

// Initialize the OTLP Exporter (defaults to )
const provider = new NodeTracerProvider();
const exporter = new OTLPTraceExporter({ url: '/v1/traces' });
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
provider.register();

const tracer = trace.getTracer('mcp-server-tracer');

// Trace execution of custom tools
async function executeWithTracing(toolName: string, executeFn: () => Promise<any>) {
  return tracer.startActiveSpan(`mcp-tool::${toolName}`, async (span) => {
    try {
      const result = await executeFn();
      span.setStatus({ code: 0 }); // Ok
      return result;
    } catch (error: any) {
      span.recordException(error);
      span.setStatus({ code: 1, message: error.message }); // Error
      throw error;
    } finally {
      span.end();
    }
  });
}

Best Practices

  • β–ΈSanitize Payloads: Do not blindly inject the arguments JSON payload from the AI agent into your Trace attributes. Agents frequently generate enormous base64 strings or PII that will bloat your tracing backend.
  • β–ΈContext Propagation: If your MCP server acts as a proxy and makes downstream HTTP calls to other microservices, ensure you inject the traceparent header into those outgoing fetch requests to maintain distributed tracing continuity.

Troubleshooting

  • β–ΈNo Traces Appearing: Ensure your Jaeger/OTLP collector is actually listening on (HTTP) or (gRPC). Ensure your exporter matches the protocol you are using.
  • β–ΈMemory Leaks: Never use a SimpleSpanProcessor in high-throughput production environments; it blocks the event loop. Switch to BatchSpanProcessor.

Using with OpenAI Codex

You can use this MCP server with the OpenAI Codex CLI by adding it to your configuration:

bash
codex mcp add --name opentelemetry --command "npx -y @modelcontextprotocol/server-opentelemetry" --env OTEL_EXPORTER_ENDPOINT=

For a full list of recommended servers, see Best MCP Servers for OpenAI Codex.

Ready to Deploy?

Build your full agent toolstack in the Visual Generator

Combine Implementing OpenTelemetry, Metrics, and Distributed Tracing in with databases, search APIs, and memory graphs in a single configuration file.

Customize in Generator

Related Guides