MP-301i · Module 1

Distributed Tracing

3 min read

Distributed tracing captures the full lifecycle of a request as a tree of spans. The root span represents the MCP client's request. Child spans represent processing steps: JSON-RPC parsing, authentication, tool dispatch, tool execution, downstream API call, response serialization. Each span records its start time, end time, and key-value attributes. When a tool invocation is slow, the trace shows exactly which span consumed the time — was it the tool logic, the database query inside the tool, or the network round-trip to a downstream service? Without tracing, you know something is slow; with tracing, you know why.

OpenTelemetry is the standard instrumentation framework for distributed tracing. It provides auto-instrumentation for HTTP clients, database drivers, and gRPC — meaning your MCP server gets spans for outbound HTTP calls and database queries without manual instrumentation. Manual instrumentation is needed for MCP-specific operations: create a span for each tool invocation, each resource read, each prompt execution. Propagate the trace context through MCP sessions using the W3C Trace Context headers (traceparent, tracestate) in Streamable HTTP, or as JSON-RPC metadata in stdio.

  1. Add OpenTelemetry SDK Install @opentelemetry/sdk-node and configure it with an OTLP exporter pointing to your collector (Jaeger, Zipkin, Grafana Tempo). Enable auto-instrumentation for HTTP and database libraries.
  2. Instrument MCP operations Create manual spans for tool invocations, resource reads, and prompt executions. Set span attributes: tool.name, tool.duration_ms, tool.result_status. Record errors as span events.
  3. Propagate context For Streamable HTTP, include W3C traceparent/tracestate headers in all requests. For stdio, add a _trace field to JSON-RPC params. Extract the context on the receiving side and create child spans.