npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@0xgks/mandate-mcp

v0.1.0

Published

MCP server for proof-gated MANDATE agent execution — a thin stdio wrapper around @0xgks/mandate-sdk for MoonPay Agent, Claude, Codex, and other MCP-compatible clients.

Readme

@0xgks/mandate-mcp

An MCP (Model Context Protocol) server that exposes MANDATE — a proof-gated, policy-constrained order execution protocol — to MoonPay Agent, Claude, Codex, or any other MCP-compatible AI client.

This package is a thin stdio wrapper around @0xgks/mandate-sdk. It does not reimplement any prover, commitment, Merkle-tree, or submission logic — every order that goes through it is proven with a real Noir/Barretenberg zero-knowledge proof and submitted through the real MANDATE contracts and sequencer, exactly as @0xgks/mandate-sdk's MandateClient.proveAndSubmit does it.

⚠️ MANDATE is unaudited research software. Do not use it, or this MCP server, with real funds or real private keys. The demo/test keys referenced anywhere in this repository are Anvil's public, well-known test keys — never use them (or this software) outside a local, throwaway chain.

Architecture

MoonPay Agent / Claude / Codex
        ↓  (MCP over stdio)
@0xgks/mandate-mcp        (this package — tool surface + env config only)
        ↓  (proveAndSubmit)
@0xgks/mandate-sdk        (prover wrapper, commitments, Merkle, submission)
        ↓
Noir prover (nargo + bb)  +  MANDATE sequencer  +  MANDATE smart contracts

MoonPay is the agent interface; MANDATE is the execution-policy layer. This server does not talk to MoonPay's trading APIs at all — "MoonPay Agent" here means the MCP-compatible agent runtime that will have this server registered as one of its tools. Whatever gives that agent read-only market data, quotes, or balances (MoonPay's own read-only tools, if you wire them up) is a separate concern from whether an order is allowed to execute. Execution only ever happens through this server's mandate_submit_order tool, which is proof-gated: see the security warning below.

What this server does NOT do

  • It does not expose any MoonPay swap, transfer, bridge, buy/sell, or wallet-signing tool. There is no way to move funds through this server except by proving compliance and going through mandate_submit_orderMandateClient.proveAndSubmit.
  • It does not implement a previewOrder/dry-run tool. @0xgks/mandate-sdk does not expose one, and this integration does not invent one — a "preview" that isn't backed by the real prover would be misleading about what authorizes execution.
  • It does not modify the Noir circuit, the contracts, the sequencer, or @0xgks/mandate-sdk. It only calls the SDK's public API and a small number of already-public, read-only contract views / sequencer endpoints.

⚠️ Security warning: do not also expose unrestricted MoonPay execution tools

If the same agent session also has access to unrestricted MoonPay transaction tools (swap, transfer, bridge, arbitrary signing), the agent can simply bypass MANDATE entirely by calling those tools directly instead of mandate_submit_order. MANDATE's proof-gating only has teeth if it is the only execution path available to the agent.

For a meaningful demo/deployment of the security model, an agent using this server should be given:

  • ✅ MANDATE's tools from this package (mandate_get_portfolio, mandate_get_epoch, mandate_submit_order)
  • ✅ read-only MoonPay tools if useful (balances, prices, token metadata, quotes)
  • not MoonPay's (or any other) unrestricted execution/signing tools

Prerequisites

This server calls out to the same toolchain the rest of the MANDATE repo needs — it does not bundle or replace any of it:

  • Node.js ≥ 20
  • nargo (matching the version used by circuits/policy_check) reachable on PATH, or via MANDATE_NARGO_PATH
  • bb (Barretenberg), reachable on PATH, or via MANDATE_BB_PATH
  • A running MANDATE stack to talk to: an EVM RPC endpoint with the MandateRegistry/BatchAuction contracts deployed, and a running MANDATE sequencer — see the repo root README / demo/run.sh for how to stand up a local Anvil-based stack
  • The compiled circuit artifacts (target/policy_check.json, target/vk) for whatever circuit directory MANDATE_CIRCUIT_PATH points at

