Claude Code MCPフェイルオーバーをMac miniで実装する手順

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、再試行ロジックの実装手順です
  • 監視・レート制御・コスト最適化まで含めた運用チェックポイントです
僕は福祉事業のIT全般を担当しつつ、複業でAI×SaaS開発を続けています。非ITの現場でも回る仕組みを作るのが得意なので、今回は「止めない設計」に絞って、実際に回る形でまとめます。

なぜClaude Code単独依存を外すのか

最初に結論です。生産性を落とさない近道は、モデルを増やすことより「切り替えの仕組み」を先に作ることです。Claude Code自体はかなり強力ですが、単一依存だと一時障害やレート制限がそのまま停止になります。Mac miniの常時運用では、数分の停止でも朝のレビュー、日中の修正、夜のバッチに連鎖しやすいです。つまり問題はモデル性能より、止まった時の逃げ道がないことです。

  • 障害リスク — 単発の503でもジョブが詰まると、次の処理まで遅延が広がります
  • レート制限 — RPM/RPD/TPM/TPD/IPMのどれかに触れると、実行計画が崩れます
  • コスト上振れ — 高性能モデルに固定すると、繁忙日に費用が急増しやすいです
  • ルール変更 — 提供条件の更新時に、運用全体へ影響が出やすいです

運用判断に使える具体データ

  • OpenAIのレート制御は5軸管理なので、1つ余裕があっても別軸で詰まる可能性があります
  • Geminiは429 RESOURCE_EXHAUSTED と503 UNAVAILABLE が代表的で、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版では、トランスポートはstdioStreamable HTTPが標準です。旧HTTP+SSEからの移行が進んでいるので、新規構築なら最初から新仕様で組むのがおすすめです。セキュリティ面では、Origin検証、127.0.0.1バインド、認証実装が明示されています。ローカル常駐のMac miniでも、この境界設計を省くと「ローカルだから安全」という思い込みが生まれやすいです。

運用で迷ったら「ツールはMCPに集約、モデル切り替えはゲートウェイに集約」と役割を分けると整理しやすいです。責務分離しておくと、障害時の切り分けが速くなります。

OpenAI Gemini 自動切り替えを設計する方法

自動切り替えで失敗しやすいのは、「全部同じ再試行」で処理してしまうことです。実際には、429と503とポリシーエラーでは打ち手が違います。先にエラー分類を決めると、フェイルオーバーは急に実装しやすくなります

エラー種別 よくある原因 推奨アクション 切り替え先
429(レート超過) RPM/TPM不足 指数バックオフ+ジッター 同系列の軽量モデル
500/503 一時障害 短時間リトライ後に切替 別ベンダーモデル
コンテキスト超過 入力長すぎ context_window_fallbacks 長文対応モデル
ポリシー拒否 安全制約 content_policy_fallbacks 方針差分のあるモデル

OpenAI側はレートヘッダーが取れるので、x-ratelimit-remaining-requestsx-ratelimit-reset-requestsを見て待機時間を決めると精度が上がります。Geminiは500/503時に別モデル切り替えが案内されているので、ProからFlashへ段階的に逃がす設計が現実的です。つまり、切り替え判断を「エラーメッセージの雰囲気」ではなく、ヘッダーとステータスで機械的に決めるのがポイントです。

  1. 第1段 — 同一ベンダー内の軽量モデルへ切り替えます
  2. 第2段 — 別ベンダーへ切り替えて可用性を確保します
  3. 第3段 — それでも失敗したら待機し、通知を飛ばして手動判断へ渡します

この3段設計にすると、可用性優先と品質優先を状況で切り替えやすいです。Mac mini運用では、夜間無人時間に特に差が出ます。

実装手順:.mcp.jsonとゲートウェイ設定

ここは今日から触れるように、最小構成で書きます。
LiteLLM(PR)OpenRouter(PR)をゲートウェイにして、Claude CodeからMCP経由で叩く形です。
どちらもOpenAI互換で扱えるので、既存コードの変更を小さくできます。

  1. MCP接続を可搬化.mcp.jsonでURLとAPIキーを環境変数化します
  2. ルーティング定義 — 失敗理由別fallbacksを設定します
  3. 再試行実装 — 429/503は指数バックオフ+ジッターで吸収します
  4. 出力上限調整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.orderallow_fallbacksで挙動を分けます。可用性重視ならallow_fallbacks=true、監査要件で経路固定したいならfalseが扱いやすいです。「平常時は品質重視、障害時は継続重視」をスイッチで切り替えられる状態を作っておくと、運用のストレスが減ります。公式設定はClaude Code MCPドキュメントの形式に合わせると、チーム展開しやすいです。

検証手順:障害注入テストと復旧時間の測定

構成を作ったら、必ず「壊すテスト」をします。ここを飛ばすと、本番で初めて弱点が見つかります。
Mac miniのtmuxセッションで、疑似障害を入れて切り替え時間を測ります。
目標は“切り替わること”ではなく“何秒で復旧するか”を数字で持つことです。

  1. 429再現 — 負荷を上げ、レートヘッダーから待機時間が正しく反映されるか確認します
  2. 503再現 — primaryモデルを停止し、secondaryへ自動遷移するか確認します
  3. 長文再現 — コンテキスト超過を作り、context_window_fallbacksを検証します
  4. 通知確認 — 3段目でも失敗した時にSlack/Discord通知が飛ぶか確認します
  5. 復旧計測 — エラー発生から正常応答までの秒数を記録します
SLOの目安は、成功率99%以上、P95応答時間は平常時+30%以内、障害時の自動復旧は60秒以内に置くと運用しやすいです。最初は厳密でなくていいので、毎週同じ指標で比較するのがおすすめです。

この検証結果を残しておくと、モデル変更や料金見直しのときにも判断が速くなります。感覚ではなく時系列データで見られるので、チーム合意も取りやすいです。

本番運用の勘所:監視・コスト・セキュリティ

最後に、実運用で効率差が出るポイントをまとめます。まず監視は「プロセス監視」と「品質監視」を分けます。前者は死活、後者はレスポンス遅延や失敗率です。
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現場でも使える形に翻訳して届けることが、僕の役割だと思っています。

次のアクション

今日からできるアクション

実装してみて詰まったポイントがあれば、記事コメントかSNSで質問してもらえると嬉しいです。