コンテンツにスキップ

MCP 連携

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

MCP は、アプリケーションが LLM にコンテキストを提供する方法を標準化するオープンなプロトコルです。MCP を AI アプリケーション向けの USB-C ポートだと考えてください。USB-C がデバイスをさまざまな周辺機器やアクセサリに接続する標準化された方法を提供するのと同様に、MCP は AI モデルをさまざまなデータソースやツールに接続する標準化された方法を提供します

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

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

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

必要なこと推奨オプション
既定の OpenAI Responses モデルで公開アクセス可能なリモートサーバーを呼び出す1. リモート MCP サーバーツール
公開アクセス可能なリモートサーバーを使うが、ツール呼び出しはローカルでトリガー2. Streamable HTTP
ローカルで稼働する Streamable HTTP サーバーを使用2. Streamable HTTP
OpenAI Responses 以外のモデルで任意の Streamable HTTP サーバーを使用2. Streamable HTTP
標準 I/O プロトコルのみをサポートするローカルの 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 メソッド)でエージェントを実行できます:

リモート 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 { 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) のアプローチを利用できます。

リモート MCP サーバーツールでの Human in the loop(人間の介入)
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 ツール / 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);

コンストラクターは、authProviderrequestInitfetchreconnectionOptionssessionId などの追加の MCP TypeScript‑SDK オプションも受け付けます。詳細は 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);

Streamable HTTP と Stdio のサーバーでは、Agent を実行するたびに、利用可能なツールを検出するために list_tools() を呼び出す場合があります。特にリモートサーバーでは、この往復がレイテンシの原因となるため、MCPServerStdio または MCPServerStreamableHttpcacheToolsList: true を渡して、結果をメモリにキャッシュできます。

ツール一覧が変わらないと確信できる場合にのみ有効化してください。後でキャッシュを無効化するには、サーバーインスタンスで invalidateToolsCache() を呼び出します。

各サーバーから公開するツールを制限するには、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',
});