npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@raybooysen/etoro-agent

v1.0.25

Published

MCP server and CLI for the eToro Public API

Readme

etoro-agent

CI License: MIT Node.js

MCP server and CLI for the eToro Public API. Two interfaces, one codebase — use the MCP server from AI assistants (Claude Desktop, Claude Code, Cursor, OpenClaw, Windsurf) or the CLI from your terminal, scripts, and agents.

Table of Contents

Features

| Category | Capabilities | |----------|-------------| | Market Data | Search instruments, live rates, historical candles (OHLC), closing prices, reference data (exchanges, industries, instrument types) | | Trading | Market orders (by amount or units), limit orders, close positions (full or partial), cancel orders. Demo and real environments. | | Portfolio | Current positions, P&L summary, order execution status, closed trade history | | Social | Discover/search traders, public portfolios, gain metrics, daily performance, copier data | | Watchlists | Full CRUD — create, rename, delete, reorder, add/remove instruments, default and public watchlists | | Feeds | Instrument and user social feeds, create posts, comment on posts | | Discovery | Curated investment lists, personalized market recommendations | | Agent Portfolios | Create/manage agent portfolios and user tokens |

Prerequisites

When creating your User Key, you choose:

  • Environment — Demo or Real (keys are environment-specific)
  • Permissions — Read (portfolio, market data) or Read+Write (trading, posts)
  • IP Whitelist — optional restriction to specific IPs
  • Expiration — optional expiry date

Installation

git clone https://github.com/raybooysen/etoro-agent.git
cd etoro-agent
npm install
npm run build

Configuration

Both the CLI and MCP server accept configuration via environment variables with optional CLI argument overrides. CLI arguments take priority.

| Config | Env Var | CLI Arg | Required | Default | |--------|---------|---------|----------|---------| | API Key | ETORO_API_KEY | --api-key | Yes | — | | User Key | ETORO_USER_KEY | --user-key | Yes | — | | Environment | ETORO_ENVIRONMENT | --environment | No | demo |

Set environment variables once to avoid repeating credentials:

export ETORO_API_KEY=your-api-key
export ETORO_USER_KEY=your-user-key
export ETORO_ENVIRONMENT=demo

Or pass inline with any command:

etoro-cli identity --api-key your-api-key --user-key your-user-key

CLI Reference

The CLI outputs JSON to stdout and errors to stderr. Exit code 0 on success, 1 on failure. Pipe output to jq for filtering or to other tools for processing.

etoro-cli <command> [subcommand] [args] [options]
etoro-cli help

Identity

Get the authenticated user's account information.

etoro-cli identity

Market Data

Search instruments

Search for stocks, crypto, ETFs, indices, commodities, and currencies by symbol or name.

# Search by symbol (default — exact server-side match)
etoro-cli market search AAPL

# Search by name (client-side substring match)
etoro-cli market search Apple --filter-by name

# Paginate results
etoro-cli market search TSLA --page 1 --page-size 5

Get instrument metadata

Retrieve detailed metadata for instruments by their IDs. Multiple IDs are automatically fetched individually and merged (the eToro API only supports one ID per request).

# Single instrument
etoro-cli market instrument 1137

# Multiple instruments (auto-fans out into individual requests with rate limiting)
etoro-cli market instrument 1137,1001,1003

Get live rates

Get current market prices for instruments.

# Single instrument
etoro-cli market rates 1

# Multiple instruments (max 100, look up IDs with: etoro-cli market search <name>)
etoro-cli market rates <id1>,<id2>,<id3>

Get historical candles

Retrieve OHLC candle data for charting and analysis.

# Default: 100 daily candles, newest first
etoro-cli market candles 1

# 1-hour candles, last 50
etoro-cli market candles 1 --interval OneHour --count 50

# 5-minute candles, oldest first
etoro-cli market candles 1 --interval FiveMinutes --count 200 --direction asc

Available intervals: OneMinute, FiveMinutes, TenMinutes, FifteenMinutes, ThirtyMinutes, OneHour, FourHours, OneDay, OneWeek

Get reference data

Retrieve cached reference data (instrument types, exchanges, stock industries).

etoro-cli market ref instrument-types
etoro-cli market ref exchanges
etoro-cli market ref stocks-industries

Check market status

Check if instruments are currently tradeable and whether their exchanges are open.

etoro-cli market status AAPL,BTC,TSLA

Returns isCurrentlyTradable, isExchangeOpen, isBuyEnabled, exchange name, and asset class for each symbol. Use this before placing orders to verify the market is open.

Portfolio

View positions

Get all current open positions in your portfolio.

etoro-cli portfolio positions

