跳转到内容

MCP 集成

Model Context Protocol (MCP) 是一种开放协议,用于标准化应用如何向 LLM 提供工具和上下文。摘自 MCP 文档:

MCP 是一种开放协议,用于标准化应用如何向 LLM 提供上下文。你可以把 MCP 想象成 AI 应用的 USB-C 接口。就像 USB-C 为设备连接各类外设和配件提供了标准化方式一样,MCP 为 AI 模型连接不同数据源和工具提供了标准化方式。

此 SDK 支持三种 MCP 服务器类型:

  1. 远程 MCP 服务器工具——由 OpenAI Responses API 作为工具使用的远程 MCP 服务器
  2. Streamable HTTP MCP 服务器——实现了 Streamable HTTP transport 的本地或远程服务器
  3. Stdio MCP 服务器——通过标准输入/输出访问的服务器(最简单的选项)

注意:SDK 还包含用于旧版 Server-Sent Events 传输的 MCPServerSSE,但 SSE 已被 MCP 项目弃用。新集成建议优先使用 Streamable HTTP 或 stdio。

请根据你的使用场景选择服务器类型:

你的需求推荐选项
使用默认 OpenAI responses 模型调用可公开访问的远程服务器1. 远程 MCP 工具
使用可公开访问的远程服务器,但工具调用在本地触发2. Streamable HTTP
使用本地运行的 Streamable HTTP 服务器2. Streamable HTTP
在非 OpenAI-Responses 模型中使用任意 Streamable HTTP 服务器2. Streamable HTTP
使用仅支持标准 I/O 协议的本地 MCP 服务器3. Stdio

托管工具会将完整往返流程交给模型处理。你的代码不再直接调用 MCP 服务器,而是由 OpenAI Responses API 调用远程工具端点,并将结果流式返回给模型。

下面是使用远程 MCP 工具的最简单示例。你可以将远程 MCP 服务器的标签和 URL 传给 hostedMcpTool 工具函数,这有助于创建远程 MCP 服务器工具。

hostedAgent.ts
import { Agent, hostedMcpTool } from '@openai/agents';
export const agent = new Agent({
name: 'MCP Assistant',
instructions: 'You must always use the MCP tools to answer questions.',
tools: [
hostedMcpTool({
serverLabel: 'gitmcp',
serverUrl: 'https://gitmcp.io/openai/codex',
}),
],
});

然后,你可以使用 run 函数(或你自定义 Runner 实例的 run 方法)运行 Agent:

使用远程 MCP 工具运行
import { run } from '@openai/agents';
import { agent } from './hostedAgent';
async function main() {
const result = await run(
agent,
'Which language is the repo I pointed in the MCP tool settings written in?',
);
console.log(result.finalOutput);
}
main().catch(console.error);

要流式传输增量 MCP 结果,请在运行 Agent 时传入 stream: true

使用远程 MCP 工具运行(流式传输)
import { isOpenAIResponsesRawModelStreamEvent, run } from '@openai/agents';
import { agent } from './hostedAgent';
async function main() {
const result = await run(
agent,
'Which language is the repo I pointed in the MCP tool settings written in?',
{ stream: true },
);
for await (const event of result) {
if (
isOpenAIResponsesRawModelStreamEvent(event) &&
event.data.event.type !== 'response.mcp_call_arguments.delta' &&
event.data.event.type !== 'response.output_text.delta'
) {
console.log(`Got event of type ${JSON.stringify(event.data)}`);
}
}
console.log(`Done streaming; final result: ${result.finalOutput}`);
}
main().catch(console.error);

对于敏感操作,你可以要求对单个工具调用进行人工审批。传入 requireApproval: 'always',或传入将工具名映射到 'never'/'always' 的细粒度对象。

如果你可以通过程序判断工具调用是否安全,可以使用 onApproval 回调来批准或拒绝工具调用。如果你需要人工审批,也可以像本地函数工具一样,使用 interruptions 采用同样的人机协作(HITL)方法

