Skip to content

Commit e88a107

Browse files
committed
Fix Windows stdio client issues: wrap stderr in FallbackProcess, correct PIPE usage, fix pyright errors
1 parent cee78d3 commit e88a107

File tree

2 files changed

+11
-5
lines changed

2 files changed

+11
-5
lines changed

src/mcp/client/stdio.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
from __future__ import annotations
2+
13
import logging
24
import os
35
import sys
6+
import subprocess
47
from contextlib import asynccontextmanager
58
from pathlib import Path
69
from typing import Literal, TextIO
@@ -20,8 +23,8 @@
2023
get_windows_executable_command,
2124
terminate_windows_process_tree,
2225
)
23-
from mcp.shared.message import SessionMessage
2426
from mcp.shared.jupyter import is_jupyter
27+
from mcp.shared.message import SessionMessage
2528

2629
logger = logging.getLogger(__name__)
2730

@@ -123,7 +126,7 @@ async def stdio_client(server: StdioServerParameters, errlog: TextIO = sys.stder
123126
# because sys.stderr redirection might not be reliable for subprocesses.
124127
actual_errlog = errlog
125128
if is_jupyter():
126-
actual_errlog = anyio.lowlevel.PIPE
129+
actual_errlog = subprocess.PIPE
127130

128131
# Open process with stderr piped for capture
129132
process = await _create_platform_compatible_process(

src/mcp/os/win32/utilities.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,11 @@ def __init__(self, popen_obj: subprocess.Popen[bytes]):
7575
self.popen: subprocess.Popen[bytes] = popen_obj
7676
self.stdin_raw = popen_obj.stdin # type: ignore[assignment]
7777
self.stdout_raw = popen_obj.stdout # type: ignore[assignment]
78-
self.stderr = popen_obj.stderr # type: ignore[assignment]
78+
self.stderr_raw = popen_obj.stderr # type: ignore[assignment]
7979

8080
self.stdin = FileWriteStream(cast(BinaryIO, self.stdin_raw)) if self.stdin_raw else None
8181
self.stdout = FileReadStream(cast(BinaryIO, self.stdout_raw)) if self.stdout_raw else None
82+
self.stderr = FileReadStream(cast(BinaryIO, self.stderr_raw)) if self.stderr_raw else None
8283

8384
async def __aenter__(self):
8485
"""Support async context manager entry."""
@@ -99,12 +100,14 @@ async def __aexit__(
99100
await self.stdin.aclose()
100101
if self.stdout:
101102
await self.stdout.aclose()
103+
if self.stderr:
104+
await self.stderr.aclose()
102105
if self.stdin_raw:
103106
self.stdin_raw.close()
104107
if self.stdout_raw:
105108
self.stdout_raw.close()
106-
if self.stderr:
107-
self.stderr.close()
109+
if self.stderr_raw:
110+
self.stderr_raw.close()
108111

109112
async def wait(self):
110113
"""Async wait for process completion."""

0 commit comments

Comments
 (0)