Rightshold™ Sign up

Answers · MCP

How do I ask the user to confirm an action from inside an MCP server (elicitation)?

Last updated

TL;DR: Use elicitation. In the current MCP spec (2026-07-28), a tool that needs a yes or more details doesn't call the client back: it answers the tools/call with an InputRequiredResult (resultType "input_required") holding an elicitation/create request, the client asks the user, and then retries the same tool call with the user's answer in inputResponses plus the requestState you sent. Proceed only on action "accept" with the content you asked for; treat "decline" and "cancel" as no. Form mode is fine for a confirmation or a choice, but it may never ask for passwords, API keys, tokens or payment details; those need URL mode, which sends the user to a page on your own domain. Only send elicitation to clients that declared the capability, and keep a fallback for those that didn't. The answer comes from the client, so for actions that really matter, check the user on your own page (URL mode) or require an approval the client can't fake.

What should I check, step by step?

1. Check the client's capabilities first: elicitation is declared per request in _meta under io.modelcontextprotocol/clientCapabilities. An empty elicitation object means form mode only; servers must not send a mode the client didn't declare.

  1. Return the question from the tool call itself: an InputRequiredResult with an inputRequests map (your own key, for example "confirm_delete", mapped to an elicitation/create request with a message and a flat requestedSchema).
  2. Write the message so the user can decide from it alone: what will happen, to what, and the exact values (for example the record ids and the count), not the model's paraphrase.
  3. Put what you need to finish the job in requestState and protect it: the spec says to treat it as attacker-controlled, use HMAC or AEAD when it affects authorization or business logic, and bind it to the user, a short expiry and the original request.
  4. On the retry, act only if inputResponses carries action "accept" for your key and the content matches your schema. Decline and cancel mean stop; if the response is missing, ask again rather than guess.
  5. Make the action single-use on your side: the spec notes that an integrity-protected requestState limits replay but does not by itself make it one-time, so record that you've done it before you report success.
  6. Never collect secrets or payment details in form mode. Switch to URL mode, point it at a page on your domain, and check there that the person who opens it is the same user who made the tool call.
  7. If the client doesn't support elicitation, fail safe: return a plain result that says confirmation is needed and do nothing, instead of carrying on.

What changed in the 2026-07-28 spec

Multi Round-Trip Requests (MRTR) replaces server-initiated requests. Servers must now send elicitation/create, sampling/createMessage and roots/list inside an InputRequiredResult; the spec calls this a breaking change, and the old pattern is no longer supported in this version.

Form mode or URL mode?

Form mode: in-band, structured, and the data is visible to the client. Schemas are flat objects with string, number, integer, boolean and enum fields (string formats email, uri, date, date-time). Good for "Delete these 42 rows? yes/no" or picking one of several targets.

How much does an accept prove?

The spec requires clients to show which server is asking and to offer clear decline and cancel options, and says hosts SHOULD keep a human in the loop for tool calls. It doesn't prove to your server that a person clicked: the accept arrives from the client, and the spec tells servers not to trust client-provided identity without verifying it.

How do I ask Rightshold about this (free, no key)?

Add the MCP server https://www.rightshold.com/mcp to Claude, Cursor, ChatGPT, Grok or VS Code, then ask: “Before my MCP tool deletes the 42 stale customer records, ask me to approve exactly that action, and give me a receipt the tool can check before it runs.”

One-click setup

{
  "tool": "request_human_approval",
  "arguments": {
    "summary": "Delete 42 stale customer records (ids in the action) from the production CRM.",
    "action": {
      "type": "delete_records",
      "system": "crm-prod",
      "table": "customers",
      "record_count": 42,
      "ids_sha256": "SHA256_OF_SORTED_ID_LIST"
    },
    "expires_in_minutes": 30
  }
}

Rightshold doesn't run your MCP server, render elicitation prompts or stop a tool that never checks. It records approval requests and signed decisions that your tool can verify before acting.

What are the sources?

Related

Not legal advice. JSON · Markdown · All answers

Get a free API key in one call

No card and no email needed. 100 free credits; the license and policy checks stay free without a key.

curl -s -X POST https://www.rightshold.com/v1/accounts/signup -H "Content-Type: application/json" -d '{"accept_terms":true}'
export RIGHTSHOLD_API_KEY=rs_...   # the api_key from the reply (shown once)
curl -s https://www.rightshold.com/v1/licenses/check -H "Authorization: Bearer $RIGHTSHOLD_API_KEY" \
  -H "Content-Type: application/json" -d '{"license":"MIT","intended_use":{"commercial_use":true}}'