modelcontextprotocol / modelcontextprotocol/python-sdk

Server hangs when shutting down if a connection is still open

未关闭
#1,272 2 条评论 6 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

bug P1 ready for work
主要语言
Python
星标
24.3k
派生
4k
平均合并
1 天 1 小时
30 天内合并 PR
31

描述

Initial Checks
Description

Hello!

I was testing my MCP server with the inspector npx @modelcontextprotocol/inspector using streamable-http and I noticed that if the inspector is connected, the MCP Server will not shutdown.

We can't keep the server running if a client forgot to disconnect right? This is tested with the official inspector tools, so there might be other clients working the same way.

Shouldn't the server close its active connections/tasks on shutdown?

Reproduction
  1. Run the server (see code snippet)
  2. In the MCP Inspector click "connect"
  3. In the server's terminal hit CTRL+C

At this point

  • The server shows Waiting for connections to close (CTRL+C to force quit) and CTRL+C doesn't work, in fact nothing works except killing the process
  • Clicking "Disconned" in the Inspector cannot disconnect, because Error in /mcp route: TypeError: fetch failed
Evidences

Shell execution

$ python demo-mcp.py                 
INFO:     Started server process [10749]
INFO:     Waiting for application startup.
[08/14/25 11:03:16] INFO     StreamableHTTP session manager started                                                                                                                                                                                 streamable_http_manager.py:110
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
[08/14/25 11:03:21] INFO     Created new transport with session ID: 4134f60ccda44baf8a01733ed94bc0d8                                                                                                                                                streamable_http_manager.py:233
INFO:     127.0.0.1:54629 - "POST /mcp HTTP/1.1" 200 OK
INFO:     127.0.0.1:54629 - "POST /mcp HTTP/1.1" 202 Accepted
INFO:     127.0.0.1:54630 - "GET /mcp HTTP/1.1" 200 OK
^CINFO:     Shutting down
INFO:     Waiting for connections to close. (CTRL+C to force quit)

Inspector proxy Disconnect error

Received DELETE message for sessionId dd8a78d2-d5a8-4ff2-b679-6a8571f7cd0c
Connection refused. Is the MCP server running?
Error in /mcp route: TypeError: fetch failed
    at node:internal/deps/undici/undici:13502:13
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async StreamableHTTPClientTransport.terminateSession (file://.../.npm/_npx/5a9d879542beca3a/node_modules/@modelcontextprotocol/sdk/dist/esm/client/streamableHttp.js:355:30)
    at async file://.../.npm/_npx/5a9d879542beca3a/node_modules/@modelcontextprotocol/inspector/server/build/index.js:264:17 {
  [cause]: Error: connect ECONNREFUSED 127.0.0.1:8000
      at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1636:16) {
    errno: -61,
    code: 'ECONNREFUSED',
    syscall: 'connect',
    address: '127.0.0.1',
    port: 8000
  }
}
Mitigation

Setting the timeout_graceful_shutdown uvicorn config to a few seconds will eventually quit the process, BUT this is exiting with a non 0 exit code, which is an issue trying to run this in production. (This setting has been request here and currently available in FastMCP 2.0)

Example Code
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("demo")

@mcp.tool()
async def hello() -> str:
    return "world"

mcp.run(transport="streamable-http")
Python & MCP Python SDK
Python 3.12.8
mcp 1.12.4

Edit: reproduced with mcp 1.13.0

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

使用提供的 FastMCP streamable-http 示例重现关闭行为,并检查日志中显示的 streamable_http_manager.py 会话处理。跟踪关闭期间活动连接和任务的处理方式,然后验证在 Inspector 保持连接的情况下,CTRL+C 能够正常退出。

由索引模型根据 Issue 内容生成。

评估

技术栈
python
领域
api, backend
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
停滞
描述清晰度
基本清楚
新手友好度
45/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。