DML uses a stricter path than query execution because an approval must still describe the same mutation at commit time.
UPDATE and DELETE
- Compile the mutation
Parse, validate, authorize, and compile the requested mutation before any approval is requested.
- Preview the affected row set
Open a preview transaction and read the rows that currently match without executing the mutation.
- Create one-time approval evidence
Bind the challenge to the validated compiled plan, policy version, affected-row count, and row-set fingerprint.
- Ask a human through MCP Elicitation
Send
elicitation/createand require explicit form approval from the MCP client. - Consume the approved challenge
After acceptance, validate and consume the one-time challenge so it cannot be replayed as a generic permission token.
- Re-query inside the commit transaction
Read the matched rows again and compare the current fingerprint and count with the approved preview.
- Commit only if everything still matches
Execute the exact compiled mutation only when the plan, policy, challenge, row count, and row set are unchanged.
INSERT VALUES
An INSERT ... VALUES statement has no pre-existing matched row set. The approval protocol therefore binds the immutable insert payload and exact compiled plan rather than a row-set preview.
Elicitation is required
execute_dml_sql and published DML Custom Tools require form Elicitation support from the MCP client. A client that cannot perform the approval interaction cannot use those mutation paths.
This is intentionally different from a UI-only confirmation dialog: the approval challenge participates in the server-side mutation protocol and is checked again before execution.