第 5 章 · MCP(Model Context Protocol)
5.1 为什么需要 MCP
第 4 章我们写了工具 schema,让 LLM 能调工具。但这里有个问题:
每个 agent 框架的工具格式都不一样。
- Anthropic SDK 用
{"name": ..., "input_schema": ...} - OpenAI SDK 用
{"type": "function", "function": {"name": ..., "parameters": ...}} - LangGraph 有自己的工具类
- CrewAI 又是一套
如果你写了一个"查天气"工具给 Claude 用,想再给 GPT 用,得改一遍格式。N 个模型 × M 个工具 = N×M 个集成。N=5、M=20 的时候就是 100 个集成。这就是"集成地狱"。
2024 年 11 月,Anthropic 开源了 MCP(Model Context Protocol),把这事儿解决了。官方比喻是"USB-C for AI applications"——一个标准接口,所有模型和所有工具都遵循它,N×M 降成 N+M。
注:"N×M → N+M" 是社区通俗比喻,非 Anthropic 官方原话。官方说的是"a universal, open standard for connecting AI systems with data sources"。
参考:MCP 官方规范 / Anthropic 发布博客
5.2 三角色:Host / Client / Server
MCP 是个客户端-服务端协议。三个角色:
- Host(宿主):AI 应用本身,比如 Claude Code、Cursor、VS Code。它管理多个 client,给 LLM 提供 context。
- Client(客户端):Host 里的一个组件,跟某个 server 维持 1:1 连接。Host 有几个 server 就有几个 client。
- Server(服务端):一个独立程序,提供 context(工具、资源、提示词)。你可以自己写,也可以用别人写好的。
数据流:
[Host: Claude Code]
├── [Client A] ←→ [Server A: 文件系统]
├── [Client B] ←→ [Server B: GitHub]
└── [Client C] ←→ [Server C: 你自己写的数据库工具]Host 启动时,每个 client 连一个 server,把 server 提供的能力(工具/资源/提示词)暴露给 LLM。LLM 调工具时,Host 通过 client 把请求转给 server,server 执行后把结果通过 client 还给 Host。
5.3 三类能力:Tools / Resources / Prompts
MCP server 能提供三种东西,区别在"谁来控制":
| 能力 | 控制方 | 用途 | 例子 |
|---|---|---|---|
| Tools | model-controlled | 模型自己决定何时调 | search_papers(query)、send_email(to, body) |
| Resources | application-driven | 应用程序主动取 | 文件内容、数据库 schema、配置 |
| Prompts | user-controlled | 用户主动触发 | slash command,如 /summarize |
Tools 跟第 4 章讲的工具一样——LLM 根据 description 决定何时调。这是 agent 最常用的。
Resources 不是给 LLM 自动调的,是给应用程序主动塞进 context 的。比如把数据库 schema 作为 resource,应用启动时读出来塞进 system prompt。
Prompts 是预定义的提示词模板,用户通过 slash command 主动调用。比如 Claude Code 里的 /commit 就是把"写 commit message"这套指令打包成一个 prompt。
5.4 30 行代码写一个 MCP server
用 Python SDK(pip install mcp)写一个最小的 MCP server:
from mcp.server import MCPServer
mcp = MCPServer("my-first-server")
@mcp.tool()
def add(a: int, b: int) -> int:
"""两个整数相加。当用户做加法运算时使用。"""
return a + b
@mcp.resource("greeting://{name}")
def greeting(name: str) -> str:
"""返回问候语。"""
return f"Hello, {name}!"
if __name__ == "__main__":
mcp.run()跑起来:
pip install mcp
mcp dev server.py # 启动 + 自动打开调试 UI这就是一个能用的 MCP server。@mcp.tool() 装饰器自动把函数转成 MCP tool schema,函数签名变成 input_schema,docstring 变成 description。@mcp.resource() 同理。
5.5 在 Host 里接入 MCP
Claude Code
三种作用域:
# 项目级(.mcp.json,可入库,团队共享)
claude mcp add --transport stdio myserver -- python server.py
# 用户级(~/.claude.json,所有项目可用)
claude mcp add --scope user myserver -- python server.py
# 本地级(默认,只当前项目当前用户)
claude mcp add myserver -- python server.py.mcp.json 长这样:
{
"mcpServers": {
"myserver": {
"command": "python",
"args": ["server.py"]
}
}
}Cursor
在项目根目录建 .cursor/mcp.json,格式和 Claude Code 类似。参考 Cursor MCP 文档。
Claude Desktop
配置文件 claude_desktop_config.json:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
}
}
}Windows 下需要用 cmd /c npx 包裹。
5.6 MCP 生态现状
截至 2026-07,MCP 生态里高星 server(按 star 排序):
| 仓库 | Stars | 用途 |
|---|---|---|
punkpeye/awesome-mcp-servers | 90k | 聚合清单(不是 server) |
modelcontextprotocol/servers | 88k | 官方参考实现集 |
microsoft/playwright-mcp | 35k | 浏览器自动化(微软官方) |
github/github-mcp-server | 31k | GitHub 官方 |
PrefectHQ/fastmcp | 26k | Python MCP 框架 |
googleapis/mcp-toolbox | 16k | 数据库 MCP(Google) |
GLips/Figma-Context-MCP | 15k | Figma 设计 |
官方参考实现(modelcontextprotocol/servers)里有:filesystem、git、memory、fetch、time、sequentialthinking 等。awesome-mcp-servers 是社区维护的清单,找新 server 直接搜这里。
5.7 MCP 的适用边界
MCP 不是万能药。这些场景别用 MCP:
| 场景 | 别用的原因 | 用什么替代 |
|---|---|---|
| 单个 agent、几个一次性工具 | 增加复杂度,没收益 | 直接写 Anthropic tool use |
| 工具只需要在该应用内用 | MCP 是跨 host 复用的,单应用没必要 | 直接写在应用里 |
| 极低延迟场景 | MCP 走子进程/HTTP,有通信开销 | 进程内直接调函数 |
| 高并发高频调用 | MCP server 通常是单进程,并发差 | 直接写 API |
适合用 MCP 的场景:
- 工具想跨多个 host 复用(同时给 Claude Code / Cursor / Claude Desktop 用)
- 工具需要给团队共享(
.mcp.json入库,所有人都能用) - 工具本身是独立服务(比如查公司内部数据库)
- 想用社区现成的 server(Playwright、GitHub、Filesystem 等)
5.8 MCP 的已知局限
实际用 MCP 时会踩到的坑:
- stdio 单行消息体积限制:~1MB JSON-RPC 会崩,工具返回大结果要小心。
- 生命周期可被绕过:有些 server 不握手也能调工具,安全风险。
- 依赖地狱:server 依赖没声明清楚,启动就崩。
- Windows 路径脆弱:UNC 路径、反斜杠在 Python server 里经常出问题。
- 鉴权仅 HTTP:stdio transport 不走 Authorization,敏感工具别用 stdio。
- 协议升级断兼容:MCP 规范版本切换期,host 和 server 版本不匹配会握手失败。
- 调试困难:有官方
inspector工具弥补,但调试体验仍不如本地代码。
前人智慧 / Prior Art
本章讲了 MCP 的工程基础:三角色、三类能力、30 行写一个 server、生态现状、适用边界、已知局限。MCP 是 2024-2025 年 Agent 工程最重要的标准化工作,理解它的来龙去脉对选型至关重要。
MCP 发布的工程背景
2024 年 11 月 25 日,Anthropic 在 MCP 发布博客 里说明 MCP 要解决的问题:
"Even the most capable models are constrained by their isolation from data... MCP makes it as straightforward to connect AI systems to the data they need."
发布前的背景:Function Calling 已经过两年验证,但每个 host(Claude / Cursor / VS Code / Codex)的 tool 集成格式都不同。一个工具想跨 host 用,要写 N 个适配。这就是本章 5.1 节讲的"N×M 集成地狱"。
MCP 的核心选择:不是发明新工具协议,是定义标准接口。让 tool 实现和 host 解耦。这个思路和 USB-C 的设计哲学一致--不规定设备长什么样,规定接口长什么样。
USB-C 类比的工程意义
本章 5.1 节用 "USB-C for AI applications" 类比 MCP。这个类比的工程价值在:
| USB-C | MCP |
|---|---|
| 标准物理接口 | 标准 JSON-RPC 协议 |
| 设备厂商各自实现 | Tool 厂商各自实现 server |
| 一个口接所有设备 | 一个 host 接所有 server |
| 不规定设备功能 | 不规定 tool 功能 |
注意"不规定设备功能"--MCP 不规定 tool 做什么,只规定 tool 怎么和 host 通信。这是 MCP 能成为标准的关键--它不抢占 tool 的业务层,只做协议层。
三角色设计的来源
本章 5.2 节讲的 Host / Client / Server 三角色不是 MCP 凭空发明的。它借鉴了几个传统协议设计:
- LSP (Language Server Protocol):VS Code 和语言服务器的协议,Host (editor) / Client (editor 里的连接器) / Server (language server)
- DAP (Debug Adapter Protocol):调试协议,类似三角色
- JSON-RPC:通信协议本身
MCP 的工程贡献是把 LSP 的三角色模式迁移到 AI 工具领域。LSP 证明了"编辑器和语言服务器解耦"能催生生态,MCP 复制了这个模式。
Tools / Resources / Prompts 的控制权分类
本章 5.3 节的三类能力(model-controlled / application-driven / user-controlled)是 MCP 的精髓设计。这个分类不是任意划分,是对"谁来决定何时调用"的精确切分:
| 能力 | 控制方 | 为何这样分 |
|---|---|---|
| Tools | model | 模型根据 context 决定何时调 |
| Resources | application | 应用主动取,避免模型乱取 |
| Prompts | user | 用户主动触发,slash command |
这个分类的工程智慧:不同能力该由不同主体控制。Tools 给模型(决策权),Resources 给应用(控制权),Prompts 给用户(触发权)。这种切分避免了"模型什么都能调"的权限失控。
MCP vs A2A:两个不同维度
Google A2A (Agent2Agent) 是 2025 年 Google 推出的另一个 Agent 协议。经常被拿来和 MCP 对比,但它们解决不同问题:
| MCP | A2A | |
|---|---|---|
| 连接 | Agent <-> Tool | Agent <-> Agent |
| 解决 | 工具连接标准化 | Agent 协作标准化 |
| 比喻 | USB-C | HTTP |
| 粒度 | 单工具 | 完整 Agent |
MCP 是"Agent 怎么调工具",A2A 是"Agent 怎么和其他 Agent 通信"。两者互补不冲突。一个完整的多 Agent 系统可能同时用 MCP(连工具)和 A2A(Agent 间通信)。
MCP 生态爆发的工程信号
本章 5.6 节列的 MCP 生态 star 数(截至 2026-07)反映了一个工程信号:MCP 已经是事实标准。
关键信号:
- 微软(Playwright MCP)、GitHub(github-mcp-server)、Google(mcp-toolbox)这些大厂都官方出 MCP server
- 主流 Host(Claude Code / Cursor / VS Code / Codex / Claude Desktop)全部原生支持
- 社区清单 awesome-mcp-servers 90k star
这种"大厂 + 工具厂商 + Host 厂商"三方共识,在协议史上不多见。LSP 用了 5 年才到这个阶段,MCP 用了不到 1 年。
MCP 已知局限的工程根源
本章 5.8 节列的 MCP 局限(stdio 单行限制 / 生命周期可绕过 / 依赖地狱 / Windows 路径脆弱 / 鉴权仅 HTTP / 协议升级断兼容 / 调试困难)不是 MCP 设计错误,是协议早期阶段的常见问题:
- stdio 限制:来自 JSON-RPC over stdio 的传输设计
- 生命周期可绕过:协议没强制 handshake 顺序
- 鉴权仅 HTTP:stdio transport 没标准鉴权机制
这些问题在协议演进中会逐步解决(2025-06-18 规范版本已经在补)。但生产环境用 MCP 时要知道这些坑,提前规避。
fastmcp 的简化贡献
PrefectHQ/fastmcp 把 MCP server 实现简化到装饰器级别(本章 5.4 节的示例就是 fastmcp 风格)。它的工程贡献:
@mcp.tool()自动转 schema@mcp.resource()自动转 resource- 函数签名 -> input_schema
- docstring -> description
这种"函数即工具"的抽象让写 MCP server 的成本从"几百行模板代码"降到"几行装饰器"。是 MCP 普及的关键推动力。
- MCP 解决 N×M 集成地狱,让工具跨 host 复用。
- 三角色:Host(AI 应用)/ Client(连接器)/ Server(能力提供方)。
- 三类能力:Tools(模型调)/ Resources(应用取)/ Prompts(用户触发)。
- 30 行 Python 能写一个 MCP server。
- 不是所有场景都该用 MCP——单应用单次工具用 tool use 更简单。
- 已知局限不少,生产环境要踩坑预警。
下一章讲 Anthropic 官方的 Claude Agent SDK——它把 agent loop、工具、权限都封装好了,你不用自己写第 3 章那 50 行代码。