Skip to content

fix: prevent a bare CancelledError during MCP connection from terminating the gateway #231

Description

@babyTa999

Summary

A failed streamable HTTP MCP connection can terminate the entire Raven gateway when the MCP SDK/anyio surfaces a bare asyncio.CancelledError.

connect_mcp_servers() currently catches (Exception, BaseExceptionGroup), but asyncio.CancelledError directly inherits from BaseException. It is therefore not caught by this handler and can escape the per-server connection boundary, terminating the gateway instead of logging a failed MCP connection and continuing startup.

In my case, the failure was triggered by an MCP server receiving no valid runtime authentication. After ensuring the Authorization header was available to the gateway process, the same server connected successfully and registered 25 tools. This fixes the local trigger, but does not address the uncaught-cancellation behavior.

Steps to reproduce

  1. Configure a streamable HTTP MCP server in Raven.
  2. Start Raven with invalid, missing, or otherwise rejected authentication for that MCP endpoint.
  3. Let the server/SDK cancel the streamable HTTP request during MCP initialization.
  4. Observe that a bare asyncio.exceptions.CancelledError can escape connect_mcp_servers() and terminate the entire gateway.

Relevant connection code currently uses:

except (Exception, BaseExceptionGroup) as e:
    logger.error("MCP server '{}': failed to connect: {}", name, e)

A bare asyncio.CancelledError is neither an Exception nor a BaseExceptionGroup.

Expected behavior

A single MCP server failing to connect should not terminate the Raven gateway.

Raven should:

  • log the failed MCP server name;
  • preserve useful context about the underlying transport/HTTP failure where possible;
  • skip that MCP server and continue starting the gateway.

External cancellation of the gateway/task should still propagate normally.

Actual behavior

The gateway terminated with a bare cancellation error similar to:

asyncio.exceptions.CancelledError: Cancelled via cancel scope ...

The original HTTP failure/status was not logged, so the underlying authentication rejection was not visible in the gateway log.

After valid runtime authentication was supplied, the MCP connection succeeded:

MCP server 'tanka': connected, 25 tools registered

Environment

  • OS: macOS arm64
  • Python: 3.12.13
  • Raven CLI: v0.1.3
  • MCP SDK: 1.28.1
  • httpx: 0.28.1
  • anyio: 4.14.2
  • MCP transport: streamable HTTP

Logs or screenshots

Please redact all credentials.

Failure:

asyncio.exceptions.CancelledError: Cancelled via cancel scope ...

Successful connection after valid runtime authentication:

MCP server 'tanka': connected, 25 tools registered

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