0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Code から Codex を呼ぶ ─ MCP でマルチ AI ワークフローを組んだ話

0
Posted at

この記事で分かること

  • Claude Code から MCP 経由で Codex を呼び出す具体的な設定と使い方
  • 2 つの AI を繋いだときに必要になるルーティング・セキュリティ・品質保証の設計
  • 実際に統合してみて起きた問題と、その対処

はじめに

AI コーディングアシスタントを複数使うこと自体は、もう珍しくありません。Claude で設計を相談し、Codex でコードを書き、別のツールでレビューする ── そういう使い分けをしている人は多いと思います。

ただ、ツール間を行き来するコストは意外と大きい。コンテキストの引き継ぎ、指示の再入力、出力のコピペ。AI が賢くなっても、ワークフローが分断されていると恩恵を活かしきれません。

そこで、Claude Code を起点に、MCP 経由で Codex を同一ワークフロー内から呼べる環境 を構築しました。本記事では、その技術的な実装・設計上の判断・統合してみて実際に起きたことを共有します。

※本記事の「Codex」は、旧来の"Codex モデル名"を指すのではなく OpenAI Codex CLI(MCP サーバーとして起動可能) を指します。内部で利用されるモデルは環境/設定に依存します。


技術実装:MCP で Claude から Codex を呼ぶ

セットアップ

Codex CLI は MCP(Model Context Protocol)サーバーとして動作します。.mcp.json に以下を記述するだけで、Claude Code から直接呼び出せるようになります。

{
  "mcpServers": {
    "codex": {
      "type": "stdio",
      "command": "npx",
      "args": ["@openai/codex", "mcp-server"]
    }
  }
}

これにより、Claude の会話内で mcp__codex__codex というツールが使えるようになり、プロンプトを渡してタスクを委譲できます。

呼び出しパラメータ

パラメータ 説明
prompt Codex への指示
sandbox read-only / workspace-write(実行権限の制御)
cwd 作業ディレクトリ
developer-instructions プロジェクト固有ルールの注入(後述)
model モデル指定(環境依存)
threadId セッション継続用(mcp__codex__codex-reply 側で指定)

mcp__codex__codex-replythreadId を指定すると、前回の会話コンテキストを保持したまま対話を継続できます。

developer-instructions:ルールの注入

Codex はプロジェクトのルールを知りません。呼び出すたびに developer-instructions でルールを注入します。

SECURITY RULES (NON-NEGOTIABLE):
- NEVER read/write .env*, *.pem, *.key, secrets/ files
- NEVER log passwords, tokens, API keys, or PII
- Use parameterized queries only (no raw SQL interpolation)

ARCHITECTURE RULES:
- Follow Clean Architecture: domain must not import infrastructure
- Follow FSD layer constraints: upper layers import lower layers only
- Public API through index.ts only

SCOPE RULES:
- Only modify files within the specified scope
- Do not add dependencies without explicit approval
- Match existing code style and patterns

ポイント:「できれば」「推奨」では守られません。MUST / NEVER で書きます。


設計判断 1:ルーティング ── どのタスクをどっちに振るか

2 つの AI を 1 箇所から呼べるようにすると、次の問題が出ます。「このタスク、どっちに振る?」

判断フロー

タスク受領
│
├─ セキュリティ敏感? → Claude
├─ マルチモジュール? → Claude
├─ アーキテクチャ判断? → Claude
├─ 設定ファイル(.claude/, infra/)? → Claude
│
└─ 明確な AC + 単一スコープ?
    ├─ YES → Codex に委譲
    └─ NO  → Claude がタスク分割して再評価

ルーティングテーブル

タスク種別 推奨 理由
アーキテクチャ設計 Claude プロジェクト固有の設計知識が必要
セキュリティ関連の変更 Claude Secret/権限/境界の判断が必要
複数モジュールの統合 Claude 依存関係と影響範囲の理解が必要
コードレビュー(アーキテクチャ) Claude レイヤー制約チェックが主
コードレビュー(バグ/性能) Codex エッジケース・性能観点の検出が得意
単一モジュールの実装 Codex 高速なコード生成
テストコード生成 Codex 仕様からのテスト生成が得意
スコープ限定のリファクタリング Codex 機械的な変換に強い

核心は Claude が常にオーケストレーション権限を保持する ことです。Codex に完全な自律性は委譲しません。Codex への委譲は実行であり、判断は常に Claude が行います。

※Codex が原則ですが、仕様が揺れている・セキュリティ境界に触れる・複数モジュールの統合、のようなケースでは Claude が実行側に回ることもあります。


設計判断 2:セキュリティ ── 2 つの AI を繋いだときに何を守るか

マルチ AI ワークフローの最大のリスクは、「AI が意図しない操作をする経路が増える」 ことです。3 層の防御を設計しました。

Layer 1: Claude Code settings(静的ルール)
   ↓ Claude の Read/Write/Edit/Bash をブロック
Layer 2: Claude Code hooks(動的チェック)
   ↓ 実行直前にパターンマッチでブロック
Layer 3: developer-instructions(プロンプト制約)
   ↓ Codex にルールを認識させる

Layer 1:Deny リスト

Claude Code の settings.json で危険な操作を静的にブロックします。

{
  "permissions": {
    "deny": [
      "Read(**/.env)", "Read(**/.env.*)",
      "Read(**/secrets/**)", "Read(**/*.pem)",
      "Write(**/.env)", "Write(**/.env.*)",
      "Bash(git push --force*)",
      "Bash(git reset --hard*)",
      "Bash(rm -rf /*)", "Bash(sudo *)"
    ]
  }
}

Layer 2:hooks

Bash 実行前にフックで検査します。終了コード 2 でブロック。

# force push を全パターンでブロック
if [[ "$COMMAND" =~ git\ push.*(-f|--force|--force-with-lease) ]]; then
  echo "BLOCKED: Force push is forbidden." >&2
  exit 2
fi

# ネットワーク流出の防止
if [[ "$COMMAND" =~ ^curl\ .*(-F|--form)\  ]]; then
  echo "BLOCKED: Network exfiltration attempt." >&2
  exit 2
fi

Layer 3:developer-instructions

Codex への呼び出し時にセキュリティルールを注入(前述)。

既知の穴:どこまでが技術的に強制できるか

ここが一番重要です。

deny リストや hooks は Claude が使うツールRead/Write/Bash 等)を制御するものであり、MCP ツール呼び出し自体はツール名のマッチ等で止めることができます。しかし、MCP サーバー(Codex)が 呼び出された先で内部的にどうファイルアクセスするかまでは、Claude 側の deny/hook では技術的に強制できません。

つまり「呼び出しを止める」ことはできても、「呼び出した先の挙動を制御する」ことはできない。ここがセキュリティ境界の分岐点です。

対策 効果 限界
developer-instructions 注入 Codex にルールを認識させる プロンプト制約(技術的強制力は弱い)
sandbox: read-only 書き込みを制限 読み取りは可能
2 段階レビュー 出力に機密情報がないか検証 レビュー自体も AI に依存

これは解決済みの問題ではありません。 現状は、MCPサーバー内部の挙動までClaude側で強制できないため、技術的強制と運用的担保の境界を明示し、穴を認識した上で運用しています。


設計判断 3:品質保証 ── Codex の出力をどう検証するか

Codex の出力をそのまま採用するわけにはいきません。Claude が 2 段階のレビューを行います。

Stage 1(仕様適合): AC がすべて満たされているか、スコープ外の変更がないか
Stage 2(コード品質): アーキテクチャ準拠、セキュリティ、エラーハンドリング、型安全性

Codex 出力
  ├─ Stage 1 PASS → Stage 2 へ
  │    ├─ Stage 2 PASS → Claude が適用
  │    └─ Stage 2 FAIL → Claude が差分修正
  └─ Stage 1 FAIL
       ├─ 1回目 → developer-instructions を補強して再委譲
       └─ 2回目 → Claude が直接実装にフォールバック

最大 2 回で打ち切り。それでもダメなら Claude がやります。

委譲テンプレート

実際に Codex へ渡すプロンプトのテンプレートです。AC(受け入れ条件)とスコープを明確に書くことで、Stage 1 レビューの判定基準にもなります。

