Skip to content

MCP 只是传输协议,企业数据安全边界应该在工具设计里

MCP 让 AI client 调用外部工具变得更标准。这是一个很重要的进展。

但在企业数据访问里,有一个容易被忽略的问题:

text
MCP 解决的是 tool calling 的 transport 和协议形态,不会自动解决数据治理。

一个 MCP tool 可以设计得很安全,也可以设计得非常危险。协议本身不会判断这个工具是否绕过权限、是否暴露敏感字段、是否允许任意 SQL、是否记录审计证据。

所以在业务系统、ERP、CRM、BI、财务和库存场景里,关键问题不只是:

text
我们有没有接 MCP?

更重要的问题是:

text
我们暴露给 AI 的工具边界是什么?

MCP 解决了什么

MCP 的价值很清楚:它给 AI client 和外部能力之间提供了一套通用接口。

一个 AI client 可以通过 MCP 发现工具、查看工具描述、提交参数、获取结果。对开发者来说,这比每个 IDE、每个聊天客户端、每个 agent runtime 都单独定义插件协议要清晰得多。

这让很多集成变得容易:

  • 查询文档;
  • 调用内部 API;
  • 读取文件;
  • 检索知识库;
  • 触发自动化脚本;
  • 查询数据库或业务数据。

但“能调用工具”只是第一层能力。

企业系统里真正困难的不是调用动作本身,而是调用之前和调用之后的边界:

  • 谁在调用;
  • 代表哪个用户调用;
  • 能访问哪个租户、公司或项目;
  • 能读取哪些业务对象;
  • 能看到哪些字段;
  • 工具能不能写入;
  • 结果是否需要脱敏;
  • 请求和结果是否可审计;
  • 不明确或越界时如何失败。

这些不是 MCP 自动给出的答案。

危险的 MCP 工具形态

讨论 MCP 安全时,不能只停留在“有没有 sandbox”或“有没有 API key”。更直接的问题是:工具到底暴露了什么能力。

下面几类工具在 demo 里很常见,但在生产数据场景里风险很高。

raw SQL tool

最典型的危险工具是:

text
execute_sql(sql: string)

这类工具把问题变成“模型能否写对 SQL”。但在 ERP 和业务系统里,更大的问题是 SQL 是否应该被执行。

如果一个 AI client 可以提交任意 SQL,它可能绕过:

  • 应用层权限;
  • 多租户或多公司边界;
  • 字段可见性;
  • 数据导出限制;
  • 审计和审批流程;
  • 业务对象本身的语义约束。

即使只开放 SELECT,也不等于安全。只读查询仍然可能泄露敏感数据、跨公司数据、员工数据、客户数据或财务数据。

broad API tool

另一种常见形态是暴露一个很宽的 API:

text
call_internal_api(path: string, method: string, body: object)

这看起来不像 SQL,但风险类似。模型可以组合 path、参数和 body,实际调用范围取决于内部 API 的复杂权限逻辑。

如果工具没有在服务器端绑定用户上下文、校验允许路径、限制方法和参数,那它只是把 raw SQL 风险换成了 broad API 风险。

schema dump tool

还有一种工具是把完整数据库 schema、表说明、字段说明一次性交给模型。

schema inspection 对开发调试很有用,但它不是业务授权模型。完整 schema 可能暴露内部模块、敏感字段、定制字段、历史表和不应被普通用户知道的数据结构。

更重要的是,schema 只能说明“系统里有什么”,不能说明“当前用户应该使用什么”。

file or export tool

很多业务数据泄露并不是发生在查询时,而是发生在导出后。

如果一个 MCP tool 允许把结果保存为文件、上传到外部、发送邮件或写入共享目录,那么导出边界也必须被治理。否则查询本身受控,结果流转却失控。

governed tool 应该承担什么

企业数据 MCP tool 不应该只是一个协议 wrapper。它应该是一个受治理的执行边界。

这个边界至少应该包含下面几层。

1. 身份和租户上下文

工具不能只知道“某个 AI client 在调用”。它需要知道调用代表谁。

常见上下文包括:

  • tenant;
  • workspace;
  • organization;
  • effective user;
  • service principal;
  • company scope;
  • role 或 group;
  • request source。

如果用户身份不清楚,工具应该拒绝执行,而不是让模型在 prompt 里声明“我是谁”。

权限判断必须留在服务器端 deterministic code 里,不能依赖模型自觉遵守。

2. 宿主系统权限投影

业务系统通常已经有自己的权限体系。

ERP 里有模型权限、记录规则、公司边界、字段边界。CRM 里有 owner、team、pipeline、region。数据平台里有 dataset、metric、row-level policy、column masking。

MCP tool 的职责不是重新发明一套权限,而是把宿主系统已有权限投影到 AI 查询路径里。

关键点是:权限要在执行前生效。

不能先查出完整结果,再让模型“不要展示不该看的内容”。这等于把敏感数据先交给了模型和中间链路。

3. 语义模型选择

直接暴露物理表会让模型面对太多内部结构。

更稳的方式是暴露受治理的 query model 或 semantic tool:

  • 销售订单分析;
  • 应收账款分析;
  • 库存流转分析;
  • 客户贡献分析;
  • 员工或部门统计;
  • 已批准的指标和维度。

这些模型应该定义:

  • 可用字段;
  • 指标口径;
  • 可过滤维度;
  • 支持的聚合;
  • 可排序字段;
  • 允许的查询粒度;
  • 字段和结果边界。

