MCP Server
The tastytrade MCP server gives AI agents structured access to the tastytrade API through the Model Context Protocol. It exposes the API as MCP Tools, Resources, and Prompts, and gates order submission behind a dry-run-first confirmation flow.
Self-hosted and open source. You run it yourself. The source is at github.com/tastytrade/tastytrade-mcp. There is no tastytrade-hosted endpoint to connect to.
The default endpoint is production. With no environment configured, the server connects to the production API, where every account the supplied credentials can reach is a real brokerage account and every order moves real money, immediately and irreversibly. Set
TASTYTRADE_ENV=sandboxfor an environment with no real money in it, andTASTYTRADE_READ_ONLY=1to withhold every write and destructive tool.Production is the default deliberately: the sandbox does not serve market data, and a default endpoint that cannot quote would teach operators to override it without reading why.
Why an MCP server (vs. calling the REST API directly)
Trading APIs are unforgiving — wrong quantity, wrong account, or wrong symbol costs real money. The MCP server adds guardrails enforced server-side, so an agent cannot skip them:
- Tools — direct API actions (get a quote, place an order, cancel an order…).
- Resources — documentation bundles and computed account views the agent reads instead of stitching several tool calls together.
- Prompts — pre-composed tool-call plans (LLMs follow plans more reliably than they compose them).
LLM clients
“Sell a 30-delta SOFI put and show my portfolio theta”
Interfaces
tastytrade MCP Server
The bridge
84 tools · one protocol
Translates plain language into API calls, then returns a plain-language answer. OAuth-scoped, dry-run safety checks.
tastytrade APIs
Install
Clone-and-build is the supported install. Nothing is published to npm, and there is no published container image.
git clone https://github.com/tastytrade/tastytrade-mcp.git
cd tastytrade-mcp
npm ci
npm run build
Requires Node.js 22 or newer. The repo includes a Dockerfile that builds an
image locally — note that a stdio server must be started with docker run -i, or
the container exits immediately and looks like a crash.
Credentials
Authentication is environment-only; there is no interactive login flow. Create an OAuth client and refresh token out of band (see the OAuth2 guide, or my.tastytrade.com → Manage → My Profile → API), then supply three variables:
| Variable | Required |
|---|---|
TASTYTRADE_CLIENT_ID | yes |
TASTYTRADE_CLIENT_SECRET | yes |
TASTYTRADE_REFRESH_TOKEN | yes |
Sandbox credentials are a separate OAuth application and are not
interchangeable with production ones. A sandbox refresh token cannot mint an
access token against production, or vice versa — and the failure is
uninformative: every tool call returns auth_failed with nothing saying why.
The server does not auto-load a .env file. Export the variables yourself, or
pass them through your MCP client's env block.
Choosing an environment
| Variable | Effect |
|---|---|
TASTYTRADE_ENV | production (default) or sandbox. Unset means production. |
TASTYTRADE_API_URL | Explicit base URL; wins over TASTYTRADE_ENV. |
TASTYTRADE_READ_ONLY | 1 withholds and refuses all 14 write and destructive tools. |
MAX_ORDER_NOTIONAL_USD | Ceiling on an order's buying-power impact (default 50000). |
A TASTYTRADE_ENV the server cannot read — a typo like sandbx — resolves to
the sandbox and says so, on the principle that a failed instruction must not
land in the same place as an unset default. TASTYTRADE_READ_ONLY fails closed
the same way.
Three surfaces announce the active environment: a stderr startup banner, the
instructions field of the MCP initialize result (the only signal the agent
itself can read), and an environment member on every order and dry-run
result, so a transcript is evidence of where an order actually went.
What the sandbox cannot do
The sandbox does not serve market data — /market-data and /market-metrics
return HTTP 502 — so quotes, quote snapshots, market metrics, historical
dividends and earnings reports all fail there. Everything else works:
instruments, option chains, futures, accounts, balances, positions,
transactions, orders, and the dry-run and submission paths. The sandbox also
resets every 24 hours, clearing trades, transactions and positions.
Connecting a client
The server speaks MCP over stdio: the client launches it as a subprocess. What
is constant across clients is the command (node), the absolute path to
dist/index.js, and the environment variables.
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"tastytrade": {
"command": "node",
"args": ["/absolute/path/to/tastytrade-mcp/dist/index.js"],
"env": {
"TASTYTRADE_ENV": "sandbox",
"TASTYTRADE_CLIENT_ID": "…",
"TASTYTRADE_CLIENT_SECRET": "…",
"TASTYTRADE_REFRESH_TOKEN": "…"
}
}
}
}
Every value in that object is a string, "1" included. Name the environment
explicitly rather than relying on the default, so the block cannot mean something
different from what it says.
Claude Code writes the file for you:
claude mcp add tastytrade \
-e TASTYTRADE_CLIENT_ID=… \
-e TASTYTRADE_CLIENT_SECRET=… \
-e TASTYTRADE_REFRESH_TOKEN=… \
-- node /absolute/path/to/tastytrade-mcp/dist/index.js
-s project writes a shareable .mcp.json instead — which makes it the wrong
place for a client secret or refresh token.
Other clients (Cursor, Zed, Continue among them) keep their own config file and do not all use the same key; check your client's documentation.
Tool surface
84 tools — 70 read-only, 2 write, 12 destructive. Read-only tools are
auto-approvable; every tool carries MCP annotations (readOnlyHint /
destructiveHint / idempotentHint) so clients render the right approval UI.
Five tools require a confirmation token — the five that submit or change an
order: tastytrade_place_order, tastytrade_edit_order,
tastytrade_replace_order, tastytrade_place_complex_order and
tastytrade_edit_complex_order. Each takes a single-use confirmation_token
minted by its own dry_run_* tool, valid for 60 seconds and bound to a hash
of the submitted arguments and of the request target — so you cannot dry-run
one share and submit a thousand, or pre-flight against one endpoint and submit to
another.
The other seven destructive tools carry no token and have no dry-run. They
are tastytrade_cancel_order, tastytrade_cancel_complex_order,
tastytrade_delete_quote_alert, and the four watchlist mutators
(tastytrade_update_watchlist, tastytrade_delete_watchlist,
tastytrade_add_watchlist_symbol, tastytrade_remove_watchlist_symbol). Of
those seven only the two cancels touch orders; the other five move no money. They
act on the first call, and each says so in its own description.
Safety model
In order of how much they protect you:
- Dry-run-first confirmation — the five order-submitting tools will not act without a token from their own dry-run (above). It covers those five and none of the other destructive tools.
- Pre-submit sanity checks — per-leg quantities against the account's own
published order-size ceilings, a notional cap on buying-power impact
(
MAX_ORDER_NOTIONAL_USD, default $50,000), and a refusal to send orders into frozen or closing-only accounts. Every result names the checks that did not run, so an empty warning list can never be mistaken for a completed check. - Credential-destination guard — the refresh token and client secret are only sent to a recognised tastytrade host over an encrypting channel. An unrecognised host stops the server rather than warning about it.
- Rate limiting — tastytrade's own published per-second, per-endpoint ceilings plus a 50/sec global cap, charged once per call. See Rate limits and backoff.
- Bounded, attributed output — everything the broker wrote is nested under
an
upstreammember and marked as untrusted external content, bounded in size and stripped of display-hostile codepoints, so it cannot impersonate the server's own fields.
Verify it starts
Two JSON-RPC lines on stdin prove the server starts and lists its tools. Neither call reaches tastytrade, so this works before the credentials are right:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"probe","version":"0"}}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
| node dist/index.js | cut -c1-200
Startup diagnostics go to stderr, because stdout carries the MCP protocol and nothing else. A client writes stderr to its own server log — that log is where to look when a client reports the server failed to start.
See also
- github.com/tastytrade/tastytrade-mcp — source, full README, and security policy.
- API Reference — the underlying REST operations these tools wrap.
/llms.txt— the agent index, including the golden-path instructions.