)
摘要用Python和FastMCP SDK在5分钟内搭建一个完整的MCP Server涵盖工具定义、运行调试和Claude Desktop接入全流程。适合零基础开发者快速上手MCP协议开发。5分钟跑通你的第一个MCP ServerPython版上周有个读者私信我说看了MCP的概念觉得很棒但上手时卡在第一步装了半天环境跑不起来。我让他把报错发过来一看Python版本太低又混装了fastmcp和官方mcp两个包依赖打架。其实跑通第一个Server真的不难难在没人把那些隐藏的坑提前告诉你。这篇我带你从零开始用Python写一个能跑的MCP Server定义一个工具再用官方调试工具测一把。我把每一步踩过的坑都标出来照着做不会翻车。环境准备先说清楚版本要求。官方Python MCP SDK要求Python 3.10及以上SDK版本至少1.2.0。低于这个版本要么装不上要么跑起来各种诡异报错。我推荐用uv来管理环境它比pip快很多而且能自动处理虚拟环境。装uv的命令Windows下是这样。# Windows安装uv执行后重启终端让命令生效powershell-ExecutionPolicy ByPass-cirm https://astral.sh/uv/install.ps1 | iexmacOS和Linux用这条。curl-LsSfhttps://astral.sh/uv/install.sh|sh装完重启终端确认uv可用。uv--version接着建项目目录和虚拟环境。# 建一个项目文件夹uv init my-first-mcpcdmy-first-mcp# 创建并激活虚拟环境uv venv# Windows激活.venv\Scripts\activate# macOS/Linux激活source.venv/bin/activate现在装依赖。这里有个我亲自踩过的坑要提前说。社区里有两个长得像的包一个叫mcp是Anthropic官方SDK里面带FastMCP。另一个叫fastmcp是第三方Jlowin团队维护的增强版框架。两者API很接近但不是一回事混装会冲突。我的建议是新手直接用官方的mcp[cli]带CLI工具方便调试。# 安装官方MCP Python SDK带CLI支持uvaddmcp[cli]如果你更习惯用pip等价的命令是这样。# 用pip装官方SDK效果一样pipinstallmcp[cli]装完验证一下。# 能打印出版本号说明装好了python-cimport mcp; print(mcp.__version__)写一个最简单的Server环境就绪开始写代码。我们做一个计算器Server提供两个工具一个算两数之和一个算阶乘。功能故意做简单把注意力放在MCP本身。新建文件calc_server.py下面是完整代码我会逐段解释。# calc_server.py# 一个最小的MCP Server提供加法和阶乘两个工具importsysfrommcp.server.fastmcpimportFastMCP# 初始化FastMCP实例传入Server名字# 这个名字会显示在客户端的工具列表里起个有辨识度的mcpFastMCP(calculator)# 第一个工具加法# mcp.tool()装饰器把普通函数注册成MCP工具# FastMCP会读取类型注解和docstring自动生成JSON Schemamcp.tool()defadd(a:float,b:float)-str:计算两个数的和。 Args: a: 第一个数 b: 第二个数 # 返回字符串MCP工具的返回值最终会作为文本交给模型resultabreturnf{a}加{b}等于{result}# 第二个工具阶乘# 这个用同步函数就行不一定非要asyncmcp.tool()deffactorial(n:int)-str:计算一个非负整数的阶乘。 Args: n: 非负整数 # 简单的参数校验不合法直接返回提示# 不要抛异常MCP工具里返回友好文本比抛异常更稳ifn0:return阶乘只接受非负整数ifn20:# 防止数值过大做个上限保护return数值太大请输入20以内的整数# 计算阶乘result1foriinrange(2,n1):result*ireturnf{n}的阶乘是{result}# 启动Server# transportstdio表示用标准输入输出通信# 这是本地客户端最常用的传输方式if__name____main__:mcp.run(transportstdio)几个要点解释一下。第一mcp.tool()装饰器是核心。你写一个普通Python函数加类型注解写好docstringFastMCP自动把它转成MCP协议要求的工具定义。模型的输入参数校验、类型转换都由框架处理。第二工具返回值用字符串最省心。MCP工具的返回会被封装成content传给模型字符串会被当成文本。你也可以返回更复杂的结构但起步阶段字符串足够。第三mcp.run(transportstdio)这一行决定传输方式。stdio模式下客户端通过子进程的标准输入输出跟Server通信不占网络端口本地用最合适。用MCP Inspector测试写完Server不用急着接客户端官方提供了一个可视化调试工具叫MCP Inspector能帮你单独验证Server是否正常。这是我强烈推荐的工作流先在Inspector里跑通再接客户端能省下大量排错时间。启动Inspector的命令。# 用npx直接跑不用全局安装# 后面跟着你的Server启动命令npx modelcontextprotocol/inspector python calc_server.py如果你用的也是uv管理可以写成这样。# 用uv run启动ServerInspector会接管npx modelcontextprotocol/inspector uv run calc_server.py执行后终端会打印一个本地网址类似http://localhost:6274。浏览器打开它你会看到一个调试界面。界面左侧是连接状态点Connect按钮如果Server正常会显示已连接并列出能力。中间区域有几个标签页。Tools标签能看到你定义的add和factorial两个工具点进去能手动填参数测试调用。Resources和Prompts标签因为我们这个Server没定义会是空的。在Tools里选add填a为3、b为5点Run Tool右侧会返回3 加 5 等于 8。看到这个结果说明你的Server完全正常。完整代码把上面的代码整理成一份可直接运行的完整文件。# calc_server.py# 最小可运行的MCP Server计算器示例# 运行方式python calc_server.py# 调试方式npx modelcontextprotocol/inspector python calc_server.pyimportsysimportloggingfrommcp.server.fastmcpimportFastMCP# 配置日志写到stderr千万别写stdout# stdout被JSON-RPC消息占用写进去会破坏协议logging.basicConfig(levellogging.INFO,streamsys.stderr,format%(asctime)s [%(levelname)s] %(message)s,)loggerlogging.getLogger(calc)# 初始化Server实例mcpFastMCP(calculator)mcp.tool()defadd(a:float,b:float)-str:计算两个数的和。 Args: a: 第一个数 b: 第二个数 logger.info(f调用add参数 a{a}, b{b})resultabreturnf{a}加{b}等于{result}mcp.tool()deffactorial(n:int)-str:计算一个非负整数的阶乘。 Args: n: 非负整数 logger.info(f调用factorial参数 n{n})# 校验输入ifn0:return阶乘只接受非负整数ifn20:return数值太大请输入20以内的整数# 计算result1foriinrange(2,n1):result*ireturnf{n}的阶乘是{result}if__name____main__:# stdio模式启动logger.info(计算器Server启动)mcp.run(transportstdio)效果验证把代码保存后用Inspector跑一遍。我的实测结果是这样。启动Inspector命令后终端输出类似下面这段。Starting MCP Inspector... Proxy server listening on port 6274浏览器打开http://localhost:6274点Connect连接状态变绿。切到Tools标签看到两个工具。测试add(3.5, 2.5)返回3.5 加 2.5 等于 6.0。测试factorial(5)返回5 的阶乘是 120。测试factorial(-1)返回阶乘只接受非负整数校验生效。测试factorial(100)返回数值太大请输入20以内的整数保护生效。stderr日志里能看到对应的调用记录方便排查。到这一步你的第一个MCP Server就跑通了。常见问题与避坑坑一用print调试导致Server挂掉。这是我见过最高频的坑。stdio模式下Server的标准输出被JSON-RPC消息独占你写一个print(hello)这段文本会混进协议流客户端解析失败直接断连。症状是Inspector连不上或者连上后调用工具就掉线。解决办法调试日志一律走stderr用print(msg, filesys.stderr)或者配置logging输出到stderr。本文完整代码里就是这么做的。坑二混装mcp和fastmcp两个包。这两个包都提供FastMCP但来源不同。同时装会导致import混乱运行时报莫名其妙的属性错误。症状是明明装了却import失败或者类型对不上。解决办法只用一个。新手用官方mcp[cli]进阶想要更多特性再考虑独立的fastmcp包别同时装。坑三Python版本低于3.10。SDK用了3.10才有的类型语法低版本直接语法错误。症状是import时报SyntaxError。解决办法python --version确认版本不够就升级或者用uv指定版本uv venv --python 3.11。坑四async函数和同步函数混用导致阻塞。FastMCP支持async def和普通def两种工具函数。如果你在一个async工具里调用同步的阻塞操作比如requests请求会卡住事件循环整个Server卡死。症状是第一个工具调用正常第二个就超时。解决办法async工具里用httpx等异步库或者干脆用同步def让框架自动丢进线程池。坑五Inspector版本太旧连不上新协议。MCP协议在迭代老版本Inspector可能不支持新协议版本号表现为连接后立刻断开。解决办法用npx每次拉最新版不要用本地缓存的旧版必要时加latest。两种SDK写法对比顺便说下官方SDK和第三方fastmcp包在写法上的差异帮你选型。对比项官方 mcp[cli]第三方 fastmcp 包来源Anthropic官方Jlowin团队导入路径mcp.server.fastmcp.FastMCPfastmcp.FastMCP装饰器mcp.tool()mcp.tool()额外特性够用官方同步更新更多语法糖和高级特性适合人群新手、求稳进阶、要更多便利两者核心API几乎一致从官方迁移到第三方成本很低。我的建议是先用官方的跑通流程遇到具体痛点再看第三方有没有更顺手的解法。小结跑通第一个MCP Server的关键就三步。装好官方mcp[cli]依赖用mcp.tool()装饰器把函数注册成工具用stdio模式启动。调试时一定先用MCP Inspector单独验证再接客户端。最大的坑是stdout污染协议流所有调试输出走stderr就能避开。下一节我把这个Server接进Claude Desktop和Cursor让你看到AI真正调用你写的工具是什么效果。相关推荐MCP是什么为什么2026年每个AI开发者都需要了解它MCP三大原语初体验Tools、Resources、Prompts一个都不少Python MCP SDK入门FastMCP快速开发