From 7677d1a288582ab4cf9840710a20450360c809f6 Mon Sep 17 00:00:00 2001 From: douxt <8429023+douxt@users.noreply.github.com> Date: Fri, 17 Jul 2026 10:00:13 +0800 Subject: [PATCH] fix(mcp): add 30s timeout to prevent MCP tool calls from hanging indefinitely Previously, MCP tool calls via call_tool() had no timeout, so a hung MCP server would block the entire session indefinitely (exacerbated by concurrency.session=1). This wraps the call in asyncio.timeout(30) and raises an Exception on expiry, letting the LLM recover gracefully. Closes #2339 --- src/langbot/pkg/provider/tools/loaders/mcp.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/langbot/pkg/provider/tools/loaders/mcp.py b/src/langbot/pkg/provider/tools/loaders/mcp.py index e8fc5b1bf..87f04b997 100644 --- a/src/langbot/pkg/provider/tools/loaders/mcp.py +++ b/src/langbot/pkg/provider/tools/loaders/mcp.py @@ -968,7 +968,12 @@ class RuntimeMCPSession: raise Exception('MCP session is not connected') try: - result = await self.session.call_tool(tool_name, arguments) + async with asyncio.timeout(30): + result = await self.session.call_tool(tool_name, arguments) + except TimeoutError as e: + raise Exception( + f"MCP tool '{tool_name}' on server '{self.server_name}' timed out after 30 seconds" + ) from e except Exception as e: if attempt == 0 and self._is_session_terminated(e): self.ap.logger.warning(