Skip to content

fix(server,client): non-SEP draft spec conformance (eager list handlers, pagination docs, path-sanitization note)#2269

Open
mattzcarey wants to merge 1 commit into
mainfrom
fix/draft-spec-non-sep-changes
Open

fix(server,client): non-SEP draft spec conformance (eager list handlers, pagination docs, path-sanitization note)#2269
mattzcarey wants to merge 1 commit into
mainfrom
fix/draft-spec-non-sep-changes

Conversation

@mattzcarey

@mattzcarey mattzcarey commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Implements the non-SEP changes from the 2025-11-25 → draft spec diff tracked in #2202. Per-item breakdown:

(a) Deterministic tools/list ordering — already compliant, tests added

Servers SHOULD return tools in a deterministic order (i.e., the same ordering across requests when the underlying set of tools has not changed). — draft server/tools.mdx

McpServer lists tools via Object.entries(this._registeredTools), which is stable insertion order — no code change needed. Added regression tests (identical order across repeated tools/list calls, and stability across disable()/enable() toggles, including that re-enabling restores insertion position rather than appending) plus a short comment on the list handler documenting the guarantee.

(b) List responses when capability declared — the only behavioral change

Servers that declare the tools capability MUST respond to tools/list requests with the set of tools currently available to the requesting client. This set MAY be empty… — draft server/tools.mdx (equivalent language for resources/prompts)

Previously, McpServer installed list/call handlers lazily on first registerTool/registerResource/registerPrompt, so a server constructed with capabilities: { tools: {} } and zero registrations answered tools/list with -32601 (Method not found). The constructor now eagerly installs handlers for every primitive capability declared in ServerOptions.capabilities:

  • toolstools/list returns []; tools/call for an unknown tool returns -32602
  • resourcesresources/list / resources/templates/list return []; resources/read returns resource-not-found
  • promptsprompts/list returns []; prompts/get returns -32602

Undeclared capabilities with no registrations still return -32601, and lazy installation on first registration is unchanged for servers that don't declare capabilities up front. Low-level Server users remain responsible for their own handlers — documented on ServerOptions.capabilities.

Happy to split this item into its own PR if you'd prefer to keep behavioral and docs-only changes separate.

(c) Empty-string cursor — doc examples fixed

Don't make any determination based on cursor value other than whether a non-null value was provided (e.g. an empty string is a valid cursor and thus MUST NOT be treated as the end of results) — draft server/utilities/pagination.mdx

The SDK has no runtime pagination loop, but the pagination examples in client.examples.ts (and the JSDoc on listTools/listPrompts/listResources generated from them via sync:snippets) used } while (cursor);, which stops on an empty-string cursor. Fixed to while (cursor !== undefined) and re-ran pnpm sync:snippets.

(d) Resource path sanitization — docs only

Servers MUST sanitize file paths to prevent directory traversal attacks when serving file:// resources — draft server/resources.mdx (Security Considerations)

The SDK serves no files itself; added a security note to the Resources section of docs/server.md about sanitizing user-influenced paths (traversal sequences, encoded forms, symlink escapes).

(e) Completion value caps — already compliant, already tested

values: Array of suggestions (max 100) … hasMore: Additional results flag — draft server/utilities/completion.mdx

createCompletionResult in mcp.ts already slices to 100 and sets hasMore/total, and test/e2e/scenarios/completion.test.ts (requirement completion:result-shape, 150-item fixture) already asserts the 100-cap, total, and hasMore: true. No change needed.

Notes

Validation

  • pnpm build:all, pnpm typecheck:all, pnpm lint:all (includes sync:snippets --check): pass
  • Package tests: core 463/463, client 367/367, server 72/72
  • Integration suite: 327/327 (includes 7 new tests in test/integration/test/server/declaredCapabilities.test.ts)
  • Changeset: patch for @modelcontextprotocol/server and @modelcontextprotocol/client

Closes #2202

…rs, pagination docs, path-sanitization note)

- McpServer eagerly installs tools/resources/prompts handlers for
  capabilities declared in ServerOptions.capabilities, so declared-but-empty
  capabilities answer their list methods with empty results instead of
  -32601 (draft spec MUST)
- Fix pagination doc examples to loop while (cursor !== undefined) so an
  empty-string cursor is not treated as end-of-results (draft spec MUST NOT)
- Add path-sanitization security note to docs/server.md resources section
- Add regression tests for deterministic tools/list ordering (already
  compliant; insertion order)
- Completion 100-cap + hasMore already implemented and covered by e2e tests

Closes #2202
@mattzcarey mattzcarey requested a review from a team as a code owner June 9, 2026 20:37
@changeset-bot

changeset-bot Bot commented Jun 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f1377e9

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

This PR includes changesets to release 2 packages
Name Type
@modelcontextprotocol/server Patch
@modelcontextprotocol/client 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 Jun 9, 2026

Copy link
Copy Markdown

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/client@2269

@modelcontextprotocol/codemod

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/codemod@2269

@modelcontextprotocol/server

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/server@2269

@modelcontextprotocol/server-legacy

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/server-legacy@2269

@modelcontextprotocol/express

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/express@2269

@modelcontextprotocol/fastify

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/fastify@2269

@modelcontextprotocol/hono

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/hono@2269

@modelcontextprotocol/node

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/node@2269

commit: f1377e9

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.

Implement non-SEP changes from the 2025-11-25 → draft spec diff

1 participant