Sandbox (no install)
Connect https://mcp.spendctl.dev/mcp (MCP over Streamable HTTP, no login) and let your model drive a real spendctl sidecar: budgets, refusals, approvals and receipts, exactly as in the quickstart, without installing anything.
Every sandbox is its own sidecar with a throwaway wallet, a mock x402 facilitator and two mock paid APIs, all inside one isolated process on our side. Nothing here is real: no funds move, no key of yours is involved, and the sandbox cannot reach any host on the internet. It is the same code as npx spendctl, so what you see is what the product does.
Connect
Section titled “Connect”| Client | How |
|---|---|
| Claude (web, desktop) | Settings → Connectors → Add custom connector → URL https://mcp.spendctl.dev/mcp, no authentication |
| Claude Code | claude mcp add --transport http spendctl-sandbox https://mcp.spendctl.dev/mcp |
| Cursor | .cursor/mcp.json: { "mcpServers": { "spendctl-sandbox": { "url": "https://mcp.spendctl.dev/mcp" } } } |
| VS Code | code --add-mcp '{"name":"spendctl-sandbox","type":"http","url":"https://mcp.spendctl.dev/mcp"}' |
| Anything else | Any MCP client that speaks Streamable HTTP; GET https://mcp.spendctl.dev/ describes the server |
| Tool | What it does |
|---|---|
sandbox_create |
Creates a sandbox and returns its sandbox_id, the agent’s policy and the paid endpoints. Presets: default (comfortable caps), strict ($0.015 per request, $0.03 per day, weather only), approvals (payments at or above $0.015 wait for a human). |
sandbox_pay |
The local pay tool against the sandbox: fetches a paid endpoint through the sidecar, which applies the policy and pays with the throwaway wallet or explains why not. Supports dryRun, idempotencyKey and approvalId. |
check_budget |
Limits, spend per window, what is left. |
list_receipts |
Recent attempts: paid, refused, waiting — with amounts, reasons and mock transaction hashes. |
get_policy |
The sandbox’s spendctl.yaml. |
approve |
Approves or denies a held sandbox payment, as a human would with spendctl approve. |
Paid endpoints inside a sandbox: https://weather.sandbox.spendctl.dev/weather?city=<name> ($0.01, x402 v2) and https://search.sandbox.spendctl.dev/search?q=<query> ($0.02, x402 v1). These hosts exist only inside the sandbox.
Try it
Section titled “Try it”Ask your model, for example:
Create a strict spendctl sandbox. Fetch the weather for Kyoto, then try the search API and explain why it was refused. Show the receipts and what is left of today’s budget.
Then the approval flow:
Create an approvals spendctl sandbox. Run a search for “mpp”: it should be held. Approve it and retry the payment with the approval id, then list the receipts.
What you should see: one settled receipt with a mock transaction hash, one denied (domain_not_allowed), a held attempt with an approval id, and the retry paid once approved. The same happens locally; the quickstart runs it on your machine and Real payments swaps the mock facilitator for a wallet of yours.
Limits
Section titled “Limits”- 200 governed payments and 20 pending approvals per sandbox; request bodies up to 16 KB; responses clipped at 20 000 characters.
- 5 sandboxes per minute and 120 requests per minute per client address.
- A sandbox is deleted after 2 hours without calls, and 24 hours after creation at the latest. Its
sandbox_idis the only key to it: anyone who has the id can use the sandbox, so do not put anything private into one.
What we record
Section titled “What we record”The sandbox contents (policy, mock receipts, approvals) live in isolated storage until the sandbox expires. For product metrics we count tool calls by tool name, outcome (ok / refused / error) and client family (for example Claude-User), nothing else: no tool arguments, no request or response bodies, no addresses. Rate limiting uses the client address inside Cloudflare’s rate limiter and is not stored by us. Details in the privacy policy.