Skip to content

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

@acsezen

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions