Skip to content

[Server] Stream 2026-07-28 responses on servers that write the body themselves - #691

Merged
chr-hertel merged 3 commits into
modelcontextprotocol:mainfrom
webagil-kevin:stream-sse-frames-under-event-loop
Nov 8, 2026
Merged

chr-hertel merged 3 commits into
modelcontextprotocol:mainfrom
webagil-kevin:stream-sse-frames-under-event-loop

Conversation

@webagil-kevin

Copy link
Copy Markdown
Contributor

Follow-up to #616 and #636, for the first limit under an event loop: a server that sends the PSR-7 body itself, like amphp/http-server or react/http, never got the SSE frames the transport echoes, so the examples answered 501.

  • CallbackStream::chunks() hands such a server the SSE text of a 2026-07-28 response. On an empty chunk it waits on its loop, and dropping the generator ends the stream, so the handler sends nothing more. The PHP-FPM output stays the same, byte for byte.
  • StatelessProtocol::listen() no longer sleeps itself, its consumer paces it: a [BC Break] for code reading StatelessProtocol::handle() streams directly.
  • The Revolt and ReactPHP examples stream these responses, with an InMemoryNotificationBus so that subscriptions/listen carries something. Handshake-era streams still get 501, and the Inspector negotiates that era, so the interop tests open a subscriptions/listen stream directly.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Stored callbacks retain cancelled handler generators and delay cleanup while the body remains alive, and the ReactPHP loop can resume handlers after a known disconnect.

2 open issues
What changed in this PR

This PR enables event-loop HTTP servers to write streamed 2026-07-28 responses themselves, extending the earlier fiber-scheduler support while retaining the PHP-output path.

Changes:

  • Add CallbackStream::chunks() and move subscription polling delays to stream consumers.
  • Update Revolt and ReactPHP examples to stream modern responses; handshake-era streams still return 501.
  • Add streaming and cancellation coverage, and document the new API and polling behavior change.
File Description
tests/​Unit/​Server/​Transport/​Http/​StatelessResponderTest.php Cover SSE output, flushing, pacing, and chunks.
tests/​Unit/​Server/​Transport/​CallbackStreamTest.php Cover chunk availability and single-use behavior.
tests/​Unit/​Server/​Stateless/​StatelessProtocolTest.php Verify consumer-paced, unlimited subscriptions.
tests/​Unit/​Server/​Fiber/​RealEventLoopTest.php Cover streamed notifications and handler cleanup.
tests/​Interop/​Server/​Http/​HttpRevoltTest.php Verify subscription streaming over Revolt HTTP.
tests/​Interop/​Server/​Http/​HttpReactPhpTest.php Verify subscription streaming over ReactPHP HTTP.
tests/​Interop/​Server/​Http/​HttpInspectorSnapshotTestCase.php Add a timed HTTP stream-reading helper.
src/​Server/​Transport/​Http/​StatelessResponder.php Share SSE encoding between chunk and PHP-output consumers.
src/​Server/​Transport/​CallbackStream.php Expose single-use response chunks.
src/​Server/​Stateless/​StatelessProtocol.php Delegate subscription pacing to consumers.
examples/​server/​revolt/​server.php Stream chunks through AMPHP with idle pacing.
examples/​server/​README.md Describe modern streaming support and remaining limits.
examples/​server/​reactphp/​server.php Pump chunks with idle pacing and backpressure handling.
docs/​run/​server-builder.md Document chunk consumption and event-loop limits.
CHANGELOG.md Record streaming support and the polling behavior break.

Review effort: Balanced

Comment thread examples/server/reactphp/server.php Resolved
Comment thread src/Server/Transport/CallbackStream.php Resolved
@webagil-kevin
webagil-kevin force-pushed the stream-sse-frames-under-event-loop branch from bd73dac to effe802 Compare November 8, 2026 17:09
@chr-hertel
chr-hertel requested a balanced review from Copilot November 8, 2026 18:03
@chr-hertel chr-hertel added the Server Issues & PRs related to the Server component label Nov 8, 2026
@chr-hertel chr-hertel added this to the 0.10.0 milestone Nov 8, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues are reported for the event-loop HTTP streaming changes.

No open issues 🎉

2 resolved since last review

Review effort: Balanced

@chr-hertel
chr-hertel merged commit b5735d3 into modelcontextprotocol:main Nov 8, 2026
31 checks passed
@chr-hertel chr-hertel added 2026-07-28 All issues and PRs related to the spec release 2026-07-28 breaking change Breaking the Backwards Compatibility Promise labels Nov 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2026-07-28 All issues and PRs related to the spec release 2026-07-28 breaking change Breaking the Backwards Compatibility Promise Server Issues & PRs related to the Server component

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants