Demo: MCP execution binding — changed argument is blocked with mismatch evidence
EVE cryptographically binds the approved MCP request to the executed request. Any mutation between approval and execution is rejected before the side effect. This demo approves an MCP tool call, changes one approved argument at execution time, and shows the request is blocked with mismatch evidence.
Synthetic MCP server and recording tool. No production credentials.
Readiness
- MCP execution binding: PILOT_READY.
- MCP distributed deployment: distributed-pilot validated in the documented test topology.
- Python only for MCP governance (
mcp_gateway/ embedded service modes).
Setup
# demo_mcp_binding.py — synthetic fixtures only
from core.eve_sdk import EVE
IDENT = {"tenant_id": "acme", "principal_id": "agent-1", "session_id": "sess-1"}
calls = [] # recording target for the synthetic MCP tool
def mcp_send_email(**kwargs):
"""Synthetic MCP tool. Records; sends nothing."""
calls.append(kwargs)
return {"message_id": "M-1", "status": "queued"}
eve = EVE(policy="lending_v1", mode="embedded")
APPROVED_ARGS = {"to": "compliance@acme.example", "subject": "Q3 report", "body": "attached"}
Code
# 1) Approve a specific MCP request. EVE binds intent + capability schema + server identity
# + context digests to the approval.
approval = eve.approve_mcp_call(
tool="send_email",
arguments=APPROVED_ARGS,
context=IDENT,
server="mcp://mail.internal",
)
assert approval.approved
# 2) Execute EXACTLY the approved request -> digests match -> ALLOW -> tool runs once.
ok = eve.govern_mcp_call(
tool="send_email",
arguments=APPROVED_ARGS, # unchanged
context={**IDENT, "approval_id": approval.approval_id},
server="mcp://mail.internal",
)
assert ok.allowed
if ok.allowed:
mcp_send_email(**APPROVED_ARGS)
assert len(calls) == 1
# 3) Change ONE approved argument at execution time -> digest mismatch -> BLOCK.
tampered = dict(APPROVED_ARGS, to="attacker@evil.example") # recipient changed
blocked = eve.govern_mcp_call(
tool="send_email",
arguments=tampered,
context={**IDENT, "approval_id": approval.approval_id},
server="mcp://mail.internal",
)
assert not blocked.allowed, "changed argument must be blocked"
assert len(calls) == 1, "mismatch must not execute the MCP tool"
print("decision:", blocked.action, blocked.reason_codes)
Expected decision
| Step | Verdict | MCP tool executed |
|---|---|---|
| execute approved request unchanged | ALLOW | yes (1 recorded) |
execute with changed to argument |
BLOCK (digest mismatch) | no |
Expected evidence
MCP execution evidence records the approved digests and the executed digests; on the tampered call they differ and the authorization is not consumed for the executed side effect:
{"action": "BLOCK",
"mcp": {"approved_digests": "...", "executed_digests": "...(differ)...",
"authorization_consumed": true},
"reason_codes": ["...digest_mismatch..."],
"certificate": {"content_hash": "...", "signature": "ed25519-...", "canon": "jcs-1"}}
Verification command
from core.eve_sdk import verify_evidence
v = verify_evidence("mcp_execution", blocked.certificate, expected_tenant="acme")
assert v["valid"], v.get("reason")
print("verify:", v["valid"]) # -> True
Zero-side-effect assertion
len(calls) == 1: only the unchanged, approved MCP request executed. The tampered request was
rejected before mcp_send_email could run.
Cleanup
calls.clear()
No external state created.
Limitations
- Binding provides at-most-once authorization consumption and approved-equals-executed
matching. Remote outcomes are not assumed: an unknown remote outcome is recorded as
OUTCOME_UNKNOWNand never silently retried. - Cross-process single-use consumption was validated across separate OS processes on one host with a PostgreSQL-authoritative backend; true multi-host consumption across networked machines is argued from PostgreSQL transactional guarantees, not yet demonstrated across hosts.
- PILOT_READY, not production.