{"slug": "stop-your-ai-agent-deleting-things-human-approval-for-destructive-mcp-tools", "title": "Stop your AI agent deleting things: human approval for destructive MCP tools", "summary": "A developer released mcp-safe-actions, an open-source TypeScript library that wraps destructive MCP tools so they cannot run until a human approves. The library splits each dangerous tool into a side-effect-free preview and an execute step gated either by MCP client elicitation or a single-use, expiring token bound to the same tool and arguments, and it ships a mutation-testing suite that deliberately breaks the safety code in 10 ways, all of which the tests catch.", "body_md": "Your AI agent should not be able to delete a file, send an email or drop a table just because it decided to. \"Please ask first\" in a system prompt is a request. It is not a control.\n\nIf you build MCP (Model Context Protocol) servers, you can enforce the rule in code. I wrote a small TypeScript library, `mcp-safe-actions`, that wraps a dangerous tool so it does nothing until a human approves.\n\nRepo: [https://github.com/techsaurabh-394/mcp-safe-actions](https://github.com/techsaurabh-394/mcp-safe-actions)\n\nA prompt-injected or confused model can call `delete_file(\"../../important\")`. Two things are true at once:\n\nYou split a dangerous tool into two functions. `preview` describes what will happen and changes nothing. `execute` runs only after approval.\n\n``` js\nimport { rmSync, statSync } from \"node:fs\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport { registerConfirmedTool, fileAudit } from \"mcp-safe-actions\";\n\nconst server = new McpServer({ name: \"files\", version: \"1.0.0\" });\n\nregisterConfirmedTool(server, {\n  name: \"delete_file\",\n  description: \"Permanently delete one file.\",\n  inputSchema: { path: z.string() },\n  preview: ({ path }) => ({\n    summary: `Permanently delete \"${path}\" (${statSync(path).size} bytes)`,\n    details: [\"This cannot be undone.\"],\n  }),\n  execute: ({ path }) => {\n    rmSync(path);\n    return { content: [{ type: \"text\", text: `Deleted ${path}` }] };\n  },\n  audit: fileAudit(\"./audit.jsonl\"),\n});\n\nawait server.connect(new StdioServerTransport());\n```\n\nThe tool is listed with `destructiveHint: true`.\n\n**Client supports elicitation:** the server asks the human through the client UI. The model never sees the approval step, so it cannot approve itself. Declined, cancelled, timed out or crashed means nothing runs.\n\n**Client does not support elicitation:** the server returns the plan plus a one-time token. The assistant has to show the plan to the user and call again with the token. The token is single-use, expires, and only works for the same tool with the same arguments.\n\nThe `mode` option picks the behaviour: `auto` (default), `elicit` or `token`.\n\nSafety code needs tests that try to break it. From the repo:\n\n`src/`.` npm run mutation`) that breaks the code on purpose in 10 ways, such as a reusable token, approval skipped on error, or secrets in the log. It fails if the tests do not notice. All 10 are caught.\nThe mutation check also exposed one weak test of mine. It is written up in `docs/TESTING.md`.\n\n`mode: \"elicit\"`.` execute()` should re-check state that changed since the preview.`npm install github:techsaurabh-394/mcp-safe-actions`.\n\n```\ngit clone https://github.com/techsaurabh-394/mcp-safe-actions.git\ncd mcp-safe-actions\nnpm install\nnpm run demo   # prints both approval flows\nnpm test\n```\n\nApproval channel hooks (Slack, webhook) for headless servers, a policy mode that auto-approves low-risk calls and always asks for high-risk ones, and a Python version for FastMCP servers.\n\nIf you build MCP servers, I would like to know which of your tools you would not let a model call unattended, and what approval flow you would want for them. Issues and PRs are welcome.", "url": "https://wpnews.pro/news/stop-your-ai-agent-deleting-things-human-approval-for-destructive-mcp-tools", "canonical_source": "https://dev.to/saurabh_pathak394/stop-your-ai-agent-deleting-things-human-approval-for-destructive-mcp-tools-5ha9", "published_at": "2026-11-01 03:01:51+00:00", "updated_at": "2026-11-01 03:23:07.478650+00:00", "lang": "en", "topics": ["ai-agents", "agent-protocols", "ai-tools", "ai-safety", "developer-tools"], "entities": ["mcp-safe-actions", "Model Context Protocol", "techsaurabh-394", "FastMCP", "Slack"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/stop-your-ai-agent-deleting-things-human-approval-for-destructive-mcp-tools", "markdown": "https://wpnews.pro/news/stop-your-ai-agent-deleting-things-human-approval-for-destructive-mcp-tools.md", "text": "https://wpnews.pro/news/stop-your-ai-agent-deleting-things-human-approval-for-destructive-mcp-tools.txt", "jsonld": "https://wpnews.pro/news/stop-your-ai-agent-deleting-things-human-approval-for-destructive-mcp-tools.jsonld"}}