Skip to content

bug(mcp): Unhandled exception 'Event loop is closed' on shutdown with HTTP MCP servers #2537

Description

@acsezen

Summary

When an HTTP MCP server (StreamableHTTP transport) is configured and the session ends, the following error is printed to stderr:

Unhandled exception in event loop:
  File ".../httpx/_client.py", line 1985, in aclose
    await self._transport.aclose()
  ...
  File ".../asyncio/base_events.py", line 762, in call_soon
    self._check_closed()
  File ".../asyncio/base_events.py", line 520, in _check_closed
    raise RuntimeError('Event loop is closed')

Exception Event loop is closed

Root Cause

When _stop_mcp_loop() stops and closes the MCP background event loop, the httpx/httpcore async transports held by the MCP SDK's streamablehttp_client eventually fire __del__ finalizers. These finalizers call call_soon() on the now-dead loop to schedule connection teardown. asyncio catches the resulting RuntimeError and routes it to the loop's exception handler, which by default prints the error to stderr.

The connection teardown is a no-op at this point (the loop is gone) — the error is purely cosmetic noise.

Steps to Reproduce

  1. Configure an HTTP MCP server in ~/.hermes/config.yaml
  2. Start a session (the MCP server connects via StreamableHTTP)
  3. Exit the session
  4. Observe Unhandled exception in event loop: Event loop is closed on stderr

Impact

Cosmetic only — no data loss, no broken functionality. However it is alarming and may mask real errors in output.

Related

Same class of async shutdown race previously fixed in:

  • model_tools.py (ab6abc2) — persistent event loop for tool handlers
  • agent/auxiliary_client.py — stale async client cache invalidation

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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