zshield-mcp
Exposes a zcash_pay tool for agent-initiated shielded ZEC payments under policy, enforcing per-call spending caps and recipient allow-lists, with viewing-key fingerprinted audit logging. Chain interactions are currently mocked, with a live light-wallet adapter stubbed and refused at startup.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@zshield-mcpsend 0.05 ZEC to the demo merchant with memo 'invoice 123'"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.

zshield-mcp
Open-source MCP server that exposes one tool, zcash_pay, for agent-initiated shielded ZEC payments under human policy:
Hard per-call spending cap
Recipient allow-list
Append-only viewing-key fingerprinted audit log
Spend keys never belong in the model. Mock chain by default. A live adapter sends real shielded payments on Zcash testnet only through zingo-cli.

Purpose
Agents need a payment tool they can call safely. This server enforces policy before any payment attempt, records an audit row for every call (success or reject), and fingerprints viewing-key material so auditors can correlate receipts without storing raw keys in the log.
Built as a concrete, minimal artifact for design-partner review of shielded agent-payment MCP surfaces (see Zcash Community Grants discussions around agent/MCP payment tooling).
Related MCP server: cedulon
Demo
Real output of npm run demo:mock (mock chain, no coins spent): one payment allowed, one blocked by the spending cap, one blocked by the allow-list, then the audit log.