Installation

Inside this monorepo (workspace-local development):

npm install
npm run build -w @0xgks/mandate-mcp

As a published package (once published):

npm install -g @0xgks/mandate-mcp
# or run without installing:
npx @0xgks/mandate-mcp

Configuration

All configuration is read from environment variables only — never from MCP tool arguments. This is intentional: an MCP client can ask this server to submit an order, but it can never redirect the server at a different RPC endpoint, a different sequencer, a different signer, or a different circuit.

See .env.example for a placeholder-only template (never commit a real .env — it's git-ignored, along with .env.*, everywhere except this example file).

Required

| Variable | Description | |---|---| | MANDATE_AGENT_ID | This agent's identity in the registry. A 0x-prefixed bytes32 hex value, or a plain decimal integer (padded automatically). | | MANDATE_SESSION_KEY | The session EOA's private key (0x-prefixed, 32 bytes). Never logged. The session key has zero authority over funds in MANDATE's design — only over proof-gated order submission. | | MANDATE_AUCTION_ADDRESS | BatchAuction contract address. | | MANDATE_REGISTRY_ADDRESS | MandateRegistry contract address. | | MANDATE_CIRCUIT_PATH | Absolute path to the Noir circuit project directory (containing Nargo.toml and a compiled target/) used for proving. |

Also required: the plaintext mandate (policy) parameters

@0xgks/mandate-sdk's MandateClient requires the plaintext mandate parameters — the opening of the on-chain policy commitment — to prove against. There is no way to recover this from the chain (only the one-way Poseidon2 commitment is stored on-chain), so it must be supplied here. These five variables must match exactly what is registered on-chain for MANDATE_AGENT_ID (MandateClient checks this and refuses to prove otherwise — see PolicyMismatchError):

| Variable | Description | |---|---| | MANDATE_WHITELIST_ROOT | Merkle root of the market whitelist (decimal or 0x-hex). | | MANDATE_MAX_ORDER_NOTIONAL | Max per-order notional (size * limitPrice). | | MANDATE_MAX_POSITION | Max post-fill absolute position. | | MANDATE_MAX_DAILY_LOSS | Max daily loss before the mandate rejects further risk-increasing orders. | | MANDATE_POLICY_SALT | The policy commitment's salt. |

These five variables are not part of the original brief's short env var list — they were added after inspecting @0xgks/mandate-sdk's actual MandateClientConfig type (packages/mandate-sdk/src/types.ts), which declares policy: PolicyParams as a required (non-optional) field. See the top of src/config.ts for the same note in code.

Optional (with defaults)

| Variable | Default | Description | |---|---|---| | MANDATE_RPC_URL | http://127.0.0.1:8545 | EVM JSON-RPC endpoint. | | MANDATE_SEQUENCER_URL | http://127.0.0.1:8787 | MANDATE sequencer base URL. | | MANDATE_NARGO_PATH | $NARGO_BIN or nargo on PATH | Override the nargo binary. | | MANDATE_BB_PATH | $BB_BIN or bb on PATH | Override the bb binary. | | MANDATE_MARKET_MAP | {"ETH/USDC":"1","ETH":"1","WBTC/USDC":"2","WBTC":"2"} | JSON object mapping human-readable market symbols (as used in tool calls, e.g. "ETH/USDC") to the circuit's numeric market id. Merged over the default map. A plain numeric string (e.g. "1") always passes through unchanged. |

Local development

# run directly against source with tsx (no build step)
MANDATE_AGENT_ID=0x... MANDATE_SESSION_KEY=0x... ... npm run dev -w @0xgks/mandate-mcp

# or build once, then run the compiled binary
npm run build -w @0xgks/mandate-mcp
MANDATE_AGENT_ID=0x... MANDATE_SESSION_KEY=0x... ... node packages/mandate-mcp/dist/index.js

The server communicates exclusively over stdio — it prints nothing to stdout except MCP protocol frames. All diagnostics (startup errors, proving failures, unexpected errors) go to stderr.

MCP Inspector

@modelcontextprotocol/inspector is the standard way to interactively exercise an MCP server over stdio:

cd packages/mandate-mcp
npx @modelcontextprotocol/inspector node dist/index.js

This opens a local web UI where you can browse the exposed tools and call them by hand. It also has a scriptable --cli mode, e.g.:

npx @modelcontextprotocol/inspector --cli node dist/index.js --method tools/list

(Note: the Inspector CLI's --tool-arg coerces numeric-looking values to JSON numbers, which will fail this server's schemas — amount/limitPrice are intentionally strings. Use the interactive web UI, or a raw JSON-RPC/stdio client, to pass them correctly quoted as strings.)

MoonPay Agent configuration

Register this server as an MCP tool provider. Restart the MCP client fully after any configuration change — most clients only read this file at startup.

Development (local build)

{
  "mcpServers": {
    "mandate": {
      "command": "node",
      "args": [
        "/ABSOLUTE/PATH/TO/mandate/packages/mandate-mcp/dist/index.js"
      ],
      "env": {
        "MANDATE_AGENT_ID": "1",
        "MANDATE_RPC_URL": "http://127.0.0.1:8545",
        "MANDATE_SEQUENCER_URL": "http://127.0.0.1:8787",
        "MANDATE_SESSION_KEY": "0x...",
        "MANDATE_AUCTION_ADDRESS": "0x...",
        "MANDATE_REGISTRY_ADDRESS": "0x...",
        "MANDATE_CIRCUIT_PATH": "/ABSOLUTE/PATH/TO/mandate/circuits/policy_check",
        "MANDATE_WHITELIST_ROOT": "0x...",
        "MANDATE_MAX_ORDER_NOTIONAL": "1000000",
        "MANDATE_MAX_POSITION": "1000",
        "MANDATE_MAX_DAILY_LOSS": "500",
        "MANDATE_POLICY_SALT": "42"
      }
    }
  }
}

Published npm package

{
  "mcpServers": {
    "mandate": {
      "command": "npx",
      "args": ["-y", "@0xgks/mandate-mcp"],
      "env": {
        "MANDATE_AGENT_ID": "1",
        "MANDATE_RPC_URL": "http://127.0.0.1:8545",
        "MANDATE_SEQUENCER_URL": "http://127.0.0.1:8787",
        "MANDATE_SESSION_KEY": "0x...",
        "MANDATE_AUCTION_ADDRESS": "0x...",
        "MANDATE_REGISTRY_ADDRESS": "0x...",
        "MANDATE_CIRCUIT_PATH": "/ABSOLUTE/PATH/TO/mandate/circuits/policy_check",
        "MANDATE_WHITELIST_ROOT": "0x...",
        "MANDATE_MAX_ORDER_NOTIONAL": "1000000",
        "MANDATE_MAX_POSITION": "1000",
        "MANDATE_MAX_DAILY_LOSS": "500",
        "MANDATE_POLICY_SALT": "42"
      }
    }
  }
}

Give the agent only this MCP server (plus, if desired, read-only MoonPay tools) — see the security warning above.

Test prompts

Once registered, these four prompts exercise every tool this server exposes. Use them verbatim in the MoonPay Agent (or Claude/Codex) chat:

Epoch test

Use the mandate_get_epoch tool and tell me the current epoch, phase, and breaker status.

Portfolio test

Use the mandate_get_portfolio tool and summarize the current portfolio state for the configured agent.

Valid order test

Use only mandate_submit_order to submit a buy order for 500 units at a price of 3500. Do not use any unrestricted wallet, swap, transfer, or MoonPay execution tool.

Invalid order test

Use only mandate_submit_order to attempt a buy order for 10000 units at a price of 3500. Return the exact policy or proof rejection reason. Do not bypass the MANDATE policy engine.

Whether the "valid order" prompt's 500 units actually clears depends on the configured agent's registered MANDATE_MAX_ORDER_NOTIONAL — see the note under mandate_submit_order below. Against the demo's default mandate (cap 1,000,000), 500 × 3500 = 1,750,000 would actually be rejected; either raise the amount's own agent's cap or use a smaller compliant amount (e.g. 250) when testing against the default demo policy.

Tools

mandate_get_portfolio

Read-only. No arguments. Returns this agent's current position, daily PnL, and anchored state root (cross-checked against the on-chain root).

mandate_get_epoch

Read-only. No arguments. Returns the current batch-auction epoch, phase ("commit" or "reveal"), and circuit-breaker bit.

mandate_submit_order

Generates a real zero-knowledge compliance proof and submits the proof-gated order through MANDATE. This is the only tool in this server that can put an order in the batch auction; there is no separate execution or signing tool, and there is no preview/dry-run mode. A preview is informational only does not apply here because there is no preview tool — only successful proof generation and protocol acceptance authorize an order.

Input:

{
  "market": "ETH/USDC",
  "side": "buy",
  "amount": "250",
  "limitPrice": "3500"
}

amount and limitPrice are positive whole-number strings (the circuit's size/limitPrice fields are u32; fractional amounts are rejected by input validation, not silently truncated). market may be a symbol from MANDATE_MARKET_MAP (default: ETH/USDC, ETH, WBTC/USDC, WBTC) or a raw numeric circuit market id. Note that amount * limitPrice must stay within the agent's registered MANDATE_MAX_ORDER_NOTIONAL — with the demo's default mandate (1,000,000), 250 × 3500 = 875,000 is compliant while 10,000 × 3500 = 35,000,000 (see the rejected example below) is not.

Valid order → real proof + submission

{
  "status": "submitted",
  "submitted": true,
  "orderCommitment": "0x022eb705af984a8e1682756a02238b58d065777e9588fa4fc477e58bb4be9912",
  "epoch": "7",
  "txHash": "0x39ad1cb0736b93eac40cd808861f878abd6032406fb85b88480119cd1ee7b26d"
}

(Captured from a real local run against a freshly deployed Anvil stack — independently confirmed on-chain via cast call <auction> "committedIn(uint64,bytes32)(bool)" 7 0x022eb7... → true.)

Rejected order → mandate violation, nothing touches the chain

{
  "status": "rejected",
  "submitted": false,
  "reason": "Assertion failed: order notional exceeds mandate maximum"
}

isError: true is set on the MCP tool result whenever submitted is false. The reason string is the real Noir circuit assertion message — this server preserves it rather than replacing it with a generic error.

Error handling

  • Full error detail (including stack traces) is only ever written to stderr, never returned to the MCP client.
  • Tool results carry a short, sanitized reason string. For the SDK's own error types (MandateViolationError, PolicyMismatchError, PortfolioMismatchError, EpochClosedError) this is the real, meaningful message (none of them embed key material). For anything else, it's the first line of the error message, length-capped.
  • The session private key is never included in any tool response or log line.

Known limitations

  • MandateClient does not expose a public portfolio- or epoch-reading method, so mandate_get_portfolio/mandate_get_epoch call the same read-only contract views and sequencer endpoint that MandateClient.proveAndSubmit uses internally, directly from this package — not through the SDK. No proving, commitment, or Merkle logic is duplicated; these are plain reads.
  • There is no mandate_preview_order tool: @0xgks/mandate-sdk exposes no preview/dry-run method, and one is not invented here.
  • MANDATE_MARKET_MAP is a convenience layer translating human-readable market symbols to the protocol's numeric market ids; it is not part of the MANDATE protocol itself.
  • This server assumes a single configured agent identity per process (one MANDATE_AGENT_ID/session key pair). Running multiple agents means running multiple server processes with different environments.