From 58cb5f97ccc92ca21893bc24bc48c22eb3b87a73 Mon Sep 17 00:00:00 2001 From: Ates Goral Date: Sat, 18 Apr 2026 19:42:19 -0400 Subject: [PATCH] Handle 202 Accepted response in HTTP client The Streamable HTTP spec allows a server to respond 202 Accepted when it has received the request but will deliver the response later via an SSE stream. The client previously errored on 202 because the response has no parseable Content-Type. Return `{ "accepted" => true }` so the caller can decide how to proceed. Actually picking up the deferred response requires listening on an SSE stream (GET-for-SSE), which is not yet implemented. This PR only prevents the hard error on a valid server response. Co-Authored-By: Claude Opus 4.7 --- lib/mcp/client/http.rb | 4 ++++ test/mcp/client/http_test.rb | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/lib/mcp/client/http.rb b/lib/mcp/client/http.rb index 8b135e3..b5ba8e9 100644 --- a/lib/mcp/client/http.rb +++ b/lib/mcp/client/http.rb @@ -106,6 +106,10 @@ def parse_response_body(response, method, params) parse_sse_response(response.body, method, params) elsif content_type&.include?("application/json") response.body + elsif response.status == 202 + # Server accepted the request and will deliver the response via an SSE stream. + # https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#sending-messages-to-the-server + { "accepted" => true } else raise RequestHandlerError.new( "Unsupported Content-Type: #{content_type.inspect}. Expected application/json or text/event-stream.", diff --git a/test/mcp/client/http_test.rb b/test/mcp/client/http_test.rb index 89d3649..c21441b 100644 --- a/test/mcp/client/http_test.rb +++ b/test/mcp/client/http_test.rb @@ -369,6 +369,21 @@ def test_send_request_parses_sse_error_response assert_equal("Invalid request", response.dig("error", "message")) end + def test_send_request_returns_accepted_for_202_response + request = { + jsonrpc: "2.0", + method: "notifications/initialized", + } + + stub_request(:post, url) + .with(body: request.to_json) + .to_return(status: 202, body: "") + + response = client.send_request(request: request) + + assert_equal({ "accepted" => true }, response) + end + def test_send_request_raises_error_for_sse_without_response request = { jsonrpc: "2.0",