Skip to content

[BUG] MCPClient background thread fails to start under uvicorn/ASGI - "coroutine was never awaited" #1512

@jpvelasco

Description

@jpvelasco

Checks

  • I've updated to the latest strands-agents version
  • I've checked the documentation
  • I've searched for similar issues

Environment Information

  • Strands Version: 1.22.0 (also tested 1.21.0)
  • Python Version: 3.13.1 (also tested 3.12)
  • Operating System: Linux (Debian Bookworm in Docker container)
  • Installation Method: pip/uv

Steps to Reproduce

# Minimal reproduction setup:
# 1. Create a simple ASGI app

# app.py
from strands.tools.mcp import MCPClient
from mcp import StdioServerParameters, stdio_client

async def app(scope, receive, send):
    if scope["type"] == "http":
        # This will fail with "background thread did not start in 30 seconds"
        mcp_client = MCPClient(
            lambda: stdio_client(StdioServerParameters(command="awslabs.cost-explorer-mcp-server"))
        )
        with mcp_client:
            tools = mcp_client.list_tools_sync()
        
        await send({"type": "http.response.start", "status": 200, "headers": []})
        await send({"type": "http.response.body", "body": b"OK"})

# 2. Run with uvicorn:
# uvicorn app:app --host 0.0.0.0 --port 8000

# 3. Make a request:
# curl http://localhost:8000/

Container details:

  • Base image: ghcr.io/astral-sh/uv:python3.13-bookworm-slim
  • Running via: opentelemetry-instrument python -m app

Expected Behavior

MCPClient should start its background thread and event loop successfully, allowing list_tools_sync() to return tools from the MCP server.

Actual Behavior

The background thread starts but the async coroutine never runs:

RuntimeWarning: coroutine 'MCPClient._async_background_thread' was never awaited
  File "/usr/local/lib/python3.13/site-packages/strands/tools/mcp/mcp_client.py", line 737, in _background_task
    self._background_thread_event_loop.run_until_complete(self._async_background_thread())

strands.tools.mcp.mcp_client.MCPClientInitializationError: background thread did not start in 30 seconds

The _init_future never completes because _async_background_thread() is never awaited, causing the 30-second timeout.

Additional Context

The issue occurs when:

  1. Running under uvicorn (ASGI server)
  2. In a Docker container
  3. Using opentelemetry-instrument wrapper

The _background_task method creates a new event loop and calls run_until_complete():

def _background_task(self):
    self._background_thread_event_loop = asyncio.new_event_loop()
    asyncio.set_event_loop(self._background_thread_event_loop)
    self._background_thread_event_loop.run_until_complete(self._async_background_thread())

Something in the uvicorn/ASGI environment appears to prevent the new event loop from properly scheduling the coroutine.

Tested configurations (all fail identically):

  • strands-agents 1.21.0 + Python 3.13
  • strands-agents 1.22.0 + Python 3.13
  • strands-agents 1.22.0 + Python 3.12

Works correctly:

  • Running the same code outside uvicorn (direct Python execution)
  • Unit tests with mocked MCPClient

Related Issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions