Skip to content

Fix ClientSession error handling: add transport_exception_handler callback (Fixes #1401) - #3369

Closed
mukktinaadh wants to merge 1 commit into
modelcontextprotocol:mainfrom
mukktinaadh:main
Closed

Fix ClientSession error handling: add transport_exception_handler callback (Fixes #1401)#3369
mukktinaadh wants to merge 1 commit into
modelcontextprotocol:mainfrom
mukktinaadh:main

Conversation

@mukktinaadh

Copy link
Copy Markdown

Summary

This PR addresses issue #1401 by adding a dedicated transport_exception_handler callback to ClientSession and Client classes. This allows users to properly handle transport-level exceptions (timeouts, connection errors, etc.) instead of having them silently swallowed by the default message_handler.

Changes

Core Changes (src/mcp/client/session.py)

  • Added new TransportExceptionHandlerFnT protocol for the callback type
  • Added transport_exception_handler parameter to ClientSession.__init__
  • Updated _deliver_stream_exception to use the new handler with fallback to message_handler for backwards compatibility
  • Modified _default_message_handler to log transport exceptions at ERROR level (so users are aware of issues even without a custom handler)

Client Integration (src/mcp/client/client.py)

  • Added transport_exception_handler field to Client dataclass
  • Updated _build_session to pass the handler to ClientSession

Tests (tests/client/test_session.py)

  • Added test_transport_exception_handler_receives_exceptions_separately_from_message_handler: verifies transport exceptions go to the dedicated handler while server notifications go to message_handler
  • Added test_transport_exception_handler_fallback_to_message_handler: verifies backwards compatibility when no dedicated handler is provided

Usage Example

from mcp.client import Client

async def handle_transport_error(exc: Exception):
    # User can now properly handle transport errors
    logger.error(f"Transport error: {exc}")
    # Could trigger reconnection, alerting, etc.

async with Client("http://localhost:8000/mcp", transport_exception_handler=handle_transport_error) as client:
    result = await client.call_tool("my_tool", {"arg": "value"})

Backwards Compatibility

  • Existing code using message_handler continues to work unchanged
  • When no transport_exception_handler is provided, transport exceptions fall back to message_handler
  • The default message_handler now logs transport exceptions at ERROR level

Testing

All existing tests pass (5744 tests). Two new tests added for the new functionality.

…lback

- Add new  callback to ClientSession and Client
  for handling transport-level exceptions (timeouts, connection errors)
- Update  to use the new handler with fallback to
   for backwards compatibility
- Make default  log transport exceptions at ERROR level
- Add tests for the new callback and fallback behavior

Fixes modelcontextprotocol#1401
@github-actions github-actions Bot added the missing-issue-link Auto-closed: PR needs a linked issue assigned to its author (see CONTRIBUTING.md) label Aug 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for the contribution. This repository only keeps pull requests open when they're linked to an issue that a maintainer has assigned to the author — CONTRIBUTING.md explains why and how we work. This PR has been closed for now because its description doesn't yet link an open issue in this repository (with Fixes #123 or similar).

If there isn't an issue for this yet, please open one — a clear description of the problem is genuinely the most useful thing for us. Then add Fixes #<number> to this PR's description. If a maintainer would like the change as a PR from you, they'll assign you to the issue and this PR will reopen automatically.

There's no need to open a new PR — this one will be reopened. While it's closed, please push any updates as new commits rather than force-pushing, since GitHub can't reopen a PR whose branch has been rewritten.

Maintainers: reopening this PR, removing the missing-issue-link label, or adding bypass-issue-check bypasses the check.

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

Labels

missing-issue-link Auto-closed: PR needs a linked issue assigned to its author (see CONTRIBUTING.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant