Merge pull request #433 from koic/mrtr_result_type

Recognize multi round-trip `input_required` results per SEP-2322
This commit is contained in:
Koichi ITO 2026-07-12 02:15:01 +09:00 • committed by GitHub
commit c43ea6e51b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 143 additions and 0 deletions

View file

@ -17,6 +17,7 @@ module MCP
autoload :Prompt, "mcp/prompt"
autoload :Resource, "mcp/resource"
autoload :ResourceTemplate, "mcp/resource_template"
autoload :ResultType, "mcp/result_type"
autoload :Server, "mcp/server"
autoload :ServerSession, "mcp/server_session"
autoload :Tool, "mcp/tool"

View file

@ -5,6 +5,7 @@ require_relative "client/stdio"
require_relative "client/http"
require_relative "client/paginated_result"
require_relative "client/tool"
require_relative "result_type"
module MCP
class Client
@ -34,6 +35,25 @@ module MCP
# server-returned JSON-RPC error, which is raised as `ServerError`.
class ValidationError < StandardError; end
# Raised when a server answers with a SEP-2322 Multi Round-Trip `input_required` result instead of
# a final result. The result is not an error on the wire: it asks the client to fulfill the server's
# `inputRequests` (a map of id => `{ "method" => ..., "params" => ... }` request objects with
# `sampling/createMessage`, `roots/list`, or `elicitation/create` shapes) and re-issue
# the original request with `inputResponses` plus the echoed opaque `requestState`.
# This SDK does not yet drive that resume loop automatically; callers can inspect `input_requests`
# and respond manually.
# https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2322
class InputRequiredError < StandardError
attr_reader :input_requests, :request_state, :result
def initialize(message, input_requests:, request_state: nil, result: nil)
super(message)
@input_requests = input_requests
@request_state = request_state
@result = result
end
end
# Raised when the server responds 404 to a request containing a session ID,
# indicating the session has expired. Inherits from `RequestHandlerError` for
# backward compatibility with callers that rescue the generic error. Per spec,
@ -434,9 +454,26 @@ module MCP
raise ServerError.new(error["message"], code: error["code"], data: error["data"])
end
raise_on_input_required(response)
response
end
# Recognizes a SEP-2322 `input_required` result and raises rather than returning it as if it were a final result.
# Servers on stable protocol versions never emit `resultType`, so this is a no-op for them.
def raise_on_input_required(response)
result = response.is_a?(Hash) ? response["result"] : nil
return unless result.is_a?(Hash) && result["resultType"] == ResultType::INPUT_REQUIRED
raise InputRequiredError.new(
"Server returned `input_required`; this SDK does not yet resume multi-round-trip requests (SEP-2322). " \
"Inspect `input_requests` to respond manually.",
input_requests: result["inputRequests"] || {},
request_state: result["requestState"],
result: result,
)
end
# Generates a fresh JSON-RPC request id for an outgoing request.
# Ids are an internal concern: the public API never accepts or exposes them, and cancellation is driven through
# an `MCP::Cancellation` token instead.

18
lib/mcp/result_type.rb Normal file
View file

@ -0,0 +1,18 @@
# frozen_string_literal: true
module MCP
# Values of the `resultType` result field introduced by SEP-2322 (Multi Round-Trip Requests)
# for the MCP 2026-07-28 draft.
#
# A result with `resultType: "input_required"` is not a final answer: it carries an `inputRequests` map
# of server-to-client requests (`sampling/createMessage`, `roots/list`, `elicitation/create` shapes) plus
# an opaque `requestState` string, and the client is expected to fulfill the requests and re-issue
# the original request with `inputResponses` and the echoed `requestState`. A missing `resultType`
# or `"complete"` is a final result.
#
# https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2322
module ResultType
COMPLETE = "complete"
INPUT_REQUIRED = "input_required"
end
end