Skip to content

Broker Layer — New MCP Tools

Problem

Current trading tools (trading_place_limit_order, etc.) work by automating TradingView's UI — clicking buttons, filling forms, scraping order tables. This is: - Fragile: Breaks when TradingView updates CSS selectors - Slow: 2-5 seconds per operation (wait for UI transitions) - Limited: No access to account data, position sizing, or order types beyond what the UI exposes - Paper Trading only: No real broker connection

Solution: Direct Broker API MCP Tools

Add new MCP tools that call broker APIs directly, bypassing TradingView's trading panel entirely.


Broker: Tradovate

API: REST + WebSocket Auth: OAuth 2.0 (client credentials or authorization code) Docs: https://api.tradovate.com Markets: CME futures (ES, NQ, CL, GC, etc.)

New Tools

broker_tradovate_connect

Authenticate with Tradovate API.

Params:
  credentials: "demo" | "live"    # Which environment
Returns:
  { connected: true, account_id: "...", environment: "demo", balance: 50000 }
Implementation: OAuth token exchange, store token in memory. Refresh automatically.

broker_tradovate_account

Get account info (balance, margin, buying power).

Params: (none)
Returns:
  { account_id, balance, available_margin, realized_pnl, unrealized_pnl }

broker_tradovate_place_order

Place an order via API.

Params:
  symbol: string          # "ESU6", "NQU6", "CLV6"
  side: "buy" | "sell"
  type: "limit" | "market" | "stop" | "stop_limit"
  quantity: number        # Number of contracts
  price?: number          # Required for limit/stop_limit
  stop_price?: number     # Required for stop/stop_limit
  bracket?: {
    take_profit: number   # Limit price for profit target
    stop_loss: number     # Stop price for protective stop
  }
  time_in_force: "day" | "gtc" | "ioc" | "fok"
Returns:
  { order_id, status: "pending" | "filled" | "rejected", fill_price?, message? }

broker_tradovate_modify_order

Modify a pending order (price, quantity, bracket levels).

Params:
  order_id: string
  price?: number
  quantity?: number
  bracket?: { take_profit?: number, stop_loss?: number }
Returns:
  { order_id, status: "modified", new_price, new_quantity }

broker_tradovate_cancel_order

Cancel a pending order.

Params:
  order_id: string
Returns:
  { order_id, status: "cancelled" }

broker_tradovate_get_orders

List all orders (pending, filled, cancelled).

Params:
  status?: "pending" | "filled" | "cancelled" | "all"
Returns:
  [{ order_id, symbol, side, type, quantity, price, status, fill_price, timestamp }]

broker_tradovate_get_positions

List open positions.

Params: (none)
Returns:
  [{ symbol, side, quantity, avg_price, unrealized_pnl, margin_used }]

broker_tradovate_close_position

Flatten a position (market order to close).

Params:
  symbol: string
Returns:
  { symbol, closed_quantity, fill_price, realized_pnl }

broker_tradovate_get_fills

Get recent fill history.

Params:
  symbol?: string
  limit?: number          # Default 50
Returns:
  [{ fill_id, order_id, symbol, side, quantity, price, timestamp }]


Broker: Interactive Brokers (IBKR)

API: Client Portal API (REST) or TWS API (socket) Auth: Session-based (Client Portal) or TWS gateway Markets: All asset classes (stocks, options, futures, forex)

New Tools

broker_ibkr_connect

Authenticate with IBKR Client Portal or TWS gateway.

Params:
  mode: "portal" | "tws"       # Client Portal REST or TWS socket
  port?: number                 # TWS gateway port (default 7497 paper, 7496 live)
Returns:
  { connected: true, account_id: "...", mode: "paper" | "live" }

broker_ibkr_account

Get account summary.

Params: (none)
Returns:
  { account_id, net_liquidation, available_funds, buying_power, cushion }

broker_ibkr_place_order

Place an order.

