Newsroom
AIEII

MCP server 怎么从零写:Python 示例、调试和连不上的排查

用官方 Python SDK 2.x 写一个最小 MCP server,接进 Claude Code,并列出 Failed to connect 的常见原因和排查顺序。

TL;DR
  • 官方 Python SDK 当前是 mcp 2.3.0(2026-10-02 发布),pip install “mcp[cli]” 装的就是 2.x,要求 Python 3.10 及以上,不到 20 行代码就能跑起一个 server。
  • v2 把 v1 的 FastMCP 改名为 MCPServer,旧的 from mcp.server.fastmcp import FastMCP 会直接 ModuleNotFoundError,网上大量旧教程要改一行 import。
  • 接入 Claude Code 用 claude mcp add – <命令>,连不上先跑 claude mcp list 和 claude mcp get,九成问题出在路径、环境和 stdout 污染。
MCP server 怎么从零写:Python 示例、调试和连不上的排查

写一个最小的 MCP server,用官方 Python SDK 2.x 只要不到 20 行:装 mcp[cli],用 MCPServer 注册一个 @mcp.tool() 函数,再用 claude mcp add 接进 Claude Code。连不上时先看 claude mcp list,再查路径、Python 环境和 stdout 污染。

最容易踩的坑是版本。2026-07-28 发布 2.0 之后,PyPI 上 mcp 的最新版是 2.3.0(2026-10-02),而大多数教程还在写 v1 的 FastMCP。照抄旧代码会直接报错,下面的示例都按 2.x 写,最后核对日期 2026-10-09。


环境准备:Python 版本和安装命令

SDK 要求 Python 3.10 及以上。推荐用 uv 管理,pip 也行:

uv init mcp-demo && cd mcp-demo
uv add "mcp[cli]"
# 或者
pip install "mcp[cli]"

cli 这个 extra 提供 mcp dev、mcp run、mcp install 三个命令,调试要用,建议装。不需要命令行工具的话装 mcp 就够。

想留在 v1 线的话固定上界:pip install "mcp[cli]<2",v1 最新是 1.30.0,只接收关键 bug 和安全修复。

写一个最小 server

一个工具函数加一个资源,足够验证整个流程:

# server.py
import sys
from mcp.server.mcpserver import MCPServer

mcp = MCPServer("Demo")

