Skip to content

Commit b46ebd6

Browse files
author
g97iulio1609
committed
fix: prevent stdio transport from closing real stdin/stdout
When using transport='stdio', the server wraps sys.stdin.buffer and sys.stdout.buffer in TextIOWrapper and anyio.AsyncFile. When these wrappers are garbage collected after the server exits, they close the underlying sys.stdin/sys.stdout, causing subsequent I/O operations to fail with ValueError. Use os.dup() to duplicate the file descriptors before wrapping them, so closing the wrapped streams only closes the duplicates, leaving the original stdin/stdout intact. Fixes #1933
1 parent 62575ed commit b46ebd6

1 file changed

Lines changed: 9 additions & 2 deletions

File tree

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 via os.dup() to avoid closing the
43+
# real sys.stdin/sys.stdout when the wrapped streams are closed.
4144
if not stdin:
42-
stdin = anyio.wrap_file(TextIOWrapper(sys.stdin.buffer, encoding="utf-8"))
45+
stdin = anyio.wrap_file(
46+
TextIOWrapper(os.fdopen(os.dup(sys.stdin.fileno()), "rb"), encoding="utf-8")
47+
)
4348
if not stdout:
44-
stdout = anyio.wrap_file(TextIOWrapper(sys.stdout.buffer, encoding="utf-8"))
49+
stdout = anyio.wrap_file(
50+
TextIOWrapper(os.fdopen(os.dup(sys.stdout.fileno()), "wb"), encoding="utf-8")
51+
)
4552

4653
read_stream: MemoryObjectReceiveStream[SessionMessage | Exception]
4754
read_stream_writer: MemoryObjectSendStream[SessionMessage | Exception]

0 commit comments

Comments
 (0)