大家好,我是晚安code。
上个月我想让 AI 帮我查个快递,折腾半天才发现它不是不会,是「手」和「眼睛」都得靠外部工具接。一搜全是 MCP、协议、传输这种词,直接把我劝退。后来按官方仓库老老实实走了一遍才发现,MCP Server 开发真没传说中那么玄:一条命令建工程,一个类暴露工具,30 分钟就能跑通。这篇就把整个流程拆给你看,附三种传输协议的选型避坑,看完你也能写出自己的第一个。
一、MCP 是什么:AI 的 USB-C 接口
MCP 是目前大模型接入外部工具的事实标准,想给 AI 加「手」和「眼睛」,绕不开它。
MCP(Model Context Protocol):Anthropic 开源的大模型上下文协议,让大模型通过统一接口调用外部工具和数据源。你可以理解为「AI 的 USB-C 接口」——一根线,接遍所有设备。
真正干活的程序叫 MCP Server:本质就是一段 Node.js 或 Python 程序,把外部工具包装成 MCP 认识的接口,再交给 AI 客户端调用。你可以把它当成「给 AI 打工的工具接线员」。
为什么不干脆让 AI 直接连数据库、直接调接口?因为它真敢给你下单买十台冰箱。隔一层 MCP Server,权限、白名单、操作边界全都握在你手里,这就是它存在的最大意义。
看一下图 1,整条链路是这样的:AI 客户端通过 MCP 协议向 Server 要工具,Server 再替你操作数据库、天气 API 这些外部世界,你来定边界。


二、动手前准备:uv 建一个 Python 工程
写 MCP Server 不需要你懂底层协议,Python 官方 SDK 把最难的协议封装好了,你只要先把环境搭利索。
uv:Python 生态里目前最快的包管理与虚拟环境工具(Astral 出品),一条命令建工程、装依赖、切 Python 版本。你可以理解为「更快的 pip + venv」。(2026 年 8 月实测,SDK 版本 mcp 1.27.x)
安装和初始化就四行命令,每行干什么我写在代码块下面:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
uv python list
uv python install 3.11
uv init . -p 3.11
uv add "mcp[cli]"
第一行在 Windows 上一键装 uv(Mac/Linux 装法看官方文档);uv init . -p 3.11 把当前空文件夹初始化为 Python 3.11 工程;最后一行 uv add "mcp[cli]" 装官方 MCP SDK,带上 cli 扩展才有 MCP Inspector 这个调试工具。
装完 uv 用 VS Code 打开工程目录,装上商店里的 Python 和 Python Debugger 两个插件。uv 会顺手给你建好 .venv 虚拟环境,uv add 的东西全装进去,跑代码前记得先激活它。

