Skip to content

The heart beat (ping) is not working in streamable-http #4862

@und3rs

Description

@und3rs

Bug description
The streamable-http server closes the connection immediately after responding to the client’s request.
As a result, the server fails to send ping messages to the client.
Since IDEs like Cursor do not receive the ping, they mark the MCP server as closed (red state) after the idle-timeout period.

Environment
Spring AI: 1.1.0
Webflux

Steps to reproduce
You can test this issue with below example.

  1. Use this source code
    https://github.com/spring-projects/spring-ai-examples/tree/main/model-context-protocol/weather/starter-webflux-server

  2. Change protocol from STATELESS to STREAMABLE in 'application.properties'
    spring.ai.mcp.server.protocol=STREAMABLE

  3. Add following settings into 'application.properties'
    logging.level.root=DEBUG
    spring.ai.mcp.server.keep-alive-interval=30s
    spring.ai.mcp.server.streamable-http.keep-alive-interval=30s

  4. Start webflux-mcp-server and wait after connection with mcp client.

  • Request "Initialize" and "tools/list"
  1. Monitor logs
    2025-11-13T10:47:56.059+09:00 DEBUG 22168 --- [ctor-http-nio-3] io.modelcontextprotocol.spec.McpSchema : Received JSON message: {
    "jsonrpc": "2.0",
    "id": "list-1",
    "method": "tools/list",
    "params": {}
    }
    2025-11-13T10:47:56.088+09:00 DEBUG 22168 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter : [f1db6cad-2] Completed 200 OK
    2025-11-13T10:47:56.088+09:00 DEBUG 22168 --- [ctor-http-nio-3] r.n.http.server.HttpServerOperations : [f1db6cad-2, L:/[0:0:0:0:0:0:0:1]:8080 - R:/[0:0:0:0:0:0:0:1]:55851] Last HTTP response frame
    2025-11-13T10:47:56.088+09:00 DEBUG 22168 --- [ctor-http-nio-3] r.n.http.server.HttpServerOperations : [f1db6cad-2, L:/[0:0:0:0:0:0:0:1]:8080 - R:/[0:0:0:0:0:0:0:1]:55851] Decreasing pending responses count: 0
    2025-11-13T10:47:56.089+09:00 DEBUG 22168 --- [ctor-http-nio-3] r.n.http.server.HttpServerOperations : [f1db6cad-2, L:/[0:0:0:0:0:0:0:1]:8080 - R:/[0:0:0:0:0:0:0:1]:55851] Last HTTP packet was sent, terminating the channel
    2025-11-13T10:47:56.089+09:00 DEBUG 22168 --- [ctor-http-nio-3] r.netty.channel.ChannelOperations : [f1db6cad-2, L:/[0:0:0:0:0:0:0:1]:8080 - R:/[0:0:0:0:0:0:0:1]:55851] [HttpServer] Channel inbound receiver cancelled (subscription disposed).
    2025-11-13T10:48:20.038+09:00 WARN 22168 --- [oundedElastic-1] i.m.util.KeepAliveScheduler : Failed to send keep-alive ping to session io.modelcontextprotocol.spec.McpStreamableServerSession@5fd8c0ef: Stream unavailable for session f7223451-6867-4b8c-8b46-e8ded21a7691

Expected behavior
The webflux-mcp-server should keep the connection open after sending a response to the client’s request.
It must only close the connection according to the logic defined in the KeepAliveScheduler.

Minimal Complete Reproducible example
https://github.com/spring-projects/spring-ai-examples/tree/main/model-context-protocol/weather/starter-webflux-server

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions