CLAUDE_CODE_MCP_STARTUP_WAIT_MSでMCP接続待機を変える
非対話セッションの初回ターンがMCPサーバーの接続を待つ時間を、環境変数で明示的に設定する方法を解説します。
CLAUDE_CODE_MCP_STARTUP_WAIT_MSとは
CLAUDE_CODE_MCP_STARTUP_WAIT_MSは、非対話セッション(claude -pやAgent SDK経由の実行)の初回ターンが、まだ接続中のMCPサーバーをどれだけ待つかをミリ秒単位で指定する環境変数です。Claude Code v2.1.274で追加されました。
この変数を設定すると、待機はまだ接続待ちの全サーバーに一律で適用されます。0を指定すると待機自体をスキップできます。値を設定しない場合は、後述するデフォルトの初回ターン待機がそのまま使われます。
デフォルトの初回ターン待機はどう決まるか
CLAUDE_CODE_MCP_STARTUP_WAIT_MSを設定しない状態では、Claude Codeは接続待ちのMCPサーバーの種類によって待機の扱いを変えます。
| サーバーの種類 | 初回ターンを遅らせるか | 待機のタイムアウト |
|---|---|---|
| stdioサーバー、またはツール一覧のキャッシュがないHTTP/SSEサーバー | 初回ターンを遅らせるか遅らせる(接続完了まで) | 待機のタイムアウトMCP_TIMEOUT(既定30秒)。期限で接続失敗扱い |
| 過去の接続でツール一覧をキャッシュ済みのリモートサーバー | 初回ターンを遅らせるか遅らせない | 待機のタイムアウトなし。初回のツール呼び出し時に接続する |
| インプロセスのSDKサーバー | 初回ターンを遅らせるか遅らせる(接続とツール一覧取得まで) | 待機のタイムアウトMCP_TIMEOUT(既定30秒)。接続試行ごとに適用 |
.mcp.jsonやプラグインなど設定ファイル由来のサーバーは、初期化メッセージ上でpendingと表示されることがよくあります。Agent SDKのoptions.mcpServersにstdio・HTTP・SSEサーバーを渡した場合、初回ターンはこれらのpendingサーバーもMCP_TIMEOUTまで待ちます。options.mcpServersが空か、SDKサーバーしか含まない場合は、待機時間は2秒に短縮されます。
さらにツール検索が有効かどうかでも扱いが変わります。
- ツール検索が有効(既定): 待機の対象は
alwaysLoad: trueを設定してツール検索の遅延対象から除外したサーバーだけです。それ以外のサーバーはバックグラウンドで接続を続けます - ツール検索が無効: 待機は接続待ちの全サーバーが対象になります。
disallowedToolsでToolSearchを除外した場合もこの扱いになります
permissionPromptToolName(CLIでは--permission-prompt-tool)を設定している場合は、上記のどちらであっても初回ターンがそのツールのサーバーの接続をMCP_TIMEOUTまで待ちます。
--permission-prompt-toolサーバーは対象外
CLAUDE_CODE_MCP_STARTUP_WAIT_MSを設定しても、--permission-prompt-tool(Agent SDKではpermissionPromptToolName)で指定したサーバーだけは別枠のままです。このサーバーは値に関わらず、独自のMCP_TIMEOUT待機(既定30秒)を使い続けます。
権限プロンプトの承認判断を担うサーバーの接続を短縮すると、承認フローそのものが壊れかねないための例外です。全体の起動を早めたくてCLAUDE_CODE_MCP_STARTUP_WAIT_MSを短く設定しても、権限プロンプト用サーバーの待機時間はこの変数では変わりません。
CLIの--mcp-configにも似た待機がある
claude -pに--mcp-configを渡すと、Claude Codeは接続待ちのサーバーを初回ターンの前に待ちます。待機の上限は同じくMCP_TIMEOUT(既定30秒)で、この挙動自体はv2.1.221以降で入っています。ツール一覧をキャッシュ済みのリモートサーバーはこの待機をスキップし、system/initでpendingと表示されたまま初回のツール呼び出し時に接続します。
CLAUDE_CODE_MCP_STARTUP_WAIT_MSはこの--mcp-config由来の待機も上書きします。stdio・HTTP・SSEサーバーについては、CLAUDE_CODE_MCP_STARTUP_WAIT_MSの値がMCP_TIMEOUTベースの初回ターン待機に置き換わります。
なお、Claude Codeは--mcp-configの各エントリを起動時に検証し、typeのないurlエントリのような不正な設定は読み込まずスキップします。実行はそのまま続き、スキップされたサーバーはsystem/initのmcp_serversには現れず、mcp_server_errorsフィールドにname・type(unknown_typeやurl_missing_typeなどのカテゴリ)・messageが記録されます。ターミナルで直接実行した場合はWarning: 1 MCP server skipped due to invalid config:という警告もstderrに出ますが、標準エラーをリダイレクトしていたりCIランナーが出力を捕捉している場合はこの警告は出ず、mcp_server_errorsだけが手がかりになります。CLAUDE_CODE_MCP_STARTUP_WAIT_MSを長くしても現れないサーバーは、待機不足ではなく設定エラーでスキップされている可能性を疑う必要があります。
設定方法
Agent SDKではoptions.envに渡します。
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Summarize the failing tests",
options: {
mcpServers: {
// 対象の MCP サーバー
},
env: {
CLAUDE_CODE_MCP_STARTUP_WAIT_MS: "5000",
},
},
})) {
console.log(message);
}CLIから直接使う場合はシェルでエクスポートするか、settings.jsonのenvキーに書きます。
export CLAUDE_CODE_MCP_STARTUP_WAIT_MS="5000"
claude -p "Summarize the failing tests" --mcp-config ./mcp-config.json毎回のセッションに適用したい場合は~/.claude/settings.json(自分だけ)か.claude/settings.json(プロジェクト全体)に書きます。
{
"env": {
"CLAUDE_CODE_MCP_STARTUP_WAIT_MS": "5000"
}
}シェルと設定ファイルの両方で値を設定した場合は、設定ファイル側の値が優先されます。値を確認するには、claudeを起動する前の同じシェルでecho $CLAUDE_CODE_MCP_STARTUP_WAIT_MS(Windows PowerShellならecho $env:CLAUDE_CODE_MCP_STARTUP_WAIT_MS)を実行します。この変数を明示的に取り消す方法は空文字を設定することだけです。シェルのプロファイルが古い値を残している場合は、空文字を明示して上書きします。
どんなときに変えると効くか
| 状況 | 対応 | 理由 |
|---|---|---|
| CIでstdioのMCPサーバーが数百ms〜数秒で確実に立ち上がる | 対応短めの値(例: 2000)に設定 | 理由既定のMCP_TIMEOUT(30秒)より早く初回ターンへ進める |
| リモートMCPサーバーの応答が不安定でタイムアウトが頻発する | 対応長めの値に設定するか、そのサーバーにalwaysLoad: trueを付ける | 理由接続失敗扱いになる前に接続を完了させる |
| MCPサーバーの初回ツール呼び出し時の接続で十分 | 対応0を設定 | 理由初回ターンの待機自体を丸ごと省き、起動を最速にする |
--permission-prompt-toolのサーバーだけ遅い | 対応この変数では変わらない | 理由権限プロンプト用サーバーは常に独自のMCP_TIMEOUTを使う |
0を設定して待機をスキップした場合、まだ接続していないサーバーのツールは初回ターンには現れません。ツール検索が有効なら、それらのサーバーはバックグラウンドで接続を続け、接続が終わり次第ツールが使えるようになります。
system/initメッセージで接続状況を確認する
Agent SDKでは、初回ターンの接続待機が終わったタイミングでsystemメッセージ(subtype: "init")が発行され、各MCPサーバーのstatusがpending / connected / failed / needs-auth / disabledのいずれかで報告されます。CLAUDE_CODE_MCP_STARTUP_WAIT_MSを短く設定するほど、この時点でまだpendingのサーバーが増えることになります。
pendingは失敗を意味しません。次のいずれかに当てはまります。
- まだ接続していない(待機時間内に間に合わなかった)
- ツール一覧がキャッシュから提供されていて、実際の接続は初回のツール呼び出し時に行われる
- 接続の期限が切れた(このケースは
pendingのこともfailedのこともある)
CLAUDE_CODE_MCP_STARTUP_WAIT_MSを短くした結果として本当に使えないサーバーが出ていないかは、failedやneeds-authだけを見て判定します。
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Process data",
options: {
mcpServers: { "data-processor": dataServer },
env: { CLAUDE_CODE_MCP_STARTUP_WAIT_MS: "2000" },
},
})) {
if (message.type === "system" && message.subtype === "init") {
const unavailable = message.mcp_servers.filter(
(s) => s.status === "failed" || s.status === "needs-auth"
);
if (unavailable.length > 0) {
console.warn("Unavailable MCP servers:", unavailable);
}
}
}待機を短くしてもpendingのまま残ったサーバーは、バックグラウンドで接続を続けます。ツール検索が有効なら、接続が完了した時点でそのサーバーのツールが利用可能になります。
起動そのものをブロックする別の設定
CLAUDE_CODE_MCP_STARTUP_WAIT_MSが扱うのは、初期化メッセージが送られたあとの「初回ターンの待機」です。それより前の段階、初期化メッセージが送られる前の接続バッチそのものをブロックしたい場合は、別の変数を使います。
MCP_CONNECTION_NONBLOCKINGを0に設定すると、接続バッチ全体の完了を待ってから起動を進めます。上限は既定5秒で、MCP_CONNECT_TIMEOUT_MS(ミリ秒)で調整できます。この期限までに終わらなかったサーバーはバックグラウンドで接続を続けます- サーバー設定に
alwaysLoad: trueを付けると、そのサーバーのツールをフルスキーマで初回ターンから使える状態にできます(ツール検索の遅延対象から除外されます)。Claude Codeは起動時にそのサーバーのツールを待ちますが、上限は同じ期限が使われ、他のサーバーはその間もバックグラウンドで接続を続けます。このalwaysLoad: trueのサーバーは、MCP_CONNECTION_NONBLOCKINGを既定のままにしていても起動を待たせます(そのサーバーが接続キャッシュから応答している場合は例外です)
MCP_CONNECT_TIMEOUT_MSはMCP_TIMEOUTとは別物です。MCP_TIMEOUTが個々のサーバーの接続試行そのものの上限なのに対し、MCP_CONNECT_TIMEOUT_MSは接続バッチをまとめてスナップショットするまでの上限で、MCP_CONNECTION_NONBLOCKING=0のときとalwaysLoad: trueのサーバーの両方に効きます。
CLAUDE_CODE_MCP_STARTUP_WAIT_MSとMCP_CONNECTION_NONBLOCKINGは別のフェーズを制御するため、両方を組み合わせて使うこともできます。CI環境でどちらのフェーズが遅延の原因になっているかを切り分けるには、まずMCP_CONNECTION_NONBLOCKINGを既定のままにしてCLAUDE_CODE_MCP_STARTUP_WAIT_MSだけを変えてみると、どちらの待機が支配的かが分かります。
MCP_TIMEOUTやTOOL_IDLE_TIMEOUTとの違い
MCP関連の待機・タイムアウト系の環境変数は複数あり、対象のフェーズがそれぞれ異なります。MCP_TIMEOUTとCLAUDE_CODE_MCP_STARTUP_WAIT_MSが扱うのは接続が確立するまでの起動フェーズで、CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUTとMCP_TOOL_TIMEOUTが扱うのは接続が終わったあとのツール実行フェーズです。対象フェーズを一覧にすると次の通りです。
| 変数名 | 対象フェーズ | 既定値 |
|---|---|---|
MCP_TIMEOUT | 対象フェーズサーバー起動(接続確立)そのもの。stdio・HTTP/SSE(キャッシュなし)・SDKサーバーの接続、--permission-prompt-toolサーバーの待機 | 既定値30秒 |
CLAUDE_CODE_MCP_STARTUP_WAIT_MS | 対象フェーズ非対話セッションの初回ターンが接続待ちサーバーを待つ時間(--permission-prompt-toolサーバーは対象外) | 既定値未設定時はMCP_TIMEOUTベースの初回ターン待機を使用 |
MCP_CONNECTION_NONBLOCKING | 対象フェーズ初期化メッセージが送られるより前の、サーバー接続バッチ全体のブロック | 既定値5秒(MCP_CONNECT_TIMEOUT_MSで調整) |
CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT | 対象フェーズ接続後、個々のMCPツール呼び出しが応答も進捗通知も返さないまま放置される時間 | 既定値ネットワーク300,000ミリ秒(5分)、stdio 1,800,000ミリ秒(30分) |
MCP_TOOL_TIMEOUT | 対象フェーズMCPツール実行全体 | 既定値約28時間(HTTP・SSE・claude.aiコネクタはリクエストごとに別途60秒) |
CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS | 対象フェーズ実行中のMCPツール呼び出しをバックグラウンドタスクへ移すまでの経過時間 | 既定値120,000ミリ秒 |
CLAUDE_CODE_MCP_STARTUP_WAIT_MSは「初回ターンをどれだけ待つか」を扱う変数で、接続後のツール実行時間や自動バックグラウンド化には影響しません。目的の挙動に合わせて上の表から選べます。
v2.1.274の関連する修正
CLAUDE_CODE_MCP_STARTUP_WAIT_MSが入ったv2.1.274のchangelogには、MCP接続待機に関わる修正もいくつか含まれています。
--strict-mcp-configを空の--mcp-configと組み合わせたとき、無関係なMCPサーバーのせいで初回の非対話ターンがMCP_TIMEOUTいっぱいまで止まっていたバグを修正--input-format stream-jsonセッションの起動を改善: ツール検索によって接続が遅延されるサーバーについて、初回ターンが最大2秒待たされることがなくなり、それらのツールは後のターンで利用可能になる- クラウドセッションの初回ターンが、まだ接続中のSDKホストMCPサーバーのツールを欠いたまま始まってしまう場合があったのを修正
いずれも「非対話セッションの初回ターンがMCPサーバーの接続をどう扱うか」という同じ領域の変更で、v2.1.274ではCLAUDE_CODE_MCP_STARTUP_WAIT_MSの追加とあわせて、初回ターンの待機まわりの修正が3件同時に入っています。
--bareモードとの関係
claude -pに--bareを付けると、フック・スキル・カスタムコマンド・サブエージェント・インストール済みプラグイン・MCPサーバー・auto memory・CLAUDE.mdの自動読み込みをすべて省いて起動が速くなります。--bareではMCPサーバーそのものを読み込まないため、CLAUDE_CODE_MCP_STARTUP_WAIT_MSが扱う「接続待ちサーバー」自体が存在しません。この変数を使う場面は、--mcp-configや.mcp.jsonでMCPサーバーを渡している非対話セッションに限られます。
CIで同じ結果を毎回再現したいだけなら、--bareでMCPサーバーごと読み込みを止める選択肢もあります。逆に、特定のMCPサーバーは使いたいが接続待ちだけを短くしたい場合は、--bareを使わずにCLAUDE_CODE_MCP_STARTUP_WAIT_MSで待機時間を絞り込みます。
まとめ
CLAUDE_CODE_MCP_STARTUP_WAIT_MSは、非対話セッションの初回ターンがMCPサーバーの接続をどれだけ待つかを一律に指定する環境変数です。v2.1.274以降で使え、0で待機をスキップできます。ただし--permission-prompt-tool(permissionPromptToolName)で指定したサーバーだけは対象外で、常に独自のMCP_TIMEOUT待機を使い続けます。CIでの起動時間短縮や、不安定なリモートサーバーへの猶予確保など、待機時間を自分でコントロールしたい場面で設定します。
より広くMCPサーバーの自動バックグラウンド化や長時間ツール呼び出しの扱いを知りたい場合は、MCPの長時間ツール呼び出しが自動でバックグラウンド化する仕組みも参考になります。セッション全体のターン数を制御したい場合はCLAUDE_CODE_MAX_TURNSとはを参照してください。