Skip to content

McpToolset connection failure (HTTP 401/403/5xx) causes ASGI crash instead of graceful error #4300

@simone-viozzi

Description

@simone-viozzi

🔴 Required Information

Describe the Bug:
When an MCP server returns HTTP 401 Unauthorized (e.g., due to an expired/invalid JWT token), the entire ASGI application crashes instead of returning a proper error to the caller. The HTTP error is not propagated, causing the SSE response stream to terminate abruptly.

Steps to Reproduce:

  1. Configure McpToolset with a header_provider that returns a JWT token
  2. Make a request where the JWT is invalid/expired (or MCP server rejects it)
  3. The MCP server returns HTTP 401
  4. Observe app crash with ASGI callable returned without completing response
from google.adk.tools.mcp_tool import McpToolset, StreamableHTTPConnectionParams

def _mcp_header_provider(ctx: ReadonlyContext) -> dict[str, str]:
    jwt = ctx.state.get("jwtToken")
    if not jwt:
        return {}
    return {"Authorization": f"Bearer {jwt}"}

toolset = McpToolset(
    connection_params=StreamableHTTPConnectionParams(
        url="https://example.com/mcp",
    ),
    header_provider=_mcp_header_provider,
    tool_filter=["some_tool"],
)

Expected Behavior:
The 401 error should be caught and propagated as a ConnectionError or similar, allowing the application to handle it gracefully (e.g., return an error message to the user, refresh token, etc.).

Observed Behavior:
The application crashes with:

ERROR - uvicorn.error - ASGI callable returned without completing response.

Environment Details:

  • ADK Library Version: 1.20.0
  • Desktop OS: Linux
  • Python Version: 3.13.8
  • MCP library version: 1.25.0

Model Information:

  • Are you using LiteLLM: No
  • Which model is being used: N/A (crash happens before LLM interaction)

🟡 Optional Information

Logs:

2026-01-27 16:18:49,502 DEBUG - mcp.client.streamable_http - Connecting to StreamableHTTP endpoint: https://example.com/mcp
2026-01-27 16:18:49,502 DEBUG - mcp.client.streamable_http - Sending client message: root=JSONRPCRequest(method='initialize', ...)
2026-01-27 16:18:49,583 DEBUG - httpcore.http11 - receive_response_headers.complete return_value=(b'HTTP/1.1', 401, b'', [..., (b'WWW-Authenticate', b'Basic realm="Realm"'), ...])
2026-01-27 16:18:49,584 DEBUG - httpcore.http11 - response_closed.complete
2026-01-27 16:18:49,585 ERROR - uvicorn.error - ASGI callable returned without completing response.

Additional Context:
The issue may originate in the MCP Python SDK (streamable_http.py) where HTTP errors like 401 are not sent through the response stream, unlike 404 which is handled explicitly. This might warrant an upstream issue to https://github.com/modelcontextprotocol/python-sdk as well.

How often has this issue occurred?:

  • Always (100%) — whenever MCP server returns a non-2xx/non-404 status code

Metadata

Metadata

Assignees

No one assigned

    Labels

    mcp[Component] Issues about MCP supporttools[Component] This issue is related to tools

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions