MCP 接入中的契约与边界

我喜欢把工具接入理解为一张清楚的借用单:可以借什么、要提供哪些信息、借完以后会发生什么。协议能够统一一部分表达方式,但它不会替应用决定信任谁,也不会自动理解一次操作对用户的影响。
本文以一个“查询个人阅读清单”的工具为例,整理一套可以自己实现的接入检查。规范核对日期为 2026 年 10 月 21 日;涉及协议细节时,应以接入双方明确支持的版本为准。
先分清三种内容
MCP 的架构说明描述了 host、client、server 的协作关系,以及工具、资源和提示模板等服务端原语。协议处理上下文交换,应用仍然需要设计自己的模型使用方式与执行边界。
在阅读清单练习中,我会把数据目录作为资源,把查询动作作为工具,把“按主题整理阅读笔记”的表达方式作为模板。它们可以围绕同一份资料工作,但不需要拥有相同的权限。
| 能力 | 练习中的例子 | 需要明确的边界 |
|---|---|---|
| 资源 | 清单字段说明 | 谁可以读取,内容是否最新 |
| 工具 | 按标签查询文章 | 参数范围、返回上限、错误语义 |
| 模板 | 组织一份阅读计划 | 哪些内容是说明,哪些只是输入资料 |
不要因为名称里出现同一个项目名,就把读权限和写权限捆在一起。一个只需查阅清单的助手,没有理由同时拿到删除记录的能力。
写出一个有界的工具契约
下面是应用层输入结构示意,不是某个 MCP 版本的完整报文。这里刻意把查询长度、标签数量和返回条数限制为一个小练习可观察的范围。
type ReadingQuery = {
text: string // 最多 200 个字符
tags: string[] // 最多 5 个标签
limit: number // 1 到 20
}
type ReadingResult = {
items: Array<{ id: string; title: string; sourceUrl: string }>
nextCursor: string | null
}
这些限制需要在服务端实际校验。把它们写在描述里能够帮助模型选择参数,但文字描述不能代替执行器。对于不合法的参数,返回明确错误,别悄悄改成另一种查询后再声称成功。
把返回内容放在正确的位置
一篇网页可能包含“忽略之前的规则”这样的文字。资料助手需要把它当作网页内容保存,而不是将其提升为操作指令。同样,工具返回一段建议,也不意味着它可以替用户扩大下一次调用的权限。
我会在日志里分开保存用户目标、工具结果和执行决定。查看一次失败时,就能定位:错误来自资料内容、参数生成、权限判断,还是执行后的状态检查。
接入之前先做四次故障演练
先发送缺少必填字段的请求;再请求超过上限的结果;然后模拟服务端暂时不可用;最后让结果中混入一条格式不完整的记录。记录客户端如何展示错误,以及它是否会在不清楚结果时继续执行后续动作。
有副作用的能力应当单独设计确认与恢复流程。查询工具的测试结果,不能证明删除或发布工具也已经可靠。协议接通只是开始,能解释每一次行动,才是这个阅读助手真正有用的部分。
下一篇:工具调用的重试与幂等。
MCP 接入中的契约与边界 · LovelyCat · 2026-10-21
个人学习与创作札记 · 设计参考 Yohaku