Skip to content

fix(core): keep streamable HTTP session alive when an SSE stream writ… - #1132

Open
Lubaoshuai wants to merge 1 commit into
modelcontextprotocol:mainfrom
Lubaoshuai:fix/streamable-session-write-failure
Open

fix(core): keep streamable HTTP session alive when an SSE stream writ…#1132
Lubaoshuai wants to merge 1 commit into
modelcontextprotocol:mainfrom
Lubaoshuai:fix/streamable-session-write-failure

Conversation

@Lubaoshuai

Copy link
Copy Markdown

…e fails

A failed write inside HttpServletStreamableMcpSessionTransport.sendMessage removed the whole McpStreamableServerSession from the provider. Any transient failure (slow or aborted client, momentary IO error) therefore made the server forget the session: the client's next POST got a 404 and client sessions surfaced 'MCP session with server terminated' (#952).

A failed write now breaks only the affected SSE stream, mirroring close(): the transport is marked closed so further sends on the dead stream are no-ops, the async context is completed behind a guard, and session removal stays with explicit DELETE handling and lifecycle events. Clients can still reopen a stream via GET with Last-Event-ID.

Added servlet-mock regression tests: a failed stream write no longer evicts the session (subsequent POST is accepted), while an explicit DELETE still removes it.

Motivation and Context

How Has This Been Tested?

Breaking Changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

…e fails

A failed write inside HttpServletStreamableMcpSessionTransport.sendMessage
removed the whole McpStreamableServerSession from the provider. Any
transient failure (slow or aborted client, momentary IO error) therefore
made the server forget the session: the client's next POST got a 404 and
client sessions surfaced 'MCP session with server terminated' (modelcontextprotocol#952).

A failed write now breaks only the affected SSE stream, mirroring
close(): the transport is marked closed so further sends on the dead
stream are no-ops, the async context is completed behind a guard, and
session removal stays with explicit DELETE handling and lifecycle
events. Clients can still reopen a stream via GET with Last-Event-ID.

Added servlet-mock regression tests: a failed stream write no longer
evicts the session (subsequent POST is accepted), while an explicit
DELETE still removes it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant