tastytrade-mcp

mcp
Guvenlik Denetimi
Basarisiz
Health Uyari
  • License — License: NOASSERTION
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Basarisiz
  • network request — Outbound network request in .github/dependabot.yml
  • rm -rf — Recursive force deletion command in build.sh
  • process.env — Environment variable access in jest.config.mjs
  • network request — Outbound network request in package.json
  • exec() — Shell command execution in scripts/check-coverage-floors.mjs
  • process.env — Environment variable access in src/credential-target.ts
  • network request — Outbound network request in src/credential-target.ts
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

MCP server for the tastytrade open API: quotes, positions, balances, and dry-run-gated order flow for LLM agents.

README.md

tastytrade MCP server

A Model Context Protocol server for the
tastytrade open API, giving an LLM agent
access to quotes, instruments, option chains, balances, positions, transactions,
watchlists, and order entry.

[!WARNING]

The default endpoint is PRODUCTION. Production is real.

With no environment configured, this server connects to the tastytrade
production API. Every account the supplied credentials can reach is a
real brokerage account, and every order this server places, edits,
replaces or cancels moves real money in it. Those actions take effect
immediately and cannot be undone.

For an environment with no real money in it, set TASTYTRADE_ENV=sandbox.
To withhold every write and destructive tool, set TASTYTRADE_READ_ONLY=1.

Read Choosing an environment and
Safety model before you point this at an account you care
about, and Disclaimer, Disclosures and
Notice for what this software does and does not promise.

Production is the default because the sandbox does not serve market data: a
server pointed there cannot quote, and a default that cannot do the job is not a
safe default — it is one that teaches an operator to override it without reading
why. The switch is one word either way, and the environment in use is stated in
three places: a startup banner on stderr, the instructions the MCP client
receives when it connects, and an environment member on every order result.

No tool, resource, prompt or example here is a recommendation to buy or sell
anything. Nothing in this repository is financial advice. See
Disclaimer.


Requirements

  • Node.js 22 or newer (see .node-version)
  • A tastytrade OAuth client and refresh token

Install

git clone https://github.com/tastytrade/tastytrade-mcp.git
cd tastytrade-mcp
npm ci
npm run build

Clone-and-build is the supported install: nothing here is published to npm and
there is no published container image. The included Dockerfile builds one
locally if you would rather run the server in a container — read its header
first, because a stdio server has to be started with docker run -i, and
without that the container exits immediately and looks exactly like a crash.

Credentials

Authentication is environment-only. There is no interactive login flow: a
server an agent can make bind a listening socket, and that then prints a
long-lived refresh token into a transcript, is not defensible.

Create an OAuth client and refresh token out of band — see tastytrade's
OAuth2 guide, or
my.tastytrade.com → Manage → My Profile → API — then supply three variables:

Variable Required Default
TASTYTRADE_CLIENT_ID yes
TASTYTRADE_CLIENT_SECRET yes
TASTYTRADE_REFRESH_TOKEN yes

Which endpoint those credentials are sent to is a separate decision, and its
default is production — see Choosing an environment
below.

Sandbox credentials are a separate OAuth application, and the two sets are not
interchangeable.
my.tastytrade.com issues production credentials; a sandbox
client id, secret and refresh token are created under a sandbox user, with the
tools on tastytrade's own sandbox page. A sandbox refresh token cannot mint an
access token against production, and a production one cannot against the
sandbox. That is worth knowing in advance because the failure is uninformative
on its own: every tool call returns auth_failed and nothing says why. The
preflight below names it outright, by comparing the issuer claim inside your
refresh token against the endpoint you configured.

Nothing in this repository auto-loads a .env file. Export the variables
yourself, or hand them to the server through your MCP client's env block.
.env.sample documents the same set.

Choosing an environment

The default is production. With nothing set, this server talks to
https://api.tastyworks.com, and every order it places, edits, replaces or
cancels is real and cannot be undone.

Variable Effect
TASTYTRADE_ENV production (also prod, live) or sandbox (also cert, staging, sbx). Case-insensitive, surrounding whitespace tolerated. Unset means production.
TASTYTRADE_API_URL An explicit base URL. Wins over TASTYTRADE_ENV, and is the only way to reach a host that is not one of tastytrade's own — a gateway, a proxy, a local test double.

