Skip to main content
Glama
tivojn

ibkr-mcp-guard

by tivojn

ibkr-mcp-guard

IBKR (guarded): a small local MCP server that lets your AI assistant use Interactive Brokers' official MCP server through a safety guard. The assistant can read your account and market data and create order drafts. It can never send an order to the market.

An opt-in paper trading mode lets the assistant submit orders to an IBKR paper (simulated) account, so you can test strategies. Live accounts can never receive orders.

Unofficial. This project is not affiliated with, endorsed by, or supported by Interactive Brokers. It connects to IBKR's official public MCP server (https://api.ibkr.com/v1/api/mcp-public), announced on 28 July 2026, using IBKR's own browser sign-in.

  • Runs locally over stdio. Needs Node.js 20 or newer and has no npm dependencies.

  • Installs by URL as a plugin in EnConvo, Claude Code and Codex, or runs with npx.

Safety guarantees

Never requests order submission

It asks for the scopes openid account-ids mcp.read mcp.write and nothing else. If code ever asks for mcp.orders.submit, an assertion throws, and a test checks this. If IBKR grants that scope anyway, ibkr_status reports it. The only exception is the opt-in paper trading mode, which you must turn on yourself.

Submit tools removed

Any upstream tool that places, submits, transmits or executes an order, or that requires mcp.orders.submit, is removed from the tool list and refused if called by name. This also covers buy/sell tools, replies to order confirmations, and changes to live orders.

Drafts only

Order instructions (create_order_instruction, delete_order_instruction) are IBKR's order drafts. They are listed with the warning "Creates/changes an order DRAFT (order instruction) only — nothing is sent to the market; you approve drafts inside IBKR." and marked destructiveHint: true. A draft becomes an order only when you approve it inside IBKR.

Asks before drafting

If your MCP client supports elicitation, the guard asks you to Approve or Cancel each draft before sending it. Otherwise your host's own tool-approval prompt applies, which is triggered by destructiveHint.

Tokens stay local

macOS: stored in your login Keychain. Elsewhere: stored in a file with mode 0600. Tokens are never logged.

Nothing else leaves your machine

The guard connects only to api.ibkr.com, plus 127.0.0.1 for the sign-in callback. There is no telemetry and no third-party server.

Tool classes:

Class

Examples

Behaviour

read

get_account_balances, get_account_positions, get_account_summary, get_account_orders, get_account_trades, get_price_snapshot, get_price_history, get_option_data, search_contracts, whats_new

Listed with readOnlyHint: true.

write

create_alert, set_alert_status, watchlist create/update/delete, provide_customer_feedback

Listed with readOnlyHint: false, destructiveHint: false.

draft

create_order_instruction, delete_order_instruction

Listed with the DRAFT prefix and destructiveHint: true; asks first when the client supports elicitation.

block

place_order, submit_order, transmit_order, any tool requiring mcp.orders.submit

Never listed, never called.

Set IBKR_MCP_GUARD_READONLY=1 to hide the write and draft tools as well.

Related MCP server: IBKR MCP Server

Install

EnConvo

Open Plugins → Install from URL and paste:

https://github.com/tivojn/ibkr-mcp-guard

EnConvo reads .mcp.json and expands ${CLAUDE_PLUGIN_ROOT}.

Claude Code

As a plugin (this repo is its own marketplace):

claude plugin marketplace add https://github.com/tivojn/ibkr-mcp-guard
claude plugin install ibkr-mcp-guard@ibkr-mcp-guard

Inside Claude Code, the same commands are /plugin marketplace add tivojn/ibkr-mcp-guard followed by /plugin install ibkr-mcp-guard@ibkr-mcp-guard.

Or as a plain MCP server:

claude mcp add ibkr -- npx -y github:tivojn/ibkr-mcp-guard

Codex

Add to ~/.codex/config.toml:

[mcp_servers.ibkr]
command = "npx"
args = ["-y", "github:tivojn/ibkr-mcp-guard"]
startup_timeout_sec = 60   # the first npx run downloads the package

If you use a local clone, set command = "node" and args = ["/path/to/ibkr-mcp-guard/server/index.mjs"]. The repo also ships a .codex-plugin/plugin.json manifest for hosts that install Codex-format plugins by URL.

Any other MCP client

npx -y github:tivojn/ibkr-mcp-guard        # stdio MCP server
# or from a clone:
node server/index.mjs

First use

  1. Ask your assistant to "sign in to IBKR", or ask any IBKR question, such as "what are my positions?".

  2. Your browser opens IBKR's sign-in page. The consent screen should list read access and order-instruction (draft) access only, not order submission. Approve it.

  3. The tab says Signed in to IBKR. Go back to the assistant and ask again.

The guard's own tools work before you sign in:

  • ibkr_sign_in opens the browser sign-in. It returns immediately and finishes in the background, and does nothing if you are already signed in.

  • ibkr_status shows whether you are signed in, your account ids (if IBKR reports them), the granted scopes, when the token expires, and whether order submission was granted (it should say no).

  • ibkr_sign_out revokes the tokens at IBKR and deletes them locally.

  • ibkr_paper_log (only in paper trading mode) shows the latest paper-order audit entries.

Before you first sign in, the tool list shows only these three tools. After that, the guard caches IBKR's tool list, so the tools still appear when you are signed out. Calling one while signed out starts a sign-in.

Environment variables

Variable

Effect

IBKR_MCP_GUARD_READONLY=1

Hide and refuse write and draft tools; reads only. Also turns paper mode off.

IBKR_MCP_GUARD_PAPER=1

Paper trading mode: order submission to IBKR paper accounts only.

IBKR_MCP_GUARD_PAPER_NO_CONFIRM=1

In paper mode, skip the guard's Approve/Cancel prompt before each paper order (for automated strategy runs). Has no effect outside paper mode.

IBKR_MCP_GUARD_STORE=file

Use the 0600 file instead of the macOS Keychain.

IBKR_MCP_GUARD_NO_BROWSER=1

Don't open a browser; the sign-in result includes the link to open yourself (useful over SSH).

CLAUDE_PLUGIN_DATA / PLUGIN_DATA

Data directory (set by plugin hosts). Otherwise $XDG_CONFIG_HOME/ibkr-mcp-guard or ~/.config/ibkr-mcp-guard.

IBKR_MCP_GUARD_UPSTREAM

Testing only: a different upstream MCP URL. A warning is logged to stderr.

The data directory holds the token file (non-macOS, or with STORE=file), tools-cache.json (the last tool list, which contains no secrets) and, in paper mode, paper-orders.log.

Paper trading mode

Paper trading mode is for testing strategies on an IBKR paper trading account through IBKR's official connector. It is off by default. When it is off, nothing on this page applies and the guard behaves exactly as described above.

What it does

With IBKR_MCP_GUARD_PAPER=1:

  • The sign-in also asks for order submission. The guard requests openid account-ids mcp.read mcp.write mcp.orders.submit. Only this code path can ask for mcp.orders.submit; the default path still throws if anything asks for it.

  • Changing modes needs a new sign-in. Each saved sign-in remembers which scopes it was made with. If you turn paper mode on or off, the old sign-in is not used, and the guard asks you to sign in again.

  • Order submission is gated to paper accounts. The tools that the default mode removes (place, submit, cancel or modify orders, and so on) are allowed only when every account the sign-in can see is a paper account, meaning its id starts with DU or DF. Before every submit, the guard:

    1. reads the account ids again from IBKR, by calling the account tools (get_account_positions, get_account_balances, get_account_summary, get_account_orders and any other read tool whose name mentions accounts) and scanning their answers for account ids;

    2. refuses if it sees any non-paper id (U…, F…, I…), or if it cannot find any account id at all;

    3. refuses if the order's arguments name an account that is not one of those paper accounts.

    The result of this check is never cached. Each submit makes its own check.

  • Submit tools are shown only while the session is paper-only. They are listed with the description prefix "PAPER ACCOUNT ONLY — submits a simulated order to your IBKR paper account (DU…). Refused for live accounts." and destructiveHint: true. The guard checks again on every tools/list and after each sign-in, and sends notifications/tools/list_changed when the answer changes. At other times the submit tools are hidden, and they are refused if called by name.

  • Every order is confirmed. If your MCP client supports elicitation, the guard shows a plain read-back (account, side, quantity, symbol, order type, price if given, time in force) and asks you to Approve or Cancel. After you approve, it checks the accounts again before sending. Without elicitation, your host's own approval prompt applies, which is triggered by destructiveHint. For automated strategy runs, IBKR_MCP_GUARD_PAPER_NO_CONFIRM=1 skips the guard's prompt. Even then, orders still go only to paper accounts.

  • Every attempt is logged. Each paper submit attempt (submitted, failed, refused or cancelled) is added as one JSON line to paper-orders.log in the data directory (file mode 0600). Each line records the time, the tool, the decision and reason, the accounts seen, a read-back of the order and its arguments. Tokens are never written to the log. Use the ibkr_paper_log tool (optional limit, default 20) to see recent entries.

  • ibkr_status shows the paper state: whether paper mode is on, the accounts seen in a fresh read (each labelled paper or LIVE), whether mcp.orders.submit was granted, and whether submits are allowed right now and why.

