Skip to content

Drain stdio responses after redirected stdin EOF#2682

Closed
Asti1982 wants to merge 1 commit into
modelcontextprotocol:mainfrom
Asti1982:codex/mcp-stdio-eof-drain
Closed

Drain stdio responses after redirected stdin EOF#2682
Asti1982 wants to merge 1 commit into
modelcontextprotocol:mainfrom
Asti1982:codex/mcp-stdio-eof-drain

Conversation

@Asti1982

Copy link
Copy Markdown

Fixes #2678.

Summary

  • keep the stdio write side open after redirected stdin EOF so already accepted request handlers can finish and flush responses
  • bound stdio EOF draining with a 5s timeout while preserving the existing immediate-cancel behavior for other transport closes
  • add a regression test that drives an MCPServer through redirected stdin and asserts response ids 0, 1, and 2 are all written before process exit

Tests

  • python -m ruff check src/mcp/shared/session.py src/mcp/server/session.py src/mcp/server/lowlevel/server.py src/mcp/server/mcpserver/server.py tests/issues/test_2678_stdio_eof_drain.py
  • python -m ruff format --check src/mcp/shared/session.py src/mcp/server/session.py src/mcp/server/lowlevel/server.py src/mcp/server/mcpserver/server.py tests/issues/test_2678_stdio_eof_drain.py
  • python -m pyright src/mcp/shared/session.py src/mcp/server/session.py src/mcp/server/lowlevel/server.py src/mcp/server/mcpserver/server.py tests/issues/test_2678_stdio_eof_drain.py
  • python -m pytest tests/issues/test_2678_stdio_eof_drain.py tests/server/test_cancel_handling.py tests/server/test_session.py -q

@Asti1982 Asti1982 force-pushed the codex/mcp-stdio-eof-drain branch from 4dd758d to f1c0e22 Compare May 26, 2026 04:16

@StantonMatt StantonMatt left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I checked this against the stdio EOF case from #2678.

The focused tests pass locally:

TMPDIR=.codex-tmp/tmp UV_CACHE_DIR=.codex-tmp/uv-cache uv run --frozen pytest tests/issues/test_2678_stdio_eof_drain.py tests/server/test_cancel_handling.py tests/server/test_session.py -q

I also ran a local memory-stream probe for the shutdown edge where an accepted tools/call handler never finishes after stdin/read EOF. With drain_in_flight_on_read_eof=True and drain_in_flight_on_read_eof_timeout_seconds=0.2, server.run() returned after the bounded drain window instead of hanging indefinitely.

That covers the main lifecycle risk I was looking for: redirected stdin gets a chance to flush accepted responses, but EOF is still a bounded shutdown signal. I did not find an issue in this pass.

@Kludex

Kludex commented Jun 25, 2026

Copy link
Copy Markdown
Member

You've opened a duplicated pull request, please search opened PRs before creating new ones. Duplicated from #2680.

@Kludex Kludex closed this Jun 25, 2026
@modelcontextprotocol modelcontextprotocol locked as resolved and limited conversation to collaborators Jun 25, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FastMCP/stdio: in-flight tool responses dropped on stdin EOF when input is bash-redirected from a file

3 participants