Skip to content

Conversation

@manuelibar
Copy link
Contributor

Problem

Context propagation was broken in StreamableClientTransport because:

  1. Connect() used context.Background() instead of the parent context
  2. Close() created a race condition where DELETE requests were cancelled before completion

Solution

  • Use parent context when creating the connection context in Connect()
  • Reorder Close() operations to perform cleanup DELETE before cancelling context

Impact

  • Request-scoped values (auth tokens, trace IDs) now propagate correctly to background HTTP operations
  • Eliminates race condition in cleanup operations
  • Maintains proper Go context semantics

Fixes #513

Context propagation was broken in StreamableClientTransport because:
1. Connect() used context.Background() instead of the parent context
2. Close() created a race condition where DELETE requests were cancelled

This change fixes both issues by:
- Using the parent context when creating the connection context
- Reordering Close() to perform cleanup DELETE before cancelling context

This ensures request-scoped values (auth tokens, trace IDs) propagate
correctly to background HTTP operations.

Fixes modelcontextprotocol#513
@samthanawalla
Copy link
Contributor

Thanks for the PR!

There seems to be a race failure. Could you also add a test to streamable_test.go that demonstrates that the context is now propagated correctly?

@manuelibar manuelibar marked this pull request as draft September 22, 2025 18:36
Adds TestStreamableClientContextPropagation to verify that context values
are properly propagated to background HTTP operations (SSE GET and cleanup
DELETE requests) in StreamableClientTransport.

The test uses a custom HTTP handler to capture request contexts and verify
that context values from the parent context are accessible in both the
SSE connection establishment and session cleanup requests.
@manuelibar manuelibar force-pushed the fix/context-propagation-issue-513 branch from 473a047 to 2934625 Compare September 22, 2025 18:38
The test now properly verifies that StreamableClientTransport can handle
contexts with values without errors, demonstrating that the context
propagation fix is working correctly.

The test validates the fix at streamable.go:1021 where context.WithCancel(ctx)
is used instead of context.WithCancel(context.Background()).
…nsport

Replace bloated context propagation test with clean, idiomatic Go code that:
- Follows existing test patterns in the codebase
- Removes unnecessary comments and complex synchronization
- Tests actual context derivation (cancellable contexts)
- Demonstrates the fix works without HTTP value propagation complexity

The test verifies that background HTTP operations (SSE GET and DELETE cleanup)
use properly derived contexts from the original Connect() context, confirming
the fix in streamable.go where context.WithCancel(ctx) replaced
context.WithCancel(context.Background()).
@manuelibar manuelibar force-pushed the fix/context-propagation-issue-513 branch from 6a5dd46 to 016015c Compare September 22, 2025 20:44
Replace unsafe global testAuth boolean with atomic.Bool to prevent
data race between test setup/teardown and background HTTP operations
in StreamableClientTransport.
@manuelibar manuelibar marked this pull request as ready for review September 22, 2025 20:51
@manuelibar
Copy link
Contributor Author

Hi @samthanawalla, thanks for the review. I've updated the PR with the following:

  • Feedback Addressed: The changes you requested have been implemented.
  • Additional Fix: I also resolved a pre-existing race condition on the testAuth flag to improve test stability.

Ready for another look when you get a chance 👍 .

mu.Lock()
defer mu.Unlock()

if getCtx != nil && getCtx.Done() == nil {
Copy link
Contributor

@samthanawalla samthanawalla Sep 23, 2025

Choose a reason for hiding this comment

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

This test only checks that the context is cancellable but doesn't check if the values are passed. Can we change this test to verify that the value of some testkey is preserved?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I addressed this comment on this commit

Add test to verify that context values and cancellation are properly
propagated through StreamableClientTransport.Connect().

The test ensures:
- Context values are preserved in the connection context
- Connection context remains cancellable
- Parent context cancellation propagates to connection context

This addresses the context propagation requirements for the streamable
transport implementation.
@samthanawalla samthanawalla merged commit 5d64d61 into modelcontextprotocol:main Sep 23, 2025
5 checks passed
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.

Context propagation is broken in StreamableClientTransport

2 participants