MCP 連携
Model Context Protocol (MCP) は、アプリケーションが LLM にツールやコンテキストを提供する方法を標準化するオープンプロトコルです。MCP のドキュメントより:
MCP は、アプリケーションが LLM にコンテキストを提供する方法を標準化するオープンプロトコルです。MCP は AI アプリケーション向けの USB-C ポートのようなものだと考えてください。USB-C がデバイスをさまざまな周辺機器やアクセサリーに接続するための標準化された方法を提供するのと同様に、MCP は AI モデルをさまざまなデータソースやツールに接続するための標準化された方法を提供します。
この SDK がサポートする MCP サーバーは 3 種類あります:
- リモート MCP サーバーツール – OpenAI Responses API がツールとして使用するリモート MCP サーバー
- Streamable HTTP MCP サーバー – Streamable HTTP transport を実装するローカルまたはリモートのサーバー
- Stdio MCP サーバー – 標準入出力経由でアクセスするサーバー(もっともシンプルな選択肢)
注: SDK には旧来の Server‑Sent Events transport 向けの
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 |
1. リモート MCP サーバーツール
Section titled “1. リモート MCP サーバーツール”Hosted tool は往復処理全体をモデル側に委ねます。コードが MCP サーバーを呼び出す代わりに、OpenAI Responses API がリモートツールエンドポイントを呼び出し、その結果をモデルにストリーミングで返します。
以下は Hosted MCP tool を使うもっともシンプルな例です。リモート MCP サーバーのラベルと URL を hostedMcpTool ユーティリティ関数に渡せます。これは Hosted 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: 'gitmcp', serverUrl: 'https://gitmcp.io/openai/codex', }), ],});次に、run 関数(または独自にカスタマイズした Runner インスタンスの run メソッド)で Agent を実行できます:
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 を使った同じ human-in-the-loop (HITL) アプローチ を使用できます。
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);Hosted MCP オプションリファレンス
Section titled “Hosted MCP オプションリファレンス”hostedMcpTool(...) は、MCP サーバー URL とコネクターバックのサーバーの両方をサポートします:
| オプション | 型 | 注記 |
|---|---|---|
serverLabel | string | 必須。イベントやトレース内で Hosted MCP サーバーを識別するラベル |
serverUrl | string | リモート MCP サーバー URL(通常の Hosted MCP サーバーではこれを使用) |
connectorId | string | OpenAI connector id(コネクターバックの Hosted サーバーでは serverUrl の代わりに使用) |
authorization | string | 任意。Hosted MCP バックエンドに送信する認可トークン |
headers | Record<string, string> | 任意の追加リクエストヘッダー |
allowedTools | string[] | object | モデルに公開するツール名の許可リスト。string[] または { toolNames?: string[] } を渡します |
deferLoading | boolean | Hosted MCP tools 向けの Responses 専用遅延読み込み。同じ Agent 内で toolSearchTool() が必要です |
requireApproval | 'never' | 'always' | object | Hosted MCP tool 呼び出しの承認ポリシー。ツールごとの上書きにはオブジェクト形式を使用します。デフォルトは 'never' です |
onApproval | Approval callback | 任意。requireApproval で承認処理が必要な場合に、プログラムで承認 / 拒否するためのコールバック |
モデルに Hosted MCP サーバーのツール定義を最初から公開するのではなく、tool search 経由で必要時に読み込ませたい場合は、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;}> {}コネクターバックの Hosted サーバー
Section titled “コネクターバックの Hosted サーバー”Hosted MCP は OpenAI connector もサポートします。serverUrl を指定する代わりに、connector の connectorId と authorization トークンを渡します。すると Responses API が認証を処理し、Hosted MCP インターフェース経由で connector のツールを公開します。
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 tools / Streamable HTTP / stdio + ストリーミング、HITL、onApproval)は、GitHub リポジトリの examples/mcp にあります。
2. Streamable HTTP MCP サーバー
Section titled “2. Streamable HTTP MCP サーバー”Agent が Streamable HTTP MCP サーバー(ローカルまたはリモート)と直接やり取りする場合は、サーバーの url、name、および必要に応じたオプションを指定して MCPServerStreamableHttp を生成します:
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);コンストラクターオプション:
| オプション | 型 | 注記 |
|---|---|---|
url | string | Streamable HTTP サーバー URL |
name | string | サーバーの任意ラベル |
cacheToolsList | boolean | レイテンシ削減のためにツール一覧をキャッシュ |
clientSessionTimeoutSeconds | number | MCP クライアントセッションのタイムアウト |
toolFilter | MCPToolFilterCallable | MCPToolFilterStatic | 利用可能なツールをフィルタリング |
toolMetaResolver | MCPToolMetaResolver | 呼び出しごとの MCP _meta リクエストフィールドを注入 |
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 接続用の明示的な session id |
このコンストラクターは、authProvider、requestInit、fetch、reconnectionOptions、sessionId などの追加の MCP TypeScript‑SDK オプションも受け付けます。詳細は MCP TypeScript SDK repository とそのドキュメントを参照してください。
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 リクエストフィールドを注入 |
errorFunction | MCPToolErrorFunction | null | MCP 呼び出し失敗をモデルに見えるテキストへマッピング |
timeout | number | リクエストごとのタイムアウト(ミリ秒) |
logger | Logger | カスタムロガー |
MCP サーバーライフサイクル管理
Section titled “MCP サーバーライフサイクル管理”複数の MCP サーバーを扱う場合は、connectMcpServers を使ってまとめて接続し、失敗を追跡し、1 か所で閉じることができます。このヘルパーは active、failed、errors の各コレクションを持つ MCPServers インスタンスを返すので、正常なサーバーだけを Agent に渡せます。
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);ユースケース:
- 複数サーバーを同時に扱う: すべてを並列接続し、Agent には
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 | 中断系のエラーは無視しつつ、失敗したサーバーの追跡は継続 |
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 }) によってキャッシュの分割方法をカスタマイズできます(たとえば、サーバー + Agent + 実行コンテキストごとなど)。
ツールフィルタリング
Section titled “ツールフィルタリング”各サーバーから公開するツールを制限するには、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 – 上で参照した実行可能なデモ