fix(mcp): add onprogress callback so resetTimeoutOnProgress actually works#21701
fix(mcp): add onprogress callback so resetTimeoutOnProgress actually works#21701techtoboggan wants to merge 1 commit intoanomalyco:devfrom
Conversation
…allTool
resetTimeoutOnProgress: true is set in convertMcpTool, but the TypeScript
MCP SDK (@modelcontextprotocol/sdk) only injects _meta.progressToken into
the outgoing JSON-RPC request when an onprogress callback is provided — not
when resetTimeoutOnProgress alone is set:
// sdk/src/shared/protocol.ts
if (options?.onprogress) { // ← ONLY path that injects progressToken
this._progressHandlers.set(messageId, options.onprogress);
jsonrpcRequest.params = { ..., _meta: { progressToken: messageId } };
}
this._setupTimeout(messageId, timeout, ..., options?.resetTimeoutOnProgress);
Without a progressToken in the request, MCP server progress notifications
cannot match the pending request (the SDK matches by params.progressToken →
messageId), so _resetTimeout is never called, and the 60s default timeout
fires regardless of how often the server pings.
Fix: pass a no-op onprogress: () => {} to force progressToken injection.
The SDK then auto-resets the per-request timer on every incoming progress
notification, keeping long-running HITL tool calls alive indefinitely.
References:
- MCP TS SDK issue: modelcontextprotocol/typescript-sdk#245
- Root cause analysis: https://github.com/techtoboggan/openwebgoggles/blob/next-version/CHANGELOG.md
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 2 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
|
The following comment was made by an LLM, it may be inaccurate: Potential Duplicate Found: PR #14501: "fix: add onprogress callback to MCP tool calls for timeout renewal" Why it's related: This PR appears to address the exact same issue — adding an You should check PR #14501's status (merged, closed, or still open) to determine if this is truly a duplicate or if it needs to be closed in favor of #21701. |
Problem
convertMcpToolpassesresetTimeoutOnProgress: truetoclient.callTool(), but the TypeScript MCP SDK (@modelcontextprotocol/sdk@1.27.1) only injects_meta.progressTokeninto the outgoing JSON-RPC request when anonprogresscallback is provided — not whenresetTimeoutOnProgressalone is set:Without
progressTokenin the request, MCP servers cannot match theirnotifications/progressresponses to the pending call. The SDK's_onprogresshandler matches byparams.progressToken → messageId— no token means no match, means_resetTimeoutis never called, and the 60-secondDEFAULT_REQUEST_TIMEOUT_MSECfires regardless of how often the server sends progress pings.Symptom: long-running HITL tools (tools that open a browser window and wait for a human) time out with
-32001after exactly 60 seconds even though the server is actively sending progress notifications.Related SDK issue: modelcontextprotocol/typescript-sdk#245
Fix
Pass a no-op
onprogress: () => {}callback. This forces the SDK to injectprogressTokeninto the request_meta, which allows incomingnotifications/progressto be matched and_resetTimeoutto fire — makingresetTimeoutOnProgress: trueactually do what it says.Impact
onprogress: () => {}is a no-op callback that doesn't affect anything else.Longer-term
A proper fix in the SDK itself would be to inject
progressTokenwheneverresetTimeoutOnProgress: trueis set, not only whenonprogressis provided. A PR for that is open at https://github.com/modelcontextprotocol/typescript-sdk — but this 1-line fix works today without waiting on upstream.