Claude Codeを毎日触っていると、API制限や一時障害で作業が止まる日がありますよね。この記事は、Claude Code MCP フェイルオーバーを実運用したい人、特にMac miniでAIエージェントを常時動かしている人に向けて書きました。読むと、OpenAIとGeminiへ自動で切り替える設計と実装手順がわかり、今日から止まりにくい運用へ移せます。
こんな方におすすめ
- Claude Codeを業務の中心に置いていて、止まるリスクを減らしたい方です
- Mac miniでAIエージェントを常時運用し、夜間停止を避けたい方です
- OpenAI Gemini 自動切り替えを、勘ではなく設計で実現したい方です
- MCPを使って将来のモデル変更にも耐える基盤を作りたい方です
この記事でわかること
- Claude Code依存を外すための、実運用向けアーキテクチャです
- エラー種別ごとに切り替えるフェイルオーバー設計の具体例です
- .mcp.json、LiteLLM/OpenRouter、再試行ロジックの実装手順です
- 監視・レート制御・コスト最適化まで含めた運用チェックポイントです
なぜClaude Code単独依存を外すのか
最初に結論です。生産性を落とさない近道は、モデルを増やすことより「切り替えの仕組み」を先に作ることです。Claude Code自体はかなり強力ですが、単一依存だと一時障害やレート制限がそのまま停止になります。Mac miniの常時運用では、数分の停止でも朝のレビュー、日中の修正、夜のバッチに連鎖しやすいです。つまり問題はモデル性能より、止まった時の逃げ道がないことです。
- 障害リスク — 単発の503でもジョブが詰まると、次の処理まで遅延が広がります
- レート制限 — RPM/RPD/TPM/TPD/IPMのどれかに触れると、実行計画が崩れます
- コスト上振れ — 高性能モデルに固定すると、繁忙日に費用が急増しやすいです
- ルール変更 — 提供条件の更新時に、運用全体へ影響が出やすいです
運用判断に使える具体データ
- OpenAIのレート制御は5軸管理なので、1つ余裕があっても別軸で詰まる可能性があります
- Geminiは429
RESOURCE_EXHAUSTEDと503UNAVAILABLEが代表的で、500/503時は別モデル切り替えが推奨されています - Claude CodeのMCP出力は10,000トークンで警告、既定25,000なので、長文ツール出力の制御が必要です
イメージとしては、単一依存は「電車1路線で通勤している状態」に近いです。止まった瞬間に全部止まります。MCPとLLMゲートウェイを挟めば、複数路線に分散できます。“普段は最速ルート、詰まったら自動で別ルート”という運用へ変えられるので、体感の安心感がかなり違います。
Mac mini AIエージェント 冗長化の全体像
構成はシンプルです。Claude Codeを入口にして、MCPでツール層を統一し、その先のLLM呼び出しをLiteLLMやOpenRouterへ集約します。そうすると、アプリ側は「同じインターフェースのまま」、裏側だけOpenAIやGeminiへ切り替えできます。ここで大事なのは、モデル切り替えを“機能追加”ではなく“インフラ機能”として扱うことです。
| レイヤー | 役割 | 実装ポイント |
|---|---|---|
| Claude Code | 開発者の操作入口 | MCP設定の優先順位は local > project > user です |
| MCPサーバ | ツール実行の共通窓口 | stdio/Streamable HTTPを使い、環境差分を減らします |
| LLMゲートウェイ | モデル選択・フェイルオーバー | 失敗理由別ルーティングを定義します |
| モデル群 | OpenAI/Gemini等の実行先 | 用途別に優先順位を決めておきます |
MCP仕様の2025-11-25版では、トランスポートはstdioとStreamable HTTPが標準です。旧HTTP+SSEからの移行が進んでいるので、新規構築なら最初から新仕様で組むのがおすすめです。セキュリティ面では、Origin検証、127.0.0.1バインド、認証実装が明示されています。ローカル常駐のMac miniでも、この境界設計を省くと「ローカルだから安全」という思い込みが生まれやすいです。
OpenAI Gemini 自動切り替えを設計する方法
自動切り替えで失敗しやすいのは、「全部同じ再試行」で処理してしまうことです。実際には、429と503とポリシーエラーでは打ち手が違います。先にエラー分類を決めると、フェイルオーバーは急に実装しやすくなります。
| エラー種別 | よくある原因 | 推奨アクション | 切り替え先 |
|---|---|---|---|
| 429(レート超過) | RPM/TPM不足 | 指数バックオフ+ジッター | 同系列の軽量モデル |
| 500/503 | 一時障害 | 短時間リトライ後に切替 | 別ベンダーモデル |
| コンテキスト超過 | 入力長すぎ | context_window_fallbacks | 長文対応モデル |
| ポリシー拒否 | 安全制約 | content_policy_fallbacks | 方針差分のあるモデル |
OpenAI側はレートヘッダーが取れるので、x-ratelimit-remaining-requestsやx-ratelimit-reset-requestsを見て待機時間を決めると精度が上がります。Geminiは500/503時に別モデル切り替えが案内されているので、ProからFlashへ段階的に逃がす設計が現実的です。つまり、切り替え判断を「エラーメッセージの雰囲気」ではなく、ヘッダーとステータスで機械的に決めるのがポイントです。
- 第1段 — 同一ベンダー内の軽量モデルへ切り替えます
- 第2段 — 別ベンダーへ切り替えて可用性を確保します
- 第3段 — それでも失敗したら待機し、通知を飛ばして手動判断へ渡します
この3段設計にすると、可用性優先と品質優先を状況で切り替えやすいです。Mac mini運用では、夜間無人時間に特に差が出ます。
実装手順:.mcp.jsonとゲートウェイ設定
ここは今日から触れるように、最小構成で書きます。
LiteLLM(PR)かOpenRouter(PR)をゲートウェイにして、Claude CodeからMCP経由で叩く形です。
どちらもOpenAI互換で扱えるので、既存コードの変更を小さくできます。
- MCP接続を可搬化 —
.mcp.jsonでURLとAPIキーを環境変数化します - ルーティング定義 — 失敗理由別fallbacksを設定します
- 再試行実装 — 429/503は指数バックオフ+ジッターで吸収します
- 出力上限調整 —
MAX_MCP_OUTPUT_TOKENSを用途に合わせて見直します
{
"mcpServers": {
"llm-gateway": {
"url": "${API_BASE_URL:-https://gateway.example.com}/mcp",
"headers": {
"Authorization": "Bearer ${API_KEY}"
}
}
}
}
from litellm import Router
from tenacity import retry, wait_random_exponential, stop_after_attempt
router = Router(
model_list=[
{"model_name": "primary", "litellm_params": {"model": "openai/gpt-4.1"}},
{"model_name": "secondary", "litellm_params": {"model": "gemini/gemini-2.5-pro"}},
{"model_name": "tertiary", "litellm_params": {"model": "gemini/gemini-2.5-flash"}}
],
fallbacks=[{"primary": ["secondary", "tertiary"]}],
context_window_fallbacks=[{"primary": ["secondary"]}],
content_policy_fallbacks=[{"primary": ["tertiary"]}]
)
@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(6))
def run_chat(messages):
return router.completion(model="primary", messages=messages)
OpenRouterを使う場合は、provider.orderとallow_fallbacksで挙動を分けます。可用性重視ならallow_fallbacks=true、監査要件で経路固定したいならfalseが扱いやすいです。「平常時は品質重視、障害時は継続重視」をスイッチで切り替えられる状態を作っておくと、運用のストレスが減ります。公式設定はClaude Code MCPドキュメントの形式に合わせると、チーム展開しやすいです。
検証手順:障害注入テストと復旧時間の測定
構成を作ったら、必ず「壊すテスト」をします。ここを飛ばすと、本番で初めて弱点が見つかります。
Mac miniのtmuxセッションで、疑似障害を入れて切り替え時間を測ります。
目標は“切り替わること”ではなく“何秒で復旧するか”を数字で持つことです。
- 429再現 — 負荷を上げ、レートヘッダーから待機時間が正しく反映されるか確認します
- 503再現 — primaryモデルを停止し、secondaryへ自動遷移するか確認します
- 長文再現 — コンテキスト超過を作り、context_window_fallbacksを検証します
- 通知確認 — 3段目でも失敗した時にSlack/Discord通知が飛ぶか確認します
- 復旧計測 — エラー発生から正常応答までの秒数を記録します
この検証結果を残しておくと、モデル変更や料金見直しのときにも判断が速くなります。感覚ではなく時系列データで見られるので、チーム合意も取りやすいです。
本番運用の勘所:監視・コスト・セキュリティ
最後に、実運用で効率差が出るポイントをまとめます。まず監視は「プロセス監視」と「品質監視」を分けます。前者は死活、後者はレスポンス遅延や失敗率です。
tmux自動再起動に加えて、失敗率しきい値を超えたら通知する形。
止まらない運用は、再起動より“早く気づく仕組み”で決まります。
コスト最適化で押さえる数字
- Prompt Cachingは遅延最大80%削減、入力コスト最大90%削減の案内があります
- 自動キャッシュは1024トークン以上で有効なので、プロンプト先頭の共通化が重要です
- 同一キー+同一プレフィックスで高頻度連打すると効率低下しやすいため、分散設計が必要です
- 保持時間は短期5〜10分が中心なので、夜間バッチではextended運用の検討が有効です
- レート制御 — 5軸を同時監視し、上限の近い軸から抑制します
- セキュリティ境界 — MCP HTTPは
127.0.0.1バインド、Origin検証、認証を必須にします - 出力制御 —
MAX_MCP_OUTPUT_TOKENSをユースケース別に分けます - 運用導線 — 関連設定はリポジトリ内に集約し、端末差分を環境変数で吸収します
詳細なMCP運用の基礎は、MCP実装の関連記事と、Mac mini常時運用の記事をセットで見ると理解しやすいです。
この構成を後回しにすると運用で失うもの
フェイルオーバーを知らないままだと、作業時間より「待ち時間」が増える可能性があります。特に複業や小規模チームでは、停止の影響がそのまま信用に直結しやすいです。障害はゼロにできませんが、停止時間は設計で短くできます。後回しにすると、障害発生時に「何から直すか」で時間を消費しやすいです。
- 納期の遅延 — 夜間ジョブ停止が翌日作業を圧迫しやすいです
- 判断の属人化 — 毎回その場判断になり、復旧が遅れやすいです
- コストの暴発 — 緊急時に高額モデルへ固定し、予算超過しやすいです
この記事を書いている理由
僕自身、Mac mini M4 Pro(24GB)を24時間稼働させて、Node.js + TypeScript + tmux + Tailscaleで自律エージェントを回してきました。実際に止まる瞬間を何度も見たからこそ、根性ではなく構成で解決する大事さを強く感じています。2026年3月1日に公開したMCP運用設計ガイドと、同日のMac mini停止対策の記事で基礎を整理したので、今回はその次の一手としてマルチLLM化をまとめました。非IT現場でも使える形に翻訳して届けることが、僕の役割だと思っています。
次のアクション
今日からできるアクション
- .mcp.jsonを環境変数化し、端末ごとの差分をなくします
- 429/503/長文超過の3パターンだけ先に障害注入テストします
- ゲートウェイ導入を試すならOpenRouterの紹介ページ(PR)かLiteLLMの紹介ページ(PR)を確認します
実装してみて詰まったポイントがあれば、記事コメントかSNSで質問してもらえると嬉しいです。