一个安全的 MCP 工具服务模板:查询、审批与审计
# 一个安全的 MCP 工具服务模板:查询、审批与审计
本文提供的是可复现工程模板,用于组织 MCP 工具服务的能力边界;不是已上线的业务系统说明。
安全的 MCP 服务并不等于“工具越少越好”,而是要让每项能力的范围、授权和后果都可以解释。下面是一组适合从零起步的能力组合。
| 工具 | 用途 | 是否改变外部状态 |
|---|---|---|
search_knowledge | 在已授权资料中检索片段 | 否 |
get_task_status | 查询任务处理状态 | 否 |
create_review_request | 创建待人工审核的请求草稿 | 仅创建内部审批记录 |
注意最后一个工具没有直接“发送通知”或“修改正式数据”。它的结果应该是一个待确认对象,而不是一次不可逆的自动执行。
# 一次调用应当经过什么
可以把服务端处理分成六步:
发现工具 → 校验输入 → 鉴权 → 执行业务逻辑 → 返回结构化结果 → 记录审计事件
每一步都不能省略。
- 发现工具:客户端取得当前允许使用的能力列表,向用户说明来源和用途。
- 校验输入:检查字段是否缺失、格式是否正确、范围是否合理。
- 鉴权:根据当前身份和资源范围判断是否允许访问,不能依赖模型自行判断。
- 执行业务逻辑:只调用已经封装好的业务服务,不把底层数据库或系统命令直接暴露出来。
- 返回结构化结果:让模型能准确理解结果,也让客户端能据此展示下一步。
- 记录审计事件:保留调用工具、目标资源、结果状态和关联审批信息,敏感字段应脱敏。
# 结果要有稳定的失败语义
不要把所有失败都返回成一段自然语言。服务端可以用稳定状态让客户端和模型采取不同处理方式:
{
"ok": false,
"code": "NEEDS_APPROVAL",
"message": "该操作需要负责人确认后才能继续",
"review_id": "review_example_001"
}
常见的失败码可以包括:
INPUT_INVALID:参数格式或业务规则不满足。FORBIDDEN:当前身份没有访问目标资源的权限。NOT_FOUND:目标不存在,或在可见范围内不可用。UPSTREAM_UNAVAILABLE:下游服务暂不可用,可以稍后重试。NEEDS_APPROVAL:操作有效,但需要人工确认。
示例中的 review_id 只是演示字段,不代表真实业务记录或线上接口。
# 高风险能力的默认边界
以下能力不宜直接作为宽泛工具暴露给模型:
- 任意系统命令执行。
- 不受目录约束的文件读写。
- 全量数据库查询或更新。
- 凭据、令牌、隐私内容的读取与回显。
- 不经确认的消息发送、转账、删除或权限变更。
如果业务确实需要其中某项能力,应将它收窄为一个具体动作,例如“导出当前项目已授权的汇总数据”,并在服务端做资源范围、频率和审批控制。
# 超时、重试与幂等
模型可能因为网络波动或上下文变化重复发起请求,因此写操作需要幂等标识或明确的重复处理策略。下游调用要设置短超时;只对可判定为暂时性故障的情况重试。不要因为一次执行超时,就让模型自动反复提交高影响操作。
查询结果也要限制返回量。过大的文本既浪费上下文,又可能把无关或敏感信息带入对话。优先返回摘要、分页标识或可按需读取的资源链接。
# 上线前检查清单
- 每个 Tool 是否只有一项清晰业务意图?
- 输入、输出和错误码是否可测试、可解释?
- 每个资源访问是否在服务端完成身份与权限校验?
- 写操作是否存在预览、确认或审批路径?
- 日志是否避免记录密钥、隐私正文和完整调用上下文?
- 超时、限流、重试和幂等策略是否已明确?
把这份清单跑通后,再增加新工具,能避免 MCP 服务在“看起来能用”后迅速变成难以治理的系统。
# 延伸阅读
最后更新: 9/24/2026, 4:22:53 AM
- 01
- AI 应用前端:把生成结果做成可理解、可确认的交互09-24
- 02
- Docker 实战:让服务从本地可运行走向可交付09-24
- 03
- Linux 服务部署与排障:一份从症状到证据的清单09-24