Codex で plugin や MCP tool を使い始めると、単純な「実行してよいですか」だけでは足りなくなります。日付、金額、対象 repository、通知先、実行理由のように、tool を呼ぶ直前に人間が入力したい値があります。逆に、API key や OAuth のように、フォームへ入れてはいけない値もあります。
2026年8月の ChatGPT / Codex changelog では、Codex Remote 側に standard MCP forms と editable message approvals の対応が追加されています。これは便利な UI 改善ですが、運用では「入力欄が出せるようになった」だけで終わらせると危険です。フォームで集める値、承認文として編集できる値、URL へ逃がす値、監査ログに残す値を分ける必要があります。
この記事では、Codex の MCP forms と editable approvals の運用設計 に絞ります。MCP の input_required と再送の protocol 設計は MCP MRTR 設計ガイド、OAuth scope と token passthrough 禁止は MCP authorization / OAuth scope 設計ガイド、Codex 全体の sandbox と approval は Codex sandbox / approvals 設計ガイド、plugin の許可境界は Codex plugin governance 設計ガイド に分けています。
先に結論: form は入力欄、approval は実行許可として分ける
私なら、Codex の MCP form と approval を次のように分けます。
| 入口 | 役割 | 入れてよいもの | 入れてはいけないもの |
|---|---|---|---|
| MCP form | tool 実行に足りない非機密パラメータを集める | 日付、選択肢、件名、上限金額、対象ID | API key、password、access token |
| editable approval | 実行前の承認文や送信文を人間が直す | PR comment、Slack draft、mail draft、理由説明 | 承認済みでない scope 変更 |
| URL mode | 機密情報や外部認可を別画面で扱う | OAuth、payment、credential 登録 | client に見せたい通常入力 |
| audit log | 後から判断を説明する | requester、server、tool、before/after、action | secret 本文、フォーム全文の無制限保存 |
大事なのは、form を approval の代わりにしないことです。フォームに amount: 10000 と入れたからといって、その支払いが承認されたことにはなりません。入力は入力、承認は承認です。
standard MCP forms で何が変わるか
MCP の elicitation は、server が client を通じてユーザーに追加情報を求める仕組みです。form mode では、server が requestedSchema を出し、client が構造化された入力欄を表示できます。
たとえば、次のような値は form に向いています。
- 対象 repository
- ticket ID
- review severity
- dry-run か実行か
- 通知先 channel
- 上限件数
- 実行予定日
これらは「LLM に自然文で聞く」より、form で選ばせる方が安全です。型、必須項目、選択肢、既定値を schema で固定できるからです。
一方で、form mode は in-band です。MCP client、transcript、debug log、tool result の周辺に値が残る可能性があります。MCP 仕様でも、password、API key、access token、payment credential のような機密情報は form mode で求めてはいけないと整理されています。
editable approvals は「送信直前の人間編集」に使う
editable message approvals は、Codex が作った送信文や action request を、人間が実行前に直せる導線です。これは、外部 write を伴う plugin / MCP tool で特に効きます。
たとえば次のような場面です。
- GitHub PR comment を投稿する前に、断定を弱める
- Slack 返信の宛先と文面を確認する
- issue 作成前に、再現手順の欠落を足す
- メール下書きから社外秘の表現を削る
ここでやってはいけないのは、編集可能な承認文へ新しい権限を紛れ込ませることです。たとえば最初は「PR にコメントする」承認だったのに、文面編集で「ついでに label を変更する」「branch を push する」まで含めるのは別 action です。承認単位を増やすなら、新しい approval request として出し直します。
form schema は UX ではなく安全境界として書く
MCP form の schema は、見た目を整えるためだけのものではありません。tool に渡せる値の境界です。
最初は次の制約を強めに置きます。
{
"type": "object",
"properties": {
"target_repo": {
"type": "string",
"title": "Target repository",
"pattern": "^[a-z0-9_.-]+/[a-z0-9_.-]+$"
},
"severity": {
"type": "string",
"title": "Severity",
"enum": ["low", "medium", "high"]
},
"dry_run": {
"type": "boolean",
"title": "Dry run first",
"default": true
}
},
"required": ["target_repo", "severity"]
}
この例で見ているのは UI ではなく、事故半径です。
target_repoを自由入力にするなら形式を縛るseverityは enum にして表記揺れを消すdry_runは defaulttrueにするhighのときだけ別 approval を要求する
AIエージェントに「適当に repository を選んで」と渡すより、form で人間に選ばせる方が、後から説明しやすくなります。
secret と OAuth は URL mode へ逃がす
API key、password、access token、payment credential は form に入れません。MCP の URL mode elicitation は、こうした機密情報や外部認可を MCP client の外へ逃がすための導線です。
実務では次の境界にします。
| 入力 | form mode | URL mode |
|---|---|---|
| review 対象 branch | ○ | 不要 |
| 実行理由 | ○ | 不要 |
| Slack channel 名 | ○ | 不要 |
| OAuth consent | × | ○ |
| API key 登録 | × | ○ |
| payment credential | × | ○ |
URL mode でも油断はできません。Codex や MCP client は、target domain を明示し、ユーザーが開く前に同意できる UI を出す必要があります。server 側は elicitationId と user identity を結び、session ID だけで状態を判断しないようにします。
approval log には before / after を残す
editable approval を使うなら、監査ログには「最終文面」だけでなく、少なくとも次を残します。
- 元の proposed action
- 人間が編集した後の final action
- 変更した actor
- 変更時刻
- 対象 server / tool / connector
- action kind
- secret redaction の有無
たとえば PR comment の文面を編集したなら、before / after の差分は残します。ただし本文に secret や customer data が含まれる可能性がある場合、全文保存ではなく redacted diff と artifact pointer に分けます。ここは AIエージェント artifact retention 設計ガイド の領域です。
approval と form を分けた実務例
Codex automation に「PR コメントを見て修正し、必要なら返信案を作る」タスクを任せる場合、私は次のように分けます。
task:
goal: respond_to_pr_feedback
allowed_actions:
- read_pr
- edit_worktree
- run_build
- draft_reply
forbidden_actions:
- merge_pr
- publish_release
- send_reply_without_approval
mcp_form:
fields:
pr_number: integer
max_files_changed: integer
response_tone: enum
dry_run: boolean
approval:
required_for:
- push_branch
- post_pr_comment
editable_message:
- pr_comment_body
この設計なら、form は「何を処理するか」を固定し、approval は「外へ出すか」を止めます。Codex が修正した差分を build で検証するまでは、PR comment を投稿しません。
よくある失敗
1. form に secret を入れさせる
フォーム UI が出ると、つい API key を入力させたくなります。これは避けます。form mode の値は client 側に露出する前提で扱い、secret は URL mode、既存の connector 認可、または workspace 管理の secret store へ逃がします。
2. editable approval を「承認後の自由編集」にする
承認対象は、実行する action と対象 resource です。文面を直すのはよいですが、実行範囲を広げるなら新しい approval が必要です。
3. cancel と decline を同じ扱いにする
MCP elicitation には accept / decline / cancel の区別があります。cancel は「明示拒否」ではなく、閉じた、失敗した、後回しにした可能性があります。automation では cancel を retry loop に入れず、inbox へ戻す方が安全です。
4. form schema を自由入力だらけにする
自由入力欄ばかりだと、結局 prompt と変わりません。enum、boolean、min/max、format を使い、tool が受け取れる値を狭くします。
導入 checklist
- MCP server ごとに form mode / URL mode の対応を台帳化する
- form に入れてよい非機密 field を決める
- secret / OAuth / payment は URL mode か connector 認可へ逃がす
- editable approval で編集できる field を文面に限定する
- action scope が変わる編集は別 approval に戻す
- accept / decline / cancel を別状態として処理する
- before / after と actor を audit log に残す
- automation では未承認の外部 write を inbox へ戻す
まとめ
Codex の standard MCP forms と editable approvals は、MCP tool や plugin を実務で使いやすくします。ただし、便利な入力 UI と実行承認を混ぜると、何を人間が決め、何を agent が埋め、何が外部へ送られたのか分からなくなります。
form は非機密パラメータを構造化する場所。approval は外部副作用を止める場所。URL mode は secret と外部認可を逃がす場所。audit log は、後から判断を説明する場所です。
この4つを分けておけば、Codex に MCP tool を増やしても、便利さだけで権限境界が溶ける事故を避けやすくなります。