青蛙小白

Model Context Protocol(模型上下文协议)

模型上下文协议(Model Context Protocol,MCP) 是 Anthropic 于 2024 年 11 月提出的开放标准,定义了 AI 模型与外部工具、数据源、服务之间的通信方式。目标是让任何 AI 客户端都能用同一套协议连接任何工具服务器,而不是为每对「模型 + 工具」单独写集成代码。

核心思路

传统做法:每个工具都要为每个模型单独实现一套集成,M 个模型 × N 个工具 = M×N 个集成。MCP 引入统一协议层,变成 M + N:工具只需实现一次 MCP 服务器,模型只需实现一次 MCP 客户端。

组成部分

  • MCP 服务器(MCP Server):封装具体工具能力(读数据库、查 Issue、搜索文件等),对外暴露标准接口
  • MCP 客户端(MCP Client):AI 模型或 Agent 框架,通过标准协议调用服务器提供的工具
  • 工具(Tools):服务器提供的可调用函数,模型可以选择调用哪个、传什么参数
  • 资源(Resources):服务器提供的可读数据(文件、数据库记录、API 响应等)
  • 提示模板(Prompts):服务器提供的预设提示,供客户端复用

在循环工程中的作用

MCP 是Loop Engineering(循环工程)「插件与连接器」模块的底层实现机制。没有 MCP,每接入一个新工具都需要定制集成;有了 MCP,Agent 可以:

  • 读取 Issue 跟踪系统(GitHub/Linear/Jira)
  • 查询数据库或内部 API
  • 在 Slack/飞书发通知
  • 触发 CI/CD 流水线
  • 调用任意内部系统

主流工具(Claude Code、Codex、Cursor 等)都支持通过 MCP 服务器扩展 Agent 能力。

Codex 的 CLI 会把用户在配置中接入的 MCP 工具转换为 Responses API(响应 API) 的工具定义,和内置 shell、计划工具、Web search 等一起提供给模型。Codex 的权限说明只约束自身提供的 shell 工具;MCP 服务器暴露的工具需要在服务器侧实现自己的权限边界和安全策略。

与传统函数调用的区别

维度Function Calling(函数调用)MCP
定义位置在调用请求里临时声明由外部服务器持久提供
复用性每次请求都要重新传 schema一次部署,所有客户端共用
工具发现由开发者手动指定客户端可动态列举服务器提供的工具
跨模型各家格式不同统一协议,换模型不需改工具

两者也可以组合使用:客户端从 MCP 服务器发现工具,再把这些工具转换为目标模型 API 支持的 function/tool calling schema。此时 MCP 是工具供应和发现层,Function Calling 是模型请求工具调用时的表达层。

OpenAI 的 Responses API 也支持 Remote MCP:开发者可在 tools 中配置 type: "mcp"、服务器标签、说明、URL 和审批策略,让模型访问远程 MCP 服务器提供的能力。这个入口属于 OpenAI API Tools(OpenAI API 工具)的一部分;它降低了接入成本,但不替代 MCP 服务器自己的权限控制、工具描述治理和审计机制。

在 Responses API 中,Remote MCP 的运行过程更像“协议桥接”而不是普通函数定义注入:API 先向服务器列举工具,返回 mcp_list_tools;模型需要动作时再产生 mcp_call,由 API 向远程 MCP server 发起调用并把输出放回模型上下文。连接器场景下,OpenAI API Connectors也复用同一套 type: "mcp"mcp_call 输出形态,只是配置项从 server_url 变成 connector_id

这带来两个工程含义。第一,工具列举结果应尽量保留在对话上下文里,否则每轮重复发现工具会增加延迟。第二,大 MCP server 不宜完整暴露给模型:可以用 allowed_tools 限定导入范围,或用 defer_loading: true 配合 tool search 延迟加载函数定义。

Claude Messages API 中的 MCP connector 也扮演类似角色:把远程 MCP 服务器接入 Claude API Tools,让 Claude 在当前请求中发现并调用外部工具。这里 MCP 仍是工具供应和发现层,Claude tool_use / tool_result 是模型调用层的表达格式。

Claude Agent SDK也支持在 options 中声明 MCP servers,让 Claude Code 风格的 Agent 在自己的工具循环中连接 Playwright、数据库、内部 API 等外部能力。工程边界仍然相同:SDK 可以发现和调用 MCP 工具,但 MCP 服务器自己的权限、审计和工具描述治理不能被 SDK 自动代替。

