コンテンツにスキップ

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 トランスポート向けの MCPServerSSE も含まれますが、SSE は MCP プロジェクトで非推奨になっています。新しい連携では Streamable HTTP または stdio を推奨します。

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

必要なこと推奨オプション
デフォルトの OpenAI responses models で公開リモートサーバーを呼び出す1. Hosted MCP tools
公開リモートサーバーを使いつつ、ツール呼び出しはローカルでトリガーしたい2. Streamable HTTP
ローカルで実行中の Streamable HTTP サーバーを使う2. Streamable HTTP
non-OpenAI-Responses models で任意の Streamable HTTP サーバーを使う2. Streamable HTTP
標準 I/O プロトコルのみをサポートするローカル 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 を実行できます:

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 { 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 callback を使ってツール呼び出しを承認または拒否できます。人間の承認が必要な場合は、ローカル関数ツールと同様に interruptions を使う同じ human-in-the-loop (HITL) approach を利用できます。

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.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 と connector-backed サーバーの両方をサポートします:

OptionTypeNotes
serverLabelstring必須。イベントやトレースで Hosted MCP サーバーを識別するラベル
serverUrlstringリモート MCP サーバー URL(通常の Hosted MCP サーバーで使用)
connectorIdstringOpenAI connector id(connector-backed Hosted サーバーでは serverUrl の代わりに使用)
authorizationstringHosted MCP バックエンドに送信する任意の認可トークン
headersRecord<string, string>任意の追加リクエストヘッダー
allowedToolsstring[] | objectモデルに公開するツール名の許可リスト。string[] または { toolNames?: string[] } を指定
deferLoadingbooleanHosted MCP ツール向けの Responses 専用遅延ロード。同じ agent に toolSearchTool() が必要
requireApproval'never' | 'always' | objectHosted MCP ツール呼び出しの承認ポリシー。ツール単位の上書きは object 形式を使用。既定値は 'never'
onApprovalApproval callbackrequireApproval で承認処理が必要な場合の、プログラムによる承認/拒否用の任意 callback

deferLoading: true を設定すると、Hosted MCP サーバーのツール定義を最初から公開する代わりに、モデルが tool search 経由で必要時に読み込めます。これは OpenAI Responses API でのみ動作し、同じリクエストに toolSearchTool() が必要で、GPT-5.4 以降の対応モデルリリースと併用する必要があります。遅延ロード設定の詳細は Tools guide を参照してください。

requireApproval の object 形式:

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

onApproval シグネチャ:

async function onApproval(
context,
item,
): Promise<{
approve: boolean;
reason?: string;
}> {}

Hosted MCP は OpenAI connectors もサポートします。serverUrl を指定する代わりに、connector の connectorIdauthorization トークンを渡します。すると Responses API が認証を処理し、Hosted MCP インターフェースを通じて connector のツールを公開します。

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 トークンを入れています。これにより connector-backed サーバーが Calendar API を呼び出せます。ストリーミングも示す実行可能なサンプルは examples/connectors を参照してください。

完全に動作するサンプル(Hosted tools / Streamable HTTP / stdio + Streaming, HITL, onApproval)は、GitHub リポジトリの examples/mcp にあります。

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

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

OptionTypeNotes
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 repository とそのドキュメントを参照してください。

標準 I/O のみを公開するサーバーでは、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);

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

OptionTypeNotes
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 に渡せます。

Manage multiple MCP servers
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 オプション:

OptionTypeDefaultNotes
connectTimeoutMsnumber | null10000各サーバー connect() のタイムアウト。無効化は null
closeTimeoutMsnumber | null10000各サーバー close() のタイムアウト。無効化は null
dropFailedbooleantrue失敗サーバーを active から除外
strictbooleanfalseいずれかのサーバー接続失敗時に throw
suppressAbortErrorbooleantrue失敗サーバーの追跡は維持しつつ、abort 類似エラーを無視
connectInParallelbooleanfalse順次ではなく全サーバーを同時接続

mcpServers.reconnect(options) のサポート:

OptionTypeDefaultNotes
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 による静的フィルター、またはカスタム関数で制限できます。以下は両方の方法を組み合わせた例です:

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