Skip to main content
The Joyride MCP server lets an AI client read market and RFQ state and request quotes on option packages. It ships inside the joyride-cli package and speaks MCP over stdio. It is a reading and requesting surface, not a full trading surface. Read The server holds no signing key before planning anything around it.

Connect a client

Install the CLI, sign in, then register the server with a client:
--client accepts claude, codex, or cursor. Pass --force to overwrite an existing entry, and joyride mcp uninstall --client <client> to remove it. To register it by hand, the server entry is the joyride binary with the mcp serve arguments:
The server is a pure auth client: it reads the session token that joyride login wrote and sends it as a bearer for every downstream call. It never runs Sign-In with Solana itself and never opens the keystore. If the session has expired, every tool reports that and points back at joyride login. A wallet selected on the command line that does not match the stored session is a fatal startup error, so one wallet’s session can never be used to act as another.

What the RFQ tools expose

Package legs are ordered and their quantities are signed decimal strings: positive buys the leg, negative sells it. Submitted order is canonical and is never sorted. request_rfq_quote takes an optional client_ref idempotency key. When a request’s outcome comes back unknown, re-sending the same key retries that request rather than opening a second one. Market data and account reads are available through the server’s other tools and resources. Order-book trading tools also exist from the exchange’s earlier shape; the venue these pages document is RFQ, and nothing here teaches the order book. Three maker tools — watch_rfq_requests, respond_rfq_quote, and decline_rfq_request — exist behind an operator switch and are absent from the tool listing unless it is on. Quoting from MCP is limited by the same missing key described below, so a desk should read TypeScript Maker SDK instead.

The server holds no signing key

This is a design decision, not a gap to configure around. The MCP server is a pure auth client. It resumes a session token; it never opens the keystore and never produces an ed25519 signature. Accepting a quote and responding to a request are both signing operations, so in production:
  • accept_rfq_quote cannot sign an acceptance.
  • respond_rfq_quote cannot sign a maker quote. Its refusal says so in those words and points at the CLI.
No environment variable enables signing here. There is no flag, no setting, and no configuration file entry that turns it on. An agent that goes looking for one is looking for something that does not exist. Signing happens in the joyride CLI, which holds the keystore, or in the Joyride app. A workable division of labour is: let the agent find the package and request the quote through MCP, then accept from the CLI with joyride rfq accept. A refused accept consumes nothing. No nonce is spent, no request state changes, and the account’s other live requests are unaffected.

The spend ceiling

accept_rfq_quote is gated by two environment variables before it touches anything, and the gate is a safety requirement rather than an optional tweak. They are required together: with neither set, or with only one set, every accept refuses. A half-configured operator would otherwise believe spend is capped while a whole dimension stayed open. JOYRIDE_RFQ_MAX_PREMIUM_USDC caps the total cash one accept may cost. JOYRIDE_RFQ_MAX_LOCKED_USDC caps the collateral one accept may lock. Set both in the env object of the server entry in your client’s configuration, or export them in the shell that launches the server. Values are plain USDC decimals, for example 250.00.

Total cash, not premium alone

That first cap is a cost ceiling, not a premium ceiling. It bounds the premium plus the trading fee maximum the signature authorizes, compared as one number. The fee is real money leaving the account, and it is charged and capped per leg rather than per package, so it grows with the number of legs while the premium does not have to. A package can therefore owe far more in fees than its premium suggests; the worked example on Fees and Limits shows one. A credit package is not automatically under the ceiling. A credit pays the taker, so its premium contributes nothing to the cost — but the fee is still owed, and it is the whole cost. Those are exactly the structures a premium-only ceiling never bounded at all.
This changed the meaning of a variable you may already have set. A ceiling pitched at exactly what a package’s premium costs now refuses that package, because the fee pushes the total over it. If accepts start refusing with max_premium after an upgrade, that is the cause: raise the ceiling to cover the premium and the fee together.
The same two caps bound the maker tools when they are switched on, with the worst-case package outflow standing in for the premium: a quote is refused when that outflow plus the max_maker_fee it signs for is above the cost ceiling. The refusal names the bound, the limit, the figure and the overshoot. Three properties are deliberate:
  • The ceilings are the operator’s, and accept_rfq_quote exposes no arguments for them. A model cannot pass what it cannot name, so it cannot raise them.
  • They are read at call time, not at startup, so there is no stale captured copy to disagree with the environment.
  • They are handed to the SDK, which evaluates them against the same read the signature is built from. A pre-check would test one read and sign against another.
The tool stays listed when the ceiling is unset. An agent that can see it can explain why it cannot act; a tool that vanishes looks like a bug, and a bug invites a workaround. Because the server holds no key, an accept refuses even with both ceilings set. Configure them anyway: they are the guard that is already in place for any future signing path.

What an agent can and cannot do

There is no cancel and no replace

A quote delivered to the venue is firm until its expires_at. Nothing pulls it back, amends it, or replaces it, and the quote’s TTL is the only control over how long that commitment stands. For an agent on the taking side, the consequence is on the clock: a quote that is read and reasoned about for too long expires, and the venue refuses an accept that arrives with under two seconds of life left. Treat expires_at as a deadline, not a hint, and re-request rather than accepting stale state.

Support

support@joyride.exchange.