About ferdousbhai/tasty-agent
ferdousbhai/tasty-agent is an MCP server published by ferdousbhai in the Developer Tools category: let Claude manage your tastytrade portfolio.
The repository has 87 stars and 27 forks, with the last commit 13 days ago. Recent commit activity is the strongest signal that reported issues will get attention.
Install
git clone https://github.com/ferdousbhai/tasty-agentThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Ask AI
Ask AI about ferdousbhai/tasty-agent
Powered by Claude · Grounded in docs
Security checks
Static checks derived from the repository 7 hours ago. Heuristics on the source, not an audit.
- ✓README presentThe repository ships documentation.
- ✓License declaredUsable under a stated license.
- ✓Tests presentA test suite exists in the repository.
- ✓Dependencies pinnedA lockfile pins dependency versions.
- ✓No dynamic code executionSource scan found no eval, dynamic Function, or shell execution.
- !Scoped permissionsDoesn't declare a permission scope. Assume it can do anything its process can.
Releases
README
tasty-agent: A TastyTrade MCP Server
A Model Context Protocol server for TastyTrade brokerage accounts. Enables LLMs to monitor portfolios, analyze positions, and execute trades. Features automated IV analysis prompts and compact tool output.
Written in TypeScript against the Tastytrade REST API and DXLink directly (no SDK). The same code runs locally over stdio (npx tasty-agent) or as a remote MCP server on Cloudflare Workers.
v7 is a rewrite. The Python package (
uvx tasty-agent, 6.x) is replaced by the npm package, and the Modal deployment by Cloudflare Workers. Tool names are unchanged. What differs from 6.x:
get_quotesno longer takestimeout: quotes come from REST market data, so they also answer outside market hours.get_greeksaccepts at most 100 contracts and atimeoutof at most 30 seconds.- Orders and replacements are refused when the broker's dry run returns any warning.
- A cancel, order, or watchlist change the broker may have applied without answering reports an unknown outcome instead of failing.
- Prices are rounded with the broker's tick schedules read as upper bounds (e.g. sub-penny below $1, a cent from $1), and futures options can now be priced.
- The
GTDtime-in-force and the local SSE/HTTP transports are gone; a blankTASTYTRADE_ACCOUNT_IDcounts as unset.
Authentication
OAuth Setup:
- Create an OAuth app at https://my.tastytrade.com/app.html#/manage/api-access/oauth-applications
- Check all scopes, save your client ID and client secret
- Create a "New Personal OAuth Grant" in your OAuth app settings (check all scopes)
- Copy the generated refresh token
- Configure the MCP server with your credentials (see Usage below)
| Variable | Required | Notes |
|---|---|---|
TASTYTRADE_CLIENT_SECRET |
yes | OAuth app client secret |
TASTYTRADE_REFRESH_TOKEN |
yes | Personal OAuth grant refresh token |
TASTYTRADE_ACCOUNT_ID |
no | Needed only when the grant exposes several accounts; otherwise the one account is used |
TASTYTRADE_API_BASE |
no | Defaults to https://api.tastyworks.com; use https://api.cert.tastyworks.com for the sandbox |
MCP_BEARER_TOKEN |
Cloudflare only | Clients must send Authorization: Bearer <token> |
MCP Tools
Account & Portfolio
account_overview(include=["balances","positions"])- Account balances (including net liquidating value) and open positions.
Market Data & Research
get_quotes(instruments)- Live bid/ask/mid quotes for stocks, options, futures, and indices (indices without a two-sided market report their last price)get_greeks(options, timeout=10.0)- Greeks (delta, gamma, theta, vega, rho) for equity and futures options via DXLink streaming (up to 100 contracts, timeout at most 30s)get_market_metrics(symbols)- IV rank, percentile, beta, liquidity for multiple symbolsmarket_status(exchanges=['Equity'])- Market hours, status, holidays, and current NYC time ('Equity', 'CME', 'CFE', 'Smalls')search_symbols(symbol, limit=10)- Search for symbols by name/ticker
History
get_history(type, days=None, underlying_symbol=None, transaction_type=None, page_offset=0, limit=25)- Transaction history (type="transactions", default 90 days) or order history (type="orders", default 7 days). Paginated — usepage_offsetandlimitfor large result sets. Filter transactions by"Trade"or"Money Movement".
Order Management
place_order(legs, target_value=None, time_in_force="Day", dry_run=false)- Place multi-leg orders with quote-derived mid pricing only. The tool fetches live quotes for the exact resolved instruments, computes the signed net mid, validates the final limit against bid/ask guardrails, and optionally sizes quantity fromtarget_value.quantityis the actual share/contract count.target_value=50000sizes an equity or equity-option order from quote-derived pricing; omitquantityfor single-leg target-value orders. For multi-leg spreads withtarget_value, usequantityonly to express the leg ratio, such as 1:1 or 2:1.- Order prices are aligned to the broker's valid tick grid before submission. If tick-size data is unavailable, the tool fails before placement instead of submitting an invalid price increment.
- Every order is sent to the broker as a dry run first. Any dry-run warning refuses the order;
dry_run=truereturns the preview and marks such an orderblocked. - If the broker does not answer a submission (timeout or 5xx), the tool reports an unknown outcome and never retries; check
list_ordersbefore placing again. Cancels and watchlist changes are handled the same way. - Equities and options use
Buy to Open,Buy to Close,Sell to Open, orSell to Close; futures useBuyorSell.
replace_order(order_id)- Reprice an existing live order at the current quote-derived mid (dry-run checked the same way).cancel_order(order_id)- Cancel an order.list_orders()- Get all live orders.- Tool outputs are compact: quote tables include actionable bid/ask/mid/size fields; order results include compact order, buying-power, fee, warning, pricing, and sizing summaries.
Watchlist Management
watchlist(action, ...)- Unified watchlist management:action="list"- Nonamereturns compact watchlist metadata (name,group,symbol_count); withname, returns compact symbol entries.action="add"- Add symbols to a watchlist (creates if doesn't exist)action="remove"- Remove symbols from a watchlistaction="delete"- Delete a watchlist
MCP Prompts
- IV Rank Analysis - Automated prompt to analyze IV rank extremes across positions and watchlists for entry/exit opportunities
All broker requests, including token refreshes, share one two-requests-per-second gate (per process locally, one Durable Object on Cloudflare).
Usage
Local (stdio)
Requires Node.js 22+. Add to your MCP client configuration (e.g., claude_desktop_config.json):
{
"mcpServers": {
"tastytrade": {
"command": "npx",
"args": ["-y", "tasty-agent@7"],
"env": {
"TASTYTRADE_CLIENT_SECRET": "your_client_secret",
"TASTYTRADE_REFRESH_TOKEN": "your_refresh_token"
}
}
}
}
Add "TASTYTRADE_ACCOUNT_ID": "your_account_id" only if your grant exposes more than one account.
Remote (Cloudflare Workers)
The Worker is configured in cloudflare.config.ts and deployed with the cf CLI. From a checkout:
npm install
npx cf auth login
npm run deploy # builds and deploys the Worker
# with the values exported in your shell; MCP_BEARER_TOKEN is e.g. the output of: openssl rand -hex 32
for name in TASTYTRADE_CLIENT_SECRET TASTYTRADE_REFRESH_TOKEN MCP_BEARER_TOKEN; do
npx cf workers secrets update "$name" --worker tasty-agent --text "${!name}"
done
# only for multi-account grants:
npx cf workers secrets update TASTYTRADE_ACCOUNT_ID --worker tasty-agent --text "$TASTYTRADE_ACCOUNT_ID"
The server is then at https://tasty-agent.<your-subdomain>.workers.dev/mcp (streamable HTTP). Connect with the bearer token, for example in Claude Code:
claude mcp add --transport http tastytrade https://tasty-agent.<your-subdomain>.workers.dev/mcp \
--header "Authorization: Bearer $MCP_BEARER_TOKEN"
To redeploy on every push, connect your fork under the Worker's Settings → Builds in the Cloudflare dashboard, with build command npm run workers-builds:build and deploy command npx cf deploy --prebuilt; a failing check stops the deploy.
The Worker serves only your own account: anyone holding the bearer token can trade it, so treat the token like the refresh token.
Reusing the Tastytrade client
The REST client, rate gate, tick-size rules, and DXLink feed have no MCP dependency and are exported separately:
import { createTastytradeClient, IntervalGate, collectFeedEvents } from 'tasty-agent/tastytrade'
createTastytradeClient authenticates with either an OAuth grant it refreshes itself (clientSecret / refreshToken, each a string or an async getter read only when a token is minted) or a caller-minted accessToken, which is never refreshed or retried. Every request, including token refreshes, goes through the gate you pass. request(path, { raw: true }) returns the whole response body (with pagination), and signal aborts a request early. A mutation that fails without a definite answer raises TastytradeOutcomeUnknownError. spicytrade uses this client for its own transport.
Examples
"Get my account balances and current positions"
"What's my net liquidating value?"
"Get real-time quotes for SPY and AAPL"
"Get quotes for a TQQQ call at strike 100 expiring YYYY-MM-DD" (use a concrete listed expiration)
"Get Greeks for an AAPL put at strike 150 expiring YYYY-MM-DD" (use a concrete listed expiration)
"Get Greeks for an /ES call at strike 5800 expiring YYYY-MM-DD" (use a concrete listed expiration)
"Buy to open 100 AAPL shares at mid"
"Buy to open 17 TQQQ calls at strike 100 expiring YYYY-MM-DD" (use a concrete listed expiration)
"Buy $50K of TSLA calls at strike 300 expiring YYYY-MM-DD" (use a concrete listed expiration)
"Place an AAPL 150/155 call spread expiring YYYY-MM-DD" (use a concrete listed expiration)
"Buy one /ES-CONTRACT future at mid" (use a concrete active contract symbol)
"Reprice order 12345 at mid"
"Cancel order 12345"
"Show my live orders"
"Get my trading history from January"
"Get my order history for SPY"
"Get my private watchlists"
"Add TSLA and NVDA to my tech watchlist"
Development
npm install
npm run check # type-check the Node and Worker builds
npm test # unit tests; test/integration.test.ts runs live only when credentials are set
npm run dev # local Worker via Vite (put secrets in .dev.vars, see .dev.vars.example)
# Debug with MCP inspector
npm run build && npx @modelcontextprotocol/inspector node dist/stdio.js
License
MIT
README fetched from the repository 7 hours ago. The original is authoritative.