コンテンツにスキップ

MCP 連携

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 transport を実装するローカルまたはリモートのサーバー
  3. 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

Hosted tool は往復処理全体をモデル側に委ねます。コードが MCP サーバーを呼び出す代わりに、OpenAI Responses API がリモートツールエンドポイントを呼び出し、その結果をモデルにストリーミングで返します。

以下は Hosted MCP tool を使うもっともシンプルな例です。リモート 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 メソッド)で Agent を実行できます:

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 を渡します:

Hosted MCP tools で実行(ストリーミング)
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);

機密性の高い操作では、個々のツール呼び出しに人間の承認を必須にできます。requireApproval: 'always' を渡すか、ツール名ごとに 'never' / 'always' を対応付ける細かなオブジェクトを渡してください。

ツール呼び出しが安全かどうかをプログラムで判定できる場合は、onApproval コールバック を使ってツール呼び出しを承認または拒否できます。人間の承認が必要な場合は、ローカル関数ツールと同様に interruptions を使った同じ human-in-the-loop (HITL) アプローチ を使用できます。

Hosted MCP tools での 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.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 とコネクターバックのサーバーの両方をサポートします:

オプション注記
serverLabelstring必須。イベントやトレース内で Hosted MCP サーバーを識別するラベル
serverUrlstringリモート MCP サーバー URL(通常の Hosted MCP サーバーではこれを使用)
connectorIdstringOpenAI connector id(コネクターバックの Hosted サーバーでは serverUrl の代わりに使用)
authorizationstring任意。Hosted MCP バックエンドに送信する認可トークン
headersRecord<string, string>任意の追加リクエストヘッダー
allowedToolsstring[] | objectモデルに公開するツール名の許可リスト。string[] または { toolNames?: string[] } を渡します
deferLoadingbooleanHosted MCP tools 向けの Responses 専用遅延読み込み。同じ Agent 内で toolSearchTool() が必要です
requireApproval'never' | 'always' | objectHosted MCP tool 呼び出しの承認ポリシー。ツールごとの上書きにはオブジェクト形式を使用します。デフォルトは 'never' です
onApprovalApproval 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 の connectorIdauthorization トークンを渡します。すると Responses API が認証を処理し、Hosted MCP インターフェース経由で connector のツールを公開します。

コネクターバックの 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 tools / Streamable HTTP / stdio + ストリーミング、HITL、onApproval)は、GitHub リポジトリの examples/mcp にあります。

Agent が 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);

コンストラクターオプション:

オプション注記
urlstringStreamable HTTP サーバー URL
namestringサーバーの任意ラベル
cacheToolsListbooleanレイテンシ削減のためにツール一覧をキャッシュ
clientSessionTimeoutSecondsnumberMCP クライアントセッションのタイムアウト
toolFilterMCPToolFilterCallable | MCPToolFilterStatic利用可能なツールをフィルタリング
toolMetaResolverMCPToolMetaResolver呼び出しごとの MCP _meta リクエストフィールドを注入
errorFunctionMCPToolErrorFunction | nullMCP 呼び出し失敗をモデルに見えるテキストへマッピング
timeoutnumberリクエストごとのタイムアウト(ミリ秒)
loggerLoggerカスタムロガー
authProviderOAuthClientProviderMCP TypeScript SDK の OAuth プロバイダー
requestInitRequestInitリクエスト用の Fetch 初期化オプション
fetchFetchLikeカスタム fetch 実装
reconnectionOptionsStreamableHTTPReconnectionOptions再接続調整オプション
sessionIdstringMCP 接続用の明示的な session id

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

標準 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 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 / argsstring / string[]stdio サーバー向けのコマンド + 引数
fullCommandstringcommand + args の代替となる完全なコマンド文字列
envRecord<string, string>サーバープロセス用の環境変数
cwdstringサーバープロセスの作業ディレクトリ
cacheToolsListbooleanレイテンシ削減のためにツール一覧をキャッシュ
clientSessionTimeoutSecondsnumberMCP クライアントセッションのタイムアウト
namestringサーバーの任意ラベル
encodingstringstdio ストリームのエンコーディング
encodingErrorHandler'strict' | 'ignore' | 'replace'エンコーディングエラー時の戦略
toolFilterMCPToolFilterCallable | MCPToolFilterStatic利用可能なツールをフィルタリング
toolMetaResolverMCPToolMetaResolver呼び出しごとの MCP _meta リクエストフィールドを注入
errorFunctionMCPToolErrorFunction | nullMCP 呼び出し失敗をモデルに見えるテキストへマッピング
timeoutnumberリクエストごとのタイムアウト(ミリ秒)
loggerLoggerカスタムロガー

MCP サーバーライフサイクル管理

Section titled “MCP サーバーライフサイクル管理”

複数の MCP サーバーを扱う場合は、connectMcpServers を使ってまとめて接続し、失敗を追跡し、1 か所で閉じることができます。このヘルパーは activefailederrors の各コレクションを持つ MCPServers インスタンスを返すので、正常なサーバーだけを Agent に渡せます。

複数の MCP サーバーを管理
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 を使用
  • 部分的な失敗の処理: failederrors を確認し、続行するか再試行するかを判断
  • 失敗したサーバーの再試行: mcpServers.reconnect() を呼び出し(デフォルトでは失敗したサーバーのみ再試行)

厳密な「すべて成功か、すべて失敗か」の接続や異なるタイムアウトが必要な場合は、connectMcpServers(servers, options) を使い、環境に合わせてオプションを調整してください。

connectMcpServers のオプション:

オプションデフォルト注記
connectTimeoutMsnumber | null10000各サーバー connect() のタイムアウト。無効化するには null を使用
closeTimeoutMsnumber | null10000各サーバー close() のタイムアウト。無効化するには null を使用
dropFailedbooleantrue失敗したサーバーを active から除外
strictbooleanfalseいずれかのサーバー接続が失敗した場合に例外を投げる
suppressAbortErrorbooleantrue中断系のエラーは無視しつつ、失敗したサーバーの追跡は継続
connectInParallelbooleanfalse順次ではなく、すべてのサーバーを同時接続

mcpServers.reconnect(options) がサポートするオプション:

オプションデフォルト注記
failedOnlybooleantrue失敗したサーバーのみ再試行(true)またはすべてのサーバーを再接続(false

ランタイムが Symbol.asyncDispose をサポートしている場合、MCPServersawait using パターンもサポートします。TypeScript では、tsconfig.jsonesnext.disposable を有効にしてください:

{
"compilerOptions": {
"lib": ["ES2018", "DOM", "esnext.disposable"]
}
}

その後、次のように書けます:

await using mcpServers = await connectMcpServers(servers);

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

これを有効にするのは、ツール一覧が変わらないと確信できる場合だけにしてください。あとでキャッシュを無効化するには、サーバーインスタンスの invalidateToolsCache() を呼び出します。getAllMcpTools(...) による共有 MCP ツールキャッシュを使っている場合は、invalidateServerToolsCache(serverName) によりサーバー名で無効化することもできます。

高度なケースでは、getAllMcpTools({ generateMCPToolCacheKey }) によってキャッシュの分割方法をカスタマイズできます(たとえば、サーバー + Agent + 実行コンテキストごとなど)。

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