[Task]
- Scope: apps/data-collector/src/modules/system/*
- Goal: Add GET /health endpoint returning service status

[Acceptance Criteria]
- [ ] GET /health returns 200 with { status, timestamp, version }
- [ ] Service checks DB connectivity (PrismaService)
- [ ] Returns 503 if DB is unreachable
- [ ] Adds unit tests (success + DB failure)
- [ ] No changes outside Scope

[Constraints]
- Follow existing controller pattern (try-catch + HttpException)
- Use HealthInfo interface for response type

developer-instructions(セキュリティ/アーキテクチャルール)はこのテンプレートとは別に、すべての呼び出しに自動で注入されます。


統合してみたら起きたこと

ここからが本番です。仕組みを作って動かしたら、仕組み自体の問題が出てきました。

Codex にルール自体をレビューさせたら、矛盾が 10 件出てきた

マルチ AI ワークフローのルーティングルールやエージェント定義を PR にしたとき、Codex(CI 上の自動レビュー)が以下の問題を検出しました。

セキュリティアーキテクチャの穴(P1):

.claude/settings.json の deny リストは MCP 経由に適用されないと Known Limitations に明記しているのに、実装委譲のデフォルトが workspace-write になっている。ガードレールが機能しない状態で書き込み権限を与えている」

ポリシーの論理矛盾(P1):

approval-policy: never を MUST NOT で禁止しているのは danger-full-access との組み合わせのみ。workspace-write + never は禁止されておらず、承認なし実行が可能なまま」

ドキュメント間の不整合(P2):

「リトライ回数の定義が、ルーティングルール(計 2 回)・エージェント定義(計 3 回)・ワークフロー文書で食い違っている。運用者ごとに挙動がズレる」

「ルーティング条件が Codex 禁止ディレクトリ(.claude/, infra/)を除外していない。判定で Codex に振り分け → 実行時に拒否 → 無駄にフォールバックが走る」

これらは ESLint でも TypeScript でも見つからない問題です。ポリシーの論理矛盾、ドキュメント間の不整合、設計の意図と実装の乖離 ── 人間のレビューでも見落とされていたものを、Codex が横断的に検出しました。

E2E テスト結果

S/M サイズのタスク + エッジケース、計 6 件の Codex 委譲を E2E で検証しました。
※小規模検証(n=6)なので統計的に強い主張はできませんが、少なくともこの範囲では以下の結果でした。

指標 基準 結果
quality-gates 通過率 100% 100%
フォールバック率 < 30% 17%(1/6)
平均リトライ回数 < 1.0 0.0
E2E 完走 Yes Yes

フォールバックの 1 件は、プロジェクト固有の内部 API(Prisma の拡張パターン)を Codex が知らなかったケースです。これは Codex の弱点(プロジェクトコンテキストの不足)が明確に出た場面で、Claude フォールバックで正常に完走しました。

CLI と MCP の使い分け

観点 CLI(codex review MCP(mcp__codex__codex
対話性 1 回完結 セッション継続可能
ルール注入 限定的 developer-instructions で強化しやすい
スコープ diff / タスク単位 ディレクトリ/ファイル単位で委譲しやすい
統合性 独立プロセス Claude のワークフローに組み込み

結論として、開発中は MCP、CI/CD では CLI という使い分けに落ち着きました。


全体ワークフロー

要件受領
  │
  ▼
仕様策定(Claude)── 対話的にユーザーと深掘り
  │
  ▼
タスク分解(Claude)── 実行可能な小タスクに分割
  │
  ▼
┌─────────────────────────────────┐
│  各タスクごとにルーティング判断   │
│                                 │
│  Claude 直接:                    │
│   ・アーキテクチャ判断            │
│   ・セキュリティ関連              │
│   ・マルチモジュール統合          │
│                                 │
│  Codex 委譲(MCP 経由):          │
│   ・単一モジュール実装            │
│   ・テストコード生成              │
│   ・バグ検出                     │
│     └→ 2段階レビュー → 適用      │
└─────────────────────────────────┘
  │
  ▼
完了検証 ── 統合的な動作確認
  │
  ▼
品質ゲート ── format → lint → typecheck → test → build

学んだこと

1. 統合して初めて見える問題がある

2 つの AI を繋いだとき、仕組み自体に矛盾が生まれる。ルーティング条件と実行制約の不一致、ドキュメント間のポリシー矛盾、セキュリティ設計の穴 ── これらは個別に設計している段階では気づきにくく、統合して初めて表面化しました。

2. セキュリティの境界は自分で引き直す必要がある

Claude Code の deny リストや hooks は MCP 経由には効かない。これは Claude Code の問題ではなく、MCP で外部ツールを繋ぐ以上、セキュリティの境界線が変わるという構造的な事実です。どこからが技術的強制で、どこからが運用的担保なのかを明示することが重要でした。

3. フォールバックがないと止まる

Codex が期待通りの出力を返さないケースは普通にあります。「2 回失敗したら Claude がやる」というシンプルなフォールバックだけで、ワークフローが止まることがなくなりました。

4. developer-instructions は契約書

Codex への指示は MUST / NEVER で書く。「できれば」「推奨」では守られません。実際、スコープ外の要件を渡したとき、developer-instructions を根拠に Codex が自発的に「これはスコープ外です」と拒否したケースがありました。明確に書けば、AI はそれに従います。


おわりに

複数の AI を使い分けること自体は、もう当たり前です。しかし 1 箇所から呼べるようにして、ルーティング・セキュリティ・品質保証を設計すると、単なる「使い分け」では見えなかった問題が次々と出てきます。

ポリシーの矛盾、セキュリティ境界の変化、フォールバックの必要性 ── どれも、統合して初めてわかったことです。

まだ試行錯誤の段階ですが、AI を"1 人の万能エンジニア"として扱うより、役割とゲートを設計して"チーム"として扱う方が安定する、というのが現時点での実感です。次は 委譲条件のテンプレ化差分監査の自動化を進めて、仕組みの精度を上げていく予定です!


参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?