P&L summary

Get profit and loss summary for your portfolio.

etoro-cli portfolio pnl

Order status

Check the execution status of a specific order.

etoro-cli portfolio order 12345678

Trade history

Get closed trade history. The --min-date parameter is required.

# All trades since January 2025
etoro-cli portfolio history --min-date 2025-01-01

# Paginate
etoro-cli portfolio history --min-date 2025-01-01 --page 2 --page-size 10

Trading

All trading commands route to demo or real API paths based on your configured environment. If you use a demo key with --environment demo, trades execute on your virtual portfolio.

Open a market order (by cash amount)

# Buy $100 of Apple stock with 1x leverage
etoro-cli trade open --instrument 1 --buy --leverage 1 --amount 100

# Short sell $50 of an instrument with 2x leverage (look up ID first)
# etoro-cli market search "Tesla" | jq '.items[0].instrumentId'
etoro-cli trade open --instrument <instrument_id> --sell --leverage 2 --amount 50

# With stop loss and take profit
etoro-cli trade open --instrument 1 --buy --leverage 1 --amount 100 \
  --stop-loss 145.00 --take-profit 200.00

Open a market order (by units)

# Buy 0.5 units of an instrument (look up ID first)
# etoro-cli market search "Bitcoin" | jq '.items[0].instrumentId'
etoro-cli trade open-units --instrument <instrument_id> --buy --leverage 1 --units 0.5

Close a position

etoro-cli trade close 12345678

Place a limit or stop entry order

A limit order executes when the instrument reaches your specified price. The same command works for both limit entries (buy the dip) and stop entries (buy the breakout) — the API accepts any rate:

# Limit buy — buy when price DROPS to $150
etoro-cli trade limit --instrument 1001 --buy --leverage 1 --amount 100 --rate 150.00 \
  --stop-loss 140.00 --take-profit 180.00

# Stop entry buy (breakout) — buy when price RISES to $260
etoro-cli trade limit --instrument 1111 --buy --leverage 1 --amount 500 --rate 260.00 \
  --stop-loss 250.00 --take-profit 280.00

# Stop entry sell (breakdown) — short when price DROPS to $4300
etoro-cli trade limit --instrument 18 --sell --leverage 1 --amount 1000 --rate 4300.00 \
  --stop-loss 4400.00 --take-profit 4100.00

Cancel an order

Cancel a pending open order or limit order.

etoro-cli trade cancel 12345678

Social

Search for traders

Discover traders using eToro's search with filters.

# Find Popular Investors this year
etoro-cli social search --period CurrYear --popular-investor

# Paginate results
etoro-cli social search --period CurrYear --page 1 --page-size 10

Available periods: CurrMonth, CurrQuarter, CurrYear, LastYear, LastTwoYears, OneMonthAgo, TwoMonthsAgo, ThreeMonthsAgo, SixMonthsAgo, OneYearAgo

Get user info

View detailed information about a specific trader.

# Public portfolio
etoro-cli social user sometrader portfolio

# Historical gain metrics
etoro-cli social user sometrader gain

# Trade statistics
etoro-cli social user sometrader tradeinfo

# Daily gain data
etoro-cli social user sometrader daily-gain

Get copiers

Get copier information for the authenticated user (Popular Investors).

etoro-cli social copiers

Watchlists

List all watchlists

etoro-cli watchlist list

Get a specific watchlist

etoro-cli watchlist get abc123

Create a watchlist

etoro-cli watchlist create "Tech Leaders"

Delete a watchlist

etoro-cli watchlist delete abc123

Add instruments to a watchlist

# Add instruments by ID (look up IDs first with: etoro-cli market search <name>)
etoro-cli watchlist add-items abc123 <id1>,<id2>,<id3>

Remove instruments from a watchlist

etoro-cli watchlist remove-items abc123 <id1>,<id2>

Feeds

Read instrument feed

Get social posts about a specific instrument.

# Default: 20 posts
etoro-cli feed instrument 1

# Custom pagination
etoro-cli feed instrument 1 --take 50 --offset 20

Read user feed

Get social posts from a specific user.

etoro-cli feed user 12345 --take 10

Create a post

etoro-cli feed post --message "Bullish on tech this quarter!" --owner 12345

Discovery

Curated investment lists

etoro-cli discovery curated

Personalized recommendations

# Default: 10 recommendations
etoro-cli discovery recommendations

# Custom count
etoro-cli discovery recommendations --count 25

Scripting examples

The CLI outputs JSON, making it easy to use with jq and in scripts:

# Get Apple's current price
etoro-cli market rates 1 | jq '.[0].Ask'

