コンテンツにスキップ

MCP 連携

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 サーバー – 標準入出力でアクセスするサーバー(最もシンプルな選択肢)

注: SDK にはレガシーな Server‑Sent Events トランスポート向けに MCPServerSSE も含まれていますが、SSE は MCP プロジェクトにより非推奨となりました。新規の連携では Streamable HTTP か stdio を推奨します。

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

必要なこと推奨オプション
公開アクセス可能なリモートサーバーを既定の OpenAI Responses モデルで呼び出したい1. リモート MCP サーバーツール
公開アクセス可能なリモートサーバーを使いたいが、ツール呼び出しはローカルで開始したい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 ツールを使う最も簡単な例です。hostedMcpTool ユーティリティ関数にリモート MCP サーバーのラベルと URL を渡すことで、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 ツールで実行
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 ツールで実行(ストリーミング)
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) アプローチを使用できます。

Hosted 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.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 コネクター ID(コネクター連携の Hosted サーバーでは serverUrl の代わりにこちらを使用)
authorizationstringHosted MCP バックエンドに送信する任意の認可トークン
headersRecord<string, string>追加のリクエストヘッダー(任意)
allowedToolsstring[] | objectモデルに公開するツール名の許可リスト。string[] または { toolNames?: string[] } を渡す
requireApproval'never' | 'always' | objectHosted MCP ツール呼び出しの承認ポリシー。ツール単位で上書きする場合はオブジェクト形式。既定は 'never'
onApproval(context, item) => Promise<{ approve: boolean; reason?: string }>requireApproval が承認処理を要求する場合の、プログラムによる承認/拒否の任意コールバック

requireApproval のオブジェクト形式:

{
always?: { toolNames: string[] };
never?: { toolNames: string[] };
}

コネクター連携の Hosted サーバー

Section titled “コネクター連携の Hosted サーバー”

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

コネクター連携の Hosted MCP ツール
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 にあります。

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 接続の明示的なセッション ID

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

標準入出力のみを公開するサーバーには、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);

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

オプション備考
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 を使って一括接続し、失敗を追跡し、まとめてクローズできます。 このヘルパーは activefailederrors コレクションを持つ MCPServers インスタンスを返すため、エージェントには正常なサーバーだけを渡せます。

複数の 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);

ユースケース:

  • 複数サーバーを同時に: すべてを並列接続し、エージェントには mcpServers.active を使用
  • 部分的な失敗の処理: failederrors を検査し、続行か再試行かを判断
  • 失敗サーバーの再試行: mcpServers.reconnect() を呼ぶ(既定で失敗サーバーのみ再試行)

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

connectMcpServers のオプション:

オプション既定値備考
connectTimeoutMsnumber | null10000各サーバーの connect() タイムアウト。無効化するには null
closeTimeoutMsnumber | null10000各サーバーの close() タイムアウト。無効化するには null
dropFailedbooleantrueactive から失敗サーバーを除外
strictbooleanfalseいずれかのサーバー接続が失敗したら例外を投げる
suppressAbortErrorbooleantrue中断系エラーを無視しつつ、失敗サーバーは追跡
connectInParallelbooleanfalse逐次ではなく全サーバーを同時に接続

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

オプション既定値備考
failedOnlybooleantrue失敗サーバーのみ再試行するか(true)、全再接続か(false

非同期ディスポーザブル(任意)

Section titled “非同期ディスポーザブル(任意)”

実行環境が 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 }) により、(サーバー + エージェント + 実行コンテキストなどで)キャッシュの分割方法をカスタマイズできます。

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