a2ally™ Sign up

MCP Guard · free · one file

Pin, police and prove every MCP tool call

A local proxy between your agent and any MCP server. It pins tool definitions so a quietly rewritten tool never reaches your agent, enforces your allow and deny rules, catches payment demands before anything is paid, and gives every call a tamper-evident receipt. Only hashes leave your machine.

Pins every tool definition

The first time the guard sees a server's tools it pins each one: name, description, input schema and annotations. If a definition later changes (the classic rug pull: a harmless tool quietly rewritten to exfiltrate), or a tool appears that was never announced, the guard withholds it from your agent and refuses its calls until you review it and start once with --approve.

Enforces your policy

A small JSON file: tools to allow and deny (with * wildcards), what to do when a definition changes, what to do when a server asks for payment, and a calls-per-minute ceiling. Refusals reach your agent as ordinary tool errors that say why.

Catches payment demands

When a tool answers with HTTP 402, a JSON-RPC 402 error or x402 payment requirements, the guard records the demand (amount, asset, network, recipient) and either passes it on to your agent or, under "payments": "block", refuses it. The guard never pays, holds no wallet and touches no money.

Gives every call a receipt

Each call, refusal, definition change and payment demand becomes a receipt in your a2ally record: hash-chained, timestamped and committed to the public ledger, so nobody, including us, can quietly edit it later.

Install

curl -fsSL --create-dirs -o ~/.a2ally/mcp-guard.mjs https://www.a2ally.com/cli/mcp-guard.mjs
curl -fsSL https://www.a2ally.com/cli/mcp-guard.sha256
shasum -a 256 ~/.a2ally/mcp-guard.mjs
node ~/.a2ally/mcp-guard.mjs --help

Version 1.0.0 · SHA-256 5c18cf697becf5649963e6c0696240b4d91fdbbcac65f6a1685351407faefe0e. The two hashes must match before you run it. The file is plain, readable JavaScript with no dependencies: read it first.

Put it in front of a server

Wrap the command your client already runs. The guard starts the server itself and passes everything through.

Claude Desktop claude_desktop_config.json

{
  "mcpServers": {
    "files": {
      "command": "node",
      "args": ["/Users/you/.a2ally/mcp-guard.mjs", "--name", "files", "--", "npx", "-y", "@modelcontextprotocol/server-filesystem", "/Users/you/Documents"],
      "env": { "A2ALLY_API_KEY": "<your key>" }
    }
  }
}

Claude Code terminal

claude mcp add files -e A2ALLY_API_KEY=<your key> -- node /Users/you/.a2ally/mcp-guard.mjs --name files -- npx -y @modelcontextprotocol/server-filesystem /Users/you/Documents

Cursor ~/.cursor/mcp.json

{
  "mcpServers": {
    "files": {
      "command": "node",
      "args": ["/Users/you/.a2ally/mcp-guard.mjs", "--name", "files", "--", "npx", "-y", "@modelcontextprotocol/server-filesystem", "/Users/you/Documents"],
      "env": { "A2ALLY_API_KEY": "<your key>" }
    }
  }
}

VS Code .vscode/mcp.json

{
  "servers": {
    "files": {
      "type": "stdio",
      "command": "node",
      "args": ["/Users/you/.a2ally/mcp-guard.mjs", "--name", "files", "--", "npx", "-y", "@modelcontextprotocol/server-filesystem", "/Users/you/Documents"],
      "env": { "A2ALLY_API_KEY": "<your key>" }
    }
  }
}

A remote MCP server any client

"command": "node",
"args": ["/Users/you/.a2ally/mcp-guard.mjs", "--name", "remote", "--url", "<server-url>/mcp", "--header", "Authorization: Bearer <that server's token>"]

No a2ally key yet? Add --accept-terms once: the first receipt opens a free account (terms) and the guard keeps its key in its state directory. Or add --no-record to pin and enforce locally and send nothing.

Policy

{
  "allow": ["read_*", "search_*", "premium_search"],
  "deny": ["delete_*", "send_*"],
  "on_change": "block",
  "payments": "block",
  "max_calls_per_minute": 60
}

Pass it with --policy policy.json. Without a policy everything is allowed except changed or unannounced tools. Deny wins over allow.

What leaves your machine

Per receipt, only:

What stays in the local log (~/.a2ally/mcp-guard/log/):

Each log line holds the full record and its SHA-256. To prove what a call contained, hand someone that one record: they hash it (canonical JSON, keys sorted, no whitespace) and compare the hash with the receipt. Then verify the receipt without an account.

What it does not prove

A receipt proves what was recorded and when, and that it has not changed since. It does not prove that a tool did what it said. The guard sees only the traffic that passes through it, and pinning is trust on first use: review a server's tools the first time you run it.

Download mcp-guard.mjs · See your receipts in the console · Why proof matters now · Markdown