远程 MCP 工具中的人工干预
import { Agent, run, hostedMcpTool, RunToolApprovalItem } from '@openai/agents';
async function main(): Promise<void> {
const agent = new Agent({
name: 'MCP Assistant',
instructions: 'You must always use the MCP tools to answer questions.',
tools: [
hostedMcpTool({
serverLabel: 'gitmcp',
serverUrl: 'https://gitmcp.io/openai/codex',
// 'always' | 'never' | { never, always }
requireApproval: {
never: {
toolNames: ['search_codex_code', 'fetch_codex_documentation'],
},
always: {
toolNames: ['fetch_generic_url_content'],
},
},
}),
],
});
let result = await run(agent, 'Which language is this repo written in?');
while (result.interruptions && result.interruptions.length) {
for (const interruption of result.interruptions) {
// Human in the loop here
const approval = await confirm(interruption);
if (approval) {
result.state.approve(interruption);
} else {
result.state.reject(interruption);
}
}
result = await run(agent, result.state);
}
console.log(result.finalOutput);
}
import { stdin, stdout } from 'node:process';
import * as readline from 'node:readline/promises';
async function confirm(item: RunToolApprovalItem): Promise<boolean> {
const rl = readline.createInterface({ input: stdin, output: stdout });
const name = item.name;
const params = item.arguments;
const answer = await rl.question(
`Approve running tool (mcp: ${name}, params: ${params})? (y/n) `,
);
rl.close();
return answer.toLowerCase().trim() === 'y';
}
main().catch(console.error);

hostedMcpTool(...) 同时支持 MCP 服务器 URL 和基于连接器的服务器:

选项类型说明
serverLabelstring必填标签,用于在事件和追踪中标识远程 MCP 服务器。
serverUrlstring远程 MCP 服务器 URL(常规远程 MCP 服务器使用此项)。
connectorIdstringOpenAI connector id(对于连接器支持的托管服务器,用此项替代 serverUrl)。
authorizationstring可选授权令牌,会发送到远程 MCP 后端。
headersRecord<string, string>可选的额外请求头。
allowedToolsstring[] | object允许暴露给模型的工具名白名单。可传 string[]{ toolNames?: string[] }
deferLoadingboolean仅适用于 Responses 的远程 MCP 工具延迟加载。要求同一智能体中包含 toolSearchTool()
requireApproval'never' | 'always' | object远程 MCP 工具调用的审批策略。按工具覆盖请使用对象形式。默认值为 'never'
onApprovalApproval callbackrequireApproval 要求审批处理时,用于程序化批准/拒绝的可选回调。

当你希望模型通过工具搜索按需加载远程 MCP 服务器的工具定义,而不是一开始全部暴露时,请设置 deferLoading: true。这仅适用于 OpenAI Responses API,要求同一请求中包含 toolSearchTool(),并建议配合 GPT-5.4 及更新的受支持模型版本使用。完整的延迟加载配置见工具指南

requireApproval 对象形式:

{
always?: { toolNames: string[] };
never?: { toolNames: string[] };
}

onApproval 签名:

async function onApproval(
context,
item,
): Promise<{
approve: boolean;
reason?: string;
}> {}

远程 MCP 也支持 OpenAI 连接器。你无需提供 serverUrl,而是传入连接器的 connectorIdauthorization 令牌。随后 Responses API 会处理认证,并通过远程 MCP 接口暴露连接器工具。

基于连接器的远程 MCP 工具
import { Agent, hostedMcpTool } from '@openai/agents';
const authorization = process.env.GOOGLE_CALENDAR_AUTHORIZATION!;
export const connectorAgent = new Agent({
name: 'Calendar Assistant',
instructions:
"You are a helpful assistant that can answer questions about the user's calendar.",
tools: [
hostedMcpTool({
serverLabel: 'google_calendar',
connectorId: 'connector_googlecalendar',
authorization,
requireApproval: 'never',
}),
],
});

在此示例中,GOOGLE_CALENDAR_AUTHORIZATION 环境变量保存了从 Google OAuth Playground 获取的 OAuth 令牌,该令牌授权连接器支持的服务器调用 Calendar API。可运行示例(也演示了流式传输)见 examples/connectors

完整可运行示例(远程工具/Streamable HTTP/stdio + 流式传输、HITL、onApproval)位于我们 GitHub 仓库中的 examples/mcp

当你的智能体直接与 Streamable HTTP MCP 服务器(本地或远程)通信时,可使用服务器 urlname 及可选设置来实例化 MCPServerStreamableHttp

