从 OAuth、Tool Annotations 到业务审批与最终授权,把“工具已连接”和“业务可放心执行”之间缺失的工程链路讲清楚。
假设你已经为一套业务系统接好了 MCP Server。
Agent 可以发现并调用这些工具:
order.query 查询订单
refund.create 创建退款
inventory.adjust 调整库存
customer.export 导出客户资料
工具名称、说明和参数 Schema 都很清晰;客户端能完成授权,也能正确发起 tools/call。第一次演示相当顺利:用户说“查一下订单”,Agent 选择了 order.query,业务结果很快返回。
接下来,产品经理把需求推进了一步:
既然查询已经能做,那就让它直接处理退款吧。
这时,工程团队会发现一组新的问题:
- 当前聊天场景是否应该让 Agent 看见退款工具?
- Agent 此刻代表哪个门店、员工或客户行动?
- 退款 100 元和退款 10000 元是否应采用同一种处理方式?
- 需要人工确认时,究竟批准的是哪一组参数?
- 审批之后 Agent 重新推理并改变了金额怎么办?
- 调用失败、被拒绝或最终成功后,审计系统应留下什么证据?
- 即使前面的控制都通过,订单现在是否仍允许退款,最终由谁判断?
这些问题并不意味着 MCP 做得不够好。恰恰相反,它们通常只会在 MCP 已经把工具连接问题解决得足够好之后,才集中暴露出来。
本文想讨论的不是“MCP 和某个新标准谁取代谁”,而是一个更实际的问题:
当工具已经可以被发现和调用,企业还需要补上哪些治理层次,才能把只读演示推进到真实业务操作?
1. 先把 MCP 已经解决的事情说准确
讨论企业治理之前,必须先承认 MCP 已经建立的价值。
按照当前 MCP Tools 规范,一个工具可以提供名称、说明、输入 Schema、输出 Schema 和执行能力信息,客户端可以标准化地列出工具并发起调用。相比每个 Agent 平台、模型 SDK 和业务工具之间分别做一套私有适配,这大幅降低了工具互操作成本。
MCP 也不是“完全没有安全和授权”。
它的 Authorization 规范基于 OAuth 2.1 等标准定义了 HTTP 传输下的授权流程:受保护的 MCP Server 作为资源服务器,客户端代表资源所有者取得访问令牌,令牌需要绑定目标资源,服务器必须验证令牌是否确实签发给自己。MCP 的安全最佳实践还明确禁止直接透传上游令牌,因为这会绕过安全控制并破坏责任识别与审计链路。
在工具行为描述上,MCP 已经提供四个重要注解:
readOnlyHint:工具是否只读;destructiveHint:工具是否可能产生破坏性更新;idempotentHint:相同参数重复调用是否不会产生额外影响;openWorldHint:工具是否可能与开放世界中的外部实体交互。
因此,把 MCP 描述成“只有调用通道、没有任何授权或风险信息”,是不准确的。
更准确的说法是:
MCP 已经解决了工具发现、调用互操作、传输授权和基础行为提示;企业业务治理还需要回答更靠近具体业务行动的问题。
这不是否定 MCP,而是在它已经完成的地基上继续往生产环境走。
2. “授权”这个词,实际上混合了三个不同问题
很多讨论之所以绕不清,是因为大家都在说“权限”或“授权”,指的却不是同一件事。
2.1 客户端能否访问 MCP Server
这是协议接入层的问题:
- 客户端是谁?
- 是否完成 OAuth 授权?
- Token 是否有效?
- Token 是否签发给当前 MCP Server?
- 当前请求是否具有访问这个资源服务器所需的 scope?
MCP Authorization 正在解决这一层。
2.2 某项业务能力是否应进入当前 Agent 的可达范围
这是能力治理层的问题:
- 客服场景是否需要看见
refund.create? - 访客聊天组件是否只能看见公开查询工具?
- 当前路由是否只允许
order.read,而不允许order.delete? - 该操作是低、中还是高后果?
- 是否必须绑定可信业务主体?
- 哪些参数条件会产生人工审批意图?
这回答的是 Agent 的 Reach:在一个明确场景里,它最多能触达什么。
2.3 当前业务主体此刻能否操作这个具体对象
这是最终业务授权层的问题:
- 员工是否属于这个订单所在门店?
- 他是否拥有退款权限?
- 订单当前状态是否允许退款?
- 可退款金额是否足够?
- 是否已经存在一笔退款?
- 当前租户的数据边界是否匹配?
这回答的是 Authority:这个主体在这个时间点,究竟能不能完成这次具体操作。
只有业务系统掌握实时权限、对象状态、租户边界和业务不变量,因此最终 Authority 不能交给模型,也不能仅由 MCP Client、控制面或静态契约代替。
三个层次可以同时存在:
MCP / OAuth
解决“客户端能否访问这个 MCP Server”
↓
能力治理声明与运行时策略
解决“当前场景允许 Agent 触达哪些业务能力”
↓
业务系统最终授权
解决“当前主体此刻能否操作这个具体业务对象”
如果把它们都压缩成一句“有 Token 就有权限”,生产风险就从这里开始了。
3. 为什么拿到了 OAuth Token,仍不等于可以退款
继续看一笔退款。
MCP Client 已经取得了访问退款 MCP Server 的 Token。这个 Token 至少可以证明:客户端完成了规定的协议授权,当前请求可以被这个资源服务器受理。
但业务 API 仍然需要验证:
调用者是否有权代表 employee_1024?
employee_1024 是否属于 store_18?
order_9001 是否属于 store_18?
order_9001 当前是否可退款?
退款 5000 元是否超过剩余可退款金额?
这些判断依赖实时业务数据。即便 OAuth scope 写得非常细,也很难把每个订单的当前状态、每个门店的动态权限和每笔退款的业务不变量全部预编码进令牌。
所以,一个正确的 MCP 接入通常需要两套凭证关系:
- 客户端访问 MCP Server 的协议凭证;
- MCP Server 或下游执行方访问业务系统的独立凭证和可信主体上下文。
MCP 安全规范明确反对 Token Passthrough,原因之一正是直接转交令牌会混淆信任边界、绕过下游安全控制并削弱审计责任。
因此,OAuth 非常重要,但它解决的是一段明确的授权关系,不自动替代所有下游业务授权。
4. Tool Annotations 很有价值,但“行为提示”不等于完整治理契约
MCP Tool Annotations 是一项重要进展。
如果工具声明 readOnlyHint: true,可信客户端可以对它采用比写操作更宽松的交互策略;如果 destructiveHint: true,客户端可以提高警惕;如果 idempotentHint: true,运行时能够更合理地考虑重试。
这些注解让不同客户端拥有一组共同的工具风险词汇。
但规范同时写得很克制:这些属性都是 hints,并不保证忠实描述工具行为;客户端不能依据来自不可信服务器的注解直接作出工具使用决策。换句话说,它们首先描述“这个工具看起来具有什么行为特征”,信任和执行策略仍由客户端或运行时决定。
企业业务治理还经常需要声明另外几类事实:
- 这项能力是否显式允许暴露给 Agent;
- 它在组织内部使用哪个稳定治理标识;
- 最坏合理后果属于什么等级;
- 调用前是否必须存在一个可信业务主体;
- 是否存在参数级的条件审批意图;
- 参数或结果是否可能包含敏感数据;
- 是否存在超时、限流等通用执行约束。
其中有些内容与 MCP 注解存在合理重叠,例如只读和幂等。重叠并不意味着一定要重复维护两份互相冲突的配置,而是需要清晰的绑定和来源优先级:哪个是协议层行为提示,哪个是组织采信的治理声明,编译时如何映射,冲突时如何诊断。
真正需要避免的是两个极端:
- 因为 MCP 已经有注解,就假设所有业务治理都已经完成;
- 为了证明另一层的价值,故意忽略 MCP 已经提供的授权和风险词汇。
工程上更稳妥的结论是:
MCP Tool Annotations 与企业治理声明可以互补,但前者不是后者天然可信、完整且可移植的替代品。
5. 一笔退款,在完整链路里应该经过什么
现在把前面的分层放回一次具体调用。
用户说:
给订单
ORD-20260715-001退款 5000 元。
5.1 工具发现与参数生成
MCP Client 从可信 MCP Server 获得工具列表,模型选择 refund.create,并生成参数:
{
"order_id": "ORD-20260715-001",
"amount": 5000,
"reason": "duplicate payment"
}
MCP 负责标准化工具描述、调用请求与返回结构。
5.2 参数不能因为来自模型就被信任
工具参数必须按 Schema 校验类型、必填项、长度和范围,还要执行路径、查询和业务相关的输入约束。
微软的 Agent Safety 指南也明确建议把 LLM 生成的函数参数视为不可信输入,像处理 Web API 的用户输入一样执行白名单、类型、范围和长度校验。
正确选择了工具,不代表生成的每个参数都安全。
5.3 读取可信治理声明
假设这项 OpenAPI operation 使用 ACC v1 声明:
x-agent-capability:
version: 1
enabled: true
scope: refund.create
risk:
level: high
subject:
required: true
approval:
prompt: "Approve refund for order {order_id}?"
when:
- param: amount
op: ">"
value: 1000
label: Refund amount exceeds 1000.
audit:
sensitive: true
execution:
readonly: false
idempotent: true
timeout_ms: 10000
rate_limit:
count: 10
window: 1m
这份声明没有直接执行退款,也没有决定谁来审批。它只是提供机器可读的治理事实:
- 该能力显式允许进入 Agent 可调用范围;
- 它的治理标识是
refund.create; - 它是高后果操作;
- 必须存在可信主体;
- 金额大于 1000 时产生审批意图;
- 参数或结果可能包含敏感数据;
- 执行具有幂等、超时和限流提示。
ACC v1 当前的标准绑定是 OpenAPI operation extension。它并不声称自己就是 MCP 的一部分;一个运行时可以把 OpenAPI + ACC 编译成自己的工具模型,再通过 MCP、Function Calling 或其他传输方式暴露。若要建立 ACC 到 MCP 的规范化映射,仍需要单独定义绑定和一致性规则。
5.4 运行时执行治理,而不是让声明自己“生效”
声明不会自动形成安全边界。运行时或控制面需要真正执行:
- 按当前路由的 allowlist 判断
refund.create是否可见; - 确认可信主体来自签名票据、会话或可信身份系统,而不是模型文本;
- 校验风险和审批条件;
- 金额命中条件时创建审批意图并暂停调用;
- 将审批绑定到精确参数快照或哈希;
- 审批通过后检查即将执行的参数是否发生漂移;
- 应用限流、超时、审计和 Trace;
- 最后才把请求发往业务系统。
这也是为什么“声明标准”和“控制面产品”不是一回事:前者定义跨实现语义,后者负责在真实系统里兑现语义。
5.5 业务系统完成最终授权
即使控制面已经放行,业务系统仍必须检查:
- 当前员工是否拥有退款权限;
- 订单与门店、租户是否匹配;
- 订单状态是否允许退款;
- 剩余可退款金额是否足够;
- 幂等键是否已经处理过;
- 资金系统是否接受这笔请求。
任何一项不满足,业务系统都应该拒绝。
这就是 Reach 与 Authority 的边界:
控制面可以缩小 Agent 的可达范围并组织治理流程,但不能替业务系统签发最终业务许可。
6. 企业工具治理至少要回答七个问题
从退款场景抽象出来,一套面向真实业务的 Agent 工具治理至少要回答:
| 问题 | 主要责任层 |
|---|---|
| 客户端如何发现和调用工具? | MCP / Function Calling 等调用协议 |
| 客户端如何访问受保护的工具服务器? | MCP Authorization / OAuth 等协议授权 |
| 当前场景允许 Agent 触达哪些业务能力? | 能力治理声明 + Runtime Policy |
| Agent 正代表谁行动? | 可信主体解析 + 业务身份系统 |
| 哪些调用需要人类介入? | 治理声明表达意图,运行时拥有流程 |
| 调用前后留下什么责任证据? | 审计与 Trace 系统 |
| 当前主体此刻能否操作这个对象? | 业务系统最终授权 |
企业真正需要的不是“再加一个权限开关”,而是让这些答案在同一条执行链上能够被验证。
如果它们分别散落在提示词、Agent 平台配置、MCP Server 代码、API Gateway 插件和业务后端里,却没有稳定语义和责任边界,系统仍然可以运行,但迁移、审计和事故定位会越来越困难。
7. 为什么不把所有治理都塞进 MCP
一种直觉是:既然 MCP 已经定义工具,为什么不继续增加风险、审批、审计、主体和企业策略字段,最终把所有问题一次解决?
技术上当然可以扩展,MCP 也提供 _meta 等扩展空间。但“可以加字段”和“应该进入通用核心”不是同一件事。
企业治理中有大量内容依赖部署方:
- 谁来审批取决于组织结构;
- 何时可操作取决于企业策略;
- 租户隔离必须由业务数据层强制;
- 订单能否退款依赖实时业务状态;
- 跨操作事务依赖 Workflow、Saga 或业务事务协调;
- 审计保留期取决于企业和行业合规要求。
如果把这些全部写进工具协议,MCP 会逐渐变成通用业务策略语言、身份系统和工作流引擎。不同运行时无法一致兑现时,字段越多,互操作的错觉越强。
更合理的做法不是禁止扩展,而是明确分层:
- MCP 保持工具互操作和协议安全;
- 独立治理契约只保留可跨实现声明的最小事实;
- Runtime Policy 承担组织策略和执行决策;
- Workflow / Approval System 拥有具体流程;
- 业务系统保留最终授权。
这也解释了为什么一个治理契约应当保持“薄”:薄不是少做安全,而是不把无法跨系统兑现的私有规则伪装成公共标准。
8. 为什么也不能把所有治理都塞进 ACC
ACC 同样必须克制。
它不应该定义:
- 企业使用 JWT、LDAP、企业微信还是其他身份格式;
- 经理、总监或财务负责人谁来审批;
- 某组织的节假日和工作时间策略;
- 租户 ID 应如何拼进数据库查询;
- 多个 API 如何组成原子事务;
- 退款金额是否超过订单可退款余额;
- 审计记录必须保留几年。
这些问题都重要,但重要不等于属于契约核心。
ACC 的角色是声明跨运行时可理解的治理元数据,并明确安全不变量;它不是最终授权系统,不是通用策略引擎,也不是审批工作流产品。
如果未来某个字段只有 BailingHub 能正确解释,或者它默认了某一种私有身份模型、数据库结构和 UI,那么这个字段就不应该因为对某个产品方便而进入 ACC 核心。
标准中立的代价是克制,收益是不同实现可以在同一语义上竞争。
9. API Gateway、OPA / Cedar、控制面和业务系统分别做什么
企业并不一定需要为了每一层都部署一个独立产品。层次是责任划分,产品形态可以组合。
例如:
| 组件或体系 | 更适合承担的责任 |
|---|---|
| OpenAPI / JSON Schema | 描述业务接口、参数和返回结构 |
| MCP | 工具发现、调用互操作、传输授权、基础行为提示 |
| ACC | 声明可移植的 Agent 能力治理事实 |
| API Gateway | 认证、路由、限流、网络边界与策略执行 |
| OPA / Cedar 等策略引擎 | 结合组织上下文计算动态策略决策 |
| Agent Runtime / 控制面 | 工具装配、审批暂停恢复、参数绑定、审计与 Trace |
| 业务系统 | 实时业务校验、租户隔离和最终授权 |
同一个企业可以把运行时策略嵌入 API Gateway,也可以使用独立控制面;Agent 平台也可以原生实现这些治理能力。
真正需要保持稳定的不是某一种产品部署图,而是这些责任不能被悄悄交给模型:
- 模型可以建议调用什么;
- 模型不能修改自己面对的风险等级;
- 模型可以生成参数;
- 模型不能自证参数已经获批;
- 模型可以解释业务结果;
- 模型不能替业务系统决定最终权限。
10. 你的场景是否真的需要独立治理层
不是每个 MCP 项目都需要一套完整控制面。
MCP 本身可能已经足够的场景
- 个人本地使用;
- 工具来自完全可信的服务器;
- 只有少量只读或低后果操作;
- 没有复杂业务身份;
- 不要求跨平台复用治理配置;
- 出错后影响范围很小。
这时,MCP 的工具 Schema、OAuth、Tool Annotations,加上客户端自身的确认机制和业务 API 校验,可能已经足够。
应认真建设显式治理层的场景
- Agent 将修改订单、资金、库存、员工或客户数据;
- 同一企业使用多个 Agent 平台、模型或工具协议;
- 同一套业务能力需要在不同路由和场景中采用不同可见范围;
- 必须绑定真实业务主体;
- 需要参数级审批、不可抵赖审计或完整 Trace;
- 需要私有部署、内网执行或跨系统交付;
- 希望更换 Agent 平台时不重写全部治理语义。
此时,治理层的价值不是为了增加一道昂贵中间件,而是把原本散落、隐含、不可验证的控制变成显式、可移植、可审计的工程对象。
11. ACC 在这里提出的是什么
Agent Capability Contract(ACC) 是对这层声明问题的一种开放、实现中立的回答。
它基于 OpenAPI operation extension 声明:
- 能力是否启用;
- 稳定的治理
scope; - 风险等级;
- 是否要求可信主体;
- 审批意图与参数级条件;
- 审计敏感性;
- 只读、幂等、超时和限流等执行提示;
- 面向模型的使用引导。
ACC 只管理 Reach,不替代业务系统的 Authority。它不要求企业采用某个模型、Agent 平台、MCP Client、审批系统或控制面产品。
BailingHub(百灵中枢) 是一个基于 ACC 的开源实现,用来验证路由、可信主体、工具治理、审批、审计、Trace 和执行器如何组成可运行链路。它不是 ACC 的专属拥有者,也不享有特殊规范地位;其他团队可以独立实现 ACC,或者在自己的网关和 Agent Runtime 中实现同样的声明语义。
这条边界很重要:
标准负责建立公共语义,实现负责证明语义能够落地;任何单一实现都不应反过来控制公共标准。
12. 结语:连通是开始,治理让企业敢于放行
MCP 解决的是一个极其重要的问题:让 Agent 与工具之间建立标准化连接。
当连接完成后,企业会继续追问:
- 哪些能力可以进入当前场景?
- Agent 代表谁行动?
- 哪些后果需要人工介入?
- 审批是否绑定了精确参数?
- 谁执行了什么,结果如何追踪?
- 最终业务许可由谁签发?
这些问题不会因为换一个更强的模型而消失,也不能只靠一段更严格的提示词解决。
因此,MCP 与企业工具治理不是二选一:
MCP 让工具可连接、可发现、可调用;治理声明、运行时策略和业务授权共同让这些工具在真实企业里可被放心使用。
对于低风险个人工具,连接本身可能已经足够。对于资金、库存、员工、客户和生产数据,治理不是拖慢 Agent 的刹车,而是企业敢于向 Agent 开放写操作的前提。
这才是“工具已经连通以后,治理问题为什么刚刚开始”的真正含义。
参考资料与进一步阅读
- MCP Tools 规范:https://modelcontextprotocol.io/specification/2025-11-25/server/tools
- MCP Authorization:https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization
- MCP Security Best Practices:https://modelcontextprotocol.io/docs/tutorials/security/security_best_practices
- Microsoft Agent Safety:https://learn.microsoft.com/en-us/agent-framework/agents/safety
- ACC 官网:https://www.agentcapability.org/
- ACC 开放规范仓库:https://github.com/agent-capability/agent-capability-contract
- BailingHub 开源仓库:https://github.com/bailinghub/bailinghub
- 退款审批与 Trace 演示:https://github.com/bailinghub/bailinghub/discussions/7