MCP_TOOL_TIMEOUTを設定しても5分で切れるAgent SDKのMCPツール呼び出し
Agent SDK TypeScriptでMCP_TOOL_TIMEOUTを伸ばしてもMCPツール呼び出しが5分で失敗する既知報告と、原因が一致する公式修正、確認しておきたい設定をまとめます。
@anthropic-ai/claude-agent-sdk で MCP_TOOL_TIMEOUT を長く設定しても、HTTP/SSE経由のMCPツール呼び出しが5分(300秒)ちょうどで失敗する報告がありました。原因として報告者が挙げたのはNode.jsの通信基盤undiciの既定タイムアウトです。この記事では報告内容と、同じ症状を直したとみられる公式changelogの記録、そして修正後も5分で切れうる別のタイマーを取り上げます。
5分で切れたとき、どのタイマーが効いているか
MCPツール呼び出しには、止める理由の違うタイマーが複数あります。症状の出方から順に絞り込めます。
5分前後で失敗したときの切り分け
- 1
SDKのバージョンを見る
入っている版は
package.jsonかロックファイルで読めます。0.3.274より前なら、Streamable HTTPの約5分切断が未修正の版です。 - 2
切れるまでの時間を見る
ちょうど60秒なら、HTTP/SSE/コネクター向けのリクエスト単位タイマーです。5分(300秒)なら、無応答を検出するアイドルタイムアウトか、未修正版の切断です。
- 3
サーバー種別と進捗通知を見る
HTTP・SSE・WebSocket・コネクターのサーバーは、応答も進捗通知も5分止まると打ち切られます(stdioは30分)。サーバーが進捗通知を送る実装なら、そのたびにタイマーが戻ります。
- 4
対応する設定を上げる
アイドルなら
CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUTを伸ばすか0で無効にします。60秒ならMCP_TOOL_TIMEOUT、MCP_TIMEOUT、サーバー個別のtimeoutのいずれかを60000超にします。
GitHub issueが報告する症状
2026年1月5日、claude-agent-sdk-typescript リポジトリのissue #118として次の報告が上がりました。E2Bサンドボックス上で @anthropic-ai/claude-agent-sdk v0.1.65〜v0.1.76を使い、settings.json の env セクションで MCP_TOOL_TIMEOUT=1200000(20分)を設定した状態です。長時間実行のMCPツールを呼び出すと、次のログを残して失敗します。
[DEBUG] MCP server "deep-research": Tool 'get_results' failed after 300s: fetch failed
[ERROR] TypeError: fetch failed
at node:internal/deps/undici/undici:14900:13設定した20分(1,200,000ミリ秒)を待たず、ちょうど300秒で fetch failed が出ています。issueのタイトルは原因を「undiciの既定headersTimeoutがMCP_TOOL_TIMEOUTより優先される」としています。このissueはopenのままで、コメントは0件、Anthropicからの反応も付いていません。単独の報告である点は踏まえておく必要があります。
報告者の原因診断 — undiciの既定headersTimeout
スタックトレースが指しているのは、Node.js組み込みの fetch() を実装するundiciのコード位置です。undiciのHTTPクライアントには、リクエストを送ってから応答ヘッダーが届くまでの上限を区切る headersTimeout があり、既定値は300,000ミリ秒(5分)です。CLIが内部でMCPサーバーへ送るリクエストがこの既定値を上書きしていなければ、MCP_TOOL_TIMEOUT を伸ばしても通信層のタイムアウトが先に効きます。
issue本文には、この推定を裏付ける追加コードはありません。報告者自身の解釈です。
Claude Code側のドキュメントにも、似た構造が書かれています。HTTP・SSE・claude.aiコネクターのサーバーには、ツール全体の制限とは別に「各リクエストをサーバーの最初の応答バイトまで待つタイマー」があります。このタイマーは、60秒、そのサーバーに適用されるツールタイムアウト、MCP_TIMEOUT のうち最大のものに設定されます。stdioとWebSocketのサーバーにはありません。
公式changelogの修正を年表で追う
code.claude.com/docs/en/changelog には、この系統の不具合を直した記録が時期をずらして3つ残っています。症状の数字(60秒・5分)が違うので、読み分けが要ります。
MCPタイムアウト関連の修正
- 2026年5月14日v2.1.142 — 60秒の壁
MCP_TOOL_TIMEOUTがリモートHTTP/SSEサーバーのリクエスト単位タイマーを引き上げず、設定値にかかわらずツール呼び出しが60秒で頭打ちになる不具合を修正しました。 - 2026年6月23日v2.1.187 — 無応答5分で中断
リモートMCPツール呼び出しが無応答のまま止まる場合に、5分でエラー終了するようになりました。
CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUTで上書きできます。 - 2026年9月17日v2.1.274 — Streamable HTTPの約5分
サーバー個別の
timeoutを長く設定していても、Streamable HTTP経由のMCPツール呼び出しが約5分でタイムアウトする不具合を修正しました。
最後の記録が、issue #118の症状に最も近いものです。Agent SDK TypeScriptの変更履歴では、v0.3.274が「Updated to parity with Claude Code v2.1.274」と記録されています。npmへの公開は2026年9月16日(UTC)で、この修正はSDK v0.3.274以降に入っています。
changelogはissue #118に触れていません。ただし「約5分」「長く設定したタイムアウトが効かない」「Streamable HTTP(type: "http" のMCPサーバー)」の3点が揃って一致します。当時の報告と同じ系統の不具合を直したものと見てよさそうです。v2.1.274の修正が入る前の版では、同じ制約が残りえます。
自分の設定がStreamable HTTPに当たるかは、.mcp.json の type で見分けます。http に加えて streamable-http もエイリアスとして受け付けられ、どちらの表記でも同じ通信方式です。
修正後も5分で切れるアイドルタイムアウト
最新版でも、MCP_TOOL_TIMEOUT だけを設定していると5分で切れることがあります。原因は、undiciとは別にClaude Code CLI自身が持つアイドルタイムアウトです。公式ドキュメントは次のように書いています。
A tool call to an MCP server that sends no response and no progress notification for the idle window aborts with an error instead of waiting for the wall-clock limit. [...] The idle window defaults to five minutes for HTTP, SSE, WebSocket, and claude.ai connector servers, and to 30 minutes for stdio servers.
関係する3つのタイマーは、止める理由がまったく別です。
3つのタイマーと調整先
ツール呼び出し全体の壁時計
MCP_TOOL_TIMEOUT(既定は約28時間)か、サーバー個別のtimeoutで決まります。個別のtimeoutは進捗通知があっても延びない固定の上限です。応答が止まっている時間
CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUTで調整します。0を渡すと無効になります。最初の応答バイトまで
HTTP・SSE・コネクターだけにあります。既定は60秒で、
MCP_TOOL_TIMEOUT、MCP_TIMEOUT、サーバー個別のtimeoutのうち最大の値まで上がります。
MCP_TOOL_TIMEOUT を60000未満にしても、リクエスト単位のタイマーは60秒より短くなりません。
アイドルタイムアウトの設定値には、互いの関係があります。CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT は有効な MCP_TOOL_TIMEOUT を上限とし、1000未満は1秒に切り上げられます。サーバー個別の timeout が1000以上なら、そのサーバーのアイドル窓は少なくとも timeout の値まで延びます(v2.1.203以降)。stdioサーバーがアイドルタイムアウトの対象に入ったのも、同じv2.1.203からです。
IDEサーバーとSDKインプロセスサーバーには、アイドルタイムアウトは適用されません。
SDKのenvで上限を渡す
SDKからは env オプションで環境変数をCLIサブプロセスへ渡します。壁時計とアイドルの両方を同じ長さにそろえる例です。
import { query } from "@anthropic-ai/claude-agent-sdk";
const result = query({
prompt: "長時間かかるMCPツールを呼び出す",
options: {
env: {
...process.env,
MCP_TOOL_TIMEOUT: "1200000",
CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT: "1200000",
},
},
});サーバーごとに分けたい場合は、.mcp.json のエントリにミリ秒の timeout を書きます。公式ドキュメントの例は "timeout": 600000(10分)で、MCP_TOOL_TIMEOUT をそのサーバーだけ上書きします。
TypeScriptでSDK内に作るインプロセスサーバーには、createSdkMcpServer() の timeout オプションがあります。1000以上の整数をミリ秒で渡す形で、TypeScript Agent SDK v0.3.248以降が対象です。他の値は無視されます。
MCP_TOOL_TIMEOUT と MCP_TIMEOUT の違いを含めた基本的な既定値と設定例はMCP_TIMEOUTとMCP_TOOL_TIMEOUTの違いにあります。解析に時間のかかる処理を呼ぶstdio型MCPの例としては、Ghidra MCPの設定ガイドが参考になります。
よくあるつまずき
CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUTだけを大きくする: 設定値は有効なMCP_TOOL_TIMEOUTが上限なので、壁時計側が小さいとアイドル側も頭打ちです。1000未満は1秒に切り上げられる点も、ミリ秒で書くときに効きます- サーバー個別の
timeoutが進捗通知で延びると思う: 個別のtimeoutは進捗通知があっても延びない固定の上限です。進捗を返し続ける長時間ツールには、MCP_TOOL_TIMEOUT側を使います MCP_TOOL_TIMEOUTを下げて60秒を短くしようとする: リクエスト単位のタイマーは60秒より短くなりません。60秒を超えて待たせたいときに、MCP_TOOL_TIMEOUT、MCP_TIMEOUT、サーバー個別のtimeoutのいずれかを60000超にしますcreateSdkMcpServerのインプロセスサーバーにアイドル設定を足す: アイドルタイムアウトの対象外なので効きません。上限はtimeoutオプションで決めます。並列呼び出しで起きる別の不具合はMCP Stream closedエラーはAgent SDKの並列呼び出しで起きるにあります
まとめ
進捗通知を送れないサーバーを走らせるなら、MCP_TOOL_TIMEOUT と CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT を同じ値にそろえるのが出発点です。SDK内のインプロセスサーバーなら、createSdkMcpServer() の timeout オプションで上限を決めます。
Agent SDKでのカスタムMCPサーバーの作り方はAgent SDKカスタムツールの作り方にあります。