Skip to main content
Glama
selvakumarEsra

ibkr-mcp-server

ibkr-mcp-server

MCP server that exposes Interactive Brokers via the TWS API as 14 tools: account reads, market data, contract resolution, and order placement.

Paper-by-default. Live trading requires explicit opt-in via IBKR_TRADING_MODE=live.

Prerequisites

  1. TWS or IB Gateway running locally. Download from IBKR.

  2. API enabled in TWS/Gateway: Configure → API → Settings

    • Check "Enable ActiveX and Socket Clients"

    • Uncheck "Read-Only API"

    • Socket port: 7497 (paper) or 7496 (live) — defaults match this server

    • Add 127.0.0.1 to "Trusted IPs"

  3. uv installed: curl -LsSf https://astral.sh/uv/install.sh | sh

Install

git clone <this repo>
cd ibkr-mcp-server
uv sync

Configure

Copy .env.example and adjust as needed (or export the vars in your shell / MCP client config).

Register with Claude Code

Add to ~/.claude.json (or a per-project .mcp.json):

{
  "mcpServers": {
    "ibkr": {
      "command": "uv",
      "args": [
        "--directory", "/absolute/path/to/ibkr-mcp-server",
        "run", "ibkr-mcp-server"
      ],
      "env": {
        "IBKR_TRADING_MODE": "paper",
        "IBKR_CLIENT_ID": "17"
      }
    }
  }
}

Tools

Tool

Purpose

status

Connection + mode + gateway info

get_account_summary

Cash, net liq, buying power, margin

get_positions

Open positions with market price enrichment

get_pnl

Account-level or per-position P&L

get_executions

Today's fills (or since ISO timestamp)

search_symbol

IBKR symbol search

qualify_contract

Resolve symbol → canonical contract with conid

get_quote

Snapshot bid/ask/last/volume

get_historical_bars

OHLCV bars

place_order

Place MKT/LMT/STP/STP_LMT order

place_bracket_order

Entry + take-profit + stop-loss

modify_order

Modify an existing open order

cancel_order

Cancel an open order

list_open_orders

List currently open orders

Safety

  • Mode gate: server reads managedAccounts on connect and verifies prefixes (DU* = paper, U* = live). On mismatch, all order tools are blocked.

  • Audit log: every order placement / modification / cancellation is appended as a JSON line to $IBKR_AUDIT_LOG (default ~/.ibkr-mcp-server/audit.log).

  • Read-only mode: set IBKR_READONLY=1 to disable all order tools.

Risk rails (v2)

Three additional rails apply to place_order, place_bracket_order, and modify_order. cancel_order and list_open_orders are intentionally not gated.

  • Notional caps. Per-order and daily-cumulative ceilings in USD. Mode-aware: paper and live have independent envs. Set to unlimited to disable an individual cap.

  • Rate limit. Each gated tool has its own token bucket (capacity 10, refill 10/min). Hardcoded in v2.

  • Kill switch. If IBKR_HALT_FILE exists, every gated tool returns {status:"rejected", error_code:"HALT", ...} immediately. Remove the file to re-enable.

Blocks are returned as data (same shape as IB-side rejections) and appended to the audit log. They do not raise.

get_quote now returns a data_type field: "live" | "delayed" | "delayed_frozen" | "frozen". The server calls ib.reqMarketDataType(3) on connect so weekend/out-of-hours quotes fall back to delayed data instead of returning nulls.

Env var

Default

Purpose

IBKR_MAX_ORDER_NOTIONAL_PAPER

100000

Per-order notional cap in paper (USD); unlimited to disable

IBKR_MAX_ORDER_NOTIONAL_LIVE

25000

Per-order notional cap in live (USD); unlimited to disable

IBKR_MAX_DAILY_NOTIONAL_PAPER

1000000

Daily cumulative cap in paper; unlimited to disable

IBKR_MAX_DAILY_NOTIONAL_LIVE

100000

Daily cumulative cap in live; unlimited to disable

IBKR_HALT_FILE

~/.ibkr-mcp-server/HALT

Path probed on every order; presence halts all order-mutating tools

Testing

uv run pytest                          # unit tests (default)
IBKR_INTEGRATION_TESTS=1 uv run pytest -m integration   # against a running paper gateway
uv run python scripts/smoke.py         # manual end-to-end smoke