Claude Media
Claude CodeのMCP connection closedで二重実行を避ける確認手順

Claude CodeのMCP connection closedで二重実行を避ける確認手順

MCPのツール呼び出しで「connection closed before the tool call was answered」が出たとき、再実行の前に何を確かめるか。自動再試行の条件とidempotentHintも解説。

「ツールが実行されたか分からない」を知らせるエラー

MCPのツールを呼んだ直後に、次のメッセージがツール結果として返ることがあります。

MCP server "<name>" connection closed before the tool call was answered. The tool may have run: check whether it did before running it again.

意味は、サーバーが答える前に接続が切れたので、Claude Codeにはツールが動いたかどうか判断できない、ということです。対象はHTTPのMCPサーバーとclaude.aiのコネクタです。

「失敗した」ではなく「結果が不明」な状態。ここを取り違えると、同じ操作を二度流すことになります。

このエラーを見たときの判断

  • ツールの動作は未確定。サーバー側では実行済みかもしれない
  • 先にすることは再実行ではなく、操作先のサービスでの結果確認
  • 実行済みなら再実行しない。未実行なら改めて頼む

再実行の前に確かめること

二重実行がいちばん困るのは、課題の作成、メッセージ送信、レコード追加のように、呼ぶたびに副作用が増えるツールです。Issueを作るツールなら、同じIssueが2件できます。

手順は次のとおりです。

手順

再実行までの確認の流れ

  1. 1

    操作先のサービスを直接見る

    作るはずだったIssueやレコードが、GitHubや課題管理ツールの画面にあるかを確かめます。Claudeに読み取り専用のツールで探させてもかまいません。

  2. 2

    実行済みならClaudeに結果を伝える

    Claudeが受け取ったのはこのメッセージで、ツールの本来の結果ではありません。「Issueは作成済み。番号は123」のように、結果を言葉で伝えて先へ進めます。

  3. 3

    未実行ならもう一度頼む

    先にサーバーを再接続する必要はありません。次のツール呼び出しで、Claude Codeが改めてサーバーへ接続します。

3つ目で再接続が要らないのは、エラー参照ページがそう明記しているためです。それでも接続に失敗するなら、サーバー側が落ちている可能性があります。その場合はMCPのツール更新と接続断からの自動再接続の仕組みにある再試行の上限と、/mcpからの手動再接続が次の手です。失敗したサーバーが複数あるなら/mcp reconnect allでの一括再接続が使えます。

Claudeに任せるときの指示の例

確認をClaudeに任せる運用なら、CLAUDE.mdに次のような一文を置く手があります。以下は筆者が考えた例で、公式の推奨文面ではありません。

## MCPツールのエラー処理
- `connection closed before the tool call was answered` が返ったら、
  同じ書き込みツールを再実行する前に、読み取り用のツールで結果を確認する
- 結果が確認できないときは、再実行せずに状況を報告して指示を待つ

「再実行する前に確認する」を明文化しておくと、書き込み系のツールで同じ操作が繰り返されるリスクを下げられます。実際にどこまで従うかはモデルとセッション次第なので、重要な書き込みには権限ルールも併用します。権限の書き方はMCP権限ルールのserver:tool単位の書き方にまとめています。

Claude Codeが自動で再試行する条件

実は、このエラーが出ない場合もあります。エラー参照ページによると、Claude Codeは、サーバーがそのツールを「繰り返しても安全」と印付けしているときに限り、呼び出しを自分で1回だけやり直します。印の有無による違いは次のとおりです。

ツールの印接続断のあとの挙動
idempotentHintがtrue接続断のあとの挙動新しい接続で1回だけ自動再試行する
readOnlyHintがtrue接続断のあとの挙動同上(読み取り専用の宣言)
どちらもなし接続断のあとの挙動再試行せず、上のエラーを返す

自動再試行の対象は、HTTPのサーバーとclaude.aiのコネクタです。回数は1回で、何度も繰り返すわけではありません。

したがって、このエラーを頻繁に見るサーバーは、ツールに印が付いていないか、付いていても再試行が間に合っていない可能性があります。ただし、どのツールに印があるかをクライアント側から一覧で見る手段は、MCPページに載っていません。サーバーの提供元のドキュメントか、tools/listの応答を見て確かめます。

サーバーを作る側のannotations

自分でMCPサーバーを作っているなら、安全に繰り返せるツールに印を付けておくと、利用者側のこのエラーが減ります。tools/listのエントリのannotationsで、次のどちらかをtrueにします。

  • idempotentHint: 状態を変えるが、同じ引数でもう一度呼んでも安全
  • readOnlyHint: 何も変えない。Claude Codeは、読み取り専用の呼び出しを他の読み取り専用の呼び出しと並列に実行する

set_issue_statusを安全に繰り返せるツールとして示す例は、次の形です(MCPページの例に沿っています)。

{
  "name": "set_issue_status",
  "annotations": {
    "idempotentHint": true
  }
}

ステータスを「完了」に設定する操作は、何度呼んでも結果が同じなので、印を付ける向きです。反対に「Issueを新規作成する」ツールは、呼ぶたびにIssueが増えるので、idempotentHintを付けてはいけません。付ければ、自動再試行が二重作成を引き起こします。

前と後

印の付け方で、接続断の結果が変わる

BEFORE

印なしの作成ツール

接続が切れると再試行されず、エラーが返ります。利用者が結果を確認してから再実行を決めます。

AFTER

冪等な更新ツールに印あり

接続が切れても、Claude Codeが新しい接続で1回だけやり直します。利用者はエラーを見ずに済みます。

接続断の前後で、どの再試行が働くのか

このエラーは、ツール呼び出しの最中に切れた場合の話です。接続そのものが切れたときの再接続は、別の仕組みが受け持ちます。

  • セッション途中で切れたリモートサーバー: Claude Codeは最大5回、1秒から倍々の待機で再接続を試みます。5回失敗するとサーバーを失敗扱いにし、対話セッションではMCP server "<name>" disconnected · open /mcp to reconnectと表示されます
  • 最初の接続が一時的なエラーで失敗したHTTP・SSEサーバー: 最大3回再試行します。認証エラーや見つからないエラーは、設定を直さない限り直らないので対象外です
  • 接続後のtools/listなどの問い合わせ: 一時的なネットワーク・サーバーエラーなら最大3回、短い待機で再試行します。認証エラー、4xx、リクエストのタイムアウトは再試行しません

つまり「接続の復旧」は自動で進みますが、「その瞬間に飛んでいた1回の呼び出し」は、印がない限り自動ではやり直されません。復旧と呼び出しの再実行は別の話です。

stdioサーバーでは文言が変わる

エラー参照ページがこの文言の対象にしているのは、HTTPのMCPサーバーとclaude.aiのコネクタです。ローカルプロセスのstdioサーバーは扱いが違い、claude -pとAgent SDKでは、プロセスが落ちても次のツール呼び出しでサーバーが再起動され、接続できた時点で呼び出しが実行されます。対話セッションでは失敗扱いになり、/mcpのメニューからReconnectを選んで起動し直します。

非対話実行(claude -p)で気をつけること

claude -pでは、/mcpパネルで結果を見ながら判断する場面がありません。書き込み系のツールを含むジョブでは、次の点を見ておくと安全です。

  • 失敗時にそのままジョブを再実行する設計だと、前回の呼び出しがサーバー側で完了していた場合に二重実行になる
  • ジョブの最初か最後に、読み取り専用のツールで結果を確かめる工程を入れておく
  • 書き込みに使うツールを、必要なものだけ許可しておく(権限の書き方は前述の記事を参照)
  • Agent SDKのアプリケーションなら、サーバーの状態がfailedになったときにTypeScriptのreconnectMcpServer()、PythonのClaudeSDKClient.reconnect_mcp_server()へサーバー名を渡して再接続できる。再接続の前に、直前の書き込みが完了していないかも確かめる

自動化の再試行ループに「確認してから再実行」を組み込めるかどうかが、二重実行を避けられるかの分かれ目です。

切断の原因が長い処理のときの見方

接続断そのものを減らしたい場合は、時間制限が関係していないかを見ます。MCPページによると、ツール呼び出しには次のような制限があります。

  • サーバーごとのtimeout(ミリ秒)は、1回の呼び出しの上限時間で、進捗通知では延びない。1000未満の値は無視される
  • 全サーバー共通の上限はMCP_TOOL_TIMEOUTで、未設定の既定は約28時間
  • 応答も進捗通知もない状態が続くと、HTTP・SSE・WebSocket・claude.aiコネクタでは既定で5分、stdioでは30分で呼び出しが中止される。CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUTで変更でき、0で無効になる

これらの制限で中止された場合のメッセージは、この記事のエラーとは別物です。タイムアウトの場合は、メッセージにtimed out afterのような表現が入ります。接続が相手側や経路で切れた場合に、今回の文言になります。切れた理由までは、メッセージからは分かりません。

長時間かかるツールの扱いはMCPの長時間ツール呼び出しが自動でバックグラウンド化する仕組みで扱っています。

似た表示との見分け

接続まわりの表示は文言が近く、対処が逆になることがあります。

表示ツールは動いたか主な対処
connection closed before the tool call was answeredツールは動いたか不明主な対処操作先で結果を確認してから再実行
MCP server "<name>" is disabledツールは動いたか動いていない主な対処/mcpでサーバーを有効にする
Skipping connection (recent failure cached…)ツールは動いたか接続自体を試していない主な対処15分待つか、/mcpのReconnect。詳細はSkipping connectionの解説

無効化されたサーバーの場合は、Claude Codeがサーバーに接続していないので、ツールは動いていません。今回のエラーだけが「動いたかもしれない」状態です。この違いが、再実行してよいかどうかを分けます。

まとめ

このエラーは、失敗ではなく結果不明の知らせです。再実行の前に、操作先のサービスで結果を確かめます。実行済みなら結果をClaudeに伝え、未実行なら改めて頼みます。サーバーを作る側は、安全に繰り返せるツールにだけidempotentHintかreadOnlyHintを付けると、自動再試行が1回働きます。

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