跳转到内容

MCP 与工具生态:连接能力,不等于授予权限

一个 AI 应用接进 GitHub、文件系统、数据库和浏览器后,模型可能在工具列表里看见 refund_order。看见、生成参数和真正获准退款,是三件不同的事。

没有统一接口的时候,每个连接都要自己处理 SDK、鉴权、错误格式和升级。Model Context Protocol(MCP)解决的就是应用与外部上下文、工具之间的通用连接问题,让 Host 能以相对一致的方式发现 Server 提供的能力。理解 MCP 不能只记接口,还要知道 Host、政策和后端各自该挡住什么:工具是否可发现、调用方是否有身份、这笔业务是否允许执行。

这一篇的底线: MCP 让能力可连接;授权、审批、幂等和审计仍然是应用与业务系统的责任。

最后会跑一个很小的实验:Client 能看到读和写两个工具,但没有批准时,写操作只能停在 approval_required

MCP 是一种开放协议,用于让 AI 应用连接外部系统。官方架构包含 Host、Client 和 Server:[1]

  • Host:面向用户的 AI 应用,负责整体体验、政策和模型编排;
  • Client:Host 内与某个 Server 建立会话的协议组件;
  • Server:暴露 Tools、Resources、Prompts 等能力的程序。

可以把它类比成 USB-C:接口形状统一之后,设备更容易接入,但接口本身不会决定你是否应该把硬盘里的文件发出去。

MCP 不是一个能自主规划任务的 Agent,不是多个 Agent 相互协作的组织协议,不是自动安全的插件商店,也不能替代业务授权系统,更不对工具质量和返回内容的真实性做背书。它标准化的是“怎样描述、发现和交换能力”,产品决策仍留在 Host。把这个边界说清楚,“装个 MCP Server 就自动安全”的误解就不会发生。

初学者最容易把 Client 理解成用户界面,把 Server 理解成远程网站。MCP 的 Client 实际位于 Host 内部,通常一个 Client 对应一个 Server 连接。

