Skip to content

Commit 7345bd7

Browse files
Clean up idle timeout implementation
- Remove unrelated blank line between logger.info and try block - Only create CancelScope when session_idle_timeout is set, keeping the no-timeout path identical to the original code - Add docstring to _effective_idle_timeout explaining the 3x retry_interval multiplier rationale
1 parent 2c87708 commit 7345bd7

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

src/mcp/server/streamable_http_manager.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ async def lifespan(app: Starlette) -> AsyncIterator[None]:
131131
# Store the task group for later use
132132
self._task_group = tg
133133
logger.info("StreamableHTTP session manager started")
134-
135134
try:
136135
yield # Let the application run
137136
finally:
@@ -335,7 +334,14 @@ async def run_server(*, task_status: TaskStatus[None] = anyio.TASK_STATUS_IGNORE
335334
await response(scope, receive, send)
336335

337336
def _effective_idle_timeout(self) -> float:
338-
"""Compute the effective idle timeout, accounting for retry_interval."""
337+
"""Compute the effective idle timeout, accounting for retry_interval.
338+
339+
When SSE retry_interval is configured, clients periodically reconnect
340+
to resume the event stream. A gap of up to ``retry_interval`` between
341+
connections is normal, not a sign of idleness. We use a 3x multiplier
342+
to tolerate up to two consecutive missed polls (network jitter, slow
343+
client) before considering the session idle.
344+
"""
339345
assert self.session_idle_timeout is not None
340346
timeout = self.session_idle_timeout
341347
if self.retry_interval is not None:

0 commit comments

Comments
 (0)