firstrade-mcp-server
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| FT_PIN | Yes | Your Firstrade PIN (usually a numeric code used during login). | |
| FT_EMAIL | Yes | Your email address associated with the Firstrade account, used for receiving OTP codes. | |
| FT_PASSWORD | Yes | Your Firstrade login password. | |
| FT_USERNAME | Yes | Your Firstrade login username. | |
| FT_TOTP_SECRET | No | Optional TOTP seed (the authenticator app's full secret) to enable headless session refresh. If not set, manual OTP entry is required when the session expires. | |
| FT_ACCOUNT_NUMBER | No | Optional Firstrade account number to use when the login has more than one account. If unset, order/quote/cancel tools will refuse to operate on multi-account logins. | |
| FT_ALLOW_LIVE_ORDERS | No | Set to 'true' to enable live order placement (place_* tools). Defaults to false; any other value disables order placement. | false |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| get_account_positionA | Get current stock and options positions for all accounts. |
| get_account_balanceA | Get account equity, cash, and balance overview for all accounts. |
| get_account_historyA | Get transaction history (fills, dividends, interest, transfers). Args: date_range: today|1w|1m|2m|mtd|ytd|ly|cust. Use "ly" for the trailing year, or "cust" with custom_from/custom_to for an explicit window. custom_from: Window start, "YYYY-MM-DD". Required when date_range="cust"; supplying it also implies "cust" so the range arg can be left alone. custom_to: Window end, "YYYY-MM-DD". Defaults to custom_from when omitted. Returns JSON keyed by account number. |
| get_ordersA | List orders and their status (open / filled / cancelled) for all accounts. Each entry carries the Firstrade order id (e.g. 'G42621-1601'), which is the authoritative link between a fill and the GTC ladder it came from. Use this to see resting GTC orders, detect dead orders, and attribute fills to a plan. Args: per_page: Orders per page. 0 (default) returns all. Returns JSON keyed by account number. |
| get_single_quoteB | Get real-time quote for a stock symbol. |
| get_watchlist_quoteA | Get real-time quotes for multiple symbols (comma-separated, e.g. 'AAPL,NVDA,MU'). |
| get_option_chainA | Get the broker's own option chain for a stock symbol. Args: symbol: Underlying ticker, e.g. 'NVDA'. exp_date: Expiration as 'YYYYMMDD' (or 'YYYY-MM-DD'). Omit to list the available expiration dates instead of returning a chain. strike_min / strike_max: Optional inclusive strike filter (0 = no bound). Full chains on NVDA/MU/CRWD exceed the MCP result-size cap (~100-140k chars); pass a band around spot (e.g. ±15%) to keep the payload small. Returns JSON: {"items": [{exp_date, day_left, exp_type}, ...]} when exp_date is omitted, else the chain for that expiration (filtered if bounds given). |
| get_option_greeksA | Get broker-computed greeks (delta/gamma/theta/vega/rho, IV) for an option chain. Prefer this over locally derived greeks when sizing or comparing legs. Args: symbol: Underlying ticker, e.g. 'TSLA'. exp_date: Expiration as 'YYYYMMDD' (or 'YYYY-MM-DD'). Get valid dates from get_option_chain with exp_date omitted. strike_min / strike_max: Optional inclusive strike filter (0 = no bound); full greeks on liquid names exceed the MCP result-size cap. Returns JSON {"chains": [{strike, cp, side, symbol, iv, delta, gamma, rho, theta, vega}, ...]}. Illiquid strikes report "--" rather than a number. |
| preview_stock_orderA | Preview a stock order WITHOUT sending it (dry_run=True). Always call this first. Args: symbol: Ticker symbol (e.g. 'NVDA'). order_type: buy | sell | sell_short | buy_to_cover quantity: Number of shares. price_type: limit | market | stop | stop_limit | trailing_stop_dollar | trailing_stop_percent duration: day | day_ext | overnight | gt90 (gt90 ≈ GTC, 90-day) price: Limit price (required for limit/stop_limit orders). stop_price: Stop trigger price (required for stop/stop_limit orders). Returns JSON with order preview confirmation data, plus "confirm_token": pass that token unchanged to place_stock_order (with the identical order arguments) to actually send it. The token expires in 10 minutes and works once. |
| place_stock_orderA | Place a real stock order (dry_run=False). Requires FT_ALLOW_LIVE_ORDERS=true in .env AND a confirm_token from preview_stock_order called with these exact same arguments — the server rejects the order otherwise, it does not just rely on the caller having "meant to" preview first. Args: symbol: Ticker symbol (e.g. 'NVDA'). order_type: buy | sell | sell_short | buy_to_cover quantity: Number of shares. confirm_token: Token returned by preview_stock_order for this exact order. price_type: limit | market | stop | stop_limit | trailing_stop_dollar | trailing_stop_percent duration: day | day_ext | overnight | gt90 (gt90 ≈ GTC, 90-day) price: Limit price (required for limit/stop_limit orders). stop_price: Stop trigger price (required for stop/stop_limit orders). Returns JSON with order confirmation. This sends a real order to Firstrade. |
| preview_option_orderA | Preview an option order WITHOUT sending it (dry_run=True). Always call this first. Args: option_symbol: OCC format symbol (e.g. 'AAPL250620C00150000'). order_type: buy_to_open | sell_to_close | sell_to_open | buy_to_close ('buy' = buy_to_open, 'sell' = sell_to_open; to exit a long option you MUST use sell_to_close, otherwise Firstrade treats it as opening a short and rejects with ref 1103). contracts: Number of contracts. price_type: limit | market | stop | stop_limit duration: day | day_ext | gt90 price: Limit price per contract (required for limit orders). stop_price: Stop trigger price (required for stop/stop_limit orders). Returns JSON with order preview confirmation data, plus "confirm_token": pass that token unchanged to place_option_order (with the identical order arguments) to actually send it. The token expires in 10 minutes and works once. |
| place_option_orderA | Place a real option order (dry_run=False). Requires FT_ALLOW_LIVE_ORDERS=true in .env AND a confirm_token from preview_option_order called with these exact same arguments — the server rejects the order otherwise, it does not just rely on the caller having "meant to" preview first. Args: option_symbol: OCC format symbol (e.g. 'AAPL250620C00150000'). order_type: buy_to_open | sell_to_close | sell_to_open | buy_to_close ('buy' = buy_to_open, 'sell' = sell_to_open; to exit a long option you MUST use sell_to_close, otherwise Firstrade treats it as opening a short and rejects with ref 1103). contracts: Number of contracts. confirm_token: Token returned by preview_option_order for this exact order. price_type: limit | market | stop | stop_limit duration: day | day_ext | gt90 price: Limit price per contract (required for limit orders). stop_price: Stop trigger price (required for stop/stop_limit orders). Returns JSON with order confirmation. This sends a real order to Firstrade. |
| preview_option_spreadA | Preview a two-leg option spread WITHOUT sending it (dry_run=True). Always call this first. Args: symbol1 / symbol2: OCC symbols of the two legs (e.g. 'NVDA261120C00270000'). transaction1 / transaction2: buy_to_open | sell_to_open | sell_to_close | buy_to_close per leg (e.g. debit call spread = leg1 buy_to_open lower strike, leg2 sell_to_open higher strike). limit_type: 'debit' (you pay net_price) or 'credit' (you receive net_price). net_price: Net limit price per spread. contracts1 / contracts2: Contracts per leg (default 1 each). Notes: complex orders are DAY only (no GTC) and accepted by Firstrade only 7AM–4PM ET (ref 1110 otherwise). Returns JSON preview plus "confirm_token": pass that token unchanged to place_option_spread (with the identical arguments) to actually send it. The token expires in 10 minutes and works once. |
| place_option_spreadA | Place a real two-leg option spread (dry_run=False). Requires FT_ALLOW_LIVE_ORDERS=true in .env AND a confirm_token from preview_option_spread called with these exact same arguments — the server rejects the order otherwise, it does not just rely on the caller having "meant to" preview first. Same arguments as preview_option_spread, plus confirm_token. DAY order only; 7AM–4PM ET window. Returns JSON with order confirmation. This sends a real order to Firstrade. |
| cancel_orderA | Cancel an open order by order_id (e.g. 'G42621-1569'). Args: order_id: The order ID returned by place_stock_order or place_option_order. Returns JSON with cancellation result. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 15 tools
Each tool targets a distinct responsibility: account data, quotes, option chains/greeks, order preview vs. placement, and cancellation. The preview/place pairs are clearly separated by the confirm_token workflow, and even the two option-order tools (single vs. spread) are distinct in scope.
The set follows a clear verb-first pattern: get_* for reads, preview_*/place_* for order flows, and cancel_order. Minor inconsistency exists between get_single_quote and get_watchlist_quote, which could be more uniformly get_quote/get_quotes, but the intent remains obvious.
15 tools is at the upper edge of reasonable, but the count is justified by the trading domain: separate preview/place pairs for stocks, options, and spreads plus account data. Could be slightly consolidated (e.g., one quote tool), but it is not bloated.
The set covers the core brokerage workflow well: quotes, positions, balances, history, option chains/greeks, order preview/placement for stocks/options/spreads, and cancellation. Missing order modification/replacement, but cancel+recreate covers most needs.