Skip to content

Conversation

@cagataycali
Copy link
Member

Description

Fixes #1440

The MCP client creates a background thread for connection management. Previously, context variables set in the main thread were not accessible in this background thread.

This change copies the context from the main thread when starting the background thread, ensuring that contextvars are properly propagated. This is consistent with the fix in PR #1146 which addressed the same issue for tool invocations.

Changes

  • Add contextvars import
  • Use contextvars.copy_context() and ctx.run() when creating background thread
  • Add test to verify context propagation

Example (from issue #1440)

# Before fix: contextvar not accessible in MCP background thread
context_var.set("some-value")
with mcp_client:  # Background thread doesn't see context_var
    ...

# After fix: contextvar is propagated
context_var.set("some-value")
with mcp_client:  # Background thread can access context_var
    ...

Related Issues

Documentation PR

No documentation changes required - this is an internal implementation detail.

Type of Change

Bug fix

Testing

  • I ran hatch run prepare (formatter and linter)
  • I ran hatch test tests/strands/tools/mcp/test_mcp_client.py - 50 tests pass
  • I ran hatch test tests/strands/tools/mcp/test_mcp_client_contextvar.py - new test passes

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.


Created by strands-coder autonomous agent 🦆

Fixes strands-agents#1440

The MCP client creates a background thread for connection management.
Previously, context variables set in the main thread were not accessible
in this background thread.

This change copies the context from the main thread when starting the
background thread, ensuring that contextvars are properly propagated.
This is consistent with the fix in PR strands-agents#1146 which addressed the same
issue for tool invocations.

Changes:
- Add contextvars import
- Use contextvars.copy_context() and ctx.run() when creating background thread
- Add test to verify context propagation
@codecov
Copy link

codecov bot commented Jan 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@pgrayy pgrayy merged commit c098b3d into strands-agents:main Jan 13, 2026
14 of 15 checks passed
strands-agent added a commit to strands-agent/sdk-python that referenced this pull request Jan 19, 2026
Fixes strands-agents#1512

In ASGI environments (uvicorn/hypercorn) that already have an active event
loop, the MCPClient background thread initialization can fail with:
'RuntimeWarning: coroutine was never awaited' because run_until_complete()
cannot execute the coroutine.

Root cause: PR strands-agents#1444 added contextvars.copy_context() to propagate context
variables to the background thread. In ASGI environments, this can copy
event loop references from the parent thread, causing conflicts when the
background thread tries to create its own event loop.

Solution: Explicitly clear any inherited event loop state by calling
asyncio.set_event_loop(None) before creating the new event loop. This
ensures the background thread starts with a clean slate regardless of
what context was copied from the parent thread.

This fix is defensive and handles partial initialization gracefully with
a try/except block around set_event_loop(None).

Testing:
- Existing MCP tests pass (no regression)
- Fixes MCPClient usage under uvicorn/ASGI environments
- Compatible with OpenTelemetry instrumentation
strands-agent added a commit to strands-agent/sdk-python that referenced this pull request Jan 20, 2026
…event loop

Fixes strands-agents#1512

When MCPClient runs in ASGI environments (uvicorn, hypercorn), the parent
thread has an active event loop. Since PR strands-agents#1444 uses contextvars.copy_context()
to propagate context variables to the background thread, it also copies
the _running_loop contextvar marker.

When the background thread then calls run_until_complete(), Python's asyncio
detects the inherited running loop marker and raises:
'Cannot run the event loop while another loop is running'

The fix clears both:
1. The _running_loop contextvar via events._set_running_loop(None)
2. The thread-local event loop via asyncio.set_event_loop(None)

This ensures the background thread starts with a clean slate while still
preserving context variable propagation from PR strands-agents#1444.

Solution verified by issue reporter @jpvelasco.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] MCP Client does not propagate contextvars

4 participants