About AgentGuard
AgentGuard is an MCP server that lets AI agents request NEAR payments through a vault governed by on-chain spending rules. It provides payment controls, address checks, and owner review for transactions flagged by policy or text scans.
Key features
- 01Request NEAR payments through a vault
- 02Enforce on-chain payment limits and approvals
- 03Check addresses against risk signals
- 04Review payment status and history
- 05Scan payment text for prompt injection
- 06Buy Sentinel checks through the vault
Use cases
- 01Let an agent pay an approved recipient
- 02Require owner approval for policy-triggered payments
- 03Check recipients before sending funds
- 04Hold requests when payment text is flagged
MCP support
It exposes tools for vault payments, address checks, balances, policy, payment status and history, plus optional Sentinel checks. The agent's key can request payments, while the vault contract applies the spending rules.
Configuration
Local server config is the same for every client. Copy it into your client’s MCP config file.
npx -y @zaxcoraider/agentguard-mcpAGENTGUARD_VAULTYour AgentGuard vault account, e.g. my-agent.agentguard.testnetNEAR_NETWORKtestnet (default) or mainnetAGENTGUARD_AGENT_KEYSecretThe agent's ed25519 function-call key; without it the server is read-onlyAGENTGUARD_KEY_FILESecretPath to a key file to read instead of AGENTGUARD_AGENT_KEYNEAR_RPC_URLOverride the NEAR RPC endpointSENTINEL_URLWhere to buy Sentinel's paid checkLocal servers need a runtime on your machine (e.g. Node.js 18+). Config file locations differ by client; see your client’s docs.
Tools
Local servers expose tools only once running on your machine, and the maintainer has not provided a tool list.
Details
From the project READMEAgentGuard MCP server
Lets any MCP agent (Claude Code, Claude Desktop, Codex, ...) pay on NEAR through an AgentGuard vault. The agent holds only a function-call key that can ask the vault to pay. The vault contract decides on-chain: paid, pending (waits for the human owner) or blocked. A prompt-injected agent can ask for anything; the contract still says no.
Tools
| Tool | What it does |
|---|---|
agentguard_pay | Ask the vault to pay recipient amount_near. Returns paid / pending / blocked, the reason and the tx link. Pass the invoice / email / page as source_text: if it shows prompt-injection tricks, the vault is asked to hold the payment for the owner (flagged_for_review) |
agentguard_check_address | "Is this address safe to pay?" Shared scam registry, account exists, is a contract, on the allowlist, lookalike names, and (with source_text) a prompt-injection scan of the text asking for the payment. Returns allow / warn / block + reasons |
agentguard_balance | Balance, available, spent in 24h, paid / blocked / pending counts |
agentguard_policy | Per-payment cap, 24h limit, approval threshold, allowlist, registry, locked |
agentguard_payment_status | One payment by id (e.g. did the owner approve it?) |
agentguard_history | Recent payment requests, including blocked ones |
agentguard_sentinel_check | Buys Sentinel's paid check over HTTP 402: pays the price through your vault (your rules apply; never above max_price_near, default 0.02), retries with X-PAYMENT, returns the check + tx. Set SENTINEL_URL |
Setup
cd packages/mcp
npm install
npm run build
Configuration (environment variables):
| Variable | Default | Meaning |
|---|---|---|
AGENTGUARD_VAULT | (required) | Your vault, e.g. demo2.agentguard.testnet |
NEAR_NETWORK | testnet | testnet or mainnet |
AGENTGUARD_AGENT_KEY | read from file | The agent's ed25519:... function-call key |
AGENTGUARD_KEY_FILE | ~/.near-credentials/<network>/<vault>.json | Where to read the key if the variable above is not set (created by scripts/gen-agent-key.mjs) |
NEAR_RPC_URL | FastNEAR public RPC | Override the RPC endpoint |
SENTINEL_URL | https://sentinel.agentguard.app | Where agentguard_sentinel_check buys checks (set http://localhost:3000 for a local Sentinel) |
Without a key the server still runs, read-only.
Claude Code
claude mcp add agentguard -e AGENTGUARD_VAULT=demo2.agentguard.testnet -- npx -y @zaxcoraider/agentguard-mcp
Published on npm as @zaxcoraider/agentguard-mcp. From a clone instead: -- node /absolute/path/to/packages/mcp/dist/index.js.
Then ask Claude: "Check if agentguard-evil.testnet is safe to pay, then pay agentguard-shop.testnet 0.05 NEAR for coffee."
Any MCP client (JSON config)
{
"mcpServers": {
"agentguard": {
"command": "npx",
"args": ["-y", "@zaxcoraider/agentguard-mcp"],
"env": { "AGENTGUARD_VAULT": "demo2.agentguard.testnet", "NEAR_NETWORK": "testnet" }
}
}
}
Get your own vault (testnet, about 2 minutes)
Needs near CLI and a testnet account (YOU.testnet). Every step below was run on testnet (vault guide-test.agentguard.testnet, see docs/TESTNET-RESULTS.md §9).
1. Create the vault from the factory. 1 NEAR goes into the vault (it stays yours). The vault is born with no full-access key:
near contract call-function as-transaction agentguard.testnet create_vault json-args '{
"name": "my-agent",
"policy": {"max_per_payment": "500000000000000000000000", "daily_limit": "1000000000000000000000000",
"approval_threshold": "200000000000000000000000", "unknown_recipient": "require_approval",
"pending_ttl_ns": "86400000000000"},
"allowlist": ["agentguard-shop.testnet"]
}' prepaid-gas '100 Tgas' attached-deposit '1 NEAR' sign-as YOU.testnet network-config testnet sign-with-keychain send
That's 0.5 NEAR max per payment, 1 NEAR per day, above 0.2 NEAR needs your approval, and strangers wait for you (amounts are in yoctoNEAR, 1 NEAR = 10^24).
2. Make the agent's key. It's saved to ~/.near-credentials/testnet/my-agent.agentguard.testnet.json; only the public key is printed:
node scripts/gen-agent-key.mjs my-agent.agentguard.testnet # from the repo root
3. Give that key to the vault. It can only call request_payment:
near contract call-function as-transaction my-agent.agentguard.testnet add_agent \
json-args '{"public_key": "ed25519:<printed key>", "label": "my-agent"}' \
prepaid-gas '30 Tgas' attached-deposit '1 yoctoNEAR' sign-as YOU.testnet network-config testnet sign-with-keychain send
4. Point the MCP server at it (AGENTGUARD_VAULT=my-agent.agentguard.testnet, see Setup) and ask your agent to pay. Results from the test run:
agentguard_pay agentguard-shop.testnet 0.1 -> paid
agentguard_pay agentguard-user.testnet 0.1 -> pending, unknown_recipient (approve or deny it as the owner)
As the owner, with 1 yoctoNEAR attached: approve {"id": "1"} / deny {"id": "1"}, add_to_allowlist, set_policy, withdraw, set_paused, and lock_rules (one-way; after it nobody can loosen the vault, you included). See contracts/vault.
Try it without an agent
npm test # 24 unit tests: scoring, lookalikes, prompt-injection scan, NEAR amount math, HTTP 402 payment checks
npx tsx scripts/live-demo.ts # starts the server over stdio and calls every tool on testnet
live-demo.ts needs the agent key for demo2.agentguard.testnet to make payments. Without it, the read-only tools still work and agentguard_pay returns an error saying the key is missing.
Expected (recorded 2026-11-03):
agentguard_check_address agentguard-evil.testnet -> block: flagged in the shared AgentGuard registry: ...
agentguard_check_address agentguard-sh0p.testnet -> block: does not exist; looks like trusted account agentguard-shop.testnet
agentguard_pay agentguard-shop.testnet 0.05 -> paid
agentguard_pay agentguard-evil.testnet 0.2 -> blocked, recipient_flagged
agentguard_pay agentguard-shop.testnet 5 -> blocked, over_per_payment_limit
What the agent can't do
The key is limited by NEAR itself to request_payment on the vault. It cannot transfer NEAR, call owner methods (withdraw, set_policy, approve, ...), attach deposits, call other contracts, add keys, deploy code or delete the account. Proof on testnet: scripts/prove-agent-key.sh (12/12 refused) and docs/TESTNET-RESULTS.md in the repo root.
agentguard_check_address is advice for the agent. The rules that matter run in the vault contract, whatever the agent decides.
Prompt-injection scan (src/inject.ts)
Give agentguard_pay or agentguard_check_address the text that asked for the payment (source_text). It is scanned for known tricks, with no model involved:
| Sign | Severity |
|---|---|
Invisible characters: zero-width, direction overrides, Unicode "tag" characters (hidden text is decoded and returned as hidden_text) | hostile |
| "Ignore your previous instructions", "new instructions:", "you are now…" | hostile |
| "Don't tell the owner", "without approval", "bypass the limit / allowlist" | hostile |
Fake role markers: <system>, [SYSTEM], <|im_start|> | hostile |
| Text aimed at an AI ("if you are an AI assistant…"), hidden HTML/CSS, "our payment address has changed", other NEAR accounts in the text, long encoded blobs | suspicious |
What happens: check_address turns hostile into block and suspicious into warn. agentguard_pay (which also scans the memo) sends any hit to the vault with force_review, so the contract holds the payment for the owner instead of paying it. The scan can only make things stricter. It is a heuristic and can be evaded; a clean scan proves nothing, and the vault's rules still decide. Live run: TESTNET-RESULTS §14 (scripts/injection-demo.mts: same shop, same kind of amount, the clean invoice is paid and the poisoned one is held).
Comments
New to MCP?
From what the protocol is to installing your first server, these answers cover most first questions.
An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.