# List instrument IDs from search
etoro-cli market search BTC | jq '.items[].instrumentId'

# Get total P&L
etoro-cli portfolio pnl | jq '.TotalPnL'

# Find Popular Investors with >20% yearly gain (using jq filtering)
etoro-cli social search --period CurrYear --popular-investor --page-size 50 | \
  jq '.items[] | select(.gain > 20) | {userName, gain, riskScore}'

MCP Server Setup

The MCP server exposes the same eToro API capabilities as 18 MCP tools, accessible from any MCP-compatible client. The server communicates via stdio transport.

Claude Desktop

Edit your config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "etoro": {
      "command": "node",
      "args": ["/absolute/path/to/etoro-agent/dist/index.js"],
      "env": {
        "ETORO_API_KEY": "your-api-key",
        "ETORO_USER_KEY": "your-user-key",
        "ETORO_ENVIRONMENT": "demo"
      }
    }
  }
}

Restart Claude Desktop after saving.

Claude Code

Add via CLI:

claude mcp add etoro \
  -e ETORO_API_KEY=your-api-key \
  -e ETORO_USER_KEY=your-user-key \
  -e ETORO_ENVIRONMENT=demo \
  -- node /absolute/path/to/etoro-agent/dist/index.js

Or add to ~/.claude.json manually:

{
  "mcpServers": {
    "etoro": {
      "command": "node",
      "args": ["/absolute/path/to/etoro-agent/dist/index.js"],
      "env": {
        "ETORO_API_KEY": "your-api-key",
        "ETORO_USER_KEY": "your-user-key",
        "ETORO_ENVIRONMENT": "demo"
      }
    }
  }
}

Verify with claude mcp list.

OpenClaw

Via CLI:

openclaw mcp set etoro '{"command":"node","args":["/absolute/path/to/etoro-agent/dist/index.js"],"env":{"ETORO_API_KEY":"your-api-key","ETORO_USER_KEY":"your-user-key","ETORO_ENVIRONMENT":"demo"}}'

Or add to your OpenClaw config under mcp.servers:

{
  "mcp": {
    "servers": {
      "etoro": {
        "command": "node",
        "args": ["/absolute/path/to/etoro-agent/dist/index.js"],
        "env": {
          "ETORO_API_KEY": "your-api-key",
          "ETORO_USER_KEY": "your-user-key",
          "ETORO_ENVIRONMENT": "demo"
        }
      }
    }
  }
}

Verify with openclaw mcp list.

Cursor

Create .cursor/mcp.json in your workspace root:

{
  "mcpServers": {
    "etoro": {
      "command": "node",
      "args": ["/absolute/path/to/etoro-agent/dist/index.js"],
      "env": {
        "ETORO_API_KEY": "your-api-key",
        "ETORO_USER_KEY": "your-user-key",
        "ETORO_ENVIRONMENT": "demo"
      }
    }
  }
}

Windsurf

Edit ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "etoro": {
      "command": "node",
      "args": ["/absolute/path/to/etoro-agent/dist/index.js"],
      "env": {
        "ETORO_API_KEY": "your-api-key",
        "ETORO_USER_KEY": "your-user-key",
        "ETORO_ENVIRONMENT": "demo"
      }
    }
  }
}

Dual Environment (Demo + Real)

Configure two server instances to access both environments simultaneously. This works with any MCP client:

{
  "mcpServers": {
    "etoro-demo": {
      "command": "node",
      "args": ["/absolute/path/to/etoro-agent/dist/index.js"],
      "env": {
        "ETORO_API_KEY": "demo-api-key",
        "ETORO_USER_KEY": "demo-user-key",
        "ETORO_ENVIRONMENT": "demo"
      }
    },
    "etoro-real": {
      "command": "node",
      "args": ["/absolute/path/to/etoro-agent/dist/index.js"],
      "env": {
        "ETORO_API_KEY": "real-api-key",
        "ETORO_USER_KEY": "real-user-key",
        "ETORO_ENVIRONMENT": "real"
      }
    }
  }
}

Example MCP conversations

Once connected, you can ask your AI assistant things like:

  • "Search for Apple stock and show me the current price"
  • "Buy $500 of Tesla with 1x leverage on my demo account"
  • "Show my portfolio and calculate my total P&L"
  • "Find the top popular investors this year with low risk scores"
  • "Create a watchlist called 'Tech Leaders' and add AAPL, MSFT, GOOGL"
  • "Show me 1-hour candles for Bitcoin over the last 24 hours"
  • "Close my Tesla position"
  • "What limit orders do I have open?"

MCP Tools Reference

