Skip to content

Error related to asyncio when using mcp with autogen on Windows 11 but not on CentOS 7 #6467

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
KamikazEr101 opened this issue May 6, 2025 · 3 comments
Assignees

Comments

@KamikazEr101
Copy link

KamikazEr101 commented May 6, 2025

What happened?

Describe the bug
When using AutoGen with McpWorkbench to connect and call a weather query MCP server on Windows 11, the business logic (e.g., listing tools and agent tool calls) executes correctly. However, after the business logic completes, an exception is raised related to unclosed transports and I/O operations on closed pipes. This issue does not occur on CentOS 7.9 with the same setup.

To Reproduce
Steps to reproduce the behavior:

  1. Set up a weather query MCP server using FastMCP on Windows 11.
  2. Use AutoGen's McpWorkbench to connect and call the server.
  3. Execute business logic that involves agent tool calls.
  4. Observe the exception after the business logic completes.

Code Example:

    weather_mcp_server = StdioServerParams(
        **MCP_PARAM_JSON,
    )
    
    model_client = OpenAIChatCompletionClient(model="gpt-4o-mini")
    
    async with McpWorkbench(server_params=weather_mcp_server) as mcp:
        agent = AssistantAgent(
            name="WeatherAgent",
            model_client=model_client,
            workbench=mcp,
        )
        
        team = RoundRobinGroupChat(
            participants=[agent],
            termination_condition=TextMessageTermination(source='WeatherAgent'),
        )
        
        await Console(
            team.run_stream(task="How is the weather like in Beijing?"),
            output_stats=True,
        )

Exception Traceback:

Exception ignored in: <function BaseSubprocessTransport.__del__ at 0x000001DFBE4B8400>
Traceback (most recent call last):
  File "D:\miniconda3data\condaenvs\llm_dev\Lib\asyncio\base_subprocess.py", line 125, in __del__
    _warn(f"unclosed transport {self!r}", ResourceWarning, source=self)
                               ^^^^^^^^
  File "D:\miniconda3data\condaenvs\llm_dev\Lib\asyncio\base_subprocess.py", line 78, in __repr__
    info.append(f'stdout={stdout.pipe}')
                         ^^^^^^^^^^^^^
  File "D:\miniconda3data\condaenvs\llm_dev\Lib\asyncio\proactor_events.py", line 80, in __repr__
    info.append(f'fd={self._sock.fileno()}')
                      ^^^^^^^^^^^^^^^^^^^
  File "D:\miniconda3data\condaenvs\llm_dev\Lib\asyncio\windows_utils.py", line 102, in fileno
    raise ValueError("I/O operation on closed pipe")
ValueError: I/O operation on closed pipe
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000001DFBE4B9BC0>
Traceback (most recent call last):
  File "D:\miniconda3data\condaenvs\llm_dev\Lib\asyncio\proactor_events.py", line 116, in __del__
    _warn(f"unclosed transport {self!r}", ResourceWarning, source=self)
                               ^^^^^^^^
  File "D:\miniconda3data\condaenvs\llm_dev\Lib\asyncio\proactor_events.py", line 80, in __repr__
    info.append(f'fd={self._sock.fileno()}')
                      ^^^^^^^^^^^^^^^^^^^
  File "D:\miniconda3data\condaenvs\llm_dev\Lib\asyncio\windows_utils.py", line 102, in fileno
    raise ValueError("I/O operation on closed pipe")
ValueError: I/O operation on closed pipe

Expected behavior
The program should complete without raising exceptions related to unclosed transports or I/O operations on closed pipes, as observed on CentOS 7.9.

Screenshots

Image

Image

Additional context

  • Operating System: Windows 11 (issue present), CentOS 7.9 (no issue)
  • MCP Server Setup: Using FastMCP for a weather query service.
  • MCP Server Source Code:

server.py

from mcp.server import FastMCP
import utils

mcp = FastMCP("weather")

@mcp.tool()
async def get_signature(city: str) -> str:
    """
    获取天气签名
    :param city: 城市名称
    :return: 签名
    """
    forecast = await utils.get_weather_simple(city)
    return f"天气签名: {city}的天气为 {forecast}"

@mcp.tool()
async def get_detail(city: str) -> str:
    """
    获取天气详情
    :param city: 城市名称
    :return: 详情
    """
    forecast = await utils.get_weather_description(city)
    return f"天气详情: \n{forecast}"

# Run the server
if __name__ == "__main__":
    print("Starting weather mcp server...")
    mcp.run(transport='stdio')

