@@ -16,6 +16,8 @@ module MCP
1616 class Server
1717 module Transports
1818 class StreamableHTTPTransport < Transport
19+ class InvalidJsonError < StandardError ; end
20+
1921 SSE_HEADERS = {
2022 "Content-Type" => "text/event-stream" ,
2123 "Cache-Control" => "no-cache" ,
@@ -339,8 +341,11 @@ def handle_post(request)
339341 body_string = request . body . read
340342 session_id = extract_session_id ( request )
341343
342- body = parse_request_body ( body_string )
343- return body if parse_error_tuple? ( body )
344+ begin
345+ body = parse_request_body ( body_string )
346+ rescue InvalidJsonError
347+ return invalid_json_response
348+ end
344349
345350 # The `MCP-Protocol-Version` header is only meaningful after negotiation, so on `initialize`
346351 # the JSON-RPC body `params.protocolVersion` is authoritative and the header (if any) is ignored.
@@ -352,7 +357,8 @@ def handle_post(request)
352357 return protocol_version_error if protocol_version_error
353358 end
354359
355- return body unless body . is_a? ( Hash ) # Non-Hash JSON-RPC bodies are not supported in 2025-11-25.
360+ # MCP 2025-11-25 does not support JSON-RPC batch, so the body must be a single message object.
361+ return non_hash_body_response unless body . is_a? ( Hash )
356362
357363 if initialize_request? ( body )
358364 handle_initialization ( body_string , body )
@@ -510,11 +516,19 @@ def not_acceptable_response(required_types)
510516 def parse_request_body ( body_string )
511517 JSON . parse ( body_string , symbolize_names : true )
512518 rescue JSON ::ParserError , TypeError
519+ raise InvalidJsonError
520+ end
521+
522+ def invalid_json_response
513523 [ 400 , { "Content-Type" => "application/json" } , [ { error : "Invalid JSON" } . to_json ] ]
514524 end
515525
516- def parse_error_tuple? ( body )
517- body . is_a? ( Array ) && body . size == 3 && body [ 0 ] == 400
526+ def non_hash_body_response
527+ [
528+ 400 ,
529+ { "Content-Type" => "application/json" } ,
530+ [ { error : "Bad Request: request body must be a single JSON-RPC message object" } . to_json ] ,
531+ ]
518532 end
519533
520534 def initialize_request? ( body )
0 commit comments