diff --git a/.changeset/sep-2164-resource-not-found-invalid-params.md b/.changeset/sep-2164-resource-not-found-invalid-params.md new file mode 100644 index 0000000000..d2689a8cf8 --- /dev/null +++ b/.changeset/sep-2164-resource-not-found-invalid-params.md @@ -0,0 +1,6 @@ +--- +'@modelcontextprotocol/server': patch +'@modelcontextprotocol/core': patch +--- + +Resource not found now returns `-32602` (Invalid params) per SEP-2164; `-32002` (`ProtocolErrorCode.ResourceNotFound`) is deprecated. The error includes the requested URI in `data.uri` so clients can still distinguish not-found from other invalid-params errors. Clients SHOULD continue to accept legacy `-32002` from older servers. diff --git a/packages/core/src/types/enums.ts b/packages/core/src/types/enums.ts index 0e3b65f9f0..49ee6a62ae 100644 --- a/packages/core/src/types/enums.ts +++ b/packages/core/src/types/enums.ts @@ -11,6 +11,13 @@ export enum ProtocolErrorCode { InternalError = -32_603, // MCP-specific error codes + /** + * Legacy error code for reads of nonexistent resources. + * + * @deprecated Per SEP-2164, servers MUST return {@link ProtocolErrorCode.InvalidParams} + * (`-32602`, with the requested URI in `data.uri`) for nonexistent resources. This code + * remains exported because clients SHOULD still accept `-32002` from older servers. + */ ResourceNotFound = -32_002, /** * Processing the request requires a capability the client did not declare diff --git a/packages/server/src/server/mcp.ts b/packages/server/src/server/mcp.ts index 40ec8bb1eb..3d51e611d7 100644 --- a/packages/server/src/server/mcp.ts +++ b/packages/server/src/server/mcp.ts @@ -406,7 +406,9 @@ export class McpServer { } } - throw new ProtocolError(ProtocolErrorCode.ResourceNotFound, `Resource ${uri} not found`); + // SEP-2164: nonexistent resources MUST return -32602 (Invalid params); the + // requested URI is included in `data` so clients can distinguish not-found. + throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Resource ${uri} not found`, { uri: uri.toString() }); }); this._resourceHandlersInitialized = true; diff --git a/test/e2e/requirements.ts b/test/e2e/requirements.ts index ea471a21fc..dc506b4c89 100644 --- a/test/e2e/requirements.ts +++ b/test/e2e/requirements.ts @@ -531,7 +531,8 @@ export const REQUIREMENTS: Record = { }, 'resources:read:unknown-uri': { source: 'https://modelcontextprotocol.io/specification/2025-11-25/server/resources#error-handling', - behavior: 'resources/read for an unknown URI returns JSON-RPC error -32002 (resource not found).' + behavior: 'resources/read for an unknown URI returns JSON-RPC error -32602 (Invalid params) with the URI in error data.', + note: 'SEP-2164: the draft spec upgrades this to MUST -32602 (2025-11-25 said SHOULD -32002); clients SHOULD still accept legacy -32002 from older servers.' }, 'resources:subscribe:capability-required': { source: 'https://modelcontextprotocol.io/specification/2025-11-25/server/resources#capabilities', diff --git a/test/e2e/scenarios/resources.test.ts b/test/e2e/scenarios/resources.test.ts index ea83696915..c40fa8f86a 100644 --- a/test/e2e/scenarios/resources.test.ts +++ b/test/e2e/scenarios/resources.test.ts @@ -203,8 +203,10 @@ verifies('resources:read:unknown-uri', async ({ transport }: TestArgs) => { await using _ = await wire(transport, makeServer, client); await expect(client.readResource({ uri: 'file:///no-such-resource' })).rejects.toMatchObject({ - code: -32_002, - message: expect.stringMatching(/not found|unknown/i) + // SEP-2164: nonexistent resources return -32602 (Invalid params) with the URI in `data` + code: -32_602, + message: expect.stringMatching(/not found|unknown/i), + data: { uri: 'file:///no-such-resource' } }); }); diff --git a/test/integration/test/server/mcp.test.ts b/test/integration/test/server/mcp.test.ts index 8c844b11cb..09681382bf 100644 --- a/test/integration/test/server/mcp.test.ts +++ b/test/integration/test/server/mcp.test.ts @@ -2728,8 +2728,10 @@ describe('Zod v4', () => { } }) ).rejects.toMatchObject({ - code: ProtocolErrorCode.ResourceNotFound, - message: expect.stringContaining('not found') + // SEP-2164: nonexistent resources return -32602 (Invalid params) with the URI in `data` + code: ProtocolErrorCode.InvalidParams, + message: expect.stringContaining('not found'), + data: { uri: 'test://nonexistent' } }); });