Claude Code 中的 MCP 客户端实现

Claude Code 展示了 MCP 从“协议标准”落到编码 Agent harness 时会新增哪些工程问题。它不只是连接 server,还要处理配置作用域、信任确认、OAuth、工具上下文膨胀、工具输出体积、动态工具变化和人类审批。

Claude Code 支持 HTTP、SSE、stdio、WebSocket、插件内置 server 和 claude.ai connector。团队共享通常用 project scope,把配置写入 .mcp.json;个人实验或带私密凭证的 server 更适合 local/user scope。重名 server 按 local > project > user > plugin > claude.ai connector 覆盖,且整条 server 配置替换,不做字段级合并。这个设计把 MCP 配置也纳入了代码仓库信任模型:项目提交 .mcp.json 可以共享能力,但不能让克隆者在未信任仓库前自动执行任意 server。

在上下文管理上,Claude Code 默认启用 MCP tool search:启动时只加载工具名和 server instructions,具体工具 schema 等需要时再进入上下文。server 作者因此要把 server instructions 写得像工具目录的索引:说明工具类别、何时搜索、核心能力,并把关键内容放在前 2KB 内。若某个小型 server 的工具每轮都要可见,可以在配置里设置 alwaysLoad: true,代价是启动时阻塞连接并持续消耗上下文。

MCP 的三类能力在 Claude Code 里有不同用户界面:tools 由模型按需调用;resources 可用 @server:protocol://resource/path 像文件一样引用;prompts 会变成 /mcp__servername__promptname 形式的 slash command。它们共同说明 MCP 不只是 Function Calling(函数调用)的工具列表来源,也是一套把外部知识、流程和执行能力映射到 Agent 工作台的接口。

治理上,Claude Code 给 MCP server 作者提供了几种 Anthropic 专用 _meta 注解:anthropic/maxResultSizeChars 可提高特定文本工具的大结果阈值;anthropic/requiresUserInteraction 可要求某个工具每次调用都必须触达人类确认;anthropic/alwaysLoad 可让特定工具跳过 tool search 延迟加载。客户端还会处理 root-level anyOf / oneOf / allOf 这类 Claude API 不接受的 schema 形态,把它们压平成对象并在描述里提示参数组合,但最终仍要求 server 端重新校验参数组合。

这类实现细节强化了 MCP 的核心边界:协议能标准化发现和调用,但不能自动解决权限、最小 scope、输出分页、schema 兼容、工具投毒和 prompt injection。生产系统仍要把 MCP server 当作有执行能力的第三方程序来审查,而不是当成普通文档源。

Anthropic 后续的 containment 经验进一步强调:审查 MCP server 代码不等于审查 MCP server 返回的数据。一个 GitHub connector 可以通过了软件供应链审查,却把被投毒的 README 原样加载进模型上下文。任何会把外部内容放进 Agent 上下文的工具输出,都应按网页内容一样做 prompt injection 扫描;否则日志里最后只会看到一次“合法且授权”的 API 调用。

远程和本地 MCP 的信任边界也不同。本地工具可以读源码、pin 版本、纳入企业软件分发;远程 MCP server 或云 connector 在安装批准之后仍可能改变行为。对不在受审 connector directory 内的远程工具,应先用假数据和低 blast radius 环境试运行,再授予真实数据访问。

Claude Cowork 的架构变化也给 MCP 接入一个现实取舍:把本地 MCP server 放进 VM 会更难审计、依赖更脆弱,也无法连接 host 上的数据库或本地进程;把它放在 host 上更实用,但它就更像用户主动安装的软件,必须由管理员决定是否启用。Remote MCP server 不运行在本机,问题则转向数据权限、工具输出扫描和 connector 持续审查。

代码执行式 MCP

Anthropic 在《Code execution with MCP》中提出了另一种大规模 MCP 使用模式:代码执行式 MCP。核心做法不是把所有 MCP 工具定义都作为模型 tool schema 预先加载,而是把 server 和 tool 生成成代码 API 或文件树,让 Agent 在 Agent Sandbox(Agent 沙箱)里写代码调用 MCP 工具。

这个模式把 MCP 从“模型直接调用的一组工具”变成“代码可调用的外部能力库”。模型通过列目录、搜索工具或读取具体工具文件来渐进披露接口;长文档、表格和 transcript 等中间结果可以在执行环境里作为变量流动、过滤、聚合或写入另一个工具,只把摘要和必要样本返回给模型。

它对应 MCP 规模化后的新瓶颈:工具生态越大,直接把工具定义和工具结果塞进上下文越昂贵,也越容易触发 Context Engineering(上下文工程)里的上下文混乱和上下文腐烂。传统直连 MCP 通常有两类成本:

  • 工具定义前置膨胀:模型在读用户请求前就要处理大量工具名称、描述、参数和返回值说明。
  • 中间结果反复穿过模型:从一个工具读出的长文档、表格或 transcript,如果要写入另一个工具,往往先进入模型上下文,再由模型作为参数写出去。

Anthropic 的例子是“从 Google Drive 下载会议 transcript,再写入 Salesforce lead”。直连工具调用会让完整 transcript 通过上下文至少两次;2 小时会议可能额外消耗约 50,000 token,并增加复制错误概率。代码执行式 MCP 的关键是让 transcript 在执行环境中作为变量流动,模型只看到代码、必要日志和最终摘要。

一种实现方式是把所有 MCP server 生成成文件树,每个工具对应一个 TypeScript 文件:

servers/
├── google-drive/
│   ├── getDocument.ts
│   └── index.ts
└── salesforce/
    ├── updateRecord.ts
    └── index.ts

工具文件暴露普通函数,内部再调用 MCP client:

export async function getDocument(input: GetDocumentInput): Promise<GetDocumentResponse> {
  return callMCPTool<GetDocumentResponse>("google_drive__get_document", input);
}

Agent 通过列目录和读文件来发现能力:先看有哪些 server,再只打开当前任务需要的工具文件。这与上下文工程中的渐进披露一致:模型不需要一次性持有整个工具生态,只要知道去哪里查。

传统直连 MCP 的消息循环可以表示为:

sequenceDiagram
    participant M as Model
    participant C as MCP Client
    participant S as MCP Server
    C->>S: tools/list
    S-->>C: tools/list result
    C->>M: system prompt + tool definitions
    M-->>C: tool call
    C->>S: tools/call
    S-->>C: tools/call result
    C->>M: tool result enters context

代码执行式 MCP 在这个循环中插入执行环境:模型写代码,代码在沙箱里调用 MCP 工具、保存变量、过滤结果、执行循环和条件分支,最后只 console.log 或返回模型真正需要的摘要。

主要收益有五类:

  • 渐进披露工具定义:把工具作为文件或可搜索 API 暴露,模型只读取相关接口。Anthropic 在示例中声称,这能把某类任务的工具定义上下文从 150,000 token 降到 2,000 token,节省 98.7%。
  • 结果在模型外处理:读取 10,000 行表格后,可以在代码里筛选 Status === "pending",只打印前 5 行给模型审核。聚合、join、字段抽取和格式转换都可以在执行环境中完成,而不是让模型直接阅读全量结果。
  • 复杂控制流更自然:循环、条件、等待、重试和错误处理可以用代码表达。比如轮询 Slack 是否出现部署完成通知,不必让模型在每次工具调用和 sleep 之间反复进入 Agent Loop(智能体循环)
  • 隐私边界更细:中间结果默认留在执行环境里,模型只看到显式日志。MCP client 还可以对 PII 做 tokenization:模型看见 [EMAIL_1][PHONE_1] 这类占位符,真实值只在 Google Sheets 到 Salesforce 的工具调用路径中解 token。
  • 状态和技能可持久化:Agent 可以把中间文件写入 workspace,后续执行继续读取;也可以把常用代码保存成函数,再配上 SKILL.md 演化成 Agent Skills式的可复用能力。

代价也很明确:代码执行式 MCP 可以降低 token 和延迟,但把复杂度转移给 Harness Engineering(驾驭工程)。执行环境需要沙箱、资源限制、网络出口控制、敏感数据 tokenization、日志审计、MCP 工具权限治理,以及对 Agent 生成代码的超时、重试和异常包装。

因此它不替代 Agent-Computer Interface(智能体计算机接口)面向 Agent 的工具设计。底层工具仍要有清晰命名、参数 schema、错误返回和高信号输出;只是模型不必在每一步都直接阅读所有 schema 和所有结果。

与 Agent Skills 的关系

Agent Skills和 MCP 经常一起出现,但解决的是不同层的问题。MCP 标准化的是“外部系统如何向 Agent 暴露工具、资源和提示”;Agent Skills 标准化的是“Agent 如何按需加载某类任务的流程知识、参考材料和辅助脚本”。

