MCP协议:号称要统一AI工具调用,但大多数人连第一步都走不对
最近MCP(Model Context Protocol)在技术圈的热度居高不下。
我翻了翻掘金上的文章,清一色的套路------先科普MCP是什么,再贴个架构图,然后演示一个Hello World,最后总结"MCP是未来"。
我换个角度。
MCP我用了一个月,踩了一堆坑。今天不教你怎么搭MCP,而是告诉你大多数人用MCP都用错了,错在哪,后果是什么,以及怎么才算用对了。
MCP到底是什么,一句话说清楚
MCP是Anthropic搞的一个开放协议,目标是标准化AI模型与外部工具之间的通信方式。
打个比方:USB接口出现之前,鼠标用PS/2,打印机用并口,键盘用串口,每个外设都有自己的接口标准。MCP出现之前也差不多------OpenAI有Function Calling,Anthropic有Tool Use,Google有自己的方式,工具开发者要为每个平台写不同的适配。
MCP想做的事情很简单:一个协议,所有模型都能用。
听起来很美好对吧?但实际用起来,完全是另一回事。
用对了是什么样
先说正面案例,免得你觉得我是在全盘否定。
我们组有个场景:内部有个工单系统,需要AI能够查询工单状态、创建工单、分配工单。之前用Function Calling实现,换了个模型就得重写适配层。
后来用MCP包了一层,Server端暴露三个工具:get_ticket、create_ticket、assign_ticket。Client端不管用什么模型,只要支持MCP协议,直接就能调用。
这个场景用MCP是对的,因为:
- 工具接口稳定,不经常变
- 调用逻辑简单,没有复杂的参数依赖
- 确实需要跨模型支持
用对了的效果:
| 指标 | Function Calling | MCP |
|---|---|---|
| 模型迁移成本 | 重写适配层 | 改一行配置 |
| 工具复用性 | 绑死单一模型 | 跨模型复用 |
| 维护成本 | 每个模型一套 | 统一维护 |
| 调试难度 | 中等 | 较高 |
看起来确实有优势。但注意,这是"用对了"的场景。
用错了是什么样
接下来是重头戏。
第一种错:什么都往MCP里塞
最常见的错误。有些人听说了MCP之后,恨不得把所有功能都包成MCP Server。
我见过一个团队,把数据库查询、文件操作、HTTP请求、消息队列、缓存操作全部包成了MCP Server。光工具列表就有50多个。
你知道结果是什么吗?
AI拿到50个工具的描述,光工具描述就占了上下文窗口的三分之一。留给实际对话的上下文严重不足,AI的回答质量直线下降。
更离谱的是,很多工具之间有依赖关系------比如"查询数据库"之后才能"更新缓存",但MCP协议本身不支持工具间的依赖声明。AI经常在没查询数据库的情况下直接尝试更新缓存,然后报错。
MCP不是万能的包装层。工具越多,AI的选择空间越大,出错概率也越高。每个工具都会占用上下文空间,50个工具的描述可能吃掉你三分之一的上下文窗口。
第二种错:把MCP当性能方案
有些人觉得MCP比Function Calling更快、更高效。
这是一个很常见的误解。MCP本质上只是一个通信协议,它定义了Client和Server之间怎么对话,但不涉及任何性能优化。
实际测试下来,MCP的响应时间通常比直接调用Function Calling慢20%-50%,因为多了一层协议开销:
text
Function Calling路径:
AI模型 → 工具函数 → 返回结果
MCP路径:
AI模型 → MCP Client → JSON-RPC序列化 → 传输层 → MCP Server → 工具函数 → 返回结果 → JSON-RPC反序列化 → MCP Client → AI模型
多出来的每一层都是开销。如果你的场景对延迟敏感,MCP可能不是好选择。
第三种错:不处理错误场景
MCP协议定义了错误码,但大多数人写MCP Server的时候,错误处理几乎是零。
我见过一个MCP Server,调用工具时如果参数不对,直接返回500错误,错误信息是"Internal Server Error"。AI拿到这个错误信息后完全不知道发生了什么,只能瞎猜。
正确做法是返回结构化的错误信息:
python
# 错误示范
def get_ticket(ticket_id: str):
ticket = db.query(ticket_id)
return ticket # 如果ticket_id不存在,直接抛异常
# 正确示范
def get_ticket(ticket_id: str):
ticket = db.query(ticket_id)
if ticket is None:
return {
"error": "ticket_not_found",
"message": f"工单 {ticket_id} 不存在,请检查ID是否正确",
"suggestion": "可以使用 list_tickets 工具查看可用工单列表"
}
return ticket
区别在于:第一种让AI无从下手,第二种告诉AI出了什么问题以及下一步该怎么做。
第四种错:工具描述写得太烂
MCP的工具描述是给AI看的,但很多人写描述跟写给开发者的API文档一样。
python
# 烂描述
@tool(description="Get user info by id")
def get_user(user_id: str):
...
# 好描述
@tool(description="根据用户ID查询用户信息,包括姓名、邮箱、注册时间。当用户问到'某人的信息'、'查找用户'时使用此工具。如果用户没有提供ID,请先询问。")
def get_user(user_id: str):
...
第一种描述,AI不知道什么时候该用这个工具,也不知道参数从哪来。第二种描述,AI清楚地知道触发条件和参数来源。
工具描述的质量直接决定了AI调用工具的准确率。这不是MCP的问题,但MCP把工具描述的 responsibility 交给了开发者,而大多数开发者并不擅长写给AI看的文档。
大多数人到底在怎么用MCP
我总结了下观察到的情况:
| 使用方式 | 占比 | 典型特征 | 效果 |
|---|---|---|---|
| 全包型 | 30% | 什么都往MCP里塞 | 上下文爆炸,AI变笨 |
| 性能追求型 | 20% | 以为MCP更快 | 延迟反而更高 |
| 零错误处理型 | 25% | 不写错误信息 | AI出错后无法恢复 |
| 烂描述型 | 15% | 工具描述像API文档 | AI调用准确率低 |
| 精准使用型 | 10% | 只包核心工具,描述清晰 | 正收益 |
又是10%。
和Skills的情况一模一样------真正获益的永远是少数。
那10%的人做对了什么?
- 只暴露5-10个核心工具,不贪多
- 工具描述写给AI看,包含触发条件和参数来源
- 完整的错误处理,告诉AI下一步该怎么做
- 定期监控工具调用日志,发现低频工具就下线
- 不用MCP替代直接调用,性能敏感场景用Function Calling
MCP的坑,远不止这些
除了上面说的"用错",MCP本身也有一些设计层面的问题。
第一个坑:连接管理
MCP的stdio传输方式是进程级通信,每个MCP Server是一个独立进程。如果你有10个MCP Server,就是10个子进程。进程的启动、关闭、异常恢复都需要你自己管理。
MCP SDK没有提供连接池机制。如果你的工具调用频率高,每次都新建连接、销毁连接,性能开销很大。
第二个坑:并发竞态
MCP协议基于JSON-RPC 2.0,理论上支持并发请求。但很多MCP Server的实现是单线程的,并发请求会排队,甚至互相阻塞。
我遇到过一个问题:AI同时调用了"查询工单"和"创建工单"两个工具,Server端因为共享了同一个数据库连接,两个请求互相阻塞,最后超时了。
第三个坑:版本兼容
MCP协议还在快速迭代,SDK版本之间不完全兼容。我升级了一次Python SDK,结果工具注册方式变了,所有Server都得改。
你到底该不该用MCP
说了这么多反面,给个决策参考:
text
你需要让AI调用外部工具?
├── 只用一个模型?
│ ├── 是 → Function Calling就够了,别上MCP
│ └── 否 → 继续
│
├── 工具数量少于5个?
│ ├── 是 → Function Calling更简单
│ └── 否 → 继续
│
├── 需要跨团队复用工具?
│ ├── 是 → MCP合适
│ └── 否 → 继续
│
├── 对延迟敏感?
│ ├── 是 → 别用MCP,协议开销太大
│ └── 否 → 继续
│
├── 愿意维护MCP Server进程?
│ ├── 是 → 可以用MCP
│ └── 否 → 老老实实用Function Calling
│
└── 以上都不是?
└── 你可能不需要MCP
MCP的未来,我谨慎悲观
乐观地看,MCP的方向是对的。标准化工具调用协议,这个需求是真实存在的。如果生态成熟了,开发者写一次工具,所有模型都能用,确实是效率提升。
悲观地看,MCP面临几个硬伤:
- 协议层开销:比直接调用慢20%-50%,性能敏感场景用不了
- 生态碎片化:Python SDK、TypeScript SDK、Go SDK,行为不完全一致
- 模型支持不均衡:Claude原生支持,GPT需要适配层,Gemini支持不完整
- 工具描述质量:把责任交给开发者,但大多数人不擅长写给AI看的文档
更深层的矛盾是:MCP试图用一个协议统一所有模型的工具调用,但不同模型的工具调用能力差异巨大。Claude的工具调用准确率远高于开源模型,同样的MCP Server,换个模型可能就不好使了。
MCP解决的是"接口标准化"问题,但没有解决"调用质量"问题。接口统一了,不代表调用就对了。
我的建议是:如果你正在做跨模型的AI工具调用平台,MCP值得试。如果只是用单一模型做项目,Function Calling更简单、更快、更成熟。
别因为"MCP是趋势"就跟风上。技术选型要看场景,不看热度。
以上就是我对MCP的一些反面思考。不是唱衰MCP,而是希望大家在跟风之前先想清楚:你的场景到底适不适合,以及你有没有能力用好它。
协议只是协议,能不能用好,关键还是看人。