MCP server for Interactive Brokers portfolio management, news retrieval, and screener integration with OAuth 2.1 authentication
8 tools with generally good naming (verb_noun pattern) and moderate description quality. All tools are read-only (low risk). However, significant gaps exist: most tools lack documented output schemas, several have minimal or generic parameter descriptions, and error handling is underdeveloped. Tool #8 (ib_screener) has critically weak descriptions. Parameter validation and input constraints are largely absent from descriptions. Output field documentation is missing across all tools, forcing LLMs to guess structure. This is a mid-range server, functional but not production-polished.
Return a summary of the connected Interactive Brokers account. Reads NetLiquidation, BuyingPower, TotalCashValue, AvailableFunds, and UnrealizedPnL from ib-gateway. Read-only.
Look up IBKR scanner filter parameters. Filters narrow scan results (e.g. ``priceAbove``, ``marketCapAbove``, ``avgVolumeAbove``). The catalog groups filters by category (``price``, ``volume``, ``market_cap``, ``fundamentals``, ``technical``, ``options``) and by applicable instrument. Args: category: filter category to list. instrument: instrument code (e.g. ``"STK"``) — restricts the returned filters to those allowed by that instrument.
Fetch the body of a single news article. Args: provider_code: provider code from ``ib_news_for_symbol`` (e.g. ``"BRFG"``, ``"DJ-N"``). article_id: article ID from ``ib_news_for_symbol``. WARNING: Each call may incur a per-article fee charged by the provider (Dow Jones in particular). Use sparingly. Returns ``article_type`` (``0``=plain text, ``1``=HTML, ``2``=binary) and ``article_text``. If the account lacks entitlement for the provider, ``article_text`` is empty and a ``notice`` is included.
Fetch recent news headlines for a US stock symbol. Resolves ``symbol`` to a USD stock contract (SMART routing), pulls up to ``count`` headlines across all subscribed providers from the last ``lookback_days`` days. Returns headline metadata only (no article body). Note: IBKR's ``reqHistoricalNews`` requires per-provider *historical* entitlement, which is separate from the live news subscriptions listed by ``ib_news_providers``. Paper accounts usually have the provider list populated but no historical entitlement, so this tool will return an empty list with a ``notice`` field on a paper connection. Switch the gateway to ``TRADING_MODE=live`` (and use a funded live account with the news subscriptions) to get headlines.
Output schemas undocumented for all tools. LLMs cannot reliably extract or chain results. E.g., ib_account_summary returns a dict with 'account', 'managed_accounts', 'summary', but the structure of 'summary' values is only visible in code, not in the tool definition.
ib_screener has critically weak definition. Description is only 'Run an IBKR scanner with optional filters and sorting' (47 chars), below the 100-char minimum for adequate context. No mention of what scan_code values are valid, what filters are available, or what the output represents. The tool name is vague ('run' is a generic verb); should be 'execute_stock_scanner' or similar.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 55 | 2026-07-28+ | v2 |
List IBKR news providers this account is subscribed to. Some providers (e.g. Briefing, Dow Jones, Reuters) require paid subscriptions; the free set varies per account. The provider ``code`` values returned here are what ``ib_news_for_symbol`` accepts.
Typed catalog of IBKR scan codes. Each entry carries: ``category`` (IBKR taxonomy), ``strategy_tags`` (intent — value, growth, income, momentum_up, etc.), ``vendor``, ``inverse_of`` (paired ASC/DESC or HIGH/LOW code), and the instruments the scan applies to. AND-combines the filters. Args: category: exact category (e.g. ``"Fundamentals"``, ``"Price Movement"``). strategy: exact strategy tag (e.g. ``"value"``, ``"growth"``, ``"income"``). instrument: substring against machine instruments (``"STK"`` matches ``"STK.US.MAJOR"``). query: substring against code/name/description. limit: max rows. list_meta: if True, also return the list of all categories and strategy tags so the LLM can discover what's available.
Run an IBKR scanner with optional filters and sorting
Substring search across raw IBKR scan codes (legacy / fallback). Use ``ib_scan_catalog`` for the typed catalog with categories and strategy tags. This tool still reads ``scan-parameters.xml`` directly and is useful when you need a code that's not in the curated catalog (newer SCAN_* vendor codes, etc.).
Parameter descriptions lack validation constraints. E.g., ib_news_for_symbol's 'count' param has no min/max (the code enforces min 1, max 50, but LLM doesn't know this). ib_scan_catalog's 'limit' defaults to 50 with no stated range. ib_filter_catalog's 'category' has no enum or list of valid values. Without constraints, LLMs guess and pass invalid values.
Error handling is minimal. ib_news_for_symbol returns a 'notice' field on paper accounts, but most tools have no documented error responses. ib_screener has no error guidance. Agents do not know which errors are retryable, which are user-fixable, or what to do next. Missing recovery guidance per pattern:recovery-guide.
Missing chaining IDs. ib_scan_catalog and ib_screener_codes return raw scan codes but no category/strategy tags that the agent would need to refine a search. ib_screener lacks output schema entirely. Downstream tools like ib_scanner likely require scan_code, but the preceding discovery tools don't guarantee those fields will be present.
ib_filter_catalog description and ib_screener_codes description do not explain WHEN to use them relative to ib_scan_catalog. An LLM cannot determine which discovery tool suits a given intent without clearer contextual guidance. The pattern advises: 'Discovery tools should explain what structure they reveal and when to call them.'
ib_news_for_symbol description includes a long note about paper vs. live accounts, but does not formally mark this as a 'notice' field in the output. The code returns {'notice': '...'} on paper accounts, but the agent has no schema to expect this field structure.