跳转到内容

MCP 集成

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

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

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

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

注意:SDK 也包含用于遗留 Server‑Sent Events 传输的 MCPServerSSE,但 SSE 已被 MCP 项目弃用。新的集成应优先选择 Streamable HTTP 或 stdio。

请根据你的用例选择服务器类型:

你的需求推荐选项
使用默认的 OpenAI responses 模型调用可公开访问的远程服务器1. Hosted MCP tools
使用可公开访问的远程服务器,但在本地触发工具调用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 方法)来运行智能体:

Run with hosted MCP tools
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

Run with hosted MCP tools (streaming)
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?',
{ stream: true },
);
for await (const event of result) {
if (
event.type === 'raw_model_stream_event' &&
event.data.type === 'model' &&
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)方法

Human in the loop with hosted MCP tools
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);

托管 MCP 也支持 OpenAI connectors。无需提供 serverUrl,而是传入 connector 的 connectorIdauthorization 令牌。Responses API 将处理认证,并通过托管 MCP 接口暴露该 connector 的工具。

Connector-backed hosted MCP tool
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 令牌,它授权基于 connector 的服务器调用 Calendar API。要查看也演示了流式传输的可运行示例,请参阅 examples/connectors

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

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

Run with Streamable HTTP MCP servers
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);

构造函数还接受其他 MCP TypeScript‑SDK 选项,例如 authProviderrequestInitfetchreconnectionOptionssessionId。详情请参阅 MCP TypeScript SDK 仓库及其文档。

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

Run with Stdio MCP servers
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);

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

仅当你确定工具列表不会变化时才启用此功能。若需稍后使缓存失效,请在服务器实例上调用 invalidateToolsCache()

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

Tool filtering
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',
});