Splunk OpenTelemetry instrumentation for FastMCP (Model Context Protocol)
Project description
This library provides automatic instrumentation for FastMCP, a Python library for building Model Context Protocol (MCP) servers.
Compatibility Matrix
Instrumentation |
fastmcp |
util-genai |
Notes |
|---|---|---|---|
0.1.1 |
2.x (jlowin/fastmcp) |
<= 0.1.9 |
PR #147. Wraps ToolManager.call_tool. |
0.2.0 |
>= 3.0.0, < 4 |
>= 0.1.12 |
Wraps FastMCP.call_tool, read_resource, render_prompt. Breaking change from 0.1.x. |
0.2.1 |
>= 3.0.0, < 4 |
>= 0.1.13 |
initialize MCPOperation replaces AgentInvocation as session root span on both client and server. MCP session duration metrics now emitted from the initialize span. |
Installation
pip install splunk-otel-instrumentation-fastmcp
This can also be installed with the instruments extra to automatically install FastMCP:
pip install 'splunk-otel-instrumentation-fastmcp[instruments]'
Usage
Programmatic instrumentation:
from opentelemetry.instrumentation.fastmcp import FastMCPInstrumentor
FastMCPInstrumentor().instrument()
Auto-instrumentation:
The instrumentation is automatically applied when using OpenTelemetry auto-instrumentation:
opentelemetry-instrument python your_mcp_server.py
Environment Variables
The following environment variables control the instrumentation behavior:
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT: Capture tool arguments and results (default: false)
OTEL_INSTRUMENTATION_GENAI_EMITTERS: Select emitters - span, metric, event (default: span)
What is Instrumented
Server-side (v0.2.1 — FastMCP 3.x):
Session lifecycle — Server.run is wrapped with an initialize MCPOperation span that spans the full session and acts as the root span for all server-side operations.
Tool execution via FastMCP.call_tool
Resource reads via FastMCP.read_resource
Prompt rendering via FastMCP.render_prompt
Client-side (v0.2.1):
Session lifecycle — Client.__aenter__ / __aexit__ are wrapped with an initialize MCPOperation span. After a successful connect the span is enriched with mcp.protocol.version and sdot.mcp.server_name from the server handshake.
Tool calls via Client.call_tool
Tool listings via Client.list_tools
Resource reads via Client.read_resource
Prompt rendering via Client.get_prompt
Server-side (v0.2.0 — FastMCP 3.x):
FastMCP server initialization
Tool execution via FastMCP.call_tool
Resource reads via FastMCP.read_resource
Prompt rendering via FastMCP.render_prompt
Server-side (v0.1.x — FastMCP 2.x):
FastMCP server initialization
Tool execution via ToolManager.call_tool
Transport-level:
Automatic trace context propagation via _meta field
Works for all MCP transports: stdio, SSE, streamable-http
Trace Context Propagation
The instrumentation automatically propagates W3C TraceContext (traceparent, tracestate) and baggage between MCP client and server processes. This enables distributed tracing across process boundaries:
Client spans and server spans share the same trace_id
Server tool execution spans are children of client tool call spans
No code changes required in your MCP server or client
Transport bridge (transport_instrumentor.py)
The MCP Python SDK v1.x (current stable, up to 1.27.0) does not natively propagate OpenTelemetry context. This instrumentation includes a transport-layer bridge (transport_instrumentor.py) that:
Client side: wraps BaseSession.send_request to inject traceparent, tracestate, and baggage into params.meta (serialized as _meta on the wire).
Server side: wraps Server._handle_request to extract trace context from request_meta and populate an MCPRequestContext (via ContextVar) for the server instrumentor to read transport-level attributes like jsonrpc.request.id and network.transport.
Upstream native support (mcp v2.x)
Native OTel support has been merged to the upstream SDK’s main branch, targeting v2.x (not yet released as of Apr 2026):
#2298 (merged Mar 31) — propagate contextvars.Context through anyio streams. Supersedes #1996 (closed).
#2381 (merged Mar 31) — native CLIENT + SERVER spans, W3C trace-context inject/extract via params.meta, and opentelemetry-api as a mandatory dependency.
Related open/draft PRs that may further extend the native support:
Migration plan
Once mcp >= 2.x is released and the minimum supported version is raised:
_send_request_wrapper (client-side inject) can be removed.
The trace-context extract/attach portion of _server_handle_request_wrapper can be removed. The MCPRequestContext population (jsonrpc.request.id, network.transport) should remain because the v2.x native spans (per #2381) only surface mcp.method.name and jsonrpc.request.id; network.transport is not included. Re-evaluate as the upstream spans mature.
_extract_carrier_from_meta can be removed.
A feature-detection guard (similar to _has_native_telemetry in the server instrumentor) should be added so the wrappers gracefully become no-ops when running against mcp >= 2.x, allowing a wider version range.
Telemetry
Spans:
initialize (client + server) — Session root span. Spans the full client/server session lifetime. All MCP operation spans are children.
tools/call {tool_name} — Child span for each tool execution. SpanKind.CLIENT on client side, SpanKind.SERVER on server side.
tools/list — Child span for tool listing.
resources/read {uri} — Child span for resource reads.
prompts/get {name} — Child span for prompt rendering.
Metrics:
mcp.client.operation.duration — Duration of client-side MCP operations (histogram).
mcp.server.operation.duration — Duration of server-side MCP operations (histogram).
mcp.client.session.duration — Client session duration, emitted when the initialize span ends (histogram).
mcp.server.session.duration — Server session duration, emitted when the initialize span ends (histogram).
mcp.tool.output.size — Size of tool output in bytes (histogram, custom SDOT attribute).
Events:
When content capture is enabled (OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true):
gen_ai.tool.message — Tool input arguments and output results.
References
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file splunk_otel_instrumentation_fastmcp-0.2.2.tar.gz.
File metadata
- Download URL: splunk_otel_instrumentation_fastmcp-0.2.2.tar.gz
- Upload date:
- Size: 27.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: Hatch/1.16.5 cpython/3.11.15 HTTPX/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd52f1bfd1c4e9bd5799a182f7c8d4368aad6bfd6e74b84011689881f0e59abd
|
|
| MD5 |
27c9bed73ddab9b07488fc15d9735eb5
|
|
| BLAKE2b-256 |
462cdbf47d49ff560f1a425bfd3bcb6c68dcf47f6feb1bf0ebd43f218536019f
|
File details
Details for the file splunk_otel_instrumentation_fastmcp-0.2.2-py3-none-any.whl.
File metadata
- Download URL: splunk_otel_instrumentation_fastmcp-0.2.2-py3-none-any.whl
- Upload date:
- Size: 24.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: Hatch/1.16.5 cpython/3.11.15 HTTPX/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5c6ce57df7259bce7c261f2d8603d778defb41aff4cb426c260eb2d3c5992e66
|
|
| MD5 |
d2be45e981762d031bcd65abc63b4b0f
|
|
| BLAKE2b-256 |
05750ff017cec2c2d9de2340209487490c6f9329295d51626ab19fbf1f503b33
|