@@ -11,6 +11,11 @@ def initialize(url:, headers: {})
1111 @session_id = nil
1212 end
1313
14+ # Sends a JSON-RPC request and returns the parsed response.
15+ # Supports both application/json and text/event-stream responses.
16+ #
17+ # @param request [Hash] The JSON-RPC request to send
18+ # @return [Hash] The parsed JSON-RPC response
1419 def send_request ( request :)
1520 method = request [ :method ] || request [ "method" ]
1621 params = request [ :params ] || request [ "params" ]
@@ -25,7 +30,18 @@ def send_request(request:)
2530 @session_id = response . headers [ "Mcp-Session-Id" ]
2631 end
2732
28- response . body
33+ # Handle different response types based on content-type
34+ content_type = response . headers [ "content-type" ]
35+
36+ parsed_body = if content_type &.include? ( "text/event-stream" )
37+ # Parse SSE response
38+ parse_sse_response ( response . body )
39+ else
40+ # Standard JSON response (Faraday already parsed it)
41+ response . body
42+ end
43+
44+ parsed_body
2945 rescue Faraday ::BadRequestError => e
3046 raise RequestHandlerError . new (
3147 "The #{ method } request is invalid" ,
@@ -78,12 +94,26 @@ def client
7894 require_faraday!
7995 @client ||= Faraday . new ( url ) do |faraday |
8096 faraday . request ( :json )
81- faraday . response ( :json )
97+ # Don't automatically parse JSON responses - we need to handle SSE too
8298 faraday . response ( :raise_error )
8399
100+ # Add Accept header to support both JSON and SSE
101+ faraday . headers [ "Accept" ] = "application/json, text/event-stream"
102+
84103 headers . each do |key , value |
85104 faraday . headers [ key ] = value
86105 end
106+
107+ # Use a middleware that doesn't auto-parse to handle both content types
108+ faraday . response do |env |
109+ content_type = env . response_headers [ "content-type" ]
110+
111+ # Only auto-parse JSON, leave SSE as raw text
112+ if content_type &.include? ( "application/json" )
113+ require "json"
114+ env [ :body ] = JSON . parse ( env [ :body ] ) if env [ :body ] . is_a? ( String ) && !env [ :body ] . empty?
115+ end
116+ end
87117 end
88118 end
89119
@@ -105,6 +135,27 @@ def require_faraday!
105135 "Add it to your Gemfile: gem 'faraday', '>= 2.0'" \
106136 "See https://rubygems.org/gems/faraday for more details."
107137 end
138+
139+ # Parses Server-Sent Events (SSE) response
140+ # Looks for the message event and parses its data as JSON
141+ def parse_sse_response ( body )
142+ require "json"
143+ result = nil
144+
145+ body . split ( "\n " ) . each do |line |
146+ # SSE format: "event: message\ndata: {...}\n\n"
147+ if line . start_with? ( "data: " )
148+ data = line [ 6 ..-1 ] # Remove "data: " prefix
149+ result = JSON . parse ( data )
150+ end
151+ end
152+
153+ result || raise ( RequestHandlerError . new (
154+ "No data found in SSE response" ,
155+ { } ,
156+ error_type : :internal_error ,
157+ ) )
158+ end
108159 end
109160 end
110161end
0 commit comments