Skip to content

fix(everything): stop long-running operation when the request is cancelled - #4847

Open
Ewertonslv wants to merge 1 commit into
modelcontextprotocol:mainfrom
Ewertonslv:fix/everything-long-running-cancellation
Open

Ewertonslv wants to merge 1 commit into
modelcontextprotocol:mainfrom
Ewertonslv:fix/everything-long-running-cancellation

Conversation

@Ewertonslv

Copy link
Copy Markdown

Description

trigger-long-running-operation waited on plain setTimeout promises and never checked extra.signal. When a client cancelled the request, the loop kept running to the end and kept sending progress notifications. On stdio the pending timers held the process open, which is what delays shutdown in #4846.

The wait now uses setTimeout from node:timers/promises with the request's abort signal. When the request is cancelled, the pending timer is cleared and the handler rejects immediately, so no further steps or progress notifications run.

Fixes #4846

Server Details

  • Server: everything
  • Changes to: tools (trigger-long-running-operation)

Motivation and Context

The Everything server is the reference for how MCP features should behave. A long-running tool that ignores cancellation shows the wrong pattern, and it keeps stdio clients from shutting down cleanly after a cancel.

How Has This Been Tested?

Added should stop when the request is cancelled to src/everything/__tests__/tools.test.ts. It starts the operation with an AbortController signal, aborts after 50 ms, and asserts that the handler settles within 500 ms without sending any progress notification.

  • Without the fix: fails with expected 'still running' to be 'stopped'.
  • With the fix: passes.
  • npx vitest run __tests__/tools.test.ts: 62 passed.
  • npx tsc --noEmit: clean.

I did not test it against an LLM client.

Breaking Changes

None. Calls that are not cancelled behave the same as before.

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 Protocol Documentation
  • My changes follows MCP security best practices
  • I have updated the server's README accordingly (not needed, behaviour on cancel only)
  • I have tested this with an LLM client
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling

…elled

trigger-long-running-operation waited on plain setTimeout promises and
never looked at extra.signal, so after a client cancelled the request the
loop kept running and sending progress notifications. On stdio this held
the process open and delayed shutdown.

Wait with node:timers/promises setTimeout and pass the request signal, so
the pending timer is cleared and the handler rejects as soon as the
request is aborted.

Fixes modelcontextprotocol#4846

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.

everything: cancelled long-running operation delays stdio shutdown

1 participant