Skip to content

Commit 07b2613

Browse files
author
g97iulio1609
committed
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
1 parent 62575ed commit 07b2613

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)