Skip to content

Fix timeout reset upon progress notification - #2817

Open
lowlyocean wants to merge 1 commit into
modelcontextprotocol:mainfrom
lowlyocean:fix_progress_notification_timer_reset
Open

lowlyocean wants to merge 1 commit into
modelcontextprotocol:mainfrom
lowlyocean:fix_progress_notification_timer_reset

Conversation

@lowlyocean

@lowlyocean lowlyocean commented Sep 14, 2026

Copy link
Copy Markdown

Motivation and Context

Closes #2816

How Has This Been Tested?

Ran the full test suite

Breaking Changes

No breaking changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

This fixes MCP inspector v2, which claims to automatically reset request timeout when progress notifications are received

@lowlyocean
lowlyocean requested a review from a team as a code owner September 14, 2026 12:27
@changeset-bot

changeset-bot Bot commented Sep 14, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 8e1043a

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Sep 14, 2026

Copy link
Copy Markdown

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/@modelcontextprotocol/client@2817

@modelcontextprotocol/codemod

npm i https://pkg.pr.new/@modelcontextprotocol/codemod@2817

@modelcontextprotocol/core

npm i https://pkg.pr.new/@modelcontextprotocol/core@2817

@modelcontextprotocol/server

npm i https://pkg.pr.new/@modelcontextprotocol/server@2817

@modelcontextprotocol/server-legacy

npm i https://pkg.pr.new/@modelcontextprotocol/server-legacy@2817

@modelcontextprotocol/express

npm i https://pkg.pr.new/@modelcontextprotocol/express@2817

@modelcontextprotocol/fastify

npm i https://pkg.pr.new/@modelcontextprotocol/fastify@2817

@modelcontextprotocol/hono

npm i https://pkg.pr.new/@modelcontextprotocol/hono@2817

@modelcontextprotocol/node

npm i https://pkg.pr.new/@modelcontextprotocol/node@2817

commit: 8e1043a

@koriyoshi2041 koriyoshi2041 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The startTime reset here changes maxTotalTimeout from an absolute request lifetime cap into another inactivity window. That is why all 12 protocol:timeout:max-total E2E variants time out in Node 20/22/24: recurring progress can now postpone the maximum indefinitely. The inactivity timer already resets via clearTimeout + setTimeout; startTime needs to remain the original request timestamp. Please remove the info.startTime = Date.now() assignment and keep/add a regression where progress extends the ordinary timeout but the request still rejects at the original maxTotalTimeout deadline.

@lowlyocean

lowlyocean commented Sep 20, 2026

Copy link
Copy Markdown
Author

@koriyoshi2041 What is the correct fix for this behavior? Are you able to reproduce it? What is the maxTotalTimeout, because currently I am seeing the MCP inspector client always report an error after 60s despite receiving progress notifications.

@koriyoshi2041

Copy link
Copy Markdown

I can reproduce it: all three test-e2e jobs fail the protocol:timeout:max-total cases on this head. maxTotalTimeout is caller-supplied; in the conformance tests it is 150 ms, while Inspector’s 60 s is likely its own configured value.

The intended split is: timeout is the inactivity window and is reset by progress; maxTotalTimeout is an absolute cap measured from the original request start. clearTimeout(info.timeoutId) + setTimeout(info.onTimeout, info.timeout) already extends the inactivity window. Resetting info.startTime makes the absolute cap slide too, so recurring progress can keep the request alive indefinitely.

The fix here is to remove info.startTime = Date.now() and keep a regression where progress prevents the ordinary timeout but the request still rejects at the original total deadline. If Inspector should allow more than 60 s overall, it needs to pass a larger maxTotalTimeout (or omit that cap) separately.

@lowlyocean

lowlyocean commented Sep 22, 2026

Copy link
Copy Markdown
Author

Sorry, I didn't mean can you reproduce the e2e test failures introduced by this PR.

I meant, can you reproduce the error reported in the linked issue modelcontextprotocol/inspector#2314 ( Inspector receieves progress notifications but times out after 60s).

Since the protocol supports resetting the 60s default request timeout on progress notifications , then Inspector should not be using a maxTotalTime of 60s (because it defeats the reset).

@koriyoshi2041

Copy link
Copy Markdown

Thanks for clarifying. I have not reproduced the original Inspector #2314 report yet.

I checked the current Inspector path instead. InspectorClient.getRequestOptions() passes timeout plus resetTimeoutOnProgress: true, and does not pass maxTotalTimeout. Its integration suite also has a Streamable HTTP case with timeout: 350 where four progress notifications extend the request until completion. So the reported 60 s failure cannot be explained by an Inspector maxTotalTimeout: 60000 on current main, and resetting the SDK's startTime would still change the separate absolute-cap contract.

The useful next reproduction is therefore version/transport-specific: run the #2314 server pattern against Inspector 2.2.0 and current main, capture the actual RequestOptions, and determine whether progress reaches the SDK callback on the failing Web/TUI path. The issue does not include a runnable server fixture, so I don't want to claim that result without one. If you have the server or a minimal delay/progress schedule used for #2314, I can test that exact path.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[v2] _resetTimeout never updates startTime, so totalElapsed keeps accumulating from the original

2 participants