Skip to content

SEP-2164: Standardize resource-not-found error code (-32002 → -32602) #867

@alexhancock

Description

@alexhancock

Source: MCP release 2026-07-28, scoped SEP-2164.
Spec PR: modelcontextprotocol/modelcontextprotocol#2164
Filed as part of a sweep of the release's scoped SEPs for rust-sdk impact.

Summary

SEP-2164 standardizes the JSON-RPC error code returned for a "resource not found" condition. The spec moves this from the MCP-specific -32002 to the standard -32602 (INVALID_PARAMS).

Current state in rmcp

The SDK currently defines and uses -32002 (confirmed in crates/rmcp/src/model.rs):

  • ErrorCode::RESOURCE_NOT_FOUND: Self = Self(-32002) (line ~503).
  • ErrorCode::INVALID_PARAMS: Self = Self(-32602) already exists (line ~506).
  • ErrorData::resource_not_found(message, data) (line ~544) is a thin wrapper: Self::new(ErrorCode::RESOURCE_NOT_FOUND, message, data).

ErrorData carries no protocol version, and resource_not_found() is a static constructor, so the cleanest version-gating happens at the call sites (where the negotiated ProtocolVersion is known), not inside the constructor.

Proposed work

  • Keep ErrorCode::RESOURCE_NOT_FOUND = -32002 as a named constant for back-compat / parsing, but stop hard-coding it for new responses.
  • Add a helper that picks the code by negotiated version — e.g. ErrorData::resource_not_found_for(version, ..) returning -32602 for >= V_2026_07_28 and -32002 for older peers — or set the code at the resource handler call sites in handler/server/router.rs where the peer's ProtocolVersion is available.
  • Audit existing call sites of ErrorData::resource_not_found(..) (resource read/subscribe paths) and route them through the version-aware path.
  • Client side: when matching resource-not-found, accept both -32002 and -32602 (code == RESOURCE_NOT_FOUND || code == INVALID_PARAMS in the not-found context).
  • Update tests/conformance fixtures asserting -32002.

Affected areas

crates/rmcp/src/model.rs (ErrorCode, ErrorData::resource_not_found), handler/server/router.rs (resource handlers / call sites), service/client.rs (error interpretation).

Notes / risks

  • Small but observable change. Favor version-gating at call sites over flipping the constant, so older peers aren't broken. Confirm with the final SEP whether a hard switch at 2026-07-28 is acceptable.
  • Related: Input validation errors returned as -32602 instead of isError (SEP-1303) #840 (SEP-1303) also touches -32602 semantics for input validation — different concern, but worth coordinating the error-code story.

Metadata

Metadata

Assignees

Labels

P2Medium: important but non-blocking improvementT-enhancementNew features and enhancementsT-modelModel/data structure changes

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions