URL-mode elicitation: the hosted capture page
Some tool calls need a sensitive value from a human — a payment-mandate confirmation token, an OAuth authorization code, an API key. Asking your MCP client (Claude Desktop, Cursor, or any agent harness) to render that value in its own chat window would hand the client, its logs, and its transcript a plaintext copy of the secret. The Orbit MCP server instead uses the MCP specification’s URL-mode elicitation so the value goes straight to Orbit and never transits the client at all.In-band vs URL-mode elicitation
MCP elicitation has two modes, and this server uses both:- Form mode (in-band): the client renders a schema-defined form inline. Orbit uses this for simple yes/no confirmations before high-risk tools (the ones that send, spend, or delete) — see the client setup guide for the budget and allow-list knobs that sit alongside it.
- URL mode (out-of-band): the tool call fails with a structured JSON-RPC
error, code -32042 (
UrlElicitationRequired), whose payload carries a URL. The client opens that URL for the human instead of collecting the value itself. Orbit uses this whenever the requested input is a credential.
How the capture page is reached
When a tool needs a sensitive value, it registers a pending elicitation and throws the -32042 error. The error payload carries one entry:Error payload shape
/en/mcp/elicit/<elicitationId> —
rendered by the same hosted app as your dashboard. The page asks for exactly
one value and explains why: it goes straight to Orbit, never to the agent’s
host app.
What the user sees
- The capture page renders a single masked input (a password-style field with a show/hide toggle) and a Submit button.
- On submit, the page POSTs the value to
POST /api/mcp/elicitations/<id>, which relays it server-side to the MCP server. - The server single-uses the elicitation id — the first successful submission resolves it; any replay, expiry, or unknown id is refused.
- The page confirms “Sent” and tells the human to return to their agent. The next attempt of the same tool call picks up the resolved value and proceeds.
Security notes
- The URL is a capability token: the
elicitationIdis a random UUID, single-use and time-limited, so possession of the link is what authorizes exactly one submission. - Pending elicitations expire after 15 minutes — a stale link cannot be resolved later.
- The page is deliberately noindexed (
robots: noindex, nofollow) so the link never shows up in search results, and carries no canonical or Open Graph tags. - Don’t forward the link. Whoever opens it and submits supplies the value the tool will receive — share it only as you would an OAuth consent link.
- Elicitation is an additive safety layer. Server-side controls — scoped API
keys, the
MCP_TOOLS_BUDGET_LIMIT_USDcap, allow/deny lists, and the audit log of every chargeable call — still apply underneath it.
Worked example: payment-mandate confirmation
Consider a tool that charges a card on file and requires a payment-mandate confirmation token:- Your prompt asks the agent to run the charge.
- The tool has everything except the mandate token, so it returns the -32042 error with a capture URL. Your client surfaces: “This tool needs a secret to continue — complete it here:” plus the link.
- You open the link, paste the mandate token, submit, and see Sent.
- Re-run the prompt (or let the client retry). The tool fetches the resolved value and completes the charge — and at no point did the token pass through the client’s chat window.
Troubleshooting
See also
- Orbit-as-MCP: hosted server handshake — the protocol surface those elicitation requests flow through.
- Connect Orbit to your AI coding assistant via MCP — client setup, plus the security knobs (allow-list, budget cap) that compose with elicitation.