utils.py

import os
import httpx
from typing import Dict, Any

async def get_weather_dict(city: str) -> Dict[str, Any] | None:
    get_location_id_url = f'https://{os.getenv("WEATHER_API_HOST")}/geo/v2/city/lookup?location={city}&key={os.getenv("WEATHER_API_KEY")}'

    async with httpx.AsyncClient() as client:
        try:
            resp = await client.get(url=get_location_id_url)
            resp.raise_for_status()
            location_id = resp.json()['location'][0]['id']

            get_weather_url = f'https://{os.getenv("WEATHER_API_HOST")}/v7/weather/now?location={location_id}&key={os.getenv("WEATHER_API_KEY")}'
            resp = await client.get(url=get_weather_url)
            resp.raise_for_status()

            return resp.json()
        except Exception:
            return None

async def get_weather_simple(city: str) -> str:
    return (await get_weather_dict(city))['now']['text']

async def get_weather_description(city: str) -> str:
    weather_dict = await get_weather_dict(city)
    current_weather = weather_dict['now']
    return f"""
111当前温度: {current_weather['temp']}°C
体感温度: {current_weather['feelsLike']}°C
天气状况: {current_weather['text']}
湿度: {current_weather['humidity']}%
风速: {current_weather['windSpeed']} km/h
风向: {current_weather['windDir']}
气压: {current_weather['pressure']} hPa
能见度: {current_weather['vis']} km
"""

if __name__ == '__main__':
    import asyncio

    async def main():
        city = "北京"
        simple, description = await asyncio.gather(
            get_weather_simple(city),
            get_weather_description(city)
        )
        print(f"Simple: {simple}")
        print(f"Description: {description}")

    asyncio.run(main())
  • Call MCP From Autogen Source Code:
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.conditions import TextMessageTermination
from autogen_agentchat.ui import Console
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_ext.tools.mcp import McpWorkbench, StdioServerParams


MCP_PARAM_JSON = {
    "command": "uv",
    "args": [
    "--directory",
    "D:\\Codings\\myMCPs\\weather_mcp",
    "run",
    "server.py"
    ],
    "env": {
        "WEATHER_API_KEY": "EXAMPLE_KEY",
        "WEATHER_API_HOST": "EXAMPLE_HOST",
    }
}

async def main():
    weather_mcp_server = StdioServerParams(
        **MCP_PARAM_JSON,
    )
    
    model_client = OpenAIChatCompletionClient(model="gpt-4o-mini")
    
    async with McpWorkbench(server_params=weather_mcp_server) as mcp:
        agent = AssistantAgent(
            name="WeatherAgent",
            model_client=model_client,
            workbench=mcp,
        )
        
        team = RoundRobinGroupChat(
            participants=[agent],
            termination_condition=TextMessageTermination(source='WeatherAgent'),
        )
        
        await Console(
            team.run_stream(task="How is the weather like in Beijing?"),
            output_stats=True,
        )

if __name__ == "__main__":
    asyncio.run(main())

This issue appears to be specific to the Windows environment, possibly due to differences in how subprocesses or asynchronous I/O are handled in Python on Windows compared to Linux.

Which packages was the bug in?

Python Extensions (autogen-ext)

AutoGen library version.

Python 0.5.6

Python version

3.12

Operating system

Windows11 and CentOS7.9

@KamikazEr101 KamikazEr101 changed the title MCP Workbench Error on Windows 11 but not on CentOS 7 Error related to asyncio when using mcp with autgen on Windows 11 but not on CentOS 7 May 6, 2025
@KamikazEr101 KamikazEr101 changed the title Error related to asyncio when using mcp with autgen on Windows 11 but not on CentOS 7 Error related to asyncio when using mcp with autogen on Windows 11 but not on CentOS 7 May 6, 2025
@KamikazEr101
Copy link
Author

The initial diagnosis indicates that this error is caused by the resource cleanup when the program exits. The problem might lie in the specific implementation of McpWorkbench.

@jackgerrits
Copy link
Member

Now that #6497 is merged, could you try and repro again from main @KamikazEr101 ?

@KamikazEr101
Copy link
Author

Now that #6497 is merged, could you try and repro again from main @KamikazEr101 ?

Thanks for the update! I tested the bug with the latest main branch after #6497 was merged, but the issue still persists. Besides, I noticed that when running the code in debug mode on Windows 11, the bug does not occur, regardless of whether I use the latest main branch or the previous version. However, in normal mode (non-debug), the bug consistently appears on Windows 11.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants