feat: SSE heartbeat#761
Open
UnscientificJsZhai wants to merge 2 commits into
Open
Conversation
ae7b4af to
29365d6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds optional SSE heartbeat configuration for streamable HTTP MCP server connections.
This lets
Application.mcpStreamableHttpcallers pass Ktor'sHeartbeatconfiguration for SSE streams, including heartbeat period and event payload. Heartbeats remain disabled by default, preserving the existing stream behavior unless the new option is explicitly provided.Motivation and Context
Some MCP clients need heartbeat messages on SSE connections to keep the connection alive. Without those heartbeats, the client may proactively disconnect from the MCP server. MCP server developers need a way to configure an SSE heartbeat mechanism so they can avoid unexpected client disconnects.
In my case, my MCP server was consistently disconnected by Gemini CLI. I worked around the issue with some fallback approaches, but I believe the best implementation is to add heartbeat support by using Ktor's built-in API.
My solution:
Implementation Notes
sseHeartbeatConfig: (Heartbeat.() -> Unit)? = nullparameter toApplication.mcpStreamableHttp.StreamableHttpServerTransport.Configuration.sse { ... }block before handling the existing streamable HTTP transport request.How Has This Been Tested?
Added
StreamableHttpHeartbeatTestcovering:sseHeartbeatConfigis omitted.Verified locally with:
./gradlew :kotlin-sdk-server:jvmTest --tests "io.modelcontextprotocol.kotlin.sdk.server.StreamableHttpHeartbeatTest"Result:
BUILD SUCCESSFUL.Breaking Changes
No source-level breaking changes are expected. The new heartbeat option is nullable and defaults to
null, so existingmcpStreamableHttpcalls continue to use the previous behavior with no heartbeat.This PR does update the public API surface by adding an optional parameter and configuration property.
Types of changes
Checklist
Additional context
Heartbeat behavior is delegated to Ktor's SSE heartbeat support, so applications can use the same configuration semantics they would use in native Ktor SSE routes.
Related issue: SSE needs a heartbeat #344