etoro-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@etoro-mcp show my portfolio"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
etoro-mcp
MCP server for the eToro public API: market data, balances, portfolio, trade history, watchlists, alerts, investor rankings, user statistics, social feeds, and — behind explicit opt-in gates — trading, watchlist/alert mutations, and social posting. Coverage is organised into toolsets; only the toolsets you select are registered, and write tools are not registered at all unless their gate is enabled — a client connected to the default configuration cannot see or call them.
Features
Read-first by design — 62 read tools across eleven of the twelve toolsets (the
socialtoolset is write-only); the 43 write tools exist only when their gate is set — 5 trading tools behindETORO_MCP_ENABLE_TRADING, the other 38 (watchlist, alert, social, and notification mutations) behindETORO_MCP_ENABLE_WRITES.Demo environment by default — trading tools call the demo endpoint group unless
ETORO_ENV=realis set.Toolset selection — register only what you need via
ETORO_MCP_TOOLSETS; unknown names fail startup rather than serving a partial tool set.Trimmed responses — tools return the fields an investor acts on (prices, units, P&L, timestamps), not raw API dumps; list tools are bounded by a
limitparameter or by explicit range parameters (min_date/max_date/count) on the time-series tools.Credentials stay in the environment — keys travel only in the
x-api-key/x-user-keyheaders, and error messages never echo header or credential values.Rate-limit aware — HTTP 429 responses are retried once, honouring
Retry-After, re-sending the samex-request-idso a retried order cannot fill twice.
Related MCP server: eToro MCP Server
Toolsets
Select toolsets with ETORO_MCP_TOOLSETS (comma-separated; all selects every toolset).
Without it, the trading core is registered:
Toolset | Default | Covers |
| ✓ | Instrument search and details, candles, rates, closing prices, exchanges, instrument types, stock industries |
| ✓ | Profile, balances (aggregated, by account type, history), cash transactions |
| ✓ | Portfolio, P&L, order status, eligibility and cost estimates; gated order/position writes |
| ✓ | Closed-trade history |
| ✓ | Own/public/curated watchlists and recommendations; gated watchlist mutations |
| ✓ | Price alerts; gated alert mutations |
| Investor rankings, presets, tags, sector/industry summaries | |
| User search, profiles, portfolios, performance and copier statistics | |
| News, following, for-you, instrument, and user feeds; posts and comments | |
| Gated posting, comments, replies, reactions, polls, and media upload | |
| eToro Club dashboard | |
| Notifications; gated mark-read |
Tools
Read tools (registered whenever their toolset is selected)
Toolset | Tool | Description |
|
| Search instruments by ticker symbol and return candidate matches (contains-matching, so verify the symbol) |
|
| Display data for instruments by id: name, symbol, type, exchange |
|
| OHLCV candles for one instrument (nine intervals, up to 1000 bars) |
|
| Latest official closing prices per instrument |
|
| Real-time bid/ask quotes for instruments |
|
| Exchanges (id and description) for resolving |
|
| Instrument types (stocks, crypto, ETFs, ...) by id |
|
| Stock industries (id and name) for resolving |
|
| The authenticated user's identity and the scopes their keys carry |
|
| Current balances aggregated across the user's accounts |
|
| Current balances for every account of one account type |
|
| Current balance of one specific account |
|
| Daily balance snapshots over a date range |
|
| Transactions of a cash account, newest pages first |
|
| Aggregated portfolio: account totals plus one aggregate per instrument |
|
| Position-level snapshot: open positions and pending orders |
|
| Portfolio snapshot with unrealized P&L per position |
|
| Look up an order's status by order id or reference id |
|
| Look up a close order's status by its order id |
|
| Per-instrument trading rules: leverage, sizing mode, SL/TP bounds |
|
| Estimate the costs of a hypothetical open order without placing it |
|
| Closed trades since a given date |
|
| The authenticated user's watchlists with their items |
|
| A single watchlist owned by the authenticated user, by id |
|
| Items of the authenticated user's default watchlist |
|
| Another user's public watchlists by their numeric user id |
|
| eToro's curated investment lists available to the user |
|
| Personalized market recommendations for the authenticated user |
|
| The active price alerts on the account |
|
| Names of all publicly available ranking presets |
|
| Investor ranking rows for a named preset |
|
| A filtered, sorted page of investor ranking rows |
|
| The full ranking row for a single investor |
|
| Ranking rows for several investors in one call |
|
| The catalog of ranking tags with resolved names |
|
| The ranking universe aggregated by sector or industry |
|
| Search public investors with performance and risk filters |
|
| Public profile and account summary for one or more users |
|
| A user's live public portfolio: open positions and copy trades |
|
| A user's full monthly and yearly gain history |
|
| A user's day-by-day or aggregated gain over a date range |
|
| A user's trading statistics for a period (copy-trading due diligence) |
|
| An investor's gain time-series at daily, monthly, or yearly resolution |
|
| A portfolio's daily asset-allocation breakdown over time |
|
| A portfolio's daily directional market exposure per instrument |
|
| An investor's live copier count and assets-under-management tier |
|
| Anonymised info about the people copying your portfolio |
|
| Search trader portfolios or Smart Portfolios by free text |
|
| A user's top assets ranked by impressions-based score |
|
| The eToro news feed (editorial and market-news posts) |
|
| Posts from users the authenticated user follows |
|
| The personalised For You feed for the authenticated user |
|
| The discussion feed for one instrument (market) |
|
| The posts published by one user |
|
| The posts the authenticated user has saved |
|
| The posts a user has pinned to their profile |
|
| A single post by its UUID, with an inline comments preview |
|
| The top-level comments on a post |
|
| The replies nested under one comment |
|
| Who shared a post (plain reshares and quote shares) |
|
| The eToro Club dashboard for the authenticated user |
|
| The account's in-app notifications, newest data first |
Trading write tools (registered only when ETORO_MCP_ENABLE_TRADING is set)
Toolset | Tool | Description |
|
| Place an order to open a position — not idempotent: every call places a new order |
|
| Cancel a pending (not yet executed) order |
|
| Close an open position, fully or partially, at market |
|
| Cancel a pending close order before it executes |
|
| Edit an open position's stop-loss and/or take-profit |
Other write tools (registered only when ETORO_MCP_ENABLE_WRITES is set)
Toolset | Tool | Description |
|
| Create a new watchlist |
|
| Rename a watchlist |
|
| Delete a watchlist |
|
| Add items to a watchlist |
|
| Remove items from a watchlist |
|
| Reorder items within a watchlist |
|
| Set a watchlist as the selected default |
|
| Change a watchlist's display position |
|
| Create a price alert on an instrument |
|
| Change the target price of an existing price alert |
|
| Permanently delete a price alert |
|
| Mark all in-app notifications as read |
|
| Create a discussion post on the authenticated user's feed |
|
| Create a poll post with 2 to 4 answer options |
|
| Edit the authenticated user's own post in-place |
|
| Soft-delete the authenticated user's own post |
|
| Pin one of the authenticated user's own posts to their profile |
|
| Remove the authenticated user's pin from a post |
|
| Create a top-level comment on a post |
|
| Edit the authenticated user's own comment in-place |
|
| Soft-delete the authenticated user's own comment |
|
| Create a reply nested under an existing comment |
|
| Edit the authenticated user's own reply in-place |
|
| Soft-delete the authenticated user's own reply |
|
| Share an existing post, as a plain reshare or a quote share |
|
| Upload a JPEG or PNG image (max 8 MB) for use as an attachment; requires |
|
| Like a post |
|
| Remove a like from a post |
|
| Like a comment on a post |
|
| Remove a like from a comment |
|
| Like a reply (a nested answer to a comment) |
|
| Remove a like from a reply |
|
| Bookmark a post |
|
| Remove a post from the saved bookmarks |
|
| Subscribe to notifications on a post |
|
| Unsubscribe from notifications on a post |
|
| Cast a vote on a poll option |
|
| Remove a vote from a poll option |
Configuration
All configuration comes from environment variables — no config files, no flags carrying secrets.
Variable | Default | Purpose |
| — (required) | eToro API key, sent as the |
| — (required) | eToro user key, sent as the |
|
|
|
| trading core (see table above) | Comma-separated toolset names; |
| off |
|
| off |
|
| — (unset) | The only directory |
Getting started
Run straight from the repository with uv:
uvx --from git+https://github.com/florinel-chis/etoro-mcp etoro-mcpThe server speaks stdio by default; pass --transport http --host 127.0.0.1 --port 8000 to serve
streamable HTTP at /mcp instead.
Warning: the HTTP endpoint has no authentication — anyone who can reach the port can call every registered tool with your API keys' privileges. The server therefore refuses to bind a non-loopback
--hostunless--allow-remoteis also passed; only use that flag behind an authenticated reverse proxy or an otherwise-restricted network (such as the Docker port-mapping below).
MCP client configuration
Add the server to your MCP client's configuration (the exact file location depends on the client):
{
"mcpServers": {
"etoro": {
"command": "uvx",
"args": ["--from", "git+https://github.com/florinel-chis/etoro-mcp", "etoro-mcp"],
"env": {
"ETORO_API_KEY": "your-api-key",
"ETORO_USER_KEY": "your-user-key",
"ETORO_ENV": "demo"
}
}
}
}Or run the Docker image (build it first, see below):
{
"mcpServers": {
"etoro": {
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "ETORO_API_KEY", "-e", "ETORO_USER_KEY", "-e", "ETORO_ENV", "etoro-mcp"],
"env": {
"ETORO_API_KEY": "your-api-key",
"ETORO_USER_KEY": "your-user-key",
"ETORO_ENV": "demo"
}
}
}
}Docker
docker build -t etoro-mcp .
# stdio (for MCP client configs)
docker run -i --rm -e ETORO_API_KEY -e ETORO_USER_KEY etoro-mcp
# streamable HTTP at http://127.0.0.1:8000/mcp
# (-p 127.0.0.1:8000:8000 keeps the unauthenticated endpoint off external interfaces;
# --host 0.0.0.0 refers to interfaces inside the container and is required for the
# port mapping to work, hence --allow-remote — the host-side bind stays loopback-only)
docker run --rm -p 127.0.0.1:8000:8000 -e ETORO_API_KEY -e ETORO_USER_KEY \
etoro-mcp --transport http --host 0.0.0.0 --port 8000 --allow-remoteSafety
Trading tools call the demo endpoint group unless
ETORO_ENV=realis set. Keys are environment-bound, so a demo key againstreal(or vice versa) fails at the API rather than trading the wrong account.Write tools are hidden behind two independent gates —
ETORO_MCP_ENABLE_TRADINGfor order/position writes andETORO_MCP_ENABLE_WRITESfor everything else (watchlists, alerts, notifications, social). Gated tools are never registered, not merely rejected, so MCP clients cannot discover or call them.The HTTP transport is unauthenticated: anyone who can reach the port can call every registered tool — read balances and positions always, and place or close orders when trading is enabled — using your API keys' privileges. The server refuses non-loopback binds unless
--allow-remoteis passed; only use that flag behind an authenticated proxy or an otherwise-restricted network (the stdio transport has no such exposure).upload_mediareads local JPEG/PNG files and returns a public CDN URL for them — an extra privilege class beyond the API keys themselves. It is therefore triple-gated: thesocialtoolset,ETORO_MCP_ENABLE_WRITES, andETORO_MCP_UPLOAD_DIRmust all be set, and it reads only inside that directory (paths and symlinks resolving outside it are rejected, file content must actually be JPEG/PNG, and the 8 MB limit is checked before the file is read).create_orderis not idempotent across calls: each call mints a freshx-request-id, which is the order's idempotency key, so calling it twice places two orders. (The 429 retry re-sends the same id, so a rate-limited retry cannot double-fill.) Poll fill status withget_orderbefore treating an order as filled — an accepted order can still be rejected.Candle history is capped at roughly 1000 bars per interval with no way to page further back; use a coarser interval (e.g.
OneWeek) for deeper history.The API enforces per-group rate quotas (order execution 20 requests/60 s; market data 120/60 s; portfolio and most other groups 60/60 s; eligibility and cost estimates 20/60 s each). Each tool's description names its quota; 429s are retried once, honouring
Retry-After.Trading leveraged products is risky. Use at your own risk, and test everything against a demo account first.
Development
uv sync
uv run pytest
uv run ruff check .Tests are hermetic: all HTTP is mocked with respx and the server is exercised through the
in-memory FastMCP client. No credentials or network access are needed to run them. A manual,
read-only smoke check against a real demo account lives at scripts/smoke.py.
License
MIT — see LICENSE.
Available Tools
29 toolscheck_trading_eligibilityARead-only
Per-instrument trading rules: leverage, sizing mode, SL/TP bounds.
Provide instrument_ids and/or symbols (at least one, at most 100 combined). For each instrument returns the minimum position exposure (USD), max units per order, whether opening/closing/partial closes/ market-if-touched orders/trailing stop-loss are allowed, whether units are whole or fractional, whether sizing must be by units, by amount, or either, and per settlement type and direction the valid leverage values, minimum position amount (USD), and stop-loss/take-profit percentage bounds. Call before create_order to pick valid parameters. Rate limit: dedicated 20 requests/60s quota.
Inputs: symbols, instrument_ids. Returns: object
get_aggregated_balancesARead-only
Get current balances aggregated across the user's accounts.
Calls GET /api/v1/balances. Returns totalBalance (in display_currency) plus one entry per account with its native-currency balance, the converted displayBalance, and the exchangeRate used. Account types: Trading, Cash, Options, Crypto, MoneyFarm, Spaceship. Amounts are numbers in the stated currency. Rate limit: 60 requests per 60 seconds (default shared quota).
Inputs: account_types, display_currency, include_zero_balances, include_equity_details. Returns: object
get_balanceARead-only
Get the current balance of one specific account.
Calls GET /api/v1/balances/{accountType}/{accountId}. Account types: Trading, Cash, Options, Crypto, MoneyFarm, Spaceship. Returns the account's balance in its native currency plus the displayBalance converted into display_currency. With include_equity_details, Trading accounts also report available buying power, frozen cash, current PnL, and used margin. Rate limit: 60 requests per 60 seconds (default shared quota).
Inputs: account_id (required), account_type (required), display_currency, include_zero_balances, +1 more. Returns: object
get_balance_historyARead-only
Get daily balance snapshots over a date range.
Calls GET /api/v1/balances/history (or the {accountType} / {accountType}/{accountId} variant when narrowed). Dates are YYYY-MM-DD; the default range is the last 30 days, history covers at most the last 12 months, and a single range spans at most 365 days — the API answers 404 when no data exists for the range. Each snapshot carries total cash, invested amount, PnL, and balance, both in native currencies and converted into display_currency. Rate limit: 60 requests per 60 seconds (default shared quota).
Inputs: to_date, from_date, account_id, account_type, +1 more. Returns: object
get_balances_by_typeARead-only
Get current balances for every account of one account type.
Calls GET /api/v1/balances/{accountType}. Account types: Trading, Cash, Options, Crypto, MoneyFarm, Spaceship. Returns totalBalance (in display_currency) and per-account balances in their native currency alongside the converted displayBalance. Rate limit: 60 requests per 60 seconds (default shared quota).
Inputs: account_type (required), account_ids, display_currency, include_zero_balances, +1 more. Returns: object
get_candlesARead-only
Get OHLCV candles for one instrument.
Returns {"instrumentId": int, "interval": str, "candles": [{"time": ISO-8601 period start, "open": float, "high": float, "low": float, "close": float, "volume": float}]}. Prices are in the instrument's quote currency; the newest bar can be the still-forming session.
History depth is capped at about 1000 bars per interval — there is no way to page further back in time (no from/to parameters exist), so at OneDay one request covers roughly four years; use a coarser interval such as OneWeek for deeper history. 'direction' only changes ordering: asc and desc return the same most-recent window, oldest-first vs newest-first. An unknown instrument id yields no candle data and this tool raises an error rather than returning an empty series.
Rate limit: shares the market-data pool of 120 requests per 60 seconds.
Inputs: instrument_id (required), count, interval, direction. Returns: object
get_close_order_infoARead-only
Look up a close order's status by its order id.
Same status codes as get_order (1 Received … 10 RejectedPartiallyFilled); positionsToClose and positionExecutions show which positions closed and at what price. Returns HTTP 404 if the close order does not exist. Rate limit: shares a 60 requests/60s pool with get_order.
Inputs: order_id (required). Returns: object
get_closing_pricesARead-only
Get the latest official closing prices per instrument.
The API returns closing prices for every instrument in one response; this tool filters to 'instrument_ids' when given and truncates to 'limit'. Returns {"results": [{"instrumentId": int, "officialClosingPrice": float, "daily"/"weekly"/"monthly": {"price": float, "date": ISO-8601}}]} — daily is the previous trading day's close, weekly the previous week's, monthly the previous month's. A price of -1 with date 0001-01-01 means no data for that period.
Rate limit: shares the market-data pool of 120 requests per 60 seconds.
Inputs: limit, instrument_ids. Returns: object
get_curated_listsARead-only
Get eToro's curated investment lists available to the user.
Each list carries uuid, name, description, and the instrument IDs it contains (resolve them via the market-data tools). Dedicated quota of 60 requests per 60 seconds.
Inputs: limit. Returns: object
get_default_watchlistARead-only
Get the items of the authenticated user's default watchlist.
Returns items with itemId (instrument or person ID), itemType ('Instrument' or 'Person'), itemRank (position in the list), symbol and displayName when market metadata is included, and itemAddedDate (ISO 8601). Shares the watchlist read quota of 60 requests per 60 seconds.
Inputs: limit, items_per_page. Returns: object
get_instrument_detailsARead-only
Get display data for instruments by id: name, symbol, type, exchange.
Returns {"results": [{"instrumentId": int, "displayName": str, "symbol": str, "instrumentTypeId": int, "exchangeId": int, "stocksIndustryId": int, "priceSource": str, "isInternalInstrument": bool}]}. isInternalInstrument true means the instrument is restricted from public trading. Use search_instruments to resolve a ticker to an instrumentId first.
Rate limit: shares the market-data pool of 120 requests per 60 seconds.
Inputs: instrument_ids (required). Returns: object
get_market_recommendationsARead-only
Get personalized market recommendations for the authenticated user.
Returns responseType and instrumentIds — the recommended instrument IDs, resolvable via the market-data tools. Dedicated quota of 60 requests per 60 seconds.
Inputs: limit. Returns: object
get_orderARead-only
Look up an order's status by order_id or reference_id (exactly one).
Status ids: 1 Received, 2 Placed, 3 Filled, 4 Rejected, 5 PartiallyFilled, 6 PendingCancel, 7 Canceled, 8 Expired, 9 CanceledPartiallyFilled, 10 RejectedPartiallyFilled. A filled order lists its positions under positionExecutions (positionId, state, remaining units, execution price and fees). Rates are absolute instrument prices; timestamps ISO 8601. Rate limit: shares a 60 requests/60s pool with get_close_order_info.
Inputs: order_id, reference_id. Returns: object
get_pnlARead-only
Account P&L: portfolio snapshot with unrealized P&L per position.
Returns credit (available trading balance, USD), bonusCredit, the account-level unrealizedPnl (sum across open positions, account currency), and open positions each carrying an unrealizedPnl figure in the account currency, plus mirror summaries with closedPositionsNetProfit. Total P&L = sum of position unrealizedPnl (own and mirror positions) + sum of mirror closedPositionsNetProfit. Rate limit: shares a 60 requests/60s pool with get_portfolio and get_portfolio_breakdown.
Inputs: limit. Returns: object
get_portfolioARead-only
Aggregated portfolio: account totals plus one aggregate per instrument.
Account totals are in the account currency (usually USD): accountAvailableCash, accountFrozenCash, accountCurrentPnl, accountTotalUsedMargin, accountBalance, and accountTotalValue (= available cash + used margin + current P&L). Each instrument aggregate carries net units (positive = long, negative = short), average open rate and leverage, margin, exposure, and unrealized return (accountCurrencyReturn) in the account currency. Filters narrow the instrument aggregates only — account totals ignore them. Rate limit: shares a 60 requests/60s pool with get_portfolio_breakdown and get_pnl.
Inputs: limit, mirror_ids, instrument_ids, conversion_mode. Returns: object
get_portfolio_breakdownARead-only
Position-level portfolio snapshot: open positions and pending orders.
Returns credit (available trading balance, USD), bonusCredit, open positions (positionID, instrumentID, isBuy — true long / false short, leverage, amount = invested margin in USD, units, openRate, openDateTime ISO 8601, stop-loss/take-profit rates as absolute prices, mirrorID — 0 = manual position, non-zero = copy trading), pending market-if-touched orders (pendingOrders), pending market opens (ordersForOpen), and pending closes (ordersForClose), plus copy-trading mirror summaries. Cheaper than get_pnl — no unrealized P&L fields. Rate limit: shares a 60 requests/60s pool with get_portfolio and get_pnl.
Inputs: limit. Returns: object
get_profileARead-only
Get the authenticated user's identity and the scopes their keys carry.
Calls GET /api/v1/me. Returns gcid (global customer id), realCid and demoCid (real/demo account customer ids), username, first/last name when set, playerLevel (1 Bronze, 2 Platinum, 3 Gold, 4 Internal, 5 Silver, 6 PlatinumPlus, 7 Diamond) with its name, and the OAuth scopes granted to the credentials — useful to verify keys and to see which endpoint groups are accessible. Rate limit: 60 requests per 60 seconds (default shared quota).
Inputs: no named parameters. Returns: object
get_public_watchlistsARead-only
List another user's public watchlists by their numeric user ID.
Returns the same shape as list_watchlists: watchlistId, name, watchlistType, totalItems, watchlistRank, and up to items_per_watchlist items each. Shares the watchlist read quota of 60 requests per 60 seconds.
Inputs: user_id (required), limit, items_per_watchlist. Returns: object
get_ratesARead-only
Get real-time bid/ask quotes for instruments.
Recommended before placing an order. Returns {"results": [{"instrumentId": int, "bid": float (sell price), "ask": float (buy price), "lastExecution": float, "conversionRateBid": float, "conversionRateAsk": float (instrument currency to USD), "date": ISO-8601 quote timestamp}]}.
Rate limit: shares the market-data pool of 120 requests per 60 seconds.
Inputs: instrument_ids (required). Returns: object
get_trading_cost_estimateARead-only
Estimate the costs of a hypothetical open order without placing it.
Takes the same arguments as create_order (exactly one of symbol/instrument_id, exactly one of amount/units/contracts) and returns the cost breakdown: one entry per cost type (markup, marketSpread, transactionFee, overnightFee, overWeekendFee, sdrt) with an amount and currency, plus the quote timestamp (ISO 8601). Rate limit: dedicated 20 requests/60s quota.
Inputs: transaction (required), units, amount, symbol, +7 more. Returns: object
get_watchlistARead-only
Get a single watchlist owned by the authenticated user, by ID.
Items are paginated with page_number (zero-based) and items_per_page. Returns the watchlist's metadata plus its items: itemId, itemType ('Instrument' or 'Person'), itemRank, symbol, and itemAddedDate (ISO 8601). Shares the watchlist read quota of 60 requests per 60 seconds.
Inputs: watchlist_id (required), page_number, items_per_page. Returns: object
list_cash_transactionsARead-only
List transactions of a cash account, newest pages first.
Calls GET /api/v1/money/accounts/cash/{accountId}/transactions. Paginated by cursor: pass pagination.nextPageToken from one call as page_token to fetch the next page; nextPageToken null (or hasNext false) means the last page. Amounts are decimal strings in ISO 4217 currencies; postedAt is an ISO 8601 timestamp. transactionType is one of card, internalTransfer, bankTransfer, balanceAdjustment; direction is debit or credit; status is one of failed, authorized, settled, rejected, returned, expired, unknown. Rate limit: 60 requests per 60 seconds (default shared quota).
Inputs: account_id (required), limit, page_token. Returns: object
list_exchangesARead-only
List exchanges (id and description) for resolving exchangeId values.
Returns {"results": [{"exchangeId": int, "description": str}]}.
Rate limit: shares the market-data pool of 120 requests per 60 seconds.
Inputs: limit, exchange_ids. Returns: object
list_instrument_typesARead-only
List instrument types (stocks, crypto, ETFs, ...) by id.
Resolves instrumentTypeId values returned by other market-data tools. Returns {"results": [{"instrumentTypeId": int, "description": str}]}.
Rate limit: shares the market-data pool of 120 requests per 60 seconds.
Inputs: limit, instrument_type_ids. Returns: object
list_price_alertsARead-only
List the active price alerts on the account.
Returns up to limit alerts, each with its alertId (UUID),
instrumentId, symbol (e.g. AAPL), targetPrice (trigger
level in the instrument's quote currency), currentPrice (market
bid when the alert was created or last updated), and ISO 8601 UTC
createdAt/updatedAt timestamps. Quota: 60 requests per 60
seconds (shared default pool).
Inputs: limit. Returns: object
list_stock_industriesARead-only
List stock industries (id and name) for resolving stocksIndustryId values.
Returns {"results": [{"industryId": int, "name": str}]}.
Rate limit: shares the market-data pool of 120 requests per 60 seconds.
Inputs: limit, industry_ids. Returns: object
list_trading_historyARead-only
List closed trades since a given date.
Returns trades closed on or after min_date for the configured
environment (demo or real account). Each trade includes position and
order ids, instrument id, direction (isBuy), leverage, units,
invested amount and fees in the account currency, open/close rates in
the instrument's quote currency, and ISO 8601 open/close timestamps.
Paginate with page and limit. Quota: 60 requests per 60
seconds (shared default pool).
Inputs: min_date (required), page, limit. Returns: object
list_watchlistsARead-only
List the authenticated user's watchlists with their items.
Each watchlist carries watchlistId, name, watchlistType (one of Static, Dynamic, RecentlyInvested, Default), totalItems, isDefault, isUserSelectedDefault, watchlistRank (display order), and up to items_per_watchlist items with itemId (instrument or person ID), itemType ('Instrument' or 'Person'), itemRank, and itemAddedDate (ISO 8601). Shares the watchlist read quota of 60 requests per 60 seconds.
Inputs: limit, include_builtin, items_per_watchlist. Returns: object
search_instrumentsARead-only
Search instruments by ticker symbol and return candidate matches.
Matching is contains/prefix, NOT exact: searching 'AAPL' also returns variants such as 'AAPL.24-7' and 'AAPL.EUR'. Always verify that the candidate's internalSymbolFull exactly equals the symbol you want before using its instrumentId. Instrument ids are immutable (they survive rebrands and ticker changes), so they are safe to cache.
Returns {"totalItems": int, "results": [{"instrumentId": int, "internalSymbolFull": str, "displayName": str, "isCurrentlyTradable": bool}]}.
Rate limit: shares the market-data pool of 120 requests per 60 seconds.
Inputs: query (required), limit. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 29 tools
Each tool targets a distinct resource or action, with clear descriptions. Even similar tools like get_balance, get_aggregated_balances, and get_balances_by_type are well-differentiated by scope. No overlapping purposes.
All tool names follow a consistent verb_noun pattern (e.g., get_balance, list_watchlists, search_instruments), using lowercase with underscores. No mixing of conventions.
29 tools is on the high side for a single server, exceeding the 'heavy' threshold of 16-25. While each tool serves a specific endpoint, the count may overwhelm an agent. However, the domain is complex enough to justify most tools.
Several critical operations are missing, such as create_order, cancel_order, create/delete/update watchlists, and manage price alerts. The server provides many read operations but lacks corresponding write/delete actions, leading to dead ends for common trading workflows.
Maintenance
Related MCP Connectors
Trading MCP server for AI agents, with live market data, account reads and controlled execution.
Hosted MCP server for MT4 and MT5: read accounts, prices and candles, and place or close orders.
MCP server for Financial Modeling Prep API with 250+ financial data tools
MCP server with quote and live cryptocurrency price tools, local and cloud-deployed transports.
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP server for the Trading 212 API. Provides 28 tools for portfolio management, trading, pies, dividends, market data, and analytics.28125 PyPI10MIT
- FlicenseAqualityDmaintenanceA security-hardened MCP server that wraps the eToro public API, enabling AI assistants to trade, access market data, manage portfolios, and interact with social feeds via 34 tools.6-
- AlicenseAqualityDmaintenanceMCP server connecting AI assistants to eToro for portfolio analysis, market research, and trading, with 35 tools.35105 npm1MIT
- AlicenseAqualityDmaintenanceMCP server for the tastytrade brokerage API, providing tools for account management, market data, and order execution.18MIT