Skip to content

Bug Report: ClientSession expires after idle periods causing ClosedResourceError with empty error message #2054

@LastRemote

Description

@LastRemote

[Note: I am too lazy, so this issue is also generated by cursor. I did take a look, but I would apologize in advance if there are some minor confusions somewhere]

Environment

  • mcp-haystack version: 0.4.0
  • mcp version: 1.10.1
  • Transport: SSE
  • Environment: Client: same issue whether it's inside a docker or local. Server: from url.

Description

When using MCPTool with SSE transport, the underlying ClientSession expires after approximately 5~10 minutes of idle time, causing tool invocations to fail with anyio.ClosedResourceError. The error is then wrapped in MCPInvocationError but the original error message is lost, resulting in an empty error message.

Root Cause

The issue occurs in the call_tool method at line 237:

result = await self.session.call_tool(tool_name, tool_args)

The ClientSession from the MCP SDK becomes closed after idle periods, but mcp-haystack doesn't detect this condition or attempt to reconnect. When call_tool is invoked on a closed session, it raises anyio.ClosedResourceError(), which gets caught by the generic exception handler at line 248 and wrapped in MCPInvocationError with an empty error message.

Steps to Reproduce

  1. Initialize an MCPTool with SSE transport:
from haystack.tools import MCPTool, SSEServerInfo

tool = MCPTool(
    name="some_tool",
    server_info=SSEServerInfo(url="http://localhost:8000/sse")
)
  1. Use the tool successfully initially
  2. Wait approximately 10 minutes without invoking the tool
  3. Attempt to invoke the tool again

Expected Behavior

  • The tool should either automatically reconnect when the session expires, or
  • Provide a clear error message indicating the session has expired and needs to be reconnected

Actual Behavior

Tool invocation fails with:

MCPInvocationError("Failed to invoke tool 'tool_name' with args: {...} , got error: ")

Note the empty error message after "got error: " - this is because anyio.ClosedResourceError() converts to an empty string.

Technical Details

The current architecture uses _MCPClientSessionManager to maintain a long-running connection in the background, but there's no mechanism to:

  1. Detect when the session becomes closed/expired
  2. Automatically reconnect when this occurs
  3. Provide meaningful error messages when connection issues occur

Proposed Solutions

  1. Automatic Reconnection: Implement session health checking and automatic reconnection when ClosedResourceError is detected
  2. Better Error Handling: Preserve the original error type and message when wrapping in MCPInvocationError
  3. Connection Refresh Method: Provide a method to manually refresh the connection when needed
  4. Keep-Alive Mechanism: Consider implementing periodic keep-alive requests to prevent session expiration

Workaround

Currently, the only workaround is to recreate the MCPTool instance when this error occurs.

Additional Context

This issue is particularly problematic when deploying pipelines as services, where tools may remain idle for extended periods between invocations. The empty error message makes debugging difficult, as it's not immediately clear that the issue is related to session expiration.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions