A Model Context Protocol (MCP) server exposing the eToro Public API route catalog. It refreshes the public API OpenAPI (swagger) document every few minutes, serves the route catalog through MCP tools, and proxies route execution to the eToro Public API via the execute tools.
The MCP endpoint (streamable HTTP, stateless) is served at the root path: POST /
| Tool | Description |
|---|---|
get-tags |
Returns only the catalog's tag groups — a map of tag to route count, the total route count and the untagged route count — the bounded first call for orienting before get-all-routes with a tag. Counts follow the same partner visibility rules as get-all-routes. |
get-all-routes |
Returns all available eToro Public API routes with a short explanation for each. Partner-only routes appear automatically when the MCP connection carries a partner application's x-api-key header. |
get-route-spec |
Returns the full OpenAPI specification (parameters, responses, referenced schemas) for a route by its route id. Partner-only routes resolve on a connection carrying a partner x-api-key header. |
execute-read |
Executes a read against the eToro Public API and relays the response (status, body, rate-limit info): every GET route, plus the read-semantics POST routes (cost previews, eligibility dry-runs, bulk lookups) via an optional raw-JSON-string body — the server verifies the route is read-only before sending. Credentials travel on the MCP connection's own headers (x-user-key + x-api-key, or Authorization: Bearer), never as tool arguments. The x-request-id header is generated automatically and returned. |
execute-write |
Executes a state-changing route (POST/PUT/PATCH/DELETE) with an optional raw-JSON-string body — same connection-header credential rules as execute-read. The returned xRequestId can be passed back to retry the same operation idempotently. |
get-my-portfolio-summary |
Returns the connected user's condensed portfolio in one call — totals, holdings sorted by value (with symbols, names and logos), copied traders (with usernames and avatars) and pending orders — aggregated server-side from several Public API calls, so agents need no discover-and-execute back-and-forth. Read-only and idempotent; optional arguments select the account (real/demo) and toggle per-position rows, pending orders and copied traders. Requires credentials on the MCP connection (same header rules as the execute tools); anonymous calls are challenged with 401 + WWW-Authenticate. All prices and P&L come from one consistent portfolio snapshot; a warnings field flags degraded enrichment while the money numbers remain authoritative. |
get-my-balances |
Returns every account the connected user holds in one call — Trading (including sub-accounts), Cash, Crypto, Options, MoneyFarm, Spaceship and Plaee — by relaying the balance aggregator's response verbatim. The tool derives no figures: it converts nothing, sums nothing and subtotals nothing. Alongside the payload it returns a fieldGuide naming, per account type present, which field carries the spendable figure (equityDetails.available, equityDetails.spendableBalanceInFiat, or none) and which field names that figure's currency, plus notes covering the approved-sub-accounts-only filter and the rule that equityDetails amounts are in each account's own native currency rather than the requested displayCurrency. Optional arguments select the display currency, filter account types, and toggle sub-accounts and zero balances. Read-only and idempotent; requires the etoro-public:money.balance:read scope and credentials on the MCP connection — anonymous calls are challenged with 401 + WWW-Authenticate. |
get-instruments-overview |
Returns a batch overview of 1 to 100 instruments in one call — market identity (symbol, name, logos), live quote (ask/bid/spread), recent performance (previous close plus daily/weekly/monthly change % computed from official closing prices against the live rate) and the connection account's trading-eligibility summary — resolved from symbols and/or instrument ids, or from a free-text query when the exact symbol is unknown. Unknown identifiers are reported in notFoundSymbols/notFoundInstrumentIds; degraded upstream data surfaces as warnings with the matching fields null. Read-only and idempotent. Requires credentials on the MCP connection; anonymous calls are challenged with 401 + WWW-Authenticate. |
get-my-profile-and-scopes |
Returns who is connected in one call. Under profile: the authenticated user's account ids (gcid, and the realCid/demoCid that account-scoped routes take), username, first/middle/last name, playerLevel, gender, language, dateOfBirth, avatarUrl and scopes — the OAuth scopes actually granted to this connection's token or key. Alongside it authChannel (bearer/keys) reports how the connection authenticated. Takes no arguments — the credential on the connection is the input. Read-only and idempotent. Requires credentials on the MCP connection; anonymous calls are challenged with 401 + WWW-Authenticate. |
get-my-watchlists |
Returns the connected user's watchlists in one call (Public API / watchlist BFF V2). Under watchlists: the upstream document relayed verbatim — watchlist metadata, items and pagination meta. Alongside it authChannel (bearer/keys) reports how the connection authenticated. Takes no arguments — the credential on the connection is the input. Read-only and idempotent. Requires credentials on the MCP connection; anonymous calls are challenged with 401 + WWW-Authenticate. |
get-trader-profile-summary |
Returns the public profile of 1 to 100 eToro investors in one call — per trader the profile identity (name, country, avatar, AUM tier, industry/sector tags), performance for the requested ranking period (gain, annualized return, drawdowns, win ratio), risk score (current and max daily/monthly), copier statistics (copiers, copiers gain, copy investment share) and portfolio composition (exposure, leverage mix, top traded instrument, activity) — served from the public rankings surface. Batch-first: one username rides the single-investor lookup, several ride one batch call. Usernames the rankings surface will not answer for come back in notFoundUsernames; the upstream deliberately does not distinguish nonexistent, private and unranked. Read-only and idempotent. Requires credentials on the MCP connection; anonymous calls are challenged with 401 + WWW-Authenticate. |
get-my-positions-and-orders |
Returns the connected user's current positions and pending orders in one call — both directly opened (direct) and held via copy-trading (mirrors, one entry per mirror), kept structurally separate because the upstream API itself never mixes them. Each position carries live unrealized pnl/pnlPercent and its stop-loss/take-profit; each order carries its status and requested stop-loss/take-profit, plus an optional richer per-order detail object (fills, numeric status/error code) when includeOrderDetail is set, capped at 10 orders. All money amounts are in accountCurrency. Read-only and idempotent; optional arguments select the account (real/demo) and toggle order detail. Requires credentials on the MCP connection; anonymous calls are challenged with 401 + WWW-Authenticate. |
get-my-trading-history |
Returns the connected user's closed trades (trading history) in one call, paginated — each trade carries symbol/name, direction, leverage, open/close time and rate, units, investment, fees and netProfit, the REALIZED closed profit/loss (distinct from get-my-positions-and-orders' unrealized pnl). Stop-loss/take-profit are always present as numbers on this route — never null — so a near-zero value can mean "not really set". Optional arguments select the account (real/demo), the start date (minDate, defaults to 90 days ago) and the page (page/pageSize, default 50 capped at 200); the upstream API has no total count, so hasMore is a heuristic. Read-only and idempotent. Requires credentials on the MCP connection; anonymous calls are challenged with 401 + WWW-Authenticate. |
prepare-trade |
Validates a proposed open order against live eToro Public API data — the user's instrument eligibility (direction, leverage, order type, size and stop-loss/take-profit bounds), a live ask/bid quote, the full cost breakdown and whether the account's available balance covers amount plus costs — and returns a confirmation preview (market identity and logos, direction, sizing, leverage, estimated units, quote, costs, balance check, eligibility summary) together with a short-lived signed confirmation token when every hard check passes. Read-only and idempotent — nothing is placed; a hard failure returns verdict rejected with reasons and no token, while soft findings surface as warnings. Requires credentials on the MCP connection; anonymous calls are challenged with 401 + WWW-Authenticate. The token is the only way to place the trade — see place-trade. |
place-trade |
Executes the exact order sealed in a prepare-trade token — the single argument is the token itself, so what the user approved is what executes. The signed token is verified statelessly (any pod or region; bound to the connection's credentials — an expired, tampered or wrong-connection token is rejected before anything is sent), the prepared order is placed with the idempotency key sealed in the token, and the order is then polled server-side to a final outcome (executed, partiallyFilled, rejected, pending, …) with fills, orderId/referenceId and follow-up guidance — so agents never poll orders themselves. Retrying the same token after an unknown outcome is safe: placement is idempotent by construction. |
prepare-close |
Confirms a position belongs to the connected account and returns a confirmation preview (market identity, direction, leverage, units, open/current rate, invested amount, unrealized P&L) together with a short-lived signed confirmation token when the position is found. Optional unitsToDeduct requests a partial close (validated against the position's own units and the instrument's partial-close eligibility); omitted, the close is full. Copied (copy-trading / mirror) positions can only be closed in full — a partial close of one is verdict rejected with no token. Read-only and idempotent — nothing is closed; an unknown or not-owned position returns verdict rejected with no token. Requires credentials on the MCP connection; anonymous calls are challenged with 401 + WWW-Authenticate. The token is the only way to place the close — see place-close. |
place-close |
Executes the exact close sealed in a prepare-close token — the single argument is the token itself. The signed token is verified statelessly and MUST carry the close-specific token kind (a prepare-trade token is rejected the same way a tampered token is), the close request is submitted, and the close order is then polled server-side to a final outcome (executed, partiallyFilled, rejected, cancelled, expired, pending) with positionId, orderId, unitsClosed and a decoded hint for known upstream error codes (already executed, already closed, already pending close, not owned, remaining amount too low). A close request that gets no HTTP response at all answers unknown rather than a false rejected — the same token is safe to retry. |
{
"mcpServers": {
"etoro-public-api": {
"url": "<service-url>/"
}
}
}
Download a ready-to-use agent skill, pre-configured with this environment's MCP and eToro Public API URLs: Download SKILL.md.
Install it by placing the file at:
.claude/skills/etoro-public-api-operations/SKILL.md~/.cursor/skills/etoro-public-api-operations/SKILL.md