Skip to content

Forward Mcp-Name header in the McpTransportContext for extension validation #1317

Description

@Kehrlann

Tasks may want to validate HTTP headers. For example, SEP-2663 Tasks mandates, in Streamable HTTP routing headers:

When tasks/get, tasks/update, or tasks/cancel is sent over the Streamable HTTP transport, the client MUST set the Mcp-Name header (defined by SEP-2243) to the value of params.taskId

In that case, the taskId is in the request params, which would likely be interpreted at the Feature level, similar to x-mcp-header in #1199.

Passing headers to features can be accomplished with a context extractor at the transport-level, but that defeats the server / transport separation. Mcp-Method is validated in the transport already for every method, so we do not need to pass it down, but we should extract, decode and pass the Mcp-Name header if present.

Activity

  1. added this to the 2.2.0-M3 milestone on Nov 6, 2026
  2. added
    P2Moderate issues affecting some users, edge cases, potentially valuable feature
    on Nov 6, 2026
  3. media-ctrl commented on Nov 8, 2026

    @media-ctrl

    The routing role and the validation role pull in different directions here, and pinning that down is the part worth settling in the SEP.

    Mcp-Method can be validated in the transport for every method because the transport knows the method name before a body exists. Mcp-Name cannot work the same way: its legality is a function of the task id inside the request params, which only exists after the body is decoded. So one header has two moments.

    1. Bind early, before the body is read. A routing header is only worth anything if a proxy or a session dispatcher can act on it without parsing the body, and that is the whole point of the SEP-2243 header family.
    2. Compare late, after decoding, where the header and the decoded task id can be compared and a mismatch can be a 400 instead of a silently misrouted task.

    Putting the raw value on McpTransportContext serves (1) and leaves (2) to the Feature, which is the right split, but only if the context carries the header verbatim and the feature is documented as owning the equality check. If the transport normalised or dropped a mismatched value on the way through, a client bug would surface as a server routing bug and that is a long debug.

    Two smaller things from the server side of this. Header names are case-insensitive, so read the context key case-insensitively or populate the fast lookup with a folded key. And the header can legally arrive more than once through a proxy, so treat a repeated or comma-joined value as invalid rather than taking the first one, otherwise a misconfigured proxy becomes a wrong-task read.

    On the transport extractor tradeoff you raised: extracting in the transport and passing a typed value down does not have to break the server/transport separation, as long as the context type is transport-agnostic. The separation argument bites when the feature has to reach back into the transport for the raw header, not when the transport hands it a decoded value it already had.

  4. neerajbhatt commented on Nov 8, 2026

    @neerajbhatt
    Contributor

    Hi @Kehrlann , I’ll start working on #1317. I previously contributed to the servlet header handling in #982. I’ll look at how the modern server HTTP transport handles Mcp-Name, add the context propagation and focused tests, and link the PR here when it’s ready.

  5. Kehrlann commented on Nov 9, 2026

    @Kehrlann
    ContributorAuthor

    Hey @neerajbhatt please go ahead.

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

Metadata

Metadata

Assignees

Labels

P2Moderate issues affecting some users, edge cases, potentially valuable featurearea/serverarea/transportmodernv3 covering the 2026-07-28 spec

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions