From cd7a54a5c9110035a530dddb1607329ddf4e78a9 Mon Sep 17 00:00:00 2001 From: dak2 Date: Sun, 24 Aug 2025 16:50:19 +0900 Subject: [PATCH] Fix to return a response code 202 if the server accepts JSON-RPC notifications and responses If the server accepts JSON-RPC notifications and responses, it must return an HTTP status code of 202 without a body. refs - https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#sending-messages-to-the-server - https://www.jsonrpc.org/specification Follow up: https://github.com/modelcontextprotocol/ruby-sdk/issues/111 --- .../transports/streamable_http_transport.rb | 14 +++++++--- .../streamable_http_transport_test.rb | 26 +++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/lib/mcp/server/transports/streamable_http_transport.rb b/lib/mcp/server/transports/streamable_http_transport.rb index 531566bc..e513862a 100644 --- a/lib/mcp/server/transports/streamable_http_transport.rb +++ b/lib/mcp/server/transports/streamable_http_transport.rb @@ -108,8 +108,8 @@ def handle_post(request) if body["method"] == "initialize" handle_initialization(body_string, body) - elsif body["method"] == MCP::Methods::NOTIFICATIONS_INITIALIZED - handle_notification_initialized + elsif notification?(body) || response?(body) + handle_accepted else handle_regular_request(body_string, session_id) end @@ -168,6 +168,14 @@ def parse_request_body(body_string) [400, { "Content-Type" => "application/json" }, [{ error: "Invalid JSON" }.to_json]] end + def notification?(body) + !body["id"] && !!body["method"] + end + + def response?(body) + !!body["id"] && !body["method"] + end + def handle_initialization(body_string, body) session_id = SecureRandom.uuid @@ -187,7 +195,7 @@ def handle_initialization(body_string, body) [200, headers, [response]] end - def handle_notification_initialized + def handle_accepted [202, {}, []] end diff --git a/test/mcp/server/transports/streamable_http_transport_test.rb b/test/mcp/server/transports/streamable_http_transport_test.rb index 3c896355..5bf44110 100644 --- a/test/mcp/server/transports/streamable_http_transport_test.rb +++ b/test/mcp/server/transports/streamable_http_transport_test.rb @@ -620,6 +620,32 @@ class StreamableHTTPTransportTest < ActiveSupport::TestCase assert_empty(response[2]) end + test "handles POST request with body including JSON-RPC response object and returns with no body" do + init_request = create_rack_request( + "POST", + "/", + { "CONTENT_TYPE" => "application/json" }, + { jsonrpc: "2.0", method: "initialize", id: "init" }.to_json, + ) + init_response = @transport.handle_request(init_request) + session_id = init_response[1]["Mcp-Session-Id"] + + request = create_rack_request( + "POST", + "/", + { + "CONTENT_TYPE" => "application/json", + "HTTP_MCP_SESSION_ID" => session_id, + }, + { jsonrpc: "2.0", result: "success", id: "123" }.to_json, + ) + + response = @transport.handle_request(request) + assert_equal 202, response[0] + assert_empty(response[1]) + assert_empty(response[2]) + end + private def create_rack_request(method, path, headers, body = nil)