-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Description
When a client (e.g., Claude) cancels a timed‑out call, FastMCP logs a validation warning and the connection drops. Timeouts are surfaced as unhandled exceptions rather than clean tool errors.
Client Symptoms
- Tool calls hang then fail; on timeout, Claude sends
notifications/cancelled
,
after which the session sometimes disconnects. - Users see intermittent “disconnected” or “no response” after long OpenAPI tool
calls.
Server Behavior
- Logs show duplicate “Processing request” lines, then warnings like: “Failed to
validate notification: RequestResponder must be used as a context manager”. - Timeout exceptions (asyncio/httpx) bubble through OpenAPI tools and are not tr
anslated into ToolErrors. - On cancellation, the SDK attempts
RequestResponder.cancel()
on a responder t
hat was never entered, triggering the warning and session instability.
Observations
-
FastMCP’s OpenAPI tool generation produces callables that do not accept
/useContext
and therefore do not run underRequestResponder
. -
Cancellation notifications from the client can’t be matched to an active respo
nder; FastMCP logs a warning and the transport becomes unstable. -
Timeouts are not handled by the generated tools, so exceptions propagate and c
an break the MCP session. -
Use FastMCP OpenAPI-generated tool for a slow API call (HTTP transport or stdi
o). -
Configure client with a shorter tool timeout (e.g., 20–30s).
-
Observe: at timeout, client sends
notifications/cancelled
; FastMCP logs “Req
uestResponder must be used as a context manager” and the session may disconnect.
Expected vs Actual
- Expected: Tool runs under
RequestResponder
; cancellation cleanly cancels the
tool; timeout surfaces as a ToolError without disconnecting. - Actual: No responder context; cancellation triggers validation warning; timeou
ts raise exceptions; session may disconnect.
Proposed Fix (FastMCP)
- Ensure OpenAPI-generated tools execute within
RequestResponder
:- Generated functions should accept
ctx: Context
and usewith ctx.request_r esponder() as rr:
around the call. - Map
notifications/cancelled
to the active responder sorr.cancel()
clean
ly aborts the call. - Catch timeout/cancellation (
asyncio.CancelledError
, httpx timeouts) and re
turn a proper ToolError (not a raw exception), preserving the MCP session.
- Generated functions should accept
- Optionally, centralize timeout handling in the OpenAPITool layer (wrap
__call __
) to convert timeouts to ToolErrors consistently.
Temporary Workarounds (confirmed working)
- Add a logging filter to suppress the specific cancellation warning; prevents d
isconnect but is a band‑aid. - Wrap
OpenAPITool.__call__
to catch timeouts (asyncio.TimeoutError
,httpx. TimeoutException
,ReadTimeout
,ConnectTimeout
) and return a structured erro
r instead of raising. - Increase client and server read timeouts (e.g., 60–180s) for legitimately long
calls.
Environment
- FastMCP with experimental OpenAPI parser enabled (
FASTMCP_EXPERIMENTAL_ENABLE _NEW_OPENAPI_PARSER=true
). - Server runs both stdio and HTTP transports; issue reproduced in both.
- Client: Claude Desktop sending
notifications/cancelled
after tool timeout.
Example Code
Version Information
2.12