Skip to main content
Glama
slemos

eToro MCP Server

by slemos

eToro MCP Server (unofficial)

Talk to your eToro account from Claude. Ask about your portfolio in plain language, check prices and costs, and — only if you choose to turn it on — place orders that you approve one by one.

tests security OpenSSF Scorecard license: MIT node MCP

Disclaimer. This project is not affiliated with, endorsed by or supported by eToro. "eToro" is a trademark of its owner. Nothing here is financial advice. Trading — especially with leverage or CFDs — can lose money, and software that lets an AI act on a brokerage account can lose it faster. Read the safety model, start on the demo environment, and check eToro's API terms before automating anything.

What it does

MCP is the standard way to give Claude tools. This server gives Claude a set of tools that talk to the eToro Public API with your own keys, so instead of opening the app and clicking around you can just ask:

You say

What happens

"How is my portfolio doing? What are my biggest positions?"

Claude reads your positions, balances and profit and loss, and summarises them.

"How are the traders I copy performing?"

One compact summary per copied trader, with their positions available on request.

"What would it cost to buy 50 dollars of AAPL, and can my account even do that?"

Live price, the settlement types and leverage your account is offered, and an estimate of the fees.

"What if I had bought 1,000 dollars of AAPL in January with a stop at 170?" / "How would investing 100 dollars every two weeks have done over two years?"

A simulation on eToro's past price candles (etoro_simulate_position, etoro_backtest): entry and exit, why it ended, the result, the worst moment. It places nothing and prepares nothing, and it is not a forecast or advice.

"Find popular investors with moderate risk who trade mostly tech, and show me one's stats."

Searches investors by performance, risk and what they hold (etoro_search_investors), then reads one's public statistics, copiers and history (etoro_get_investor). Public data only, past performance is not a forecast.

"How did my balance change over the last three months? What went through my cash account?"

etoro_get_balance_history and etoro_get_cash_transactions.

"Show my closed trades since January."

Your trade history, filtered by date.

"Find the Apple instrument and tell me how it did over the last year."

Searches by name, then reads the price candles and summarises them (first open, last close, high, low, change).

"Prepare a purchase of 20 dollars of AAPL on my demo account."

Claude prepares the order (instrument, size, costs, environment) and your browser opens an approval page with the exact action. You press Execute there; Claude cannot. Then it follows the order.

"Prepare closing that position." / "Add a stop loss at 780 to it." / "Prepare cancelling that pending order."

Same: Claude proposes, you execute on the page.

"Tell me when AAPL reaches 350." / "Move that alert to 340." / "Delete the alert."

Price alerts: Claude lists them and prepares creating, changing or deleting one; you execute on the page. An alert only notifies you: it places no order and moves no money.

"Add these instruments to my Tech watchlist."

Creates and edits watchlists (no money involved).

24 read tools, 12 prepare-only write tools and one gated transfer tool; see Tools.

Safe by default. It starts read-only and on eToro's demo environment. The tools that can move money are not even registered until you switch them on, real money needs a second switch, and Claude can only prepare an action: you execute it yourself on a local approval page, never Claude. Size caps, a rate limit and an audit log apply on top. Your keys stay on your machine (OS keychain, password manager or a protected file) and are never shown to Claude. Details in the safety model.

Related MCP server: eToro Portfolio Connector

TL;DR: install in two minutes

You need an eToro API key pair; a Read key on the Demo environment is enough to start (how to get one).

Claude Desktop

  1. Download etoro-mcp-server-<version>.mcpb from the latest release (or build it: npm ci && npm run mcpb:pack).

  2. Double-click it, or drag it into Settings → Extensions. Claude Desktop shows a red warning that the extension gets access to your computer and that Anthropic has not verified the developer: that is expected for an independent project, and you can check where the file came from.

  3. Paste your API key and user key, leave Use the REAL environment and Enable write tools off. The keys go to your OS keychain.

  4. Start a chat and ask: "Check my eToro connection." Then try "How is my portfolio doing?"

Claude Code

git clone https://github.com/slemos/etoro-mcp-server.git && cd etoro-mcp-server && npm ci && npm run build
claude mcp add etoro -- node "$(pwd)/dist/index.js"   # reads ETORO_API_KEY / ETORO_USER_KEY from your environment

Other MCP clients and safer ways to hand over the keys (keychain, password manager, protected file) are in Install and Securing your setup.

Why you can trust it

An AI that can touch a brokerage account deserves more scrutiny than most code, so the project treats security as a feature, and checks it automatically on every change:

Check

What it proves

Runs

Tests

Logic, the prepare → you-execute flow, caps and blocked paths, against a mocked eToro API and an in-memory MCP client

every push and pull request

SAST (CodeQL, security-extended)

No known vulnerability patterns in the TypeScript source

every push and pull request, weekly

Dependency audit (npm audit, registry signatures, Dependabot)

The few production dependencies have no known high-severity advisories

same, plus weekly

Secret scan (Gitleaks)

No keys or tokens in the repository or its history

same

Dynamic security checks (npm run security:check)

The built server, run as a real process with the network cut off, exposes only the tools each permission switch allows, refuses a non-eToro base URL, rejects hostile arguments before any request, cannot be made to call another API path, and never leaks the keys into results, logs or the audit trail

every CI run and release

OpenSSF Scorecard

An independent score of the repository's security practices (protected main, pinned actions, least-privilege tokens, static analysis, signed releases, ...), published at scorecard.dev

on every push to main and weekly

Protected main

Nobody, the owner included, can push to main directly or rewrite its history: every change goes through a pull request whose CI and security checks must pass

always

Build provenance + checksums + SBOM

A release file was built by this repository's workflow from the tagged commit, after everything above passed

every release

Details and the threat model are in SECURITY.md.

Where it stands (v0.8.0). Early software, tried against a live eToro demo account from Claude Desktop: the connection check, portfolio, positions, PnL, balances, trade history, instrument lookup and text search, rates, candles, eligibility, cost estimates and watchlist listing, the prepare → you-execute flow for opening an order and changing a stop loss, and the action history page with the daily counter. Closing and cancelling from Claude Desktop, watchlist changes and transfers are covered by tests but not yet exercised live (the demo script has closed positions), and nothing has been run with real money. Start on demo.

This server and eToro's official MCP server