| Tool | Description | Parameters | |------|-------------|------------| | get_identity | Get authenticated user's account info | — | | search_instruments | Search instruments by symbol or name | query, filterBy (symbol/name), page, pageSize | | get_instruments | Get instrument metadata by ID | instrumentIds (comma-separated) | | get_rates | Get current prices or closing prices | instrumentIds, type (current/closing_price), includeNames (opt-in) | | get_candles | Get OHLC candle data | instrumentId, interval, count, direction | | get_reference_data | Get instrument types, exchanges, or industries | type, ids (optional filter) | | get_market_status | Check if instruments are currently tradeable | symbols (comma-separated, e.g. "AAPL,BTC") | | open_order | Open a market order | order_type (by_amount/by_units), InstrumentID, IsBuy, Leverage, Amount/AmountInUnits | | close_position | Close an open position | positionId, UnitsToDeduct (optional partial close) | | manage_order | Cancel or place limit orders | action (cancel_open_order/cancel_close_order/place_limit_order/cancel_limit_order), orderId, order params | | get_portfolio | View positions, P&L, or order status | view (positions/pnl/order), orderId | | get_trade_history | Get closed trade history | minDate (YYYY-MM-DD), page, pageSize | | search_people | Search/discover traders | action (search/lookup), period, filters | | get_user_info | Get user portfolio, gain, trade info | view (portfolio/tradeinfo/gain/daily_gain/copiers), username | | manage_watchlists | Full watchlist CRUD | action (list/get/create/delete/rename/add_items/remove_items/...), params per action | | get_discovery | Curated lists or recommendations | type (curated_lists/recommendations), count | | get_feeds | Read instrument or user feeds | type (instrument/user), id, take, offset | | create_post | Create a post or comment | action (post/comment), message, owner/postId | | manage_agent_portfolios | Agent portfolio CRUD + tokens | action (list/create/delete/create_token/revoke_token/update_token), params per action |


Demo vs Real

eToro API keys are environment-specific — you choose Demo or Real when generating keys. The server uses different API paths based on your configured environment:

| Category | Demo Path | Real Path | |----------|-----------|-----------| | Trading execution | /trading/execution/demo/... | /trading/execution/... | | Portfolio | /trading/info/demo/portfolio | /trading/info/portfolio | | P&L | /trading/info/demo/pnl | /trading/info/real/pnl | | Order info | /trading/info/demo/orders/{id} | /trading/info/real/orders/{id} |

Market data, social, watchlists, feeds, and discovery endpoints are shared — they work the same regardless of environment.

If there's a key/environment mismatch (e.g., a demo key with --environment real), the eToro API returns an authentication error. The server never blocks requests — it routes to the configured paths and passes through whatever eToro returns.

Rate Limits

The eToro API enforces rate limits on a rolling 1-minute window:

| Limit | Operations | |-------|-----------| | 60 req/min | GET — market data, portfolio queries, social, watchlist reads | | 20 req/min | Write — trade execution, watchlist mutations, posts |

The client proactively tracks request timestamps and waits when a bucket is full. If the server still returns HTTP 429, it retries with exponential backoff (max 3 retries).

Reference data (instrument types, exchanges, industries) is cached for 24 hours to conserve rate limit quota.

Error Handling

CLI errors

Errors are written to stderr as JSON with a non-zero exit code:

{
  "error": "HTTP 401: Unauthorized",
  "statusCode": 401,
  "errorCode": "Unauthorized",
  "body": {
    "errorCode": "Unauthorized",
    "errorMessage": "Unauthorized"
  }
}

MCP errors

MCP tool handlers never throw. On failure, they return { isError: true, content: [{ type: "text", text: "error message" }] }, allowing the AI assistant to handle the error gracefully.

Common errors

| Status | Meaning | Resolution | |--------|---------|------------| | 401 | Invalid or expired API keys | Regenerate keys in eToro Settings | | 403 | Insufficient permissions | Ensure key has Read+Write for trading | | 429 | Rate limit exceeded | Wait and retry (automatic) | | 400 | Invalid request parameters | Check parameter values and types |

Development

npm run build          # Compile TypeScript (MCP + CLI)
npm run dev            # Run MCP server with hot-reload
npm run cli            # Run CLI with hot-reload (tsx)
npm test               # Run unit tests
npm run test:watch     # Run tests in watch mode
npm run test:coverage  # Run tests with coverage report
npm run test:integration  # Run integration tests (requires .env)
npm run lint           # Run ESLint

Run a single test file:

npx vitest run tests/unit/utils/cache.test.ts

Integration tests

Copy .env.example to .env, fill in your API keys, and run:

cp .env.example .env
# Edit .env with your keys
npm run test:integration

License

MIT