用 Python 写一个能连上的 MCP Server:本地搭建与验证步骤

MCP Server 搭建的核心不是把服务跑起来,而是让 MCP 客户端能通过约定的传输方式连上它、完成初始化握手、正确列出工具。
本文用 Python 写一个最小可用的 MCP Server,走 stdio 传输,接入 Claude Desktop 验证;
如果你卡在连接失败,文中也给出定位顺序。

先明确传输方式和运行环境

MCP Server 支持多种传输方式,本地开发最省事的是 stdio:客户端把 Server 当作子进程启动,通过标准输入输出收发 JSON-RPC 消息。
这意味着两件事:

  • Server 进程不能往 stdout 打印调试信息,否则会污染协议消息流;日志一律走 stderr。
  • 客户端配置里写的启动命令必须能在它自己的工作目录下执行成功,路径和环境变量要写绝对路径。

本文环境:Python 3.10 及以上,使用官方 mcp Python SDK。
如果机器上同时有多个 Python 版本,后面所有命令都用 python3 -m 形式,避免 pip 和 python 指向不同解释器。

安装 SDK 并写一个最小 Server

先建独立虚拟环境,把依赖装干净:

python3 -m venv mcp-venv
source mcp-venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install mcp

新建文件 server.py,实现一个加法工具和一个问候资源。
工具函数是客户端真正会调用的部分,参数类型要写清楚:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("demo-server")

@mcp.tool()
def add(a: int, b: int) -> int:
    """返回两个整数之和"""
    return a + b

@mcp.resource("greeting://hello")
def hello() -> str:
    """返回一句问候语"""
    return "hello from mcp server"

if __name__ == "__main__":
    mcp.run(transport="stdio")

这里没有写任何 print 语句。
如果后续要加日志,用 logging 并显式输出到 sys.stderr,不要用默认 stdout 输出。

用 inspect 先验证服务本身

在接客户端之前,先确认 Server 自己能正常响应工具列表。
SDK 自带开发调试命令:

mcp dev server.py

该命令会启动一个本地调试入口,浏览器打开它给出的地址,能看到 add 工具和 greeting://hello 资源。
在调试界面里手动调用一次 add,参数传 1 和 2,应返回 3。

这一步能通过,说明协议层、工具注册和参数解析都没问题,剩下的失败基本都出在客户端配置或启动环境上。

接入 Claude Desktop 并确认连接状态

在 Claude Desktop 的配置文件中加入这段服务定义。
macOS 路径通常是 ~/Library/Application Support/Claude/claude_desktop_config.json,Windows 是 %APPDATA%\Claude\claude_desktop_config.json:

{
  "mcpServers": {
    "demo-server": {
      "command": "/绝对路径/mcp-venv/bin/python3",
      "args": ["/绝对路径/server.py"]
    }
  }
}

两个绝对路径必须写全:command 指向虚拟环境里的解释器,args 指向脚本本身。
写 python3 这种相对命令时,客户端可能找不到虚拟环境里的依赖。

保存后完全退出 Claude Desktop 再重新打开,在对话输入框的工具图标或设置里的 MCP 服务列表查看 demo-server 是否显示为已连接。
连接成功后,直接提问“用 add 工具算 1 加 2”,观察返回结果是否为 3。

连不上时按这个顺序排查

客户端显示未连接或工具列表为空,按下面顺序查,不要一上来改代码:

  • 在终端手动执行配置里的 command 和 args 组合,看进程是否直接退出并打印异常。最常见的报错是 ModuleNotFoundError: No module named 'mcp',说明客户端调用的 Python 不是装了依赖的那个。
  • 检查 server.py 里是否有 print 或第三方库往 stdout 写内容。stdio 模式下 stdout 只允许走 JSON-RPC,任何多余输出都会让客户端解析失败。
  • 查看 Claude Desktop 的 MCP 日志,路径在 macOS 的 ~/Library/Logs/Claude/mcp*.log,Windows 的 %APPDATA%\Claude\logs 下。日志里出现 Unexpected token 或 JSON 解析错误,优先回查上一条。
  • 确认配置 JSON 本身合法,末尾不要多逗号,mcpServers 拼写正确。改完配置必须完全重启客户端,只关窗口不算。

什么时候需要换传输方式

stdio 适合本地单机调试和桌面客户端接入。
如果 Server 要部署在远程服务器、供多个客户端同时连接,或者客户端本身不支持拉起子进程,就需要改用 HTTP 类传输,并在服务端处理端口、鉴权和会话管理。
这类场景的配置复杂度明显高于本地 stdio,建议先把本地链路跑通,再迁移部署。

常见疑问:

工具写好了但客户端列表里没有,先看服务是否显示已连接,再看工具函数是否真的带上了 @mcp.tool() 装饰器,最后用 mcp dev 复核。

改完代码需要重启客户端吗?
stdio 模式下 Server 是客户端启动的子进程,改代码后要重启客户端才能加载新进程。

能不能用系统 Python 直接跑?
可以,但依赖必须装在同一个解释器里;
用虚拟环境并写绝对路径是更稳的做法。

分享到:
上一篇
MCP协议配置教程:在客户端接入本地工具服务
下一篇
MCP Client 怎么配置才能连上本地服务
1
系统公告

关于香港云优质服务器IP地址更换的通知

尊敬的客户: 因原IP运营商大幅涨价,为避免成本转嫁至用户,我司决定更换IP服务商。本次更换后,您的续费价格将保持不变,且新IP网络质量与服务标准不受影响。新IP已分配至后台,即刻生效(更换的新IP都是香港原生IPv4)。 涉及 IP 段: 45.192.x.x 旧 IP 停用时间: 2026 年 12 月 1 日
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意