eToro publishes its own MCP server (https://mcp.public-api.etoro.com, described at https://mcp.public-api.etoro.com/skill). This project is independent of it and not affiliated with eToro. The two solve overlapping problems differently, and you can install both: their tool names do not collide.

eToro's official server

This server

Publisher and support

eToro

An independent open-source project (MIT)

Where it runs

Remote, hosted by eToro; your credentials go in the connection headers

Local, on your machine; credentials from your keychain, a password manager or a protected file

Authentication

API key pair or OAuth

API key pair

Coverage

Read and write tools plus a generic route catalogue (execute-read, execute-write) covering the whole Public API, and trader profiles

A fixed, reviewed route allowlist; no trader profiles yet

Who executes a trade

Claude: prepare-trade returns a signed token to the model, and place-trade sends the order with it

You: Claude prepares, and only the Execute button on a local page sends anything

What enforces the approval step

Its documentation describes it as an instruction to the model (show the confirmation, get an explicit yes); it does not describe a server-side human confirmation

The server: no tool Claude can call executes anything, and the HTTP client refuses a write without the permission that button issues

Size limits, history

Not described in its documentation

Per-order, per-session and per-day caps; a searchable local history

Extras

Instrument overview, trader profiles

Candles with summaries, what-if simulations and backtests, a pre-close estimate

As of October 2026, from its public documentation and our own tests on a demo account: in one Claude Code session the official server's prepare-trade and place-trade flow placed an order after a plain "yes". In an earlier test of this project, a session declined to call the tool that executed. We did not isolate why; whether a model calls an execute tool is its own decision, and a gate that depends on it is only as strong as that decision.

Which to use. Use the official server for the widest coverage and for OAuth, if you accept that the model can place orders once you approve in chat. Use this one if you want the approval to be enforced outside the model, local control of your keys, spending limits and a record of what you did. If you only read data, either works. Whichever you choose, start on demo, give the key only the permissions it needs, and keep real-money access off until you have decided you want it.

Safety model

Layer

Default

What it does

Environment

demo

Keys and routes target eToro's demo environment unless you set ETORO_ENV=real.

Write tools

off

ETORO_ENABLE_WRITE=true registers the order/close/cancel/watchlist tools. A client cannot call a tool that does not exist.

Real-money writes

off

On real, write tools also need ETORO_ALLOW_REAL_WRITE=true.

Transfers

off

The internal-transfer tool needs real + both switches + ETORO_ALLOW_TRANSFERS=true.

Claude proposes, you execute

always

Every change (orders, closes, cancels, transfers, watchlists) is an etoro_prepare_* call that only registers a proposal. The server opens a local approval page in your browser; only pressing Execute there sends anything to eToro. No tool Claude can call executes an action, and the HTTP client refuses every write route without the permission that button issues.

The approval page

always

Served on 127.0.0.1 only, with a one-time secret in its address that is not given to Claude by default, a Host check (DNS rebinding), Origin and anti-CSRF checks, no JavaScript and every external string escaped.

Size caps

100 USD / order, 500 USD / session, 1000 USD / day

ETORO_MAX_ORDER_USD (exposure = amount × leverage), ETORO_MAX_SESSION_USD and ETORO_MAX_DAILY_USD.

Daily limits

1000 USD and 25 writes per day, per environment

ETORO_MAX_DAILY_USD and ETORO_MAX_DAILY_WRITES, counted in the history database, so they hold across restarts and across server processes (Claude Desktop and Claude Code each start their own). A day starts at midnight in ETORO_TIMEZONE. Only you can change them, in the server's configuration: no tool can.

Rate brake

5 writes / minute

ETORO_MAX_WRITES_PER_MINUTE.

Route allowlist

fixed

The HTTP client can only call the routes in src/endpoints.ts, only on the eToro host, and refuses write routes when writes are off.

Environment guard

always

Before any trading preview the server reads the key's scopes (GET /api/v1/me) and checks that the account answering for ETORO_ENV is that environment's account (demoCid/realCid). It refuses if the key lacks Write permission for the environment, if the data belongs to the other account, or if this cannot be verified.

Idempotency

always

Each prepared action has its own x-request-id, reused on retries, and it can be executed only once.

Tool annotations

always

Read and write tools are separate and carry MCP annotations (readOnlyHint, destructiveHint, title), so clients can apply sensible permission prompts.

Secrets

—

Never in tool inputs, results, errors or the audit log. ETORO_BASE_URL can only point to an https://*.etoro.com host.

Also strongly recommended on the eToro side: create a Read key unless you need to trade, restrict it by IP, and set an expiry. Keys are separate for Demo and Real, so a demo key can never touch real money.

See SECURITY.md for the threat model and how to report a vulnerability.

History and daily limits

Everything Claude prepares, and what you do with it (execute, reject, let it expire), is recorded in a local SQLite file (ETORO_HISTORY_DB, private to your user, never containing keys or approval links). It has three jobs:

  • Look back. Ask Claude "what did I do this week?" (etoro_get_action_history), or ask it to open the history (etoro_open_history): a page in your browser with a search box (words, tickers, order or position ids), filters for date, environment, action and status, the detail of each action with eToro's answer and its timeline, today's use of the daily limits, and a CSV download. The page listens on 127.0.0.1 only, uses a secret address that expires after an hour, is read-only and has no JavaScript. Nothing in it can change or delete the history.

  • Hold the daily limits. ETORO_MAX_DAILY_USD and ETORO_MAX_DAILY_WRITES are checked and reserved in one database transaction when you press Execute, so two server processes cannot both spend the same allowance, and a restart does not reset it.

  • Survive restarts. An action that was waiting when the server stopped is shown as expired, and one that was executing is shown as failed with a note to check eToro.

The file is a plain SQLite database; you can open it with any SQLite tool, and deleting it only erases the record (and resets the day's counters).

Install

Claude Desktop (MCPB bundle)

  1. Get etoro-mcp-server-<version>.mcpb from the GitHub release, or build it: npm ci && npm run mcpb:pack.

  2. Open it with Claude Desktop (double-click, or drag it into Settings → Extensions).

  3. Fill in the form: API key, user key, and leave Use the REAL environment off to start on demo. Keys are stored in your OS keychain.

  4. Leave Enable write tools off until you have tried the read tools.

Claude Desktop shows a red warning before installing: the extension runs with your user's access to your computer, and any developer information shown "has not been verified by Anthropic". That is the case for any extension from outside Anthropic's own directory, and this bundle is also not signed with a code-signing certificate; see Verifying a release for how to check where it came from. Some organisations restrict which extensions may be installed; if yours does, ask your administrator or build from source.

Claude Code

git clone https://github.com/slemos/etoro-mcp-server.git && cd etoro-mcp-server
npm ci && npm run build

Export your keys in your shell profile or secret manager (do not paste them into chat or commit them), then register the server. A project-scoped .mcp.json can reference them without containing them:

{
  "mcpServers": {
    "etoro": {
      "command": "node",
      "args": ["/absolute/path/to/etoro-mcp-server/dist/index.js"],
      "env": {
        "ETORO_API_KEY": "${ETORO_API_KEY}",
        "ETORO_USER_KEY": "${ETORO_USER_KEY}",
        "ETORO_ENV": "demo"
      }
    }
  }
}

Or from the CLI: claude mcp add etoro -- node /absolute/path/to/etoro-mcp-server/dist/index.js (the server reads ETORO_API_KEY / ETORO_USER_KEY from the environment Claude Code runs in). Check with claude mcp list.

Any other MCP client

It is a standard stdio server: run node dist/index.js with the environment variables below. With npx once published: npx -y etoro-mcp-server.

Getting eToro API keys

  1. Use a verified eToro account.

  2. In eToro go to Settings → Trading → API Key Management → Create New Key.

  3. Choose the environment (Demo first), the permission (Read, or Write only if you want to trade) and, ideally, an IP allowlist and an expiry. SMS verification is required.

  4. You get an API key (x-api-key) and a user key (x-user-key). Treat both like passwords.

Reference: Authentication.

Securing your setup

The server needs two secrets (the API key and the user key). How you hand them over matters as much as what the server does with them. Anyone who gets the pair can read your account, and with a Write key can trade on it.

On the eToro side (always): create a Read key unless you really need to trade; keep Demo and Real keys separate (eToro's documentation says a key serves one environment, but a key can carry scopes for both — etoro_check_connection shows them, and strict key scope — on by default for real, off for demo, configurable with ETORO_STRICT_KEY_SCOPE — makes the server refuse such keys for trading); restrict the key by IP address; set an expiry; revoke it at once if it may have leaked. etoro_check_connection shows the key's scopes and warns when a read-only server holds a Write key.

On your side: keep the secrets out of config files and shell history. Pick the first option that your client allows:

Option

Where the secret lives

Use it with

MCPB bundle (sensitive fields)

OS keychain, managed by the host

Claude Desktop

ETORO_API_KEY_CMD / ETORO_USER_KEY_CMD

OS keychain or password manager; the config only holds the command

Any client, manual setup

ETORO_API_KEY_FILE / ETORO_USER_KEY_FILE

A file readable only by you (the server refuses it otherwise)

Any client, manual setup

Plain ETORO_API_KEY / ETORO_USER_KEY

Your shell or a config file in clear text

Quick local tests only

Avoid putting the keys directly in claude_desktop_config.json, in claude mcp add -e ETORO_API_KEY=... (stored in clear text in ~/.claude.json and in your shell history), or in a committed .mcp.json. Set exactly one source per key; the server refuses ambiguous setups.

*_CMD takes a command line that prints the secret on one line. It is split into words (quotes are honored) and run without a shell: no pipes, no expansion. It runs with your privileges, so treat it like the command of the server itself. *_FILE accepts ~/... paths; on macOS and Linux the file must not be accessible to group or others (chmod 600).

Recipes

macOS Keychain (prompts for the value without echoing it):

security add-generic-password -U -s etoro-mcp-server -a api-key -w
security add-generic-password -U -s etoro-mcp-server -a user-key -w
"env": {
  "ETORO_API_KEY_CMD": "security find-generic-password -s etoro-mcp-server -a api-key -w",
  "ETORO_USER_KEY_CMD": "security find-generic-password -s etoro-mcp-server -a user-key -w",
  "ETORO_ENV": "demo"
}

When macOS asks whether security may read the item, prefer Allow over Always Allow: with "Always Allow", any program you run that calls security can read it without asking.

Linux (libsecret): secret-tool store --label="eToro API key" service etoro-mcp-server key api-key (same for user-key), then ETORO_API_KEY_CMD="secret-tool lookup service etoro-mcp-server key api-key".

Password managers: any CLI that prints the secret works, for example op read "op://Private/eToro/api-key" (1Password, with biometric unlock), pass show etoro/api-key, or bw get password etoro-api-key (Bitwarden, needs an unlocked session).

A protected file:

mkdir -p ~/.config/etoro-mcp && chmod 700 ~/.config/etoro-mcp
( umask 077; printf "API key: "; read -rs v; echo; printf '%s' "$v" > ~/.config/etoro-mcp/api-key )
( umask 077; printf "User key: "; read -rs v; echo; printf '%s' "$v" > ~/.config/etoro-mcp/user-key )
# then: ETORO_API_KEY_FILE=~/.config/etoro-mcp/api-key  ETORO_USER_KEY_FILE=~/.config/etoro-mcp/user-key

Windows: use the MCPB bundle (keys go to the host's credential store), or a password manager CLI through *_CMD.

What this does not protect against

The server runs as you. Another program running as your user can read what you can read, including the keychain items you allow and files with your permissions. Prompt injection is a separate risk, covered by the write-tool safeguards above. Use IP restrictions and short expiries so that a leaked key is worth little.

Verifying what you install

Building from source is small and auditable (npm ci uses the committed lockfile). Release bundles are built by GitHub Actions from the tagged commit, after tests and security checks pass.

Verifying a release

Each release attaches the bundle, a SHA256SUMS file and an SBOM (*.sbom.cdx.json, CycloneDX). The bundle is not code-signed with a certificate; its provenance is attested instead, which proves it was produced by this repository's release workflow:

shasum -a 256 -c SHA256SUMS --ignore-missing
gh attestation verify etoro-mcp-server-<version>.mcpb --repo slemos/etoro-mcp-server

If you would rather not trust a binary at all, build it yourself (npm ci && npm run mcpb:pack) and compare the result with the release.

Configuration

All settings are environment variables (see .env.example). The server does not read a .env file by itself: export the variables, or load a git-ignored .env with Node's flag, e.g. node --env-file=.env dist/index.js (Node 22.13+, which the history database needs).

Variable

Default

Description

ETORO_API_KEY

— (required)

Public API key (x-api-key). Alternatives: ETORO_API_KEY_FILE or ETORO_API_KEY_CMD (see Securing your setup). Set exactly one.

ETORO_USER_KEY

— (required)

User key (x-user-key). Alternatives: ETORO_USER_KEY_FILE or ETORO_USER_KEY_CMD. Set exactly one.

ETORO_ENV

demo

demo or real. Must match the environment of the key pair.

ETORO_USE_REAL

unset

true or false: the same choice as ETORO_ENV, as a switch (the MCPB bundle's form uses it, since extension forms have toggles but no drop-down). If both are set they must agree; otherwise the server refuses to start.

ETORO_ENABLE_WRITE

false

Register the write tools. Needs a key with Write permission.

ETORO_ALLOW_REAL_WRITE

false

Second switch required for write tools when ETORO_ENV=real.

ETORO_ALLOW_TRANSFERS

false

Register the internal-transfer tool (real only, needs both switches above).

ETORO_STRICT_KEY_SCOPE

true on real, false on demo

Refuse trading previews when the key can also write in the other environment. On real it means the key must be real-only; on demo it would mean the key must not be able to trade real money. Set it explicitly to override either default.

ETORO_OPEN_BROWSER

true

Open the approval page in your default browser when an action is prepared. If it cannot be opened, the address is in the server's log (stderr).

ETORO_SHOW_APPROVAL_URL

false

Put the approval page's address in the tool result. That lets Claude see it, and with browser tools open it: meant for scripts (npm run demo:order uses it) and for machines without a browser.

ETORO_MAX_ORDER_USD

100

Max exposure (amount × leverage) or transfer amount per action.

ETORO_MAX_SESSION_USD

500

Max total exposure executed until the server restarts.

ETORO_MAX_WRITES_PER_MINUTE

5

Local brake on executed writes (eToro also rate-limits).

ETORO_MAX_DAILY_USD

1000

Max total exposure (and transfers) executed per calendar day, per environment. Counted in the history database: it survives restarts and is shared by every server process. A request that clearly fails at eToro (a 4xx answer) gives its share back; a timeout or network error does not, because the order may exist.

ETORO_MAX_DAILY_WRITES

25

Max executed writes (orders, closes, stop-loss changes, watchlist changes...) per calendar day, per environment.

ETORO_TIMEZONE

UTC

IANA time zone (for example America/Santiago) that decides where a day starts for the daily limits and how the history page shows times.

ETORO_HISTORY_DB

your data folder

Path of the SQLite file with the action history and the daily ledger (macOS ~/Library/Application Support/etoro-mcp-server/history.sqlite, Linux ~/.local/share/etoro-mcp-server/, Windows %APPDATA%\etoro-mcp-server\). off keeps it in memory only: the daily limits then restart with the server. A server that can write refuses to start if the file cannot be opened.

ETORO_CONFIRM_TTL_SECONDS

600

How long a prepared action waits for you on the approval page.

ETORO_MAX_RESPONSE_CHARS

120000

Output size cap per tool result. Above it, arrays are shortened to their first N items (the result stays valid JSON and lists each array's real length).

ETORO_DEBUG

false

Log each HTTP call to eToro (method, path, query names, status, duration) to stderr. Never logs keys, headers or bodies.

ETORO_AUDIT_LOG

unset

Append JSON-lines audit events to this file (also logged to stderr).

ETORO_BASE_URL

https://public-api.etoro.com

Must be https on an etoro.com host.

Tools

24 read tools (always available) and 12 write tools that only prepare (+1 gated transfer tool). Full parameters and the eToro routes they use are in docs/TOOLS.md.

Tool

Kind

Purpose

etoro_check_connection

read

Verify the keys authenticate, show their scopes (demo/real, read/write), and prove which account (demo or real) the data comes from

etoro_get_portfolio

read

Aggregated portfolio snapshot

etoro_get_portfolio_breakdown

read

Open positions (ids, units), pending orders, credit

etoro_get_pnl

read

Unrealized PnL and portfolio details

etoro_get_balances

read

Balances across your eToro accounts

etoro_get_trade_history

read

Closed trades since a date

etoro_get_order

read

Status of one order

etoro_get_instruments

read

Resolve exact tickers / ids to instruments

etoro_search_instruments

read

Find instruments by name or partial text ("apple", "S&P 500")

etoro_get_candles

read

Historical price candles (1m to 1w) for a window, with a summary: first open, last close, high, low, % change, volume

etoro_search_investors

read

Find investors by performance and risk filters (period, risk score, copiers, instrument held...), compact public stats per investor

etoro_get_investor

read

One investor's public data by username: profile, statistics over a period, copiers, gain history and live portfolio. Free text they wrote is flagged as untrusted

etoro_get_balance_history

read

Day-by-day total balance between two dates, with a summary (start, end, change, lowest, highest)

etoro_get_cash_transactions

read

Movements of one of your cash accounts, newest first, paginated

etoro_simulate_position

read

What-if on past prices: a long or short with leverage, stop loss and take profit, followed over a window of candles (entry, exit and why, result in USD and %, worst and best moments). Places nothing

etoro_backtest

read

Backtest buy_and_hold or dca (an amount every N days) over a window, with the same total invested at the start for comparison. Places nothing

etoro_get_rates

read

Bid/ask for instruments

etoro_check_eligibility

read

Settlement types, leverage, limits per instrument

etoro_get_trading_costs

read

What-if cost breakdown for an order

etoro_list_price_alerts

read

Your active price alerts, with which way the price has to move to reach each target and how far

etoro_list_watchlists

read

Your watchlists

etoro_get_action_status

read

Where a prepared action stands (waiting, executed with eToro's answer, rejected, expired, failed); also finds actions from earlier sessions

etoro_get_action_history

read

Search the local history (text, ids, dates, environment, action, status) and see today's use of the daily limits

etoro_open_history

read

Open a read-only page in your browser to search, filter and export the history

etoro_prepare_open_position

write (preview)

Validate + preview an order, open its approval page; returns actionId

etoro_prepare_close_position

write (preview)

Preview closing all/part of a position: instrument, direction, current price, rough result, what stays open

etoro_prepare_modify_position

write (preview)

Preview changing the stop loss / take profit of an open position (new rates, trailing, or removing them)

etoro_prepare_cancel_order

write (preview)

Preview cancelling a pending order

etoro_prepare_cancel_close_order

write (preview)

Preview cancelling a pending close order (the position stays open)

etoro_prepare_transfer

write (preview, gated)

Preview an internal transfer (real + opt-in only)

etoro_prepare_create_price_alert / ..._update_price_alert / ..._delete_price_alert

write (preview)

Propose creating, changing the target of, or deleting a price alert (no order, no money); you execute them on the page

etoro_prepare_create_watchlist / ..._add_watchlist_items / ..._remove_watchlist_items / ..._delete_watchlist

write (preview)

Propose watchlist changes (no money involved); you execute them on the page

Example: a guarded order

You:    Prepare a purchase of 50 USD of AAPL as a CFD on my demo account.
Claude: [etoro_prepare_open_position] → preview: BUY AAPL (id 1001) | $50.00 | 1x | cfd | mkt | DEMO,
        eligibility, estimated costs, actionId 6b1c…  (nothing sent; your browser opens the approval page)
You:    (review the page, press Execute)                → the server sends the order to eToro
Claude: [etoro_get_action_status]     → executed, eToro's orderId
Claude: [etoro_get_order]             → status of the order

eToro answers an order with "accepted for processing", not "filled": follow the order with etoro_get_order.

Trying an order on the demo environment

npm run demo:order runs the whole flow through the real server on eToro's demo (virtual money) environment: connection and environment check, instrument lookup, eligibility, preview with cost estimate, your confirmation in the terminal, execution, and following the order until it has a position.

npm run demo:order -- --symbol AAPL --amount 50                 # buy $50 on demo, keep the position
npm run demo:order -- --symbol AAPL --amount 50 --close         # ... and close it afterwards (asks again)
npm run demo:order -- --symbol AAPL --amount 20 --settlement cfd
npm run demo:order -- --close-position 123456789                # close an open demo position by id
npm run demo:order -- --symbol AAPL --amount 50 -y 2>&1 | tee demo-order.log   # no questions, output to a log

The script forces ETORO_ENV=demo whatever your environment says, stops unless the connection check proves the key reaches your demo account, and asks in the terminal before sending anything; your "yes" (or -y) is what it uses to press Execute on the approval page for you. -y (or --yes) answers yes to the questions — the order and, with --close, the close — so you can pipe the output to a log (use 2>&1 to include the server's audit lines). Without a terminal and without -y it refuses to start instead of hanging. Use a key with demo Write permission. After a fill it prints the new position's settlement (cfd or real) with its settlementTypeID and isSettled. --settlement real on an account that is only offered CFDs is refused at the preview.

Known limitations

  • Very large responses are shortened. A big portfolio (many positions or copy-trading mirrors) can exceed the output cap; the server then keeps the first N items of each array and says how many there really were. Prefer narrower tools or raise ETORO_MAX_RESPONSE_CHARS.

  • Responses are passed through as eToro sends them. The shapes come from eToro's reference pages and from a live demo account (see "Where it stands" above); the actions listed there have been tried live and the rest only through tests. If a field is missing or renamed, please open an issue with the (redacted) response shape (--verbose --mask in the smoke script produces one that is safe to paste).

  • etoro_get_instruments is an exact lookup (ticker or id); use etoro_search_instruments for names. ETF tickers on eToro carry an exchange suffix such as EXMPL.L.

  • Claude cannot execute, by design. Claude's own rules keep it from executing financial transactions, so the server never asks it to: it prepares, you press Execute on the approval page. That needs a browser on the same computer (or ETORO_SHOW_APPROVAL_URL=true to read the address from the log or result); without a screen, nothing can be executed.

  • Prepared actions live in memory. They are forgotten when the server restarts (for example when Claude Desktop restarts it), and expire after ETORO_CONFIRM_TTL_SECONDS.

  • Prompt injection is a real risk for any tool-using agent: do not let Claude read untrusted content (web pages, emails, documents) in the same session in which it can prepare real orders, and read the approval page carefully before pressing Execute. If Claude has browser tools, keep ETORO_SHOW_APPROVAL_URL off so it never sees the page's address.

  • No streaming/WebSocket data, no copy-trading actions, no OAuth (API key pair only).

  • Eligibility to use the API and the instruments available depend on your account and jurisdiction. In particular, depending on jurisdiction some accounts can only open CFDs, not real shares: settlementType: "real" is then rejected by eToro (seen on a demo account that was offered only CFDs). etoro_prepare_open_position reads the eligibility answer first and refuses a settlement type the account is not offered, before anything can be confirmed.

  • Two instruments for some stocks. eToro lists a regular-trading-hours instrument (symbol ending in .RTH) next to the 24/5 one for some stocks. The preview shows the exact symbol and instrument id, and warns on .RTH; pass instrumentId when in doubt.

Development

npm ci
npm run typecheck
npm test                 # unit + end-to-end tests with a mocked eToro API (no network, no keys)
npm run build            # tsc → dist/
node scripts/smoke.mjs   # launch the built server over stdio and list tools (dummy keys)
npm run security:check   # runs the built server with the network cut off: permission switches, hostile inputs, secret redaction
npm run mcpb:pack        # esbuild bundle → server/index.js, then etoro-mcp-server.mcpb
npm run pack:dev         # throwaway etoro-mcp-server-dev.mcpb, versioned <version>-dev.<n>, to try changes in Claude Desktop

With your own keys in a git-ignored .env, npm run smoke:live (or node scripts/smoke.mjs --live with the variables exported) runs etoro_check_connection and a few read tools and prints only the shape of the responses (never values), which is a safe first check. In a client, ask Claude to run etoro_check_connection to confirm the keys work and which mode the server is in.

Debugging options for the script (all run the real server over stdio):

Option

Effect

--report

Only verify the connection and the environment (npm run verify with a .env): prints a one-line verdict and reads no account data.

--verbose

Print each tool's full output. It contains your real account data: keep it private.

--verbose --mask

Same, but every value is replaced by a placeholder (<number>, <string, 12 chars>), keeping field names, types and nesting. Safe to paste into an issue.

--tool <name> --args '<json>'

Call a single tool, e.g. --tool etoro_get_trade_history --args '{"minDate":"2026-01-01"}'.

--debug

Sets ETORO_DEBUG=true so the server logs each HTTP call.

--entry <file>

Launch another entry point, e.g. server/index.js (the bundle used by the .mcpb).

src/
  config.ts      env parsing, switches, caps
  endpoints.ts   the complete route allowlist (read vs write)
  client.ts      HTTP client: auth headers, idempotency ids, 429 retry, redaction, policy checks
  approval/      proposals (limits, status), the local approval page (server, renderer, browser opener), the write permission
  audit.ts       JSON-lines audit trail
  tools/         read.ts, write.ts, common.ts
test/            vitest, including MCP client ↔ server tests over an in-memory transport

Contributing

Issues and pull requests are welcome — see CONTRIBUTING.md. Security issues: see SECURITY.md.

License

MIT

Available Tools

11 tools
etoro_check_eligibilityCheck eToro trading eligibilityA
Read-onlyIdempotent

What the demo account may do with instruments: available settlement types (real/cfd), leverage values, buy/sell and partial-close permissions, minimum position amounts, stop-loss/take-profit limits. Computes only; places nothing. Provide instrumentIds and/or symbols (max 100 combined).

ParametersJSON Schema
NameRequiredDescriptionDefault
symbolsNo
instrumentIdsNo

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already cover readOnlyHint, idempotentHint, destructiveHint and openWorldHint, so the safety profile is known. The description still adds genuine value by stating 'Computes only; places nothing' and by describing the returned decision fields (settlement types, permissions, limits), which no output schema provides. It does not, however, cover auth scope or any per-call limits beyond input count.

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?

One dense clause stating what is returned, followed by a short constraint sentence and a short input instruction. Strongly front-loaded with the payload description and no filler. Slightly run-on list inside the first clause, but nothing is wasted.

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

Completeness4/5

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

With no output schema and 0% schema description coverage, the description must explain both returns and inputs, and it does so competently for a two-parameter read tool. Remaining gaps are minor: behavior when neither parameter is given, and the 'demo account' scoping, which could confuse an agent unsure whether it applies to live accounts.

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 description coverage is 0%, so the description must carry the parameter burden and largely does: it explains that instrumentIds and symbols are alternatives ('and/or') and imposes a 'max 100 combined' limit that is stricter and more useful than the schema's per-array maxItems of 100. It does not explain symbol format or what happens when neither is supplied.

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

Purpose4/5

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

The description enumerates exactly what the tool returns for a given instrument set (settlement types, leverage, buy/sell and partial-close permissions, minimums, SL/TP limits), which is far more specific than a restatement of the name. It is clearly distinct from the portfolio/pnl/balances siblings. It lacks an explicit verb ('check'), but the resource and scope are unambiguous.

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

Usage Guidelines3/5

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

Usage is implied rather than stated: the tool reports what an account may trade, and 'Computes only; places nothing' signals a pre-trade query. However, there is no explicit when-to-use framing, no prerequisites, and no alternative sibling is named or excluded, so an agent must infer the context.

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

etoro_get_balancesGet eToro balancesB
Read-onlyIdempotent

Aggregated balances across the user's eToro accounts (trading, cash, ...), expressed in a display currency. Not environment-specific: it reports the account the key belongs to.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountTypesNoComma-separated filter: Trading, Cash, Options, Crypto, MoneyFarm, Spaceship, Plaee.
displayCurrencyNoISO 4217 code used for totals.USD
includeSubAccountsNo
includeZeroBalancesNo

TDQS

B3/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=true, so the safety profile is covered. The description usefully adds that balances are aggregated in a display currency and that the tool reports the account the key belongs to (not environment-specific), which is real context beyond annotations, but it says nothing about response shape or currency-conversion behavior.

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?

Two compact sentences with the core purpose front-loaded and no filler. Slightly terse given the tool's scope, but nothing is wasted.

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

Completeness3/5

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

For a zero-required-parameter read tool with annotations covering safety, the description is adequate on purpose but incomplete: it omits the meaning of unfiltered calls (all account types?), pagination, and the shape of the aggregated result. With no output schema present, a bit more disclosure would help.

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

Parameters2/5

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

Schema coverage is only 50%: accountTypes and displayCurrency are documented, while includeSubAccounts and includeZeroBalances have no description in either the schema or the description. The description mentions no parameter at all, so it fails to compensate for the coverage gap.

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

Purpose4/5

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

States a specific verb+resource ('aggregated balances across the user's eToro accounts') and clarifies scope with 'trading, cash, ...'. It hints at differentiation from portfolio siblings via 'Not environment-specific', but never names a sibling like etoro_get_portfolio, so an agent must still infer the boundary.

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

Usage Guidelines2/5

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

There is no explicit when-to-use guidance and no named alternative among the many portfolio/PnL siblings. The only routing clue is the negative statement that it is not environment-specific, which does not tell the agent when to prefer this over etoro_get_portfolio or etoro_get_portfolio_breakdown.

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

etoro_get_instrumentsFind eToro instrumentsA
Read-onlyIdempotent

Look up instruments by exact ticker symbols or by instrument ids, or list by type. Returns instrumentId, symbol, displayName, type and exchangeId. Free-text name search is not supported; ETF listings use exchange suffixes (for example CSPX.L). Provide symbols or instrumentIds, not both.

ParametersJSON Schema
NameRequiredDescriptionDefault
typeNo
symbolsNoExact tickers, e.g. ['AAPL', 'CSPX.L'].
pageSizeNo
instrumentIdsNo

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already establish readOnly/idempotent/openWorld/non-destructive, so the safety profile is covered. The description adds genuinely useful behavior beyond that: the lack of free-text search, the exchange-suffix convention for ETFs with a concrete example (CSPX.L), and the return field list (no output schema exists, so this is the only source).

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?

Three dense sentences with no filler, front-loaded with the core action before the constraints. The return-field list and the 'not both' rule each carry weight, though the sentences are packed tightly enough that a little breathing room would help readability.

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

Completeness4/5

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

With no output schema, the description supplies the return shape itself, and it covers the input modes and mutual-exclusion rule. Remaining gaps are minor: it never says what happens when no parameters are supplied (full listing?) or how pageSize pagination behaves.

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 only 25% (just 'symbols'), so the description does meaningful compensation: it clarifies symbols are exact tickers, contrasts symbols vs instrumentIds, explains the ETF suffix format, and notes only one of the two should be supplied. pageSize and the type enum values are left to the schema, which documents them adequately.

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 and resource ('look up instruments') and enumerates the three lookup modes (exact symbols, instrument ids, or by type). Also names the returned fields (instrumentId, symbol, displayName, type, exchangeId), so an agent knows exactly what it gets. Clearly distinct from the sibling portfolio/order/rate tools.

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

Usage Guidelines4/5

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

Gives concrete operating constraints: free-text name search is not supported, and symbols/instrumentIds should not be combined. These are real usage rules that steer the caller. It does not name an alternative tool, but none of the siblings overlaps this lookup function, so the guidance is effectively complete.

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

etoro_get_orderLook up an eToro orderA
Read-onlyIdempotent

Status and execution details of one order, found by orderId (returned when an order is placed) or by referenceId. Provide exactly one.

ParametersJSON Schema
NameRequiredDescriptionDefault
orderIdNo
referenceIdNo

TDQS

A3.7/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered. The description adds provenance context ('orderId returned when an order is placed') but says nothing about behavior on a missing order, pagination, or rate limits, so it adds only modest value beyond the annotations.

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

Conciseness5/5

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

One front-loaded sentence naming the return content, followed by a terse clause on key selection and the exactly-one constraint. Nothing is redundant and no sentence is wasted.

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

Completeness4/5

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

For a two-parameter read-only lookup with no output schema, the description covers what is returned at a summary level and how to identify the order. It does not sketch the shape of 'status and execution details' or error behavior, which is the only real gap.

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 description coverage is 0%, so the description must carry the parameter burden, and it does: it explains what orderId is (returned when an order is placed), that referenceId is an alternative identifier, and that exactly one must be supplied. It omits type/format constraints (positive integer, string length), keeping it short of a 5.

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

Purpose4/5

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

States a specific verb and resource ('Status and execution details of one order') and names the lookup keys, so the agent knows it fetches a single order rather than a list. The resource is distinct from every sibling (portfolio, pnl, balances, rates, watchlists), though the description never explicitly contrasts itself with them.

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

Usage Guidelines3/5

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

It gives useful invocation guidance — use either orderId or referenceId and 'Provide exactly one' — which tells the agent how to call it. However, it says nothing about when this tool is appropriate versus other order- or history-related siblings such as etoro_get_trade_history, so usage context is only implied.

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

etoro_get_pnlGet eToro account PnLA
Read-onlyIdempotent

Unrealized profit/loss and portfolio details of the demo account (positions, mirrors, pending orders and orders to open/close).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive), so the bar is lower, and the description still adds two useful pieces of context: that it targets the demo account specifically and exactly which data classes are returned. It stops short of noting any auth, rate-limit, or freshness/valuation caveats.

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

Conciseness5/5

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

A single front-loaded sentence with no filler; the subject (unrealized P/L) comes first and the enumeration is compactly parenthesized. Every clause carries information.

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

Completeness4/5

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

With no parameters and no output schema, the description must convey what comes back, and it does enumerate the returned data classes. The remaining gap is the absence of sibling differentiation, which matters given three other portfolio-style tools in the same family.

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?

The tool takes zero parameters, so there is nothing for the description to disambiguate and the baseline of 4 applies. The parenthetical clarifies what the (parameterless) response covers, which is a reasonable substitute.

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

Purpose4/5

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

States a specific resource and result: unrealized P/L plus portfolio details, with an explicit enumeration of contents (positions, mirrors, pending orders, orders to open/close). It is clear what the tool returns, but it never distinguishes itself from close siblings like etoro_get_portfolio, etoro_get_portfolio_breakdown, or etoro_get_balances, which an agent must choose between.

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

Usage Guidelines2/5

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

The only scoping signal is 'demo account', which implies a context but is not framed as a when-to-use rule. No alternatives are named and no conditions for choosing this over the other portfolio/balance tools are given, leaving selection to inference.

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

etoro_get_portfolioGet eToro portfolio snapshotA
Read-onlyIdempotent

Aggregated snapshot of the demo account: account totals, open positions grouped by instrument, and copy-trading mirrors. For individual open positions with their position ids and pending orders use etoro_get_portfolio_breakdown. Reference: https://api-portal.etoro.com.

ParametersJSON Schema
NameRequiredDescriptionDefault
pnlLevelNoProfit/loss detail to include.Pnl
instrumentIdsNoRestrict the snapshot to these instrument ids.

TDQS

A4/5.0
Behavior3/5

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

Annotations already declare readOnly, idempotent, openWorld and non-destructive, so the safety profile is covered. The description usefully scopes the call to the 'demo account' and sketches the aggregation shape, but discloses nothing about pagination, latency, or auth requirements beyond the API reference link.

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

Conciseness5/5

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

Three short sentences, all front-loaded: what it returns first, the sibling alternative second, the reference link last. No filler or restatement of the title.

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

Completeness4/5

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

With no output schema, the description carries the burden of describing the return shape, and it does so adequately (totals, positions grouped by instrument, mirrors). The 'demo account' framing answers an important scope question, though the absence of any note on the aggregate-vs-breakdown trade-offs for filtering remains a small gap.

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

Parameters3/5

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

Schema description coverage is 100%, so pnlLevel and instrumentIds are already documented in the schema, including the enum values and maxItems constraint. The description adds no additional meaning about these filters, so the baseline of 3 applies.

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 and resource ('aggregated snapshot of the demo account') and enumerates exactly what the payload contains: account totals, open positions grouped by instrument, and copy-trading mirrors. It explicitly contrasts itself with the sibling etoro_get_portfolio_breakdown, so an agent can distinguish the two without opening schemas.

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

Usage Guidelines4/5

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

Names an alternative and the condition that selects it ('For individual open positions with their position ids and pending orders use etoro_get_portfolio_breakdown'), which is genuine routing guidance. It does not, however, say when to prefer this aggregated view over other sibling reads like etoro_get_pnl or etoro_get_balances, which overlap in scope.

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

etoro_get_portfolio_breakdownGet eToro positions and pending ordersA
Read-onlyIdempotent

Open positions (with position ids and units), pending orders and available credit for the demo account. Position ids from here are what etoro_prepare_close_position needs.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already establish the safe-read profile (readOnlyHint, idempotentHint, destructiveHint=false). The description then adds behavior the annotations cannot convey: the data is scoped to the demo account and the response carries position ids and units that are consumable downstream. It does not mention pagination or result size limits, but the added account scoping is meaningful context.

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

Conciseness5/5

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

Two short sentences with no filler. Content is front-loaded (what is returned first, then the downstream-id note), and every clause carries information.

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

Completeness4/5

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

With no output schema, the description must convey what comes back, and it does list the three main return groups plus the demo-account scope. It stops short of describing field-level detail or ordering, which is acceptable for a read-only breakdown tool but leaves some minor gaps.

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?

The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline for a no-parameter tool applies. The description correctly spends no words on arguments and instead characterizes the returned data.

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

Purpose4/5

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

The description names the concrete resources returned: open positions (with ids and units), pending orders, and available credit. That is specific enough for an agent to know what it gets, but it never explicitly distinguishes itself from likely overlapping siblings such as etoro_get_portfolio or etoro_get_balances.

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

Usage Guidelines3/5

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

It gives one real usage hook — the position ids are the inputs that etoro_prepare_close_position needs — which is genuinely useful workflow guidance. However, there is no statement of when to prefer this over etoro_get_portfolio, etoro_get_balances, or etoro_get_pnl, so selection among siblings is left to inference.

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

etoro_get_ratesGet eToro bid/ask ratesA
Read-onlyIdempotent

Current bid and ask for up to 100 instruments by id. Prices are eToro's quotes, not necessarily the underlying venue's.

ParametersJSON Schema
NameRequiredDescriptionDefault
instrumentIdsYes

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already cover safety (readOnlyHint, idempotentHint, destructiveHint=false), so the description's added value is the caveat that these are eToro's own quotes rather than the underlying venue's prices, which is genuinely decision-relevant for an agent. It does not discuss failure behavior for unknown ids or rate limits, keeping it short of a 5.

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

Conciseness5/5

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

Two sentences, no waste, with the core operation stated first and the important quote-source caveat second. Both sentences earn their place.

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

Completeness4/5

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

With no output schema, the description usefully names the returned fields (bid and ask) and the quote provenance, so an agent knows what comes back. Only minor gaps remain around id validity and error behavior for a tool this simple and well-annotated.

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

Parameters3/5

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

Schema description coverage is 0% for the single instrumentIds parameter, so the description must carry the load. It conveys the id-based array and the 100-item ceiling, matching the schema's maxItems, but adds no clarification on id format, ordering, or error handling for invalid ids.

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

Purpose4/5

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

States a specific verb and resource (current bid and ask) plus a scope limit (up to 100 instruments by id), which separates it from sibling lookups like etoro_get_instruments or etoro_get_trade_history. It stops short of naming an alternative sibling explicitly, so it is clear but not fully differentiated.

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

Usage Guidelines2/5

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

There is no explicit when-to-use or when-not-to-use guidance, nor any pointer to etoro_get_instruments as the source of the ids this tool requires. The 'by id' phrasing implies a prerequisite lookup, but the routing decision is left entirely to inference.

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

etoro_get_trade_historyGet eToro closed tradesA
Read-onlyIdempotent

Closed trades of the demo account since a date, with open/close rates, net profit and fees. Paginated.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo
minDateYesStart date, YYYY-MM-DD.
pageSizeNo

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already cover read-only, idempotent, non-destructive, and open-world behavior. The description adds useful operation-specific context: it is limited to the demo account, returns closed trades with open/close rates, net profit and fees, and is paginated. It still does not explain pagination behavior or authentication needs.

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

Conciseness5/5

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

Two short sentences with no wasted words. The core purpose, scope, return fields, and pagination caveat are front-loaded and easy to parse.

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

Completeness4/5

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

For a simple read-only listing tool with no output schema and rich safety annotations, the description covers the key facts an agent needs: demo-account scope, closed trades only, date filtering, returned fields, and pagination. It remains incomplete on pagination details and lacks sibling routing, but overall it is sufficient for correct invocation.

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

Parameters3/5

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

Schema coverage is low at 33%, with only minDate documented. The description adds some semantic value: 'since a date' clarifies minDate as a start date, and 'Paginated' signals that page/pageSize exist and matter. However, it does not explain page or pageSize behavior, defaults, or limits, so the two undocumented parameters remain underspecified.

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

Purpose4/5

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

States specific verb+resource ('Get eToro closed trades'), scope ('demo account since a date'), and returned fields. It distinguishes closed trades from generic portfolio/PnL siblings implicitly through 'closed trades' and 'open/close rates, net profit and fees', but does not explicitly say how it differs from tools like etoro_get_pnl.

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

Usage Guidelines2/5

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

There is no explicit when-to-use or when-not-to-use guidance, and no alternative sibling is named. The description only implies usage by specifying 'closed trades of the demo account since a date', leaving the agent to infer context.

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

etoro_get_trading_costsEstimate eToro trading costsA
Read-onlyIdempotent

What-if cost breakdown (markup, market spread, transaction fee, overnight and weekend fees, stamp duty) for a hypothetical order. Computes only; places nothing. Amounts are in USD. For closing, pass the position ids.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionNoopen
symbolNo
leverageNo
amountUsdNo
orderTypeNomkt
positionIdsNo
transactionNobuy
instrumentIdNo
settlementTypeNo

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive/openWorld, so the bar is lower, yet the description adds real value: it confirms nothing is placed, enumerates the fee components computed (markup, spread, transaction, overnight/weekend, stamp duty), and specifies amounts are in USD. It omits any statement about return shape or latency, but the added context is solid.

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

Conciseness5/5

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

Three short sentences, front-loaded with the purpose and the compute-only guarantee, then the currency unit and the closing hint. No filler.

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

Completeness2/5

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

For a 9-parameter tool with zero schema descriptions and no output schema, the description is thin: it names the output fee components and currency but leaves nearly all input semantics undocumented, so an agent must infer which parameters pair with which action (open vs close) and what values are valid.

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

Parameters2/5

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

Schema description coverage is 0% across 9 parameters, so the description carries the full burden. It only clarifies one parameter ('For closing, pass the position ids') and never explains action, symbol, leverage, amountUsd, orderType, transaction, instrumentId, or settlementType — enums and defaults exist in the schema but no semantics are added.

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 and resource — a what-if cost breakdown for a hypothetical order — and immediately clarifies 'Computes only; places nothing', which cleanly separates it from the read-only portfolio/pnl/balance siblings and from any order-placement flow.

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

Usage Guidelines4/5

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

The 'what-if ... hypothetical order' framing plus 'Computes only; places nothing' tells the agent this is for estimation rather than execution, and 'For closing, pass the position ids' gives a concrete conditional. It stops short of naming an alternative tool or stating exclusions explicitly.

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

etoro_list_watchlistsList eToro watchlistsC
Read-onlyIdempotent

The user's watchlists with their items (instrument ids).

ParametersJSON Schema
NameRequiredDescriptionDefault
itemsPerPageNo
includeBuiltinNo

TDQS

C2.6/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false, so the safety profile is covered. The description adds some value by stating that items are returned as instrument ids, but it does not explain pagination behavior, whether built-in watchlists are included, or other operational details.

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

Conciseness2/5

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

The description is a single noun phrase rather than a structured sentence, so it is terse but under-specified. It is not front-loaded with a clear verb or usage context, leaving important information absent.

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

Completeness2/5

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

With two undocumented parameters, no output schema, and no usage guidance, the description is too thin for an agent to call the tool confidently. It states the broad return content but omits parameter meanings, pagination, and the role of built-in watchlists.

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

Parameters1/5

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

Schema description coverage is 0% for both itemsPerPage and includeBuiltin, and the description does not mention either parameter. The definition gives an agent no way to understand the two inputs beyond their bare names and defaults.

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

Purpose4/5

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

The description names the specific resource (the user's watchlists) and what each contains (items / instrument ids), so an agent can tell it is a read/list tool for watchlists. It lacks an explicit verb, but the title supplies 'List' and no sibling tool covers watchlists, making the purpose clear.

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

Usage Guidelines2/5

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

There is no guidance on when to call this tool, when to avoid it, or how it relates to the portfolio and instrument siblings. The agent must infer its usage from the name alone.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 11 tool updatesv0.1.0
    • First observedetoro_check_eligibility
    • First observedetoro_get_balances
    • First observedetoro_get_instruments
    • First observedetoro_get_order
    • First observedetoro_get_pnl
    • First observedetoro_get_portfolio
    • First observedetoro_get_portfolio_breakdown
    • First observedetoro_get_rates
    • First observedetoro_get_trade_history
    • First observedetoro_get_trading_costs
    • First observedetoro_list_watchlists

TDQS

B3.3/5.0

Scored across 11 tools

Disambiguation3/5

etoro_get_portfolio, etoro_get_portfolio_breakdown, etoro_get_pnl, and etoro_get_balances all return overlapping portfolio/account data. Descriptions attempt to differentiate (e.g., aggregated vs. breakdown), but an agent could still misselect among the portfolio tools. Other tools are clearly distinct.

Naming Consistency5/5

All tools use the etoro_ prefix followed by a consistent snake_case verb_noun pattern (get_, check_, list_). No deviation in style or casing.

Tool Count4/5

11 tools is a reasonable count for a read-focused trading API surface. It is not excessive, but the absence of any execution tools makes the set feel slightly under-scoped relative to the platform's purpose.

Completeness2/5

Major gaps: no tools to place orders, cancel orders, or close positions, despite etoro_check_eligibility and etoro_get_trading_costs implying trading workflows. The description of etoro_get_portfolio_breakdown references etoro_prepare_close_position, which is not present, creating a dead end. Watchlists are read-only.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides secure access to Trading 212 Public API through MCP, enabling Claude Desktop users to manage portfolios, execute trades, and analyze market data using natural language commands.
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    A read-only MCP server that connects Claude to your eToro account, enabling queries about your portfolio, P\&L, balances, watchlists, live prices, and price history.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    MCP server for Interactive Brokers that provides account, portfolio, market data, and risk analysis tools to MCP hosts like Claude Desktop, enabling natural language queries about positions, market regime, and position sizing without placing orders.
    8
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    A local-first MCP server that connects Claude Code to your Robinhood account, enabling read-only portfolio insights, tax analysis, and natural language queries, with optional human-in-the-loop trading actions.
    -