Skip to content

ADR-0002:MCP 安全网关作为 Agent 访问外部资源的唯一出口 ​

  • 状态:已采纳
  • 日期:2026-09-15
  • 决策者:毕设作者
  • 相关文档:docs/04-MCP安全网关设计.md、docs/adr/0001-dual-database-isolation.md、docs/adr/0004-security-plugin-layer-in-process.md

背景 ​

ADR-0001 已经让 Agent 拿不到业务库凭证。但"拿不到数据库"不等于"访问受控":Agent 还需要读取遥测数据、检索故障知识库、查询工单状态。这些能力必须有人提供。

有三种给法:

  1. 直接给 Agent 数据库账号或 MQTT 凭证(已被 ADR-0001 否决);
  2. 在 Agent 进程内写一段"取数逻辑"(连接串进 Agent 环境变量);
  3. 让 Agent 通过一个受控的外部服务间接取数。

决策 ​

Agent 所有对外部资源的访问,100% 经过 MCP 安全网关。

网关是一个独立部署的 TypeScript 进程,职责:

  • 统一入口:同时接收 Agent 调用与 Web 前端人类用户调用,是系统唯一的对外数据出口。
  • 身份解析:解析 JWT / 设备令牌,得到调用方身份(工程师 ID 或 Agent ID + 会话 ID)。
  • 策略校验:按"调用方 × 工具 × 参数 × 上下文"判定放行、降级还是拒绝。
  • 数据裁剪:向下取到原始数据后,按字段白名单裁剪,只回传最小数据集。
  • 审计落库:每一次调用(含被拒绝的调用)写入 business-db.audit_log,写入失败即调用失败。
  • 向下转发:ai-db 只读检索、MQTT 只读取数、business-db 受限查询。

网关对外的接口形态是 MCP 工具,工具清单是封闭的、可枚举的:

工具用途读/写主要返回字段
mqtt.read_sensor读取指定设备的遥测窗口只读temp、vibration、time
kb.search检索故障知识库只读chunk、source、score
db.query_device查询设备基础档案只读型号、位置、投运日期
db.query_workorder查询工单只读工单号、状态、处理记录
report.write落库 Agent 分析报告写(受限)报告 ID

没有任何工具可以执行任意 SQL,也没有任何工具可以发布 MQTT 消息。

理由 ​

  1. 把"能不能"变成"契约允不允许"。数据库只读账号回答不了"Agent 该不该看这张表";工具契约可以。工具是安全策略的最小可审计单元。
  2. 字段裁剪是核心价值,不只是转发。原始遥测行可能含内部序列号、校准系数、产线编码;Agent 做故障分析只需要 temp / vibration / time。网关在返回前裁剪,等于把"最小权限"落实到字段级。
  3. 人类用户与 Agent 共用入口,审计口径统一。前端查设备数据和 Agent 查设备数据走同一条链路、同一张审计表,答辩时可以用一条 SQL 同时展示两类调用。
  4. MCP 是标准协议,网关的工具可以被任意 MCP 客户端复用,不绑死在 OpenClaw 上,降低框架锁定风险。

备选方案与拒绝理由 ​

方案为什么没选
Agent 进程内直接连库取数连接串必然进入 Agent 环境变量或配置文件,一旦提示注入成功即可被读出;且 Agent 可执行任意 SQL。
用普通 REST 接口代替 MCP可行但失去标准工具发现能力,且与 OpenClaw 的工具生态脱节。MCP 是当前 Agent 工具调用的主流标准。
网关只做转发不做裁剪那样 Agent 仍能看到全部字段,最小权限落空,等于把数据库只读账号换个包装。
每个数据源各起一个网关入口一多,"唯一出口"不变量失效,审计需要跨多个服务拼接,答辩论证成本上升。

后果 ​

正面

  • 系统对外数据出口收敛为 1 个进程 + 5 个工具,安全论证可以逐条列举。
  • Agent 的能力边界可枚举:Agent 能做什么,等于工具清单能做什么。
  • 审计日志成为系统唯一的"数据访问事实来源"。

负面 / 代价

  • 网关成为性能瓶颈与单点,必须 PM2 守护并设计降级策略。
  • 新增数据需求需要走"定义工具 → 实现 → 加策略 → 加审计"的完整流程,迭代速度慢于直接写 SQL。
  • 网关代码本身成为高价值攻击目标,需要最严格的代码评审与测试覆盖。

验证方式 ​

原型验证阶段需要给出反证:在 Agent 进程内尝试直连 business-db 与订阅 MQTT 主题,均因缺少凭证而失败;同时展示审计表中被拒绝调用的记录。见 docs/09-原型验证方案.md。