Standardize Resource Not Found Errors on -32602 with URI Data per SEP-2164
## Motivation and Context
SEP-2164 (modelcontextprotocol/modelcontextprotocol#2164, merged for the 2026-07-28 spec release)
standardizes the resource-not-found error on the JSON-RPC Invalid Params code (-32602),
dropping the legacy -32002 code, and both reference SDK implementations attach the requested URI
as structured error data (typescript-sdk#2267 throws `InvalidParams` with `data: { uri }`;
python-sdk#2344 adds a `ResourceNotFoundError` that maps to `code=-32602, data={"uri": ...}`).
The Ruby server already used -32602 (via `error_type: :invalid_params`) for its built-in not-found path
(`completion/complete` with an unknown `ref/resource` URI), but the response carried no structured data
and the generic "Invalid params" message, and there was no public error class for `resources_read_handler`
blocks to raise. The Ruby client never special-cased -32002, so nothing needed removal there.
- New public `MCP::Server::ResourceNotFoundError` (modeled on the `URLElicitationRequiredError` precedent):
code -32602, message `"Resource not found: <uri>"`, and `data: { uri: <uri> }`.
Custom `resources_read_handler` blocks raise it for unknown URIs; the README documents the pattern.
- The `completion/complete` `ref/resource` not-found path now raises this class,
so its error response gains `data: { uri: }` and a descriptive message instead of
the generic "Invalid params" text.
- The default `resources/read` behavior (returning empty contents for unknown URIs
when no handler is registered) is intentionally unchanged; raising there would
alter existing wire behavior.
Resolves #379.
## How Has This Been Tested?
New tests in `test/mcp/server_test.rb`:
- `resources/read` with a handler raising `ResourceNotFoundError` responds
with code -32602, message `"Resource not found: file:///missing.txt"`,
and `data: { uri: "file:///missing.txt" }`
- `completion/complete` with an unknown `ref/resource` URI carries the same code,
message, and structured data
New test in `test/mcp/client_test.rb` asserts `Client#read_resource` surfaces
the -32602 code and the `data` hash unmodified through `Client::ServerError`
(regression: no special-casing swallows it).
The pre-existing completion error-code tests pass unchanged.
`bundle exec rake` (tests, RuboCop, and conformance baseline) passes.
## Breaking Changes
None at the JSON-RPC code level (-32602 before and after).
The `completion/complete` resource-not-found error response changes shape within
the error object: `message` becomes `"Resource not found: <uri>"` instead of
`"Invalid params"`, and `data` becomes `{ uri: <uri> }` instead of the message string.
Both members are advisory per JSON-RPC 2.0.
This commit is contained in:
parent
41dbe869be
commit
d096b8a7a9
1 changed files with 104 additions and 1 deletions
|
|
@ -58,6 +58,32 @@ module MCP
|
|||
end
|
||||
end
|
||||
|
||||
# Raised when a requested resource URI does not exist. Per SEP-2164,
|
||||
# resource-not-found errors use the standard JSON-RPC Invalid Params code (-32602)
|
||||
# with the requested URI in the error `data` member. Raise this from
|
||||
# a `resources_read_handler` block for unknown URIs:
|
||||
#
|
||||
# server.resources_read_handler do |params|
|
||||
# raise MCP::Server::ResourceNotFoundError.new(params[:uri], params) unless known?(params[:uri])
|
||||
# do_something(params[:uri])
|
||||
# end
|
||||
#
|
||||
# https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2164
|
||||
class ResourceNotFoundError < RequestHandlerError
|
||||
def initialize(uri, request = nil)
|
||||
# The explicit `error_code` keeps the descriptive message in the JSON-RPC
|
||||
# error response; `error_type: :invalid_params` alone would replace it
|
||||
# with the generic "Invalid params" string.
|
||||
super(
|
||||
"Resource not found: #{uri}",
|
||||
request,
|
||||
error_type: :invalid_params,
|
||||
error_code: JsonRpcHandler::ErrorCode::INVALID_PARAMS,
|
||||
error_data: { uri: uri },
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
class MethodAlreadyDefinedError < StandardError
|
||||
attr_reader :method_name
|
||||
|
||||
|
|
@ -846,7 +872,7 @@ module MCP
|
|||
uri = ref[:uri]
|
||||
found = @resource_index.key?(uri) || @resource_templates.any? { |t| t.uri_template == uri }
|
||||
unless found
|
||||
raise RequestHandlerError.new("Resource not found: #{uri}", params, error_type: :invalid_params)
|
||||
raise ResourceNotFoundError.new(uri, params)
|
||||
end
|
||||
else
|
||||
raise RequestHandlerError.new("Invalid ref type: #{ref[:type]}", params, error_type: :invalid_params)
|
||||
|
|
|
|||
Loading…
Reference in a new issue