@@ -486,6 +486,45 @@ async def send_prompt_list_changed(self) -> None:
486486 """Send a prompt list changed notification to the client."""
487487 await self .session .send_prompt_list_changed ()
488488
489+ async def close_sse_stream (self ) -> None :
490+ """Close the current response stream to trigger client reconnection.
491+
492+ When using StreamableHTTP transport with an EventStore configured, this
493+ method gracefully closes the HTTP connection for the current request.
494+ The client will automatically reconnect (after `retry_interval` milliseconds)
495+ and resume receiving events from where it left off via the EventStore.
496+
497+ This is useful for long-running operations to avoid load balancer timeouts.
498+ Instead of holding a connection open for minutes, you can periodically close
499+ and let the client reconnect.
500+
501+ Example:
502+ ```python
503+ @mcp.tool
504+ async def long_running_task(ctx: Context) -> str:
505+ for i in range(100):
506+ await ctx.report_progress(i, 100)
507+
508+ # Close connection every 30 iterations to avoid LB timeouts
509+ if i % 30 == 0 and i > 0:
510+ await ctx.close_sse_stream()
511+
512+ await do_work()
513+ return "Done"
514+ ```
515+
516+ Note:
517+ This is a no-op (with a debug log) if not using StreamableHTTP
518+ transport with an EventStore configured.
519+ """
520+ if not self .request_context or not self .request_context .close_sse_stream :
521+ logger .debug (
522+ "close_sse_stream() called but not applicable "
523+ "(requires StreamableHTTP transport with event_store)"
524+ )
525+ return
526+ await self .request_context .close_sse_stream ()
527+
489528 async def sample (
490529 self ,
491530 messages : str | Sequence [str | SamplingMessage ],
0 commit comments