Skip to main content
Glama
aiordanescu

ib-gateway-mcp

by aiordanescu

Gateway health

get_health
Read-only

Check the Interactive Brokers gateway connection status and diagnose why it might be unusable. Call this first when other tools fail with not_connected or timeouts.

Instructions

Report whether the Interactive Brokers gateway connection is usable, and what is known about why not.

Call this first when another tool fails with not_connected or times out. It never
fails itself. `state` is one of:
- connected: everything works.
- connecting: a connection attempt is in progress.
- not_accepting: the gateway refused or ignored the connection; this alone doesn't say
  why. Retries run in the background.
- connectivity_lost: the gateway is up but cut off from IBKR's servers; usually heals.
- not_connected: stopped, or the connection dropped and a retry is pending.
`hint` explains what to do. `last_disconnect_at` is when the connection last went down,
kept after it comes back (this server's start time if it started during the outage).
`login_state` (if configured) is the gateway's login phase: restarting or logging_in
(in progress), awaiting_2fa (the account holder must approve a challenge), throttled
(paused until retry_at; it logs in again then only if its login automation is set to
retry), login_rejected (it won't retry), login_idle (nothing is retrying), unknown
(detail says why), or logged_in, which only means the last login in the gateway's log
succeeded; later events aren't logged there, and an old log_updated_at is normal then.
Without login_state, relay hint and report last_disconnect_at; don't guess a cause the
hint doesn't name.
`trading_enabled` says whether the trading gate is open (order tools also need
`circuit_open` false: after repeated IBKR rejections the breaker halts submits until a
human resets it). `api_read_only` means the gateway's own settings reject orders.
`is_paper` is true when the login only has paper accounts. `market_data_type` is the
requested data type (set_market_data_type), and `subscriptions_used`/`subscriptions_max`
count open streams. Pass probe=true to test the connection with a real request (the
state alone can lag behind a stalled socket).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
probeNoAlso send one request to the gateway (its clock) to prove the connection answers right now; the outcome is in `probe`. Takes up to IB_REQUEST_TIMEOUT.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
hintNoWhat is wrong and what to do, when not connected.
hostYes
portYes
probeNoResult of the live round trip; null unless probe=true was asked.
stateYes
accountsNoAccounts this server may use (the allowlist).
is_paperNoTrue when every managed account is a paper account (None: unknown).
client_idYes
last_errorNo
login_stateNoThe gateway's login phase, read from its launcher.log; null unless IB_GATEWAY_SETTINGS_DIR is set.
circuit_openNoTrue when the order circuit breaker tripped after consecutive IBKR rejections: submit_order refuses new orders, modifications and exercises until a human resets it (reset_circuit_breaker, admin toolset). Cancels still work.
api_read_onlyNoThe gateway rejected a request because its API is read-only (321).
orders_syncedNoWhether this session loaded the open and completed orders (skipped when no order toolset is enabled). Informational only: trading_enabled decides whether order tools work.
server_versionNoTWS API server version (when connected).
connected_sinceNo
trading_enabledYesWhether the trading gate is open right now: connected, accounts allowed, live trading permitted, API not read-only. Order submits are also refused while circuit_open is true.
market_data_typeNoMarket data type requested for this session (live, frozen, delayed...).
circuit_thresholdNoConsecutive rejections that trip the breaker; null when disabled.
subscriptions_maxNoSubscription limit (IBKR_MCP_MAX_SUBSCRIPTIONS).
circuit_rejectionsNoConsecutive IBKR order rejections since the last accepted order.
last_disconnect_atNoWhen the connection last went down (UTC), kept after it comes back, so with connected_since it gives the last outage window. If the gateway was already down when this server started, the server's start time (the outage may be older). Null while no outage has been seen.
subscriptions_usedNoOpen streaming subscriptions.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed4 schema fields changedv0.2.0
    • addedOutput schema / $defs / LoginPhase
      Added value: +{
      +  "description": "The gateway's login phase, as its launcher.log shows it.\n\n- logged_in: the last login in the log succeeded. The gateway logs nothing after a\n  successful login, so later events (a stop, an ended session) aren't visible here,\n  and an old log_updated_at is normal.\n- restarting: the gateway just started (a container start or the daily auto-restart)\n  and is about to log in.\n- logging_in: a login is in progress, including the gateway's own retries, or IBKR just\n  ended one (detail says so; a new login then follows only if the gateway's login\n  automation is set to retry).\n- awaiting_2fa: IBKR sent a second-factor challenge (an IB Key push, for example) and\n  the gateway waits for the account holder to approve it.\n- throttled: the gateway is pausing logins after repeated failures until retry_at. It\n  logs in again then only if its login automation is set to retry (ib-gateway-docker:\n  RELOGIN_AFTER_TWOFA_TIMEOUT=yes); otherwise the phase turns login_idle.\n- login_rejected: IBKR rejected the login; the gateway doesn't retry by itself.\n- login_idle: the gateway runs but isn't logged in, and nothing is retrying.\n- unknown: launcher.log can't tell (unreadable, silent, or no gateway start in it);\n  detail says why.",
      +  "enum": [
      +    "logged_in",
      +    "restarting",
      +    "logging_in",
      +    "awaiting_2fa",
      +    "throttled",
      +    "login_rejected",
      +    "login_idle",
      +    "unknown"
      +  ],
      +  "title": "LoginPhase",
      +  "type": "string"
      +}
    • addedOutput schema / $defs / LoginState
      Added value: +{
      +  "description": "What the gateway's launcher.log says about its login to IBKR.",
      +  "properties": {
      +    "counted_since": {
      +      "anyOf": [
      +        {
      +          "format": "date-time",
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "default": null,
      +      "description": "Start of the counts (UTC): the successful login before the sequence, or the oldest log line read.",
      +      "title": "Counted Since"
      +    },
      +    "counts_complete": {
      +      "default": false,
      +      "description": "False when the log files read hold no earlier successful login: the counts are then a lower bound.",
      +      "title": "Counts Complete",
      +      "type": "boolean"
      +    },
      +    "detail": {
      +      "anyOf": [
      +        {
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "default": null,
      +      "description": "More about the phase, in this server's fixed wording (never text from the log).",
      +      "title": "Detail"
      +    },
      +    "log_updated_at": {
      +      "anyOf": [
      +        {
      +          "format": "date-time",
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "default": null,
      +      "description": "Last write to launcher.log (UTC). An old time is normal while logged_in; before a login the gateway writes to it every few minutes.",
      +      "title": "Log Updated At"
      +    },
      +    "login_attempts": {
      +      "anyOf": [
      +        {
      +          "type": "integer"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "default": null,
      +      "description": "Authentication rounds in the current login sequence: since the last successful login, or, while logged_in, the rounds that led to it. Null when unknown.",
      +      "title": "Login Attempts"
      +    },
      +    "phase": {
      +      "$ref": "#/$defs/LoginPhase",
      +      "description": "The gateway's login phase."
      +    },
      +    "retry_at": {
      +      "anyOf": [
      +        {
      +          "format": "date-time",
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "default": null,
      +      "description": "When the gateway's pause after repeated failed logins ends (UTC); set only while throttled. The gateway logs in again then only if its login automation is set to retry (ib-gateway-docker: RELOGIN_AFTER_TWOFA_TIMEOUT=yes).",
      +      "title": "Retry At"
      +    },
      +    "since": {
      +      "anyOf": [
      +        {
      +          "format": "date-time",
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "default": null,
      +      "description": "When this phase began, per the log (UTC); null when unknown.",
      +      "title": "Since"
      +    },
      +    "twofa_challenges": {
      +      "anyOf": [
      +        {
      +          "type": "integer"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "default": null,
      +      "description": "Second-factor challenges (IB Key pushes and the like) IBKR sent in the same login sequence. Null when unknown.",
      +      "title": "Twofa Challenges"
      +    }
      +  },
      +  "required": [
      +    "phase"
      +  ],
      +  "title": "LoginState",
      +  "type": "object"
      +}
    • addedOutput schema / properties / last_disconnect_at
      Added value: +{
      +  "anyOf": [
      +    {
      +      "format": "date-time",
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "When the connection last went down (UTC), kept after it comes back, so with connected_since it gives the last outage window. If the gateway was already down when this server started, the server's start time (the outage may be older). Null while no outage has been seen.",
      +  "title": "Last Disconnect At"
      +}
    • addedOutput schema / properties / login_state
      Added value: +{
      +  "anyOf": [
      +    {
      +      "$ref": "#/$defs/LoginState"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "The gateway's login phase, read from its launcher.log; null unless IB_GATEWAY_SETTINGS_DIR is set."
      +}
  2. First observedv0.1.0

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say readOnly/openWorld; the description adds substantial behavior the agent cannot get elsewhere: it never fails itself, retries run in the background for not_accepting, connection often self-heals, last_disconnect_at is intentionally retained, login_state semantics including the subtle caveat about logged_in being only the last logged event, and the circuit-breaker gate. This is exactly the extra context annotations cannot supply.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads purpose and the call-first trigger, then uses a clean bulleted enumeration of states. It is long, but nearly every sentence carries distinct semantics; only minor tightening of the field-glossary sentence would be possible.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Even though an output schema exists (so return values need not be explained), the description still maps each state and hint field to actionable meaning, covering the safety, gating, and failure-recovery context an agent needs to act on the result. Nothing material is missing for a one-parameter diagnostic tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single probe parameter is fully described in the schema, so the 3 baseline applies; the description earns above baseline by supplying the rationale for probing ('the state alone can lag behind a stalled socket'), which the schema does not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (report) and resource (IB gateway connection usability) plus the diagnostic intent ('what is known about why not'). This is clearly distinct from read-only data siblings like get_account_summary or get_connection_info: an agent can tell immediately this is the health/diagnosis tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger ('Call this first when another tool fails with not_connected or times out'), an explicit non-guidance rule ('don't guess a cause the hint doesn't name'), and a conditional escalation path (probe=true when the state may lag). Routing guidance is complete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.