Hook event 24 of 33

Elicitation

Runs when an MCP server asks the user for input during a task and can answer or reject the request before Claude Code shows its dialog.

Exit code veto
Exit 2 blocks
Matchers
MCP server name, or omit to match every server
if filter
Does not apply
Docs checked
2026-08-29

A server asks a question and the hook answers first

MCP, short for Model Context Protocol, lets a server your session is connected to pause mid-task and ask a human a question. You do not have to wait for that dialog. Before Claude Code shows the question, Elicitation runs. A hook here can supply the answer itself, so the request never reaches a person, or it can refuse the request outright. The matcher filters on mcp_server_name, and omitting it runs the handler for every server that asks.

Form mode and URL mode

The payload carries permission_mode, mcp_server_name, and message, plus optional mode, url, elicitation_id, and requested_schema.

FieldWhat it holds
modeWhich kind of request this is. The hooks reference shows two, form and URL.
requested_schemaFor a form request, the object schema describing the fields the server wants filled in.
urlFor a URL request, a browser-authentication link.
elicitation_idThe identifier this request carries.

The reference does not list any mode beyond those two, and it does not define which subset of JSON Schema requested_schema may use.

Accept, decline, or cancel

The JSON answer lives under hookSpecificOutput with hookEventName: "Elicitation" and an action of accept, decline, or cancel. content carries form values and applies only when the action is accept. systemMessage and continue are discarded.

Exit 0 shows the normal dialog unless the JSON supplies one of those actions. Exit 1 is the same, with the JSON still read. The reference does not say how the server sees the difference between decline and cancel on its side.

Exit 2 throws your JSON away

Exit 2 denies the request. Stderr is shown nowhere, not to you and not to Claude. And hookSpecificOutput is ignored even when stdout holds valid JSON. On most events valid JSON still applies on a non-zero code. On Elicitation, and on ElicitationResult, it does not. The exit code wins by discarding the JSON, not by outranking it.

The mistake most people make first

You want to refuse one server’s requests and say why, so the hook exits 2 with the reason on stderr.

The request is denied and the reason reaches nobody: not you, not Claude, not the server. You add a JSON decline and keep the exit 2, and the JSON is discarded too. From the outside, the dialog never appeared and nothing explained why.

Return action: "decline" and exit 0. Exit 2 is the silent form of the same refusal.

Module 09 lists this event in the blocking inventory, and module 10 is where you connect a server that could ask.