Categories
Artificial Intelligence

Form or URL? The two elicitation modes in MCP

MCP servers can ask the user for input in the middle of a tool call. Form mode has the client draw a dialog; URL mode sends the user to a web page. How both work on 2025-11-25 and 2026-07-28, why secrets belong in URL mode, and what Open WebUI 0.13.2 does.

Some tools can’t run without the user: a delete wants a confirmation, a booking needs a date, a third-party API needs a token. Elicitation lets an MCP server ask for exactly that in the middle of a tool call. Since 2025-11-25 there are two modes, and they solve different problems. All examples come from mcp-feature-test, a small server built to exercise these features.

Form modeURL mode
User seesA dialog the client draws from a JSON schemaA link that opens in the browser
Answer travelsThrough the clientFrom the browser straight to the server
Good forConfirmations, choices, datesTokens, passwords, OAuth, payments
Capabilityelicitation.formelicitation.url

Form mode

The server sends a message and a flat requestedSchema (strings, numbers, booleans, enums); the client decides what the dialog looks like. The user can accept, decline or cancel; only accept carries data.

Open WebUI dialog drawn from an MCP form elicitation: "Really delete important-file.txt?" with a Yes/No select and Cancel, Decline and Submit buttons.
A form elicitation in Open WebUI 0.13.2.

How the question reaches the client depends on the protocol generation. On 2025-11-25 the server sends an elicitation/create request back to the client while the tool call is still open. On the stateless 2026-07-28 there are no server-to-client requests: the tool returns input_required, and the client retries the call with the answers plus an opaque requestState. That state passes through the client, so the server must sign it; mcp-feature-test uses an HMAC with a 15-minute TTL.

Sequence diagram of form-mode elicitation: on 2025-11-25 the server sends elicitation/create while tools/call is pending; on 2026-07-28 tools/call returns input_required and the client retries with inputResponses and requestState.
Form mode on both generations. Red arrows carry the user’s answer, through the client in both cases.

URL mode

The server sends a message and a URL; the client shows the full URL and asks for consent. Whatever the user types on that page goes to the server’s own backend. The client never sees it, and neither does the model. In mcp-feature-test, elicit_url serves a token page at /flow/<uuid> and returns only a masked token.

Connect Fake Service page served by the MCP server: anything typed here goes straight to the MCP server, not to the MCP client or the model; a masked API token field and a Connect button.
The page behind elicit_url: the token is posted to the server, not to the client.

One trap: in URL mode, accept means “the user agreed to open the link”, not “the user finished”. It often arrives before anything was submitted, so the server has to wait for its own flow. mcp-feature-test keeps the call open for up to five minutes.

Sequence diagram of URL-mode elicitation: the client shows the URL and asks for consent, answers accept, the browser opens the server's flow page and posts the secret directly to the server; the tool result contains only a masked token.
URL mode: the secret goes from the browser straight to the server (step 10).

Why secrets must use URL mode

The spec forbids asking for passwords, API keys or tokens in form mode. A form answer passes through the client and may end up in chat history, logs and the model’s context, where the model can repeat it or hand it to another tool. URL mode keeps the secret between browser and server. In return, the URL is a bearer capability: make it unguessable and short-lived, and in production bind the flow to the user who started it.

What Open WebUI 0.13.2 does

  • Both modes work on both protocol generations.
  • Forms support every spec field type and are validated before sending. Unknown formats such as color become plain text boxes.
  • In URL dialogs the link itself is the accept button: clicking it answers accept at once.
  • Elicitation only works in an interactive browser chat, not through the REST API or from MCP Apps.

Need input a flat form can’t express, like a colour or a 3D selection? That’s what MCP Apps are for.

Try it yourself

docker run --rm -p 127.0.0.1:3457:3457 ghcr.io/linuxrrze/mcp-feature-test
# then point your client at http://127.0.0.1:3457/mcp

Ask the assistant to call inspect_client, then elicit_confirm, elicit_wizard and elicit_url. If browsers on other machines should reach the /flow pages, set PUBLIC_URL (e.g. -e PUBLIC_URL=http://myhost:3457); the server warns at startup when it’s missing. Source and full findings are on GitHub.

Leave a Reply

Your email address will not be published. Required fields are marked *

Are you human? Please solve:Captcha