fix(mcp): report configured timeout in MCP call errors

Track elapsed wall time in _run_on_mcp_loop, cancel the in-flight future when a timeout expires, and raise a descriptive TimeoutError that includes the elapsed and configured timeout. Add regression coverage for the new timeout diagnostics.
This commit is contained in:
Mason James 2026-04-15 12:59:10 -04:00 committed by Teknium
parent 25187ca05c
commit 80548f9a4f
2 changed files with 45 additions and 2 deletions

View file

@ -547,6 +547,43 @@ class TestRunOnMCPLoopInterrupts:
mcp_mod._mcp_loop = old_loop
mcp_mod._mcp_thread = old_thread
def test_timeout_reports_elapsed_and_configured_timeout(self):
import tools.mcp_tool as mcp_mod
loop = asyncio.new_event_loop()
thread = threading.Thread(target=loop.run_forever, daemon=True)
thread.start()
cancelled = threading.Event()
async def _slow_call():
try:
await asyncio.sleep(5)
return "done"
except asyncio.CancelledError:
cancelled.set()
raise
old_loop = mcp_mod._mcp_loop
old_thread = mcp_mod._mcp_thread
mcp_mod._mcp_loop = loop
mcp_mod._mcp_thread = thread
try:
with pytest.raises(TimeoutError, match=r"MCP call timed out after .*configured timeout: 0.2s"):
mcp_mod._run_on_mcp_loop(_slow_call(), timeout=0.2)
deadline = time.time() + 2
while time.time() < deadline and not cancelled.is_set():
time.sleep(0.05)
assert cancelled.is_set()
finally:
loop.call_soon_threadsafe(loop.stop)
thread.join(timeout=2)
loop.close()
mcp_mod._mcp_loop = old_loop
mcp_mod._mcp_thread = old_thread
# ---------------------------------------------------------------------------
# Tool registration (discovery + register)