Skip to content

Interoperating with OpenTelemetry instrumentation in the MCP SDK聽#3451

Open

Description

@aabmass

Enhancement

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).

Activity

  1. added
    enhancementImprovement to existing functionality. For issues and smaller PR improvements.
    on Mar 10, 2026
  2. added
    serverRelated to FastMCP server implementation or server-side functionality.
    on Mar 10, 2026
  3. jlowin commented on Mar 13, 2026

    @jlowin
    Member

    Thanks @aabmass! Copying @chrisguidry for visibility, as he's the OTEL guru on the FastMCP side

  4. chrisguidry commented on Mar 19, 2026

    @chrisguidry
    Collaborator

    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 馃

  5. strawgate commented on Mar 25, 2026

    @strawgate
    Collaborator

    Happy to help look at this too

  6. ringerc commented on May 8, 2026

    @ringerc
    Contributor

    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:

    1. Extract traceparent/tracestate from params._meta when processing each message
    2. Wrap the task function to attach the extracted OTel context before execution
    3. The httpx instrumentation then sees the correct parent and injects matching HTTP headers
    # Extract trace context from _meta
    traceparent = params.get("_meta", {}).get("traceparent")
    if traceparent:
        carrier = {"traceparent": traceparent}
        trace_ctx = extract(carrier)
    
    # Wrap handler to run with restored trace context
    async def handle_with_context():
        token = otel_context.attach(trace_ctx)
        try:
            await handle_request_async()
        finally:
            otel_context.detach(token)
    
    tg.start_soon(handle_with_context)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementImprovement to existing functionality. For issues and smaller PR improvements.serverRelated to FastMCP server implementation or server-side functionality.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions