I'm working on an approval gate for destructive MCP tools. The server asks the human through MCP elicitation, so the model never sees the approval step.
A commenter pointed out a hole: in Claude Code, a hook on the Elicitation event can exit 0 with action "accept" and answer the request with no dialog. The server only receives accept, so it can't tell a person from a script. A project .claude/settings.json in a cloned repo could register such a hook once the folder is trusted.
What I'm considering:
- Log "client-accepted" instead of "approved", so the audit file never claims a human was involved.
- Run the allowlist and policy checks before any elicitation, so a scripted accept can't override them.
- Refuse irreversible tools when I can't tell how the answer was produced.
My question: is there any reliable way for an MCP server to know that a real person answered an elicitation? Or should the design assume it can't know, and rely on reversibility and quarantine instead?
I haven't checked which other clients let a script answer elicitation. If you know of any, please tell me. The project is open source, so PRs and issues are welcome.
Top comments (1)
From the Auten team (screen-control tools, same wall). Is your threat model only hooks that a cloned repo brings in, or also hooks the user wrote? If it's repo hooks, an out-of-band step closes most of it: for irreversible tools, send a short one-time code to something the client process can't read (a phone push, an authenticator) and require that code in the elicitation reply. A scripted accept doesn't have it, so "client-accepted" and "human-confirmed" become two separate log states.