Skip to content

Commit cacd81b

Browse files
author
PR-Contributor
committed
fix(server): prevent stdio transport from closing original stdio handles
When using transport='stdio', the stdio_server context manager wraps sys.stdin.buffer and sys.stdout.buffer in TextIOWrapper. When these wrappers are closed (either explicitly or when exiting the context), they also close the underlying buffers, causing subsequent stdio operations to fail with ValueError. This fix duplicates the file descriptors before wrapping them, so that the original stdin/stdout remain open after the transport is closed. Fixes #1933
1 parent d5b9155 commit cacd81b

File tree

1 file changed

+9
-2
lines changed

1 file changed

+9
-2
lines changed

src/mcp/server/stdio.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ async def run_server():
1717
```
1818
"""
1919

20+
import os
2021
import sys
2122
from contextlib import asynccontextmanager
2223
from io import TextIOWrapper
@@ -38,10 +39,16 @@ async def stdio_server(stdin: anyio.AsyncFile[str] | None = None, stdout: anyio.
3839
# standard process handles. Encoding of stdin/stdout as text streams on
3940
# python is platform-dependent (Windows is particularly problematic), so we
4041
# re-wrap the underlying binary stream to ensure UTF-8.
42+
# We duplicate the file descriptors to avoid closing the original stdio
43+
# when the transport is closed (fixes issue #1933).
4144
if not stdin:
42-
stdin = anyio.wrap_file(TextIOWrapper(sys.stdin.buffer, encoding="utf-8", errors="replace"))
45+
stdin_fd = os.dup(sys.stdin.fileno())
46+
stdin_bin = os.fdopen(stdin_fd, "rb", closefd=True)
47+
stdin = anyio.wrap_file(TextIOWrapper(stdin_bin, encoding="utf-8", errors="replace"))
4348
if not stdout:
44-
stdout = anyio.wrap_file(TextIOWrapper(sys.stdout.buffer, encoding="utf-8"))
49+
stdout_fd = os.dup(sys.stdout.fileno())
50+
stdout_bin = os.fdopen(stdout_fd, "wb", closefd=True)
51+
stdout = anyio.wrap_file(TextIOWrapper(stdout_bin, encoding="utf-8"))
4552

4653
read_stream_writer, read_stream = create_context_streams[SessionMessage | Exception](0)
4754
write_stream, write_stream_reader = create_context_streams[SessionMessage](0)

0 commit comments

Comments
 (0)