Skip to content

Commit a675bd5

Browse files
Extract Windows fallback process creation to separate function
Refactor create_windows_process to improve readability by extracting the fallback logic into _create_windows_fallback_process. This: - Reduces nesting and complexity in the main function - Makes the primary vs fallback paths clearer - Improves testability of the fallback logic - Better separates concerns between anyio and subprocess approaches No functional changes, just code organization.
1 parent 475b1c2 commit a675bd5

File tree

1 file changed

+50
-25
lines changed

1 file changed

+50
-25
lines changed

src/mcp/client/stdio/win32.py

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -159,31 +159,7 @@ async def create_windows_process(
159159
)
160160
return process
161161
except NotImplementedError:
162-
# Fall back to subprocess.Popen for SelectorEventLoop compatibility
163-
try:
164-
popen_obj = subprocess.Popen(
165-
[command, *args],
166-
stdin=subprocess.PIPE,
167-
stdout=subprocess.PIPE,
168-
stderr=errlog,
169-
env=env,
170-
cwd=cwd,
171-
bufsize=0, # Unbuffered output
172-
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0),
173-
)
174-
return FallbackProcess(popen_obj)
175-
except Exception:
176-
# If creationflags failed, try without them
177-
popen_obj = subprocess.Popen(
178-
[command, *args],
179-
stdin=subprocess.PIPE,
180-
stdout=subprocess.PIPE,
181-
stderr=errlog,
182-
env=env,
183-
cwd=cwd,
184-
bufsize=0,
185-
)
186-
return FallbackProcess(popen_obj)
162+
return _create_windows_fallback_process(command, args, env, errlog, cwd)
187163
except Exception:
188164
# If anyio failed for other reasons, try without creation flags
189165
process = await anyio.open_process(
@@ -193,3 +169,52 @@ async def create_windows_process(
193169
cwd=cwd,
194170
)
195171
return process
172+
173+
174+
def _create_windows_fallback_process(
175+
command: str,
176+
args: list[str],
177+
env: dict[str, str] | None = None,
178+
errlog: TextIO | None = sys.stderr,
179+
cwd: Path | str | None = None,
180+
) -> FallbackProcess:
181+
"""
182+
Create a FallbackProcess using subprocess.Popen.
183+
184+
This is used when anyio.open_process is not available (e.g., on SelectorEventLoop).
185+
186+
Args:
187+
command: The executable to run
188+
args: List of command line arguments
189+
env: Environment variables
190+
errlog: Where to send stderr output (defaults to sys.stderr)
191+
cwd: Working directory for the subprocess
192+
193+
Returns:
194+
FallbackProcess: Async-compatible subprocess wrapper
195+
"""
196+
try:
197+
# Try launching with creationflags to avoid opening a new console window
198+
popen_obj = subprocess.Popen(
199+
[command, *args],
200+
stdin=subprocess.PIPE,
201+
stdout=subprocess.PIPE,
202+
stderr=errlog,
203+
env=env,
204+
cwd=cwd,
205+
bufsize=0, # Unbuffered output
206+
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0),
207+
)
208+
return FallbackProcess(popen_obj)
209+
except Exception:
210+
# If creationflags failed, try without them
211+
popen_obj = subprocess.Popen(
212+
[command, *args],
213+
stdin=subprocess.PIPE,
214+
stdout=subprocess.PIPE,
215+
stderr=errlog,
216+
env=env,
217+
cwd=cwd,
218+
bufsize=0,
219+
)
220+
return FallbackProcess(popen_obj)

0 commit comments

Comments
 (0)