Disclaimer: I am not a native English speaker. This issue was drafted with AI translation assistance. I apologize for any awkward phrasing.
Bug description
When using the Streamable HTTP transport, the Java client receives an SSE frame whose payload contains a valid JSON-RPC response, but the SSE event name is omitted by the server.
In standard SSE semantics, if the event: field is omitted, the event type defaults to message. However, the current Java SDK only parses the frame if event.event() is explicitly equal to "message". If the event name is missing and Spring/WebFlux exposes it as null, the client drops the frame instead of treating it as a default message event.
As a result, the initialize response is ignored even though the client has already received the JSON-RPC result, and initialization eventually times out with:
Client failed to initialize by explicit API call
In my case, the server is rmcp over Streamable HTTP.
Environment
- Spring AI:
2.0.0-M3
- MCP Java SDK:
1.1.0
- Transport:
WebClientStreamableHttpTransport (via spring-ai-starter-mcp-client-webflux)
- Spring Boot:
4.0.4
- Java:
25.0.2
- Reactor Netty:
1.3.4
- MCP server:
rmcp 1.2.0 (Rust, Streamable HTTP)
- OS: macOS
Steps to reproduce
- Run an MCP server over Streamable HTTP.
- Make the server return a valid JSON-RPC
initialize result as text/event-stream.
- The SSE frame should contain only
data: ... and omit the event: field. For example:
data: {"jsonrpc":"2.0","id":"1","result":{"protocolVersion":"2025-06-18","capabilities":{"tools":{}},"serverInfo":{"name":"test","version":"1.0.0"}}}
- Start a Spring AI / MCP Java SDK client using
WebClientStreamableHttpTransport.
- Call
client.initialize() (or let Spring AI auto-initialize the MCP client during startup).
Expected behavior
The client should treat an SSE frame without an explicit event: field as a default message event and parse the JSON-RPC payload normally.
So the initialize response above should be accepted, and client initialization should complete successfully.
Actual behavior
The client receives the SSE payload, but the event type is exposed as null and is not parsed as a JSON-RPC message.
As a result, the initialize response is effectively ignored, and initialization times out.
From debug logs:
Received SSE event with type: ServerSentEvent [id = 'null', event='null', retry=null, comment='null', data={"jsonrpc":"2.0","id":"9642da98-0","result":{"protocolVersion":"2025-06-18","capabilities":{"tools":{}},"serverInfo":{"name":"rmcp","version":"1.2.0"},"instructions":"..."}}]
...
Caused by: java.util.concurrent.TimeoutException: Did not observe any item or terminal signal within 20000ms
...
Client failed to initialize by explicit API call
Disclaimer: I am not a native English speaker. This issue was drafted with AI translation assistance. I apologize for any awkward phrasing.
Bug description
When using the Streamable HTTP transport, the Java client receives an SSE frame whose payload contains a valid JSON-RPC response, but the SSE event name is omitted by the server.
In standard SSE semantics, if the
event:field is omitted, the event type defaults tomessage. However, the current Java SDK only parses the frame ifevent.event()is explicitly equal to"message". If the event name is missing and Spring/WebFlux exposes it asnull, the client drops the frame instead of treating it as a defaultmessageevent.As a result, the
initializeresponse is ignored even though the client has already received the JSON-RPC result, and initialization eventually times out with:Client failed to initialize by explicit API callIn my case, the server is
rmcpover Streamable HTTP.Environment
2.0.0-M31.1.0WebClientStreamableHttpTransport(viaspring-ai-starter-mcp-client-webflux)4.0.425.0.21.3.4rmcp 1.2.0(Rust, Streamable HTTP)Steps to reproduce
initializeresult astext/event-stream.data: ...and omit theevent:field. For example:WebClientStreamableHttpTransport.client.initialize()(or let Spring AI auto-initialize the MCP client during startup).Expected behavior
The client should treat an SSE frame without an explicit
event:field as a defaultmessageevent and parse the JSON-RPC payload normally.So the
initializeresponse above should be accepted, and client initialization should complete successfully.Actual behavior
The client receives the SSE payload, but the event type is exposed as
nulland is not parsed as a JSON-RPC message.As a result, the initialize response is effectively ignored, and initialization times out.
From debug logs: