Claude Media
MCPの長時間ツール呼び出しが自動でバックグラウンド化する仕組み

MCPの長時間ツール呼び出しが自動でバックグラウンド化する仕組み

MCPツール呼び出しがメイン会話で2分を超えると、Claude Codeはバックグラウンドタスクへ自動で切り替えます。しきい値の変更方法と対象外になる4つのケースを扱います。

MCPツール呼び出しはなぜ2分でバックグラウンドに移るのか

メイン会話でのMCPツール呼び出しは、実行が2分を超えるとバックグラウンドタスクへ自動的に切り替わり、Claudeは待たずに次の作業へ進みます。この仕組みはClaude Code v2.1.212以降が対象です。

以前は、長時間のMCPツール呼び出しがセッション全体を止めていました。データベースの大規模集計や、外部APIの重いバッチ処理を呼ぶサーバーでは、応答が返るまでClaudeは他の作業に着手できませんでした。自動バックグラウンド化は、この待ち時間をClaudeの手が空く時間に変えます。

手順

2分を超えた呼び出しの流れ

  1. 1

    メイン会話でツールを呼ぶ

    通常どおり実行が始まります。2分以内に終われば、いつもと同じ同期呼び出しです。

  2. 2

    2分経ってもまだ実行中

    呼び出しはバックグラウンドタスクに移り、Claudeにはタスクidがすぐ返ります。

  3. 3

    Claudeは別の作業を続ける

    タスクは/tasksに並び、そこから停止もできます。サーバーが報告した最新の進捗もタスクの行に出ます。

  4. 4

    呼び出しが決着する

    成功でも失敗でも、結果はタスク通知としてClaudeに届きます。セッションを終了するとタスクは残りません。

判定基準は経過時間です。ただし、次の節の呼び出しは対象外になります。

対象外になる4つの呼び出し

すべてのMCPツール呼び出しが対象になるわけではありません。バックグラウンドに移らないのは次の4つです。

呼び出しの種類扱い解除できるか
サブエージェントからの呼び出し扱いバックグラウンド化されない解除できるかできない
IDEサーバーへの呼び出し扱いバックグラウンド化されない解除できるかできない
非対話モード(claude -p)扱い既定ではされない解除できるかCLAUDE_AUTO_BACKGROUND_TASKS=1で対象になる
elicitationダイアログが開いている呼び出し扱いダイアログが閉じるまで移行を保留解除できるか閉じれば通常どおり判定

非対話モードが既定で外れているのは、一回限りの実行が、バックグラウンドタスクの結果が届く前に終わってしまうことがあるからです。CIやスクリプトでclaude -pを使い、長いMCP呼び出しを裏に回したいときだけCLAUDE_AUTO_BACKGROUND_TASKS=1を立てます。

ただし、この環境変数はMCPだけに効くスイッチではありません。長時間のエージェントタスクの自動バックグラウンド化を強制する変数で、有効にすると約2分を超えたサブエージェントもバックグラウンドへ移ります。MCPについては、非対話モードでもツール呼び出しの自動バックグラウンド化を有効にします。CIで立てるなら、サブエージェントの挙動も変わる前提で見ます。

elicitationは、MCPサーバーがツール呼び出しの途中でユーザーに入力を求める仕組みです。フォームモードはサーバーが定義した入力欄のダイアログを出し、URLモードはサインインのようにターミナルの外で完結する手順へブラウザで誘導します。URLモードでは、ブラウザで開く前に同意の確認が出ます。URLの長さには上限があり、エスケープ後で数えるため、素のURLなら約8,000字、%が3文字に1つ入るURLなら約4,000字です。超えると、選べるのは拒否だけになります。Elicitationフックを使えば、この要求に自動で応答させることもできます。ダイアログが開いている間、サーバーは遅いのではなくあなたの入力で止まっています。そのため、閉じるまでバックグラウンド化は先送りされます。

裏に回ったかどうかを見分ける手がかり

「2分で裏に回るはず」の呼び出しが期待どおりに動かないときは、まず次の3点を見ます。

まとめ

切り分けの手がかり

  • /tasksに行があるか

    裏へ移っていれば、その呼び出しが/tasksに1行として並びます。行が無いなら移行はまだ起きておらず、呼び出しは同期のまま走っています。

  • 環境変数が立っていないか

    env | grep -E 'AUTO_BACKGROUND|DISABLE_BACKGROUND'で環境変数を確かめます。CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS=0とCLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1は、どちらも自動バックグラウンド化を止めます。

  • 打ち切りが移行の前か後か

    /tasksに行が出る前に止まったなら、timeoutがしきい値より短い組み合わせです。行が出た後に止まったなら、壁時計の上限かアイドルタイムアウトに当たっています。

