Using SafeClaw with MCP Servers: Tool Execution Gating
Scenario
You are developing an MCP (Model Context Protocol) server that exposes tools to AI clients. Your server provides tools like read_file, write_file, run_command, and fetch_url. Any MCP-compatible client (Claude Desktop, Cursor, custom agents) can invoke these tools. You need to ensure that no client can misuse your tools to access unauthorized files, run dangerous commands, or reach restricted network endpoints.
SafeClaw sits between the MCP tool handler and the actual execution layer. When a client calls a tool, the handler evaluates the action against your policy before executing it. The client receives a denial response if the action is blocked.
Threat Model
An MCP server without action-level gating on its tools exposes:
- Unrestricted file access. A
read_filetool without path restrictions lets any connected client read/etc/passwd,~/.ssh/id_rsa, or.envfiles containing secrets. - Arbitrary command execution. A
run_commandtool without command filtering becomes a remote shell for any connected AI agent. - Server-side request forgery (SSRF). A
fetch_urltool without domain restrictions lets clients probe internal network services, cloud metadata endpoints (169.254.169.254), or exfiltrate data. - Cross-client interference. Multiple clients connected to the same MCP server can affect each other's state if file writes are unrestricted.
- Supply chain risk. If your MCP server is distributed as a package, users who install it inherit whatever permissions the tools have, with no way to restrict them.
Recommended Policy
# MCP Server Tool Execution Policy
policy:
name: "mcp-server-tools"
default: DENY
rules:
# --- read_file tool ---
- action: file_read
path: "/workspace/**"
decision: ALLOW
- action: file_read
path: "/workspace/.env"
decision: DENY
- action: file_read
path: "/workspace/.env.*"
decision: DENY
- action: file_read
path: "/.ssh/"
decision: DENY
- action: file_read
path: "/etc/**"
decision: DENY
# --- write_file tool ---
- action: file_write
path: "/workspace/output/**"
decision: ALLOW
- action: file_write
path: "/workspace/src/**"
decision: REQUIRE_APPROVAL
- action: file_write
path: "/workspace/.git/**"
decision: DENY
- action: file_write
path: "/workspace/node_modules/**"
decision: DENY
# --- run_command tool ---
- action: shell_exec
command: "ls *"
decision: ALLOW
- action: shell_exec
command: "cat *"
decision: ALLOW
- action: shell_exec
command: "grep *"
decision: ALLOW
- action: shell_exec
command: "npm test*"
decision: ALLOW
- action: shell_exec
command: "npm run build*"
decision: ALLOW
- action: shell_exec
command: "rm *"
decision: DENY
- action: shell_exec
command: "sudo*"
decision: DENY
- action: shell_exec
command: "chmod*"
decision: DENY
- action: shell_exec
command: "curl*"
decision: DENY
# --- fetch_url tool ---
- action: network
domain: "api.github.com"
decision: ALLOW
- action: network
domain: "registry.npmjs.org"
decision: ALLOW
- action: network
domain: "169.254.169.254"
decision: DENY
- action: network
domain: "*.internal"
decision: DENY
- action: network
domain: "*"
decision: DENY
Example Action Requests
1. Client reads a project source file (ALLOW)
{
"action": "file_read",
"path": "/workspace/src/index.ts",
"agent": "mcp-client-claude",
"tool": "read_file",
"timestamp": "2026-02-13T11:00:00Z"
}
// Decision: ALLOW — path matches /workspace/**
2. Client reads a .env file (DENY)
{
"action": "file_read",
"path": "/workspace/.env",
"agent": "mcp-client-claude",
"tool": "read_file",
"timestamp": "2026-02-13T11:00:30Z"
}
// Decision: DENY — /workspace/.env is explicitly denied
3. Client writes to the output directory (ALLOW)
{
"action": "file_write",
"path": "/workspace/output/report.json",
"content": "{\"status\": \"complete\"}",
"agent": "mcp-client-cursor",
"tool": "write_file",
"timestamp": "2026-02-13T11:01:00Z"
}
// Decision: ALLOW — path matches /workspace/output/**
4. Client modifies source code (REQUIRE_APPROVAL)
{
"action": "file_write",
"path": "/workspace/src/utils.ts",
"content": "export function newHelper() { ... }",
"agent": "mcp-client-cursor",
"tool": "write_file",
"timestamp": "2026-02-13T11:02:00Z"
}
// Decision: REQUIRE_APPROVAL — /workspace/src/** requires human sign-off
5. Client attempts to reach cloud metadata endpoint (DENY)
{
"action": "network",
"domain": "169.254.169.254",
"method": "GET",
"path": "/latest/meta-data/iam/security-credentials/",
"agent": "mcp-client-unknown",
"tool": "fetch_url",
"timestamp": "2026-02-13T11:03:00Z"
}
// Decision: DENY — cloud metadata IP is explicitly denied
6. Client runs a safe command (ALLOW)
{
"action": "shell_exec",
"command": "npm test -- --reporter json",
"agent": "mcp-client-claude",
"tool": "run_command",
"timestamp": "2026-02-13T11:04:00Z"
}
// Decision: ALLOW — matches npm test*
Setup Steps
- Install SafeClaw in your MCP server project:
npx @authensor/safeclaw
The browser-based setup wizard opens. Free tier with 7-day renewable keys, no credit card required.
- Select the "MCP Server" template from the wizard. This pre-configures rules for common MCP tool patterns: file read, file write, shell exec, and network fetch.
- Integrate SafeClaw into each tool handler. The enforcement point sits between the MCP request handler and the execution function:
import { evaluate } from "@authensor/safeclaw";
server.setRequestHandler("tools/call", async (request) => {
const { name, arguments: args } = request.params;
if (name === "read_file") {
const decision = await evaluate({
action: "file_read",
path: args.path,
agent: request.meta?.clientId || "unknown",
tool: "read_file"
});
if (decision.result !== "ALLOW") {
return { content: [{ type: "text", text: Access denied: ${args.path} }] };
}
return readFile(args.path);
}
// ... repeat for write_file, run_command, fetch_url
});
- Block sensitive paths explicitly. Even though deny-by-default catches unknown paths, explicitly deny
.env,.ssh,/etc, and cloud metadata IPs for defense in depth.
- Use REQUIRE_APPROVAL for source code modifications. This lets connected clients suggest changes that you review in the SafeClaw dashboard before they take effect.
- Test with simulation mode. Connect your MCP clients and run typical workflows. The dashboard shows every tool invocation, the evaluated policy rule, and the decision.
- Ship with SafeClaw built in. When you distribute your MCP server, SafeClaw is included as part of the execution pipeline. Users can customize the policy through the dashboard without modifying server code.
- Monitor the audit trail. The tamper-proof SHA-256 hash chain logs every tool invocation with client identity, tool name, action parameters, and decision. Export for security review or incident response.
Cross-References
- SafeClaw Quickstart Guide — Full installation and first-run walkthrough
- MCP Integration Reference — Handler-level integration patterns for MCP servers
- Deny-by-Default Architecture — Why SafeClaw blocks everything unless explicitly allowed
- Action Types Reference — Complete schemas for file_read, file_write, shell_exec, and network
- REQUIRE_APPROVAL Workflow — How human-in-the-loop approval works for tool invocations
Try SafeClaw
Action-level gating for AI agents. Set it up in your browser in 60 seconds.
$ npx @authensor/safeclaw