MCP协议:号称要统一AI工具调用,但大多数人连第一步都走不对

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_ticketcreate_ticketassign_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面临几个硬伤:

  1. 协议层开销:比直接调用慢20%-50%,性能敏感场景用不了
  2. 生态碎片化:Python SDK、TypeScript SDK、Go SDK,行为不完全一致
  3. 模型支持不均衡:Claude原生支持,GPT需要适配层,Gemini支持不完整
  4. 工具描述质量:把责任交给开发者,但大多数人不擅长写给AI看的文档

更深层的矛盾是:MCP试图用一个协议统一所有模型的工具调用,但不同模型的工具调用能力差异巨大。Claude的工具调用准确率远高于开源模型,同样的MCP Server,换个模型可能就不好使了。

MCP解决的是"接口标准化"问题,但没有解决"调用质量"问题。接口统一了,不代表调用就对了。

我的建议是:如果你正在做跨模型的AI工具调用平台,MCP值得试。如果只是用单一模型做项目,Function Calling更简单、更快、更成熟。

别因为"MCP是趋势"就跟风上。技术选型要看场景,不看热度。


以上就是我对MCP的一些反面思考。不是唱衰MCP,而是希望大家在跟风之前先想清楚:你的场景到底适不适合,以及你有没有能力用好它。

协议只是协议,能不能用好,关键还是看人。

相关推荐
思考着亮2 小时前
2. Redis 缓存实战
后端
晚安code2 小时前
Java 并发编程必会的 JUC 辅助类:从 Callable 到阻塞队列
后端
叱咤月海鱼鱼猫2 小时前
后端生成图片传递到前端
后端
长栎2 小时前
你写的 AI 品控规则三个月就过期——不是规则错了,是你没给它做"回归测试"
后端
沙湖遇雨2 小时前
7.EventLoop 生命周期
后端
雨落倾城夏未凉2 小时前
halcon核心-模板匹配定位(二)
后端
ma_king2 小时前
Spring Boot 接入飞书自定义机器人
java·后端
2401_894915533 小时前
部署 GEO 优化源码常见报错排查:端口、伪静态、缓存问题解决
java·运维·服务器·后端·缓存·开源
卷无止境3 小时前
聊聊Web开发里的流式数据 从原理到FastAPI实战
后端·python·fastapi