Params:
  symbol: string          # Contract identifier (e.g., "ES", "AAPL")
  sec_type: "FUT" | "STK" | "OPT" | "FX"
  side: "buy" | "sell"
  type: "limit" | "market" | "stop" | "stop_limit" | "trail"
  quantity: number
  price?: number
  stop_price?: number
  trail_amount?: number
  bracket?: { take_profit: number, stop_loss: number }
  time_in_force: "day" | "gtc" | "ioc"
Returns:
  { order_id, status, message? }

broker_ibkr_modify_order

Modify pending order.

Params:
  order_id: string
  price?: number
  quantity?: number
  stop_price?: number
Returns:
  { order_id, status: "modified" }

broker_ibkr_cancel_order

Cancel pending order.

Params:
  order_id: string
Returns:
  { order_id, status: "cancelled" }

broker_ibkr_get_orders

List orders.

Params:
  status?: "pending" | "filled" | "cancelled" | "all"
Returns:
  [{ order_id, symbol, side, type, quantity, price, status, timestamp }]

broker_ibkr_get_positions

List open positions.

Params: (none)
Returns:
  [{ symbol, sec_type, side, quantity, avg_price, market_price, unrealized_pnl }]

broker_ibkr_close_position

Flatten position.

Params:
  symbol: string
  sec_type: "FUT" | "STK" | "OPT" | "FX"
Returns:
  { symbol, closed_quantity, fill_price, realized_pnl }

broker_ibkr_get_fills

Recent fill history.

Params:
  symbol?: string
  limit?: number
Returns:
  [{ fill_id, order_id, symbol, side, quantity, price, commission, timestamp }]


Shared / Broker-Agnostic Tools

These tools work across any connected broker:

broker_status

Check which broker is connected and its state.

Returns:
  { broker: "tradovate" | "ibkr" | "paper" | "none", environment: "demo" | "live", connected: boolean }

broker_position_size

Calculate position size based on risk parameters.

Params:
  account_balance?: number     # Override (otherwise reads from broker)
  risk_percent: number         # e.g., 1.0 for 1%
  entry_price: number
  stop_price: number
  tick_size: number            # e.g., 0.25 for ES
  tick_value: number           # e.g., 12.50 for ES
Returns:
  { risk_dollars, stop_distance_ticks, position_size, margin_required }

broker_risk_check

Pre-flight validation before placing an order.

Params:
  symbol: string
  side: "buy" | "sell"
  quantity: number
  entry_price: number
  stop_price: number
Returns:
  { approved: boolean, risk_dollars, risk_percent, margin_available, warnings: [] }


Implementation Plan

Phase 1: Tradovate Demo

  1. Add src/core/broker-tradovate.js — REST client with OAuth
  2. Add src/tools/broker.js — MCP tool registrations
  3. Test against Tradovate demo environment
  4. Wire into FATBot dashboard position/order panels

Phase 2: IBKR Paper

  1. Add src/core/broker-ibkr.js — Client Portal REST or TWS socket
  2. Extend src/tools/broker.js with IBKR tools
  3. Test against IBKR paper trading

Phase 3: Risk Controls

  1. Implement broker_position_size and broker_risk_check
  2. Add max position limits, daily loss limits
  3. Require confirmation for live environment orders

Phase 4: Live Trading

  1. Enable live environment credentials (with explicit user confirmation)
  2. Add order audit log
  3. Add kill-switch tool (broker_flatten_all)

Safety Requirements

  1. Demo/paper first — All tools must work in demo/paper before live
  2. Explicit environment selection — Never default to live
  3. Risk checks before ordersbroker_risk_check should be called before broker_*_place_order
  4. Confirmation for destructive actions — Flatten all, cancel all
  5. Audit logging — Every order action logged with timestamp
  6. Max position limits — Configurable per-symbol contract limits
  7. Daily loss limit — Stop trading if daily P&L exceeds threshold
  8. No credentials in code — Use environment variables or secure config