MCP server for AI agents
A local, self-custody MCP server that lets an AI agent trade the desk as both maker and taker
Cessio ships a local MCP server
(@cessio/agent-mcp-server)
that turns any MCP client — Claude Code, Claude
Desktop, or your own agent loop — into a first-class desk participant. The
agent gets its own Canton party and Ed25519 key, self-registers with the desk,
and can act as both maker and taker: the backend is role-agnostic, so the
server simply speaks the same REST + WebSocket API documented on
this site.
Self-custody is preserved: the server generates and stores the party key
locally (AGENT_STATE_FILE), signs every prepared transaction itself, and the
desk never sees the key. The agent makes the trading decisions; hard operator
rails (below) bound what its signatures can commit to.
Install
The server is published to npm and speaks stdio, so it works in any MCP client with a single config entry — no checkout, no build (Node.js >= 24):
{
"mcpServers": {
"cessio": {
"command": "npx",
"args": ["-y", "@cessio/agent-mcp-server"],
"env": {
"RFQ_BASE_URL": "https://api.devnet.cessio.cc",
"AGENT_DISPLAY_NAME": "my-agent",
"AGENT_MAX_NOTIONAL": "5000"
}
}
}
}In Claude Code that's one command:
claude mcp add cessio -e RFQ_BASE_URL=https://api.devnet.cessio.cc -e AGENT_MAX_NOTIONAL=5000 \
-- npx -y @cessio/agent-mcp-serverAll configuration is env vars:
RFQ_BASE_URL=https://api.devnet.cessio.cc # desk REST/WS base (default http://localhost:4000)
AGENT_STATE_FILE=~/.cessio/agent-identity.json
AGENT_DISPLAY_NAME="my-agent"
AGENT_MAX_NOTIONAL=5000 # required to trade; unset = read-only
AGENT_INSTRUMENT_WHITELIST=cBTC,USDC # empty = all
AGENT_MAX_PRICE_DEVIATION_BPS=500From a repo checkout the same server runs directly:
node apps/agent-mcp-server/src/index.ts.
On first start the server registers a fresh party with the desk (the same
self-serve flow as POST /maker/register/start)
and persists the identity in AGENT_STATE_FILE. Delete that file and you get a
brand-new party on the next start.
Tools
Fourteen tools in three groups:
| Group | Tools |
|---|---|
| Info | get_status, get_balances, list_instruments, get_reference_price, request_faucet |
| Taker | create_rfq, list_my_rfqs, get_quotes, accept_quote, cancel_rfq |
| Maker | wait_for_rfq (long-poll), submit_quote, list_maker_trades, list_trades |
A market-making agent loops wait_for_rfq → decide a price → submit_quote.
A taker agent calls create_rfq, inspects the answers with get_quotes, and
settles with accept_quote — the tool waits for the atomic DvP outcome and
returns the settled trade with its on-ledger proof.
Operator rails
Signing is automatic, so the trust boundary is configuration, not the model's judgment. Every trade the agent attempts is checked against the rails before anything is signed; a breach returns a structured error to the agent and signs nothing.
| Env var | Meaning | Default |
|---|---|---|
AGENT_MAX_NOTIONAL | Max quote-instrument notional per trade. Unset = read-only — the trading tools refuse. | unset |
AGENT_INSTRUMENT_WHITELIST | Comma-separated catalog symbols the agent may trade | empty = all |
AGENT_MAX_PRICE_DEVIATION_BPS | Max deviation from the desk's reference price | 500 |
AGENT_SETTLE_TIMEOUT_MS | How long accept_quote waits for the settle outcome | 60000 |
AGENT_POLL_MS | Internal polling interval | 1500 |
Relation to this API
The MCP server is a convenience wrapper, not a privileged client: everything it
does is the public API described in this documentation — the
quickstart flow for the maker side, POST /rfq /
POST /quote/{id}/accept for the taker side, and the
sign queue for signatures. If a tool is missing for
your use case, call the API directly with the same identity: the API key in
AGENT_STATE_FILE is an ordinary desk key.