Skip to content

fix(server): return -32602 for nonexistent resources (SEP-2164)#2267

Draft
mattzcarey wants to merge 1 commit into
mainfrom
fix/sep-2164-resource-not-found-invalid-params
Draft

fix(server): return -32602 for nonexistent resources (SEP-2164)#2267
mattzcarey wants to merge 1 commit into
mainfrom
fix/sep-2164-resource-not-found-invalid-params

Conversation

@mattzcarey

Copy link
Copy Markdown
Contributor

Summary

Implements SEP-2164: reads of nonexistent resources now fail with JSON-RPC -32602 (Invalid params) instead of the MCP-specific -32002 (ProtocolErrorCode.ResourceNotFound). The requested URI is carried in the error's data.uri so clients can still distinguish not-found from other invalid-params failures.

Spec citation

The draft spec (server/resources.mdx, ~L395-398) says:

Servers MUST return standard JSON-RPC errors for common failure cases:

  • Resource not found: -32602 (Invalid params)
  • Internal errors: -32603 (Internal error)

Clients SHOULD also accept the legacy error code -32002 for resource-not-found errors. Servers MUST NOT return an empty contents array for a nonexistent resource.

Note the history: the 2025-11-25 revision said servers SHOULD return -32002; the draft (SEP-2164) flips this to MUST return -32602, keeping -32002 only as a legacy code clients should tolerate.

This reverses a recent deliberate change

#1389 (shipped in 2.0.0-alpha.1) intentionally moved unknown-resource reads from -32602-32002 and introduced ProtocolErrorCode.ResourceNotFound, matching the then-current SHOULD-strength spec text. SEP-2164 has since standardized the opposite direction, so this PR flips it back:

  • McpServer's resources/read handler throws ProtocolErrorCode.InvalidParams with data: { uri }.
  • ProtocolErrorCode.ResourceNotFound is marked @deprecated but remains exported — clients may still need to match it from older servers, per the spec's "SHOULD also accept legacy -32002" language.
  • Client side needs no change: it has no code-specific handling of -32002.

Open design question for maintainers

Implemented as an unconditional flip — should this instead be gated on the negotiated protocol version (runtime still defaults to 2025-11-25, where -32002 was SHOULD-strength)? Unconditional seems defensible since the draft tells clients to accept both, but flagging for a direction call. (The 2026-07-28 reference types from #2252 already define only INVALID_PARAMS for this case.)

Draft until that's resolved.

Changes

  • packages/server/src/server/mcp.ts: resources/read not-found path throws InvalidParams with data: { uri }
  • packages/core/src/types/enums.ts: ResourceNotFound deprecated with JSDoc pointing at InvalidParams per SEP-2164
  • test/integration/test/server/mcp.test.ts: unknown-resource test now asserts -32602 + data.uri
  • test/e2e/scenarios/resources.test.ts + test/e2e/requirements.ts: resources:read:unknown-uri updated to -32602 with a manifest note on the SEP-2164 SHOULD→MUST history
  • Changeset (patch, @modelcontextprotocol/server + @modelcontextprotocol/core)

Validation

  • pnpm build:all, pnpm typecheck:all, pnpm lint:all: pass
  • Core: 463/463, server: 72/72, client: 367/367, integration: 320/320, server-legacy 162/162, middleware all green
  • E2E: 1141 passed, 91 expected-fail; sole failure was the known pre-existing flake protocol:timeout:max-total [sse] (unrelated, fails only under full-suite parallel load)
  • One server-legacy timing flake (bearerAuth "expired 0 seconds ago") failed once under the full run, passes 3/3 in isolation — unrelated

Downstream impact: cloudflare/agents MCPAgent servers will emit -32602 for unknown resources after upgrading; grep confirms no agents code branches on -32002, so no downstream changes needed.

Closes #2194

Per SEP-2164, the draft spec upgrades resource-not-found handling from
SHOULD return -32002 (2025-11-25) to MUST return -32602 (Invalid params).
The requested URI is included in the error's data.uri so clients can
still distinguish not-found from other invalid-params errors.

ProtocolErrorCode.ResourceNotFound (-32002) is deprecated but remains
exported, since clients SHOULD still accept it from older servers.

Closes #2194
@changeset-bot

changeset-bot Bot commented Jun 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1f43d9c

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/core 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@2267

@modelcontextprotocol/codemod

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

@modelcontextprotocol/server

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

@modelcontextprotocol/server-legacy

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

@modelcontextprotocol/express

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

@modelcontextprotocol/fastify

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

@modelcontextprotocol/hono

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

@modelcontextprotocol/node

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

commit: 1f43d9c

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 SEP-2164: Standardize resource not found error code (-32602)

1 participant