Quickstart
git clone <this-repo> zshield-mcp && cd zshield-mcp
cp .env.example .env
npm install
npm test
npm run build
npm start # stdio MCP serverPoint your MCP client (Cursor, Claude Desktop, etc.) at:
{
"mcpServers": {
"zshield": {
"command": "node",
"args": ["/absolute/path/to/zshield-mcp/dist/index.js"],
"env": {
"SPENDING_CAP_ZEC": "0.1",
"ALLOWLIST_PATH": "/absolute/path/to/zshield-mcp/allowlists/recipients.example.json",
"CHAIN_MODE": "mock",
"AUDIT_DIR": "/absolute/path/to/zshield-mcp/audits"
}
}
}
}Or during development: "command": "npx", "args": ["tsx", "src/index.ts"] with cwd set to the repo.
Tool: zcash_pay
Arg | Type | Required | Description |
| number | yes | Must be |
| string | yes | Must exactly match an allow-list |
| string | no | Optional memo (mock) |
Resource zshield://policy returns the active cap, allow-list path, and chain mode.
Config: caps & allow-list
Precedence: environment variables override config/default.yaml.
Variable | Default | Meaning |
|
| Hard max ZEC per tool call |
|
| JSON allow-list |
|
|
|
|
| JSONL audit directory |
| from yaml | Salt for view-key fingerprints |
Allow-list shape:
{
"recipients": [
{ "address": "u1…", "label": "Demo merchant" }
]
}Audit log format
JSONL per day: audits/YYYY-MM-DD.jsonl. Example success line:
{"ts":"2026-10-05T19:00:00.000Z","tool":"zcash_pay","amount_zec":0.05,"recipient":"u1…","allowlist_hit":true,"cap_zec":0.1,"status":"ok","mock_txid":"mock_…","view_key_fingerprint":"a1b2c3d4e5f60718","memo":"test"}Raw viewing-key material is never written, only a short fingerprint. See docs/AUDIT.md.
Layout
src/policy/ caps + allow-list
src/chain/ mock adapter, testnet adapter, address checks
src/audit/ JSONL writer + fingerprint
src/tools/ zcash_pay
src/server.ts MCP registration
tests/ happy path + rejectionsTestnet mode
What it does: with CHAIN_MODE=testnet the server checks cap, allow-list, and address network first, writes the audit row, and only then calls zingo-cli quicksend against a public testnet lightwalletd (default https://testnet.zec.rocks:443). Mainnet addresses (u1, zs1, t1) are rejected; testnet ones (utest, ztestsapling, tm) are accepted. CHAIN_MODE=live alone is refused.
Setup:
# build zingo-cli (Rust)
git clone https://github.com/zingolabs/zingolib && cd zingolib
cargo build --release -p zingo-cli
# create a fresh testnet wallet outside the repo and print its address
zingo-cli --chain testnet --server https://testnet.zec.rocks:443 \
--data-dir ~/.zshield-testnet/wallet addressesFund that address with TAZ from a testnet faucet such as https://faucet.testnet.valargroup.dev (API claim) or https://zcashfaucet.jinolabs.xyz and wait for it to confirm. Keep ~/.zshield-testnet/ private; it holds the wallet seed and is never inside the repo.
Run the MCP server in testnet mode:
CHAIN_MODE=testnet ZINGO_BIN=$(which zingo-cli) \
ZINGO_DATA_DIR=~/.zshield-testnet/wallet \
ALLOWLIST_PATH=./allowlists/testnet.json npm startOptional variables: ZINGO_BIN, ZINGO_DATA_DIR, LIGHTWALLETD_URL.
Run the demo:
npm run demo:testnetThe demo creates a second fresh testnet wallet as the recipient, writes a one-entry allow-list for it, and sends 0.001 TAZ through executePay, the same policy path the zcash_pay tool uses. It prints the txid and a link on https://blockexplorer.one/zcash/testnet. A confirmed txid proves the full path works end to end: policy checks, audit write, and a real shielded transaction on the Zcash testnet.
Proof: live testnet payment
One real shielded 0.001 TAZ payment through zcash_pay, plus a blocked over-cap attempt: tx 59d9cb1b5a47... on blockexplorer.one

Status / non-goals
✅ Mock payments, policy enforcement, audit
✅ Testnet shielded sends via zingo-cli
❌ Mainnet (refused by design)
❌ Custody of user spend keys
License
MIT
Available Tools
1 toolzcash_payA
Pay shielded ZEC to an allow-listed recipient under a hard per-call spending cap. Mock chain by default; writes a viewing-key-fingerprinted audit log entry.
| Name | Required | Description | Default |
|---|---|---|---|
| memo | No | Optional memo (mock only) | |
| recipient | Yes | Recipient address; must be on the allow-list | |
| amount_zec | Yes | Amount of ZEC to pay (must be <= spending cap) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full disclosure and does add real behavioral context: it discloses the mock-chain default (important so the agent doesn't assume real funds move), a hard per-call spending cap, and an audit-log side effect keyed by viewing-key fingerprint. It stops short of stating permissions, failure behavior, or reversibility, which is a gap for a payment tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler, with the core action and its constraints front-loaded before the secondary details (mock default, audit log). Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a payment tool with no annotations and no output schema, the description covers purpose, constraints, default execution mode, and a side effect. It omits error/failure semantics and whether the cap is configurable, but the essentials an agent needs to invoke it are present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all three parameters (memo, recipient, amount_zec) are already documented in the schema, including the allow-list and cap constraints. The description adds no parameter-level syntax or format detail beyond that, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource ('Pay shielded ZEC'), and further narrows scope with two constraints ('allow-listed recipient', 'hard per-call spending cap'). No siblings exist, so no differentiation is required, and the purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Mock chain by default' implies a real-chain mode exists, but the description never states when to use this tool versus other operations, nor any preconditions beyond the allow-list/spending-cap facts already implied by the schema. Usage is inferable but not spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.1.0- First observed
zcash_pay
TDQS
Scored across 1 tool
With only one tool, there is no possibility of overlap or misselection between tools. The single tool's purpose—paying shielded ZEC under a spending cap—is singular and unambiguous.
zcash_pay follows a clear snake_case resource_action pattern. There are no competing conventions to create inconsistency, so the naming is fully predictable for this server.
A single tool is very thin for a server named zshield-mcp, which implies broader policy, allow-list, and audit functionality. The pay tool itself is well-scoped, but the overall surface feels under-provisioned.
The description implies allow-listed recipients, spending caps, and audit logging, yet only the payment action is exposed. There are no tools to inspect the audit log, manage the allow-list, check balances, or query transaction status, leaving significant operational gaps.
Maintenance
Related MCP Connectors
Scoped agent execution. Server-side credentials, policy, budgets and verifiable receipts.
Advisory policy preflight for AI-agent spend requests; never executes payments or accesses wallets.
Agent payments, API key vaulting, and governed mandates. Agents spend within user-defined limits.
Agent-native MCP for governed commerce, x402 payments, paid capabilities, and verifiable receipts.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to propose wallet payments while a local, human-authored policy decides whether each transaction is approved, requires human confirmation, or is refused, and records every decision in a signed, append-only ledger.-
- AlicenseAqualityAmaintenancePolicy-gated agent spend with signed receipts and rail-extract audit: a fail-closed gate issues a COSE receipt for every allowed payment, and the audit reconciles those receipts against a rail extract so a settlement with no receipt is named rather than assumed. It settles on a mock rail, holding no wallet and signing no transaction.51Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables agents to inspect pot balances, deposits, deposit addresses, and spend approvals, and to pay for PaidResources on spark/USDB or send to allowlisted Spark addresses within a per-spend cap. Transactions above the cap become human approval tickets, and the pot key remains in the OS keychain so nothing is signed until approval.MIT
- AlicenseNot gradedqualityCmaintenanceEnables an AI agent to manage a Bitcoin wallet and request payments through MCP, while every spend requires a per-payment human approval code and defaults to signet.MIT