しきい値と関連タイムアウトを変える

自動バックグラウンド化のしきい値はミリ秒単位で変更できます。

# しきい値を5分(300000ミリ秒)に変更
export CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS=300000
 
# 自動バックグラウンド化そのものを止める
export CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS=0

CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1を設定すると、自動バックグラウンド化が止まります。あわせて、Bashとサブエージェントのrun_in_backgroundとCtrl+Bも無効になり、Bashがタイムアウトに達したときの自動バックグラウンド化も止まります。この場合、タイムアウトに達したコマンドは裏へ移らず、そのまま止まります。

個々のサーバーの壁時計上限は、.mcp.jsonの該当エントリにtimeout(ミリ秒)を足して変えます。全サーバー共通の既定を変えるならMCP_TOOL_TIMEOUT環境変数です。

{
  "mcpServers": {
    "analytics-db": {
      "command": "npx",
      "args": ["-y", "my-analytics-mcp"],
      "timeout": 600000
    }
  }
}

この例は、重い集計を投げるサーバーの上限を10分に伸ばします。timeoutは呼び出し1回あたりの厳密な壁時計の上限で、サーバーからの進捗通知では延長されません。1000未満の値は無視され、MCP_TOOL_TIMEOUT(未設定なら約28時間)に戻ります。

timeoutを短くする場合も組み合わせに注意が要ります。たとえばtimeoutが90000で、しきい値が既定の120000のままだと、呼び出しはバックグラウンドへ移る前に上限で打ち切られます。

3層のタイムアウトは独立している

関連する制限は3層あり、既定値も変更先もそれぞれ別です。

くらべる

どの層が何を測るか

既定2分

自動バックグラウンド化のしきい値

メイン会話の呼び出しを裏へ回すまでの経過時間。変更はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MS。

既定約28時間

壁時計の上限

呼び出し1回が走ってよい総時間。変更は.mcp.jsonのtimeout(サーバー単位)かMCP_TOOL_TIMEOUT。

5分 / 30分

アイドルタイムアウト

応答も進捗通知も無い時間の上限。HTTP・SSE・WebSocket・claude.aiコネクタは5分、stdioは30分。変更はCLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUTで、0なら検査自体を止める。

アイドルタイムアウトは壁時計の上限を待たずに呼び出しを中断し、細かい規則がいくつかあります。

  • 1000未満の値は1秒に引き上げられ、実効のMCP_TOOL_TIMEOUTが上限になる
  • サーバー単位のtimeoutが1000以上なら、その値がそのサーバーのアイドル窓の下限にもなる
  • IDEサーバーとSDKのインプロセスサーバーには適用されない

アイドルタイムアウトはv2.1.187で入り、v2.1.203より前のstdioサーバーは対象外でした。サーバー単位のtimeoutをアイドル窓の下限にする規則もv2.1.203からです。

HTTP・SSE・claude.aiコネクタには、壁時計上限とは別に「最初の応答バイトが返るまで」を測るリクエスト単位のタイマーもあります。値は60秒・そのサーバーに適用されるツールタイムアウト・MCP_TIMEOUTのうち最大のものです。MCP_TOOL_TIMEOUT未設定時の約28時間は、この比較に入りません。stdioとWebSocketには、このタイマーはありません。

名前の似た環境変数を取り違えない

MCP関連のタイムアウト変数は名前が似ています。上の2つが起動(接続)側、下の3つがツール呼び出し側の変数です。ただしMCP_TIMEOUTは、HTTP系の呼び出しの最初の応答バイトのタイマーの下限にも入ります。

環境変数制御対象既定値
MCP_TIMEOUT制御対象サーバー1台の接続試行(起動)のタイムアウト。HTTP等の最初の応答バイトのタイマーの下限にも入る既定値30秒
MCP_CONNECT_TIMEOUT_MS制御対象起動をブロックする設定のとき、接続バッチを待つ時間既定値5秒
MCP_TOOL_TIMEOUT制御対象ツール実行の壁時計上限既定値約28時間
CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT制御対象無応答・進捗なしが続いたときのアイドル判定既定値上記の5分/30分
CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS制御対象バックグラウンドへ移すしきい値既定値2分

