Skip to content

Commit f5d5929

Browse files
committed
Stabilize idle-timeout coverage under CI timing
The new session_idle_timeout tests started exercising two paths the existing source annotations and timing assumptions no longer matched. CI's strict-no-cover gate now observes the session_manager return path, and the idle-reap assertion can race under slower coverage-instrumented runs. This follow-up removes the stale pragma and makes the idle-reap assertion wait for actual session removal before checking the 404 behavior. Constraint: Must preserve the PR's runtime semantics and only address CI-validity drift Rejected: Increase fixed sleeps again | keeps the test timing-sensitive and flaky under slower environments Confidence: high Scope-risk: narrow Reversibility: clean Directive: Prefer state-based waits over fixed sleeps in StreamableHTTP timeout tests Tested: uv run --frozen pytest tests/server/test_streamable_http_manager.py; coverage run of the same suite; strict-no-cover-sensitive paths exercised locally Not-tested: Full upstream matrix rerun after push
1 parent e921e8f commit f5d5929

File tree

2 files changed

+6
-3
lines changed

2 files changed

+6
-3
lines changed

src/mcp/server/lowlevel/server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ def session_manager(self) -> StreamableHTTPSessionManager:
354354
"Session manager can only be accessed after calling streamable_http_app(). "
355355
"The session manager is created lazily to avoid unnecessary initialization."
356356
)
357-
return self._session_manager # pragma: no cover
357+
return self._session_manager
358358

359359
async def run(
360360
self,

tests/server/test_streamable_http_manager.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,10 @@ async def mock_receive(): # pragma: no cover
385385

386386
assert session_id is not None, "Session ID not found in response headers"
387387

388-
# Wait for the 50ms idle timeout to fire and cleanup to complete
389-
await anyio.sleep(0.1)
388+
# Wait deterministically for the idle timeout to fire and cleanup to complete.
389+
with anyio.fail_after(1):
390+
while session_id in manager._server_instances:
391+
await anyio.sleep(0)
390392

391393
# Verify via public API: old session ID now returns 404
392394
response_messages: list[Message] = []
@@ -399,6 +401,7 @@ async def capture_send(message: Message):
399401
"method": "POST",
400402
"path": "/mcp",
401403
"headers": [
404+
(b"accept", b"application/json, text/event-stream"),
402405
(b"content-type", b"application/json"),
403406
(b"mcp-session-id", session_id.encode()),
404407
],

0 commit comments

Comments
 (0)