Disclaimer: I am not a native English speaker. This issue was drafted with AI translation assistance. I apologize for any awkward phrasing.
Description
When using the MCP Streamable HTTP transport with Spring AI’s WebClientStreamableHttpTransport, valid SSE frames are dropped if the server omits the event: field and sends only data:.
Per standard SSE semantics, when the event: field is omitted, the event type defaults to message. However, the current Spring AI implementation only parses frames whose event type is explicitly equal to "message".
As a result, a valid JSON-RPC response delivered as:
data: {"jsonrpc":"2.0","id":"1","result":{...}}
is ignored if Spring/WebFlux exposes the event type as null, and the client can time out during initialization or while consuming server-pushed messages.
This appears to be the Spring AI counterpart of the issue originally discussed in modelcontextprotocol/java-sdk#885. The Java SDK PR #913 fixed the HttpClient variant only and explicitly notes that the WebClient variant now lives in Spring AI and needs a separate fix here.
Current Behavior
In org.springframework.ai.mcp.client.webflux.transport.WebClientStreamableHttpTransport, the current parsing logic is effectively:
if (MESSAGE_EVENT_TYPE.equals(event.event())) {
// parse JSON-RPC payload
}
else {
// ignore frame
}
So if event.event() is null (which can happen when the SSE frame omits the event: field), the frame is silently dropped.
Expected Behavior
An SSE frame without an explicit event: field should be treated as a default message event and parsed as a JSON-RPC message.
That means all of the following should be accepted as message events:
event == null
event == ""
event == "message"
Why this matters
This breaks compatibility with valid Streamable HTTP MCP servers that emit legal SSE frames without an explicit event: field.
In practice, this can cause:
-
initialize() responses to be ignored
-
startup-time MCP client initialization failures
-
request timeouts such as:
Client failed to initialize by explicit API call
Did not observe any item or terminal signal within ...
Steps to Reproduce
- Run an MCP server over Streamable HTTP.
- Make the server return a valid JSON-RPC
initialize result as text/event-stream.
- Ensure the SSE frame contains only
data: and omits event::
data: {"jsonrpc":"2.0","id":"1","result":{"protocolVersion":"2025-06-18","capabilities":{"tools":{}},"serverInfo":{"name":"test","version":"1.0.0"}}}
- Configure Spring AI MCP client with WebFlux streamable-http transport.
- Start the application and let Spring AI initialize the MCP client, or call
client.initialize() directly.
Actual Behavior
The client receives the SSE payload, but because the event type is exposed as null, Spring AI does not parse it as a JSON-RPC message.
The response is effectively ignored and the client eventually times out.
Environment
- Spring AI:
2.0.0-M3
- Transport:
WebClientStreamableHttpTransport
- Starter:
spring-ai-starter-mcp-client-webflux
- Spring Boot:
4.0.4
- MCP Java SDK:
1.1.0
- Java:
25.0.2
- Reactor Netty:
1.3.4
- MCP server tested against:
rmcp 1.2.0 over Streamable HTTP
- OS: macOS
Related Issues
modelcontextprotocol/java-sdk#885
Additional Context
The issue seems easy to miss because the behavior only appears when the server omits event: instead of explicitly sending event: message.
That server behavior is still spec-compliant SSE, so dropping such frames makes the Spring AI transport stricter than it should be.
Disclaimer: I am not a native English speaker. This issue was drafted with AI translation assistance. I apologize for any awkward phrasing.
Description
When using the MCP Streamable HTTP transport with Spring AI’s
WebClientStreamableHttpTransport, valid SSE frames are dropped if the server omits theevent:field and sends onlydata:.Per standard SSE semantics, when the
event:field is omitted, the event type defaults tomessage. However, the current Spring AI implementation only parses frames whose event type is explicitly equal to"message".As a result, a valid JSON-RPC response delivered as:
is ignored if Spring/WebFlux exposes the event type as
null, and the client can time out during initialization or while consuming server-pushed messages.This appears to be the Spring AI counterpart of the issue originally discussed in
modelcontextprotocol/java-sdk#885. The Java SDK PR#913fixed theHttpClientvariant only and explicitly notes that theWebClientvariant now lives in Spring AI and needs a separate fix here.Current Behavior
In
org.springframework.ai.mcp.client.webflux.transport.WebClientStreamableHttpTransport, the current parsing logic is effectively:So if
event.event()isnull(which can happen when the SSE frame omits theevent:field), the frame is silently dropped.Expected Behavior
An SSE frame without an explicit
event:field should be treated as a defaultmessageevent and parsed as a JSON-RPC message.That means all of the following should be accepted as message events:
event == nullevent == ""event == "message"Why this matters
This breaks compatibility with valid Streamable HTTP MCP servers that emit legal SSE frames without an explicit
event:field.In practice, this can cause:
initialize()responses to be ignoredstartup-time MCP client initialization failures
request timeouts such as:
Client failed to initialize by explicit API callDid not observe any item or terminal signal within ...Steps to Reproduce
initializeresult astext/event-stream.data:and omitsevent::client.initialize()directly.Actual Behavior
The client receives the SSE payload, but because the event type is exposed as
null, Spring AI does not parse it as a JSON-RPC message.The response is effectively ignored and the client eventually times out.
Environment
2.0.0-M3WebClientStreamableHttpTransportspring-ai-starter-mcp-client-webflux4.0.41.1.025.0.21.3.4rmcp 1.2.0over Streamable HTTPRelated Issues
modelcontextprotocol/java-sdk#885Additional Context
The issue seems easy to miss because the behavior only appears when the server omits
event:instead of explicitly sendingevent: message.That server behavior is still spec-compliant SSE, so dropping such frames makes the Spring AI transport stricter than it should be.