> ## Documentation Index
> Fetch the complete documentation index at: https://docs.eco.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP tools

> The reference for what the Sauce MCP server serves, for anyone checking what an agent can call and what it gets back.

Most tools of the [Sauce MCP server](https://docs.eco.com/sauce-sdk/mcp/overview.md) call the same function as the `sauce` command of the same name. A result returns that command's `--json` output as structured content, with the same JSON as text. When a result has `notes`, they state what must be true for a transaction to land, or where a value came from.

Every input is described in the tool's schema, which `tools/list` returns. An input the schema does not name is refused:

```text theme={null}
MCP error -32602: Input validation error: Invalid arguments for tool sauce_compile: Unrecognized key: "bogus"
```

## Which tools a server lists

| Server | Tools | Left out |
| - | - | - |
| stdio, default (`sauce mcp`) | 27 | nothing |
| stdio with `--no-wallets` | 20 | the six wallet tools and `sauce_sign` |
| stdio with `--no-stores`, or HTTP (`--http <port>`) | 18 | the wallet tools, `sauce_sign`, `sauce_pot_list` and `sauce_pot_import` |

Every server lists these 18, in this order: `sauce_chains`, `sauce_globals`, `sauce_price`, `sauce_pools`, `sauce_compile`, `sauce_actions`, `sauce_tx`, `sauce_signed_cook`, `sauce_pot`, `sauce_reclaim`, `sauce_simulate`, `sauce_inspect`, `sauce_verify`, `sauce_send`, `sauce_skills`, `sauce_skill`, `sauce_dev`, `sauce_install_skills`.

A stdio server that keeps its stores also lists the stdio-only tools, after `sauce_send`:

* [`sauce_wallet_enable`](#sauce_wallet_enable)
* [`sauce_wallet_create`](#sauce_wallet_create)
* [`sauce_wallet_import`](#sauce_wallet_import)
* [`sauce_wallet_list`](#sauce_wallet_list)
* [`sauce_wallet_address`](#sauce_wallet_address)
* [`sauce_wallet_send`](#sauce_wallet_send)
* [`sauce_sign`](#sauce_sign)
* [`sauce_pot_list`](#sauce_pot_list)
* [`sauce_pot_import`](#sauce_pot_import)

`--no-wallets` removes the six wallet tools and `sauce_sign`. `--no-stores` removes all nine.

## Inputs and flags

A `sauce` command line maps onto the tools as follows:

* the command `sauce <command>` is the tool `sauce_<command>`;
* a program file is `source`, its text, or, over stdio, `path`, the file;
* a result is the command's `--json` output.

The flags map to inputs as follows:

| Flag | Input |
| - | - |
| `--args`, `--args-json` | `args` |
| `--assume-balance` | `assumeBalance` |
| `--fund`, `--fund-mode`, `--sweep` | `fund`, `fundMode`, `sweep` |
| `--owner`, `--salt`, `--salt-hex`, `--pot` | `owner`, `salt`, `saltHex`, `pot` |
| `--value` | `value` |
| `--account`, `--accounts` | `accounts` |
| `--via` | `via` |
| `--max-execution-fee` | `maxExecutionFee` |
| `--lookup-table` | `lookupTables` |
| `--cursor`, `--signature`, `--close` | `cursor`, `signatures`, `close: true` |
| `--keep`, `--keep-tables` | `keep`, `keepTables` |
| `--chain`, `--target` | `chain`, `target` |
| `--rpc-url` | `rpcUrl` |
| `--block` | `block` |
| `--pin`, `--engine`, `--min-out`, `--spl-count` | `pins`, `engines`, `minOut`, `splCount` |
| `--protocol`, `--stocks`, `--search` | `protocol`, `stocks`, `search` |
| `--sqrt-price-x96`, `--pool` | `sqrtPriceX96`, `pool` |
| `--v4-key`, `--pay`, `--price-limit`, `--per-venue`, `--slots` | `v4Pools`, `pay`, `priceLimit`, `perVenue`, `slots` |
| `--expect-revert` | `expectRevert` |
| `--max-fee`, `--nonce`, `--deadline`, `--within`, `--submitter` | `maxExecutionFee`, `nonce`, `deadline`, `within`, `submitter` (`sauce_signed_cook`, `sauce_sign`) |
| `--cancel`, `--signature` on `sauce sign` | `cancel`, `signature` |

Error messages and notes use the tools' words: a flag is named by its input (`saltHex`, not `--salt-hex`), and a command by its tool.

### Shared inputs

Several tools take the same inputs.

**The program.** These are taken by `sauce_compile`, `sauce_simulate`, `sauce_tx`, `sauce_signed_cook`, `sauce_sign` and `sauce_inspect`. `main`'s arguments are always ABI-v1 encoded.

| Input | Type | Meaning |
| - | - | - |
| `source` | string | The program: the whole text of a `.sauce.ts` file, at most 256 KiB. Required over HTTP. |
| `path` | string | stdio only, instead of `source`: the program's file on the server's machine, absolute or relative to the server's directory. It is read with its relative imports, as `sauce compile <file>` reads it. `sauce_compile`, `sauce_simulate`, `sauce_tx`, `sauce_signed_cook` and `sauce_sign` take it. |
| `file` | string | The program's file name, for messages and for resolving relative imports. Default `program.sauce.ts`. |
| `modules` | object | Files the program imports by relative path, as path → text. Each key is a path from the directory of `file`: for `file: "src/main.sauce.ts"` importing `./lib/math.sauce.ts`, the key is `lib/math.sauce.ts`. A key written from the root, `src/lib/math.sauce.ts`, is not found, and the compile fails with ``no module at `./lib/math.sauce.ts` ``. A key that starts with `../` is refused with `modules: '../outside.sauce.ts' is not a relative path inside the program's tree`, and an absolute key with `modules: '/lib/math.sauce.ts' is absolute: give it relative to the program`. An import may use `../` while it stays inside the directory of `file`: `lib/m.sauce.ts` importing `../util.sauce.ts` resolves to the key `util.sauce.ts`. An import that leaves that directory, such as `../outside.sauce.ts` from `src/main.sauce.ts`, fails with `import "../outside.sauce.ts" climbs above the project root`, whatever key is passed. `@sauce/token`, `@sauce/router`, `./artifacts/IERC20.json`, `./artifacts/ISauceRouter.json` and `./protocols/<slug>/<Export>.json` are served without being passed. |
| `chain` | string \| integer | The chain the program runs on: slug, alias or numeric id. |
| `target` | `"evm"` \| `"svm"` | Checked against the chain. `svm` alone means Solana. |
| `defines` | object | Low-level: compile-time values for names the program leaves undeclared. A program's inputs are `main`'s parameters, given as `args`. |

**The Pot and the cook.** These are taken by `sauce_simulate`, `sauce_tx` and `sauce_actions`. `sauce_pot` takes the Pot inputs.

| Input | Type | Meaning |
| - | - | - |
| `owner` | string | The Pot's owner: a `0x` address on an EVM chain, or on Solana a public key in base58 or as 32 bytes of `0x` hex. Only the owner may cook on the Pot. Any address works for `sauce_simulate`. |
| `salt` | string | A label naming one of the owner's Pots. The salt is its keccak256. With neither `salt` nor `saltHex`, the owner's default Pot (salt 0). |
| `saltHex` | string | The salt itself: 32 bytes of `0x` hex. |
| `pot` | string | EVM only: the Pot by address, instead of `owner` and salt. |
| `value` | string \| integer | EVM only: the cook's value in wei, which is the Kitchen's execution fee plus any native currency the program spends. Default: the fee, read from the chain. |
| `args` | array | `main`'s arguments in order, as JSON values: an integer in base units as a decimal string (or a number up to 2^53; negative for an `Int256` parameter, such as `"-5"`), an address as `0x` hex (a base58 key on Solana), bytes as `0x` hex, a bool, an array, a tuple as an array or an object. At most 64. |
| `accounts` | object | Solana only: each `Account` parameter of `main`, by name: an address, `pot`, `owner`, `system`, `pot:USDC`, `owner:USDC`, `@to:USDC`, `mint:USDC`, `program:USDC`, `slot:@pool:USDC.vaultA` or `pda:<program>:<seeds>`. Accounts the token methods and venue namespaces add are derived, so you name them only to replace one. |
| `via` | `"kitchen"` \| `"engine"` | Solana only: `kitchen` (default) is the Kitchen's cook on the owner's Pot; `engine` is the engine's own paid cook, with no Kitchen and no Pot, where the owner signs as the program's authority. |
| `maxExecutionFee` | string \| integer | Solana only: the most the cook may pay in execution fee, in lamports. A higher fee, as read from the cluster, is refused before anything is built. |
| `lookupTables` | string\[] | Solana only: address lookup tables holding the cook's accounts, read from the cluster. |
| `rpcUrl` | string | An RPC endpoint for this call only. See [How a tool reaches a chain](#how-a-tool-reaches-a-chain). |

**Token amounts.** `assumeBalance` and `fund` take `<TOKEN|address>:<amount>` strings:

* `USDC:1.5` is 1.5 USDC, in whole tokens, exact to the token's decimals.
* `USDC:1500000n` is 1.5 USDC: base units, with a trailing `n`.
* `USDC:1500000` is 1.5 million USDC, and the result's `notes` point this out.
* `ETH:<amount>` is the chain's native currency.

## Building tools

These thirteen tools are listed by every server.

### sauce\_chains

Lists every chain a program can run on, with its support status and where the server reads it. It reads nothing, takes no inputs and has no matching command.

Returns:

* `chains`: each chain's `slug`, `id`, `name`, `kind` (`evm` or `svm`), `aliases`, `support` and `endpoint`.
  * `support` is `"supported"` or `"preview"`.
  * `endpoint` is where the server reads the chain without a call's `rpcUrl`: `"config"` (the `--config` file), `"public"` (a built-in public endpoint) or `"none"`.
* `supported`: the supported slugs.
* `requestChain`: where to request a chain.

```json theme={null}
{
  "chains": [
    { "slug": "ethereum", "id": 1, "name": "Ethereum", "kind": "evm", "aliases": ["mainnet", "eth"], "support": "supported", "endpoint": "public" },
    { "slug": "optimism", "id": 10, "name": "Optimism", "kind": "evm", "aliases": ["op", "op-mainnet"], "support": "preview", "endpoint": "public" }
  ],
  "supported": ["ethereum", "base", "arc", "base-sepolia", "arc-testnet", "sepolia", "solana", "solana-devnet", "solana-testnet"],
  "requestChain": "<chain-support request form>"
}
```

The registry has 46 chains. Kava, ZetaChain and Evmos have `endpoint: "none"`.

### sauce\_globals

Lists the names a program on one chain may use without declaring them. It reads nothing. Matches `sauce globals`.

The result has:

* token symbols, with addresses and decimals;
* protocol namespaces, with each contract's address;
* on Solana, the venue namespaces and the accounts a program writes where it uses them;
* the chain names and the `@sauce/token` functions.

Tokenized stocks are left out unless `stocks` or `search` asks for them.

| Input | Type | Required | Flag | Meaning |
| - | - | - | - | - |
| `chain` | string \| integer | yes | `--chain` | The chain |
| `tokens` | boolean | | `--tokens` | Only the token symbols |
| `protocols` | boolean | | `--protocols` | Only the protocol namespaces |
| `protocol` | string | | `--protocol` | One namespace (`UniswapV4`) or its slug (`uniswap-v4`), with its methods' signatures |
| `stocks` | boolean | | `--stocks` | Only the chain's tokenized stocks |
| `search` | string | | `--search` | Only the tokens, stocks included, whose symbol, name, ticker or issuer contains this text, ignoring case |
| `offset` | integer | | none | The first token to return. Tokens come 200 to a page |

Returns `chain` (`key`, `slug`, `id`, `kind`), the lists the filters select, and `notes`. This result is for `{ "chain": "base", "tokens": true, "search": "USDC" }`:

```json theme={null}
{
  "chain": { "key": "Base", "slug": "base", "id": 8453, "kind": "evm" },
  "tokens": [
    { "symbol": "USDC", "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "decimals": 6 }
  ]
}
```

With `protocol: "UniswapV3"` the result has `protocol`, holding `namespace`, `name` and `contracts`, each contract with its `address` and `methods` (`name`, `signature`, `declaration`, `stateMutability`).

### sauce\_price

Turns a price into the numbers a swap program takes on an EVM chain, or reads a pool's price. Matches `sauce price`.

| Input | Type | Required | Flag | Meaning |
| - | - | - | - | - |
| `chain` | string \| integer | yes | `--chain` | The chain |
| `base` | string | yes | `<base>` operand | The token the price is per one of: a registered symbol, `<0x address>:<decimals>`, or, with an endpoint, a `0x` address alone |
| `quote` | string | yes | `<quote>` operand | The token the price is in, written the same ways |
| `price` | string | | `<price>` operand | How many whole quote tokens one whole base token is worth: `2700` |
| `sqrtPriceX96` | string | | `--sqrt-price-x96` | A pool's `sqrtPriceX96`, to read back as a price |
| `pool` | string | | `--pool` | A V3-style pool of the pair (Uniswap V3, PancakeSwap V3 or Aerodrome Slipstream), read now through an endpoint |
| `slippageBps` | integer | | none | How far from the price each direction's limit sits, in basis points: `50` is 0.5% |
| `feePpm` | integer | | none | The pool's fee in millionths (`3000` is 0.3%), included in each `minAvgPrice`. Default: the pool's own with `pool`, else none |
| `rpcUrl` | string | | `--rpc-url` | An endpoint for this call |

Give exactly one of `price`, `sqrtPriceX96` and `pool`.

Returns:

* `price`;
* `sqrtPriceX96`, for the pair's order;
* `token0` and `token1`;
* for selling (`sell`) and buying (`buy`) the base token: `priceLimit` and `maxAvgPrice` (input paid per output bought, times 1e18) and `minAvgPrice` (output per input, times 1e18);
* `units`, describing each value;
* with `slippageBps`, `limits`.

### sauce\_pools

Lists a pair's pools at the venues the registry records on the chain, with liquidity, deepest first, all read at one block. Matches `sauce pools`.

| Input | Type | Required | Flag | Meaning |
| - | - | - | - | - |
| `chain` | string \| integer | yes | `--chain` | The chain |
| `tokenA` | string | yes | first `<token>` operand | One token, paid in the first side: a registered symbol, a `0x` address, `<0x address>:<decimals>`, or on Solana a mint |
| `tokenB` | string | yes | second `<token>` operand | The other token |
| `v4Pools` | string\[] | | `--v4-key` | More hookless Uniswap V4 keys to try, each `<fee>:<tickSpacing>` |
| `block` | string \| integer | | `--block` | The block to read at: a number, or `latest`, `safe`, `finalized`. Default `latest` |
| `limit` | integer | | none | Return only this many pools; `more` counts the rest |
| `pay` | string | | `--pay` | Solana only: choose the pools a distributed swap paying this token takes |
| `priceLimit` | string | | `--price-limit` | With `pay`: only pools within this `priceLimit`, fee included |
| `perVenue` | boolean | | `--per-venue` | With `pay`: the deepest pool of each venue only |
| `slots` | integer | | `--slots` | With `pay`: how many slots the program has. Default 4 |
| `rpcUrl` | string | | `--rpc-url` | An endpoint for this call |

Returns:

* `chain`, `block`, `tokens` and `sortedBy`;
* `pools`, each with its venue, the contract a program finds it through, its address (or a V4 pool's id and key), fee, `tickSpacing`, liquidity, tick, `sqrtPriceX96`, and two `sides` with `mid`, `taker`, `priceLimit` and `depth1Pct`;
* `empty`, the pools with no liquidity, and `checked`, what was looked at;
* `more`, the count of pools that `limit` left out;
* on Solana, `skipped`, and with `pay`, `chosen`, `poolArgs` and `accounts`.

Pass `block` to `sauce_simulate` to simulate on the prices a limit was taken from.

### sauce\_compile

Compiles a program for a chain. It reads no chain. Matches `sauce compile`.

| Input | Type | Required | Flag | Meaning |
| - | - | - | - | - |
| `source` | string | one of `source`, `path` | `<file>` operand | The program's text |
| `path` | string | stdio only | `<file>` operand | The program's file, instead of `source` |
| `file` | string | | none | The program's file name |
| `modules` | object | | none | Files it imports by relative path |
| `chain` | string \| integer | | `--chain` | The chain |
| `target` | `"evm"` \| `"svm"` | | `--target` | Checked against the chain |
| `omitBytecode` | boolean | | none | Leave the bytecode out of the result, keeping its `size` |
| `args` | array | | `--args`, `--args-json` | `main`'s arguments, to size the payload |
| `accounts` | object | | `--account`, `--accounts` | Solana only: `main`'s accounts, to size the cook's transaction |
| `via` | `"kitchen"` \| `"engine"` | | `--via` | Solana only: size the Kitchen's cook (default) or the engine's own |
| `defines` | object | | `--define`, `--defines` | Low-level: compile-time values. A program's inputs are `main`'s parameters, given as `args` |

Returns:

* `chain`, `chainId`, `target`, `bytecode` (`0x` hex) and `size` in bytes;
* `entryEncoding`, always `abi-v1`, `entryParams` (`main`'s parameters) and `returnType`;
* `defines`, each name the compile resolved and where it came from;
* `contracts`, the protocol contracts the program calls;
* `compiler` and `engine`, the compiler and the released engine it pairs with;
* `sourceSha256`, the sha256 of the program's text;
* with `args`, the `payload`: its `size` and `argumentsSize`, in bytes;
* on Solana, the account `manifest`.

A program that does not compile is an error result with the compiler's message and where in the source the problem is.

This result is for the program below, on Base, with `omitBytecode`:

```ts pay.sauce.ts theme={null}
// Pays USDC from the Pot to a recipient.
//   sauce compile pay.sauce.ts --chain base
//   sauce simulate pay.sauce.ts --chain base --args <recipient> <amount>
// recipient: address that receives the USDC.
// amount: USDC to send, in base units (1000000 is 1 USDC).
function main(recipient: Address, amount: Uint256) {
  USDC.transfer(recipient, amount);
}
```

```json theme={null}
{
  "chain": "base",
  "chainId": 8453,
  "target": "evm",
  "size": 154,
  "payload": null,
  "entryEncoding": "abi-v1",
  "entryParams": [
    { "name": "recipient", "type": "Address" },
    { "name": "amount", "type": "Uint256" }
  ],
  "returnType": null,
  "defines": [
    { "name": "USDC", "value": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "source": "chain", "kind": "token", "chain": "base" }
  ],
  "contracts": [],
  "compiler": { "name": "@eco-incorp/sauce-compiler", "version": "<version>" },
  "engine": { "release": "<engine release>", "version": "<version>", "commit": "<commit>", "address": "<engine address>" },
  "sourceSha256": "7b20311abfc11f9d1897769b13f8fc3aaf7c6486c2d1ab7756c3fd91ea901b3b"
}
```

### sauce\_actions

Compiles an actions document (JSON) into the program that runs it on an EVM chain and, given a Pot, builds its unsigned cook. Matches `sauce actions`. The document is validated against the resource `sauce://actions/schema.json`.

| Input | Type | Required | Flag | Meaning |
| - | - | - | - | - |
| `program` | string \| object | yes | `<file>` operand | The document, `{ "version": 1, "actions": [...] }`, as an object or its JSON text |
| `chain` | string \| integer | | `--chain` | The chain to compile for. Needed when the document has no `chainId` |
| `target` | `"evm"` | | none | Always `evm` |
| `owner`, `salt`, `saltHex`, `pot` | string | | `--owner`, `--salt`, `--salt-hex`, `--pot` | The Pot. With one of them, the result also has `transaction` |
| `value` | string \| integer | | `--value` | The cook's value in wei |
| `args` | array | | `--args`, `--args-json` | `main`'s arguments |
| `accounts`, `via`, `maxExecutionFee`, `lookupTables` | | | as in [Shared inputs](#shared-inputs) | Present in the schema; actions run on EVM chains only |
| `rpcUrl` | string | | `--rpc-url` | An endpoint for this call |

Returns `sauce_compile`'s report for the generated program, plus:

* `source`, the generated SauceScript;
* `parameters`, the argument actions in the order `main` takes them;
* given a Pot, `transaction`: the unsigned cook, exactly as `sauce_tx` returns it.

On a preview chain, `refused` takes the place of `transaction`.

### sauce\_tx

Builds the unsigned transaction that runs a program on its Pot, for the Pot's owner to sign. Matches `sauce tx`.

| Input | Type | Required | Flag | Meaning |
| - | - | - | - | - |
| `source` / `path` | string | one of them | `<file>` operand | The program (`path` over stdio only) |
| `file`, `modules`, `chain`, `target`, `defines` | | | as in [Shared inputs](#shared-inputs) | The program's inputs; `defines` is low-level |
| `owner`, `salt`, `saltHex`, `pot` | string | | `--owner`, `--salt`, `--salt-hex`, `--pot` | The Pot |
| `value` | string \| integer | | `--value` | The cook's value in wei. Default: the Kitchen's fee, read from the chain |
| `args` | array | | `--args`, `--args-json` | `main`'s arguments |
| `accounts`, `via`, `maxExecutionFee`, `lookupTables` | | | `--account`, `--via`, `--max-execution-fee`, `--lookup-table` | Solana only |
| `fund` | string\[] | | `--fund` | EVM only: tokens the owner transfers into the Pot before the cook, as transactions after the Pot's deployment. `ETH:<amount>` is added to the cook's value instead |
| `rpcUrl` | string | | `--rpc-url` | An endpoint for this call |

Returns, on an EVM chain:

* **Pot deployed:** `{ chainId, to, data, value }`, the cook (`Pot.cook`) with `to` set to the Pot.
* **Pot not deployed yet:** `{ chainId, pot, transactions }`. The first transaction is `Kitchen.deployPot`, marked `deploysPot`, which any account may send. The cook comes last.
  * Each transaction has `gas`, the limit to sign it with. A cook that would revert after the deployment (for example, on a Pot not funded yet) has no `gas`, and a note says why. Fund the Pot after its deployment lands, not at its address before then, or pass `fund`, which with an endpoint plans a token's transfer after the deployment. `ETH:<amount>` adds to the cook's value, with no separate transfer.
  * `sendCalls` holds every transaction in order, for a wallet that sends a batch.
* Both forms carry `from`, the owner who must send the cook, and `kitchenFee` when it was read from the chain.

On Solana it returns `{ chain, via, feePayer, pot, fee, maxExecutionFee, createsPot, transaction, cursor }`, a base64 transaction for the owner to sign. A cook too large for one transaction comes as the first step of a plan, `{ step, plan, transactions, cursor }`, sent step by step through `sauce_send`.

Every result has `sourceSha256` and `notes`. On Arc, a note gives the chain's minimum base fee: each transaction must be signed with a `maxFeePerGas` (or `gasPrice`) of at least 20 gwei, or it is never mined.

On a preview chain it is refused before any endpoint is reached ([Supported and preview chains](#supported-and-preview-chains)).

### sauce\_signed\_cook

Builds a cook the Pot's owner signs and any account sends, with the Pot's `cookSigned` ([Signed cooks](https://docs.eco.com/sauce/pot.md#signed-cooks)). It signs nothing: it returns the EIP-712 typed data for the owner's wallet to sign, and, given that signature, checks it and builds the transaction to send. Every server lists it, stdio and HTTP. Matches [`sauce sign`](https://docs.eco.com/sauce-sdk/cli/sign) with no signer.

| Input | Type | Required | Flag | Meaning |
| - | - | - | - | - |
| `source` / `path` | string | one of them, unless `cancel` | `<file>` operand | The program (`path` over stdio only) |
| `file`, `modules`, `chain`, `target`, `defines` | | | as in [Shared inputs](#shared-inputs) | The program's inputs; `defines` is low-level |
| `owner`, `salt`, `saltHex`, `pot` | string | | `--owner`, `--salt`, `--salt-hex`, `--pot` | The Pot |
| `args` | array | | `--args`, `--args-json` | `main`'s arguments, appended to the program and signed with it |
| `value` | string \| integer | | `--value` | What the sender sends with the cook, in wei, signed exactly. Default 0: the Pot pays the Kitchen's fee from its own balance |
| `maxExecutionFee` | string \| integer | | `--max-fee` | The most of the Kitchen's fee the Pot pays, in wei, signed. Default: the fee read from the chain now |
| `nonce` | string \| integer | | `--nonce` | The nonce the cook runs once under. Default: random |
| `deadline` | string \| integer | | `--deadline` | The last unix second it may be sent, inclusive |
| `within` | string \| integer | | `--within` | Or how many seconds from the chain's latest block it may be sent. Default 3600 |
| `submitter` | string | | `--submitter` | The only account that may send it. Default: anyone |
| `signature` | string | | `--signature` | The owner's signature of `typedData`, made elsewhere: checked against the owner (a contract owner through ERC-1271), then `cook` is built |
| `cancel` | string\[] | | `--cancel` | Instead of a program: nonces to cancel, as the owner's unsigned `invalidateNonces` calls, one per word of nonces |
| `rpcUrl` | string | | `--rpc-url` | An endpoint for this call |

Returns `sauce sign --json`'s object:

* `chainId`, `pot`, `owner`, `engine`, `program`, `value`, `maxExecutionFee`, `nonce`, `deadline` and `submitter`: what is signed, numbers as decimal strings;
* `typedData`, as `eth_signTypedData_v4` takes it, and `digest`, the hash the signature is over;
* with `signature`, the `signature` and `cook`: `{ chainId, to: <the Pot>, data: cookSigned(…), value }`, for any account to send with exactly `value`;
* `deployPot` while the Pot has no code, for any account to send before `cook`;
* with `cancel`, `{ chainId, pot, owner, nonces, transactions, sendCalls }` instead, for the owner to sign and send;
* `notes`: who may send it and until when, the Kitchen's fee beside the ceiling and what the Pot holds.

Call it twice. The first call returns `typedData`; the owner's wallet signs it. The second call takes the same inputs without `within` (it is refused beside `deadline`), plus the `nonce`, `deadline` and `maxExecutionFee` the first returned, and `signature`, so it builds the same cook. On a local fork of Base with the current contracts, a signature made over one set of `args` and given with another was refused (`the signature given is not <owner>'s …`), and with the same inputs it returned `cook`. `sauce_wallet_send` from another wallet then sent `deployPot` and `cook`, and both succeeded.

A cook that reverts leaves its nonce unused, and whoever holds the result can send `cook` until the deadline. It is refused on a preview chain and on Solana, before any endpoint is reached ([Supported and preview chains](#supported-and-preview-chains)).

### sauce\_pot

Predicts the owner's Pot address, builds its unsigned deployment and, with an endpoint, reads what it holds. Matches `sauce pot`.

| Input | Type | Required | Flag | Meaning |
| - | - | - | - | - |
| `chain` | string \| integer | yes | `--chain` | The chain |
| `owner` | string | | `--owner` | The Pot's owner |
| `salt` | string | | `--salt` | A label naming one of the owner's Pots |
| `saltHex` | string | | `--salt-hex` | The salt itself |
| `balances` | boolean | | none | With an endpoint, read the Pot's balances. Default `true` |
| `rpcUrl` | string | | `--rpc-url` | An endpoint for this call |

Returns `chainId`, `pot`, `owner`, `salt` and `kitchen`, then the deployment:

* on an EVM chain, `Kitchen.deployPot` as `to`, `data` and `value`, with `sendCalls`;
* on Solana, the Kitchen's `create_pot` instruction, which the owner signs.

With an endpoint, it also returns:

* `deployed` (`null` without one);
* on an EVM chain, `kitchenFee`, the least a cook's `value` can be, with `symbol`, the chain's native coin;
* on an EVM chain, `balances`: `native` (with its `symbol`) and `tokens`, each registered token except tokenized stocks, `null` where a token cannot be read;
* on Solana, the Pot's associated token accounts.

On Arc the native coin is USDC, and the `USDC` token at `0x3600000000000000000000000000000000000000` reads the same balance. `balances.native` (18 decimals) and that token's entry (6 decimals) count it twice, and a note says not to add them. A note also gives Arc's 20 gwei minimum fee. This result is for an owner's default Pot on Arc, trimmed:

```json theme={null}
{
  "chainId": 5042,
  "pot": "0x6c9175d272D49e6C8C139A3FE6BC6fDb422eD3Fe",
  "owner": "0x1111111111111111111111111111111111111111",
  "salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "kitchen": "<kitchen address>",
  "to": "<kitchen address>",
  "data": "0xff9763ac…",
  "value": "0x0",
  "deployed": false,
  "kitchenFee": { "wei": "10000000000000000", "native": "0.01", "symbol": "USDC" },
  "balances": {
    "native": { "symbol": "USDC", "wei": "0", "formatted": "0" },
    "tokens": [ … ]
  },
  "notes": [
    "This is Kitchen.deployPot on the released Kitchen. Any account may send it: the Pot is 0x1111111111111111111111111111111111111111's either way, and it deploys once.",
    "On arc a transaction is included only with a maxFeePerGas (or gasPrice) of at least 20 gwei, the chain's minimum base fee: sign each with a fee cap at or above it, or it is never mined.",
    "On Arc the native coin is USDC, and the token at 0x3600000000000000000000000000000000000000 is the same balance: balances.native (18 decimals) and that token's entry (6) read it twice, so do not add them."
  ]
}
```

On Base the same call reports `kitchenFee.symbol` and `balances.native.symbol` as `ETH`.

On a preview chain the Pot is still predicted and read, and `refused` replaces the deployment. That result is not an error.

On an EVM chain, `sauce_pot`, `sauce_tx`, `sauce_actions` (with an owner), `sauce_simulate` and `sauce_signed_cook` (without `cancel`) hold the Pot to the [Pot guard](https://docs.eco.com/sauce-sdk/cli/pot.md#the-pot-guard) before anything is built: a Pot not deployed yet must be where the deployed Kitchen's `predictPot` puts it, a deployed one must be a Pot the deployed Kitchen created, and `owner` the zero address is refused. Without an endpoint the Kitchen cannot be read, so the address is not checked. With `cancel`, `sauce_signed_cook` builds the owner's nonce cancellations without these checks, as `sauce sign --cancel` does.

### sauce\_reclaim

Lists a Solana owner's open Kitchen code buffers and lookup tables, the rent they hold, and the unsigned transactions that close them. Matches `sauce reclaim`.

| Input | Type | Required | Flag | Meaning |
| - | - | - | - | - |
| `chain` | string \| integer | yes | `--chain` | The chain: `solana` |
| `owner` | string | yes | `--owner` | The owner's public key |
| `lookupTables` | string\[] | | `--lookup-table` | Tables to close, at most 24. Default: the owner's, scanned for |
| `keepTables` | boolean | | `--keep-tables` | Close the code buffers only |
| `keep` | string\[] | | `--keep` | Cursors of plans still under way, whose buffers and tables stay open |
| `rpcUrl` | string | | `--rpc-url` | An endpoint for this call |

Returns:

* `owner`;
* `buffers`;
* `lookupTables`, each with `state`: `active`, `deactivating` (with `closableFromSlot`) or `closable`;
* `lamports`, the total rent;
* `transactions`, in base64 for the owner to sign, then for `sauce_send`.

A buffer or an active table that a transaction named in the last 300 slots is listed with `inUse` and left open.

### sauce\_simulate

Simulates the cook from the Pot's owner against the chain's current state, or a pinned block. Nothing is signed or sent. Matches `sauce simulate`. It needs an endpoint.

| Input | Type | Required | Flag | Meaning |
| - | - | - | - | - |
| `source` / `path` | string | one of them | `<file>` operand | The program (`path` over stdio only) |
| `file`, `modules`, `chain`, `target`, `defines` | | | as in [Shared inputs](#shared-inputs) | The program's inputs; `defines` is low-level |
| `owner`, `salt`, `saltHex`, `pot` | string | | `--owner`, `--salt`, `--salt-hex`, `--pot` | The Pot. Any owner works |
| `value` | string \| integer | | `--value` | The cook's value in wei |
| `args` | array | | `--args`, `--args-json` | `main`'s arguments |
| `accounts`, `via`, `maxExecutionFee`, `lookupTables` | | | `--account`, `--via`, `--max-execution-fee`, `--lookup-table` | Solana only |
| `assumeBalance` | string\[] | | `--assume-balance` | Balances the Pot holds for this simulation only. EVM: by state override. Solana: in a local copy of the accounts the cook names |
| `fund` | string\[] | | `--fund` | EVM only: tokens the cook pulls from the owner into the Pot. The Pot is credited what the pulls would bring |
| `fundMode` | `"permit2"` \| `"permit"` \| `"allowance"` \| `"transfer"` | | `--fund-mode` | How `fund` pulls. Default `permit2` |
| `sweep` | boolean | | `--sweep` | With `fund`: return what is left of each funded token to the owner |
| `block` | string \| integer | | `--block` | EVM only: the block to simulate on |
| `scenarios` | object\[] | | none | 1 to 16 simulations of the same program at one block. Each has its own `args`, `assumeBalance`, `defines` and `expectRevert` |
| `expectRevert` | string | | `--expect-revert` | Expect a revert whose reason contains this text: `ok` and `asExpected` only when it does |
| `summary` | boolean | | none | Return only `ok` or the revert reason, what `main` returns, `leftInPot`, balance changes, transfers, each transaction's gas and the block |
| `rpcUrl` | string | | `--rpc-url` | An endpoint for this call |

On an EVM chain the simulation goes through `eth_simulateV1`, or through `eth_call` with state overrides where the endpoint lacks it; `path` says which. A Pot that is not deployed yet is deployed first in the simulation.

Returns:

* `ok`;
* `leftInPot`, what the Pot still holds of the tokens the cook moved;
* `transactions`, the gas of each transaction;
* what `main` returns;
* the ERC-20 transfers and approvals, native transfers, and each address's net balance change.

A cook that reverts is an error result, with `reverted: true`, `error` (the decoded reason), `ok: false` and the `stage`. With `scenarios`, the result is `{ ok, block, scenarios }`. On Solana the result reports compute units, the fee, each token account's change, and `computeStops`: each swap at a price, `held` with its `stopPrice` or `skipped`, and `deepTick` where its walk goes on into the furthest tick array its accounts give ([Swaps at a price and compute units](https://docs.eco.com/sauce-sdk/cli/solana.md#swaps-at-a-price-and-compute-units)).

### sauce\_inspect

Decodes a transaction, calldata or program back into what its author wrote: a `Pot.cook`, a `Kitchen.deployPot`, an ERC-20 call or a bare program. Matches `sauce inspect`.

| Input | Type | Required | Flag | Meaning |
| - | - | - | - | - |
| `hex` | string | | operand | `0x` hex: calldata, a program, or a 32-byte transaction hash, which is fetched on `chain` |
| `source` | string | | `--source` | The program the hex was compiled from, to check it and decode the arguments against `main`. Alone, the program to inspect |
| `file`, `modules`, `chain`, `target`, `defines` | | | as in [Shared inputs](#shared-inputs) | The program's inputs; `defines` is low-level |
| `rpcUrl` | string | | `--rpc-url` | An endpoint, for a transaction hash |

Returns the decoded call or program, and `notes`.

### sauce\_verify

Checks whether a settle payload, a `Pot.cook` or a transaction runs the settle program the package ships, and with which parameters. Matches `sauce verify`.

| Input | Type | Required | Flag | Meaning |
| - | - | - | - | - |
| `hex` | string | | operand | A settle payload, `Pot.cook` calldata, or a transaction hash |
| `signature` | string | | operand | Solana: the cook transaction's signature, in base58 |
| `chain` | string \| integer | | `--chain` | The chain a transaction is on |
| `pins` | string\[] | | `--pin` | Historical settle programs also accepted, each `<0x keccak256>:<bytes>` |
| `engines` | string\[] | | `--engine` | Engines also accepted besides the released one |
| `minOut` | string \| integer | | `--min-out` | Solana: the floor the settle enforces, in base units |
| `splCount` | string \| integer | | `--spl-count` | Solana: how many escrows the settle sweeps with its first token program |
| `rpcUrl` | string | | `--rpc-url` | An endpoint, for a transaction |

Returns `valid: true` with the settle's tokens, `minOut` and recipient. Otherwise it returns `valid: false` with the rejection `code`, as a result rather than an error.

## Sending signed transactions

### sauce\_send

Broadcasts transactions a wallet or signer has already signed, waits for each to land, and reports what each did. It takes no key and never signs. Every server lists it, stdio and HTTP. Matches `sauce send`.

| Input | Type | Required | Flag | Meaning |
| - | - | - | - | - |
| `transactions` | string\[] | | operands | The signed transactions in sending order, at most 32: raw `0x` hex on an EVM chain, base64 wire transactions on Solana |
| `cursor` | string | | `--cursor` | Solana: a plan's cursor from `sauce_tx` or the last `sauce_send`. Alone, it builds the plan's next step without sending |
| `signatures` | string\[] | | `--signature` | Solana: signatures of the plan's transactions broadcast another way, to confirm |
| `close` | boolean | | `--close` | Solana, with `cursor`: give up on the cook and close the code buffer the plan staged |
| `chain` | string \| integer | | `--chain` | Needed only for a legacy EVM transaction signed without a chain id |
| `rpcUrl` | string | | `--rpc-url` | An endpoint for this call |

How it sends:

* Each transaction is simulated as signed first: on an EVM chain an `eth_call` from its sender, on Solana a simulation that checks every signature.
* A transaction that would fail is not sent.
* On an EVM chain, every cook and Pot deployment among the transactions is held to the [Pot guard](https://docs.eco.com/sauce-sdk/cli/pot.md#the-pot-guard) first, all together. One that fails it stops the batch before anything is sent, naming it: `nothing was sent — transaction 2 of 2 (cook on Pot 0x…): …`.
* Each transaction lands before the next is simulated, and the first that does not succeed stops the rest.
* A transaction already on chain is read back, not sent again.
* On Arc, a transaction signed with a fee cap below the chain's 20 gwei minimum base fee is refused before anything is sent:

  ```text theme={null}
  transaction 1 is signed with a fee cap of 1 gwei, below arc's minimum base fee of 20 gwei, so it would never be included: sign it again with a maxFeePerGas of at least 20 gwei. Nothing was sent
  ```

Returns:

* `chain`, `chainId` and `ok`;
* `sent`, each entry with its `hash` (a signature on Solana), `status`, `explorer`, `trace`, fee or gas, and the decoded `reason` of a failure. A cook also lists what moved and `leftInPot`.
* `pots`, for each Pot a transaction deployed. A server that keeps the Pot store records them there.
* with a `cursor`, `next`, the plan's next step.

## Skill tools

These four tools are listed by every server. The same files are also served as [resources](#resources).

### sauce\_skills

Lists every agent skill the server carries, with when to use it and its files. It takes no inputs.

Returns `package`, `version`, `latest` (a newer published version, when there is one), `index` (`sauce://skills/index`) and `skills`, each with `name`, `description` and files with sizes. The package carries 13 skills.

### sauce\_skill

Returns one skill's `SKILL.md`, or one of its files under `references/` or `examples/`. Only files the package ships are served.

| Input | Type | Required | Meaning |
| - | - | - | - |
| `skill` | string | yes | The skill's name, as `sauce_skills` lists it: `sauce-overview` |
| `path` | string | | A file of that skill, relative to its directory. Default `SKILL.md` |
| `section` | string | | Only the part under the heading that holds these words |
| `query` | string | | Only the lines that hold this text, numbered, with two lines around each |

Returns `skill`, `path`, `uri`, `mimeType`, `bytes` and `text`.

### sauce\_dev

Returns the package's own documents (guides, API pages and runnable examples) for TypeScript work against the SDK, the `sauce` command, or this server.

| Input | Type | Required | Meaning |
| - | - | - | - |
| `topic` | `"start"` \| `"compile"` \| `"protocols"` \| `"actions"` \| `"execution"` \| `"solana"` \| `"verification"` \| `"testing"` \| `"api"` \| `"language"` \| `"cli"` \| `"mcp"` | | One topic |
| `question` | string | | Or the task in words; the topics are found from them |

Returns `topics` and `documents`, each with its `path` and `text`.

### sauce\_install\_skills

Returns the commands that set up a project for one coding agent, pinned to the server's own version. It writes nothing. Matches `sauce skills` and `sauce mcp setup`.

| Input | Type | Required | Meaning |
| - | - | - | - |
| `agent` | `"claude"` \| `"codex"` \| `"cursor"` \| `"copilot"` \| `"gemini"` \| `"agents-md"` | yes | The coding agent |
| `dir` | string | | The project directory the commands are for. Default: the current one |
| `config` | string | | An RPC endpoints file for the server to start with. It must exist and hold real URLs |

Returns:

* `agent`, `version` and `skillsFrom`, where the agent reads skills;
* `commands`: `add`, `install`, `update`, `status`, `init` and `mcpSetup`;
* `mcp`, the file `sauce mcp setup` writes for that agent, with its exact content.

```json theme={null}
{
  "agent": "claude",
  "version": "<version>",
  "skillsFrom": [".claude/skills"],
  "commands": {
    "install": "npx -y @eco-incorp/sauce@<version> skills install --agent claude",
    "update": "npx -y @eco-incorp/sauce@<version> skills update --agent claude",
    "mcpSetup": "npx -y @eco-incorp/sauce@<version> mcp setup --agent claude"
  },
  "mcp": { "path": ".mcp.json", "config": "{ \"mcpServers\": { \"sauce\": { … } } }" }
}
```

## Wallet tools (stdio only)

A stdio server started without `--no-wallets` or `--no-stores` lists these seven tools. They serve the wallet directory: `~/.sauce/wallets` by default, or the directory `--wallets <dir>` names. The HTTP server never lists them. [Wallets over stdio](https://docs.eco.com/sauce-sdk/mcp/wallets.md) covers the flow.

### sauce\_wallet\_enable

Enables the server's wallets to create, import and sign for the rest of the process's life. It takes the password's source, never the password. Give exactly one source.

| Input | Type | Required | Meaning |
| - | - | - | - |
| `env` | string | | The name of a variable in the server's environment, never its value |
| `file` | string | | A password file only its owner can read (`chmod 600`), the password on its first line. `~/` is the home directory |
| `dotenv` | string | | A `.env` file only its owner can read |
| `variable` | string | | With `dotenv`: the entry's name. Default `SAUCE_WALLET_PASSWORD` |
| `generate` | `true` \| string | | `true`: write a new random password to a new file beside the wallet directory (`<dir>.password`). A string is the path of the new file. It never writes over an existing file |
| `dir` | string | | Another wallet directory. Default: the server's |

Returns `dir`, `enabled`, `source`, `wallets` and, with `generate`, `passwordFile`. A server started with a password source refuses to change it.

### sauce\_wallet\_create

Creates a wallet with a fresh key, encrypted under the wallets' password. Matches `sauce wallet new`. It needs the wallets enabled.

| Input | Type | Required | Flag | Meaning |
| - | - | - | - | - |
| `name` | string | yes | `<name>` operand | Lowercase letters, digits, `-` and `_` |
| `kind` | `"evm"` \| `"solana"` | | `--solana` | `evm` (default) or a Solana keypair |

Returns `name`, `kind`, `address`, `path` and `policy` (`null` when there is no policy file), never the key. An existing name is refused.

### sauce\_wallet\_import

Imports the key a file on the server's machine holds, named by its path, as a new wallet. Matches `sauce wallet import`. It needs the wallets enabled. The file must be a regular file only its owner can read, and it is left as it is.

| Input | Type | Required | Flag | Meaning |
| - | - | - | - | - |
| `name` | string | yes | `<name>` operand | The new wallet's name |
| `path` | string | yes | `<file>` operand | The key file: a keystore, a Solana keypair file (a JSON array of 64 bytes, or base58), or an EVM private key in hex |
| `kind` | `"evm"` \| `"solana"` | | `--solana` | What the file must hold |

Returns `name`, `kind`, `address` and `policy`, never the key.

### sauce\_wallet\_list

Lists the wallets. It needs no password and reads no chain. Matches `sauce wallet list`. It takes no inputs.

Returns:

* `dir`, the wallet directory;
* `enabled`, and the `source` that enabled the wallets;
* `wallets`, each with `name`, `kind`, `address` and `policy`.

### sauce\_wallet\_address

Returns one wallet's `name`, `kind`, `address` and `policy`. It needs no password. Matches `sauce wallet address`.

| Input | Type | Required | Flag | Meaning |
| - | - | - | - | - |
| `name` | string | yes | `<name>` operand | The wallet's name |

### sauce\_wallet\_send

Signs and sends, from one of the server's wallets, the transactions another tool built unsigned. It needs the wallets enabled. It has no single matching command; it signs as `--wallet` does on `sauce run` and the other sending commands.

| Input | Type | Required | Meaning |
| - | - | - | - |
| `wallet` | string | yes | The wallet's name |
| `transaction` | object \| object\[] \| string | yes | What to send, as JSON or its text: the whole result of `sauce_tx`, `sauce_pot`, `sauce_actions` (with an owner), `sauce_signed_cook` or `sauce_sign`; one transaction, `{ chainId, to, data, value }` or a Solana `{ transaction }`; or a list |
| `chain` | string \| integer | | The chain, when the transactions do not name it |
| `rpcUrl` | string | | An endpoint for this call |

How it sends:

1. It simulates every transaction first: on an EVM chain all together in one `eth_simulateV1` block, on Solana each as signed. If any would revert, it sends nothing. On an EVM chain it holds every cook and Pot deployment to the [Pot guard](https://docs.eco.com/sauce-sdk/cli/pot.md#the-pot-guard) too, and a step that fails it stops the plan before anything is sent.
2. It holds the transactions to the wallet's policy, and refuses, naming the limit, what the policy does not allow.
3. It sends each in order and stops at the first that does not succeed.

Returns `wallet`, `from`, `chain`, `ok`, `policy` and `sent`. Each entry of `sent` has `hash`, `status`, `explorer` and `trace`. An EVM cook adds `moves`, `leftInPot` and `summary`. A Pot deployment adds `pots`.

A signed cook's result sends `deployPot`, when there is one, then `cook`, from whichever wallet you name: the owner signed it, and any wallet sends it. A signed cook already sent is refused before anything is sent: `not sent — transaction 1 (1 of 1) would revert: NonceUsed()`.

### sauce\_sign

Signs a cook with one of the server's EVM wallets, as the Pot's owner, for another account to send: `sauce_signed_cook` signed here. It needs the wallets enabled. Matches `sauce sign --wallet`.

| Input | Type | Required | Meaning |
| - | - | - | - |
| `wallet` | string | yes | The wallet that signs: the Pot's owner |
| `source`, `path`, `file`, `modules`, `chain`, `target`, `defines` | | | The program, as in [Shared inputs](#shared-inputs); `defines` is low-level |
| `owner`, `salt`, `saltHex`, `pot` | string | | The Pot. Default: the wallet's own Pot; the wallet must own the Pot named |
| `args` | array | | `main`'s arguments |
| `value`, `maxExecutionFee`, `nonce`, `deadline`, `within`, `submitter` | | | What is signed, as [`sauce_signed_cook`](#sauce_signed_cook) takes them |
| `cancel` | string\[] | | Instead of a program: nonces to cancel. The wallet sends one `invalidateNonces` per word of nonces to its Pot |
| `rpcUrl` | string | | An endpoint for this call |

Returns `sauce_signed_cook`'s result with `signature` and `cook`, and `deployPot` while the Pot has no code. With `cancel` it returns `{ chainId, pot, from, nonces, sent }`, each sent cancellation with its `hash`, `status`, `gasUsed`, `explorer` and `trace`. `sauce_wallet_send` sends `cook` from any of the server's wallets.

A wallet whose policy sets a `native` or `tokens` limit refuses to sign, naming the limit: a signed cook runs when someone else sends it, on the chain's state then, so its outflows cannot be measured when it is signed. `chains` and `to` still apply, with the Pot as the address. It is refused on a preview chain and on Solana.

## Pot store tools (stdio only)

A stdio server started without `--no-stores` lists these two tools. They read and write the Pot store that `sauce pot list` and `sauce pot import` use: `~/.sauce/pots` by default, or the directory `--pots <dir>` names. [Local server storage](https://docs.eco.com/sauce-sdk/mcp/local-server.md) covers the store.

### sauce\_pot\_list

Lists the Pots recorded in the store. It reads no chain. Matches `sauce pot list`.

| Input | Type | Required | Meaning |
| - | - | - | - |
| `chain` | string \| integer | | Only the Pots on this chain |
| `owner` | string | | Only this owner's Pots |

Returns `store` and `pots`. Each Pot has:

* its chain, address, owner, salt and kind;
* its Kitchen;
* `release` and `engine`, the release it was minted under;
* `deployment`, the transaction that deployed it.

### sauce\_pot\_import

Records in the store a Pot this machine did not deploy, read from the chain. Matches `sauce pot import`.

| Input | Type | Required | Meaning |
| - | - | - | - |
| `chain` | string \| integer | yes | The chain |
| `pot` | string | | EVM: the Pot's `0x` address. Its owner, salt and Kitchen are read from the chain |
| `owner` | string | | Or a Pot's owner, with its salt |
| `salt` | string | | A label naming one of the owner's Pots |
| `saltHex` | string | | The salt itself |
| `rpcUrl` | string | | An endpoint for this call |

Returns `store` and `pots`, as `sauce_pot_list` gives them. A Pot already recorded keeps its record.

## Resources

Every server serves these resources:

| URI | Content |
| - | - |
| `sauce://skills/index` | Every skill and its files (`text/markdown`) |
| `sauce://skills/<skill>/SKILL.md` | One skill's instructions |
| `sauce://skills/<skill>/references/…`, `sauce://skills/<skill>/examples/…` | The files a skill refers to |
| `sauce://actions/schema.json` | The JSON Schema that `sauce_actions` validates a document against (`application/schema+json`) |

These are the same files that `sauce skills install` copies into a project. They are also served as tools because many clients call tools but do not read resources.

## Prompt

`sauce_write_program` walks an agent through a program for a task, end to end with the tools: read the skills, look up the chain's names, compile, simulate, and build the unsigned Pot deployment and cook.

| Argument | Required | Meaning |
| - | - | - |
| `task` | yes | What the program should do, in plain words |
| `chain` | | The chain it runs on: `base`, `solana`, `8453` |

The prompt's message names the skills to read first: `sauce-overview`, `sauce-script` and `sauce-cli`, with `sauce-solana` in place of `sauce-script` on Solana. It embeds the `sauce-overview` skill, or `sauce-solana` on Solana. It then lists five steps: `sauce_globals`, `sauce_compile`, `sauce_simulate`, `sauce_pot` and `sauce_tx`.

## How a tool reaches a chain

A tool that reads a chain looks for an endpoint in this order:

1. the call's own `rpcUrl`;
2. the server's entry for the chain in the `--config` file, `{ "rpcUrls": { "<chain id>": "<url>" } }`;
3. a built-in public endpoint for the chain, unless the server was started with `--offline`;
4. if there is none, the call is refused with an error naming the chain and asking for `rpcUrl`.

A result read through a public endpoint says so in its `notes`:

```text theme={null}
base was read through a built-in public endpoint, which can be slow or rate-limited: pass rpcUrl with the call for an endpoint of your own.
```

`sauce_chains` reports each chain's `endpoint` as `config`, `public` or `none`.

Some tools never read a chain:

* `sauce_chains`, `sauce_globals`, `sauce_compile`;
* the skill tools;
* `sauce_wallet_list`, `sauce_wallet_address` and `sauce_pot_list`.

`sauce_simulate`, `sauce_send`, `sauce_wallet_send`, `sauce_pools`, `sauce_reclaim`, `sauce_pot_import`, a Solana cook, and any call given a transaction hash need an endpoint.

**URLs are never shown.** An RPC URL, from the call or from the `--config` file, is never returned, logged or quoted, in results or errors. This includes an upstream error that repeats the URL. The config file's path is not shown either.

Two cautions:

* A server someone else runs sees every `rpcUrl` you pass it. Pass only keys you are willing to share with its operator, or run the server yourself.
* Over HTTP, a caller's `rpcUrl` goes through a guard ([Self-hosting over HTTP](https://docs.eco.com/sauce-sdk/mcp/self-hosting.md#guard-what-callers-send)).

## Supported and preview chains

Transactions are built and sent only on Ethereum, Base, Arc and Solana, and on the testnets Arc Testnet, Base Sepolia, Ethereum Sepolia, Solana Devnet and Solana Testnet. Every other chain in the registry is a preview chain, where programs compile and reads work. [Chains](https://docs.eco.com/sauce-sdk/reference/chains.md) lists both kinds, and `sauce_chains` reports each chain's `support` (`supported` or `preview`). The testnets have no Permit2 entry and Arc Testnet has a 20 gwei fee floor ([Testnets](https://docs.eco.com/sauce-sdk/cli/chains-and-endpoints.md#testnets)).

These work on every chain:

* `sauce_chains`, `sauce_globals`, `sauce_price`, `sauce_pools`;
* `sauce_compile`, `sauce_inspect`, `sauce_verify`;
* `sauce_actions`' report, and `sauce_pot`'s prediction and reads;
* the skill tools, the wallet listing tools and the Pot store tools.

`sauce_simulate` is not gated by preview status: it runs wherever the release's engine and Kitchen are deployed and the endpoint supports the simulation. Where the engine has no code, the result is an error, `the released engine <engine address> is not deployed on <chain>: this SDK's cook cannot run there`. `sauce_pot` reports whether the engine is deployed on a chain.

On a preview chain, the following are refused before any endpoint is reached:

| Tool | On a preview chain |
| - | - |
| `sauce_tx` | An error result whose structured content is `{ refused }` |
| `sauce_signed_cook`, `sauce_sign` | An error result with `refused`, before any endpoint is reached or anything is signed |
| `sauce_send` | An error result with `refused` |
| `sauce_wallet_send` | An error result with `refused`, before anything is simulated, signed or sent |
| `sauce_pot` | Not an error: the prediction and reads, with `refused` in place of `to`, `data` and `value` |
| `sauce_actions` | Not an error: the compile report, with `refused` in place of `transaction` |

`sauce_reclaim` accepts only Solana, Solana Devnet and Solana Testnet, the supported Solana chains; on an EVM chain it is an input error.

The refusal, from `sauce_tx` on Arbitrum One:

```json theme={null}
{
  "refused": {
    "code": "preview-chain",
    "action": "building the cook transaction",
    "message": "building the cook transaction is refused: it involves arbitrum (Arbitrum One, chain id 42161), a preview chain. The sauce command and its MCP server build and send transactions only on Ethereum, Base, Arc and Solana, and the testnets Arc Testnet, Base Sepolia, Ethereum Sepolia, Solana Devnet and Solana Testnet. On a preview chain they build and send none. A program still compiles there and globals, price, pools and pot's prediction still read; simulate runs wherever the release is deployed on the chain, and says so where it is not. …",
    "supportedChains": [
      { "slug": "ethereum", "id": 1, "name": "Ethereum" },
      { "slug": "base", "id": 8453, "name": "Base" },
      { "slug": "arc", "id": 5042, "name": "Arc" },
      { "slug": "solana", "id": 1399811149, "name": "Solana" },
      { "slug": "arc-testnet", "id": 5042002, "name": "Arc Testnet" },
      { "slug": "base-sepolia", "id": 84532, "name": "Base Sepolia" },
      { "slug": "sepolia", "id": 11155111, "name": "Ethereum Sepolia" },
      { "slug": "solana-devnet", "id": 1399811150, "name": "Solana Devnet" },
      { "slug": "solana-testnet", "id": 1399811151, "name": "Solana Testnet" }
    ],
    "previewChains": [
      {
        "slug": "arbitrum",
        "id": 42161,
        "name": "Arbitrum One",
        "request": {
          "chain": { "name": "Arbitrum One", "id": 42161, "slug": "arbitrum" },
          "title": "Chain support: Arbitrum One (42161)",
          "searchUrl": "<search for an existing request>",
          "newIssueUrl": "<prefilled new request>",
          "body": "### Chain\n\nArbitrum One\n\n### Chain id\n\n42161\n\n### What you want to run there\n\n<what you want to run on Arbitrum One>\n\n…",
          "comment": "Another use case for Arbitrum One (42161):\n\n- What you want to run there: <what you want to run on Arbitrum One>\n…"
        }
      }
    ]
  }
}
```

Each preview chain's `request` names how to request support for that chain: a search for an existing request, a prefilled new one, and the `title`, `body` and `comment` to post, with placeholders for what the agent does not know. Each refusing tool's output schema makes every field optional beside `refused`, so a client that validates structured content accepts the refusal.

## Next steps

* [The Sauce MCP server](https://docs.eco.com/sauce-sdk/mcp/overview.md): setup and what the server reads.
* [Wallets over stdio](https://docs.eco.com/sauce-sdk/mcp/wallets.md) and [Local server storage](https://docs.eco.com/sauce-sdk/mcp/local-server.md).
* [Sign with a wallet's MCP server](https://docs.eco.com/sauce-sdk/mcp/external-wallets.md).
* [CLI overview](https://docs.eco.com/sauce-sdk/cli/overview.md): the same commands at a terminal.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.