IBKR_MCP_GUARD_READONLY=1 overrides paper mode: the guard does not request the submit scope and no orders are submitted.

Get a paper login

  1. In IBKR's Client Portal, open Settings → Paper Trading Account. Create (or reset) your paper account there and note its username. Paper accounts start with simulated funds, normally USD 1,000,000.

  2. When the guard opens IBKR's sign-in page, set the login page's Live / Paper switch to Paper, then sign in with the paper username.

IBKR's official MCP connector does accept paper logins. A paper sign-in through this guard has been checked: the account summary showed the paper account's USD 1,000,000 net liquidation value and no positions. If you sign in with a live login while paper mode is on, the guard sees the live account id and refuses every submit.

Turn it on

Paper mode is set by an environment variable on the MCP server, so set it in your host's server configuration.

EnConvo: in the plugin's MCP server settings, add the environment variable IBKR_MCP_GUARD_PAPER with value 1 (and, if you want, IBKR_MCP_GUARD_PAPER_NO_CONFIRM = 1). Then restart the server.

Claude Code: add it as a separate MCP server with the variable set:

claude mcp add -e IBKR_MCP_GUARD_PAPER=1 ibkr-paper -- npx -y github:tivojn/ibkr-mcp-guard

Codex (~/.codex/config.toml):

[mcp_servers.ibkr-paper]
command = "npx"
args = ["-y", "github:tivojn/ibkr-mcp-guard"]
env = { IBKR_MCP_GUARD_PAPER = "1" }
startup_timeout_sec = 60

After you turn it on, ask the assistant to "sign in to IBKR", sign in with your paper login, and then run ibkr_status. It should show your DU… account labelled paper and "Paper order submission allowed now: yes".

Paper trading is simulated. Paper fills, prices and margin can differ from what would happen in a live account, and results in paper trading do not predict live results. This is not financial advice.

