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

FastMCP客户端初始化会话超时问题求助

FastMCP Streamable-HTTP 会话初始化超时问题

本地启动了一个简单的FastMCP streamable-HTTP服务器,但客户端连接时会话初始化阶段超时。尝试开启FastMCP实例的json_response和stateless_http参数后问题依旧。SSE传输能正常工作但已被弃用,且API网关不支持SSE,无法采用该方案。

服务端代码

from mcp.server.fastmcp import FastMCP


server = FastMCP(
    name="Example-FastMCP",
    streamable_http_path="/mcp",   # ← 显式写出默认值以明确
    # json_response=True,
    # stateless_http=True
)


@server.tool()
def add(x: int, y: int) -> int:
    return x + y


if __name__ == "__main__":
    server.run(transport="streamable-http")

客户端代码

import asyncio
from datetime import timedelta

from mcp.client.streamable_http import streamablehttp_client          # <- 指定传输方式
from mcp.client.session import ClientSession                          # <- 高层API

SERVER_URL = "http://127.0.0.1:8000/mcp/"


async def main() -> None:
    async with streamablehttp_client(
        url=SERVER_URL,
        timeout=100,
        sse_read_timeout=300,
    ) as (read_stream, write_stream, get_session_id):
        session = ClientSession(
            read_stream=read_stream,
            write_stream=write_stream,
            read_timeout_seconds=timedelta(seconds=100),
        )
        init_result = await session.initialize()
        print(" 初始化完成 – 协议版本:", init_result.protocolVersion)
        print(" 从服务器获取的会话ID:", get_session_id())

        tools_result = await session.list_tools()
        tool_names = [tool.name for tool in tools_result.tools]
        print(" 服务器可用工具:", tool_names)

        call_result = await session.call_tool("add", {"x": 2, "y": 3})
        print(" add(2, 3) =", call_result.output[0].text)


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

客户端日志