A TASTYTRADE_ENV this server cannot read — a typo like sandbx — resolves to
the sandbox, and says so in a stderr banner that names the value. Unset is a
default; a typo is a failed instruction, and the two must not land in the same
place: an operator who tried to name an environment and misspelled it has not
thereby granted permission to trade live funds. TASTYTRADE_READ_ONLY fails
closed the same way, for the same reason — a value it cannot read enables
read-only mode rather than disabling it.

Three surfaces announce the environment, so it is not something anyone has to
hold in their head:

  • The stderr startup banner, which therefore fires by default. It names the
    endpoint, says that this is the default endpoint, and gives both switches:
    TASTYTRADE_ENV=sandbox to move off it, and TASTYTRADE_READ_ONLY=1 to
    disable every write.
  • instructions in the MCP initialize result — the only environment signal
    the agent itself can read, because stderr is a log file and instructions is
    context. On production it says so in those terms: real money, real account
    control, order actions that cannot be undone, and say which environment you
    are in before acting. On the sandbox it says there is no real money and that
    market data does not work. An endpoint this server does not recognise is
    described as unrecognised and to be treated as production.
  • An environment member on every order-submitting and dry-run result, valued production,
    sandbox or other, on all ten order routes — the five dry-runs and the five
    submit/edit routes. Server-authored, never copied from upstream, so a
    transcript is evidence of which environment an order actually went to.

What the sandbox cannot do

The sandbox does not currently serve market data: /market-data and
/market-metrics answer HTTP 502 on every route. So on the sandbox
tastytrade_get_quote, tastytrade_get_quote_snapshot,
tastytrade_get_market_metrics, tastytrade_get_historical_dividends and
tastytrade_get_earnings_reports all fail — the last two sit under the same
market-metrics prefix. Everything else works: instruments, option chains,
futures, accounts, balances, positions, transactions, orders, and the dry-run
and order-submission paths. tastytrade's own sandbox guide additionally lists
market metrics and net-liquidating-value history
(tastytrade_get_net_liq_history) as live-only, and notes that the sandbox
resets every 24 hours, clearing trades, transactions and positions while leaving
users and accounts intact.

That is the whole reason production is the default. Quoting is the first thing
anyone asks this server to do, and a default endpoint that cannot quote teaches
an operator to override it without reading why.

Optional configuration

Endpoint selection is above; these are the remaining
knobs, and every one of them has a working default.

