Skip to content

fix(controller): recover MCP auth session from RequestExtra in tool handlers#1853

Open
onematchfox wants to merge 1 commit into
kagent-dev:mainfrom
onematchfox:fix-mcp-auth
Open

fix(controller): recover MCP auth session from RequestExtra in tool handlers#1853
onematchfox wants to merge 1 commit into
kagent-dev:mainfrom
onematchfox:fix-mcp-auth

Conversation

@onematchfox
Copy link
Copy Markdown
Contributor

@onematchfox onematchfox commented May 12, 2026

The Go MCP SDK detaches the HTTP request context before dispatching to tool handlers. From the SDK source:

// Pass req.Context() here, to allow middleware to add context values.
// The context is detached in the jsonrpc2 library when handling the
// long-running stream.

This means the auth session placed by AuthnMiddleware is not visible via auth.AuthSessionFrom(ctx) in tool handlers.

The SDK does preserve the original HTTP headers in RequestExtra.Header though.

Re-authenticate from those headers at the top of handleInvokeAgent so the A2A client's outbound request to the agent carries the user's JWT.

Copilot AI review requested due to automatic review settings May 12, 2026 14:00
@github-actions github-actions Bot added the bug Something isn't working label May 12, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels May 12, 2026
@onematchfox onematchfox changed the title fix(mcp): recover auth session from RequestExtra in tool handlers fix(controller): recover MCP auth session from RequestExtra in tool handlers May 12, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels May 12, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses an auth-context propagation gap in the Go MCP Streamable HTTP handling path: tool handlers lose the original HTTP request context (and thus the auth.Session), so invoke_agent re-authenticates using the preserved request headers in CallToolRequest.Extra to ensure downstream A2A calls can forward the user’s JWT.

Changes:

  • Recover auth.Session inside handleInvokeAgent by re-authenticating from RequestExtra.Header, then attach it to the handler context.
  • Add unit tests validating Authorization propagation to the A2A backend when an MCP client supplies (or omits) an Authorization header.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
go/core/internal/mcp/mcp_handler.go Re-authenticates from RequestExtra.Header to restore the session in tool-handler context for downstream A2A auth propagation.
go/core/internal/mcp/mcp_handler_test.go Adds end-to-end-ish unit tests covering auth propagation behavior through MCP → A2A.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +186 to +194
// The Go MCP SDK detaches the HTTP request context when dispatching to
// tool handlers, so auth.AuthSessionFrom(ctx) returns nothing. Recover
// the auth session from the HTTP headers preserved in RequestExtra so
// that the A2A client's outbound request to the agent carries the user's JWT.
if extra := req.GetExtra(); extra != nil {
if session, err := h.authenticator.Authenticate(ctx, extra.Header, nil); err == nil {
ctx = auth.AuthSessionTo(ctx, session)
}
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

RequestExtra doesn't carry query params

Comment thread go/core/internal/mcp/mcp_handler_test.go
Comment thread go/core/internal/mcp/mcp_handler_test.go Outdated
… handlers

The Go MCP SDK detaches the HTTP request context before dispatching to tool handlers. From the [SDK source](https://github.com/modelcontextprotocol/go-sdk/blob/v1.5.0/mcp/streamable.go#L485-L487):

>  // Pass req.Context() here, to allow middleware to add context values.
>  // The context is detached in the jsonrpc2 library when handling the
>  // long-running stream.

This means the auth session placed by `AuthnMiddleware` is not visible via `auth.AuthSessionFrom(ctx)` in tool handlers.

The SDK does preserve the original HTTP headers in [RequestExtra.Header](https://github.com/modelcontextprotocol/go-sdk/blob/v1.5.0/mcp/streamable.go#L1155-L1158) though.

Re-authenticate from those headers at the top of handleInvokeAgent so the A2A client's outbound request to the agent carries the user's JWT.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Brian Fox <878612+onematchfox@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants