Tool approvals
When a tool can change things (send email, merge a PR, delete a file), you probably want to see the call before it runs, especially during a live demo. With approvals the model waits: the tool card shows its arguments and Approve / Deny buttons.
Who asks
Section titled “Who asks”From most to least specific:
- Per tool: in Settings → MCP servers → a server → Tools, click the
auto/askspill next to a tool. - Per workspace: Settings → Workspaces → Ask before every tool call puts every MCP tool in the workspace in “ask” mode, which is handy as a safe mode for demos. Tools you explicitly set to
autostill run. - Per server: Tool approval in the server form: run automatically, always ask, or never ask.
- Default: tools the server annotates with
destructiveHint: trueask. Everything else runs.
{ "mcpServers": [ { "id": "gh", "name": "GitHub", "transport": "http", "url": "https://api.githubcopilot.com/mcp/", "approval": { "default": "ask", "tools": { "search_code": "auto", "get_file_contents": "auto" } } } ], "workspaces": [{ "id": "live", "name": "Live demo", "requireApproval": true }]}Answering
Section titled “Answering”| Button | Effect |
|---|---|
| Approve | Run this call |
| Allow for session | Run it, and don’t ask again for this tool until Moka restarts |
| Always | Run it and save "tool": "auto" to moka.json |
| Deny | Don’t run it. The model is told the user declined and should ask how to proceed |
Pressing Stop cancels any pending approval. Approvals show up in the inspector as interaction.request / interaction.resolved events.
From code
Section titled “From code”With @mokalabs/core, pending approvals are published on the event bus. Answer them with engine.respond(id, { approved: true }), or pass onInteraction to decide programmatically:
const engine = new MokaEngine({ config, onInteraction: async (request) => (request.kind === "tool-approval" ? { approved: request.tool !== "delete_repository" } : { action: "decline" }),});