diff --git a/lib/mcp/server/transports/streamable_http_transport.rb b/lib/mcp/server/transports/streamable_http_transport.rb index ef85ef2f..f2ef9313 100644 --- a/lib/mcp/server/transports/streamable_http_transport.rb +++ b/lib/mcp/server/transports/streamable_http_transport.rb @@ -1883,10 +1883,10 @@ def validate_accept_header(request, required_types) nil end + # Empty list members (`application/json,,text/event-stream`), which RFC 9110 section 5.6.1.2 has + # a recipient parse and ignore, are skipped. def parse_accept_header(header) - header.split(",").map do |part| - part.split(";").first.strip.downcase - end + header.split(",").map { |part| part.split(";").first.to_s.strip.downcase }.reject(&:empty?) end def validate_content_type(request) diff --git a/test/mcp/server/transports/streamable_http_transport_test.rb b/test/mcp/server/transports/streamable_http_transport_test.rb index 1e1ebc7a..710e7e35 100644 --- a/test/mcp/server/transports/streamable_http_transport_test.rb +++ b/test/mcp/server/transports/streamable_http_transport_test.rb @@ -1756,6 +1756,23 @@ def string assert_equal 200, response[0] end + test "POST request with empty members in the Accept header succeeds" do + ["application/json,,text/event-stream", ", application/json, text/event-stream"].each do |accept| + request = create_rack_request_without_accept( + "POST", + "/", + { + "CONTENT_TYPE" => "application/json", + "HTTP_ACCEPT" => accept, + }, + { jsonrpc: "2.0", method: "initialize", id: "123", params: initialize_params }.to_json, + ) + + response = @transport.handle_request(request) + assert_equal 200, response[0], accept.inspect + end + end + test "POST request with Accept: */* succeeds" do request = create_rack_request_without_accept( "POST", @@ -1886,6 +1903,30 @@ def string assert_equal "text/event-stream", response[1]["content-type"] end + test "GET request with an empty member in the Accept header succeeds" do + init_request = create_rack_request( + "POST", + "/", + { "CONTENT_TYPE" => "application/json" }, + { jsonrpc: "2.0", method: "initialize", id: "123", params: initialize_params }.to_json, + ) + init_response = @transport.handle_request(init_request) + session_id = init_response[1]["mcp-session-id"] + + request = create_rack_request( + "GET", + "/", + { + "HTTP_MCP_SESSION_ID" => session_id, + "HTTP_ACCEPT" => ",text/event-stream", + }, + ) + + response = @transport.handle_request(request) + assert_equal 200, response[0] + assert_equal "text/event-stream", response[1]["content-type"] + end + test "GET request with Accept: */* succeeds" do init_request = create_rack_request( "POST",