MCP_CONNECT_TIMEOUT_MSは、個々のサーバーの接続試行を縛るMCP_TIMEOUTとは別物です。起動の待ち時間を詰めたいのか、実行中の呼び出しを制御したいのかで、触る変数が違います。

「バックグラウンド」という語も、MCPまわりでは2通りに使われます。alwaysLoad: trueのないサーバーは、既定で接続処理をバックグラウンドで進め、起動を止めません。MCP_CONNECTION_NONBLOCKING=0にすると、起動がサーバーの接続完了を待ちます。これは「ツール呼び出しの実行が裏へ移る」ことの話ではありません。claude -p(--input-format stream-jsonなし)では、この変数の値にかかわらず、初回ターンの前に未接続のサーバーの接続を待ちます。

接続待ちは別の仕組み

まだ接続中のサーバーのツールを呼ぼうとしたときの待ちは、自動バックグラウンド化とは別です。tool searchが有効な既定構成ではToolSearch呼び出しの内部で待ち、tool searchを使わない構成ではWaitForMcpServersツールが代わりに使われます。tool searchを使わない構成には、カスタムのANTHROPIC_BASE_URLやENABLE_TOOL_SEARCH=falseが含まれます。

どちらも「繋がっていないサーバー」への待ちで、「繋がったサーバーの呼び出しが長い」ことへの対処ではありません。非対話セッションの初回ターンがこの接続待ちをどれだけ許容するかは、CLAUDE_CODE_MCP_STARTUP_WAIT_MSで変えられます(v2.1.274以降)。

導入の経緯:v2.1.212から進捗表示まで

自動バックグラウンド化は、MCPのタイムアウト周りが段階的に整うなかで入りました。

あゆみ

関連する変更のバージョン

  1. v2.1.187アイドルタイムアウトが入る

    CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUTが登場します。

  2. v2.1.203stdioも対象になる

    それまで対象外だったstdioサーバーにアイドルタイムアウトが適用され、サーバー単位のtimeoutが窓の下限になります。

  3. v2.1.2122分で自動的に裏へ

    長いMCPツール呼び出しがバックグラウンドへ移ります。

  4. v2.1.283進捗がタスクに出る

    裏へ移った呼び出しの進捗通知が捨てられていた不具合が直り、最新の進捗がタスクに表示されます。

サブエージェントは呼び出しでなくエージェントごと裏で動く

自動バックグラウンド化は呼び出し単位の仕組みで、対象はメイン会話のMCP呼び出しだけです。サブエージェントは別の単位で裏に回ります。対話セッションでは既定でfork modeが有効で、Claudeが起動するサブエージェントはバックグラウンドで動きます。

フォアグラウンドのサブエージェントは完了までメイン会話を止めます。ここでCLAUDE_AUTO_BACKGROUND_TASKS=1を立てると、サブエージェント自体が約2分で裏へ移ります。

長いMCP呼び出しを避けるためだけにサブエージェントへ処理を切り出す回避策は、必要性が下がります。単発の呼び出しでも、2分を超えればメイン会話は解放されます。

Ctrl+Bのバックグラウンド実行との違い

Ctrl+Bでコマンドをバックグラウンドに回す機能は、あなたが明示的に指示してBashコマンドを裏へ回す操作です。Bashもフォアグラウンドのコマンドがタイムアウト(既定2分、BASH_DEFAULT_TIMEOUT_MS)に達すると、sleepで始まるものを除いて自動で裏へ移ります。MCPの自動バックグラウンド化は、タイムアウトでは動きません。経過時間のしきい値(CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS)で動き、BASH_DEFAULT_TIMEOUT_MSとは別の設定です。

タイムアウトやCtrl+Bで裏へ移ったBashコマンドは、移った時点から30分で止まります。最初からバックグラウンドで起動したコマンドは、30分か、run_in_backgroundと一緒に渡したtimeout(最大2時間)です。サーバーの登録はMCP設定ガイド、長く動くことがある例はChrome DevTools MCPの記事にあります。

まとめ

2分を超える呼び出しを持つサーバーでは、しきい値より先にtimeoutとアイドル窓を、その呼び出しの実測時間に合わせます。しきい値が決めるのは裏へ移る時点だけで、打ち切りの上限は動かさないからです。

この記事を共有:XはてブLinkedIn