Claude Media
Anthropic SDKの既定リトライ・タイムアウトは言語で違う — hooksとMCPサーバーの盲点

Anthropic SDKの既定リトライ・タイムアウトは言語で違う — hooksとMCPサーバーの盲点

Claude Codeのhooksや自作MCPサーバーでAnthropic SDKを呼ぶ際、7言語のリトライ回数・タイムアウト秒・プロキシ環境変数対応の既定値の違いをまとめます。

Claude Codeのhooksと自作MCPサーバーはAnthropic SDKの既定値に無防備になりやすい

Claude CodeのhooksやMCPサーバーの実装内でAnthropic SDKを直接呼ぶと、Claude Code自身が課すタイムアウト予算とSDK側の既定値がずれて、意図しない挙動を招くことがあります。リトライ回数は7言語とも2回で共通ですが、タイムアウト秒とプロキシ環境変数の扱いは言語ごとに差があります。この記事では、AnthropicのClient SDK(Python・TypeScript・C#・Go・Java・PHP・Ruby)の既定値そのものを、hooksの外部通知や自作MCPサーバーから呼ぶ場面に絞ってまとめます。エラー発生後の例外クラス名の言語別対応はClaude APIのエラー形式とSDK例外クラスの言語別対応表に譲り、ここでは接続前に決まる設定値だけを扱います。

リトライ回数の既定値は7言語とも2回で共通

Client SDKの既定リトライ回数とは、接続エラーや429・5xxエラーが起きたときにSDKが自動で再送する回数のことです。Python・TypeScript・C#・Go・Java・PHP・Rubyのすべてで、既定は2回です。短い指数バックオフを挟みながら、接続エラー・408・409・429・5xx系のエラーで自動的に働きます。

設定用のオプション名は言語ごとに異なります。

言語オプション名
Pythonオプション名max_retries(クライアント初期化時、またはwith_options())
TypeScriptオプション名maxRetries
C#オプション名MaxRetriesプロパティ、またはWithOptions
Goオプション名option.WithMaxRetries()
Javaオプション名.maxRetries()ビルダーメソッド
PHPオプション名RequestOptions::with(maxRetries: ...)
Rubyオプション名max_retries

タイムアウトで失敗したリクエストも、この2回のリトライ対象に含まれます。Python・TypeScriptのドキュメントは、タイムアウトの節で「タイムアウトしたリクエストは既定で2回リトライされる」と明記しており、Ruby・PHPはリトライの節自体に「タイムアウトも既定でリトライされる」と書いています。書かれている場所が違うだけで、挙動は7言語共通です。

タイムアウトの既定値は「10分」がベースライン、TypeScriptとJavaだけ動的に伸びる

非ストリーミングのMessagesリクエストは、Python・C#・Java・Ruby・Goが10分を既定タイムアウトにしています。ここまでは共通ですが、TypeScriptとJavaはさらにmax_tokens(JavaはmaxTokens)の値によって既定値が動的に変わる仕組みを持ちます。

TypeScriptは、ストリーミングしない状態で大きなmax_tokensを指定すると、60 * 60 * maxTokens / 128000秒(下限10分)まで既定タイムアウトが伸びます。上限は60分です。Javaはこれと形が違い、ストリーミング時は10分から60分まで、非ストリーミング時は30秒から10分までの範囲でmaxTokensに応じて既定値が変わります。同じ「動的タイムアウト」でも、TypeScriptはストリーミングしない場合だけ、Javaはストリーミングする場合としない場合の両方で発動する点に違いがあります。

PHPのSDKドキュメントには、タイムアウトの既定値や設定オプションを説明する節そのものがありません。エラー分類の表にTimeoutAPITimeoutExceptionという対応だけが載っており、既定秒数と設定方法は明記されていません。

Goは非ストリーミングのMessages以外にタイムアウトの既定値がない

Goのドキュメントは「非ストリーミングのMessagesリクエストは既定で10分、それ以外のリクエストには既定タイムアウトがない」と明記しています。Batch APIやFiles APIなど、Messages以外のエンドポイントをcontext.WithTimeoutなしで呼ぶと、理論上は応答が返るまで待ち続けます。他の6言語がおおむね全エンドポイントに10分の既定値を持つのに対し、Goだけはエンドポイントによって「既定値あり」と「既定値なし」が混在する設計です。自作MCPサーバーをGoで書き、Batch APIやFiles APIを呼ぶツールを実装するなら、この既定値の欠落を前提に自分でタイムアウトを設定する必要があります。

プロキシ環境変数を自動検出するのはPythonだけ

企業ネットワーク配下でhooksやMCPサーバーを動かす場合、HTTP_PROXY/HTTPS_PROXYをSDKが自動で読むかどうかは、言語間で対応が大きく分かれます。

Pythonはv0.54.0以降、http_client引数を渡さずにクライアントを初期化すれば、環境変数のプロキシ設定を自動検出します。この自動検出の仕組みと、自分でhttp_clientを渡すときの明示設定の方法はAnthropicのPython SDKでプロキシ環境変数が反映されない問題を解決するで詳しく扱っています。

TypeScriptは自動検出を行わず、ランタイムごとに異なるfetchOptionsでプロキシを明示する設計です(Node.jsはundici.ProxyAgent、Bunはproxyフィールド、DenoはDeno.createHttpClient)。Javaも自動検出はなく、java.net.Proxyオブジェクトを渡す.proxy()ビルダーメソッドで明示的に設定します。C#・Go・PHP・RubyのSDKドキュメントには、プロキシ設定を扱う節そのものがありません。

hooksのタイムアウト予算とSDKの既定値が衝突する場面

Claude Codeのhooksには、hookの種類ごとに異なるタイムアウト予算があります。commandhttpmcp_tool型のhookは多くのイベントで既定600秒ですが、UserPromptSubmitPreModelSwitchPostModelSwitchでは30秒に短縮され、MessageDisplayでは10秒、SessionEndでは合計1.5秒まで縮みます。

ここが問題になるのは、SDK側の既定値がこれらの短い予算を平気で超えることです。SessionEndhookの中でAnthropic SDKを呼び、ネットワークが不安定でタイムアウトが発生したとします。SDKは既定で2回リトライするため、Python・C#・Java・Ruby・Goでは最悪の場合10分の待ち時間が3回分、理論上30分近く消費されかねません。Claude Code側は1.5秒でhookを打ち切るため、実際には結果が返る前に強制終了され、SDKの試行は宙に浮いたまま残ります。

Pythonでの例です。

from anthropic import Anthropic
 
client = Anthropic(
    timeout=8.0,       # SessionEndの1.5秒予算には収まらないため、そもそも呼ぶ判断自体を見直す材料にする
    max_retries=0,     # hook予算内で1回だけ試行し、失敗したら即座に諦める
)

TypeScriptでも考え方は同じです。

const client = new Anthropic({
  timeout: 8000,
  maxRetries: 0
});

async: trueを付けて実行するhookはClaude Codeのタイムアウト強制の対象外になるため、この衝突自体は起きません。ただしバックグラウンドで動くぶん、SDKのリトライがどれだけ長く走っても気づきにくくなります。

自作MCPサーバーではHTTP/SSE系だけ60秒のリクエスト上限がある

自作MCPサーバーの中でツール実装がAnthropic SDKを呼ぶ場合、Claude Code側の制約はhooksとは別の仕組みです。MCP_TOOL_TIMEOUTの既定値は約28時間で、ツール実行全体としてはほぼ無制限に近い値です。ただしHTTP・SSE・claude.aiコネクター経由のMCPサーバーには、これとは別にリクエストごと60秒の上限が既定でかかります。stdioとWebSocket経由のサーバーには、このリクエストごとの上限がありません。MCP_TIMEOUTMCP_TOOL_TIMEOUTの役割の違いはMCP_TIMEOUTとMCP_TOOL_TIMEOUTの違いで扱っています。

TypeScriptやJavaでAnthropic SDKを呼ぶツールをHTTP/SSE型のMCPサーバーとして実装し、max_tokensを大きく指定すると、既定タイムアウトが動的に10分を超えて伸びる場合があります。この伸びた既定値がClaude Code側の60秒の壁を超えると、SDK側はまだ待っている途中でもリクエストごとの上限に引っかかって打ち切られます。ツール内でtimeoutを60秒未満に明示しておけば、どちらの制約が先に効くかを自分でコントロールできます。

Rustなど7言語に入っていない言語でMCPサーバーを書く場合

Anthropicが公式Client SDKを提供するのはPython・TypeScript・C#・Go・Java・PHP・Rubyの7言語です。MCPプロトコル自体はこれより対応言語が広く、Rust向けMCPサーバーSDKのような実装ガイドも存在します。Rustで書いたMCPサーバーのツール内からAnthropic APIを呼びたい場合、ここまで見てきたリトライ回数・タイムアウト秒・プロキシ自動検出のどれも既定では手に入りません。生のHTTPクライアントで/v1/messagesを叩くか、コミュニティ製の非公式クライアントを使うかの判断になります。MCPサーバー自体の作り方はMCPサーバー自作ガイドを参照してください。

言語別の既定値早見表

言語リトライ既定タイムアウト既定プロキシ環境変数
Pythonリトライ既定2回タイムアウト既定10分プロキシ環境変数自動検出(v0.54.0以降)
TypeScriptリトライ既定2回タイムアウト既定10分(非streamingかつ大きいmax_tokensで最大60分)プロキシ環境変数手動設定が必要
Javaリトライ既定2回タイムアウト既定10分(streamingは最大60分、非streamingは30秒〜10分)プロキシ環境変数手動設定が必要
C#リトライ既定2回タイムアウト既定10分プロキシ環境変数ドキュメントに記載なし
Goリトライ既定2回タイムアウト既定非streamingのMessagesのみ10分、他は既定なしプロキシ環境変数ドキュメントに記載なし
PHPリトライ既定2回タイムアウト既定ドキュメントに記載なしプロキシ環境変数ドキュメントに記載なし
Rubyリトライ既定2回タイムアウト既定10分プロキシ環境変数ドキュメントに記載なし

まとめ

Anthropic SDKのリトライ回数は7言語とも既定2回で揃っていますが、タイムアウト秒とプロキシ環境変数の扱いは言語ごとにばらつきます。TypeScriptとJavaはmax_tokens次第で既定タイムアウトが動的に伸び、Goは非ストリーミングのMessages以外に既定値を持ちません。プロキシを自動検出するのはPythonだけで、他の言語は明示設定が前提です。Claude Codeのhooksには30秒や1.5秒といった短いタイムアウト予算を持つ種類があり、自作MCPサーバーにもHTTP/SSE型なら60秒のリクエスト上限があります。どちらもSDKの既定値がその予算を上回りうるため、hooksやMCPサーバーからAnthropic SDKを呼ぶコードでは、timeoutmax_retries(または対応オプション)を予算に合わせて明示的に設定するのが安全です。

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