摘要: OpenAI Agents API 公开测试,官方示例代码直接把 MCP 写成一等公民。本文对照官方文档,梳理已有 MCP Server 要动的地方:HTTP 传输接入、server_label 标识,以及为"按需加载"重写的工具描述。附接入结构拆解和改造清单。

官方示例里直接长出了 MCP

写 MCP Server 那篇文章的时候,我结尾提过一句:给 AI 写 API 文档,比给 AI 写接口本身更难。前几天 OpenAI 发布 Agents API,我刷到官方博客,第一反应是——工具这一层,他们开始认真对待了。

先给结论:这次不是"宣布支持 MCP 概念"那种官宣,官方示例代码里直接写了 type: "mcp",连传输方式都定好了。 手上有 MCP Server 的人,接过去的姿势基本是确定的。

我把自己写过的 MCP Server 对着官方文档盘了一遍,把要动的点整理成这篇改造笔记。先声明边界:Agents API 还在公开测试期,这篇是基于官方文档和既有工程经验的梳理,不是已经跑通完整链路的实战复盘。哪些是文档里明写的、哪些是我自己的判断,下文会标出来。

Agents API 到底是什么

以下内容基于 2026.09.10 发布的公开测试版,接口仍在快速迭代,看到文章时如果版本已变,以官方文档为准。

官方公告讲得很直白:把 Codex 背后的那套 harness 托管给开发者,通过一次 API 调用创建 agent,指定任务、模型、工具和环境,剩下的交给 OpenAI 跑。

几个关键事实,都能在公告原文找到:

  • 公开测试版,发布即对所有开发者开放,没有附加费用,只按 token 和工具使用收费
  • 官方示例用的模型是 gpt-6-astra
  • 环境有三种选法:OpenAI 托管沙箱、自己的基础设施、或者 Cloudflare、Modal、Vercel 这些沙箱伙伴
  • 底层 harness 开源,仓库在 GitHub 上,逻辑能自己翻

这些不展开讲。下面说我的正题:MCP 是接进去的。想核实的朋友可以直接看官方公告原文 Introducing the Agents API,接口细节在 Agents API overview 里。

MCP 接入长什么样

整体链路画成图是这么个走向:

你的应用                    OpenAI 托管侧                       你的服务器
   │                            │                                 │
   ▼                            ▼                                 ▼
sessions.create ───────► Agents API ───────► Codex Harness ──HTTP──► MCP Server
                                   │                                 │
                        tool search 按需加载工具定义          处理请求并返回结果
                         长会话上下文自动压缩
                                   │
                       (返回结果沿同一条链路回到你的应用)

为什么要看这张图:它把"你只在登录侧动代码,中间全是托管"的关系摆清楚了。接 MCP 这件事,本质上就是在图的最右端多挂一台你的服务,中间这段不是你能改的。

官方公告里给的 MCP 配置是这么个形状:

{
  "agent": {
    "tools": [
      {
        "type": "mcp",
        "server_label": "order_service",
        "transport": {
          "type": "http",
          "server_url": "https://api.example.com/mcp"
        }
      }
    ]
  }
}

为什么要看这段:它可能是未来一段时间里"怎么给 agent 挂工具"的标准写法,直接对应你的 MCP Server 要被谁、以什么方式找到。字段结构照官方公告来的,我把 server_label 和 server_url 换成了订单场景方便演示——官方原文的 label 是 openai_docs、地址指向他们自己的文档站。本地能核对的只有字段结构,四个键名和公告一致:

// 字段结构核对(对照官方公告原文):
type: "mcp"
server_label: "order_service"        → 给这个工具源起的名字
transport.type: "http"               → 走 HTTP 传输
transport.server_url: "https://…"    → 你的 Server 地址

这一段里有三个信息点,接的时候一个都不能少:

  • type: "mcp":声明这是个 MCP 工具源
  • server_label:给这个 server 起的名字,agent 日志里靠它区分是哪个源
  • transport.http.server_url:你的 Server 得通过 HTTP 暴露出来,地址填这里

注意 transport 用的是 http,不是本地 stdio 那套。你的 Server 要能被一个跑在云上的 agent 从公网访问到。 这个前提看着不起眼,实际是本地开发最容易栽的地方,后面边界说明里再展开。

JS SDK 的调用长这样(也是官方示例,beta. 前缀如实保留;我为了突出 MCP 部分,省掉了 vault_ids、environment 这些非核心字段,input 换成了订单场景):

const session = await client.beta.agents.sessions.create({
  agent: {
    model: "gpt-6-astra",
    tools: [
      {
        type: "mcp",
        server_label: "order_service",
        transport: {
          type: "http",
          server_url: "https://api.example.com/mcp"
        }
      }
    ]
  },
  input: "把上个月的订单统计出来"
});

为什么要看这段:确认 API 层面对接成本很低——一个 sessions.create,工具挂进 agent 就完事。麻烦的不是这行调用,是和它配套的整条链路。调用主体的结构也和上面对照过:

// 调用结构核验(对照官方公告示例):
client.beta.agents.sessions.create(...)
  ├─ agent.model: "gpt-6-astra"    → 官方示例模型
  ├─ agent.tools[0].type: "mcp"    → 工具源类型
  └─ input: "把上个月的订单统计出来"  → 任务描述(我换成了订单场景)
// 调用成功返回 session 后,agent 会带着配置的 MCP 工具开始跑任务

我的 MCP Server 要动哪几处

对照完官方示例,我盘出三个要动的点。

第一个:传输层收敛到 HTTP。 我之前写 MCP Server 用的本地 stdio,文章里还专门讨论过几种 transport 的取舍。Agents API 这侧场景是"云上 agent 调你的服务",stdio 直接没了意义,必须把 Server 包成 HTTP 服务。本地开发期可以先跑隧道转发顶一段,真上生产就得有固定公网入口。

第二个:给 Server 起个能看的 label。 server_label 是 agent 配置里给这台 server 起的名字,光看示例可能觉得它只是个摆设,实际作用在出错排查时才体现出来——agent 任务一多(官方还支持多子 agent 并行),日志里要靠它分清工具调用来自哪个源。我的建议是别让一个名字通吃所有环境,label 里带上环境标识,排查事故能省很多事。

第三个,也是最花功夫的:工具描述要按"按需加载"的规矩重写。 这个单独展开说。

三个改造点先汇总成一张表,方便对照:

改造点做什么为什么
传输层stdio 收敛到 HTTPagent 在云上跑,你的 Server 得能被公网访问
server_label给 Server 起个能看的名字任务并行时,日志里分得清工具调用来自谁
工具描述按"按需加载"的规矩重写描述从"写清楚"升级为"会被检索选中"

工具描述:从"写给人看"变成"写给检索器看"

Agents API 自带一个 tool search 机制,官方文档的原话是:按需加载相关的工具定义,省 token、保持缓存命中(原文档在这里)。我理解下来就是——agent 不会把你的所有工具一次性搬进上下文,而是需要的时候再去选一批进来。

这条规则对我这种写过 MCP Server 的人来说,是实打实的变化。以前写工具描述,目标是"让 AI 理解这工具干嘛、参数别传错"——这个我在写 MCP Server 那篇时做过三版对比,验证过描述从粗到细对传参的影响。现在多了一件事:描述得让"检索"认得出来,在你需要它的时候选得中它。

下面是我本地测试台里的观察,不是官方算法说明:

// 改前:名字和描述都太泛
{
  "name": "query_orders",
  "description": "处理订单数据",
  "inputSchema": { "orderId": "string" }
}

// 改后:描述的落点具体到"什么场景会用到它"
{
  "name": "query_order_shipping_status",
  "description": "按订单号查询订单发货状态,返回预计送达时间",
  "inputSchema": {
    "orderId": { "type": "string", "description": "订单号,必填" }
  }
}

为什么要看这段:这是我在 Agent 需要"查某个订单到没到"时,同一套底层方法换两种壳的对比。改前这版是我早期连 Agent 时真实用的描述,后来在本地测试台反复跑同一批查询任务,执行结果差异一眼能看出:

同一个查询任务在本地测试台反复跑:
改前 query_orders                → 没有一次产生工具调用,直接作答
改后 query_order_shipping_status → 每次都先调工具拿数据,再基于数据作答

同样一个功能,描述写成"处理订单数据",在按需加载的场景下容易被别的带"数据"字样的工具挤掉;写成"按订单号查询发货状态",被挑中的概率明显更高。

我这里不敢说内部是关键词匹配还是语义匹配,官方没公开机制。但"更具体的描述更不容易被跳过"这个观测,我在自己的 MCP 测试台里复现过很多轮,下面把这个差异放进表里看:

维度普通 API 集成Agents API + MCP
工具怎么进上下文自己的编排代码显式调tool search 按需加载,不是全量搬入
描述的作用保证参数传对参数传对 + 还可能决定"能不能被选中"
Server 地址怎么给代码里写死server_url + 需要公网可达
多工具并行自己写编排programmatic tool calling 帮你并行

这张表基本就是我改造笔记的核心差异:同样的工具,评价尺度从"用起来对不对"加了半个维度——“在需要的时候找不找得到”。

接入后怎么验证自己改对了

改完别急着上生产,按下面几步在自己环境里验一遍,每一步都能看到明确结果。

第一步:确认 MCP Server 本身活着。 用 MCP 官方提供的 Inspector(一条 npx 命令就能拉起来)打开你的 Server,能看到工具列表正常返回,说明服务端没问题。这一步跟 Agents API 无关,纯验你 Server 这一端:

# Inspector 打开后看到的工具列表(示意)
query_order_shipping_status   按订单号查询订单发货状态
query_orders                  处理订单数据(改前,准备下线)

第二步:核对 agent 配置里的字段。 把官方示例的结构和你的配置逐键对比:type / server_label / transport.type / transport.server_url 四个键名不能错;server_url 要能外网访问,本地先 curl 一下确认能通。

第三步:跑一个描述对照实验。 挑一个最常用的工具,先用旧描述让 agent 跑一个"非调它不可"的任务,记下有没有调用;再把描述改具体,同一个任务再跑一遍。这个实验我在本地测试台做过,差异是明确的,你自己环境里也能复现:

同一个任务"查订单到哪了",两次运行对比:
旧描述 query_orders              → 没有工具调用,直接作答
新描述 query_order_shipping_status → 先调工具,再基于数据作答

第四步:看 agent 日志里的 server_label。 公开测试期里 agent 跑完任务后,去日志里确认工具调用的来源标识是不是你配的 label——顺便就验证了 label 起得够不够清楚。

哪些场景其实不用上 MCP

MCP 接入看着规整,别什么都往里塞。就一个函数能解决的事(算个折扣、查个字典),直接在 agent 配置里定义成普通函数更轻。MCP 这套的价值在"复用已有的工具服务",尤其是你已经有一批 HTTP 服务想给多个 agent 共用的时候。

再交代几个硬前提,都是实操里绕不开的:

  • 你的 Server 必须公网可达(或自托管环境能访问),这一点官方托管沙箱的链路里绕不掉
  • 传输走 HTTP 后,旧代码如果是纯 stdio,要包的层不止一处,鉴权也得提前想好
  • 如果你的 Server 用的是 SSE 这类更老的 MCP 传输形态,别想当然觉得直接能用,先对着 MCP 官方文档确认 HTTP transport 的要求,该包的兼容层一个都不能少
  • 公开测试期,接口和配置随时可能变,生产接入前盯着更新日志再动手

真要对 MCP 协议本身深入,规范在 modelcontextprotocol.io 有完整文档,这篇不展开。

一份落地自查清单

接之前对着这四条过一遍,能少踩不少坑:

  • MCP Server 已经包成 HTTP 服务,外网地址可达(本地开发先用隧道顶一段)
  • server_label 带上了环境标识,出错时日志里能分清是哪台
  • 每个工具的 description 写的是"什么场景会用到它",不是"它是什么"
  • 公开测试期的更新日志放进关注列表,接口变了不慌

回头看

OpenAI 把 MCP 写进官方示例,等于给这一届 agent 定了工具层的接口基调。对跑过 MCP Server 的人来说,接入本身不麻烦,真正要花心思的是把"给 AI 看 API 文档"升级成"在按需加载的世界里让自己的工具被选中"。前者是讲清楚,后者是会被找到——两件事,难度不一样。

如果现在就要动手,我的建议是先挑一个最常用的工具,把 description 从"它是什么"改成"什么场景会用到它",跑一轮同样的任务对比调用情况。这个验证最直观,比把全套工具重写一遍稳妥得多。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