使用 Streamable HTTP MCP 服务器运行
import { Agent, run, MCPServerStreamableHttp } from '@openai/agents';
async function main() {
const mcpServer = new MCPServerStreamableHttp({
url: 'https://gitmcp.io/openai/codex',
name: 'GitMCP Documentation Server',
});
const agent = new Agent({
name: 'GitMCP Assistant',
instructions: 'Use the tools to respond to user requests.',
mcpServers: [mcpServer],
});
try {
await mcpServer.connect();
const result = await run(agent, 'Which language is this repo written in?');
console.log(result.finalOutput);
} finally {
await mcpServer.close();
}
}
main().catch(console.error);

构造函数选项:

选项类型说明
urlstringStreamable HTTP 服务器 URL。
namestring服务器的可选标签。
cacheToolsListboolean缓存工具列表以降低延迟。
clientSessionTimeoutSecondsnumberMCP 客户端会话超时时间。
toolFilterMCPToolFilterCallable | MCPToolFilterStatic过滤可用工具。
toolMetaResolverMCPToolMetaResolver为每次调用注入 MCP _meta 请求字段。
errorFunctionMCPToolErrorFunction | null将 MCP 调用失败映射为模型可见文本。
timeoutnumber单次请求超时(毫秒)。
loggerLogger自定义日志记录器。
authProviderOAuthClientProvider来自 MCP TypeScript SDK 的 OAuth provider。
requestInitRequestInit请求的 Fetch 初始化选项。
fetchFetchLike自定义 fetch 实现。
reconnectionOptionsStreamableHTTPReconnectionOptions重连调优选项。
sessionIdstringMCP 连接的显式会话 id。

该构造函数还接受其他 MCP TypeScript-SDK 选项,如 authProviderrequestInitfetchreconnectionOptionssessionId。详见 MCP TypeScript SDK 仓库及其文档。

对于仅暴露标准 I/O 的服务器,请用 fullCommand 实例化 MCPServerStdio

使用 Stdio MCP 服务器运行
import { Agent, run, MCPServerStdio } from '@openai/agents';
import * as path from 'node:path';
async function main() {
const samplesDir = path.join(__dirname, 'sample_files');
const mcpServer = new MCPServerStdio({
name: 'Filesystem MCP Server, via npx',
fullCommand: `npx -y @modelcontextprotocol/server-filesystem ${samplesDir}`,
});
await mcpServer.connect();
try {
const agent = new Agent({
name: 'FS MCP Assistant',
instructions:
'Use the tools to read the filesystem and answer questions based on those files. If you are unable to find any files, you can say so instead of assuming they exist.',
mcpServers: [mcpServer],
});
const result = await run(agent, 'Read the files and list them.');
console.log(result.finalOutput);
} finally {
await mcpServer.close();
}
}
main().catch(console.error);

构造函数选项:

选项类型说明
command / argsstring / string[]stdio 服务器的命令 + 参数。
fullCommandstringcommand + args 的完整命令字符串替代形式。
envRecord<string, string>服务器进程的环境变量。
cwdstring服务器进程的工作目录。
cacheToolsListboolean缓存工具列表以降低延迟。
clientSessionTimeoutSecondsnumberMCP 客户端会话超时时间。
namestring服务器的可选标签。
encodingstringstdio 流的编码。
encodingErrorHandler'strict' | 'ignore' | 'replace'编码错误处理策略。
toolFilterMCPToolFilterCallable | MCPToolFilterStatic过滤可用工具。
toolMetaResolverMCPToolMetaResolver为每次调用注入 MCP _meta 请求字段。
errorFunctionMCPToolErrorFunction | null将 MCP 调用失败映射为模型可见文本。
timeoutnumber单次请求超时(毫秒)。
loggerLogger自定义日志记录器。

当你需要使用多个 MCP 服务器时,可以使用 connectMcpServers 统一连接、跟踪失败并集中关闭。该辅助函数会返回一个 MCPServers 实例,包含 activefailederrors 集合,因此你可以仅将健康服务器传给智能体。

