fix(server): keep the registry key current when a handle is renamed - #2724
fix(server): keep the registry key current when a handle is renamed#2724YatsukBogdan1 wants to merge 1 commit into
Conversation
The `update` closure for prompts, resources and resource templates captured the registration key and never reassigned it, so after one rename it pointed at a key the entry no longer occupied. - `remove()` became a silent no-op: it deletes the captured key, which is already vacant, leaving the entry listed and callable while `list_changed` still fires. - A second rename left the intermediate key registered, aliasing one entry under two live names. - Renaming back to the original name silently did nothing, because the `updates.name !== name` guard compared against the stale value. `RegisteredTool` already tracked the current key and is unchanged.
🦋 Changeset detectedLatest commit: 1a8b5d2 The changes in this PR will be included in the next version bump. This PR includes changesets to release 6 packages
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 |
@modelcontextprotocol/client
@modelcontextprotocol/codemod
@modelcontextprotocol/core
@modelcontextprotocol/server
@modelcontextprotocol/server-legacy
@modelcontextprotocol/express
@modelcontextprotocol/fastify
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
koriyoshi2041
left a comment
There was a problem hiding this comment.
Checked the exact head locally: the integration suite passes 374/374. The mutable key now follows each resource URI / template name / prompt name change, so repeated renames (including renaming back) and remove() target the live registry entry.
One coordination note: #2114 appears to cover the same registry-key bookkeeping on an older branch, including tools. This PR is narrower and has current-main integration coverage, but the overlap is worth resolving before merge.
Fixes #2723
Summary
The
updateclosure for prompts, resources and resource templates captured the registration key and never reassigned it, so after one rename it pointed at a key the entry no longer occupied.delete this._registeredX[key]then hit a vacant slot and left the live entry alone.RegisteredToolalready tracks the current key (L871); this brings the other three in line.Changes
Three sites in
packages/server/src/server/mcp.tsreassign the key binding after moving the entry — the same shape as the existing tool path.Testing
Three tests in
test/integration/test/server/mcp.test.ts, one per affected primitive, asserting through a connected client. Each renames twice, checks only the current key is listed, then callsremove()and checks the list is empty.With the fix reverted, all three fail:
Also run green:
@modelcontextprotocol/server(481), integration (374), e2e (2639 + 147 expected-fail), lint and typecheck.Notes for review
createPromptHandler(name, …)at L788 is re-invoked when a schema or callback update regenerates the handler, and usesnamein its validation error text. A prompt renamed and then given a new schema now reports the current name instead of the registration name.remove(), the binding still holds the last live key, soupdate({ name })on a removed handle resurrects it. Left alone to keep this focused.v1.xhas the same defect on all four primitives including tools; happy to open a backport once this lands.