MCP 进入工程现场后,最先要设计的是权限边界
工具接入协议降低了连接成本,也让权限、确认、审计和失败恢复成为必须先回答的系统问题。
发布于
当模型可以调用文件、数据库和业务系统时,讨论重点会从“它会不会回答”转向“它能代表谁做什么”。统一的工具接入协议降低了适配成本,这是一件好事;但连接变得容易以后,原来散落在各个集成里的权限问题会更集中地暴露出来。
先画能力图,再写提示词
一个工具名称通常不足以表达风险。例如 update_record 可能只更新草稿,也可能直接改动客户可见数据。接入前应该把能力按影响拆开,至少回答四个问题:
- 调用是只读、可逆写入,还是不可逆操作?
- 参数范围由谁约束,模型能否扩大目标集合?
- 哪些操作必须让用户看到完整预览并确认?
- 结果和错误是否进入可检索的审计记录?
这张能力图应当来自服务端真实授权,而不是写在系统提示词里的愿望。提示词可以帮助模型选择,但不能替代权限检查。
用策略包住工具调用
下面是一段简化的策略判断。重点不是枚举本身,而是默认拒绝未知能力,并让高影响操作进入显式确认分支。
type Risk = 'read' | 'reversible-write' | 'destructive';
const policy: Record<string, Risk> = {
search_notes: 'read',
create_draft: 'reversible-write',
delete_project: 'destructive',
};
export function canRun(tool: string, confirmed: boolean) {
const risk = policy[tool];
if (!risk) return false;
if (risk === 'destructive') return confirmed;
return true;
}
真实系统还要验证调用者身份、资源归属、参数大小和速率限制。对于批量操作,确认页面必须展示最终展开后的对象,而不是只显示一句“清理旧数据”。如果工具支持 dry-run,预览结果也应绑定到随后执行的参数,避免确认后目标集合发生变化。
失败恢复比成功演示更重要
工具调用会遇到超时、部分成功和外部状态变化。客户端需要区分“请求没有送达”“服务端已接受但结果未知”和“已完成”,否则自动重试可能制造重复写入。可写工具最好携带幂等键,并返回稳定的操作编号。
我判断一个接入是否接近可用,不看它连续成功了多少次,而看一次网络中断后,操作者能否知道发生了什么、能否安全继续。协议解决连接,产品仍要为授权、确认、审计和恢复负责。
(示例内容,用于站点骨架验证)