/Users/susai/repos/ds-mcp/.venv/bin/python /Users/susai/repos/ds-mcp/app/client3.py 
  + Exception Group Traceback (most recent call last):
  |   File "/Users/susai/repos/ds-mcp/app/client3.py", line 34, in <module>
  |     asyncio.run(main())
  |     ~~~~~~~~~~~^^^^^^^^
  |   File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/runners.py", line 195, in run
  |     return runner.run(main)
  |            ~~~~~~~~~~^^^^^^
  |   File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/runners.py", line 118, in run
  |     return self._loop.run_until_complete(task)
  |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  |   File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/base_events.py", line 725, in run_until_complete
  |     return future.result()
  |            ~~~~~~~~~~~~~^^
  |   File "/Users/susai/repos/ds-mcp/app/client3.py", line 11, in main
  |     async with streamablehttp_client(
  |                ~~~~~~~~~~~~~~~~~~~~~^
  |         url=SERVER_URL,
  |         ^^^^^^^^^^^^^^^
  |         timeout=30,
  |         ^^^^^^^^^^^
  |         sse_read_timeout=300,
  |         ^^^^^^^^^^^^^^^^^^^^^
  |     ) as (read_stream, write_stream, get_session_id):
  |     ^
  |   File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/contextlib.py", line 235, in __aexit__
  |     await self.gen.athrow(value)
  |   File "/Users/susai/repos/ds-mcp/.venv/lib/python3.13/site-packages/mcp/client/streamable_http.py", line 437, in streamablehttp_client
  |     async with anyio.create_task_group() as tg:
  |                ~~~~~~~~~~~~~~~~~~~~~~~^^
  |   File "/Users/susai/repos/ds-mcp/.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 772, in __aexit__
  |     raise BaseExceptionGroup(
  |         "unhandled errors in a TaskGroup", self._exceptions
  |     ) from None
  | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
  +-+---------------- 1 ----------------
    | Traceback (most recent call last):
    |   File "/Users/susai/repos/ds-mcp/.venv/lib/python3.13/site-packages/anyio/streams/memory.py", line 111, in receive
    |     return self.receive_nowait()
    |            ~~~~~~~~~~~~~~~~~~~^^
    |   File "/Users/susai/repos/ds-mcp/.venv/lib/python3.13/site-packages/anyio/streams/memory.py", line 106, in receive_nowait
    |     raise WouldBlock
    | anyio.WouldBlock
    | 
    | During handling of the above exception, another exception occurred:
    | 
    | Traceback (most recent call last):
    |   File "/Users/susai/repos/ds-mcp/.venv/lib/python3.13/site-packages/anyio/_core/_tasks.py", line 115, in fail_after
    |     yield cancel_scope
    |   File "/Users/susai/repos/ds-mcp/.venv/lib/python3.13/site-packages/mcp/shared/session.py", line 272, in send_request
    |     response_or_error = await response_stream_reader.receive()
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/Users/susai/repos/ds-mcp/.venv/lib/python3.13/site-packages/anyio/streams/memory.py", line 119, in receive
    |     await receive_event.wait()
    |   File "/Users/susai/repos/ds-mcp/.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 1774, in wait
    |     await self._event.wait()
    |   File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/locks.py", line 213, in wait
    |     await fut
    | asyncio.exceptions.CancelledError: Cancelled by cancel scope 106faafd0
    | 
    | During handling of the above exception, another exception occurred:
    | 
    | Traceback (most recent call last):
    |   File "/Users/susai/repos/ds-mcp/.venv/lib/python3.13/site-packages/mcp/shared/session.py", line 271, in send_request
    |     with anyio.fail_after(timeout):
    |          ~~~~~~~~~~~~~~~~^^^^^^^^^
    |   File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/contextlib.py", line 162, in __exit__
    |     self.gen.throw(value)
    |     ~~~~~~~~~~~~~~^^^^^^^
    |   File "/Users/susai/repos/ds-mcp/.venv/lib/python3.13/site-packages/anyio/_core/_tasks.py", line 118, in fail_after
    |     raise TimeoutError
    | TimeoutError
    | 
    | During handling of the above exception, another exception occurred:
    | 
    | Traceback (most recent call last):
    |   File "/Users/susai/repos/ds-mcp/.venv/lib/python3.13/site-packages/mcp/client/streamable_http.py", line 461, in streamablehttp_client
    |     yield (
    |     ...<3 lines>...
    |     )
    |   File "/Users/susai/repos/ds-mcp/app/client3.py", line 21, in main
    |     init_result = await session.initialize()
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/Users/susai/repos/ds-mcp/.venv/lib/python3.13/site-packages/mcp/client/session.py", line 123, in initialize
    |     result = await self.send_request(
    |              ^^^^^^^^^^^^^^^^^^^^^^^^
    |     ...<15 lines>...
    |     )
    |     ^
    |   File "/Users/susai/repos/ds-mcp/.venv/lib/python3.13/site-packages/mcp/shared/session.py", line 274, in send_request
    |     raise McpError(
    |     ...<8 lines>...
    |     )
    | mcp.shared.exceptions.McpError: Timed out while waiting for response to ClientRequest. Waited 100.0 seconds.
    +------------------------------------

Process finished with exit code 1

服务端日志

/Users/susai/repos/ds-mcp/.venv/bin/python /Users/susai/repos/ds-mcp/app/server3.py 
INFO:     Started server process [16523]
INFO:     Waiting for application startup.
StreamableHTTP session manager started
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
Created new transport with session ID: 278ddef2d9f044dd924b0b24da32c94d
INFO:     127.0.0.1:55002 - "POST /mcp/ HTTP/1.1" 200 OK
Terminating session: 278ddef2d9f044dd924b0b24da32c94d
INFO:     127.0.0.1:55006 - "DELETE /mcp/ HTTP/1.1" 200 OK

排查方向

  1. 版本一致性检查:确认FastMCP客户端与服务端版本完全匹配,版本差异可能导致协议解析异常。
  2. 临时调大超时参数:将read_timeout_seconds和timeout值临时调至更大,排除网络波动导致的超时。
  3. 开启调试日志:在服务端和客户端开启详细调试日志,查看会话初始化阶段的请求/响应交互细节,定位是否有数据丢失。
  4. 验证HTTP传输配置:确认streamable-http模式下的请求头、响应格式符合规范,比如是否正确处理Transfer-Encoding: chunked。
  5. 简化测试逻辑:暂时移除客户端中工具调用等后续逻辑,仅保留会话初始化代码,排查是否有其他异步任务干扰流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 18:14:50