Skip to main content
A server your agent starts over stdio serves the wallets in a wallet directory, the same one sauce wallet uses. The agent can list them, create or import one, and send what the other tools build. Every send is simulated and checked against the wallet’s spending policy first. No tool takes or returns a key or a password. These are hot wallets: the key is on your machine, encrypted under a password the server reads from a source that you, or the agent through sauce_wallet_enable, name. Keep small balances in them. An agent that runs commands as you can read the same wallet files and password sources outside the server, and sign with them without the policy: Agents, wallets and keys. For real funds, sign with a wallet that keeps its own key (Sign with a wallet’s MCP server).

Prerequisites

  • The server added to your agent over stdio (The Sauce MCP server).
  • A wallet directory, created by sauce wallet new or by the server itself.
  • To send a cook, the release’s engine deployed on the chain. sauce pot --chain <chain> --owner <address> reports whether it is.

The wallet directory

On start, the server writes one line to stderr that names the directory and whether it can sign:
sauce_wallet_list and sauce_wallet_address read the directory with no password, because each wallet file names its address in the clear. sauce_wallet_create, sauce_wallet_import, sauce_wallet_send and sauce_sign need the wallets enabled by a password source. Before they are, those tools are refused with an error naming sauce_wallet_enable and its four sources.

Enable the wallets when the server starts

Give the server a password source as an argument. It reads the password once, before it serves anything: There is no prompt, because over stdio the protocol owns stdin. In an agent’s configuration, add the flag to the entry’s args:
With --password-env, your client must pass that variable into the server’s environment, through the env setting of the server entry. Put the password in the client’s environment or .env, and keep the .env out of version control. A server started this way prints signing with the wallets in <dir>. sauce_wallet_list then reports the source:
sauce_wallet_enable does not replace a source given at start:

Let the agent enable the wallets

Without a source at start, the agent calls sauce_wallet_enable once per server. The call names where the password comes from, never the password itself. Give exactly one of: Notes on the sources:
  • A file that others can read or write is refused.
  • generate also takes a path instead of true. The path must be in a directory that exists, outside the wallet directory. It never writes over an existing file.
  • The agent cannot name a shell command as a source. Only you can, with --password-command at start.
  • The password stays in the server’s memory for the life of the process and is never written to disk. With generate, the generated file holds it.
  • Calling sauce_wallet_enable again replaces the source. dir names another wallet directory.
A generated password sits in its file in the clear. Whoever can read that file and a wallet file holds that wallet’s key, so keep the file out of repositories, backups and synced folders. After a restart, { "file": "<that path>" } enables the same wallets again. The result of { "generate": true }:

Create, import and list

  • sauce_wallet_create { name, kind } makes a wallet with a fresh key. kind is evm (default) or solana. It returns the wallet’s name, kind, address, file and policy, never the key. A name already in use is refused: wallet agent exists: a wallet is never overwritten (pick another name).
  • sauce_wallet_import { name, path, kind } makes a wallet from a key file on the machine, named by path. The file is a keystore, a Solana keypair file or an EVM private key in hex. It must be a regular file only its owner can read, and it is left unchanged. A keystore must open with the wallets’ password.
  • sauce_wallet_list returns the directory, enabled, source and every wallet. sauce_wallet_address { name } returns one wallet.
There is no export tool. sauce wallet export shows a key only at a terminal.

Send from a wallet

sauce_wallet_send { wallet, transaction, chain?, rpcUrl? } signs and sends. transaction is one of:
  • the whole result of sauce_tx, sauce_pot, or sauce_actions with an owner, or of sauce_signed_cook or sauce_sign;
  • one transaction;
  • a list of transactions.
Build the transactions for the wallet’s address by passing it as owner.
1

Simulate

On an EVM chain, every transaction is simulated together in one eth_simulateV1 block from the wallet. On Solana, each is simulated as signed. If any would revert, nothing is sent.
2

Hold to the policy

Before any transaction is sent, each is measured against the wallet’s policy file, per transaction and per 24 hours: what it moves out of the wallet and its Pot, and the allowances it leaves other keys. On an EVM chain a transaction is made whole first, with the gas and fees it will be signed with, and signed exactly as measured. On Solana the plan’s setup, its rent and fees, is checked before any of it is sent, and a transaction is held to the policy of every wallet unlocked to sign it. What the policy does not allow is refused, with the limit named. A wallet with no policy file has no limits.
3

Send

Each transaction is sent in order and simulated again first. Sending stops at the first that does not succeed.
Each sent transaction comes back with its hash (a signature on Solana), status, explorer and trace. An EVM cook adds moves, leftInPot and summary. Wallets, passwords and spending policy documents the policy file, the ledger and the password rules. The server shares them with sauce wallet. Wallet sends are limited to the supported chains. On a preview chain the call is refused before anything is simulated, signed or sent:

Sign a cook another account sends

sauce_sign { wallet, source, chain, args, … } signs a cook with a wallet, as its Pot’s owner, for another account to send and pay the gas for: it is sauce sign --wallet, and returns the signature and cook, with deployPot while the Pot has no code. sauce_wallet_send takes that result, or cook alone, and sends it from whichever wallet you name, with exactly its value:
On a local fork of Base with the current contracts, this sequence deployed the owner’s Pot and ran its cook from the relayer’s wallet, and a cancelled signature’s cook was then refused: not sent — transaction 1 (1 of 1) would revert: NonceUsed(). A wallet whose policy sets a native or tokens limit refuses to sign one, naming the limit: a signed cook runs when someone else sends it, on the chain’s state then, so nothing simulated at signing bounds what it moves. chains and to still apply, with the Pot as the address. For a wallet kept elsewhere, sauce_signed_cook returns the typed data to sign and signs nothing.

Over HTTP, nothing signs

The HTTP server has no wallet tools, and it refuses the wallet and password flags at start:

Next steps