You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Streamlit集成MCP Client遇NotImplemented错误求助

Streamlit集成MCP Client时的NotImplementedError问题解决

错误原因

从错误栈追踪可知,问题根源在于Windows系统下Streamlit默认使用的SelectorEventLoop不支持异步子进程操作。当MCP Client尝试通过anyio/asyncio创建子进程时,SelectorEventLoop的_make_subprocess_transport方法直接抛出NotImplementedError。nest_asyncio未生效的原因是Streamlit的事件循环初始化逻辑会覆盖手动设置的循环,导致ProactorEventLoop没被正确启用。

解决方案

方案1:强制启用ProactorEventLoop并修复nest_asyncio应用时机

在Streamlit脚本最顶部添加以下代码,确保事件循环在Streamlit初始化前就被替换:

import asyncio
import nest_asyncio
import sys

if sys.platform == "win32":
    # Windows下强制使用支持子进程的ProactorEventLoop
    asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
# 应用nest_asyncio允许嵌套事件循环
nest_asyncio.apply()

import streamlit as st
# 后续代码...

方案2:将MCP Client异步操作移至独立线程

避免在Streamlit的事件循环中直接运行异步子进程操作,用线程隔离:

import threading
import asyncio

# 封装MCP连接逻辑为同步函数
def run_mcp_connection(script_path):
    mcp_client = MCPClient()
    asyncio.run(mcp_client.connect_to_server(script_path))

# Streamlit按钮逻辑修改
available_scripts = ["mcp_server1.py", "mcp_server2.py"]
selected_script = st.selectbox("MCP server script", available_scripts)
if st.button("Enable MCP server"):
    # 启动线程执行MCP连接
    threading.Thread(target=run_mcp_connection, args=(selected_script,), daemon=True).start()
    st.success("MCP server connection started in background")

方案3:使用Streamlit的异步支持特性

Streamlit 1.28+支持异步函数作为回调,可直接使用st.button的on_click参数绑定异步函数(需确保事件环已正确配置):

async def connect_mcp(script_path):
    mcp_client = MCPClient()
    await mcp_client.connect_to_server(script_path)
    st.success("MCP server connected successfully")

available_scripts = ["mcp_server1.py", "mcp_server2.py"]
selected_script = st.selectbox("MCP server script", available_scripts)
st.button("Enable MCP server", on_click=connect_mcp, args=(selected_script,))

相关代码片段

Streamlit原代码

available_scripts = ["mcp_server1.py", "mcp_server2.py"]
selected_script = st.selectbox("MCP server script", available_scripts)
if st.button("Enable MCP server"):
    mcp_client = MCPClient()
    asyncio.run(mcp_client.connect_to_server(selected_script))

MCPClient实现代码

class MCPClient:
    def __init__(self):
        self.session: ClientSession | None = None
        self.exit_stack = AsyncExitStack()

    async def connect_to_server(self, server_script_path: str):
        is_python = server_script_path.endswith(".py")
        is_js = server_script_path.endswith(".js")
        if not (is_python or is_js):
            raise ValueError("Server script must be a .py or .js file")
        command = "python" if is_python else "node"
        server_params = StdioServerParameters(
            command=command,
            args=[server_script_path],
            env=None
        )

        stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
        self.stdio, self.write = stdio_transport
        self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))

        await self.session.initialize()

完整错误栈

File "C:\Users\danid\Documents\Personal\Projects\llm_chat_room\.venv\Lib\site-packages\streamlit\runtime\scriptrunner\exec_code.py", line 121, in exec_func_with_error_handling
    result = func()
             ^^^^^^
File "C:\Users\danid\Documents\Personal\Projects\llm_chat_room\.venv\Lib\site-packages\streamlit\runtime\scriptrunner\script_runner.py", line 595, in code_to_exec
    self._session_state.on_script_will_rerun(
File "C:\Users\danid\Documents\Personal\Projects\llm_chat_room\.venv\Lib\site-packages\streamlit\runtime\state\safe_session_state.py", line 68, in on_script_will_rerun
    self._state.on_script_will_rerun(latest_widget_states)
File "C:\Users\danid\Documents\Personal\Projects\llm_chat_room\.venv\Lib\site-packages\streamlit\runtime\state\session_state.py", line 558, in on_script_will_rerun
    self._call_callbacks()
File "C:\Users\danid\Documents\Personal\Projects\llm_chat_room\.venv\Lib\site-packages\streamlit\runtime\state\session_state.py", line 571, in _call_callbacks
    self._new_widget_state.call_callback(wid)
File "C:\Users\danid\Documents\Personal\Projects\llm_chat_room\.venv\Lib\site-packages\streamlit\runtime\state\session_state.py", line 272, in call_callback
    callback(*args, **kwargs)
File "C:\Users\danid\Documents\Personal\Projects\llm_chat_room\app.py", line 146, in toggle_mcp
    asyncio.run(mcp_client.test(st.session_state["mcp_script"]))
File "C:\Users\danid\Documents\Personal\Projects\llm_chat_room\.venv\Lib\site-packages\nest_asyncio.py", line 30, in run
    return loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\danid\Documents\Personal\Projects\llm_chat_room\.venv\Lib\site-packages\nest_asyncio.py", line 98, in run_until_complete
    return f.result()
           ^^^^^^^^^^
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\asyncio\futures.py", line 203, in result
    raise self._exception.with_traceback(self._exception_tb)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\asyncio\tasks.py", line 277, in __step
    result = coro.send(None)
             ^^^^^^^^^^^^^^^
File "C:\Users\danid\Documents\Personal\Projects\llm_chat_room\mcp_client.py", line 52, in test
    stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\contextlib.py", line 650, in enter_async_context
    result = await _enter(cm)
             ^^^^^^^^^^^^^^^^
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\contextlib.py", line 210, in __aenter__
    return await anext(self.gen)
           ^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\danid\Documents\Personal\Projects\llm_chat_room\.venv\Lib\site-packages\mcp\client\stdio\__init__.py", line 115, in stdio_client
    process = await _create_platform_compatible_process(
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\danid\Documents\Personal\Projects\llm_chat_room\.venv\Lib\site-packages\mcp\client\stdio\__init__.py", line 230, in _create_platform_compatible_process
    process = await create_windows_process(command, args, env, errlog, cwd)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\danid\Documents\Personal\Projects\llm_chat_room\.venv\Lib\site-packages\mcp\client\stdio\win32.py", line 85, in create_windows_process
    process = await anyio.open_process(
              ^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\danid\Documents\Personal\Projects\llm_chat_room\.venv\Lib\site-packages\anyio\_core\_subprocesses.py", line 190, in open_process
    return await get_async_backend().open_process(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\danid\Documents\Personal\Projects\llm_chat_room\.venv\Lib\site-packages\anyio\_backends\_asyncio.py", line 2561, in open_process
    process = await asyncio.create_subprocess_exec(
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\asyncio\subprocess.py", line 223, in create_subprocess_exec
    transport, protocol = await loop.subprocess_exec(
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\asyncio\base_events.py", line 1708, in subprocess_exec
    transport = await self._make_subprocess_transport(
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\asyncio\base_events.py", line 503, in _make_subprocess_transport
    raise NotImplementedError

内容的提问来源于stack exchange,提问作者someguy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 23:30:55