From a1f85ef2b987a79868193b741f647eb4d3fd9182 Mon Sep 17 00:00:00 2001 From: Alexander Monas Date: Tue, 5 May 2026 00:58:34 +0200 Subject: [PATCH] fix(mcp): retry stale pipe transport failures Treat closed-resource, closed-transport, broken-pipe, and EOF MCP failures as stale session equivalents so the existing reconnect/retry-once path can recover. Add regression coverage for the stale-pipe marker variants.\n\nChecks:\n- python -m py_compile tools/mcp_tool.py tests/tools/test_mcp_tool_session_expired.py\n- python -m pytest tests/tools/test_mcp_tool_session_expired.py -q -o addopts=\n- selected secret scan over touched files --- tests/tools/test_mcp_tool_session_expired.py | 11 +++++++++++ tools/mcp_tool.py | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/tests/tools/test_mcp_tool_session_expired.py b/tests/tools/test_mcp_tool_session_expired.py index 4533282e70..59601ba1c3 100644 --- a/tests/tools/test_mcp_tool_session_expired.py +++ b/tests/tools/test_mcp_tool_session_expired.py @@ -53,6 +53,17 @@ def test_is_session_expired_detects_session_terminated(): assert _is_session_expired_error(RuntimeError("Session terminated")) is True +def test_is_session_expired_detects_stale_pipe_and_closed_transport_variants(): + """Stdio/AnyIO stale-pipe failures usually surface as closed-resource + or broken-pipe text, not an HTTP session-expired JSON-RPC error.""" + from tools.mcp_tool import _is_session_expired_error + assert _is_session_expired_error(RuntimeError("ClosedResourceError")) is True + assert _is_session_expired_error(RuntimeError("closed resource in MCP child")) is True + assert _is_session_expired_error(RuntimeError("transport is closed")) is True + assert _is_session_expired_error(RuntimeError("Broken pipe while writing request")) is True + assert _is_session_expired_error(RuntimeError("End of file from MCP server")) is True + + def test_is_session_expired_is_case_insensitive(): """Match uses lower-cased comparison so servers that emit the message in different cases (SDK formatter quirks) still trigger.""" diff --git a/tools/mcp_tool.py b/tools/mcp_tool.py index b2e0ae802c..5c45f1c4f2 100644 --- a/tools/mcp_tool.py +++ b/tools/mcp_tool.py @@ -1739,6 +1739,12 @@ _SESSION_EXPIRED_MARKERS: tuple = ( "session not found", "unknown session", "session terminated", + "closedresourceerror", + "closed resource", + "transport is closed", + "connection closed", + "broken pipe", + "end of file", )