Install the MCP

writbound-mcp runs next to your agent (Claude Code, Codex, Cursor, any MCP client). It holds one key, the agent key, and that key can only trade inside your writ. Your owner wallet never touches it.

1 · Create the agent key

# on the agent's machine: creates ~/.writbound/agent.key (0600) and prints only the address
npx -y PKG init

2 · Open a writ for that address

On Open a writ, connect the wallet that should own the vault, paste the agent address, set the terms and open it. Fund the vault with USDG, and send the agent a little ETH on Robinhood Chain for gas (about 0.0003 ETH covers ~40 trades at today's fees).

3 · Add it to your agent

# Claude Code
claude mcp add writbound -- npx -y PKG --writ 0xYOUR_VAULT
# any MCP client (JSON config)
{ "mcpServers": { "writbound": { "command": "npx", "args": ["-y", "PKG", "--writ", "0xYOUR_VAULT"] } } }

On start the server checks that the RPC is Robinhood Chain (4663), that the vault was opened by the Writbound factory, and that its key is the vault's agent. If not, it refuses to start.

Tools

ToolWhat it does
writ_statusThe writ, what is left to spend today, the vault's balances, the agent's gas. Read-only.
writ_quoteQuoterV2 quote, the vault's TWAP floor, the minOut it would use, and whether the vault would file or refuse right now.
writ_tradeBuy or sell: side, stock, amount (USDG for buys, stock units for sells) and a reason of up to 280 bytes, which is published on-chain. Simulates, then sends. A predicted refusal is still sent so it is on the record; skipIfRefused only reports it, dryRun only simulates.
writ_historyFills and refusals from the last ~90 minutes on-chain, plus this machine's journal. The full record is on this site's Docket.

The writ

The owner can change any of it at any time from the writ's page or straight on the contract (setWrit, setAllowed, replaceAllowList, quash, setAgent, withdraw, withdrawAll). The agent can call execute and nothing else.

Refusal codes

Checked in this order. A refusal emits Refused(seq, code, tokenIn, tokenOut, amountIn, reason) and moves nothing. A trade that settles emits Filed(…, reason).

#CodeMeaning

Venue failures are not refusals. If the swap runs out of gas, a token is paused or the call is malformed (zero amount, balance too low, reason over 280 bytes), the transaction reverts and nothing is recorded. The docket only holds what the writ decided.

Without the MCP

Any agent that can sign a transaction can use the vault directly:

# 1 · what the vault accepts (expectedOut, minOutFloor, fee, twapWindow)
cast call $VAULT "quoteTwap(address,address,uint256)(uint256,uint256,uint24,uint32)" $USDG $NVDA 2000000 --rpc-url https://robinhood-rpc.publicnode.com
# 2 · quote the pinned pool on QuoterV2 (0x33e885eD0Ec9bF04EcfB19341582aADCb4c8A9E7), take max(quote × (1 − your tolerance), minOutFloor)
# 3 · simulate, then send: returns (code, amountOut); code 0 = filed
cast send $VAULT "execute(address,address,uint256,uint256,uint24,string)" $USDG $NVDA 2000000 $MINOUT 500 "why I am buying" --private-key $AGENT_KEY --rpc-url https://robinhood-rpc.publicnode.com

Contracts

Solidity 0.8.28, OpenZeppelin v5. The trade engine is shared with an earlier vault of ours that ran on Robinhood Chain mainnet. Tests: 42 unit tests and 8 fork tests against mainnet (real USDG, real stock tokens, real Uniswap v3 pools). Unaudited. Tests are not an audit.

Limits and risks

FAQ

Does Writbound hold my money?

No. Each vault is its own contract owned by your wallet. The factory has no owner and holds nothing.

Why send refusals on-chain at all?

Because the record is the point. A log that only shows successes cannot tell you what your agent tried. On Writbound, every attempt is on the Docket with the agent's own words.

Is this affiliated with Robinhood?

No. It runs on Robinhood Chain and trades the stock tokens issued there. It is not affiliated with Robinhood, Charles Schwab or JPMorgan Chase.