> ## 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.

# Sign with a wallet's MCP server

> Build transactions with Sauce and use a separate wallet MCP server for signing and submission.

Sauce transaction-building tools return unsigned transactions. A separate wallet MCP server can sign and submit them using its own key management and approval flow. This guide covers the transaction formats Sauce provides for Coinbase Wallet MCP and Phantom MCP.

A run on a real chain spends real funds: the gas, the Kitchen's fee and what the program spends. Your Pot is the account the program runs on, and its owner is the wallet that signs ([Pot](https://docs.eco.com/sauce/pot.md)).

## Prerequisites

* The Sauce MCP server in your agent ([The Sauce MCP server](https://docs.eco.com/sauce-sdk/mcp/overview.md)).
* A supported chain: Ethereum, Base, Arc or Solana.
* The release's engine deployed on that chain. `sauce pot --chain <chain> --owner <address>` reports whether it is (`sauce_pot` in the agent).

## Which wallet

| | Coinbase Wallet MCP | Phantom MCP |
| - | - | - |
| Chains | Base, Ethereum | Solana, Base, Ethereum |
| Whose wallet | the Coinbase Wallet you sign in with | a new wallet Phantom makes for your agent |
| Who approves | you, in your wallet, once per request | Phantom's checks; the agent shows you a preview first |
| Suited to | several transactions in one approval, all or none | Solana, and an agent that sends without asking you each time |

Sauce's own wallets, made with `sauce wallet` or by a local server, keep the key on your machine, encrypted under a password the server holds, and no one approves each send. Use them for experiments with small amounts ([Wallets over stdio](https://docs.eco.com/sauce-sdk/mcp/wallets.md)).

## Add the wallet's server

Add the wallet's server beside Sauce's. Each opens your browser to sign in the first time the agent uses it.

**Coinbase Wallet MCP** is a server on the web:

```bash theme={null}
claude mcp add --transport http wallet-mcp https://wallet-mcp.coinbase.com   # Claude Code
codex mcp add wallet-mcp --url https://wallet-mcp.coinbase.com/              # OpenAI Codex
```

In an agent configured with JSON, such as Cursor:

```json theme={null}
{ "mcpServers": { "wallet-mcp": { "url": "https://wallet-mcp.coinbase.com" } } }
```

VS Code takes the same address as `{ "type": "http", "url": … }` under `servers`. Gemini CLI takes it as `{ "httpUrl": … }` under `mcpServers`.

**Phantom MCP** runs on your machine:

```bash theme={null}
claude mcp add phantom -- npx -y @phantom/mcp-server@latest   # Claude Code
```

```json theme={null}
{ "mcpServers": { "phantom": { "command": "npx", "args": ["-y", "@phantom/mcp-server@latest"] } } }
```

## What Sauce hands over

`sauce_tx`, `sauce_pot` and `sauce_actions` (given a Pot) return their transactions in the form these wallets take:

* Each EVM transaction, `{ chainId, to, data, value, gas }` with `value` and `gas` as hex quantities, is what Phantom's `evm_send` takes. Labels Sauce adds, such as `what`, are ignored by the wallet.
* `sendCalls` holds every transaction in order, as Coinbase's `send_calls` takes it: one batch, approved once, that runs all together or not at all. It is present on Base and Ethereum, the chains Coinbase Wallet MCP serves.
* On Solana, each `transaction` is a base64 transaction, which is what Phantom's `solana_send` takes.

This `sauce_tx` result is for a Pot on Base that has no code yet, with `data` shortened:

```json theme={null}
{
  "chainId": 8453,
  "pot": "0x6c9175d272D49e6C8C139A3FE6BC6fDb422eD3Fe",
  "transactions": [
    {
      "what": "Kitchen.deployPot(0x1111111111111111111111111111111111111111, 0x0000…0000): deploys the Pot, which has no code yet",
      "deploysPot": "0x6c9175d272D49e6C8C139A3FE6BC6fDb422eD3Fe",
      "chainId": 8453,
      "to": "<kitchen address>",
      "data": "0xff9763ac…",
      "value": "0x0"
    },
    {
      "what": "cook on Pot 0x6c9175d272D49e6C8C139A3FE6BC6fDb422eD3Fe",
      "chainId": 8453,
      "to": "0x6c9175d272D49e6C8C139A3FE6BC6fDb422eD3Fe",
      "data": "0xb38dbf14…",
      "value": "0x367e69a4b6e"
    }
  ],
  "from": "0x1111111111111111111111111111111111111111",
  "kitchenFee": { "wei": "3744785386350", "native": "0.00000374478538635", "readFrom": "base" },
  "sendCalls": {
    "chain": "base",
    "calls": [
      { "to": "<kitchen address>", "value": "0x0", "data": "0xff9763ac…" },
      { "to": "0x6c9175d272D49e6C8C139A3FE6BC6fDb422eD3Fe", "value": "0x367e69a4b6e", "data": "0xb38dbf14…" }
    ]
  }
}
```

The Pot in this example is not funded, so the cook would revert after the deployment. For that reason the cook carries no `gas`, and a note says to fund the Pot and build again. Fund it once the deployment has landed, or pass `fund` so the plan puts a token's transfer after the deployment and before the cook ([Funding a Pot](https://docs.eco.com/sauce-sdk/cli/funding.md)). `ETH:<amount>` adds to the cook's value, with no separate transfer. The plan has that deployment only when the call reads the chain: a call that reaches no endpoint ([How a tool reaches a chain](https://docs.eco.com/sauce-sdk/mcp/tools.md#how-a-tool-reaches-a-chain)) checks no deployment and plans no deployment step, so deploy the Pot first. [Deployments](https://docs.eco.com/sauce-sdk/reference/deployments.md) lists the Kitchen's address.

## On Base or Ethereum, with Coinbase

**1. Get the address**

The agent asks the wallet for your address.

**2. Build for it**

The agent calls `sauce_tx` with `owner` set to that address. To move tokens from the wallet into the Pot before the program runs, it adds `fund`, such as `["USDC:100"]`.

**3. Simulate**

The agent calls `sauce_simulate` on the same program and shows you what would move.

**4. Send the batch**

The agent calls `send_calls` with `sendCalls`. You open the link it returns, check, and approve in your wallet.

**5. Wait for it**

The agent calls `get_request_status` until the wallet reports that the batch landed.

A Pot that does not exist yet is created by the same batch, so one approval deploys the Pot, funds it and runs the program. If the program fails, the whole batch fails, and no Pot is left behind. To check the result, `sauce_pot` reads what the Pot holds.

## On Solana, with Phantom

**1. Get the address**

The agent asks the wallet for its Solana address. You send that address what the program spends.

**2. Build for it**

The agent calls `sauce_tx` with `chain: "solana"` and that address as `owner`.

**3. Preview**

The agent calls `solana_send` with the `transaction`. The first call only previews, and the agent shows you what would move.

**4. Send**

When you agree, the agent calls `solana_send` again with `confirmed: true`. Phantom signs, sends and returns the signature.

**5. Continue a plan**

If the result had a `cursor`, the cook needs more than one transaction. The agent passes the cursor and the signatures to `sauce_send`, which returns the next step, until `next.step` is `done`.

A Solana transaction lands within about a minute of being built, or not at all. If approving takes longer, build it again: `sauce_send` with the cursor alone, or the tool that built it.

## On Base or Ethereum, with Phantom

The agent calls `evm_send` with each transaction as it is, in order, and waits for each to land before sending the next. As on Solana, the first call previews and `confirmed: true` sends.

## With any other signer

A hardware wallet or a key management service signs too, with the key never near the agent. The signer returns the signed bytes, and `sauce_send` broadcasts them:

```text theme={null}
sauce_tx   { source, chain: "base", owner: "<your address>", args: [...] }
  → { pot, transactions: [ { what: "Kitchen.deployPot(…)", to, data, value },
                           { what: "cook on Pot …", to, data, value } ] }
             the signer signs both, with nonces n and n + 1
sauce_send { transactions: ["0x02f8…", "0x02f8…"] }
  → { ok: true, sent: [ { hash, status, explorer, trace, … }, { hash, status, moves, leftInPot, … } ] }
```

`sauce_send` simulates each transaction as signed, refuses one that would fail, sends them in order, and stops at the first that does not succeed ([`sauce_send`](https://docs.eco.com/sauce-sdk/mcp/tools#sauce_send)).

### Order and gas

* **A new Pot, then its cook.** While the Pot has no code, the deployment comes first, marked `deploysPot`. Any account may send it; only the owner may send the cook.
* **Gas.** The cook's `gas` is estimated as if the deployment had landed, with 30% room. A signer's own estimate, taken while the Pot has no code, is far too low.
* **A cook that would revert.** A cook that would revert after the deployment, such as one on a Pot not funded yet, has no `gas`, and a note says why. Send the deployment, fund the deployed Pot and call `sauce_tx` again, or call it with `fund`, which plans a token's transfer after the deployment when the call reads the chain. `ETH:<amount>` adds to the cook's value, with no separate transfer. A call that reaches no endpoint checks no deployment and plans no deployment step, so deploy the Pot first.
* **On Arc,** sign each transaction with a `maxFeePerGas` (or `gasPrice`) of at least 20 gwei, the chain's minimum base fee. `sauce_send` refuses a transaction signed with a lower fee cap and sends nothing.
* **On Solana,** each transaction is signed by its `feePayer`, the owner the call named. Its blockhash expires in about a minute, and a transaction signed later is refused.

## A cook someone else sends

A [signed cook](https://docs.eco.com/sauce/pot.md#signed-cooks) splits the cook in two: the Pot's owner signs it as EIP-712 typed data, and another account sends it and pays the gas. On Base, Ethereum or Arc, `sauce_signed_cook` builds it and signs nothing:

```text theme={null}
sauce_signed_cook { source, chain: "base", owner: "<your address>", args: [...], within: 600 }
  → { pot, typedData, digest, nonce, deadline, maxExecutionFee, deployPot, … }
                    the owner's wallet signs typedData (eth_signTypedData_v4)
sauce_signed_cook { …the same inputs, nonce, deadline, maxExecutionFee, signature }
  → { …, signature, cook: { chainId, to, data, value } }
                    any account sends deployPot (while the Pot has no code), then cook, with exactly its value
```

Give the second call the `nonce`, `deadline` and `maxExecutionFee` the first returned, and leave `within` out, since it is refused beside `deadline`: the call then checks the signature over the same cook, and a signature over other inputs is refused. `cook` is an ordinary transaction for whichever wallet sends it, and a signer's signed bytes go to `sauce_send`. The Pot pays the Kitchen's fee from its own balance, so fund the deployed Pot with native coin before the cook is sent, or sign a value that covers the fee. [`sauce_signed_cook`](https://docs.eco.com/sauce-sdk/mcp/tools#sauce_signed_cook) lists its inputs; [`sauce sign`](https://docs.eco.com/sauce-sdk/cli/sign) is the same from a terminal.

## A Solana cook of several transactions

Some Solana cooks need more than one transaction:

* a program too large for one transaction, staged in a Kitchen code buffer;
* accounts past one transaction's list, through a lookup table;
* a Pot or a token account to create first.

`sauce_tx` then returns a plan. The steps are the setup, then the cook, then closing the code buffer.

1. `sauce_tx` returns the first step and a `cursor`.
2. The owner's signer signs each transaction of the step.
3. `sauce_send` with the signed transactions and the `cursor` sends them. It returns the next step as `next`, built fresh from what the cluster shows.
4. Repeat with `next.cursor` until `next.step` is `done`.

The owner signs and pays every transaction. The cursor carries no key and no endpoint. Special cases:

* **A step with nothing to sign** says why in `next.wait`. Call `sauce_send` with the cursor alone again.
* **A cook its simulation says would fail** is not built. `next.fails` says why, with the simulation's `logs`.
* **Giving up.** `close: true` gives up on the cook and closes the code buffer.
* **Leftover rent.** `sauce_reclaim` lists the code buffers and lookup tables left open and returns the transactions that close them.

## From the command line

`sauce tx` prints the same JSON, so a script or an agent with a shell can pass it on the same way:

```bash theme={null}
sauce tx pay.sauce.ts --chain base --owner <your address> --args <recipient> 1000000
```

Have any signer sign the transactions. `sauce send` then broadcasts them ([`sauce send`](https://docs.eco.com/sauce-sdk/cli/send)).

## Next steps

* [Wallets over stdio](https://docs.eco.com/sauce-sdk/mcp/wallets.md): wallets a local server keeps for experiments, under a policy.
* [MCP tools](https://docs.eco.com/sauce-sdk/mcp/tools.md): every tool and what it returns.
* [Cook](https://docs.eco.com/sauce/cook.md): why a cook runs on your Pot, and where its results end up.


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