Skip to content

fix: add timeout to MCP tool future.result() to prevent indefinite bl…#840

Open
walker0643 wants to merge 1 commit intoQwenLM:mainfrom
walker0643:fix/mcp-tool-call-timeout
Open

fix: add timeout to MCP tool future.result() to prevent indefinite bl…#840
walker0643 wants to merge 1 commit intoQwenLM:mainfrom
walker0643:fix/mcp-tool-call-timeout

Conversation

@walker0643
Copy link
Copy Markdown

@walker0643 walker0643 commented Mar 21, 2026

Bug: MCPManager tool calls block indefinitely when MCP server hangs

Summary

When an MCP server becomes unresponsive during a tool call, the ToolClass.call() method in mcp_manager.py blocks the calling thread indefinitely. This causes worker threads to remain permanently active, consuming CPU resources until the process is manually killed.

Root Cause

In create_tool_class(), the result of the async tool call future is awaited with no timeout:

future = asyncio.run_coroutine_threadsafe(client.execute_function(tool_name, tool_args), manager.loop)
try:
    result = future.result()  # blocks forever if the coroutine never resolves
    return result

If the underlying MCP server stalls (slow HTTP request, hung subprocess, failed SSE connection, DNS/SSL issue, etc.) the coroutine in execute_function never resolves, and future.result() waits indefinitely. The thread pool worker that called the tool is permanently blocked, and because it holds a reference to the event loop, it also prevents clean shutdown.

Observed Symptoms

  • concurrent.futures thread pool workers stuck in _worker and marked active in process monitors indefinitely
  • Python process pegged at 100% CPU on one or more threads for hours with no forward progress
  • Process does not respond to normal shutdown; requires SIGKILL
  • py-spy dump shows all active threads blocked inside future.result() with no further stack progression

Fix

Add a timeout parameter to future.result() and cancel the future on timeout

…ocking

Increase timeout for MCP tool execution to 60 seconds and handle TimeoutError.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant