mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-31 22:57:14 +00:00
fix(mcp): validate tool call timeout config
This commit is contained in:
@@ -315,8 +315,12 @@ class RuntimeMCPSession:
|
|||||||
def _parse_tool_call_timeout(self, value: typing.Any) -> float:
|
def _parse_tool_call_timeout(self, value: typing.Any) -> float:
|
||||||
"""Return a safe tool-call timeout; zero explicitly disables it."""
|
"""Return a safe tool-call timeout; zero explicitly disables it."""
|
||||||
try:
|
try:
|
||||||
timeout = float(value)
|
timeout = -1 if isinstance(value, bool) else float(value)
|
||||||
except (TypeError, ValueError):
|
if timeout > 0:
|
||||||
|
# Validate the exact conversion used for each call here, so a
|
||||||
|
# finite-but-enormous manual config cannot fail at invocation.
|
||||||
|
timedelta(seconds=timeout)
|
||||||
|
except (TypeError, ValueError, OverflowError):
|
||||||
timeout = -1
|
timeout = -1
|
||||||
|
|
||||||
if not math.isfinite(timeout) or timeout < 0:
|
if not math.isfinite(timeout) or timeout < 0:
|
||||||
@@ -1035,7 +1039,9 @@ class RuntimeMCPSession:
|
|||||||
def _is_tool_call_timeout(exc: BaseException) -> bool:
|
def _is_tool_call_timeout(exc: BaseException) -> bool:
|
||||||
"""Recognize the MCP SDK's per-request timeout without retrying it."""
|
"""Recognize the MCP SDK's per-request timeout without retrying it."""
|
||||||
return any(
|
return any(
|
||||||
isinstance(leaf, McpError) and leaf.error.code == httpx.codes.REQUEST_TIMEOUT
|
isinstance(leaf, McpError)
|
||||||
|
and leaf.error.code == httpx.codes.REQUEST_TIMEOUT
|
||||||
|
and leaf.error.message.startswith('Timed out while waiting for response')
|
||||||
for leaf in RuntimeMCPSession._iter_exception_leaves(exc)
|
for leaf in RuntimeMCPSession._iter_exception_leaves(exc)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ async def test_invoke_mcp_tool_timeout_is_not_retried_and_session_remains_usable
|
|||||||
assert call_tool.await_count == 2
|
assert call_tool.await_count == 2
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('invalid_timeout', [-1, float('inf'), 'not-a-number'])
|
@pytest.mark.parametrize('invalid_timeout', [-1, float('inf'), 1e300, True, 'not-a-number'])
|
||||||
def test_invalid_tool_call_timeout_falls_back_to_default(invalid_timeout):
|
def test_invalid_tool_call_timeout_falls_back_to_default(invalid_timeout):
|
||||||
ap = _app()
|
ap = _app()
|
||||||
session = RuntimeMCPSession(
|
session = RuntimeMCPSession(
|
||||||
|
|||||||
Reference in New Issue
Block a user