Skip to main content
Connected Accounts, device login, any hop that belongs in a browser: your action returns a Started ticket with a URL. The harness should show that URL, then wait until your callback says the grant finished. Mark the action. Register a waiter. Tokens never go through the chat.

Mark the URL

Keep returning one JSON ticket, for example:
If you omit [McpElicitUrl], the host looks for connectUri, url, authorizationUrl, or verificationUri on that JSON. Names that look like secrets (token, password, code) are ignored on purpose. Pair it with [McpTask] / HasMcpTask() so the harness waits while the operator is in the browser.

Wait until your callback fires

context has the action name, the entity key, and the Started JSON. Return null to keep that Started payload. Without a waiter, the harness still shows the URL, then the call ends. The operator finishing in the browser never comes back on MCP. If the harness cannot show a URL, they get the Started ticket and the human says when they are done.
The same elicitation is nested on the task. The operator accepts or declines; accept runs the waiter; decline skips it. Pair WithTasks and WaitForAnnotatedAction in the same AddODataMcp callback.