Read-only MCP server for analyzing brokerage portfolios. Trading 212 today, extensible to more brokers.
This is a well-structured portfolio MCP server with 25 tools across four brokers (Trading 212, Bybit, Crypto, Interactive Brokers). Strengths: consistent naming convention (verb_noun, all prefixed with broker ID), descriptions are detailed and explain prerequisites/permissions clearly, input schemas use proper Zod validation with type constraints. Weaknesses: output schemas are not formally documented in the code (no documented return types visible), many simple tools have empty parameter objects with no flexibility, descriptions are at the longer end (many >200 chars, approaching token waste), and there is no visible error handling/recovery guidance beyond basic descriptions. Tool annotations present (title, openWorldHint). The server demonstrates good patterns around explaining when to use cross-source tools (e.g., 'portfolio_snapshot' as the alternative), and permissions are clearly stated. However, production-grade quality would require: documented output shapes, richer error responses with recovery steps, and possibly batch operations for common multi-call scenarios.
Returns the Bybit UNIFIED account summary in USD: total equity (includes derivatives UPL and option value), wallet/margin/available balances, perp unrealized P&L, and margin health rates (accountIMRate/accountMMRate — an accountMMRate near 1 means liquidation risk), plus per-coin detail. In that per-coin detail, `quantity` and `equity` are COIN amounts (not dollars) and `usdValue` is the dollar value — `usdValue` is absent for coins with no USD market (e.g. delisted/zero-price tokens), so read a coin's worth from `usdValue` and never treat `quantity`/`equity` as money. Other per-coin fields: unrealized/cumulative realized P&L, borrow amount, accrued interest, locked. Requires a read-only key with Account/Wallet read permission.
Returns total equity (USD) across ALL Bybit account types — Funding wallet, Unified Trading, Earn, Trading Bots, Copy Trading, Launchpool — with per-account coin holdings, plus Funding-wallet coin quantities. The USD figures are the account/total `equity` fields (in valuationCurrency); the per-coin `quantity` is a COIN AMOUNT, NOT a dollar value — a delisted or zero-price token can show a large quantity worth ~$0, so never read a coin quantity as money (use bybit_get_positions for USD-valued per-coin holdings). Catches money invisible to bybit_get_positions (which covers the Unified account only). Requires the Assets (Wallet) read permission on the API key; per-source failures are listed in a `failures` field.
Returns open Bybit derivatives positions — USDT/USDC perpetuals and futures (linear), inverse contracts, and options: side (long/short), size, entry and mark price, position value, unrealized P&L, realized P&L, leverage, liquidation price, take-profit/stop-loss. Values are in the contract's settle coin. Spot coin balances are NOT included — use bybit_get_positions for those. Per-category failures are reported in a `failures` field without hiding other categories.
Output schemas are not formally documented. While tools clearly fetch and return structured data (account summaries, positions, dividends, etc.), there is no visible documentation of return type shapes in the code. LLMs cannot plan downstream processing without knowing what fields to expect.
Most empty-argument tools (get_account, get_positions, etc.) have no input flexibility. 10 tools accept zero parameters and use EmptyArgs with additionalProperties: false, which is correct but inflexible. If future versions need optional filters (date range, currency, status), adding them requires schema changes. Consider reserved optional params like 'options' (object) or 'filter' for forward compatibility.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | B | 72 | 2026-07-28+ | v2 |
Returns staked and saving balances across Bybit Earn families — flexible savings, on-chain staking, fixed-term deposits, the BYUSDT yield token, and dual-asset products — with amount, APY (percent), claimable/accrued yield, status, and settlement time where reported. These funds do NOT appear in bybit_get_positions or bybit_get_account. Requires the Earn read permission on the API key; per-family failures are listed in a `failures` field.
Reports what the configured Bybit API key can do: read-only flag, permission groups (diagnoses missing Wallet/Assets or Earn access for other tools), IP allowlist, expiry date with days remaining, and account margin mode/UTA status. Works with any permission set. Includes warnings when the key is not read-only or expires within 14 days.
Returns the user's currently open (unfilled) orders on Bybit — spot plus USDT/USDC linear (perpetual) orders: symbol, side (buy/sell), order type, limit price, quantity, filled quantity, and status. Read-only; requires an API key with read access to the Unified Trading Account. Returns an empty array if there are none.
Returns the user's Bybit coin balances (UNIFIED account) valued in USD by the exchange: coin symbol, quantity, current price, and market value. No cost basis or P&L. Derivatives (perpetual/futures) positions are not included. Requires a read-only API key with Account/Wallet read permission. Covers only the Bybit Unified account (not Earn, derivatives, or the Funding wallet); for a complete cross-source picture (every configured source and money bucket) use portfolio_snapshot.
Returns open limit orders on Jupiter (Solana) for your configured Solana wallet address(es), via Jupiter's public Trigger v1 API (pair, side, limit price, quantity, filled quantity, status). IMPORTANT: Jupiter's current Limit Order V2 keeps order details private (hidden by Jupiter until execution), so V2 orders are NOT exposed by any public API — an empty result does NOT mean the user has no open orders; advise checking jup.ag directly. Funds locked by open orders still show up as reduced wallet balances in crypto_get_positions. Read-only.
Returns the user's on-chain crypto holdings across the configured wallet addresses (Ethereum & EVM L2s — Arbitrum, Optimism, Base, Polygon — plus Solana, TON, Bitcoin, Litecoin, Dogecoin; the chain of each address is auto-detected, and a single 0x address is read across every EVM network) valued in USD: token symbol, quantity, current price, and market value. No cost basis or P&L (on-chain wallets do not record purchase price). Unpriced/spam tokens are omitted. Also lists any addresses that were unrecognized, on a not-yet-supported chain, or failed to load, so you can tell the user which inputs were skipped. Covers only the configured crypto wallets; for a complete cross-source picture (every configured source and money bucket) use portfolio_snapshot.
Returns current USD prices for arbitrary crypto assets (watchlist). Each coin is a DefiLlama id like 'coingecko:solana', 'coingecko:the-open-network', 'solana:<mint>', or 'ton:<jetton-address>'. Use for assets the user does not hold.
Returns the Interactive Brokers account summary from the configured Flex Query: account id, base currency, cash, invested (equity market value) and total value (NAV). End-of-day reporting data, not a live quote. Requires the Flex Query to include the Net Asset Value and Cash Report sections.
Returns Interactive Brokers dividends from the Flex Query, with gross amount, withholding tax (netted) and net amount per payment, including payments in lieu. End-of-day data. Requires the Flex Query to include the Cash Transactions section.
Returns Interactive Brokers open positions from the Flex Query: symbol, signed quantity, mark price, market value, cost basis and unrealized P&L per holding. End-of-day data, not live. Requires the Flex Query to include the Open Positions section. Covers only Interactive Brokers; for a complete cross-source picture (every configured source and money bucket) use portfolio_snapshot.
Returns Interactive Brokers executed trades from the Flex Query in raw IBKR form: symbol, buySell side, signed quantity, trade price, commission, net cash and realized P&L. End-of-day data. Requires the Flex Query to include the Trades section.
Returns Interactive Brokers cash transactions from the Flex Query: deposits, withdrawals, interest and fees, classified by kind. End-of-day data. Requires the Flex Query to include the Cash Transactions section. Dividends are reported separately by ibkr_get_dividends.
Returns Trading 212 account summary: account id, base currency, free cash, invested capital, total portfolio value, unrealized P&L, and all-time realized P&L when the API provides it. Requires the API key to have the 'Account' scope enabled.
Returns paginated Trading 212 dividend payments with instrument name, quantity held, gross amount per share, and event kind (ORDINARY, BONUS, INTEREST, ...). Default limit 20, max 50. Pass `cursor` from a previous response's nextCursor to fetch the next page.
Lists Trading 212 exchanges with their working schedules — time events for OPEN, CLOSE, BREAK_START/END, PRE_MARKET_OPEN, AFTER_HOURS_OPEN/CLOSE, OVERNIGHT_OPEN. Join instruments to schedules via workingScheduleId from t212_search_instrument. Cached for 10 minutes. Requires the 'Metadata' scope.
Returns currently pending (unfilled) orders on the Trading 212 account. Returns an empty array if there are none.
Returns paginated executed-order history for Trading 212: order details (limit/stop price, quantities, time in force), fill price/quantity, FX rate, taxes/fees, and realized P&L per fill. Use for trade history analysis.
Returns full details of one Trading 212 pie: name, slices (each instrument with target weight, current weight, quantity, invested, current value, unrealized P&L), totals.
Lists all Trading 212 pies (custom portfolios) with id, total invested, current value, unrealized P&L, dividend totals, and progress toward target. Use t212_get_pie for slice-level detail.
Returns all currently open Trading 212 positions with quantity, average price paid, current price, market value (in account currency), and unrealized P&L per holding. Covers only Trading 212; for a complete cross-source picture (every configured source and money bucket) use portfolio_snapshot.
Returns paginated cash transactions (deposits, withdrawals, fees, interest) for the Trading 212 account. Default limit 20, max 50.
Searches the Trading 212 instrument catalog by ticker, short name, or full name (case-insensitive substring). Returns up to `limit` matches with ticker, ISIN, currency, and exchange schedule id. The catalog is cached locally for 6 hours after first call.
No error recovery guidance. Descriptions state prerequisites (e.g., 'Requires Account scope') but do not tell the LLM what to do if the tool fails. If t212_get_account fails with 'Insufficient API scope', should the agent request scope, use a different tool, or ask the user? Descriptions lack actionable error messages.
Descriptions are verbose (many 200+ chars, some >350 chars). While detail is good, descriptions approaching token waste. E.g., bybit_get_account description is ~480 chars. Shorten to 150 - 250 chars: state what the tool does, when to use it, key prerequisites. Reserve verbose explanations for parameter help or dedicated docs.
Tool annotations present (title, openWorldHint) are good, but missing destructiveHint/idempotentHint. All tools are read-only (Risk: READ_ONLY in the spec), so marking them with idempotentHint: true would signal to agents that they are safe to retry without side effects. This is a minor miss but valuable for agent safety.
Pagination support is present but cursor-based only. t212_get_dividends, t212_get_transactions, t212_get_order_history, and crypto_get_prices all use cursor-based pagination, which is correct. However, no tool returns nextCursor or total count fields in their documented schemas. The description mentions 'nextCursor' but without a formal output schema, LLMs cannot reliably extract it.