Skip to content

Preserve context.Context across variant dispatch by bypassing in-memory transport#6

Merged
StevenRChen merged 8 commits intomainfrom
context_fix
Mar 18, 2026
Merged

Preserve context.Context across variant dispatch by bypassing in-memory transport#6
StevenRChen merged 8 commits intomainfrom
context_fix

Conversation

@StevenRChen
Copy link
Collaborator

@StevenRChen StevenRChen commented Mar 16, 2026

Summary

  • Switched variant dispatch from ClientSession RPC calls to direct inner server handler invocation via a new backendSession type, preserving context.Context values (e.g. RequestContext) that were previously lost crossing the in-memory transport boundary
  • Added backendSession abstraction in session.go that mirrors the mcp.ClientSession API but calls the inner server's handler chain directly, forwarding RequestExtra (token info, HTTP headers, etc.)
  • Captured the inner server's handler chain via receiving middleware (captureMCPMethodHandler) in backend.go, reused across all connections
  • Simplified innerConnection to hold *backendSession + cleanup; in-memory transport/client kept alive only for notification forwarding (progress, logging)
  • Refactored getSessiongetConnection returning *innerConnection to reduce indirection in dispatch code
  • Moved injectVariantMeta calls to after type assertion and nil checks in all dispatch handlers for consistency and nil-safety

Test plan

  • Existing variant dispatch tests pass (go test ./variants/...)
  • Verify context values (e.g. RequestContext) are available in tool handlers when invoked through variant dispatch
  • Verify RequestExtra fields (token info, HTTP headers) are forwarded to inner server handlers

…t and request extra directly to the backend handler bypassing the jsonrpc handling clientSession.
@StevenRChen StevenRChen changed the title Context fix Preserve context.Context across variant dispatch by bypassing in-memory transport Mar 16, 2026
@Degiorgio Degiorgio self-requested a review March 18, 2026 09:06
Copy link
Collaborator

@Degiorgio Degiorgio left a comment

Choose a reason for hiding this comment

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

Missing test for context propagation

The entire purpose of this PR is fixing context propagation, but there's no test proving it works?

Degiorgio
Degiorgio previously approved these changes Mar 18, 2026
@StevenRChen StevenRChen merged commit 150c110 into main Mar 18, 2026
11 checks passed
@StevenRChen StevenRChen deleted the context_fix branch March 18, 2026 10:53
@StevenRChen
Copy link
Collaborator Author

Will add integration tests in a separate PR.

StevenRChen added a commit that referenced this pull request Mar 23, 2026
…ications in stateless mode (#7)

Registers a sending middleware on each inner server that intercepts all
outgoing messages and routes them through the front session using a
session-swapped request wrapper. Replaces the previous proxy client
handler approach which dropped log messages in stateless mode.

## Motivation and Context
Tool handlers in variant servers use req.Session (the inner session) to
send notifications. Previously, log messages were silently dropped in
stateless mode because the inner session is not aware of the front
session.
This change injects the sendingMethodHandler from the frontSession into
the context and adds a sending middleware to redirect all sending
requests to the frontSession handler directly.
A few considerations in this implementation:
* Having frontSession in the context allows notifications to be sent to
the correct frontSession, when the same backend session could be used by
multiple front sessions.
* This solution will work for synchronous notifications that happen
within the same context (progress, log, sampling, elicitation) but not
working for asynchronous notifications (tool list changed, resource
updated etc), because asynchronous notifications are sent with a new
context.
* All the operations before the sending method will still happen in the
backend. Most notable impact is in stateless mode, requests from one
client could change the log level for other clients. For this reason, I
default the logging level to debug for now.
* This implementation relies on the MCP Go SDK sendingMethodHandler
taking a generic `Request` not one that tied to specific function. Based
on the current SDK implementation this is unlikely to change.
* The same generic method forwarding mechanism could work for receiving
methods too, but with some caveat. That can be addressed in separate PR.

## How Has This Been Tested?
TestNotificationDelivery — verifies progress and log messages arrive at
the front clients with multiple clients making concurrent request.

New tests added for context preservation that was added in
#6.
Context preservation is required to make the notification forwarding
work anyway. Since we use the context to carry frontSession handler to
the backend session.

All existing tests pass

## Breaking Changes
None. Tool handlers continue to use req.Session normally.

## Types of changes
Bug fix (non-breaking change which fixes an issue)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants