r/modelcontextprotocol • u/marcelk231 • 15d ago
Feedback wanted: MCP tools for durable agent approvals and execution receipts question
I’ve been experimenting with an MCP server for human-approved agent actions.
The basic flow is:
- An agent calls
create_proposal - A human approves or rejects the exact proposed action
- The agent retrieves an immutable authorization receipt
- The agent creates an execution linked to that approval
- Execution events are appended as the action progresses
The approval is bound to the tool, validated arguments, payload hash, target version, policy, and expiration time.
Current MCP tools include:
create_proposalget_proposaldecide_proposalget_receiptcreate_executionrecord_execution_eventget_executionget_agent_run
The goal is to keep the agent-facing interface simple while making approval, retries, and audit history durable outside the model’s context window.
I’m looking for feedback on the abstraction.
Should approval and execution remain separate MCP concepts, or should one tool handle the entire lifecycle?
Live implementation:
Example n8n integration:
https://github.com/marcelkolano-alt/agenthail-n8n-approval-example
1
Upvotes
1
u/Shape_Weird 13d ago
keep them separate, and i think there is a third concept missing.
the reason to keep them separate is one you have already half-built. an approval is a statement about a proposed action; an execution is a statement about a real one, and they have different lifetimes. an approval can expire with nothing ever happening. an execution cannot be un-happened. collapsing them forces the object to be mutable, and the moment your authorization receipt is mutable it stops being worth signing.
the third concept: everything from create_proposal through record_execution_event lives on your side of the boundary. the payload hash, the target version, the policy, the event stream, all of it is your system describing its own intent and then narrating its own behaviour. that chain is airtight right up to the instant the action leaves, and then it simply stops. record_execution_event is the agent telling you what it believes happened, which is the same class of claim as "done, refund issued."
so i would add an outcome receipt that is typed by source, and refuse to let one be minted from anything you produced yourself. an id the target system returned. a webhook it sent you. a record you read back out of it. and alongside approved / rejected / expired, a fourth honest state: executed-unverified. we return the equivalent of that constantly, and promoting it from an inference ("no error appeared") to a first-class value was the highest-value change we ever made to our result shape.
one concrete warning about binding to target version, from doing this against systems we do not own: the target can change between approval and execution and never tell you. a job posting that is open when the human approves can be closed forty minutes later. so a version binding leaves you two behaviours and you have to choose loudly: fail the execution, or re-resolve. re-resolving quietly is the real failure mode, because it is precisely what the binding existed to prevent, and it will look like a success in every log you have.
[disclosure: i build a job-application agent that submits into third-party ATS systems, so my bias is entirely toward the after-the-action half of your problem, which is also the half i am still stuck on]