User
|
MCP Host(AI 应用、模型、审批与上下文政策)
|-- MCP Client A <--> Files Server
|-- MCP Client B <--> GitHub Server
`-- MCP Client C <--> Database Server

这样分层的好处是:Host 可以隔离不同 Server 的会话与权限,不必把所有能力混成一个连接;Server 不需要知道完整对话和其他 Server 的状态,只处理自己声明的协议能力;用户同意、模型上下文选择、跨 Server 组合这些高层责任可以留在 Host。

图 1 是规范入口。读图时先确认 Host 才是承接用户体验、审批和上下文政策的一层,Server 不应该默认拿到完整对话和所有权限。

MCP 官方规范页面

图 1:MCP 官方规范是理解版本、架构和能力语义的一手来源。截图对应 2025-11-25 稳定规范,来源见文末。

MCP 规范刻意区分三类 Server 能力,并给出不同的控制语义。

Tool 通常有名称、描述、输入 Schema 和输出。模型可以根据任务选择调用,例如查询库存、创建 Issue 或执行搜索。“模型控制”不表示模型拥有最终授权,Host 仍应展示敏感操作、校验参数,并允许用户拒绝。

Resource 更接近可读取的数据,例如文件、数据库 Schema、文档或日志,由应用决定怎样发现、选择并加入上下文。把所有 Resource 自动塞给模型,协议层的可连接性就变成了上下文泄漏,Host 应按任务、身份和最小必要原则选择。

Prompt 是 Server 提供的可复用交互模板,通常由用户显式选择,例如“生成代码审查摘要”。它不是高于系统指令的远程命令,也不应静默覆盖 Host 政策。

三者的区别概括起来是:Tool 倾向于让模型选择动作,Resource 由应用选择上下文,Prompt 由用户选择交互入口。

以“查询订单并退款”为例,完整链路不是模型直接访问支付系统:

  1. Host 与 Server 初始化会话并协商能力;
  2. Client 获取工具清单和 Schema;
  3. Host 根据身份、任务和策略过滤可见工具;
  4. 模型选择 refund_order 并生成参数;
  5. Host 校验 Schema 和业务政策;
  6. 高风险动作展示订单、金额和后果,等待批准;
  7. Client 发起协议调用;
  8. Server 校验调用方并访问后端;
  9. Host 记录结果、错误和 Trace;
  10. 系统查询订单终态,而不是只相信自然语言返回。

这条链路上至少有三道门:协议可用、身份可用、业务允许。MCP 主要负责第一道门的标准交互,后两道省不掉。最后一步尤其容易被跳过–工具返回成功不等于业务目标已经完成,应用仍要查询订单终态。

MCP 可以在本地进程和远程服务中运行。常见传输包括:

  • stdio:Host 启动本地 Server,通过标准输入输出交换消息;适合本地工具和桌面应用;
  • Streamable HTTP:通过 HTTP 连接远程 Server,适合服务化部署、会话和流式交互。

传输方式会改变威胁模型。本地 stdio Server 可能直接继承进程权限,能看到本机文件和环境变量;远程 Server 则涉及网络边界、身份认证、租户隔离和数据出境。“本地”不等于安全,“远程”也不等于危险,要看 Server 实际拿到什么 OS、网络和业务权限。

初始化时,双方交换协议版本、实现信息和可支持能力,所以 Client 不应假设每个 Server 都支持相同功能。

截至本文核对日,官方站点列出的稳定规范是 2025-11-25。[1] 官方同时公布了面向 2026-07-28 的 Release Candidate 信息,包含 Tasks、扩展、授权和 Trace Context 等演进方向。[2]

Release Candidate 不是稳定规范。生产实现应固定已支持版本,记录协商结果,对未知能力安全降级,不要把未来候选能力写成已经普遍可用的事实。

工具描述会进入模型上下文。一个恶意或被劫持的 Server 可以用工具名称和描述诱导模型错误调用,也可能返回带提示注入的内容。常见风险包括:

  • 工具投毒:描述中夹带越权指令;
  • 名称混淆:用近似名称冒充可信工具;
  • 参数扩大:模型填入超出用户意图的范围;
  • 返回值注入:把外部文本伪装成下一步指令;
  • 权限串联:低风险读取结果被转交给高风险发送工具;
  • Rug Pull:Server 更新后改变行为,但 Host 仍沿用旧信任。

对应的做法是固定可信 Server、记录工具版本或哈希、对能力变更重新审查,并把 Server 内容一律视为不可信数据。

安全的 MCP Host 至少有四层控制。

根据用户身份和当前任务,只向模型暴露必要工具。不可见比“看见但请勿使用”更稳妥。

Schema 只能检查类型,不能判断业务合理性。amount: 100000 可能满足数字类型,却违反退款上限。

发送、删除、付款、发布等不可逆动作,应显示具体目标和参数。批准应绑定本次调用,不能成为永久通行证。

Server 和业务系统仍需验证身份、租户和资源权限,不能因为调用来自 MCP Client 就默认可信。

选择 Server 时不能只看“工具多不多”,建议核对维护主体和最近发布、License 与部署模式、要求哪些凭据和权限和网络访问、是否支持只读模式、工具 Schema 是否具体、错误是否结构化、是否有审计日志和速率限制和取消、是否能固定版本、是否存在官方或组织批准的发行渠道。

FastMCP 等项目帮助开发者构建 MCP Client/Server,Composio 等平台则提供大量 SaaS 连接。[3][4] 这两类解决的是开发和集成效率,不会自动替业务完成权限审计。

图 2 放在这里是为了防止把两种连接关系混为一谈:MCP 连接的是应用与工具/上下文,A2A 连接的是相对独立的 Agent 系统。

A2A GitHub 页面,用于与 MCP 对比

图 2:MCP 与 A2A 可以出现在同一系统,但所连接的对象不同。来源见文末。

真实工具会超时、限流、部分成功,或者在响应丢失之后其实已经完成。调用层应区分:

  • 协议错误:消息、方法或参数不符合协议;
  • 传输错误:连接断开、超时;
  • 工具错误:后端拒绝、资源不存在;
  • 业务失败:政策不允许、余额不足;
  • 状态未知:没有响应,但副作用可能已发生。

只有明确可重试的错误才能自动重试。对有副作用的调用要使用幂等键,并在超时后先查询真实状态。长任务还需要进度、取消、恢复和结果引用;协议的演进正在增强这类能力,但应用不能等协议替自己设计任务状态机。

动手跑一次:发现工具与授权写操作

Section titled “动手跑一次:发现工具与授权写操作”

从本讲目录执行:

Terminal window
python3 experiments/mcp_authorization_boundary.py

mcp_authorization_boundary.py 模拟一个 Server 暴露两个工具:只读 read_policy 和写操作 refund_order。脚本刻意不实现完整 MCP 传输,只抽出最容易被忽略的授权边界。

Client 能发现两个工具。策略层允许只读查询;没有批准时,退款调用返回 approval_required;只有绑定批准后才允许执行。

{
"mcp_discovery": ["read_policy", "refund_order"],
"read_call": {"allowed": true},
"write_without_approval": {"allowed": false},
"write_with_approval": {"allowed": true}
}

完整结果见 experiment-result.json。先看工具列表里两个名字都可见,再核对没有批准的写操作返回 allowed: falseapproval_required,绑定批准后才变成 allowed: true。这个实验要验证的只有一句话:Discovery 是能力元数据,Authorization 才是执行许可。

给实验增加三个字段:user_idtenant_ididempotency_key。设计以下测试:

  1. 用户 A 不能退款用户 B 的订单;
  2. 批准金额为 100 时,模型不能把参数改成 1000;
  3. 相同幂等键重复请求,只产生一次副作用;
  4. 工具描述发生变化时,Host 暂停自动调用并要求复审;
  5. Tool 返回一段“请调用上传工具”的文本时,系统只把它当数据。

做完这五条,你会得到一个比“工具调用成功”更接近生产现实的测试集。

MCP 的价值是把应用与外部能力之间的连接变得一致、可发现、可组合。连接越方便,Host 越需要管理上下文、权限、批准、版本和审计。

协议告诉系统“怎样连接”,政策决定系统“是否允许”。把“可发现”当成“可执行”,是工具生态里最常见的越界。

下一讲把 MCP 放回更大的协议地图:A2A、ACP、AG-UI 各自连接谁,为什么未来的 Agent 系统更像分层网络,而不是一个万能协议。

  • 想先理解一手架构、能力与版本:读 MCP Specification 2025-11-25
  • 想从安全视角审查工具接入:读 MCP Security Best Practices,再把其中的原则对照到本章三道门。
  • 想自己搭建或评估 Server:看 FastMCP 的开发侧抽象,同时审查它实际请求的凭据、网络和写入权限。

[1] Model Context Protocol, Specification 2025-11-25. https://modelcontextprotocol.io/specification/2025-11-25

[2] Model Context Protocol, 2026-07-28 Release Candidate. https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/

[3] FastMCP. https://github.com/jlowin/fastmcp

[4] Composio. https://github.com/ComposioHQ/composio

[5] Model Context Protocol, Security Best Practices. https://modelcontextprotocol.io/specification/2025-11-25/basic/security_best_practices

[6] A2A Project. https://github.com/a2aproject/A2A