Agent 工具调用设计最容易踩的 5 个坑:MCP Server 不是把 REST API 包一层
很多团队做 Agent 工具调用时,最自然的起点是:
**把现有的 REST API 包一层,变成 MCP Server。**
这很合理。现有 API 已经跑通了,业务逻辑已经验证了,包一层就能让 Agent 调用,看起来是最快的路径。
但这也是最容易踩坑的起点。
因为 MCP Server 不是"把 REST API 原样包装一遍"。工具名称、描述、JSON Schema、粒度、错误信息,每一个都会直接影响模型调用的准确率和上下文成本。
这篇用 checklist 结构,列出 Agent 工具调用设计最容易踩的 5 个坑,以及每个坑该怎么避。
---
## 坑 1:工具名称和描述写得像给人看的,不是给模型看的
### 坑是什么
工具名称和描述,是模型选择工具的唯一依据。但很多团队写工具描述时,按"给人看的文档"来写——写业务背景、写使用场景、写注意事项,就是没写清楚"什么时候该用这个工具、什么时候不该用"。
### 更像真实现场的过程
Agent 有两个工具:
- `process_data`:描述是"用于处理数据,支持多种数据格式和业务场景"
- `handle_request`:描述是"用于处理请求,覆盖常见业务流程"
用户问"帮我查昨天的订单"。模型在两个工具里选,两个描述都和"处理"沾边,模型选了 `handle_request`,但这个工具其实是用来处理工单的,不是查订单。
### 为什么会踩
- 描述写的是"这个工具是什么",不是"什么时候该用"
- 描述里有业务背景但没有使用边界
- 多个工具的描述有语义重叠,模型分不清
- 描述太长,占上下文,但关键信息没传递到
### 怎么避(Checklist)
- [ ] 描述里必须写"什么时候用"和"什么时候不用"
- [ ] 相似工具要在描述里显式区分("本工具用于 A,不要用于 B")
- [ ] 描述控制在 2-3 句话,不要写业务背景
- [ ] 工具名称要语义明确,不要用 `process_data` 这种泛化词
- [ ] 描述里给出 1-2 个典型调用场景
### 一句判断
**工具描述是写给模型看的选型指南,不是写给开发者看的业务文档。**
---
## 坑 2:JSON Schema 太宽或太严,模型要么猜不准要么传不进去
### 坑是什么
工具的参数定义靠 JSON Schema。Schema 写得太宽,模型会乱传参数;写得太严,模型传不进去,调用失败。
### 更像真实现场的过程
一个 `send_email` 工具,Schema 定义 `to` 字段为 `string`,没有格式约束。模型传了"张三"进去,工具层没校验,邮件发不出去。
另一个 `create_task` 工具,Schema 定义 `priority` 为枚举 `["P0","P1","P2","P3"]`,但没给默认值,也没写"不传时怎么处理"。模型有时候传、有时候不传,任务优先级忽高忽低。
### 为什么会踩
- Schema 太宽:字段类型不限、格式不限、范围不限,模型随便传
- Schema 太严:必填项太多、枚举值太窄,模型传不进去
- Schema 没给默认值:模型不传时,工具行为不确定
- Schema 没写示例:模型不知道参数长什么样
### 怎么避(Checklist)
- [ ] 字符串字段加格式约束(email、url、date)
- [ ] 枚举字段给全枚举值,并标注默认值
- [ ] 必填项控制在最少,能推导的不让模型传
- [ ] 复杂字段给 1-2 个示例
- [ ] Schema 和工具描述对齐——描述里说的参数,Schema 里要有
### 一句判断
**Schema 是模型和工具之间的契约。太宽模型会乱传,太严模型传不进去。**
---
## 坑 3:工具数量爆炸,全量注入上下文,token 成本和选择错误同步上升
### 坑是什么
Agent 接的工具越来越多。10 个工具时还能全量塞给模型,50 个工具时,工具定义本身就占了几千 token,模型选择准确率还会下降。
### 更像真实现场的过程
团队一开始接了 5 个工具,Agent 调用准确率 95%。后来业务扩展,工具涨到 40 个。团队把 40 个工具的定义全量塞给模型,结果:
- 每次调用上下文多了 3000 token
- 模型选择准确率掉到 78%——候选太多,模型开始混淆
- 高峰期 token 成本翻倍
### 为什么会踩
- 所有工具全量注入,没有按需发现
- 工具没有分类,模型在所有工具里选
- 工具描述重复或相似,模型分不清
- 没有工具检索机制,每次都把全部 schema 塞进去
### 怎么避(Checklist)
- [ ] 工具按业务域分类,不要平铺
- [ ] 实现按需发现:先检索候选工具,再加载精确 schema
- [ ] 工具描述做摘要化,全量注入时只给摘要,选中后再给完整 schema
- [ ] 定期清理低频工具,不要让历史工具一直占上下文
- [ ] 监控工具数量和调用准确率的关系,数量超过阈值时启动按需发现
### 一句判断
**工具不是越多越好。超过一定数量后,全量注入既费 token 又降准确率。**
---
## 坑 4:错误信息不可读,模型收到报错后不知道怎么修正
### 坑是什么
工具调用失败时,返回的错误信息是给开发者看的(stack trace、错误码),不是给模型看的。模型收到报错后,不知道怎么修正,要么重试同样的参数,要么放弃。
### 更像真实现场的过程
Agent 调 `create_order` 工具,传了 `customer_id: "abc"`。工具返回 `{"error": "INVALID_FORMAT", "detail": "ValidationError: customer_id must be int, got str"}`。
模型收到这个报错,看不懂"ValidationError"是什么意思,也不知道该怎么改。它可能会:
- 重试同样的参数(以为只是网络问题)
- 把 `customer_id` 改成另一个字符串
- 放弃调用,告诉用户"无法创建订单"
### 为什么会踩
- 错误信息是技术语言,不是模型能理解的
- 错误信息没告诉模型"该怎么修正"
- 错误信息没区分"可重试"和"不可重试"
- 错误信息没给出"正确参数应该长什么样"
### 怎么避(Checklist)
- [ ] 错误信息用自然语言写,说明"哪里错了、该怎么改"
- [ ] 区分可重试错误(超时、限流)和不可重试错误(参数错、权限不够)
- [ ] 给出正确参数的示例
- [ ] 对参数错误,明确指出哪个字段错了、应该是什么格式
- [ ] 对权限错误,说明"需要什么权限"或"该转人工"
### 一句判断
**错误信息是模型修正自己的依据。写给开发者看的报错,模型看不懂。**
---
## 坑 5:没有按需发现机制,每次都把所有工具塞给模型
### 坑是什么
这是坑 3 的延伸,但更严重。没有按需发现机制,意味着 Agent 永远在"全量工具集"里选,不管当前任务是什么。
### 更像真实现场的过程
用户问"今天天气怎么样"。Agent 有 40 个工具,其中 1 个是 `get_weather`。但模型每次都要在 40 个工具里选,而不是直接调 `get_weather`。
即使模型选对了,上下文里也塞了 39 个无关工具的 schema,白白浪费 token。如果选错了,用户问天气,模型调了 `send_email`。
### 为什么会踩
- 没有工具检索/路由层
- 没有按任务类型预过滤工具
- 没有按用户意图做工具候选集缩减
- 工具发现机制被认为是"高级功能",没在第一版做
### 怎么避(Checklist)
- [ ] 实现工具检索:根据用户意图,先检索候选工具(3-5 个),再让模型选
- [ ] 按业务域分组:不同任务类型加载不同工具集
- [ ] 用语义检索做工具发现:把工具描述向量化,按需召回
- [ ] 工具发现本身要有评测:召回率、准确率要监控
- [ ] 工具发现失败时要有兜底:检索不到候选时,怎么处理
### 一句判断
**按需发现不是高级功能,是工具数量超过 10 个后的必需品。**
---
## 一个最小可用的 MCP 工具设计 Checklist
把上面 5 个坑合并成一个可落地的 Checklist:
### 工具定义层
- [ ] 工具名称语义明确,不用泛化词
- [ ] 描述写"什么时候用 / 什么时候不用",2-3 句话
- [ ] 相似工具在描述里显式区分
- [ ] 描述里给 1-2 个典型调用场景
### 参数 Schema 层
- [ ] 字符串字段加格式约束
- [ ] 枚举字段给全枚举值 + 默认值
- [ ] 必填项控制在最少
- [ ] 复杂字段给示例
### 工具发现层
- [ ] 工具按业务域分类
- [ ] 超过 10 个工具时实现按需发现
- [ ] 全量注入时只给摘要,选中后再给完整 schema
- [ ] 定期清理低频工具
### 错误处理层
- [ ] 错误信息用自然语言写
- [ ] 区分可重试和不可重试错误
- [ ] 给出正确参数示例
- [ ] 明确指出哪个字段错了
### 可观测层
- [ ] 工具选择准确率要监控
- [ ] 参数校验失败率要监控
- [ ] 工具调用 token 成本要监控
- [ ] 按需发现召回率要监控
这个 Checklist 不复杂,但每一条都直接对应一个容易踩的坑。做完这 5 层,MCP Server 才不是一个"包了一层的 REST API",而是一个"为 Agent 设计的工具系统"。
---
## 结语
MCP Server 不是把 REST API 包一层。
工具名称、描述、Schema、粒度、错误信息、发现机制,每一个都会直接影响模型调用的准确率和上下文成本。
最容易踩的 5 个坑:
- 工具描述写得像给人看的
- Schema 太宽或太严
- 工具数量爆炸全量注入
- 错误信息不可读
- 没有按需发现机制
这 5 个坑踩了,模型再强也会调用出错。工具设计做得好,模型一般也能调对。
对技术团队来说,做 MCP Server 最该先建立的,不是"能不能包一层 API"的能力,而是:
**能不能按 Agent 的使用方式,重新设计工具边界。**
如果只是把 REST API 原样包一层,Agent 调用准确率和 token 成本都会出问题。真正能跑起来的 MCP Server,是按 Agent 任务重构了工具边界的系统。
