发布时间:2026-07-12
标签:AI Agent|LLM|MCP|标准化|协议|工程实践
系列导航
上一篇:AI Agent 工程实践(13):Tool Calling——Agent 为什么要学会用工具?
下一篇:AI Agent 工程实践(15):RAG 真正的瓶颈不是检索,而是知识治理
本文是 [AI Agent 工程实践] 系列的第 14 篇(第二季 · 工程实现)。
去年我写了三个 Agent 项目,用了三个框架:Claude Desktop、LangChain、自己裸写。
同一个"查数据库"的工具,我写了三遍。不是因为逻辑不同——查询逻辑完全一样,但每个框架要求不同的声明格式、不同的调用方式、不同的错误处理。
我突然意识到:Agent 的"手"已经标准化了(Function Call),但手抓的"工具"却没有统一接口。每个框架都是自己的插座,你换个房间就得换插头。
直到我理解了 MCP 在干什么——它不是又一个工具框架,而是一个工具的 USB 协议。插一次,哪里都能用。
本文你将学到
✓ 为什么 Agent 的工具需要标准化——以及没有标准化时多痛苦
✓ MCP 的本质:不是框架,是协议——Model ↔ MCP ↔ 外部世界
✓ Function Calling / Tool Calling / MCP 三者的精确区别和层级关系
✓ MCP 的完整架构:Host → Client → Protocol → Server → Resources/Tools
适合阅读
✓ 在不同 Agent 框架之间切换过、被"工具适配"折磨过的人
✓ 听过 MCP 但不清楚它和 Function Call 有什么区别的人
✓ 想给团队搭一套"写一次、到处用"的工具生态的人
问题背景
第13篇讲清楚了 Tool Calling 的四件套:Registry / Schema / Selection / Retry。这套设计在一个 Agent 内部跑得很顺。
但问题来了:工具是写了,可它只属于"这一个 Agent"。换个框架,全要重写。
这不是假设,是真实困境。我踩过的坑:
- Claude Desktop 要求 MCP 格式——工具必须实现 MCP Server
- LangChain 要求
BaseTool子类——工具必须继承它的抽象 - 裸写 FastAPI Agent 要求自定义 Schema——工具按自己的 JSON Schema 来
同一个"查数据库",三个框架,三种写法。不是逻辑变了,是接入标准不同——就像 USB-C 和 Lightning 和 Micro-USB:功能一样,插头不同,每次换设备就要换线。
如果 Agent 的工具能像 USB 一样——一个标准,插上即用——会怎样?这就是 MCP 要解决的问题。
错误尝试
第一次:为每个框架写适配层
最直接的做法——每个框架的工具调用写一遍。用一个 CSV 记下来"工具 X 在框架 A 怎么调、在框架 B 怎么调"。
结果:三个框架、十个工具 = 三十份适配代码。加一个新工具,三份全要更新。这不是开发,是翻译——把同一个工具的说明书翻成三种方言。
第二次:自己写一个工具抽象层
既然框架不同,我在它们上面再封一层——定义自己的 Tool 接口,每个框架适配一次,然后工具对接口写。
结果:短期的确省了事。但不久后,我又想接入一个新的 Agent 平台(Coze)。它的工具格式又不一样。我发现自己在维护一个"小型 MCP"——解决碎片化的方式,是加上自己的那一份碎片。
两次尝试指向同一个结论:工具接入的标准化,不能靠"自己再封一层"解决——它需要一个行业级的协议。一个人的抽象层是碎片,一群人的协议才是标准。MCP 就是那个协议。
关键观察
我把 Agent 工具接入的历史路径画了一条线:
每一步解决一个问题,同时暴露下一个:
| 阶段 | 解决了 | 暴露了 |
|---|---|---|
| Prompt 手写 | — | 不可靠,格式漂移 |
| Function Call | LLM 能可靠输出工具调用 | 工具怎么管理? |
| Tool Calling | Registry/Schema/Selection/Retry | 跨框架不兼容 |
| MCP | 工具跨框架复用 | 生态还在早期 |
Function Call 决定'怎么叫工具',MCP 决定'工具怎么接入'。
一个是 LLM 层面的能力,一个是协议层面的标准——不是竞争关系,是栈上不同的两层。
最终方案:MCP 作为 Agent 的 USB 协议
Model → MCP → 外部世界
你给的链路——这是 MCP 的核心架构:
MCP 的关键设计:Host(AI 应用)和 Server(工具)通过 MCP 协议通信。Server 只写一次,任何实现了 MCP Client 的 Host 都能用。工具和框架解耦了。
和 Function Calling / Tool Calling 的精确区别
这是全篇的核心——三个概念不是同义词,是不同层级的不同东西:
| 概念 | 层级 | 负责什么 | 比喻 |
|---|---|---|---|
| Function Call | LLM 层 | 让模型输出结构化函数调用 | 人学会"用语言描述动作" |
| Tool Calling | Agent 层 | 管理工具的选、调、重试 | 人的"工具使用技能" |
| MCP | 协议层 | 标准化工具的接入方式 | USB 接口 |
逐层关系:
- LLM 通过 Function Call 表达"我要调
db_query,参数是 SQL" - Agent 通过 Tool Calling(13 篇的四件套)决定"该不该调、怎么调、失败了怎么办"
- MCP 决定"
db_query这个工具怎么被 Agent 发现和连接"
一句话:Function Call 是"嘴"(表达意图),Tool Calling 是"脑"(决策治理),MCP 是"插座"(标准化接入)。三者在同一栈上,但不在同一层。
MCP Server 的实际效果
写一个 MCP Server,三个框架通用:
# mcp-server-db.yaml name: database-tools tools: - db_query: schema: query.json # 一份 Schema - db_list_tables: schema: list.json不改一行工具代码:
- Claude Desktop:加一行
mcp-server-db.yaml到配置 - Cursor:同一份 yaml
- 你的 FastAPI Agent:同一份 yaml
这就是 MCP 的"USB 效应":写一次,哪里都能插。
架构图 / 流程图
MCP 的会话生命周期
关键:发现(Discovery)阶段——Server 主动暴露它能提供什么工具,Host 注册到自己的 Tool Calling 系统(13 篇的 Registry)。MCP 不是被动等待调用,是主动声明能力。
代码或配置示例
MCP Server 声明 vs 直接 Function Call
直接 Function Call(框架锁死):
# 每个框架写一次 # Claude 版本 @claude_tool def db_query(sql: str) -> list: ... # LangChain 版本 class DBQueryTool(BaseTool): ... # 自定义版本 async def db_query_handler(request): ...MCP Server(写一次,到处用):
{ "name": "db_query", "description": "Execute a read-only SQL query", "inputSchema": { "type": "object", "properties": { "sql": { "type": "string", "description": "SQL SELECT statement" } }, "required": ["sql"] } }# mcp_server.py —— 这是唯一要写的地方 @server.tool() async def db_query(sql: str) -> list[dict]: """Execute a read-only SQL query""" validate_readonly(sql) # 安全约束 return await database.fetch_all(sql)对比触目惊心:MCP 模式下,工具逻辑只写一次,Schema 声明一次,三个框架共享。从"写 N 遍"到"写 1 遍",差的就是一个协议。
设计权衡
| 候选方案 | 优点 | 缺点 | 为什么不选 |
|---|---|---|---|
| 每个框架写适配 | 灵活、无依赖 | 重复劳动、不可持续 | N × M 的适配矩阵 |
| 自己抽象一层 | 短期省事 | 自己成为新碎片 | 一个人的抽象 ≠ 行业标准 |
| 用 MCP 协议 | 跨框架、生态在长 | 协议还在早期、工具覆盖不全 | 选择理由:唯一有希望结束碎片化的方向 |
MCP 不是银弹。它的生态还在早期——不是所有工具都有 MCP Server,不是所有框架都支持 MCP Client。但方向是对的:协议级标准化,永远比框架级二次封装更有生命力。HTTP 没被某个框架的"封装版"取代,USB 没被某个厂商的私有接口取代——标准协议胜出的逻辑从来没变过。
总结
✅ MCP 不是又一个工具框架,是工具的 USB 协议——解决"写一次、到处用"。
✅ 接入碎片化是 Agent 工具生态的最大痛点——每个框架有自己的插座,换框架就得换插头。
✅ Function Call(LLM 层)、Tool Calling(Agent 层)、MCP(协议层)——三者不是竞争,是栈上不同层级,各自解决各自的问题。
✅ MCP 架构:Host → Client → Protocol → Server → Resources/Tools。Server 主动暴露能力,Host 注册后使用。
✅ MCP 生态还在早期,但方向是对的——协议级标准化永远比框架级封装更有生命力。
参考资料
- MCP 官方文档(Model Context Protocol)→ 协议规范、Server/Client 开发指南
- 第 13 篇:Tool Calling→ MCP 接入后的上层治理(Registry/Schema/Selection/Retry)
- OpenAI Function Calling 文档→ LLM 层的能力基础,MCP 的下层依赖
- Anthropic — MCP Announcement→ MCP 的设计动机与"USB 协议"类比
- LangChain — MCP 集成文档→ 框架如何作为 MCP Host 接入工具
系列导航
上一篇:AI Agent 工程实践(13):Tool Calling——Agent 为什么要学会用工具?
下一篇: AI Agent 工程实践(15):RAG 真正的瓶颈不是检索,而是知识治理
本文是 [AI Agent 工程实践] 系列的第 14 篇(第二季 · 工程实现)。