Skip to content

Comments

SEP-414: Document OpenTelemetry Trace Context Propagation Conventions#414

Open
codefromthecrypt wants to merge 8 commits intomodelcontextprotocol:mainfrom
codefromthecrypt:patch-1
Open

SEP-414: Document OpenTelemetry Trace Context Propagation Conventions#414
codefromthecrypt wants to merge 8 commits intomodelcontextprotocol:mainfrom
codefromthecrypt:patch-1

Conversation

@codefromthecrypt
Copy link

@codefromthecrypt codefromthecrypt commented Apr 25, 2025

Summary

This PR introduces SEP-414, documenting OpenTelemetry Trace Context Propagation Conventions

SEP

  • seps/414-request-meta.md

Sponsor

@Kludex

Notes

This PR converts the earlier doc change into a standards-track SEP. Discussion links and rationale are in the SEP itself.

@samsp-msft
Copy link

I would love the text in the spec to include more of what you have written in the PR description, and that the recommendation is to use traceparent, tracestate and baggage parameters under _meta to propagate OpenTelemetry context information. The format of each of the values should be the same as the http headers in the corresponding w3c specs.

It could be labelled as "Optional: OpenTelemetry context".

I hope that SDKs decide to implement it where they have existing OTel ecosystems that they can leverage. MCP clients are not required to send it, and MCP servers that do not support OTel can safely ignore those parameters.

This may be too much for the index file, but they could be added to the typescript and documentation.

@codefromthecrypt
Copy link
Author

codefromthecrypt commented Apr 25, 2025

@samsp-msft, thanks for your thoughtful feedback! I’ve updated the "Basic" section to keep it neutral and avoid implying MCP defines OpenTelemetry (OTel) specifics:

