fix(stdio): drain pending responses before closing read stream on EOF (#2678)#2821
Open
friendlygeorge wants to merge 2 commits into
Open
fix(stdio): drain pending responses before closing read stream on EOF (#2678)#2821friendlygeorge wants to merge 2 commits into
friendlygeorge wants to merge 2 commits into
Conversation
Closes modelcontextprotocol#2678. When stdin hits EOF, the previous code closed read_stream_writer inside the `async with` block, which cascaded to close write_stream_reader before the server's pending responses could drain through stdout_writer. The fix removes the `async with read_stream_writer` wrapper from stdin_reader and instead calls `aclose()` in the `finally` block. This ensures: 1. All stdin lines are read and forwarded to the server 2. The read stream is closed promptly on EOF (signaling the server) 3. Buffered responses in write_stream_reader drain through stdout_writer before the task group exits All existing tests pass. Added regression test verifying responses are not dropped when stdin closes immediately after a request.
friendlygeorge
pushed a commit
to friendlygeorge/python-sdk
that referenced
this pull request
Jun 8, 2026
Both close() and __del__ are no-op overrides that prevent TextIOWrapper from closing real stdio handles. They are not directly tested in this PR (the test is on modelcontextprotocol#2821) and __del__ relies on GC timing which is unreliable in tests.
- Collapse multi-line io.BytesIO() to single line (ruff format) - Add blank line after module docstring (ruff format) - Remove unused imports: time, anyio (ruff check --fix)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #2678 — stdio transport drops in-flight server responses when the server process exits.
Problem
When a stdio MCP server exits, the client's closes on EOF before the server's pending responses are fully drained. This causes the client to lose responses that were already sent but not yet consumed.
Root Cause
calls on the stream immediately when EOF is detected, which signals the read loop to stop — even if there are buffered responses still in flight.
Fix
Replace the context manager with explicit in a block, allowing all pending responses to drain before the stream is closed.
All 10 existing stdio tests pass. Added test confirming pending responses are delivered before EOF.