From 2705fc432e7d94989c30bd8d4ce203c17add8842 Mon Sep 17 00:00:00 2001 From: Brad Morgan Date: Wed, 10 Jun 2026 00:08:50 +0000 Subject: [PATCH] mcp: expose the originating request context on RequestExtra Server sessions dispatch incoming messages on the session's connection context, not the per-request HTTP context, so request-scoped values set by HTTP middleware (auth principals, loggers, trace spans) never reach method handlers. Carry the originating request context on RequestExtra (alongside Header) so handlers and receiving middleware can read request-scoped values and propagate them onto the handler context. --- mcp/shared.go | 9 +++++++++ mcp/streamable.go | 5 +++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/mcp/shared.go b/mcp/shared.go index 5069a470..264b7ba9 100644 --- a/mcp/shared.go +++ b/mcp/shared.go @@ -604,6 +604,15 @@ type RequestExtra struct { TokenInfo *auth.TokenInfo // bearer token info (e.g. from OAuth) if any Header http.Header // header from HTTP request, if any + // RequestContext is the originating HTTP request's context, if any. Server + // sessions dispatch incoming messages on the session's connection context, + // not the per-request HTTP context, so request-scoped values set by HTTP + // middleware (auth principals, loggers, trace spans) do not otherwise reach + // method handlers. Read request-scoped values from here (e.g. in receiving + // middleware) and propagate them onto the handler context. Use it for its + // values only; its cancellation and deadline are not the handler's. + RequestContext context.Context //nolint:containedctx // request-scoped transport metadata, mirrors Header + // If set, CloseSSEStream explicitly closes the current SSE request stream. // // [SEP-1699] introduced server-side SSE stream disconnection: for diff --git a/mcp/streamable.go b/mcp/streamable.go index 42c28e66..f0b758ac 100644 --- a/mcp/streamable.go +++ b/mcp/streamable.go @@ -1809,8 +1809,9 @@ func (c *streamableServerConn) servePOST(w http.ResponseWriter, req *http.Reques } // Include metadata for all requests (including notifications). jreq.Extra = &RequestExtra{ - TokenInfo: tokenInfo, - Header: req.Header, + TokenInfo: tokenInfo, + Header: req.Header, + RequestContext: req.Context(), } if jreq.IsCall() { calls[jreq.ID] = struct{}{}