コンテンツにスキップ

MCP 連携

The Model Context Protocol (MCP) は、アプリケーションが LLMs にツールとコンテキストを提供する方法を標準化するオープンプロトコルです。MCP のドキュメントより:

MCP is an open protocol that standardizes how applications provide context to LLMs. Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect your devices to various peripherals and accessories, MCP provides a standardized way to connect AI models to different data sources and tools.

この SDK がサポートする MCP サーバーは 3 種類あります:

  1. リモート MCP サーバーツールOpenAI Responses API がツールとして利用するリモート MCP サーバー
  2. Streamable HTTP MCP サーバーStreamable HTTP トランスポート を実装したローカルまたはリモートのサーバー
  3. Stdio MCP サーバー – 標準入出力経由でアクセスするサーバー(最もシンプルな選択肢)

ユースケースに応じてサーバータイプを選択してください:

必要なこと推奨オプション
公開アクセス可能なリモートサーバーを既定の OpenAI Responses モデルで呼び出す1. Hosted MCP tools
公開アクセス可能なリモートサーバーを使うが、ツール呼び出しはローカルでトリガーする2. Streamable HTTP
ローカルで動作する Streamable HTTP サーバーを使う2. Streamable HTTP
非 OpenAI-Responses モデルで任意の Streamable HTTP サーバーを使う2. Streamable HTTP
標準入出力プロトコルのみをサポートするローカル MCP サーバーで作業する3. Stdio

Hosted ツールは、往復の処理全体をモデル内に押し込みます。あなたのコードが MCP サーバーを呼び出す代わりに、OpenAI Responses API がリモートのツールエンドポイントを呼び出し、その結果をモデルへストリーミングします。

以下は Hosted MCP ツールを使う最も簡単な例です。リモート MCP サーバーのラベルと URL を hostedMcpTool ユーティリティ関数に渡します。これは Hosted 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.rawItem.name;
const params = item.rawItem.providerData?.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);

Hosted MCP は OpenAI コネクタにも対応しています。serverUrl を提供する代わりに、コネクタの connectorIdauthorization トークンを渡します。Responses API が認証を処理し、Hosted MCP インターフェースを通じてコネクタのツールを公開します。

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 トークンが格納されており、コネクタ対応サーバーが Calendar API を呼び出すための認可を与えます。ストリーミングもあわせて実演する実行可能なサンプルは、examples/connectors を参照してください。

完全な動作サンプル(Hosted ツール/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);

コンストラクタは、authProviderrequestInitfetchreconnectionOptionssessionId などの MCP TypeScript SDK の追加オプションも受け付けます。詳細は MCP TypeScript SDK リポジトリとそのドキュメントを参照してください。

標準入出力のみを公開するサーバーには、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() を呼び出す場合があります。この往復は、特にリモートサーバーではレイテンシーを増加させる可能性があるため、MCPServerStdio または MCPServerStreamableHttpcacheToolsList: 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',
});