MCP 有意思的地方,在于它让 AI 集成更像明确的软件边界,而不只是提示词技巧。
模型不应获得含糊的应用访问权,而应得到少量具有名称、结构、权限检查和可预期结果的工具。边界需要清楚到工程师可以审查,用户也能理解助手被允许做什么。
安全的工具可以很小:
const GetJobStatusInput = z.object({
jobId: z.string(),
});
它只读取用户有权查看的任务状态,不修改记录、不绕过权限,也不从私人数据推断隐藏状态。这种朴素的结构很有用。
我喜欢从只读工具开始 AI 集成。它们能帮助用户提问,同时不必过早赋予助手修改数据的能力。如果只读工具都没有用,更强大的修改工具也不会因此变得安全。
工具确实需要修改数据时,应用应明确回答:谁能调用、接收什么输入、什么状态会改变、是否需要用户确认、执行后记录什么日志,以及如何报告失败。
MCP 本身不会解决这些问题,只是提供表达边界的位置。产品仍然需要权限检查、确认状态、审计日志和准确文案。
风险在于工具名称看似安全,实现却太宽泛。updateRecord 只是含糊的遥控器。更好的工具应描述具体动作,输入狭窄,结果明确。
过于宽泛:updateRecord
更好:draftStatusChange
更好:confirmStatusChange
准备修改和真正应用修改是两回事。助手可以安全地先准备,应用前则可能需要用户审阅确认。
代价是速度。设计狭窄工具集,比直接给助手通用 API 客户端更费功夫。但产品涉及重要数据时,这份投入值得。助手应简化工作流,而不是另开一条绕过产品规则的路。
希望 AI 边界清晰、可审查时,我会使用 MCP。普通路由和 API 背后的产品规则,也应同样适用于工具。模型可以选择工具,服务器仍须决定什么被允许。