You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Interoperating with OpenTelemetry instrumentation in the MCP SDK聽#3451
Hello from OpenTelemetry python 馃憢 First off, thank you for instrumenting with OTel directly, it's very exciting to see!
I wanted to give an FYI that I'm working on adding instrumentation to the MCP SDK directly modelcontextprotocol/python-sdk#421 (PR if you're curious). I imagine that will have some impact on what's been built in this repo, and at worst there will be doubled spans. It would be relatively easy to make the layers interoperate, and I'm happy to brainstorm on this.
I've also sent a PR for modelcontextprotocol/python-sdk#1969 which fixes contextvar propagation (which OTel uses) from the MCP Session layer to the transport layer (e.g. opentelemetry-instrumentation-httpx).
Thanks for the heads up, @aabmass! I think we can definitely unify things once the SDK's spans are in place. We tried to stick as close to the OTel semantic conventions for MCP, so I'm betting that once you have spans in place, we can just remove ours and add back any fastmcp-specific attributes to them where we need. Theoretically, our unit test suite should remain unchanged 馃
I just hit this issue with httpx not seeing trace context. Quite confusing.
Context propagation should still work at application layer if _meta is decoded by the request receiver, but two parallel traces may be generated (one for transport, one for application) which is very confusing.
Workaround
Patch StreamableHTTPTransport.post_writer to restore trace context from _meta before spawning request handler tasks:
Extract traceparent/tracestate from params._meta when processing each message
Wrap the task function to attach the extracted OTel context before execution
The httpx instrumentation then sees the correct parent and injects matching HTTP headers
# Extract trace context from _metatraceparent=params.get("_meta", {}).get("traceparent")
iftraceparent:
carrier= {"traceparent": traceparent}
trace_ctx=extract(carrier)
# Wrap handler to run with restored trace contextasyncdefhandle_with_context():
token=otel_context.attach(trace_ctx)
try:
awaithandle_request_async()
finally:
otel_context.detach(token)
tg.start_soon(handle_with_context)
Activity
jlowin commentedon Mar 13, 2026
Thanks @aabmass! Copying @chrisguidry for visibility, as he's the OTEL guru on the FastMCP side
chrisguidry commentedon Mar 19, 2026
Thanks for the heads up, @aabmass! I think we can definitely unify things once the SDK's spans are in place. We tried to stick as close to the OTel semantic conventions for MCP, so I'm betting that once you have spans in place, we can just remove ours and add back any fastmcp-specific attributes to them where we need. Theoretically, our unit test suite should remain unchanged 馃
strawgate commentedon Mar 25, 2026
Happy to help look at this too
ringerc commentedon May 8, 2026
I just hit this issue with
httpxnot seeing trace context. Quite confusing.Context propagation should still work at application layer if
_metais decoded by the request receiver, but two parallel traces may be generated (one for transport, one for application) which is very confusing.Workaround
Patch
StreamableHTTPTransport.post_writerto restore trace context from_metabefore spawning request handler tasks:traceparent/tracestatefromparams._metawhen processing each message