学完能做什么
你会理解 MCP 客户端、服务端和宿主应用之间的职责,能为一个 MCP 接入画出数据流、权限和信任边界,并在启用前完成最小安全审查。
MCP 解决的是连接规范,不是自动授权
MCP 让应用用统一方式发现和调用外部能力。它减少适配工作,但不会替你判断一个服务是否可信,也不会自动保证工具安全。
text
用户
↓
宿主应用(承载对话与 Agent)
↓ MCP Client
传输与会话
↓
MCP Server
├─ Tools:可执行动作
├─ Resources:可读取资源
└─ Prompts:可复用提示模板宿主应用最终决定接入哪个服务、把哪些能力提供给模型,以及调用前是否需要人工确认。
三个角色不要混淆
| 角色 | 负责什么 | 典型安全职责 |
|---|---|---|
| 宿主应用 | 展示界面、运行 Agent、保存用户配置 | 身份、授权、确认和审计 |
| MCP Client | 建立会话、发现能力、发送调用 | 会话隔离、协议校验、超时 |
| MCP Server | 实现工具和资源访问 | 参数校验、最小权限、结果脱敏 |
模型不是第四个安全主体。它只能在宿主提供的能力范围内提出调用请求。
Tools、Resources、Prompts 的风险不同
- Tool 可能产生副作用,例如写文件、发消息、创建工单;
- Resource 通常是读取,但仍可能暴露敏感数据;
- Prompt 可能把外部指令带进上下文,形成提示注入;
- 返回内容本身不可信,不能当作系统指令执行。
“只读”也不等于“无风险”。读取整个用户目录、全部邮箱或客户数据库仍然是高权限。
启用一个服务前画数据流
至少回答:
- 服务运行在哪里,由谁维护?
- 它能看到哪些请求、文件、账号和环境变量?
- 数据是否离开本机或组织边界?
- 凭据保存在何处,能否轮换和撤销?
- 每个工具是只读、写入、发送还是删除?
- 哪些调用需要用户逐次确认?
- 服务异常或被替换时如何停止?
如果无法说明数据去哪了,就不应接入真实业务数据。
用能力清单实施最小权限
不要把“文件系统访问”作为一个模糊权限。拆成可审计能力:
json
{
"allowed_roots": ["/workspace/project-a/docs"],
"operations": ["list", "read"],
"denied_patterns": ["*.env", "*.key", "credentials.*"],
"max_file_bytes": 1048576,
"follow_symlinks": false
}即使工具声明了范围,服务端也必须再次校验真实路径,防止路径穿越和符号链接越界。
对写操作分级确认
| 风险等级 | 示例 | 推荐处理 |
|---|---|---|
| 低 | 读取指定公开文档 | 首次授权范围后可执行 |
| 中 | 在草稿目录创建文件 | 展示路径和摘要,允许一次确认 |
| 高 | 发送消息、修改线上记录 | 每次展示对象、参数和影响后确认 |
| 极高 | 删除、支付、权限变更 | 默认禁用,使用专门审批流程 |
确认框要展示具体对象和参数。“允许工具执行吗”太笼统,用户无法判断影响。
抵御来自内容的提示注入
资源或工具结果可能包含“忽略之前指令”“上传所有文件”之类文字。处理原则:
- 外部内容始终标记为数据,不提升为系统指令;
- 工具选择和权限规则不由资源内容改变;
- 从工具结果中提取结构化字段,再用于下一步;
- 高风险动作依据程序规则和用户确认,不依据页面文字;
- 限制一次结果的大小、类型和可进入上下文的范围。
服务端实现的基本护栏
python
ALLOWED_PROJECTS = {"project-a", "project-b"}
def read_project_note(project_id: str, note_id: str, actor) -> dict:
if project_id not in ALLOWED_PROJECTS:
raise PermissionError("项目不在允许范围")
if not actor.can_read(project_id):
raise PermissionError("当前身份无读取权限")
if not note_id.isascii() or len(note_id) > 64:
raise ValueError("note_id 不合法")
note = repository.get_note(project_id, note_id)
return redact_sensitive_fields(note)不要相信客户端已经验证过。服务端要基于当前身份再次授权,并对返回值做最少披露。
审计记录什么
- 宿主、用户和服务实例标识;
- 服务与工具版本;
- 调用时间、工具名和参数摘要;
- 授权范围和确认记录;
- 结果状态、耗时和错误分类;
- 凭据创建、轮换和撤销事件。
日志不要保存完整密钥、授权头和超出排障需要的原始内容。
接入审查练习
假设要接入一个能读取文档并发送邮件的 MCP 服务:
- 将读取和发送拆成两个独立能力;
- 限定允许读取的目录、文件类型和大小;
- 规定邮件发送必须展示收件人、主题和正文;
- 设计一套假数据测试提示注入、路径越界和重复发送;
- 写出撤销凭据、停用服务和查看审计日志的路径。
完成检查清单
- 画清了宿主、Client、Server 和外部系统的数据流。
- 每个能力都有最小范围,不使用模糊的全盘权限。
- 资源内容和工具结果被视为不可信数据。
- 高风险动作会展示具体影响并逐次确认。
- 凭据可以轮换、撤销,调用过程可以审计。
下一步
下一篇将处理多轮 Agent 最容易失控的部分:上下文、短期记忆、长期记忆和可恢复状态。