この記事で分かること
- 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-reply で threadId を指定すると、前回の会話コンテキストを保持したまま対話を継続できます。
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 人の万能エンジニア"として扱うより、役割とゲートを設計して"チーム"として扱う方が安定する、というのが現時点での実感です。次は 委譲条件のテンプレ化と差分監査の自動化を進めて、仕組みの精度を上げていく予定です!