MCP 集成
Model Context Protocol (MCP) 是一种开放协议,用于规范应用如何向 LLMs 提供工具和上下文。MCP 文档中写道:
MCP 是一种开放协议,用于规范应用如何向 LLMs 提供上下文。可以把 MCP 理解为 AI 应用的 USB-C 端口。就像 USB-C 提供了一种标准化方式来将设备连接到各种外设和配件一样,MCP 也提供了一种标准化方式,将 AI 模型连接到不同的数据源和工具。
此 SDK 支持三类 MCP 服务器:
- 远程 MCP 服务器工具 – OpenAI Responses API 作为工具使用的远程 MCP 服务器
- Streamable HTTP MCP 服务器 – 实现了 Streamable HTTP 传输的本地或远程服务器
- Stdio MCP 服务器 – 通过标准输入/输出访问的服务器(最简单的选项)
注意:SDK 还包含用于旧版 Server-Sent Events 传输的
MCPServerSSE,但 SSE 已被 MCP 项目弃用。新集成应优先使用 Streamable HTTP 或 stdio。
根据使用场景选择服务器类型:
| 需求 | 推荐选项 |
|---|---|
| 使用默认的 OpenAI Responses 模型调用可公开访问的远程服务器 | 1. 远程 MCP 服务器工具 |
| 使用可公开访问的远程服务器,但在本地触发工具调用 | 2. Streamable HTTP |
| 使用本地运行的 Streamable HTTP 服务器 | 2. Streamable HTTP |
| 将任意 Streamable HTTP 服务器与非 OpenAI Responses 模型一起使用 | 2. Streamable HTTP |
| 使用仅支持标准 I/O 协议的本地 MCP 服务器 | 3. Stdio |
1. 远程 MCP 服务器工具
Section titled “1. 远程 MCP 服务器工具”托管工具会将整个往返过程交给模型处理。你的代码无需调用 MCP 服务器,而是由 OpenAI Responses API 调用远程工具端点,并将结果流式传输回模型。
下面是使用远程 MCP 服务器工具的最简单示例。你可以将远程 MCP 服务器的标签和 URL 传递给 hostedMcpTool 工具函数,这有助于创建远程 MCP 服务器工具。
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: 'deepwiki', serverUrl: 'https://mcp.deepwiki.com/mcp', }), ],});然后,你可以使用 run 函数(或你自定义的 Runner 实例的 run 方法)运行智能体:
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:
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);可选审批流程
Section titled “可选审批流程”对于敏感操作,可以要求人工审批单个工具调用。传入 requireApproval: 'always',或传入一个细粒度对象,将工具名称映射到 'never'/'always'。
如果可以通过程序判断某个工具调用是否安全,可以使用 onApproval 回调来批准或拒绝该工具调用。如果需要人工审批,可以采用与本地函数工具相同的人机协作方式使用 interruptions。
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: 'deepwiki', serverUrl: 'https://mcp.deepwiki.com/mcp', // 'always' | 'never' | { never, always } requireApproval: { never: { toolNames: ['read_wiki_structure', 'read_wiki_contents'], }, always: { toolNames: ['ask_question'], }, }, }), ], });
let result = await run( agent, 'For the repository openai/codex, tell me the primary programming language.', ); 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);远程 MCP 选项参考
Section titled “远程 MCP 选项参考”hostedMcpTool(...) 同时支持 MCP 服务器 URL 和由连接器支持的服务器:
| 选项 | 类型 | 说明 |
|---|---|---|
serverLabel | string | 必填标签,用于在事件和追踪中标识托管 MCP 服务器。 |
serverUrl | string | 远程 MCP 服务器 URL(普通托管 MCP 服务器使用此项)。 |
connectorId | string | OpenAI 连接器 ID(对于由连接器支持的托管服务器,使用此项而不是 serverUrl)。 |
authorization | string | 发送给托管 MCP 后端的可选授权令牌。 |
headers | Record<string, string> | 可选的额外请求头。 |
allowedTools | string[] | object | 向模型公开的工具名称允许列表。传入 string[] 或 { toolNames?: string[] }。 |
deferLoading | boolean | 仅 Responses 支持的远程 MCP 服务器工具延迟加载。需要在同一个智能体中使用 toolSearchTool()。 |
requireApproval | 'never' | 'always' | object | 远程 MCP 服务器工具调用的审批策略。使用对象形式进行每工具覆盖。默认为 'never'。 |
onApproval | 审批回调 | 当 requireApproval 需要审批处理时,用于以编程方式批准/拒绝的可选回调。 |
当你希望模型通过工具搜索按需加载远程 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;}> {}由连接器支持的托管服务器
Section titled “由连接器支持的托管服务器”托管 MCP 也支持 OpenAI 连接器。无需提供 serverUrl,而是传入连接器的 connectorId 和 authorization 令牌。随后 Responses API 会处理身份验证,并通过托管 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。
智能体级 MCP 配置
Section titled “智能体级 MCP 配置”除了选择传输方式,还可以通过设置 Agent.mcpConfig 来调整本地 MCP 工具的准备方式。
const agent = new Agent({ name: 'Assistant', mcpServers: [server], mcpConfig: { // Try to convert MCP tool schemas to strict JSON schema. convertSchemasToStrict: true, // Set to null to raise MCP tool failures instead of returning model-visible error text. errorFunction: null, // Prefix local MCP tool names with their server name. includeServerInToolNames: true, },});说明:
convertSchemasToStrict采用尽力而为策略。如果某个 schema 无法转换,将使用原始 schema。errorFunction控制如何向模型呈现 MCP 工具调用失败。- 未设置
errorFunction时,SDK 会使用默认工具错误格式化器。 - 服务器级
errorFunction值会覆盖该服务器的Agent.mcpConfig.errorFunction。 includeServerInToolNames需显式启用。启用后,每个本地 MCP 工具都会以确定性的服务器前缀名称公开给模型,这有助于在多个 MCP 服务器发布同名工具时避免冲突。
2. Streamable HTTP MCP 服务器
Section titled “2. Streamable HTTP MCP 服务器”当智能体直接与 Streamable HTTP MCP 服务器(本地或远程)通信时,使用服务器的 url、name 和任何可选设置实例化 MCPServerStreamableHttp:
import { Agent, run, MCPServerStreamableHttp } from '@openai/agents';
async function main() { const mcpServer = new MCPServerStreamableHttp({ url: 'https://mcp.deepwiki.com/mcp', name: 'DeepWiki MCP Server', }); const agent = new Agent({ name: 'DeepWiki Assistant', instructions: 'Use the tools to respond to user requests.', mcpServers: [mcpServer], });
try { await mcpServer.connect(); const result = await run( agent, 'For the repository openai/codex, tell me the primary programming language.', ); console.log(result.finalOutput); } finally { await mcpServer.close(); }}
main().catch(console.error);构造函数选项:
| 选项 | 类型 | 说明 |
|---|---|---|
url | string | Streamable HTTP 服务器 URL。 |
name | string | 服务器的可选标签。 |
cacheToolsList | boolean | 缓存工具列表以降低延迟。 |
clientSessionTimeoutSeconds | number | MCP 客户端会话超时时间。 |
toolFilter | MCPToolFilterCallable | MCPToolFilterStatic | 过滤可用工具。 |
toolMetaResolver | MCPToolMetaResolver | 注入每次调用的 MCP _meta 请求字段。 |
customDataExtractor | MCPToolCustomDataExtractor | 将仅供 SDK 使用的 JSON 元数据附加到发出的本地 MCP 工具输出项。该回调可以读取 MCP 结果 _meta、structuredContent、isError 以及模型可见的工具输出。 |
errorFunction | MCPToolErrorFunction | null | 将 MCP 调用失败映射为模型可见文本。 |
timeout | number | 每个请求的超时时间(毫秒)。 |
logger | Logger | 自定义日志记录器。 |
authProvider | OAuthClientProvider | 来自 MCP TypeScript SDK 的 OAuth 提供程序。 |
requestInit | RequestInit | 请求的 Fetch 初始化选项。 |
fetch | FetchLike | 自定义 fetch 实现。 |
reconnectionOptions | StreamableHTTPReconnectionOptions | 重连调优选项。 |
sessionId | string | MCP 连接的显式会话 ID。 |
构造函数还接受其他 MCP TypeScript SDK 选项,例如 authProvider、requestInit、fetch、reconnectionOptions 和 sessionId。详情请参见 MCP TypeScript SDK 仓库及其文档。
3. Stdio MCP 服务器
Section titled “3. Stdio MCP 服务器”对于仅公开标准 I/O 的服务器,使用 fullCommand 实例化 MCPServerStdio:
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 local package', fullCommand: `pnpm exec mcp-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 / args | string / string[] | stdio 服务器的命令 + 参数。 |
fullCommand | string | 可替代 command + args 的完整命令字符串。 |
env | Record<string, string> | 服务器进程的环境变量。 |
cwd | string | 服务器进程的工作目录。 |
cacheToolsList | boolean | 缓存工具列表以降低延迟。 |
clientSessionTimeoutSeconds | number | MCP 客户端会话超时时间。 |
name | string | 服务器的可选标签。 |
encoding | string | stdio 流的编码。 |
encodingErrorHandler | 'strict' | 'ignore' | 'replace' | 编码错误处理策略。 |
toolFilter | MCPToolFilterCallable | MCPToolFilterStatic | 过滤可用工具。 |
toolMetaResolver | MCPToolMetaResolver | 注入每次调用的 MCP _meta 请求字段。 |
customDataExtractor | MCPToolCustomDataExtractor | 将仅供 SDK 使用的 JSON 元数据附加到发出的本地 MCP 工具输出项。该回调可以读取 MCP 结果 _meta、structuredContent、isError 以及模型可见的工具输出。 |
errorFunction | MCPToolErrorFunction | null | 将 MCP 调用失败映射为模型可见文本。 |
timeout | number | 每个请求的超时时间(毫秒)。 |
logger | Logger | 自定义日志记录器。 |
MCP 服务器生命周期管理
Section titled “MCP 服务器生命周期管理”使用多个 MCP 服务器时,可以使用 connectMcpServers 统一连接它们、跟踪失败并集中关闭。该辅助函数会返回一个 MCPServers 实例,其中包含 active、failed 和 errors 集合,因此你可以只将健康的服务器传递给智能体。
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 选项:
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
connectTimeoutMs | number | null | 10000 | 每个服务器 connect() 的超时时间。使用 null 可禁用。 |
closeTimeoutMs | number | null | 10000 | 每个服务器 close() 的超时时间。使用 null 可禁用。 |
dropFailed | boolean | true | 从 active 中排除失败的服务器。 |
strict | boolean | false | 如果任何服务器连接失败,则抛出错误。 |
suppressAbortError | boolean | true | 忽略类似 abort 的错误,但仍会跟踪失败的服务器。 |
connectInParallel | boolean | false | 并发连接所有服务器,而不是按顺序连接。 |
mcpServers.reconnect(options) 支持:
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
failedOnly | boolean | true | 仅重试失败的服务器(true),或重新连接所有服务器(false)。 |
异步释放(可选)
Section titled “异步释放(可选)”如果运行时支持 Symbol.asyncDispose,MCPServers 也支持 await using 模式。在 TypeScript 中,请在 tsconfig.json 中启用 esnext.disposable:
{ "compilerOptions": { "lib": ["ES2018", "DOM", "esnext.disposable"] }}然后可以编写:
await using mcpServers = await connectMcpServers(servers);其他注意事项
Section titled “其他注意事项”对于 Streamable HTTP 和 Stdio 服务器,每次 Agent 运行时,都可能调用 list_tools() 来发现可用工具。由于这次往返可能增加延迟(尤其是在访问远程服务器时),你可以通过向 MCPServerStdio 或 MCPServerStreamableHttp 传入 cacheToolsList: true,将结果缓存在内存中。
只有在确信工具列表不会变化时才启用此功能。若要稍后使缓存失效,请在服务器实例上调用 invalidateToolsCache()。如果你通过 getAllMcpTools(...) 使用共享 MCP 工具缓存,也可以使用 invalidateServerToolsCache(serverName) 按服务器名称使缓存失效。
在高级场景中,getAllMcpTools({ generateMCPToolCacheKey }) 允许你自定义缓存分区(例如,按服务器 + 智能体 + 运行上下文)。
带服务器前缀的工具名称
Section titled “带服务器前缀的工具名称”默认情况下,本地 MCP 工具会保留 MCP 服务器报告的工具名称。如果两个本地 MCP 服务器公开了相同的工具名称,SDK 会抛出重复工具名称错误,因为模型无法安全地在它们之间选择。
若要启用确定性的服务器前缀名称,请在智能体上设置 mcpConfig.includeServerInToolNames: true:
const agent = new Agent({ name: 'Assistant', mcpServers: [docsServer, calendarServer], mcpConfig: { includeServerInToolNames: true, },});使用此设置后,来自 docs 服务器的 search 工具会以 mcp_docs__search 的名称公开给模型,而来自 calendar 服务器的 search 工具会以 mcp_calendar__search 的名称公开。SDK 仍会在原始服务器上调用原始 MCP 工具名称。
生成的名称是 ASCII 安全的,会保持在函数工具名称长度限制内,并避开同一智能体上的本地函数工具名称和已启用的交接名称。此设置仅影响本地 Streamable HTTP 和 stdio MCP 工具;远程 MCP 服务器工具会保留其托管服务器标签和工具元数据。
可以通过 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',});- Model Context Protocol – 官方规范。
- examples/mcp – 上文引用的可运行演示。