11import os
22import shutil
3- import subprocess
43import sys
54import tempfile
65import textwrap
1211from mcp .client .session import ClientSession
1312from mcp .client .stdio import (
1413 StdioServerParameters ,
14+ _create_platform_compatible_process ,
1515 stdio_client ,
1616)
1717from mcp .shared .exceptions import McpError
@@ -28,27 +28,6 @@ def escape_path_for_python(path: str) -> str:
2828 return repr (path .replace ("\\ " , "/" ))
2929
3030
31- class WindowsProcessWrapper :
32- """Minimal wrapper for subprocess.Popen to work with anyio-style process interface."""
33-
34- def __init__ (self , popen ):
35- self .pid = popen .pid
36- self ._popen = popen
37- # Add popen attribute for compatibility with _terminate_process_with_children
38- self .popen = popen
39-
40- async def wait (self ):
41- while self ._popen .poll () is None :
42- await anyio .sleep (0.1 )
43- return self ._popen .returncode
44-
45- def terminate (self ):
46- self ._popen .terminate ()
47-
48- def kill (self ):
49- self ._popen .kill ()
50-
51-
5231@pytest .mark .anyio
5332@pytest .mark .skipif (tee is None , reason = "could not find tee command" )
5433async def test_stdio_context_manager_exiting ():
@@ -423,15 +402,8 @@ async def test_stdio_client_child_process_cleanup():
423402
424403 print ("\n Starting child process termination test..." )
425404
426- # Start the parent process directly with process group
427- if sys .platform == "win32" :
428- # Windows: Don't use CREATE_NEW_PROCESS_GROUP as it isolates the process
429- # Instead, let it inherit the parent's console which allows taskkill /T to work
430- popen = subprocess .Popen ([sys .executable , "-c" , parent_script ])
431- proc = WindowsProcessWrapper (popen )
432- else :
433- # Unix: Use start_new_session for process group creation
434- proc = await anyio .open_process ([sys .executable , "-c" , parent_script ], start_new_session = True )
405+ # Start the parent process
406+ proc = await _create_platform_compatible_process (sys .executable , ["-c" , parent_script ])
435407
436408 # Wait for processes to start
437409 await anyio .sleep (0.5 )
@@ -537,15 +509,8 @@ async def test_stdio_client_nested_process_tree():
537509 """
538510 )
539511
540- # Start parent process directly
541- if sys .platform == "win32" :
542- # Windows: Don't use CREATE_NEW_PROCESS_GROUP as it isolates the process
543- # Instead, let it inherit the parent's console which allows taskkill /T to work
544- popen = subprocess .Popen ([sys .executable , "-c" , parent_script ])
545- proc = WindowsProcessWrapper (popen )
546- else :
547- # Unix: Use start_new_session for process group creation
548- proc = await anyio .open_process ([sys .executable , "-c" , parent_script ], start_new_session = True )
512+ # Start the parent process
513+ proc = await _create_platform_compatible_process (sys .executable , ["-c" , parent_script ])
549514
550515 # Let all processes start
551516 await anyio .sleep (1.0 )
@@ -629,14 +594,7 @@ def handle_term(sig, frame):
629594 )
630595
631596 # Start the parent process
632- if sys .platform == "win32" :
633- # Windows: Don't use CREATE_NEW_PROCESS_GROUP as it isolates the process
634- # Instead, let it inherit the parent's console which allows taskkill /T to work
635- popen = subprocess .Popen ([sys .executable , "-c" , parent_script ])
636- proc = WindowsProcessWrapper (popen )
637- else :
638- # Unix: Use start_new_session for process group creation
639- proc = await anyio .open_process ([sys .executable , "-c" , parent_script ], start_new_session = True )
597+ proc = await _create_platform_compatible_process (sys .executable , ["-c" , parent_script ])
640598
641599 # Let child start writing
642600 await anyio .sleep (0.5 )
0 commit comments