Reference
MCP tools
The exact tool surface a coding agent drives over the daemon's MCP connection. Every tool returns names + status, never a value.
These are the tools the daemon exposes over MCP (Streamable HTTP, 127.0.0.1/mcp, session
token required). The whole surface is the generative-UI vocabulary: the agent supplies
structured content; the daemon owns the pixels and the creds. No tool returns a secret
value โ that is enforced by check:no-leak.
Plan & status
plan()โStatus[]โ scan the manifest + connected state โ the grid (providers รlocal/dev/staging/prod). Emits key names and status, never values. Also carriespendingUserMessagesโ see Chat.updateStatus(provider, env, status)โ flip one grid cell to a credential status.
Author & render the UI
authorWizard(provider)โWizardโ derive the curated recipe's on-brand 1-2-3 setup wizard (open-urlโpasteโprovision) and push it to the cockpit. Returns step names + kinds.renderWizard(wizard)โ push an agent-authoredWizard(the long-tail fallback) to the cockpit. Schema-validated; malformed is rejected.mapActions(actions)โAction[]โ map the repo-specific + cross-tool next steps into the actions panel. EachActionis schema-validated. Returns names + prerequisites + danger- executor.
renderActions(actions)โ re-render the living action panel as the user steers it.
Complete & execute
submitStep(stepId, value?)โ the one inbound value path. For apastestep the value flows user โ daemon (validated + stored) and is never echoed back. Returns status + var name only. When the next step is a safeautostep, the daemon auto-advances it (mint โ validate-after-mint โ provision โ sync) with no agent round-trip โ the result carries the value-freeautoAdvancedoutcome.executeStep(stepId)โ the daemon runs the provisioning loop (mint โ validate-after-mint โ provision โ sync) with the stored creds. Returns status + key names.executeAction(id, confirmed?)โ run a mapped action through the gates (prereqs โ hard-confirm โ dispatch). Adestructiveaction is refused unlessconfirmed: true. Returns status + key names.mintKey(action, env?)โ the generic dynamic executor. The agent authors an HTTP action inline โ{ providerAccount, method, url, headers (with a {{ROOT}} placeholder), body?, extract? }โ and the daemon resolves the root key from the global vault, enforces the domain allowlist (a non-allowlisted host is rejected before any HTTP; redirects off the allowlisted host are refused, not followed), runs the call, and โ ifextractnames a minted secret โ files it in the sink underringtail/<repo>/<env>/<provider>naming. One path covers mint, read-only permission-check (noextract), and cross-provider wire. A consequential action (e.g. aDELETEthat spends the root key destructively) comes backneeds-confirmโ the agent gets noconfirmedargument, so it can never self-approve; a human confirms out-of-band. Returns{ providerAccount, varName?, status, reason? }โ never a value (root or minted; any reflected secret is scrubbed fromreason). The root key itself is pasted by the user viaPOST /api/root, never through the agent.
Chat (the direction channel)
sendChat(message, choices?)โ agent โ user in the dashboard chat, optionally with tappable choice pills. Text/intent only, never a value.- User โ agent is event-driven (no poll tool). A message the user types (
POST /api/chat) is queued and delivered aspendingUserMessages: string[]on the return of the agent's nextplan/executeStep/updateStatus/authorWizardcall โ intent text only, never a value. The agent re-renders actions/wizards to match on its next natural tool call.
Notice what's absent: there is no getSecret, no readValue, no tool that hands the agent a
credential. The agent's entire world is names, statuses, and the UI it authors. See
The guarantee.