From 07b26130f6750a04824c54c728d3690612baa9fd Mon Sep 17 00:00:00 2001 From: g97iulio1609 Date: Sat, 28 Feb 2026 05:15:02 +0100 Subject: [PATCH 1/2] 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 --- src/mcp/server/stdio.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/mcp/server/stdio.py b/src/mcp/server/stdio.py index e526bab56..7b4c5cc7b 100644 --- a/src/mcp/server/stdio.py +++ b/src/mcp/server/stdio.py @@ -17,6 +17,7 @@ async def run_server(): ``` """ +import os import sys from contextlib import asynccontextmanager from io import TextIOWrapper @@ -39,9 +40,13 @@ async def stdio_server(stdin: anyio.AsyncFile[str] | None = None, stdout: anyio. # python is platform-dependent (Windows is particularly problematic), so we # re-wrap the underlying binary stream to ensure UTF-8. if not stdin: - stdin = anyio.wrap_file(TextIOWrapper(sys.stdin.buffer, encoding="utf-8")) + stdin = anyio.wrap_file( + TextIOWrapper(os.fdopen(os.dup(sys.stdin.fileno()), "rb"), encoding="utf-8") + ) if not stdout: - stdout = anyio.wrap_file(TextIOWrapper(sys.stdout.buffer, encoding="utf-8")) + stdout = anyio.wrap_file( + TextIOWrapper(os.fdopen(os.dup(sys.stdout.fileno()), "wb"), encoding="utf-8") + ) read_stream: MemoryObjectReceiveStream[SessionMessage | Exception] read_stream_writer: MemoryObjectSendStream[SessionMessage | Exception] From 8a2e85683234085d327bf48dba49ce153612da29 Mon Sep 17 00:00:00 2001 From: g97iulio1609 Date: Sat, 28 Feb 2026 14:05:54 +0100 Subject: [PATCH 2/2] style: apply ruff format --- src/mcp/server/stdio.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/mcp/server/stdio.py b/src/mcp/server/stdio.py index 7b4c5cc7b..332f809b7 100644 --- a/src/mcp/server/stdio.py +++ b/src/mcp/server/stdio.py @@ -40,13 +40,9 @@ async def stdio_server(stdin: anyio.AsyncFile[str] | None = None, stdout: anyio. # python is platform-dependent (Windows is particularly problematic), so we # re-wrap the underlying binary stream to ensure UTF-8. if not stdin: - stdin = anyio.wrap_file( - TextIOWrapper(os.fdopen(os.dup(sys.stdin.fileno()), "rb"), encoding="utf-8") - ) + stdin = anyio.wrap_file(TextIOWrapper(os.fdopen(os.dup(sys.stdin.fileno()), "rb"), encoding="utf-8")) if not stdout: - stdout = anyio.wrap_file( - TextIOWrapper(os.fdopen(os.dup(sys.stdout.fileno()), "wb"), encoding="utf-8") - ) + stdout = anyio.wrap_file(TextIOWrapper(os.fdopen(os.dup(sys.stdout.fileno()), "wb"), encoding="utf-8")) read_stream: MemoryObjectReceiveStream[SessionMessage | Exception] read_stream_writer: MemoryObjectSendStream[SessionMessage | Exception]