因此,MCP 更偏工具连接层,Skills 更偏流程与知识包装层。一个发布审查 Agent 可以通过 MCP 读取 GitHub、Linear 和日志系统,同时通过 Agent Skill 学会组织内的发布 checklist、风险判断规则、回滚脚本和报告模板。Anthropic 在 Agent Skills 文章中也把 Skills 定位为 MCP 的补充:外部工具给 Agent 能力,Skill 教 Agent 怎样组合这些能力完成真实工作。

A2A:Agent 间通信的对应标准

MCP 解决的是 Agent ↔ 工具(外部能力)边界的问题;A2A(Agent-to-Agent Protocol) 解决的是 Agent ↔ Agent 边界的问题。两者互补,不竞争:

  • MCP:一个 Agent 进程调用外部工具/数据源(runtime-to-tool 解耦)
  • A2A:多个 Agent 应用之间的发现、同步/流式交互和长期任务协作(cross-process delegation)

ETCLOVG Taxonomy(ETCLOVG 分类法)中,MCP 和 A2A 都归属 T 层(工具接口与协议),但跨越不同集成边界。

MCP 的安全问题

MCP 最初规范缺乏原生安全原语,这一空缺已催生攻防两端的研究:

攻击面

  • 工具投毒(Tool Poisoning):Trail of Bits(2025)展示 MCP 服务器可在用户实际调用工具之前通过投毒工具描述来影响 LLM 行为——恶意指令在工具注册时即注入
  • MCP 强制执行:Radosevich & Halloran(2025)证明广泛使用的商业 LLM 可被诱导通过 MCP 工具执行恶意代码、建立远程访问、窃取凭证

防御方向

  • ETDI(Enhanced Tool Definition Interface):用密码学签名和版本化工具定义扩展 MCP,确保对工具代码、schema 或权限的任何修改都需要新的签名版本,防止已批准工具被静默更新为执行恶意操作的"地毯拉动(rug-pull)“攻击
  • 供应链风险:Spracklen et al.(2025)分析 576,000 个代码样本,21.7% 的开源 LLM 生成代码中存在幻觉包名(slopsquatting),攻击者可注册这些名称并注入恶意代码

OpenAI 的 MCP 文档把生产防线落到几个具体配置上:默认审批 MCP tool call,敏感动作始终要求审批;用 allowed_tools 缩小工具面;只连接可信或官方服务器;记录并定期审查发送给第三方 MCP server 的数据;谨慎处理工具输出里的 URL 和图片 URL。即使组织启用了 Zero Data Retention 或 Data Residency,数据一旦发给第三方 MCP server,就受该服务器自己的保留和驻留政策约束。

Claude Managed Agents 还展示了 MCP 凭证隔离的托管形态:Claude 通过专用代理调用 MCP 工具,代理拿到与 session 关联的 token,再从 sandbox 外部 vault 取真实 OAuth 凭证并调用外部服务。harness 与 sandbox 都不直接持有这些凭证。这个模式把 MCP 的安全边界从“工具描述可信不可信”扩展到“凭证是否可被模型生成代码读取”。

对 Prompt Caching 的影响

MCP 的动态工具发现会影响Prompt Caching(提示缓存)。工具 schema 通常位于 prompt 前缀,工具列表顺序或内容一变,后续请求就不再拥有同一个精确前缀。OpenAI 在 Codex CLI 中曾遇到 MCP 工具枚举顺序不稳定导致 cache miss 的问题;此外,MCP 的 notifications/tools/list_changed 允许服务器在会话中途改变工具列表,若立即反映到 prompt,也会造成昂贵的缓存失效。

因此,MCP 不只是 T 层的工具协议,也会跨层影响 C 层的上下文成本管理。

相关概念

参考来源
  1. 1. https://openreview.net/pdf?id=3hXEPbG0dh
  2. 2. https://openai.com/index/unrolling-the-codex-agent-loop/
  3. 3. https://developers.openai.com/api/docs/guides/tools
  4. 4. https://developers.openai.com/api/docs/guides/function-calling
  5. 5. https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview
  6. 6. https://code.claude.com/docs/en/agent-sdk/overview
  7. 7. https://code.claude.com/docs/en/mcp
  8. 8. https://developers.openai.com/api/docs/guides/tools-connectors-mcp
  9. 9. https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills
  10. 10. https://www.anthropic.com/engineering/code-execution-with-mcp
  11. 11. https://www.anthropic.com/engineering/how-we-contain-claude
  12. 12. https://www.anthropic.com/engineering/managed-agents
评论