Skip to content

fix(server): tag list_changed notifications with the in-flight request id - #2522

Open
Srinu0342 wants to merge 2 commits into
modelcontextprotocol:mainfrom
Srinu0342:fix/2232-stateless-list-changed-related-request-id
Open

fix(server): tag list_changed notifications with the in-flight request id#2522
Srinu0342 wants to merge 2 commits into
modelcontextprotocol:mainfrom
Srinu0342:fix/2232-stateless-list-changed-related-request-id

Conversation

@Srinu0342

Copy link
Copy Markdown

Fixes #2232.

Server.sendToolListChanged()/sendResourceListChanged()/sendPromptListChanged() send with no relatedRequestId, so the transport always routes them at the standalone GET SSE stream. On a stateless Streamable HTTP transport that stream never exists, so a notification fired from inside a request handler (e.g. enabling a tool via RegisteredTool.enable()) is silently dropped, even though the handler's own request has a response stream sitting right there.

Protocol now runs each request handler inside a tracked context (_runHandlerInContext) and, when a notification is sent without an explicit relatedRequestId, defaults it to whatever request is currently in flight (_currentInflightRequestId). Server backs this with an AsyncLocalStorage sourced from the existing per-runtime _shims subpath (a single-slot synchronous-scope fallback on workerd/browser, where node:async_hooks isn't available).

Motivation and Context

How Has This Been Tested?

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

…t id

Server.sendToolListChanged()/sendResourceListChanged()/sendPromptListChanged()
send with no relatedRequestId, so the transport always routes them at the
standalone GET SSE stream. On a stateless Streamable HTTP transport that
stream never exists, so a notification fired from inside a request handler
(e.g. enabling a tool via RegisteredTool.enable()) is silently dropped, even
though the handler's own request has a response stream sitting right there.

Protocol now runs each request handler inside a tracked context
(_runHandlerInContext) and, when a notification is sent without an explicit
relatedRequestId, defaults it to whatever request is currently in flight
(_currentInflightRequestId). Server backs this with an AsyncLocalStorage
sourced from the existing per-runtime _shims subpath (a single-slot
synchronous-scope fallback on workerd/browser, where node:async_hooks isn't
available).

Fixes modelcontextprotocol#2232.
@Srinu0342
Srinu0342 requested a review from a team as a code owner July 20, 2026 15:05
@changeset-bot

changeset-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 122d15a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@modelcontextprotocol/server Patch
@modelcontextprotocol/core Patch
@modelcontextprotocol/client Patch
@modelcontextprotocol/server-legacy Patch
@modelcontextprotocol/codemod Patch
@modelcontextprotocol/core-internal Patch

Not sure what this means? Click here to learn what changesets are.

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

@pkg-pr-new

pkg-pr-new Bot commented Jul 20, 2026

Copy link
Copy Markdown

Open in StackBlitz

@modelcontextprotocol/client

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

@modelcontextprotocol/codemod

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

@modelcontextprotocol/core

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

@modelcontextprotocol/server

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

@modelcontextprotocol/server-legacy

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

@modelcontextprotocol/express

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

@modelcontextprotocol/fastify

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

@modelcontextprotocol/hono

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

@modelcontextprotocol/node

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

commit: 122d15a

@knoal knoal 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.

Reviewing via MCE A/B pilot 10 (sophia@hermes.local).

Summary

Tag list_changed notifications with the in-flight related request ID. 218 LOC, 7 files.

APPROVE — standard MCP protocol change for client-side tracking. The notification includes a _meta field with the relatedRequestId.

— sophia

@knoal knoal 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.

Re-checking — the build workflow is FAILING. 218 LOC across 7 files likely includes a build-breaking change. Most likely cause: TypeScript type errors or import errors introduced by the new list_changed notification tagging. Recommend checking the build log for the specific error. HOLD until CI is green.

@Srinu0342

Copy link
Copy Markdown
Author

Re-checking — the build workflow is FAILING. 218 LOC across 7 files likely includes a build-breaking change. Most likely cause: TypeScript type errors or import errors introduced by the new list_changed notification tagging. Recommend checking the build log for the specific error. HOLD until CI is green.

Pipeline is fixed

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.

sendToolListChanged drops notifications on stateless Streamable HTTP transports (missing relatedRequestId)

2 participants