2026-01-30 · Authensor

How to Safely Run MCP Tool Servers

To safely run MCP tool servers, add SafeClaw action-level gating. Install with npx @authensor/safeclaw and define a deny-by-default policy that evaluates every tool call before it reaches the MCP server. The Model Context Protocol (MCP) is an open standard for connecting AI models to external tools and data sources. MCP servers expose capabilities — file operations, database queries, API calls, shell commands — that any MCP-compatible agent can invoke. Every MCP tool call is an action that needs policy enforcement.

What MCP Tool Servers Can Do (And Why That's Risky)

MCP servers are middleware between AI agents and system capabilities. The protocol itself provides no authorization layer:

The MCP specification defines tool schemas but not authorization policies. Any MCP client (Claude Desktop, Cursor, Claude Code, custom agents) can call any tool on any connected server with any arguments. There is no per-call gating in the protocol.

Step-by-Step Setup

Step 1: Install SafeClaw

npx @authensor/safeclaw

Select MCP Proxy as the integration type. SafeClaw acts as a proxy between the MCP client and your MCP tool servers, evaluating every tool call in transit.

Step 2: Get Your API Key

Visit safeclaw.onrender.com. Free-tier keys renew every 7 days, no credit card required.

Step 3: Configure SafeClaw as an MCP Proxy

Instead of connecting your agent directly to MCP servers, connect it to SafeClaw, which proxies to the actual servers:

Before (direct connection):

{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["@modelcontextprotocol/server-filesystem", "/path/to/allowed"]
}
}
}

After (SafeClaw proxy):

{
"mcpServers": {
"safeclaw": {
"command": "npx",
"args": ["@authensor/safeclaw", "serve", "--mode", "mcp-proxy"],
"env": {
"SAFECLAW_API_KEY": "your-key-here",
"SAFECLAW_UPSTREAM_SERVERS": "./mcp-servers.json"
}
}
}
}

Where mcp-servers.json lists your actual MCP servers:

{
  "filesystem": {
    "command": "npx",
    "args": ["@modelcontextprotocol/server-filesystem", "/path/to/allowed"]
  },
  "postgres": {
    "command": "npx",
    "args": ["@modelcontextprotocol/server-postgres", "postgresql://localhost/mydb"]
  }
}

Step 4: Define Your Policy

version: 1
default: deny

rules:
# Filesystem server rules
- action: file_read
path: "${PROJECT_DIR}/**"
effect: allow

- action: file_read
path: "*/.env"
effect: deny

- action: file_write
path: "${PROJECT_DIR}/src/**"
effect: allow

- action: file_write
path: "${PROJECT_DIR}/tests/**"
effect: allow

- action: file_write
path: "${PROJECT_DIR}/config/**"
effect: deny

# Database server rules
- action: shell_exec
command: "SELECT*"
effect: allow

- action: shell_exec
command: "DROP*"
effect: deny

- action: shell_exec
command: "DELETE*"
effect: deny

- action: shell_exec
command: "ALTER*"
effect: deny

- action: shell_exec
command: "INSERT*"
effect: allow

- action: shell_exec
command: "UPDATE*"
effect: allow

# Network/API rules
- action: network
host: "api.github.com"
effect: allow

- action: network
host: "*.slack.com"
effect: deny

- action: network
host: "*"
effect: deny

Step 5: Test in Simulation Mode

npx @authensor/safeclaw simulate --policy safeclaw.policy.yaml --mode mcp-proxy

Route test traffic through the proxy. Review verdicts. Adjust. Then enforce.

What Gets Blocked, What Gets Through

ALLOWED — Agent reads source file through filesystem server:

{ "server": "filesystem", "tool": "read_file", "action": "file_read", "path": "/project/src/app.ts", "verdict": "ALLOW" }

DENIED — Agent writes to config directory:

{ "server": "filesystem", "tool": "write_file", "action": "file_write", "path": "/project/config/database.yaml", "verdict": "DENY", "reason": "path matches config/** deny rule" }

ALLOWED — Agent runs SELECT query through database server:

{ "server": "postgres", "tool": "query", "action": "shell_exec", "command": "SELECT * FROM users WHERE active = true", "verdict": "ALLOW" }

DENIED — Agent runs DROP TABLE through database server:

{ "server": "postgres", "tool": "query", "action": "shell_exec", "command": "DROP TABLE users", "verdict": "DENY", "reason": "DROP* matches deny rule" }

DENIED — Agent tries to send Slack message through API server:

{ "server": "slack", "tool": "send_message", "action": "network", "host": "hooks.slack.com", "verdict": "DENY", "reason": "*.slack.com matches deny rule" }

Without SafeClaw vs With SafeClaw

| Scenario | Without SafeClaw | With SafeClaw |
|---|---|---|
| Agent calls filesystem server delete_file on config | File deleted, configuration lost | Blockedconfig/** is denied for writes |
| Agent sends DROP TABLE to database server | Table dropped, data lost | BlockedDROP* matches explicit deny rule |
| Agent chains: read credentials file, send via Slack server | Credentials exfiltrated to Slack channel | Both blocked.env read denied, .slack.com network denied |
| Agent reads source files for context | Files read normally | Allowedsrc/ and tests/ in read allowlist |
| Agent inserts records through database server | INSERT executed | AllowedINSERT* matches allow rule |

SafeClaw proxies MCP tool calls with sub-millisecond policy evaluation and zero third-party dependencies. Every tool call verdict is logged to a tamper-proof SHA-256 hash chain audit trail. The control plane receives only action metadata — never your database credentials, file contents, or API tokens. SafeClaw is validated by 446 tests under TypeScript strict mode. The client is 100% open source, MIT licensed.

Cross-References

Try SafeClaw

Action-level gating for AI agents. Set it up in your browser in 60 seconds.

$ npx @authensor/safeclaw