Variable Effect
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)
TASTYTRADE_ALLOW_UNKNOWN_API_HOST Hostname to permit when TASTYTRADE_API_URL is not a tastytrade host
TASTYTRADE_CREDENTIAL_CHANNEL strict refuses to start when a proxy or a modified trust store is detected
TASTYTRADE_ALLOW_PROXY Hostname of a proxy to permit under strict
TASTYTRADE_HTTP_TIMEOUT_MS Per-request socket timeout (default 30000)
TASTYTRADE_HTTP_WALL_CLOCK_MS Per-request wall-clock ceiling (default: 3× the socket timeout)
TASTYTRADE_MAX_RESPONSE_BYTES Largest response body accepted (default 32 MiB)
TASTYTRADE_ACCEPT_VERSION Override the Accept-Version header (default: today's UTC date)
TASTYTRADE_USER_AGENT Override the User-Agent header

Run it

The server speaks MCP over stdio: a client launches it as a subprocess, talks
JSON-RPC over stdin and stdout, and passes the credentials in from its own
configuration. What is the same in every client is the command (node), the
absolute path to dist/index.js, and the environment variables. What differs is
the file that configuration lives in and the key it sits under — the mcpServers
object below is what Claude Desktop and Claude Code read, while other clients
(Cursor, Zed and Continue among them) keep their own file and do not all use the
same key, so check your client's own documentation if it is not one of these
two.

Claude Desktop reads a file named claude_desktop_config.json. Its own
Settings → Developer pane opens that file, which is the reliable way to find it;
on macOS it sits in ~/Library/Application Support/Claude/, and on Windows in
%APPDATA%\Claude\.

{
  "mcpServers": {
    "tastytrade": {
      "command": "node",
      "args": ["/absolute/path/to/tastytrade-mcp/dist/index.js"],
      "env": {
        "TASTYTRADE_ENV": "production",
        "TASTYTRADE_CLIENT_ID": "…",
        "TASTYTRADE_CLIENT_SECRET": "…",
        "TASTYTRADE_REFRESH_TOKEN": "…"
      }
    }
  }
}

That block is production: real funds, real accounts. The environment is named
explicitly rather than left to the default, so the block cannot mean something
different from what it says — change it to "sandbox" for an environment with no
real money in it, and add "TASTYTRADE_READ_ONLY": "1" to withhold every write
and destructive tool. Every value in that object is a string, "1" included.

On Windows the path is a JSON string like any other, so each backslash has to be
doubled:

{
  "command": "node",
  "args": ["C:\\Users\\you\\tastytrade-mcp\\dist\\index.js"]
}

Claude Code takes the same server from the command line and 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

Everything after -- is the command to launch, so flags meant for the server
are not read as flags for the CLI. That writes to your own configuration by
default; -s project writes a .mcp.json into whatever project directory you
run it from instead. That file carries the same mcpServers shape shown above
and is meant to be committed and shared, which makes it the wrong place for a
client secret or a refresh token.

Verify it works

Two JSON-RPC lines on stdin are enough to 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

The first reply is the initialize result, whose instructions field names the
environment; the second is the tool list, which is large enough to be worth
truncating (see Tool surface). The MCP Inspector
(npx @modelcontextprotocol/inspector node dist/index.js) does the same thing
with a UI. For the credentials themselves, use the preflight below.

Startup diagnostics — the production banner, the read-only banner, the
credential-channel notes — go to stderr, because stdout carries the MCP
protocol and nothing else. A client does not show you stderr in its chat window;
it writes it to its own server log, and that log is where to look when a client
reports that the server failed to start. Running node dist/index.js directly
puts the same output on your terminal.

Check your setup first

When credentials are wrong, every tool call fails the same way. The bundled
preflight tells you which of the four things is broken, in dependency order, and
six of its eleven checks need no network at all:

npm run doctor          # or: node dist/doctor.js
node dist/doctor.js --json

It never prints your client secret or refresh token — only their presence and
length — and it masks account numbers by default so the output is safe to paste
into an issue.

Exit codes:

  • 0 — every check passed; the configuration is verified
  • 1 — a check failed; the failing check is named on the last line
  • 2 — bad usage
  • 3 — a check warned or was skipped, so the run is not verified even though
    nothing failed. Gate on 0 if you care; treat 0 and 3 alike if you do not.

A production deployment exits 3 on every run. The endpoint check treats
production as a warning — real money is at risk, and that is worth saying every
time — and one warning is what exit 3 reports. Since production is the default,
3 is what a default configuration returns, and it means exactly what it says
above: nothing failed, and nothing was certified either. So the advice in that
last bullet needs one qualification — gating a production deployment on 0 alone
will never pass. Read the report, and keep the hard stop for 1.

Tool surface

84 tools: 70 read-only, 2 write, 12 destructive. The server also exposes MCP
Resources (documentation bundles and computed account views) and Prompts
(pre-composed tool-call plans).

Five tools require a confirmation token, and they are 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.

The other seven destructive tools carry no token and have no dry-run. They
are tastytrade_cancel_order and tastytrade_cancel_complex_order,
tastytrade_delete_quote_alert, and the four watchlist mutators
tastytrade_update_watchlist, tastytrade_delete_watchlist,
tastytrade_add_watchlist_symbol and 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 one says so in its own description.

Context cost

The tool list is large, and it is worth knowing the number before you meet it.
tools/list measures about 445 KB with all 84 tools, and about 349 KB with
TASTYTRADE_READ_ONLY=1, which withholds 14 of them. Every tool carries a full
outputSchema, and the descriptions are long deliberately — they are what the
agent reads instead of this file, and they are where the order semantics and the
failure modes are written down. That payload lands in the model's context at the
start of every session, and the figures move with every schema change.

Read-only mode is the only lever this server has over that today; there is no
tool-filtering variable. Most work needs a handful of tools:
tastytrade_get_accounts, tastytrade_get_balances, tastytrade_get_positions,
tastytrade_get_quote, tastytrade_get_option_chain_compact and
tastytrade_get_live_orders, and then tastytrade_dry_run_order followed by
tastytrade_place_order. If your client lets you enable tools individually per
server, that list is a reasonable place to start.

Safety model

The reason this project exists. In order of how much they protect you:

  1. Dry-run-first confirmation. The five order-submitting tools will not act
    without a token from their own dry-run. The token is single-use, expires in
    60 seconds, and is bound to the arguments and the endpoint the dry-run
    covered — so you cannot dry-run one share and submit a thousand, or pre-flight
    one order and submit a different one. It covers those five and none of the
    other destructive tools; Tool surface names both groups.
  2. Pre-submit sanity checks. Per-leg quantities against the account's own
    published order-size ceilings, a notional cap on buying-power impact, 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.
  3. Credential-destination guard. The refresh token and client secret are only
    sent to a recognised tastytrade host, over a channel that encrypts them. An
    unrecognised host stops the server rather than warning it.
  4. Rate limiting. tastytrade's own published per-second, per-endpoint
    ceilings plus a 50/sec global cap, charged once per call.
  5. Bounded, attributed output. Everything the broker wrote is nested under an
    upstream member and marked as untrusted external content, bounded in size
    and stripped of display-hostile codepoints, so it cannot impersonate this
    server's own fields.

Order attribution

Every order this server submits is tagged, server-side, with source, a field
from tastytrade's order API:

  • sourcetastytrade-mcp/<version>, so an order placed through this
    server is distinguishable from one entered by hand or by another integration.
    tastytrade echoes source back on order reads, so it is visible in order
    history; there is no source query filter, so filter on it client-side.
    source is written by the server and cannot be set, forged or suppressed by the
    caller — it is not an input property on any tool. An attribution a caller can
    switch off is not an attribution.

The one exception is the PAIRS ratio-threshold edit, which is left unstamped
deliberately: tastytrade documents that request body as exactly
ratio-price-comparator plus ratio-price-threshold, so an extra field there is
unverified against the spec. It creates no order and changes no leg.

What it does not do

  • It does not authenticate the caller. On stdio there is one caller per
    process and no second principal to distinguish. Adding an HTTP or SSE
    transport would make caller authentication a prerequisite.
  • The confirmation token is not human approval. The same agent mints it and
    redeems it. It proves recency and identity of arguments, not intent.
  • A cancel is not automatically safe. Cancelling a protective stop or a
    working hedge changes your risk immediately, and cancels carry no token.
  • Seven destructive tools act on the first call. The two cancels, the
    quote-alert delete, and the four watchlist mutators have no dry-run and take
    no confirmation token. Nothing in that set moves money except the cancels, but
    a watchlist this server overwrites or deletes cannot be restored by it.
  • Safety state is in-memory and single-process. Correct for one stdio
    session; a multi-replica deployment would need a shared store.

Development

./build.sh          # the full gate: install, format, lint, typecheck, build, test, audit, secrets
npm test            # Jest battery
npm run typecheck
npm run lint

./build.sh is the single source of truth for whether the code is shippable, and
CI runs the identical script. SKIP_INSTALL=1 ./build.sh reuses node_modules
for a faster local re-run.

Always run tests through npm test, never a bare npx jest: the package script
supplies --experimental-vm-modules, and without it any suite that reaches an
import.meta source fails to compile.

See CONTRIBUTING.md for conventions and
SECURITY.md for how to report a vulnerability.

Third-party documentation

tastytrade-llms-txt-docs/ is a point-in-time copy of tastytrade's own public
API documentation. Four of those files are a runtime dependency — the static
MCP resources read them at module load, so the directory has to ship alongside
the built server or it does not start — and the rest are the API reference the
test suite validates the tool schemas against.

That material is tastytrade's and is not under this repository's MIT licence.
It carries its own licence in NOTICE, which grants the right to
reproduce and redistribute it for the purpose of using, building or distributing
this software. That grant exists because without it the MIT licence on the code
would not be usable: you could lawfully fork the repository and still not be able
to ship anything that runs. Keep NOTICE with any copy you distribute.

Disclaimer

This software is provided as is, without warranty of any kind, as set out in
LICENSE.

You are responsible for what you connect this server to, and for everything it
does on your behalf.
This server hands order entry to an LLM agent. Language
models are non-deterministic: they misread instructions, act on content injected
into their context by a third party, and take actions their operator did not
intend. The dry-run-first confirmation flow, the pre-submit sanity checks and the
rate limits described above reduce how much damage that can do. They do not
eliminate it, and nothing in this repository is a guarantee about what a model
will do with the tools it is given.

Neither tastytrade nor any contributor to this repository accepts responsibility
or liability for any action taken — or not taken — by an LLM, an MCP client, or
any other software interacting with this server. That includes any order placed,
modified or cancelled, any position opened or closed, any account state changed,
and any financial loss arising from any of it, on any account the configured
credentials can reach.

If you are not prepared to accept that, run with TASTYTRADE_ENV=sandbox, or
with TASTYTRADE_READ_ONLY=1, or do not supply production credentials.

No tool, resource, prompt or example in this repository is a recommendation to
buy or sell anything, and nothing here is financial advice.

See also Notice, tastytrade's own statement on third-party AI systems
connected through this server.

Licence

MIT — see LICENSE for the software, and NOTICE for the
vendored tastytrade documentation under tastytrade-llms-txt-docs/, which is
licensed separately.

Disclosures

The tastytrade Model Context Protocol (“MCP”) Server lets you connect a
third-party AI application or Large Language Model (“LLM”) (collectively, an
“AI System”) of your choosing to your tastytrade account(s) to research markets,
analyze your portfolio, and place orders in plain language. How you use your AI
System is up to you — from an interactive assistant where you review and confirm
each order, to an automated system you build and operate yourself. You are
responsible for how the server is configured and used, including any automated
or unattended trading conducted by or through your chosen AI System, and for all
orders placed from your account.

tastytrade does not endorse or recommend any third-party AI System, and
tastytrade is not responsible for any information, output, or trading activity
generated by or through your connected AI System. Any AI-generated information
should be independently verified. You are solely responsible for any actions
taken in reliance on information generated by your AI System and for any
investment or trading decisions made using it. You are responsible for
monitoring any activity undertaken by or through your AI System to ensure it is
operating as you intended. Once you share your account data with an AI System
provider you select, it leaves tastytrade's environment and is governed by that
provider's terms and privacy practices. tastytrade is not responsible for any
unauthorized access to your account data resulting from your usage of an AI
System.

AI Systems can make errors. They may misinterpret instructions, act on
incomplete or outdated information, or produce analysis that is inaccurate or
unsuitable for you. You are solely responsible for reviewing all your
AI-generated output, orders, and account activity. tastytrade does not guarantee
the accuracy, completeness, or suitability of any of your AI-generated output.

Trading securities, options, and futures involves significant risk and is not
suitable for all investors; you may lose more than your initial investment.
Before trading options, read the
Characteristics and Risks of Standardized Options
and
Futures & Exchange-Traded Options Risk Disclosure Statement.
We recommend testing with paper trading before connecting a live account.

tastytrade, Inc. is a registered broker-dealer and a member of FINRA, NFA, and
SIPC.

Disclosures: tastytrade MCP Server — Disclosures (PDF)

Notice

tastytrade does not endorse or recommend any third-party AI System connected via
the MCP server, and tastytrade is not responsible for any information, output, or
trading activity generated by or through your connected AI System. You are solely
responsible for any actions taken in reliance on information generated by your AI
System and for any investment or trading decisions made using it. tastytrade does
not guarantee the accuracy, completeness, or suitability of any of your AI
generated output.

Yorumlar (0)

Sonuc bulunamadi