Title: On Windows 11 when you initialize an mcp client it hangs indefinitely · Issue #552 · modelcontextprotocol/python-sdk · GitHub
Open Graph Title: On Windows 11 when you initialize an mcp client it hangs indefinitely · Issue #552 · modelcontextprotocol/python-sdk
X Title: On Windows 11 when you initialize an mcp client it hangs indefinitely · Issue #552 · modelcontextprotocol/python-sdk
Description: Describe the bug On Windows 11 when you initialize an mcp client it hangs indefinitely. To Reproduce Code to reproduce: # ruff: noqa import asyncio from mcp import ClientSession, StdioServerParameters from mcp.client.sse import sse_clien...
Open Graph Description: Describe the bug On Windows 11 when you initialize an mcp client it hangs indefinitely. To Reproduce Code to reproduce: # ruff: noqa import asyncio from mcp import ClientSession, StdioServerParamet...
X Description: Describe the bug On Windows 11 when you initialize an mcp client it hangs indefinitely. To Reproduce Code to reproduce: # ruff: noqa import asyncio from mcp import ClientSession, StdioServerParamet...
Opengraph URL: https://github.com/modelcontextprotocol/python-sdk/issues/552
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"On Windows 11 when you initialize an mcp client it hangs indefinitely","articleBody":"**Describe the bug**\nOn Windows 11 when you initialize an mcp client it hangs indefinitely.\n\n**To Reproduce**\nCode to reproduce:\n```python\n# ruff: noqa\nimport asyncio\n\nfrom mcp import ClientSession, StdioServerParameters\nfrom mcp.client.sse import sse_client\nfrom mcp.client.stdio import stdio_client\n\n\nasync def run():\n params = StdioServerParameters(\n command='bunx', args=['@playwright/mcp@latest']\n )\n async with stdio_client(params) as (read, write):\n print('inside client')\n async with ClientSession(read, write) as c:\n print('inside ClientSession')\n await c.initialize()\n print('exit ClientSession')\n print('exit stdio_client')\n\n\nasync def run_sse():\n async with sse_client('http://localhost:8931/sse') as (read, write):\n async with ClientSession(read, write) as c:\n await c.initialize()\n print('exit ClientSession')\n print('exit sse_client')\n\n\nif __name__ == '__main__':\n asyncio.run(run_sse()) # works\n asyncio.run(run()) # does not work\n\n```\n\n**Expected behavior**\nin both cases it should print both exit statements\n\n**Desktop (please complete the following information):**\n - OS: Windows 11\n - Python Version: Tested on both 3.13.1 and 3.12.7\n\n\n**Additional context**\ncounterintuitively commenting out the code meant to support windows fixes this issue:\n```python\nimport os\nimport sys\nfrom contextlib import asynccontextmanager\nfrom pathlib import Path\nfrom typing import Literal, TextIO\n\nimport anyio\nimport anyio.lowlevel\nfrom anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream\nfrom anyio.streams.text import TextReceiveStream\nfrom pydantic import BaseModel, Field\n\nimport mcp.types as types\n\n# from .win32 import (\n# create_windows_process,\n# get_windows_executable_command,\n# terminate_windows_process,\n# )\n\n# Environment variables to inherit by default\nDEFAULT_INHERITED_ENV_VARS = (\n [\n \"APPDATA\",\n \"HOMEDRIVE\",\n \"HOMEPATH\",\n \"LOCALAPPDATA\",\n \"PATH\",\n \"PROCESSOR_ARCHITECTURE\",\n \"SYSTEMDRIVE\",\n \"SYSTEMROOT\",\n \"TEMP\",\n \"USERNAME\",\n \"USERPROFILE\",\n ]\n if sys.platform == \"win32\"\n else [\"HOME\", \"LOGNAME\", \"PATH\", \"SHELL\", \"TERM\", \"USER\"]\n)\nprint( sys.platform)\n\ndef get_default_environment() -\u003e dict[str, str]:\n \"\"\"\n Returns a default environment object including only environment variables deemed\n safe to inherit.\n \"\"\"\n env: dict[str, str] = {}\n\n for key in DEFAULT_INHERITED_ENV_VARS:\n value = os.environ.get(key)\n if value is None:\n continue\n\n if value.startswith(\"()\"):\n # Skip functions, which are a security risk\n continue\n\n env[key] = value\n\n return env\n\n\nclass StdioServerParameters(BaseModel):\n command: str\n \"\"\"The executable to run to start the server.\"\"\"\n\n args: list[str] = Field(default_factory=list)\n \"\"\"Command line arguments to pass to the executable.\"\"\"\n\n env: dict[str, str] | None = None\n \"\"\"\n The environment to use when spawning the process.\n\n If not specified, the result of get_default_environment() will be used.\n \"\"\"\n\n cwd: str | Path | None = None\n \"\"\"The working directory to use when spawning the process.\"\"\"\n\n encoding: str = \"utf-8\"\n \"\"\"\n The text encoding used when sending/receiving messages to the server\n\n defaults to utf-8\n \"\"\"\n\n encoding_error_handler: Literal[\"strict\", \"ignore\", \"replace\"] = \"strict\"\n \"\"\"\n The text encoding error handler.\n\n See https://docs.python.org/3/library/codecs.html#codec-base-classes for\n explanations of possible values\n \"\"\"\n\n\n@asynccontextmanager\nasync def stdio_client(server: StdioServerParameters, errlog: TextIO = sys.stderr):\n \"\"\"\n Client transport for stdio: this will connect to a server by spawning a\n process and communicating with it over stdin/stdout.\n \"\"\"\n read_stream: MemoryObjectReceiveStream[types.JSONRPCMessage | Exception]\n read_stream_writer: MemoryObjectSendStream[types.JSONRPCMessage | Exception]\n\n write_stream: MemoryObjectSendStream[types.JSONRPCMessage]\n write_stream_reader: MemoryObjectReceiveStream[types.JSONRPCMessage]\n\n read_stream_writer, read_stream = anyio.create_memory_object_stream(0)\n write_stream, write_stream_reader = anyio.create_memory_object_stream(0)\n\n command = _get_executable_command(server.command)\n\n # Open process with stderr piped for capture\n process = await _create_platform_compatible_process(\n command=command,\n args=server.args,\n env=(\n {**get_default_environment(), **server.env}\n if server.env is not None\n else get_default_environment()\n ),\n errlog=errlog,\n cwd=server.cwd,\n )\n\n async def stdout_reader():\n assert process.stdout, \"Opened process is missing stdout\"\n\n try:\n async with read_stream_writer:\n buffer = \"\"\n async for chunk in TextReceiveStream(\n process.stdout,\n encoding=server.encoding,\n errors=server.encoding_error_handler,\n ):\n lines = (buffer + chunk).split(\"\\n\")\n buffer = lines.pop()\n\n for line in lines:\n try:\n message = types.JSONRPCMessage.model_validate_json(line)\n except Exception as exc:\n await read_stream_writer.send(exc)\n continue\n\n await read_stream_writer.send(message)\n except anyio.ClosedResourceError:\n await anyio.lowlevel.checkpoint()\n\n async def stdin_writer():\n assert process.stdin, \"Opened process is missing stdin\"\n\n try:\n async with write_stream_reader:\n async for message in write_stream_reader:\n json = message.model_dump_json(by_alias=True, exclude_none=True)\n await process.stdin.send(\n (json + \"\\n\").encode(\n encoding=server.encoding,\n errors=server.encoding_error_handler,\n )\n )\n except anyio.ClosedResourceError:\n await anyio.lowlevel.checkpoint()\n\n async with (\n anyio.create_task_group() as tg,\n process,\n ):\n tg.start_soon(stdout_reader)\n tg.start_soon(stdin_writer)\n try:\n yield read_stream, write_stream\n finally:\n # Clean up process to prevent any dangling orphaned processes\n # if sys.platform == \"win32\":\n # await terminate_windows_process(process)\n # else:\n process.terminate()\n\n\ndef _get_executable_command(command: str) -\u003e str:\n \"\"\"\n Get the correct executable command normalized for the current platform.\n\n Args:\n command: Base command (e.g., 'uvx', 'npx')\n\n Returns:\n str: Platform-appropriate command\n \"\"\"\n # if sys.platform == \"win32\":\n # return get_windows_executable_command(command)\n # else:\n return command\n\n\nasync def _create_platform_compatible_process(\n command: str,\n args: list[str],\n env: dict[str, str] | None = None,\n errlog: TextIO = sys.stderr,\n cwd: Path | str | None = None,\n):\n \"\"\"\n Creates a subprocess in a platform-compatible way.\n Returns a process handle.\n \"\"\"\n # if sys.platform == \"win32\":\n # print('attempting create windows process')\n # process = await create_windows_process(command, args, env, errlog, cwd)\n # print('created windows process')\n # else:\n process = await anyio.open_process(\n [command, *args], env=env, stderr=errlog, cwd=cwd\n )\n\n return process\n\n```","author":{"url":"https://github.com/BenMawnMahlauNBTC","@type":"Person","name":"BenMawnMahlauNBTC"},"datePublished":"2025-04-21T16:03:05.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":15},"url":"https://github.com/552/python-sdk/issues/552"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:c9722cfe-c68b-05ee-487d-0fd43d8ce5d6 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | E71E:2D7422:3CFE20:52667B:6A5A62B0 |
| html-safe-nonce | c71f6741e0066ff8efa5eed4f80f0ddb18042443a1a066e1ec8eb9ed9cdb5c96 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFNzFFOjJENzQyMjozQ0ZFMjA6NTI2NjdCOjZBNUE2MkIwIiwidmlzaXRvcl9pZCI6IjM5ODU2NjM1NjU4MTA1MjQ4NDgiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 53a46f7be96739c259a12ff12784a03b182152cd8fcac267fa41f582334fcf24 |
| hovercard-subject-tag | issue:3008755343 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/modelcontextprotocol/python-sdk/552/issue_layout |
| twitter:image | https://opengraph.githubassets.com/d93d4d80ea0728ddd6930c72ebd6c46d34b52d99e55b1e4b731e2f70b1ab7018/modelcontextprotocol/python-sdk/issues/552 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/d93d4d80ea0728ddd6930c72ebd6c46d34b52d99e55b1e4b731e2f70b1ab7018/modelcontextprotocol/python-sdk/issues/552 |
| og:image:alt | Describe the bug On Windows 11 when you initialize an mcp client it hangs indefinitely. To Reproduce Code to reproduce: # ruff: noqa import asyncio from mcp import ClientSession, StdioServerParamet... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | BenMawnMahlauNBTC |
| hostname | github.com |
| expected-hostname | github.com |
| None | 05b9ddf6a47d2dbe13944873a99f5fb4b83ba4871f9cb8a8e256793a63ca9687 |
| turbo-cache-control | no-preview |
| go-import | github.com/modelcontextprotocol/python-sdk git https://github.com/modelcontextprotocol/python-sdk.git |
| octolytics-dimension-user_id | 182288589 |
| octolytics-dimension-user_login | modelcontextprotocol |
| octolytics-dimension-repository_id | 862584018 |
| octolytics-dimension-repository_nwo | modelcontextprotocol/python-sdk |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 862584018 |
| octolytics-dimension-repository_network_root_nwo | modelcontextprotocol/python-sdk |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | f8d29d1bd03dda2dd14b3f80b8bc27e1111f43bd |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width