- Params **MAY** include a `_meta` key with value type `[key: string]: unknown;`. This
  allows propagation of metadata from client to server. For example, OpenTelemetry SDKs
  [default](https://opentelemetry.io/docs/languages/sdk-configuration/general/#otel_propagators) to propagate W3C `traceparent`, `tracestate` and `baggage` fields.

Updated Rationale:

This keeps _meta flexible, recommending to use what OTel SDKs are configured. The nuance is me using "default" which helps relay who owns the decision. OTel supports alternatives (like Jaeger) or excluding baggage for privacy/overhead: we could get into a slippery slope saying too much here.

Specifically, we want to make room in otel for what's likely an inevitable OTEP for MCP. I say inevitable because the other discussion includes transport details (e.g. OTLP which is not propagation). This feels a lot like past discussions that led to specification clarifications including env variable propagation and how to handle messaging. In fact, there's already work in Otel for semantic conventions (thanks for participating in that). Ideally an engineer will be able to see the otel details coherently in one place (e.g. an OTEP).

Long story short, deferring OTel keeps MCP focused on protocol mechanics, not telemetry details. By adding an example, we hint of how to hand-over to otel for clarity on telemetry. Does this address your concern?

@codefromthecrypt
Copy link
Author

codefromthecrypt commented Apr 27, 2025

I took time to update the description with feedback in the comments and also relating to discussions by @ZengyiZhao here and @wdawson here. Hope we can land this soon!

@codefromthecrypt
Copy link
Author

@dsp-ant @jspahrsummers So, for anecdotal context. What drove me to the discussion leading to this and the PR itself was your podcast on latent space with @FanaHOVA and @swyxio

Was a knock-out episode, and since working in oss since 2008 this made me feel the best:

I want to caveat it slightly that on the Internet, it's very easy to be part of a discussion and having an opinion without then actually doing the work. And so I think there. We were. Both Jansen and I are very old school. Open source people that like it's it's marriage driven in the sense that if you have done work and if you if you showcase this with like practical examples and work in SDKs towards the ex extensions you want to make, you have a good chance that it gets in. If you're just there to have an opinion, you're very likely just being ignored

So, my goal with this change was to make the absolutely least change possible, with the highest rigor. Even if it is a no, all good. Thanks for inspiring me to give it a go. I love the do the work, then let's talk approach to change.

@samsp-msft
Copy link

@samsp-msft, thanks for your thoughtful feedback! I’ve updated the "Basic" section to keep it neutral and avoid implying MCP defines OpenTelemetry (OTel) specifics:

- Params **MAY** include a `_meta` key with value type `[key: string]: unknown;`. This
  allows propagation of metadata from client to server. For example, OpenTelemetry SDKs
  [default](https://opentelemetry.io/docs/languages/sdk-configuration/general/#otel_propagators) to propagate W3C `traceparent`, `tracestate` and `baggage` fields.

LGTM

There is a balance between what needs to go into the base specification - providing the place to pass context - and having agreement amongst the SDK as to how they will use the extensibility mechanisms to implement telemetry propagation. The details of which key values pairs should be used and their values can probably be delegated to docs in the OTel space. It can probably go in the docs for the semantic conventions.

I am hoping that we can get common agreement amongst most MCP SDKs about how to incorporate telemetry so that they can interoperate nicely, and it doesn't need major retrofits later.

@codefromthecrypt
Copy link
Author

@samsp-msft thanks for the support. PS I raised a PR to csharp-sdk to change the carrier from request.params -> request.params._meta (and backfilled a test). I didn't see before that an impl was here, too, so wanted to own responsibility of change implied here, as well.

@codefromthecrypt
Copy link
Author

Earlier I mis-attributed request.params._meta[progressToken] to BeeAI ACP. It is not BeeAI specific. Rather it is in the specification already. So, we already document use of request.params._meta, just not generally yet.

I've revised the spec change to link to the progress spec, and also shored up the description accordingly.

@codefromthecrypt
Copy link
Author

@dsp-ant do you have any advice for us on how to progress this PR? I'm happy to revise it, but it seems stalled.

@codefromthecrypt
Copy link
Author

codefromthecrypt commented May 12, 2025

Right now, by naming convention (Request and JSONRPCRequest) any *Request type already implies folks should use _meta as described in this PR, just not with the exact guidance. I suggest we update the schema once the docs around it (this PR) is merged.


Specifically, this PR describes some use cases:

  • Params MAY include a _meta key with value type [key: string]: unknown;. This
    allows propagation of metadata from client to server, such as progressToken.
    OpenTelemetry SDKs default to propagate W3C traceparent,tracestate and baggage
    fields inside _meta as well.

Whereas in the schema today, there are 13 occurrences of this advice on _meta

This result property is reserved by the protocol to allow clients and servers to attach additional metadata to their responses.

The recent work by @findleyr and friends on the Go SDK design implies code generation, and there's a small gap you can see if you look carefully here.
https://go.googlesource.com/tools/+/refs/heads/master/internal/mcp/design/design.md#protocol-types

Request and JSONRPCRequest are implied as base types, and document _meta, but AFAICT, they are not strictly defined as base types. This means code generators can make a miss and prevent _meta from flowing through as desired. Specifically, it is easy to not attach the implied base properties on a request, specifically _meta here.

There are a number of ways to address code generation coherency.. we could make a single "meta" type and use that for _meta everywhere (e.g. to consolidate docs). We could add meta to all places already implied by the Request conventions (so that they are honored in code generators). We could also use other techniques to make a strict relationship to Request so that there's less duplication.

Finally, we can decide to not solve it strictly in the schema. Rather, stick with advice here and mention to code generator authors that there's a relationship with anything ending in Request, Response etc that should have special casing.

I don't have a preferred way out, but I would like to help close out this topic. Any thoughts?

@codefromthecrypt
Copy link
Author

added a section to the description that it is possible a future JSON-RPC 2.1 could formalize "_meta". That said, I don't expect this to change any current practice. cc @mpcm

@mpcm
Copy link

mpcm commented May 12, 2025

@codefromthecrypt See recently posted: https://groups.google.com/g/json-rpc/c/pFFuI0JN8Cs
tl;dr> I think it should live as an extension spec outside of json-rpc, lots of dust to settle yet, but the concept clearly is going to be needed with the payloads that want all this context to track perf/perf-spend, history of actions, consequence, model seeds, etc. The 'old http header' answers wont really work well here.

@jonathanhefner
Copy link
Member

In the JSON-RPC group discussion, I mentioned that responses could benefit from a meta property too. That can be discussed and handled separately from this PR, but I wanted to bring up naming consistency. If we standardize request.params._meta, what would be the equivalent for reponse? response.result._meta plus reponse.error._meta? response._meta?

The protocol currently uses request.params._meta for progressToken, but would a top-level request._meta or request.meta be better? I think the biggest argument against it would be backward compatibility, but the SDKs could handle that based on the MCP version.

@anuraaga
Copy link

@jonathanhefner Thanks for the suggestion - personally, if the compatibility issue is acceptable I would suggest top level meta fields request.meta and response.meta. We see the sdks currently have to do some awkward typing to have method-specific param types that also accept the generic meta, with the json schema version of the protocol effectively not modeling this at all. If moving meta, including the current progress token, to top level it could really simplify that.

@bhelx
Copy link

bhelx commented May 14, 2025

We have a similar need. I too would prefer something outside of the params, although it's a good way to experiment for the time being.

@codefromthecrypt
Copy link
Author

going to close this out as it hasn't moved forward in a month. happy to re-open when maintainers are interested in a change. Meanwhile, per the description, there are enough artifacts here and there to suggest request.params._meta is already in use by the spec and so the documentation concern is less due to that.

@bhelx
Copy link

bhelx commented May 27, 2025

FWIW, i was able to abuse the protocol's _meta for this without changing the request schema or the protocol or the clients:

sending: https://github.com/dylibso/mcp-otel/blob/2407c736c92d6a5e71b454845d839f33dabbbfca/src/agent.ts#L122
receiving: https://github.com/dylibso/mcp-otel/blob/2407c736c92d6a5e71b454845d839f33dabbbfca/src/servers/fetch.ts#L27

I think this should be safe if you do your best to avoid name collisions, but going to ask around.

Doing the actual context propagation and naming of everything works, but is a little tedious if you're not familiar with it. This could perhaps be part of an otel adapter for the SDKs, or one day adopted with the SDKs if some things can be agreed upon.

@codefromthecrypt
Copy link
Author

@bhelx thx for the feedback. I will add to the description your use of this pattern which aligns with others mentioned there including Arize Openinference which is an otel SDK. That way folks don't have to scroll through comments should there be a desire to formalize this later.

@codefromthecrypt
Copy link
Author

@Kludex any process steps missing before this can merge?

@Kludex Kludex self-assigned this Feb 4, 2026
@Kludex Kludex added draft SEP proposal with a sponsor. in-review SEP proposal ready for review. and removed proposal SEP proposal without a sponsor. draft SEP proposal with a sponsor. labels Feb 4, 2026
@Kludex
Copy link
Member

Kludex commented Feb 4, 2026

This looks good. It's just a formality of what is already happening in the ecosystem anyway. It looks good to me.

I'll check if we can present on the next meeting.

@Kludex
Copy link
Member

Kludex commented Feb 4, 2026

It seems the meeting is today, I'll see if I can join.

"location": "New York"
},
"_meta": {
"traceparent": "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, _meta keys are supposed to have reverse DNS vendor prefix (e.g. io.opentelemetry/traceparent), so this is not compliant with how things are supposed to be. The problem is that it seems everyone is already doing this.... may need a pragmatic compromise.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: How disruptive would it be to have OpenTelemetry update this? Perhaps add both during a deprecation period?

Copy link

@nacx nacx Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a huge ecosystem already using opentelemetry that has adopted the traceparent convention, and changing that would have a very high impact. I think this change is unlikely to happen.

Namespacing with the vendor prefix makes perfect sense for things that are new, but I think it is important to acknowledge that there may be some widely adopted and well-established conventions already in the ecosystem that, if we want this to be as interoperable as possible and facilitate adoption, should be supported.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a commit to clarify this exception

### Why document this?

This is currently documented elsewhere, but not as an MCP specification. Doing so ensures that
SEPs depending on this pattern can complete, as well as other SDKs in and outside the MCP org
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What SEPs depend on this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they are listed in the below section of SEPs

### Related SEPs

- [SEP-1788](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1788) - reserved
  keys in `_meta`; should be updated with `traceparent`, `tracestate`, and `baggage` when this
  SEP is implemented
- [SEP-2028](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2028) - builds on
  this SEP for forwarding `_meta` values to HTTP headers

@localden localden moved this to Review Batch in SEP Review Pipeline Feb 4, 2026
@dsp-ant dsp-ant added the accepted SEP accepted by core maintainers, but still requires final wording and reference implementation. label Feb 4, 2026
@dsp-ant
Copy link
Member

dsp-ant commented Feb 4, 2026

This was accepted by Core Maintainers in the Core Maintainer meeting of Feb 4th and an async vote afterwards. @pwwpche had some conerns that we should address. Other than thatn, please ensure it's in a good shape. we need to have

  1. Specification wording
  2. Changelog
  3. SEP wording
  4. Address @pwwpche questions

finalized. Ping a core maintainer to review and merge.

@codefromthecrypt
Copy link
Author

@pwwpche lemme know what we should revise here, and I'll rebase and clear the conflicts. thanks!

@dsp-ant
Copy link
Member

dsp-ant commented Feb 5, 2026

@pwwpche lemme know what we should revise here, and I'll rebase and clear the conflicts. thanks!

@codefromthecrypt @pwwpche's concern was mostly to document why we cannot use the DNS prefix we usually enforce for _meta tags. Usually we would say a _meta field must start with io.modelcontextprotocol, but given that everyone else have standardized on traceparent & co without any prefix, I think we are fine with using them, but should document the exception.

codefromthecrypt and others added 6 commits February 6, 2026 06:36
Co-authored-by: Cliff Hall <cliff@futurescale.com>
Signed-off-by: Adrian Cole <adrian@tetrate.io>
Signed-off-by: Adrian Cole <adrian@tetrate.io>
Signed-off-by: Adrian Cole <adrian@tetrate.io>
Signed-off-by: Adrian Cole <adrian@tetrate.io>
@codefromthecrypt
Copy link
Author

thanks @dsp-ant makes sense. I added text I believe highlights this more clearly in the last commit.

Document OpenTelemetry trace context propagation conventions for
_meta keys (traceparent, tracestate, baggage) in the draft spec,
including the rationale for the DNS prefix exception.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
@codefromthecrypt
Copy link
Author

ok added the spec and changelog. 🚢 when ready or tell me what's next. Thanks, all!

- Status: Final (accepted with reference implementations in org SDKs)
- Created: 2025-04-25 (PR creation date per convention)

Signed-off-by: Adrian Cole <adrian@tetrate.io>
@codefromthecrypt
Copy link
Author

Polish notes:

I set this status to Final as it is accepted and reverse documents the existing c# SDK implementation, which at the same time serves as a reference. This is inline with other SEPs all marked final, as well.

For the SEP date, I noticed another is using the PR creation date, so went with that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

accepted SEP accepted by core maintainers, but still requires final wording and reference implementation. in-review SEP proposal ready for review. SEP

Projects

Status: Accepted

Development

Successfully merging this pull request may close these issues.