@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers."""
    return a + b

@mcp.resource("greeting://{name}")
def greeting(name: str) -> str:
    """Greet someone by name."""
    return f"Hello, {name}!"

if __name__ == "__main__":
    print("demo server starting", file=sys.stderr)  # 日志只能走 stderr
    mcp.run(transport="stdio")

几个要点:

  1. 函数的类型注解和 docstring 会被 SDK 转成工具的 JSON Schema 和描述,模型靠这段描述决定什么时候调用,写清楚比写长重要。
  2. v1 的写法是 from mcp.server.fastmcp import FastMCP。2.x 改成 from mcp.server.mcpserver import MCPServer,旧路径会 ModuleNotFoundError。PyPI 首页的示例写的是 from mcp.server import MCPServer,我没有逐一验证两种写法是否都可用,迁移指南给的是前一种,我用前一种。
  3. host、port、stateless_http 这类传输参数在 2.x 从构造函数挪到了 run(),比如 mcp.run(transport="streamable-http", host="0.0.0.0", port=9000)。

先用 Inspector 测,别急着接 Claude Code

uv run mcp dev server.py

这条命令会打开 MCP Inspector,能列出工具、手动填参数调用、看原始消息。Inspector 里调不通,接 Claude Code 也一定调不通,先在这里排除代码问题。

想看 HTTP 方式,用 uv run mcp run server.py --transport streamable-http,客户端用 http://localhost:8000/mcp 连接。

接入 Claude Code

本地 stdio server 的格式:

claude mcp add demo -- uv run --directory /绝对路径/mcp-demo python server.py

规则只有三条:

  1. 所有 Claude 的选项(--scope、--env、--transport)放在名字 demo 之前。
  2. -- 之后全是 server 的启动命令,-y、--port 这类参数不会被 Claude 吞掉。
  3. 作用域默认是 local(只对当前项目生效,存在 ~/.claude.json),-s project 写进项目根目录的 .mcp.json 可以随 git 共享,-s user 对所有项目生效。

带环境变量的例子:

claude mcp add --env API_KEY=xxx --transport stdio demo -- uv run --directory /绝对路径/mcp-demo python server.py

--env 后面必须再放一个选项(比如 --transport stdio)再写名字,否则名字会被当成 KEY=value。

远程 server 用 claude mcp add --transport http <名字> <URL>。SSE 已被标为弃用,能用 HTTP 就用 HTTP。

接完检查:

claude mcp list        # 看状态
claude mcp get demo    # 失败时会多一行 Issue

会话里输入 /mcp 可以查看状态、重新认证或重连。

连不上时的排查顺序

claude mcp list 常见的状态有 ✔ Connected、! Needs authentication、✘ Failed to connect、⏸ Pending approval。按下面的顺序查,命中率最高:

现象常见原因处理
Failed to connect,启动即退出相对路径、找不到 uv 或 python命令和脚本都写绝对路径,用 --directory 固定工作目录
Failed to connect,手动运行正常Claude 启动的环境里没有你的虚拟环境和 PATH用 uv run 或虚拟环境里 python 的绝对路径
连上后立刻断开代码里有 print(),stdout 被污染日志改 stderr 或文件
ModuleNotFoundError装了 v2 却用 v1 的 FastMCP import,或相反对齐版本和 import
Pending approval项目 .mcp.json 里的 server 还没批准在项目里运行 claude 批准
启动慢被判超时首次 uv run 要装依赖MCP_TIMEOUT=10000 claude(毫秒)调长启动超时
配置怪异报错粘贴 token 带了首尾空格;${VAR} 没设置Claude 会给警告但不会自动 trim,手动改
工具调用中途被截断输出超过 MAX_MCP_OUTPUT_TOKENS(默认 25000)缩小返回内容或调高上限

需要更详细的日志,用 claude --debug-file /tmp/claude-debug.log 启动,直接搜 server 名字。

关于规范版本

2026-07-28 版 MCP 规范主打无状态化:按我查到的几篇资料,initialize 握手和 session id 被去掉,每个请求自带上下文,方便放在普通负载均衡后面。这对要部署 HTTP 服务的人影响大,对本地 stdio 的小工具影响很小,因为 SDK 替你处理协议细节。无状态化的细节可以看站内那篇深度解析。具体哪些行为不向后兼容,以 SDK 迁移指南为准,我没有逐条核对。

我的判断

自己写 MCP server 的门槛已经很低,难点不在代码,而在环境。我的建议是:第一次一定用 stdio 加 Inspector,把工具跑通再谈部署;路径全写绝对路径;从第一行起就禁用 print。需要对外提供服务、要多实例部署的人,再去看 streamable-http 和无状态化。只想让 Claude 读几个本地文件或查一个内部接口的人,一个 20 行的 stdio server 已经够用,别一上来就搭网关。反过来,如果你打算把 server 公开给别人用,v2 的迁移指南必读,不要照旧教程抄 v1 写法。

相关阅读

参考

最后核对日期:2026-10-09。

常见问题

MCP Python SDK 现在装哪个版本?
截至 2026-10-09,PyPI 上最新是 mcp 2.3.0,pip install mcp 默认装 2.x。想继续用 v1 的 FastMCP 写法,可以装 mcp<2,v1 线最新是 1.30.0,只收关键修复。
claude mcp add 的命令格式是什么?
本地 stdio 是 claude mcp add <名字> – <启动命令> [参数],远程是 claude mcp add –transport http <名字> 。选项必须放在名字前面,– 用来把后面的参数留给 server。
stdio 的 MCP server 能用 print 打日志吗?
不能。stdio 模式下 stdout 就是协议通道,print 会把 JSON-RPC 消息搅乱,客户端直接断连。日志要写 stderr 或文件。
新规范的无状态化会让我写的 server 失效吗?
按我查到的资料,2026-07-28 版规范去掉了 initialize 握手和 session id,但具体兼容策略因 SDK 和平台而异,建议以 SDK 迁移指南为准。最小 stdio server 用 SDK 写,不用自己处理握手。
广告合作联系
立即联系 →
加入会员申请
了解详情 →
← Claude Code 怎么切换 Opus … GPT-6 Sol 和 Luna 怎么选:价格、场景、和 … →
💬 Comments
5 min read