三、写一个能跑的 MCP Server:tool 与 resource
一个 MCP Server 的核心就两件事:用 @mcp.tool() 暴露「能动的手」,用 @mcp.resource() 暴露「只读的资料」。
FastMCP:MCP Python SDK 提供的高层接口,用装饰器就能把普通 Python 函数变成 MCP 工具,协议细节全被封装。你可以理解为「像写 FastAPI 一样写 MCP Server」。
把下面的代码存成 server.py,这就是一个最小但完整的 Server:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("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__":
mcp.run() # 默认走 stdio 传输
三件小事,少了哪个都会卡你半天:
- 类型注解必须写:FastMCP 靠它自动生成工具的 JSON Schema,也就是告诉客户端这个工具收什么参数。
- docstring 必须写:大模型靠它理解这个工具是干嘛的、什么时候该调,不写等于没告诉它。
if __name__ == "__main__"别手滑写成_init_,否则运行起来啥都不发生。
@mcp.tool() 和 @mcp.resource() 的区别,用一张表说清楚:
| 维度 | @mcp.tool() | @mcp.resource() |
|---|---|---|
| 语义 | 让 AI 执行操作 | 给 AI 提供只读数据 |
| 副作用 | 有(改数据、调接口) | 无(只读取) |
| 触发方式 | 大模型按需调用 | 通过 URI 模板请求 |
| 举例 | add、发邮件、查订单 | greeting://{name}、配置项 |

写完后怎么验证?推荐用官方调试器,一行命令打开 MCP Inspector 可视化面板,左边能看到注册好的工具、右边直接调:
python server.py # 最小验证:stdio 跑起来不报错
mcp dev server.py # 推荐:打开 MCP Inspector 调试面板
这里有个坑我得念叨一下。我一开始照着老教程写的 from mcp.server import MCPServer,import 那一行直接报错——那是 SDK v2 的类名,稳定版 1.27 根本没有这个类。网上教程版本混用,太坑了。

可能有人会问:网上有的教程写 MCPServer,有的写 FastMCP,到底哪个对啊?
都对,但是不同版本。FastMCP 是稳定版 1.x 的类名;SDK v2(还在 pre-alpha)把它改名成 MCPServer 并删掉了 fastmcp 模块。现在写新代码,认准
from mcp.server.fastmcp import FastMCP就行。
四、三种传输协议怎么选
传输协议决定你的 MCP Server 是「装在本机的程序」还是「挂在网上的服务」,这一步选错,后面全得返工。
stdio 传输:通过操作系统的标准输入输出流和 AI 客户端通信,Server 装在你本机,客户端把程序拉下来本地跑。距离最近、最快,但只能本机、单客户端。
Streamable HTTP 传输:官方推荐的远程方案,Server 独立部署在服务器上,客户端通过 HTTP 双向调用,支持鉴权、限流、多客户端。你可以理解为「把 MCP Server 做成一个真正的 Web 服务」。
SSE(Server-Sent Events):HTTP 长连接单向推送的旧方案,2025 年 3 月被官方标记废弃,仅作历史兼容。
三种协议放在一起看:
| 协议 | 部署位置 | 调用方式 | 适用场景 | 现状 |
|---|---|---|---|---|
| stdio | 本地 | 标准输入/输出 | Claude Desktop、CLI、本地开发 | 推荐(本地) |
| Streamable HTTP | 远程服务器 | HTTP 双向流 | Web 应用、生产服务 | 推荐(远程) |
| SSE | 远程 | HTTP 单向推送 | 老项目兼容 | 已废弃 |
SSE 已经过时了——网上老教程还在教它,但 2025 年 3 月起官方就把 HTTP+SSE 标成 deprecated,新项目直接上 Streamable HTTP。
切换传输方式,其实就改一个参数:
mcp.run() # 本地:stdio
mcp.run(transport="streamable-http") # 远程:Streamable HTTP
图 6 是三者的调用关系:stdio 走本地管道,Streamable HTTP 走 HTTP 双向流,SSE 只剩单向推送这一条老路。


可能有人会问:SSE 不是也能远程调用吗,为什么不让用?
因为 2025 年 3 月官方已把 HTTP+SSE 标记为 deprecated(SEP-2596),TypeScript SDK 甚至已经移除了 SSE server 支持。它单向上、效率低、没有新特性,纯属历史包袱。新项目别学老教程踩这个坑。
说真的,我一开始学的也是 SSE——查了官方 spec 才发现自己早就学过期了,那叫一个哭笑不得。

收个尾
总的说,MCP Server 开发的门槛比想象中低:一条命令建工程,一个 FastMCP 类暴露工具,选协议记住「本地用 stdio、远程用 Streamable HTTP、别碰 SSE」就够了。想深入就去看官方规范,SDK 的源码也写得很清楚,比任何二手教程都靠谱。
我就是被老教程坑过的人,所以这篇特意把版本和过时信息都标清楚了,希望你少走点弯路。

我是晚安code,持续分享编程干货。觉得有用的话记得点赞收藏和关注~也欢迎在评论区聊聊:你第一个 MCP Server 想给 AI 接什么工具?有没有被老教程的过时写法坑过?