MCP Draft System
AI drafts your infrastructure. You approve it.
Overview
The Draft System lets MCP agents propose infrastructure changes without directly mutating production. Agents create drafts; humans review, approve, and apply them. This ensures AI-generated proposals go through a human governance gate before taking effect.
How It Works
- An agent creates a draft describing a proposed configuration change
- The draft is stored in a pending state — no production resources are modified
- A human reviews the draft via CLI or UI, inspecting the proposed spec and diff
- The human applies the draft (or discards it)
- Apply-time validation runs before the change takes effect
Creating Drafts
Agents create drafts through dedicated MCP tools. In V1, agents can create draft endpoints only.
V1 Draft Types
| Type | Agent-Creatable in V1 |
|---|---|
endpoint | Yes |
route | No (V1.1+) |
policy | No (V1.1+) |
target | No (V1.1+) |
source | No (V1.1+) |
Draft Status Lifecycle
pending → applied
↓
discarded
↓
expired
- pending: Awaiting human review
- applied: Human-approved and applied to production
- discarded: Rejected or cancelled by human
- expired: TTL exceeded without action
Listing and Viewing Drafts
Agents and humans can list drafts to see what is awaiting review:
| Attribute | Description |
|---|---|
| Draft ID | Unique identifier |
| Type | Resource type (endpoint, route, etc.) |
| Status | pending / applied / discarded / expired |
| Creator | Agent or human who created it |
| Created at | Timestamp of creation |
| Expires at | Timestamp of automatic expiry |
| Proposed spec | The configuration the draft would create |
Each draft stores the proposed specification so reviewers can inspect exactly what would change.
Discarding Drafts
Drafts can be discarded by either an agent or a human if the proposal is no longer needed. Discarded drafts are not deleted but marked for audit trail purposes.
No-Apply MCP Governance
MCP agents cannot apply drafts directly.
Apply is an explicit human-only action:
- The apply API (
POST /api/v1/drafts/{id}/apply) rejects MCP authentication with a403 MCP_CANNOT_APPLYerror - Apply requires a
X-User-Idheader identifying the human operator - Drafts do not mutate any production resource until a human applies them
- The MCP surface has no apply tool, no apply route, and no write-to-production scope
This is a governance design — not a temporary limitation. Human-in-the-loop approval for infrastructure changes is intentional.
Draft Review and Apply Model
Review Surface
Drafts can be reviewed through two surfaces:
CLI (draft.py):
draft list— view all pending drafts with status and typedraft show <id>— inspect proposed spec with diffdraft apply <id>— apply a draft (human only, requiresZEN_USER_ID)draft discard <id>— discard a pending draft
UI (web dashboard):
- Pending count badge showing how many drafts await review
- Draft list table showing status, type, creator, expiry, and diff availability
- Draft review page with proposed spec visualization and diff view
- Human-only Apply and Discard buttons (gated by session authentication)
- Empty state and expired draft indicators
Apply-Time Validation
When a human applies a draft, these validations run and the apply is fail-closed:
- MCP auth rejected —
MCP_CANNOT_APPLY(403) - Pending status check — draft must be in
pendingstate - Expiry check — draft must not be expired
- Tenant ownership check — drafter and applier must belong to the same tenant
- Type check — only endpoint drafts can be applied in V1
- Proposed spec exists — draft must have a valid proposed spec
- Provider template enum check — provider must be a known, valid provider
- Target URL format check — endpoint target URL must be well-formed and non-empty
- Secret material check — proposed spec must not contain raw secrets (uses secret references)
Evidence Artifacts
Each draft lifecycle event produces separate evidence artifacts:
| Event | Fields |
|---|---|
draft_created | draft_id, type, created_by, created_at, proposed_spec_digest, merkle_position |
draft_applied | draft_id, applied_by, applied_at, resource_created, merkle_position, previous_digest |
Creation and apply evidence are generated by different endpoints and never share fields, maintaining separation of concerns.
Draft Expiry and Cleanup
Drafts have a configurable time-to-live. Expired drafts are automatically cleaned up by a garbage collection process:
- Expired drafts cannot be applied (fail-closed at validation)
- Cleanup respects tenant boundaries
- Evidence artifacts are never deleted — only the draft record is cleaned
- Maximum deletion rate is bounded to prevent resource spikes
V1 vs V1.1 Scope
V1 (Current)
| Feature | Available |
|---|---|
| Agent-created endpoint drafts | Yes |
| Draft list / show / discard | Yes |
| Human-only apply (CLI + UI) | Yes |
| Apply-time validation (9 checks, fail-closed) | Yes |
| Draft evidence artifacts | Yes |
| Draft expiry and GC | Yes |
| MCP cannot apply (403 enforcement) | Yes |
V1.1+ (Planned)
| Feature | Timeline |
|---|---|
route, policy, target, source draft types | V1.1+ |
| GitOps PR generation from drafts | V1.1+ |
| Inline draft editing before apply | V1.1+ |
| Draft comments and annotations | V1.1+ |
| Full admission webhook framework | V1.1+ |
| Merkle chain integration for draft evidence | V1.1+ |
Relationship to Read-Only V1 Policy
The Draft System extends MCP beyond pure read-only while preserving the human-in-the-loop governance model. MCP remains read-only for production operations — drafts are proposals, not mutations. Apply is exclusively human. See the Read-Only V1 Policy for the base read-only contract.
Related
- MCP Safety and Boundaries — governance model and operational boundaries
- MCP Tools Reference — available MCP tool surface
- Read-Only V1 Policy — base read-only contract