切换深色模式
02 · 工具、MCP 与 Skills
本课交付:工具契约与四种拒绝场景。前置:01 的执行轨迹;课后完成 L2:让契约阻止一次越权,用实际输出证明执行层边界。
视频辅助阅读:今天不coding 视频导读,包含工具调用时间定位,以及 MCP 本地连接、会话和授权的边界校正。
一、场景:这一步要解决什么问题
上一章的助手已经会提出“读取一篇笔记”。现在给它一个合法文档 ID,却发现文档属于另一位用户:如果只检查参数类型,这次请求仍会通过。
本章把工具当作业务接口设计。我们要解决的不只是模型会不会调用,还包括它最多能读什么、空结果意味着什么、失败后能否重试。
二、目标与方案设计
本章目标:设计一个模型能正确选择、运行时能验证、出错后能恢复的工具,并区分协议、规程与权限。资料核对:2026-09-06;下文协议字段示例以 MCP 2025-11-25 工具规范为明确版本参考。
工具契约比工具数量重要
工具是模型与程序之间的接口。名称说明动作,参数描述输入,返回值给出可被后续使用的结果。不要让调用方猜测时间单位、路径基准或空结果的含义。
下面是本专题研究助手的教学契约:
json
{
"name": "search_notes",
"description": "搜索当前用户有权读取的笔记,返回摘要与稳定文档 ID;不返回全文",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string", "minLength": 1 },
"limit": { "type": "integer", "minimum": 1, "maximum": 5 }
},
"required": ["query", "limit"],
"additionalProperties": false
}
}这是契约示意,不能直接当作所有模型 API 的请求体;不同提供方支持的 Schema 范围可能不同。
建议返回 doc_id、title、snippet、source、revision。读取全文再用另一个 read_note 工具,避免每次搜索都塞入大量正文。用户身份由服务端可信会话传入,不能让模型通过参数指定另一个用户来扩大读取范围。
如何判断一个工具粒度合适
工具过细,模型需要多次调用才能获得一次决策所需的信息;工具过宽,则参数复杂、返回过多,也容易隐藏副作用。Anthropic 的工程文章建议围绕实际任务设计工具、明确命名边界,并控制返回信息量。工具设计经验。
以本案例为例:
| 设计 | 问题 | 调整建议 |
|---|---|---|
execute(action, payload) | 名称与参数无法表达具体边界 | 暴露明确的搜索和读取动作 |
list_all_notes() | 一次把整个库送回上下文 | 支持查询、分页与返回上限 |
search_and_publish() | 读取与外部写入混在一起 | 搜索与发布分别授权、验收 |
read_note(id, revision) | 目标与版本清楚 | 返回稳定来源和截断信息 |
不要把“拆得越多”作为优化目标。先用真实任务观察错误选择率、无效参数率和多余调用量,再调整接口。
MCP 负责连接能力
MCP 描述应用与能力服务之间的通信。常见服务端能力有:Tools 提供可执行操作,Resources 提供上下文数据,Prompts 提供可复用提示模板。工具可被发现,并通过协议请求调用。官方架构说明。
text
Agent 应用 → MCP 客户端 → MCP 服务端 → 笔记库 / 业务 API模型工具调用是“模型输出动作请求”的机制;MCP 是应用接入外部能力的一种协议。接入 MCP 后,应用仍需实现任务循环、权限判断、错误处理和验收。
Skills 负责操作规程
Agent Skills 用 SKILL.md 和可选脚本、参考资料、模板描述某类任务的做法。常见加载方式是先读取名称和描述,匹配任务后再读取完整说明及必要资源。格式与加载方式。
例如,本知识库可以把“总结一篇技术文章”的步骤写成技能:标注来源、区分事实与建议、生成复习题、检查站内链接。它描述怎么做,搜索工具提供执行能力;两者可以配合。此处是设计示例,尚未创建技能包。
三、实现拆解
完整工具调用链:六个检查点
- 发现能力:应用把允许使用的工具说明交给模型。工具清单应与当前用户、任务范围相匹配。
- 生成请求:模型输出工具名称、参数和调用标识;这只是候选动作。
- 验证结构:检查类型、必填字段、长度与枚举,不把“JSON 可解析”当成业务有效。
- 验证权限:将可信会话身份与目标资源绑定,再执行访问控制。
- 执行并记录:保留开始、结束、失败或结果未知状态。
- 回传观察:结果关联原调用 ID,让后续决策知道是哪个动作产生了它。
以上是本研究助手的运行时设计。MCP 的 tools/list、tools/call 和工具 Schema 则是协议层定义的能力。MCP 工具规范。
返回值也需要契约
以下为本案例自定义结果格式,不是 MCP 原生响应的完整格式:
json
{
"ok": true,
"items": [{
"doc_id": "note-17",
"revision": "r3",
"title": "延时任务",
"snippet": "用于展示的短摘要",
"source": "/notes/delayed-tasks"
}],
"truncated": false,
"next_cursor": null
}truncated 防止模型把被截断的输出理解成全部内容;revision 使后续读取与引用能够绑定同一版本;next_cursor 用来明确继续获取数据的方式。排序分数如果暴露,也应说明它只是检索排序信号,不是结论正确的概率。
协议错误与业务执行错误要分开。MCP 2025-11-25 中,JSON-RPC 请求层问题与工具结果中的 isError: true 是不同通道;调用方应查看结果内容,不能只凭传输成功判断工具成功。错误处理规范。
把错误设计进接口
| 返回情况 | 应用处理建议 |
|---|---|
| 空结果 | 视为成功搜索但没有匹配,允许修改查询 |
| 参数无效 | 返回字段级错误,不原样重复调用 |
| 临时限流 | 在总预算内按服务提示退避 |
| 无权限 | 返回明确拒绝,不尝试换身份 |
| 写入超时 | 先查操作状态,再判断能否重试 |
对于发送、创建和扣款等写操作,超时不等于未发生。工程上可使用业务幂等键和操作状态查询,让重复请求不会重复产生业务效果。
MCP 不会替你完成业务安全
工具标记为只读或幂等,不代表应用可以放弃验证;从不可信服务收到的描述和提示仍然需要按信任边界处理。身份认证回答“谁在调用”,资源授权回答“能访问什么”,模型选择回答“这次想做什么”。这三层不应混为一谈。
OWASP 将过多功能、过大权限和过强自主性列为 Excessive Agency 的主要成因。落实到本研究助手,就是只给查询所需能力,用会话身份检查每次资源访问,并为新增写操作建立独立边界。OWASP LLM06:2025。
Skills:把稳定流程做成可维护材料
Agent Skills 规范要求 SKILL.md 包含名称与描述等元数据,正文描述步骤;可以附带脚本和参考材料。描述应说明何时适用,而不只是写“一个很有用的技能”。allowed-tools 是实验字段,其支持方式取决于具体宿主,不能据此假定实际执行权限。Skills 规范。
本案例可设计如下资料包,这里只展示结构:
text
research-note/
SKILL.md 适用条件、来源要求、写作和验收步骤
references/style.md 引文与结论的写作约定
assets/template.md 问题、证据、边界、复习题模板规程与工具的变化周期也不同:工具接口变化需要适配代码与 Schema;研究方法变化可能只需调整规程和回归用例。把两者解耦,可以避免每次改写作流程都重做连接层。
推演一次参数正确但权限不足的请求
研究助手以 alice 的可信身份运行,收到 read_note(id='private', revision='1')。字段格式正确,只能说明通过了参数检查;它不能证明 Alice 有权读取该资源。
在离线源码中,读取必须同时匹配文档 ID 与 owner。查不到授权资源时返回 not_found_or_not_allowed,不暴露他人的正文,也不透露资源究竟不存在还是无权限。搜索接口先过滤所有者,而读取接口仍然独立检查,避免调用方绕开搜索直接猜 ID。
这里的 user 参数由测试程序传入,是模拟可信身份,不是真实登录认证。上线时必须从已验证的服务端会话获得身份。示例用手工校验实现这两个工具的必填字段、类型、取值边界及额外字段拒绝;它不是通用 JSON Schema 校验器,也没有实现 MCP 服务端。
四、验证与练习
工程加深:结构化返回与模型结构化输出不是一回事
MCP 的 structuredContent 是工具服务返回的数据;模型的结构化输出是模型生成受约束的数据。前者仍需核对服务来源、字段与业务含义,后者即使格式正确也可能请求错误资源。MCP 2025-11-25 允许定义 outputSchema;声明后,服务端结果必须符合结构,客户端也应验证。输出结构规范
本案例将响应处理分成:传输成功 → 协议有效 → 业务成功 → 输出符合契约 → 可作为当前任务证据。任意一层失败,都不能直接标记“研究完成”。
工具清单也要控制成本和权限
工具很多时,先根据任务筛选候选能力,再让模型选择具体工具;但“没有展示某工具”不是安全控制,执行入口仍需白名单与资源授权。工具目录自身可能过期,所以应记录所用契约版本并拒绝不兼容参数,不能静默改变单位或副作用。
建议对搜索工具做一个小型对照实验:只改名称和描述、只改返回字段、只改默认返回量,每次固定其他条件,观察误选工具、无效参数、重复读取和端到端结果。不要把减少 token 当成唯一胜负标准;删掉版本或适用条件可能让输出更短、答案却更错。这个实验方案受官方工具工程经验启发,本站未报告实测收益。
自测与参考答案
让另一个开发者只看契约,不看实现:他能解释空结果、最大返回量和权限范围吗?若不能,先改契约。
再问:工具返回 HTTP 成功但包含业务错误,是否可以标记完成?不可以。把任意用户 ID 作为模型可填参数是否安全?仅有 Schema 不够,资源授权必须使用可信身份判断。
五、本章小结
模型选择动作,工具契约定义边界,运行时负责执行边界。MCP 连接能力,Skills 组织规程,它们都不替代资源授权。下一章处理另一半问题:即使读到合法资料,也要判断哪些内容应进入当前上下文。
六、参考资料
- Writing effective tools for agents:工具粒度、命名与结果设计。
- MCP 工具规范,2025-11-25:明确版本的字段和错误约定。
- Agent Skills Specification:规程包结构与字段限制。
- OWASP Excessive Agency:能力、权限与自主性边界。
返回 Agent 专题目录。本文场景与推演为原创教学设计,参考写法及资料边界见专题目录。