MCP server
ZeroDust has two Model Context Protocol servers:
| Hosted | Package | |
|---|---|---|
| Where | https://api.zerodust.xyz/mcp |
@zerodust/mcp-server (0.5.2), run locally over stdio |
| Install | None | npx @zerodust/mcp-server |
| Read tools | Yes | Yes |
| Sweeping | No (it holds no keys) | Yes, when enabled with a key you configure |
Package setup
Requires Node.js 18 or later. Add the server to your MCP client's configuration. For Claude Desktop this is ~/Library/Application Support/Claude/claude_desktop_config.json on macOS:
{
"mcpServers": {
"zerodust": {
"command": "npx",
"args": ["@zerodust/mcp-server"]
}
}
}
Without further settings the server is read-only. It is also listed in the MCP registry as io.github.andresdefi/zerodust.
Environment variables
| Variable | Default | Notes |
|---|---|---|
ZERODUST_API_URL |
https://api.zerodust.xyz |
|
ZERODUST_API_KEY |
none | Sent as x-api-key. Raises the API's rate limits; see API keys. |
ZERODUST_ALLOW_EXECUTE |
unset | Set to true to allow sweeps. Needs exactly one signing key below. |
ZERODUST_ALLOWED_DESTINATIONS |
unset | Comma-separated addresses the agent may sweep to, besides its own |
ZERODUST_RPC_URLS |
unset | Your own RPCs for the sweep tools, as chainId=url pairs separated by commas (package 0.5.0 and later) |
Signing key, exactly one of:
| Variable | Notes |
|---|---|
ZERODUST_SIGNER_MODULE |
Path or package name of a module that returns a viem LocalAccount (see below) |
ZERODUST_KEYSTORE_FILE |
Encrypted V3 keystore (as written by cast wallet import or geth), with ZERODUST_KEYSTORE_PASSWORD_FILE (preferred) or ZERODUST_KEYSTORE_PASSWORD |
ZERODUST_PRIVATE_KEY_FILE |
File containing a hex private key |
ZERODUST_PRIVATE_KEY |
Hex private key inline. The key then sits in your MCP config file; use it only for a throwaway wallet. |
The server refuses to start when a key is set without ZERODUST_ALLOW_EXECUTE=true, when ZERODUST_ALLOW_EXECUTE=true is set without a key, when more than one key is set, or when an allowlist entry is not an address.
The key is used locally to sign the EIP-712 intent and the two EIP-7702 authorizations. It is never sent; only signatures reach the API. Sweeps use ZeroDustAgent from @zerodust/sdk, so every quote passes the pre-signing checks first.
Enabling sweeps
{
"mcpServers": {
"zerodust": {
"command": "npx",
"args": ["@zerodust/mcp-server"],
"env": {
"ZERODUST_ALLOW_EXECUTE": "true",
"ZERODUST_KEYSTORE_FILE": "/path/to/agent-keystore.json",
"ZERODUST_KEYSTORE_PASSWORD_FILE": "/path/to/agent-keystore.pass"
}
}
}
}
Relative paths resolve against the server's working directory, which the MCP client decides. Absolute paths are safer.
Signer module
The way to use a custody provider (Turnkey, Privy, a KMS) without a raw key anywhere. The module's default export may be a function (sync or async) that returns the account, or the account itself; a named createAccount function also works.
// my-signer.ts, compiled to my-signer.js
import type { LocalAccount } from 'viem';
// Stands in for your custody provider's SDK
declare const myProvider: { toViemAccount(): Promise<LocalAccount> };
export default async function createAccount(): Promise<LocalAccount> {
// Build a viem LocalAccount with your provider's SDK.
return await myProvider.toViemAccount();
}
The account must have address, signTypedData and signAuthorization. It is loaded on first use, and the server reports a clear error if any of these is missing.
Destination allowlist
By default the agent can only sweep to its own address. This limits what a prompt-injected agent can do: it cannot send funds to an address the operator never approved. Every address in ZERODUST_ALLOWED_DESTINATIONS can receive the agent's entire balance on every chain, so list only addresses you control.
Tools
| Tool | Hosted | Package | Inputs |
|---|---|---|---|
zerodust_info |
Yes | Yes | none |
zerodust_get_chains |
Yes | Yes | none |
zerodust_get_destinations |
Yes | Yes | fromChainId |
zerodust_get_balances |
Yes | Yes | address |
zerodust_get_quote |
Yes | Yes | fromChainId, toChainId, userAddress, destination |
zerodust_get_sweep_status |
Yes | Yes | sweepId |
zerodust_list_sweeps |
Yes | Yes | address, optional limit (1 to 100) |
zerodust_register_api_key |
Yes | Yes | name, optional agentId, contactEmail |
zerodust_get_agent_address |
No | Yes | none |
zerodust_sweep |
No | Yes | fromChainId, toChainId, optional destination, dryRun |
zerodust_sweep_all |
No | Yes | toChainId, optional destination, dryRun |
The package always lists the three sweep tools. Without ZERODUST_ALLOW_EXECUTE and a key they return an error that explains how to enable them, and move nothing.
zerodust_get_agent_address: the signing address, where the key comes from, and the permitted destinations. Call it before a sweep to confirm which wallet will be emptied.zerodust_sweep: empties one chain.destinationdefaults to the agent's own address and must pass the allowlist.zerodust_sweep_all: empties every chain with a balance ontotoChainId.dryRun: trueon either sweep tool runs the whole flow, including the three signatures, and stops before submitting. Nothing moves. Use it first.
The sweep tools use the SDK's public RPC for each chain. To use your own, set ZERODUST_RPC_URLS to chainId=url pairs, for example 8453=https://base.example/rpc,42161=https://arb.example/rpc. A malformed entry stops the server at startup rather than falling back silently.
Hosted server
POST https://api.zerodust.xyz/mcp takes JSON-RPC 2.0 (initialize, ping, tools/list, tools/call). It supports protocol versions 2025-06-18, 2025-03-26 and 2024-11-05.
curl -s https://api.zerodust.xyz/mcp \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
GET /mcp returns server info and the tool list; GET /mcp/tools returns the full tool definitions. Requests count against the API's per-IP rate limits.
Example prompts
- "Which chains does ZeroDust support?"
- "Check my balances on 0x..."
- "Quote sweeping my Arbitrum balance to Base"
- "Do a dry run of sweeping my Arbitrum balance to Base" (moves nothing)
- "Sweep my Arbitrum balance to Base"