How to add human approval to MCP tool calls — no code changes

1 4
calendar_todayschedule3 min read
— Originally published at dev.to

MCP servers do what agents tell them. There's no policy check between "the agent decided to run this query" and "the query executed." If you're running MCP servers in production, every tool call goes straight through.

We built sidclaw-mcp-guard to fix that. It's a CLI that wraps any MCP server with policy-based guardrails. YAML rules, local approval dashboard, audit trail. No signup, no SaaS dependency. Apache 2.0.

Here's what it looks like.

30-second demo

npx sidclaw-mcp-guard@latest demo

Output:

ALLOW   SELECT * FROM users
  Allowed: read query on users. Read-only queries are safe.

HOLD    DELETE FROM users WHERE id = 42
  Held for approval: delete from users. Data changes need approval.

BLOCK   DROP TABLE users
  Blocked: drop users. Schema changes are never allowed.

Three decisions. Safe reads pass through. Writes wait for a human. Destructive DDL gets blocked outright.

It catches compound statements too. SELECT 1; DROP TABLE users doesn't sneak through as a read -- the destructive part gets flagged.

How it works

mcp-guard is a proxy. It sits between your MCP client (Claude Desktop, Cursor, VS Code, whatever) and the upstream MCP server. Every tools/call request passes through the guard first.

MCP Client  -->  sidclaw-mcp-guard  -->  MCP Server (postgres, filesystem, etc.)
                      |
                 policy.yaml
                      |
                 localhost:9091 (approval dashboard)

The guard reads your policies, classifies the tool call using semantic patterns, and decides: allow, hold for approval, or deny.

Setting it up

npx sidclaw-mcp-guard@latest quickstart

This creates a policy.yaml, writes .mcp.json for your client, and starts the approval dashboard at localhost:9091.

To run it manually against any MCP server:

npx sidclaw-mcp-guard --upstream "npx -y @modelcontextprotocol/server-postgres postgresql://localhost/mydb" --ui

Policy rules

Policies are YAML. Each rule matches a semantic pattern and decides what happens.

rules:
  - name: allow-reads
    description: Read-only queries are safe
    match:
      pattern: sql-read
    action: allow

  - name: approve-writes
    description: Data changes need human review
    match:
      pattern: sql-write
    action: approve

  - name: deny-destructive
    description: Schema changes are never allowed
    match:
      pattern: sql-destructive
    action: deny

default: deny

The patterns aren't regex. sql-read matches SELECT, EXPLAIN, SHOW. sql-write matches INSERT, UPDATE, DELETE. sql-destructive catches DROP, TRUNCATE, ALTER, CREATE. The guard parses the intent, not just the string.

Shell commands too

Works for filesystem and shell MCP servers, not just databases.

  • shell-safe -- ls, cat, echo
  • shell-risky -- curl, wget, ssh
  • shell-destructive -- rm -rf, chmod 777, dd

Same pattern. Same YAML. You can mix SQL and shell rules in one policy file if your agent connects to multiple MCP servers.

The audit trail

Every decision gets logged to .sidclaw/audit.jsonl:

{"timestamp":"...","tool":"query","args":{"sql":"SELECT * FROM users"},"decision":"allow","rule":"allow-reads"}
{"timestamp":"...","tool":"query","args":{"sql":"DELETE FROM users WHERE id=42"},"decision":"approve","rule":"approve-writes","status":"approved"}
{"timestamp":"...","tool":"query","args":{"sql":"DROP TABLE users"},"decision":"deny","rule":"deny-destructive"}

Every tool call, every decision, every approval. JSONL so you can grep it, pipe it, or ship it to whatever log aggregator you already use.

What this doesn't solve

mcp-guard governs tool calls. It doesn't filter LLM outputs, detect prompt injection, or validate agent reasoning. Those are different problems -- Pangea and Lakera handle the input/output layer. This sits at the action layer: the moment the agent decides to do something through an MCP server.

It also doesn't replace proper database permissions. If your postgres user has DROP access and you don't want agents dropping tables, fix the permissions too. mcp-guard is a second layer, not a replacement for the first.


2 Comments

1 vote
1 vote
🔥 Join developers growing publicly
Share your knowledge, build in public, and grow your developer presence with a global community.

More Posts

The Sovereign Vault — A Comprehensive Guide to Protocol-Driven AI

Ken W. Algerverified - Jun 4

MCP Is the USB-C of AI. So Why Are You Plugging Everything In?

Ken W. Algerverified - Jun 10

I’m a Senior Dev and I’ve Forgotten How to Think Without a Prompt

Karol Modelski - Mar 19

The Interface of Uncertainty: Designing Human-in-the-Loop

Pocket Portfolio - Mar 10

Comparison: Universal Import vs. Plaid/Yodlee

Pocket Portfolio - Mar 12
chevron_left
214 Points5 Badges
Zurich, Switzerlandsidclaw.com
3Posts
1Comments
Open-source governance for agentic AI. Policy engine, human approval workflows, and hash-chain audit... Show more

Related Jobs

Commenters (This Week)

4 comments
1 comment
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!