Skip to main content
Glama
zionto

ibkr-mcp

by zionto
README.md
# ibkr-mcp-server

MCP server for Interactive Brokers — Flex Web Service account historical analysis.

## Overview

This server exposes IBKR's [Flex Web Service](https://www.interactivebrokers.com/en/software/am/am/reports/flexwebservice.htm) as MCP tools so that Claude (or any MCP-compatible client) can retrieve and analyse your account history without manual report downloads.

## Prerequisites

1. An Interactive Brokers account.
2. A **Flex Query** configured in Account Management with the desired sections (Trades, OpenPositions, CashTransactions, EquitySummaryInBase, FIFOPerformanceSummaryInBase).
3. A **Flex Web Service token** generated in Account Management → Reports → Flex Queries → Manage → *Generate Token*.

## Setup

```bash
# Install with uv (recommended)
uv sync

# Or with pip
pip install -e .
```

Copy `.env.example` to `.env` and fill in your credentials:

```bash
cp .env.example .env
# edit .env with your IBKR_FLEX_TOKEN and IBKR_FLEX_QUERY_ID
```

## Running the server

```bash
# stdio transport (for Claude Desktop / mcp CLI)
ibkr-mcp

# Or via uv
uv run ibkr-mcp
```

### Claude Desktop config (local stdio)

Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "ibkr": {
      "command": "uv",
      "args": ["run", "--project", "/path/to/ibkr-mcp", "ibkr-mcp"],
      "env": {
        "IBKR_FLEX_TOKEN": "your_token",
        "IBKR_FLEX_QUERY_ID": "your_query_id"
      }
    }
  }
}
```

### claude.ai MCP connector (remote SSE)

claude.ai (Teams / Enterprise) supports custom MCP connectors over HTTPS.
The server must be publicly reachable; use the steps below.

**1. Deploy the server**

```bash
# Option A — Docker (recommended)
docker build -t ibkr-mcp .
docker run -d \
  -e IBKR_FLEX_TOKEN=your_token \
  -e IBKR_FLEX_QUERY_ID=your_query_id \
  -e MCP_TRANSPORT=sse \
  -e MCP_AUTH_TOKEN=your_secret_token \
  -p 8000:8000 \
  ibkr-mcp

# Option B — uv directly (on a VPS / cloud VM)
MCP_TRANSPORT=sse \
MCP_AUTH_TOKEN=your_secret_token \
IBKR_FLEX_TOKEN=your_token \
IBKR_FLEX_QUERY_ID=your_query_id \
uv run ibkr-mcp
```

**2. Put HTTPS in front** (required by claude.ai)

Use any reverse proxy that terminates TLS. A minimal Caddy example:

```
your-domain.com {
    reverse_proxy localhost:8000
}
```

Or use a managed tunnel for quick testing:

```bash
ngrok http 8000   # gives you https://xxxx.ngrok.io
```

**3. Add to claude.ai**

1. Open claude.ai → **Settings** → **Integrations** → **Add custom integration**
2. Fill in:
   - **Name**: IBKR
   - **URL**: `https://your-domain.com/sse`  *(note the `/sse` path)*
3. Under **Authorization**, select **Bearer token** and paste the value of `MCP_AUTH_TOKEN`
4. Click **Save** — the tools appear automatically

> **Health check**: `GET https://your-domain.com/health` returns `{"status":"ok"}` and
> bypasses bearer auth, so you can verify connectivity without credentials.

## Available Tools

### Flex Web Service protocol

| Tool | Description |
|------|-------------|
| `flex_send_request` | Initiate a Flex query; returns a `reference_code` |
| `flex_get_statement` | Download a completed report by reference code (polls until ready) |
| `flex_run_query` | Convenience: send + poll + download in one call |

### XML parsing

| Tool | Description |
|------|-------------|
| `flex_account_info` | Account metadata (account ID, type, currency, date range) |
| `flex_parse_trades` | Trade records — filterable by symbol, asset category, date |
| `flex_parse_positions` | Open position records |
| `flex_parse_cash_txns` | Cash transactions (dividends, interest, fees, etc.) |
| `flex_parse_equity` | Daily NAV / equity summary time series |
| `flex_parse_fifo_pnl` | FIFO realized and unrealized P&L by symbol |

### Analysis

| Tool | Description |
|------|-------------|
| `flex_analyze_pnl` | Aggregate realized P&L from trades; group by symbol, month, year, asset category |
| `flex_analyze_dividends` | Summarize gross dividends and withholding taxes by symbol |
| `flex_analyze_portfolio_history` | Portfolio value over time with total-return calculation |

## Typical workflow

```
1. flex_run_query()                    → xml_content
2. flex_account_info(xml_content)      → account metadata
3. flex_analyze_pnl(xml_content)       → realized P&L by symbol
4. flex_analyze_dividends(xml_content) → dividend income summary
5. flex_analyze_portfolio_history(xml_content) → NAV time series
```

## Flex Query setup guide

Your query must include these **Sections** for full tool coverage:

- **Account Information**
- **Trades** (select *Executions*)
- **Open Positions**
- **Cash Transactions**
- **Equity Summary in Base Currency**
- **FIFO Performance Summary in Base Currency**

Recommended date period: *Last N days* or *Custom Date Range* covering your analysis window.

## Development

```bash
uv sync --dev
pytest tests/
```

TDQS

A4.2/5.0

Scored across 13 tools

Disambiguation5/5

Each tool targets a distinct action or report section. The only potentially overlapping pair is flex_parse_fifo_pnl and flex_analyze_pnl, but their descriptions clearly differentiate raw extraction vs. aggregated analysis. Similarly, flex_run_query explicitly wraps the two-step send/get process.

Naming Consistency4/5

All tools share the flex_ prefix and almost all follow a verb_noun pattern (send_request, parse_trades, analyze_pnl). The sole exception is flex_account_info, which uses a noun-only suffix. This is a minor inconsistency that does not hinder readability.

Tool Count5/5

13 tools is within the ideal 3-15 range for a domain-specific MCP. Each tool covers a distinct stage of the Flex report lifecycle or a different report section, so none feel redundant.

Completeness5/5

The server covers the full workflow: initiate query (flex_send_request), retrieve XML (flex_get_statement, flex_run_query), parse core sections (trades, positions, cash, equity, FIFO P&L), and analyze (PnL, dividends, cash utilization, portfolio history). No obvious missing operations for the stated purpose.

Maintenance

ActivityInactive
ResponsivenessSyncing