管理多个 MCP 服务器
import {
Agent,
MCPServerStreamableHttp,
connectMcpServers,
run,
} from '@openai/agents';
async function main() {
const servers = [
new MCPServerStreamableHttp({
url: 'https://mcp.deepwiki.com/mcp',
name: 'DeepWiki MCP Server',
}),
new MCPServerStreamableHttp({
url: 'http://localhost:8001/mcp',
name: 'Local MCP Server',
}),
];
const mcpServers = await connectMcpServers(servers, {
connectInParallel: true,
});
try {
console.log(`Active servers: ${mcpServers.active.length}`);
console.log(`Failed servers: ${mcpServers.failed.length}`);
for (const [server, error] of mcpServers.errors) {
console.warn(`${server.name} failed to connect: ${error.message}`);
}
const agent = new Agent({
name: 'MCP lifecycle agent',
instructions: 'Use MCP tools to answer user questions.',
mcpServers: mcpServers.active,
});
const result = await run(
agent,
'Which language is the openai/codex repository written in?',
);
console.log(result.finalOutput);
} finally {
await mcpServers.close();
}
}
main().catch(console.error);

使用场景:

  • 同时使用多个服务器:并行连接全部服务器,并将 mcpServers.active 用于智能体。
  • 部分失败处理:检查 failed + errors,决定继续还是重试。
  • 重试失败服务器:调用 mcpServers.reconnect()(默认仅重试失败服务器)。

如果你需要严格的“全有或全无”连接,或不同超时设置,可使用 connectMcpServers(servers, options),并根据你的环境调整选项。

connectMcpServers 选项:

选项类型默认值说明
connectTimeoutMsnumber | null10000每个服务器 connect() 的超时。传 null 可禁用。
closeTimeoutMsnumber | null10000每个服务器 close() 的超时。传 null 可禁用。
dropFailedbooleantrueactive 中排除失败服务器。
strictbooleanfalse若任一服务器连接失败则抛错。
suppressAbortErrorbooleantrue忽略类似 abort 的错误,同时仍跟踪失败服务器。
connectInParallelbooleanfalse并发连接所有服务器,而不是顺序连接。

mcpServers.reconnect(options) 支持:

选项类型默认值说明
failedOnlybooleantrue仅重试失败服务器(true)或重连所有服务器(false)。

如果你的运行时支持 Symbol.asyncDisposeMCPServers 也支持 await using 模式。在 TypeScript 中,请在 tsconfig.json 里启用 esnext.disposable

{
"compilerOptions": {
"lib": ["ES2018", "DOM", "esnext.disposable"]
}
}

然后你可以这样写:

await using mcpServers = await connectMcpServers(servers);

对于 Streamable HTTPStdio 服务器,每次 Agent 运行时都可能调用 list_tools() 来发现可用工具。由于这次往返会增加延迟(尤其是远程服务器),你可以在 MCPServerStdioMCPServerStreamableHttp 中传入 cacheToolsList: true,将结果缓存到内存中。

仅在你确认工具列表不会变化时启用该选项。若后续需要使缓存失效,请在服务器实例上调用 invalidateToolsCache()。如果你在使用通过 getAllMcpTools(...) 的共享 MCP 工具缓存,也可以按服务器名调用 invalidateServerToolsCache(serverName) 进行失效处理。

在高级场景中,getAllMcpTools({ generateMCPToolCacheKey }) 允许你自定义缓存分区(例如按 server + agent + run context)。

你可以通过传入 createMCPToolStaticFilter 创建的静态过滤器,或传入自定义函数,来限制每个服务器暴露的工具。下面是同时展示两种方式的示例:

工具过滤
import {
MCPServerStdio,
MCPServerStreamableHttp,
createMCPToolStaticFilter,
MCPToolFilterContext,
} from '@openai/agents';
interface ToolFilterContext {
allowAll: boolean;
}
const server = new MCPServerStdio({
fullCommand: 'my-server',
toolFilter: createMCPToolStaticFilter({
allowed: ['safe_tool'],
blocked: ['danger_tool'],
}),
});
const dynamicServer = new MCPServerStreamableHttp({
url: 'http://localhost:3000',
toolFilter: async ({ runContext }: MCPToolFilterContext, tool) =>
(runContext.context as ToolFilterContext).allowAll || tool.name !== 'admin',
});