Skip to content

fix(client): keep resultType through decode so skills/directory results validate - #2791

Draft
tiagovilasboas wants to merge 4 commits into
modelcontextprotocol:mainfrom
tiagovilasboas:fix/client-resulttype-stripped-before-schema-2789
Draft

fix(client): keep resultType through decode so skills/directory results validate#2791
tiagovilasboas wants to merge 4 commits into
modelcontextprotocol:mainfrom
tiagovilasboas:fix/client-resulttype-stripped-before-schema-2789

Conversation

@tiagovilasboas

@tiagovilasboas tiagovilasboas commented Sep 11, 2026

Copy link
Copy Markdown

Problem

Client.request() rejects every spec-conforming skills/list, skills/get, and resources/directory/read result with:

Invalid result for skills/list: resultType: Invalid input: expected "complete"

even when the server sent resultType: "complete".

decodeResult() validates the 2026 discriminator and strips it as part of complete-result lifting. Caller schemas that still model the wire envelope (Inspector ModernListSkillsResultSchema, ModernGetSkillEnvelopeSchema, ModernDirectoryReadResultSchema) then re-require resultType: "complete" against the already-lifted object. No server payload can pass.

Core list methods (tools/list, resources/list, …) are unaffected because their post-lift schemas omit resultType.

Solution

Keep codec complete-result lifting intact. After the lifted object fails the caller/registry schema, retry once with the already-validated resultType: "complete" restored. Post-lift schemas that omit the field (core list methods, strict EmptyResult) still succeed on the first pass.

Test plan

  • skills/list accepts a spec-conforming { resultType: "complete", ttlMs, cacheScope, skills } payload
  • skills/get accepts a spec-conforming { resultType: "complete", skill } payload
  • resources/directory/read accepts a spec-conforming { resultType: "complete", resources } payload
  • An actually invalid skills/list body still fails after the discriminator is restored
  • pnpm --filter @modelcontextprotocol/core-internal exec vitest run test/shared/extensionResultType.test.ts test/shared/rawResultTypeFirst.test.ts — 15/15 passed
  • pnpm --filter @modelcontextprotocol/client exec vitest run test/client/skillsDirectoryResultType.test.ts — 3/3 passed
  • Full @modelcontextprotocol/core-internal suite — 1461 passed
  • Full @modelcontextprotocol/client suite — 890 passed

Fixes #2789

decodeResult() already checks resultType === "complete" and strips it
as part of complete-result lifting. Caller schemas that still model the
2026 wire envelope (Inspector skills/list, skills/get, and
resources/directory/read) then reject the lifted object because
resultType is gone.

Retry the caller/registry schema with the already-validated
discriminator restored only when the lifted object fails, so post-lift
schemas that omit the field keep working unchanged.

Fixes modelcontextprotocol#2789

Co-authored-by: Tiago Vilas Boas <tcarvalhovb@gmail.com>
…sults

Regression coverage for modelcontextprotocol#2789: skills/list, skills/get, and
resources/directory/read must succeed when the server sends a
resultType: "complete" payload and the caller schema still requires
that discriminator (the Inspector Modern* envelopes).

Co-authored-by: Tiago Vilas Boas <tcarvalhovb@gmail.com>
@changeset-bot

changeset-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2326041

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

This PR includes changesets to release 6 packages
Name Type
@modelcontextprotocol/client Patch
@modelcontextprotocol/codemod Patch
@modelcontextprotocol/core Patch
@modelcontextprotocol/server-legacy Patch
@modelcontextprotocol/server 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

Keep eslint import/no-duplicates and Prettier happy on the modelcontextprotocol#2789
validation helper and its protocol-level regression.

Co-authored-by: Tiago Vilas Boas <tcarvalhovb@gmail.com>
@pkg-pr-new

pkg-pr-new Bot commented Sep 11, 2026

Copy link
Copy Markdown

Open in StackBlitz

@modelcontextprotocol/client

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

@modelcontextprotocol/codemod

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

@modelcontextprotocol/core

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

@modelcontextprotocol/server

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

@modelcontextprotocol/server-legacy

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

@modelcontextprotocol/express

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

@modelcontextprotocol/fastify

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

@modelcontextprotocol/hono

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

@modelcontextprotocol/node

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

commit: 2326041

Record the modelcontextprotocol#2789 Client.request() skills/directory validation fix as a
patch on @modelcontextprotocol/client.

Co-authored-by: Tiago Vilas Boas <tcarvalhovb@gmail.com>
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.

skills/list, skills/get, resources/directory/read always fail: codec strips resultType before re-validating it

1 participant