模型选择本身也应该受权限控制。用户没有权限的 query model,不应该出现在工具发现结果里。

4. 参数校验和能力限制

工具参数不能只是“JSON 任意对象”。

它应该有明确 schema,并对下面内容做校验:

  • 时间范围是否存在;
  • 查询粒度是否支持;
  • 指标是否可用;
  • 过滤字段是否允许;
  • limit 是否合理;
  • sort 是否支持;
  • 是否请求了敏感字段;
  • 是否尝试访问物理表或内部字段;
  • 是否试图绕过权限。

如果请求缺少业务口径,工具应该返回 clarify。如果请求越界,工具应该 reject。

生产系统里,clarifyreject 是功能,不是失败。

5. 结果裁剪、脱敏和最小化

工具不应该默认把所有明细返回给 AI。

很多业务问题只需要聚合结果、TopN、分组统计或有限明细。返回越多,泄露面越大,审计也越困难。

结果处理应该遵循最小化原则:

  • 只返回回答问题需要的字段;
  • 对敏感字段脱敏或不返回;
  • 限制行数;
  • 明确总数和截断状态;
  • 对导出走单独受控流程;
  • 对错误信息做脱敏。

这比事后在 prompt 里要求模型“不要泄露敏感信息”可靠得多。

6. audit 和 provenance

企业数据查询不能只留下一个自然语言答案。

至少应该能复查:

  • 谁发起了请求;
  • 调用了哪个 tool;
  • 使用了哪个 query model;
  • 参数是什么;
  • 应用了哪些权限边界;
  • 查询返回多少行;
  • 是否发生 clarify 或 reject;
  • 结果来自哪个业务对象或指标;
  • 是否发生导出。

这不是为了让系统显得复杂,而是为了在出问题时能够定位责任和边界。

如果一个 AI 数据工具无法解释“为什么这次查询被允许”,它就还没有达到生产级治理要求。

7. fail closed,而不是默认放行

业务数据工具遇到不确定情况时,默认策略应该是 fail closed。

例如:

  • 找不到 effective user;
  • 无法确认租户;
  • query model 不存在;
  • 字段权限不明确;
  • 指标口径冲突;
  • 请求涉及写回或外部发送;
  • 请求要求访问底层表;
  • 查询范围过大。

这些情况不应该靠模型猜,也不应该自动降级成宽权限查询。

更合理的结果是:

text
需要补充范围。

或:

text
当前请求超出可执行边界。

这种拒绝比错误地返回数据要好。

Odoo 场景为什么能说明问题

Odoo 是一个很具体的例子,因为它的权限边界不在 PostgreSQL 用户上,而在 Odoo 应用层。

一个 Odoo 用户能看什么,取决于:

  • ir.model.access
  • ir.rule
  • multi-company;
  • field visibility;
  • 模块业务规则;
  • 实施商自定义逻辑。

如果 MCP tool 只是包了一层数据库查询,那么 AI client 可能绕过 Odoo 里真正的权限配置。

更稳的做法是:

  • MCP client 通过 Odoo 侧访问机制进入;
  • 工具绑定 effective Odoo user;
  • 可见 query model 由 Odoo 权限决定;
  • record rules 在查询执行前参与;
  • 多公司边界进入查询条件;
  • 字段边界在返回前处理;
  • 查询过程保留 evidence。

这样 MCP 不是数据库旁路,而是 Odoo 权限体系之后的受控查询入口。

一个 MCP 数据工具设计 checklist

如果你正在给业务系统接 MCP,可以用下面的问题做一轮自检。

身份:

  • 工具是否知道 effective user?
  • 是否能区分 tenant、company、workspace?
  • service principal 是否有最小权限?

权限:

  • 是否复用宿主系统权限?
  • 权限是否在查询执行前应用?
  • 用户不可见的模型和字段是否不会暴露给工具发现?

语义:

  • AI 面对的是业务 query model,还是物理表?
  • 指标、维度、过滤和粒度是否显式定义?
  • schema 是否只暴露必要部分?

执行:

  • 是否禁止任意 SQL?
  • 是否限制查询能力和行数?
  • 是否支持 clarify / reject?
  • 是否对错误信息脱敏?

结果:

  • 是否只返回必要字段?
  • 是否处理敏感字段?
  • 导出是否有单独治理?

审计:

  • 是否记录 tool call、query model、参数和结果范围?
  • 是否能解释权限边界?
  • 是否能追踪 clarify、reject 和导出?

如果这些问题没有答案,MCP 接入只是完成了协议集成,还没有完成生产治理。

小结

MCP 很有价值,但它不是企业数据安全的终点。

协议负责让 AI client 能够调用工具;工具设计负责决定 AI 能做什么、不能做什么、代表谁做、在什么边界内做、结果如何复查。

对企业业务数据来说,更可靠的默认路线不是:

text
给 AI 一个万能数据库工具。

而是:

text
给 AI 一组受治理的语义工具,并把身份、权限、语义、执行和审计放在服务器端边界里。

Foggy Data MCP / Foggy Odoo Bridge 目前采用的也是这个方向:MCP 作为接入方式,语义查询模型作为业务接口,宿主系统权限在执行前参与,查询过程保留证据。Odoo 只是第一个具体样板,核心原则适用于更多企业业务系统。

继续阅读