Skip to content

Commit c606382

Browse files
g97iulio1609Copilot
andcommitted
fix: use os.dup() to prevent stdio transport from closing real stdin/stdout
When stdio_server() wraps sys.stdin.buffer / sys.stdout.buffer in TextIOWrapper, closing or GC'ing the wrapper also closes the underlying buffer, making sys.stdin/sys.stdout unusable after the server exits. Use os.dup() to duplicate the file descriptors before wrapping, so the wrappers own independent descriptors that can be safely closed without affecting the original stdio handles. Fixes #1933 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 62575ed commit c606382

1 file changed

Lines changed: 7 additions & 2 deletions

File tree

src/mcp/server/stdio.py

Lines changed: 7 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
@@ -39,9 +40,13 @@ async def stdio_server(stdin: anyio.AsyncFile[str] | None = None, stdout: anyio.
3940
# python is platform-dependent (Windows is particularly problematic), so we
4041
# re-wrap the underlying binary stream to ensure UTF-8.
4142
if not stdin:
42-
stdin = anyio.wrap_file(TextIOWrapper(sys.stdin.buffer, encoding="utf-8"))
43+
stdin = anyio.wrap_file(
44+
TextIOWrapper(os.fdopen(os.dup(sys.stdin.fileno()), "rb"), encoding="utf-8")
45+
)
4346
if not stdout:
44-
stdout = anyio.wrap_file(TextIOWrapper(sys.stdout.buffer, encoding="utf-8"))
47+
stdout = anyio.wrap_file(
48+
TextIOWrapper(os.fdopen(os.dup(sys.stdout.fileno()), "wb"), encoding="utf-8")
49+
)
4550

4651
read_stream: MemoryObjectReceiveStream[SessionMessage | Exception]
4752
read_stream_writer: MemoryObjectSendStream[SessionMessage | Exception]

0 commit comments

Comments
 (0)