Troubleshooting

  • The browser didn't open. Use the link in the tool result, or set IBKR_MCP_GUARD_NO_BROWSER=1. The sign-in must finish on the same machine, because IBKR redirects to http://127.0.0.1:<port>/callback.

  • "Sign-in timed out". The flow waits 10 minutes. Ask to sign in again.

  • "Sign-in did not match". You opened an old sign-in tab. Start a new sign-in.

  • No IBKR tools after signing in. Your client may ignore notifications/tools/list_changed. Restart the MCP server or reload tools.

  • Signed out unexpectedly. IBKR refused to renew the token (for example, it was revoked or expired). Sign in again.

  • Reset everything. Run ibkr_sign_out. Then:

    • On macOS, delete the Keychain items with service ibkr-mcp-guard (Keychain Access, or security delete-generic-password -s ibkr-mcp-guard -a https://api.ibkr.com/v1/api/mcp-public).

    • Elsewhere, delete the data directory.

  • Logs. The server logs to stderr only. stdout carries MCP JSON-RPC.

  • Paper mode refuses every submit. Run ibkr_status. "This sign-in can see non-paper (live) account(s)" means you signed in with a live login: sign out and sign in with your paper login. "No account ids could be read" means IBKR's account tools did not return any account id, so the guard cannot confirm that only paper accounts are visible.

  • "You need to sign in again" after changing paper mode. This is expected: a sign-in made in one mode is not used in the other.

  • Why Node's fetch? api.ibkr.com asks for an optional TLS client certificate. Chromium-based HTTP stacks treat that as fatal, but Node's fetch handles it.

How it works

your AI host ──stdio (MCP)──▶ ibkr-mcp-guard ──HTTPS (MCP Streamable HTTP + OAuth bearer)──▶ api.ibkr.com/v1/api/mcp-public
                                   │ policy: block / draft / write / read
                                   └─ tokens: macOS Keychain or 0600 file
  • MCP server (stdio): newline-delimited JSON-RPC 2.0 with initialize, ping, tools/list and tools/call.

    • Protocol versions 2025-11-25, 2025-06-18, 2025-03-26 and 2024-11-05 are supported; 2025-06-18 is the default.

    • It sends notifications/tools/list_changed after sign-in and sign-out.

    • When the client supports it, it uses elicitation/create to confirm drafts.

  • Upstream client: MCP Streamable HTTP. It accepts JSON or SSE answers, tracks Mcp-Session-Id, follows tools/list paging and applies timeouts. A 401 triggers one token refresh, and a second 401 starts a new sign-in.

  • Sign-in (MCP authorization, OAuth 2.1):

    • Discovery from the WWW-Authenticate resource_metadata value (RFC 9728), then the authorization-server metadata (RFC 8414, path-inserted URL first).

    • Dynamic Client Registration (RFC 7591) as a public native client, with a loopback redirect http://127.0.0.1:<port>/callback. The registered port is reused when it is free; otherwise the guard registers again.

    • PKCE S256 (RFC 7636), plus a random state that is checked on the callback.

    • The resource parameter (RFC 8707) is sent.

    • Refresh tokens are rotated, and tokens are revoked on sign-out.

Development

npm test                 # node --test: offline, fake upstream + fake OAuth server

The tests cover:

  • discovery using IBKR's real metadata strings

  • the DCR body, PKCE (RFC 7636 test vector), state mismatch, and the scope assertion

  • policy classification of the real tool names

  • paper mode: the default path never asking for mcp.orders.submit, the paper scopes, mode changes needing a new sign-in, the DU/DF gate (live ids, unknown ids, accounts named in the order), tool visibility and list_changed, Approve/Cancel, NO_CONFIRM, the audit log and status

  • tools/list filtering and the draft prefix

  • the signed-out call and the 401 refresh

  • SSE parsing

  • the 0600 token file

  • an end-to-end stdio round trip (sign-in, list, call, block, elicitation) against a local fake MCP server

Disclaimer

This software is provided as is, under the MIT License, without warranty of any kind. It is not financial advice, and nothing it or your assistant outputs is a recommendation to buy or sell anything. AI assistants make mistakes: check every number and every draft yourself in IBKR before acting. You use it at your own risk and remain responsible for every action taken in your account. Interactive Brokers, IBKR and related marks belong to their owners.

License

MIT © 2026 Adam Cohen

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    B
    maintenance
    Enables AI assistants to interact with Interactive Brokers trading accounts to retrieve market data, check positions, and place trades. Includes pre-configured IB Gateway and handles OAuth authentication automatically.
    14
    283 npm
    219
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides AI models with secure access to Interactive Brokers trading data and functionality, enabling account management, market data retrieval, and trading operations through natural language interactions.
    18
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Connects AI assistants to Interactive Brokers for intelligent portfolio management, options analysis, risk monitoring, and automated trading strategy suggestions. Enables real-time account tracking, Greeks calculations, option chain analysis, and playbook-based risk adjustments through natural language.
    5
    -
  • A
    license
    B
    quality
    D
    maintenance
    Gives AI assistants real-time access to Interactive Brokers accounts via the Client Portal Web API, with 26 read-only tools for portfolio, market data, options, and scanner.
    32
    24 npm
    2
    MIT