MCP 工具设计笔记:从“能调用”到“可安全执行”

973 字
5 分钟
MCP 工具设计笔记:从“能调用”到“可安全执行”

MCP 解决了模型与外部能力之间的连接方式,但协议接通并不代表工具已经适合交给 Agent 使用。

第一次设计工具时,很容易把已有 HTTP 接口直接暴露给模型:接口有几个参数,工具就照搬几个参数。实际使用后会发现,面向程序员的 API 与面向模型的工具契约并不完全相同。模型需要更清晰的使用条件、更小的操作范围,以及可以据此修正下一步的结构化反馈。

1. 工具名称和描述就是路由条件#

模型通常先根据名称和描述判断是否调用工具,因此描述不能只写“查询数据”或“更新记录”。它至少要说明:

  • 工具适合解决什么问题;
  • 什么时候不应该调用;
  • 必填参数的业务含义;
  • 返回结果能证明什么;
  • 操作是否会修改外部状态。

如果多个工具的语义高度重叠,模型就容易随机选择。与其提供十个边界模糊的工具,不如提供少量职责清楚的能力。

2. Schema 要减少无效自由度#

工具参数应该尽量使用枚举、明确字段和可验证格式,而不是让模型拼接一段自由文本再由服务端猜测。

例如文件操作可以把 pathencodingoverwrite 分开;查询工具可以明确分页、排序和过滤条件。对于互斥参数,应在说明和服务端校验中同时表达,不能只依赖模型“自觉”。

3. 先区分只读和写操作#

我倾向于把工具按风险分层:

  • 只读工具:搜索、读取、状态检查,可以自动执行;
  • 可恢复写入:创建草稿、生成临时文件,需要返回明确变更;
  • 重要修改:覆盖配置、发送消息、发布内容,需要确认目标;
  • 破坏性操作:删除、批量迁移、权限调整,需要额外审批和范围校验。

一个名为 manage_project 的万能工具很难设置安全边界。把读与写拆开,既有利于权限控制,也能让执行日志更容易审计。

4. 返回错误要能指导下一步#

仅返回 success: false 对 Agent 帮助很小。更实用的错误结构应该包含:

{
"code": "RESOURCE_NOT_FOUND",
"message": "未找到目标文件",
"retryable": false,
"details": {
"path": "src/config/app.ts"
}
}

Agent 可以据此判断是修改参数、重新检索,还是停止并请求用户确认。对限流、超时和临时网络故障,还应明确是否适合重试,避免模型在永久错误上反复调用。

5. 写工具要考虑幂等性#

Agent 可能因为超时或响应丢失而重复调用。创建订单、发送消息或提交任务等操作,如果没有幂等键,就可能产生重复副作用。

因此写操作最好支持:

  • 请求级幂等标识;
  • 执行前的目标状态检查;
  • 明确的变更摘要;
  • 可查询的操作结果;
  • 在条件允许时提供撤销路径。

6. 一份实用检查清单#

  • 工具是否只有一个主要职责?
  • 描述能否让模型知道“不该什么时候用”?
  • 输入是否可以在服务端完整校验?
  • 读写权限是否明确分离?
  • 重复调用是否会造成额外副作用?
  • 错误是否能指导重试、改参或停止?
  • 返回值是否包含可验证的目标和状态?
  • 日志能否追踪调用者、参数范围与执行结果?

MCP 工具的价值不只是让模型“连接更多系统”,而是用稳定契约把模型的不确定推理与外部系统的确定执行隔离开。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

MCP 工具设计笔记:从“能调用”到“可安全执行”
https://blog.miansu.eu.cc/posts/mcp-tool-contract-design/
作者
叶立恒
发布于
2026-05-18
许可协议
CC BY-NC-SA 4.0

评论区