内容
# etoro-mcp
eToro 公共 API 的 MCP 服务器:市场数据、余额、投资组合、交易历史、关注列表、警报、投资者排名、用户统计数据、社交动态,以及在明确选择加入的情况下 — 交易、关注列表/警报修改和社交发布。覆盖范围分为 **工具集**;您只需选择所需的工具集,写入工具除非其开关被启用,否则不会被注册 — 连接到默认配置的客户端无法看到或调用它们。
## 功能
- **设计为优先读取** — 62 个读取工具,涵盖十二个工具集中的十一 个(`社交`工具集仅支持写入);43 个写入工具仅在启用其开关时存在 — 5 个交易工具受 `ETORO_MCP_ENABLE_TRADING` 控制,其他 38 个(关注列表、警报、社交和通知修改)受 `ETORO_MCP_ENABLE_WRITES` 控制。
- **默认演示环境** — 交易工具调用演示端点组,除非设置了 `ETORO_ENV=real`。
- **工具集选择** — 通过 `ETORO_MCP_TOOLSETS` 注册您需要的工具;未知名称会导致启动失败,而不是提供部分工具集。
- **精简响应** — 工具返回投资者操作的字段(价格、单位、盈亏、时间戳),而不是原始 API 转储;列表工具受 `limit` 参数或显式范围参数(`min_date`/`max_date`/`count`)限制。
- **凭证保留在环境中** — 密钥仅在 `x-api-key`/`x-user-key` 头部传输,错误消息不会回显头部或凭证值。
- **速率限制感知** — HTTP 429 响应会被重试一次,遵守 `Retry-After`,重新发送相同的 `x-request-id`,以便重试的订单不会被重复填充。
## 工具集
使用 `ETORO_MCP_TOOLSETS` 选择工具集(逗号分隔;`all` 选择所有工具集)。如果不设置,则会注册交易核心:
| 工具集 | 默认 | 涵盖范围 |
|---|---|---|
| `市场` | ✓ | 仪器搜索和详情、蜡烛图、汇率、收盘价、交易所、仪器类型、股票行业 |
| `账户` | ✓ | 配置文件、余额(汇总、按账户类型、历史)、现金交易 |
| `交易` | ✓ | 投资组合、盈亏、订单状态、资格和成本估算;受控制的订单/仓位写入 |
| `历史` | ✓ | 已关闭交易历史 |
| `关注列表` | ✓ | 自己的/公共/精选的关注列表和推荐;受控制的关注列表修改 |
| `警报` | ✓ | 价格警报;受控制的警报修改 |
| `排名` | | 投资者排名、预设、标签、板块/行业摘要 |
| `用户` | | 用户搜索、配置文件、投资组合、性能和复制者统计数据 |
| `动态` | | 新闻、关注、为您推荐的、仪器和用户动态;帖子和评论 |
| `社交` | | 受控制的发布、评论、回复、反应、投票和媒体上传 |
| `俱乐部` | | eToro 俱乐部仪表盘 |
| `通知` | | 通知;受控制的标记为已读 |
## 工具
### 读取工具(在选择工具集时注册)
| 工具集 | 工具 | 描述 |
|---|---|---|
| `市场` | `搜索仪器` | 按股票代码搜索仪器并返回候选匹配项(包含匹配,因此请验证代码) |
| `市场` | `获取仪器详情` | 显示仪器的详情:名称、代码、类型、交易所 |
| `市场` | `获取蜡烛图` | 某个仪器的 OHLCV 蜡烛图(九个间隔,最多 1000 个柱) |
| `市场` | `获取收盘价` | 每个仪器的最新官方收盘价 |
| `市场` | `获取汇率` | 仪器的实时买卖报价 |
| `市场` | `列出交易所` | 交易所(id 和描述)用于解析 `exchangeId` 值 |
| `市场` | `列出仪器类型` | 仪器类型(股票、加密货币、ETF 等)按 id |
| `市场` | `列出股票行业` | 股票行业(id 和名称)用于解析 `stocksIndustryId` 值 |
| `账户` | `获取配置文件` | 身份验证用户的身份和密钥携带的范围 |
| `账户` | `获取汇总余额` | 用户账户余额的当前汇总 |
| `账户` | `按类型获取余额` | 某一账户类型的每个账户的当前余额 |
| `账户` | `获取余额` | 某个特定账户的当前余额 |
| `账户` | `获取余额历史` | 某段日期范围内的每日余额快照 |
| `账户` | `列出现金交易` | 现金账户交易,最新的页面优先 |
| `交易` | `获取投资组合` | 汇总投资组合:账户总额加上每个仪器的汇总 |
| `交易` | `获取投资组合明细` | 仓位级别的快照:开仓和待处理订单 |
| `交易` | `获取盈亏` | 仓位的快照,显示未实现的盈亏 |
| `交易` | `获取订单` | 按订单 id 或参考 id 查询订单状态 |
| `交易` | `获取平仓信息` | 按订单 id 查询平仓状态 |
| `交易` | `检查交易资格` | 仪器交易规则:杠杆、大小模式、止损/获利边界 |
| `交易` | `获取交易成本估算` | 假设订单的成本估算,而不实际下单 |
| `历史` | `列出交易历史` | 某日期以来的已关闭交易 |
| `关注列表` | `列出关注列表` | 身份验证用户的关注列表及其项目 |
| `关注列表` | `获取关注列表` | 身份验证用户按 id 持有的单个关注列表 |
| `关注列表` | `获取默认关注列表` | 身份验证用户的默认关注列表项目 |
| `关注列表` | `获取公共关注列表` | 另一个用户按其数字用户 id 的公共关注列表 |
| `关注列表` | `获取精选列表` | eToro 提供的投资列表,可供用户使用 |
| `关注列表` | `获取市场推荐` | 身份验证用户的个性化市场推荐 |
| `警报` | `列出价格警报` | 账户上的活跃价格警报 |
| `排名` | `列出排名预设` | 所有公开可用的排名预设的名称 |
| `排名` | `按预设获取排名` | 命名预设的投资者排名行 |
| `排名` | `获取投资者排名` | 过滤、排序的投资者排名行页面 |
| `排名` | `获取投资者排名行` | 单个投资者的完整排名行 |
| `排名` | `批量排名行` | 一次调用多个投资者的排名行 |
| `排名` | `列出排名标签` | 具有解析名称的排名标签目录 |
| `排名` | `按板块获取排名宇宙` | 按板块或行业聚合的排名宇宙 |
| `用户` | `搜索用户` | 具有性能和风险过滤器的公共投资者搜索 |
| `用户` | `获取用户配置文件` | 一个或多个用户的公共配置文件和账户摘要 |
| `用户` | `获取用户投资组合` | 用户的实时公共投资组合:开仓和复制交易 |
| `用户` | `获取用户性能` | 用户的完整每月和每年收益历史 |
| `用户` | `获取用户每日性能` | 用户在某段日期范围内的每日或汇总收益 |
| `用户` | `获取用户交易信息` | 用户在某个期间的交易统计数据(复制交易尽职调查) |
| `用户` | `获取收益时间序列` | 投资者的收益时间序列,按每日、每月或每年分辨率 |
| `用户` | `获取资产配置历史` | 投资组合随时间变化的每日资产配置明细 |
| `用户` | `获取市场暴露历史` | 投资组合随时间变化的每日定向市场暴露,按仪器 |
| `用户` | `获取复制者统计数据` | 投资者的实时复制者数量和资产管理层级 |
| `用户` | `获取复制者信息` | 复制您投资组合的人员的匿名信息 |
| `用户` | `搜索投资组合` | 按自由文本搜索交易者投资组合或智能投资组合 |
| `用户` | `获取热门资产` | 用户按基于印象的评分排名的热门资产 |
| `动态` | `获取新闻动态` | eToro 新闻动态(编辑和市场新闻帖子) |
| `动态` | `获取关注动态` | 关注的用户发布的内容 |
| `动态` | `获取为您推荐的动态` | 身份验证用户的个性化为您推荐的动态 |
| `动态` | `获取仪器动态` | 某个仪器的讨论动态(市场) |
| `动态` | `获取用户动态` | 某个用户发布的内容 |
| `动态` | `获取保存的动态` | 身份验证用户保存的内容 |
| `动态` | `获取固定帖子` | 用户固定在其配置文件中的帖子 |
| `动态` | `获取帖子` | 按 UUID 获取单个帖子,附带内联评论预览 |
| `动态` | `列出帖子评论` | 帖子的顶级评论 |
| `动态` | `列出评论回复` | 嵌套在评论下的回复 |
| `动态` | `列出帖子分享` | 分享帖子的人员(纯粹的分享和引用分享) |
| `俱乐部` | `获取俱乐部仪表盘` | 身份验证用户的 eToro 俱乐部仪表盘 |
| `通知` | `列出通知` | 账户的应用内通知,最新的数据优先 |
### 交易写入工具(仅在设置 `ETORO_MCP_ENABLE_TRADING` 时注册)
| 工具集 | 工具 | 描述 |
|---|---|---|
| `交易` | `创建订单` | 下单开仓 — **不幂等**:每次调用都下新订单 |
| `交易` | `取消订单` | 取消待处理(尚未执行)的订单 |
| `交易` | `平仓` | 在市场上完全或部分平仓 |
| `交易` | `取消平仓订单` | 在执行前取消待处理的平仓订单 |
| `交易` | `修改仓位止损/获利` | 编辑开仓的止损和/或获利 |
### 其他写入工具(仅在设置 `ETORO_MCP_ENABLE_WRITES` 时注册)
| 工具集 | 工具 | 描述 |
|---|---|---|
| `关注列表` | `创建关注列表` | 创建新的关注列表 |
| `关注列表` | `重命名关注列表` | 重命名关注列表 |
| `关注列表` | `删除关注列表` | 删除关注列表 |
| `关注列表` | `添加关注列表项目` | 向关注列表添加项目 |
| `关注列表` | `删除关注列表项目` | 从关注列表中删除项目 |
| `关注列表` | `更新关注列表项目` | 在关注列表中重新排序项目 |
| `关注列表` | `设置默认关注列表` | 将关注列表设为选定的默认关注列表 |
| `关注列表` | `更改关注列表排名` | 更改关注列表的显示位置 |
| `警报` | `创建价格警报` | 在仪器上创建价格警报 |
| `警报` | `更新价格警报` | 更改现有价格警报的目标价格 |
| `警报` | `删除价格警报` | 永久删除价格警报 |
| `通知` | `标记通知为已读` | 将所有应用内通知标记为已读 |
| `社交` | `创建帖子` | 在身份验证用户的动态中创建讨论帖 |
| `社交` | `创建投票帖` | 创建带有 2 到 4 个答案选项的投票帖 |
| `社交` | `更新帖子` | 原地编辑身份验证用户自己的帖子 |
| `社交` | `删除帖子` | 软删除身份验证用户自己的帖子 |
| `社交` | `固定帖子` | 将身份验证用户自己的帖子固定在其配置文件中 |
| `社交` | `取消固定帖子` | 从帖子中删除身份验证用户的固定 |
| `社交` | `创建评论` | 在帖子上创建顶级评论 |
| `社交` | `更新评论` | 原地编辑身份验证用户自己的评论 |
| `社交` | `删除评论` | 软删除身份验证用户自己的评论 |
| `社交` | `创建回复` | 在现有评论下创建回复 |
| `社交` | `更新回复` | 原地编辑身份验证用户自己的回复 |
| `社交` | `删除回复` | 软删除身份验证用户自己的回复 |
| `社交` | `分享帖子` | 分享现有帖子,作为纯分享或引用分享 |
| `社交` | `上传媒体` | 上传 JPEG 或 PNG 图片(最大 8 MB)以用作附件;需要 `ETORO_MCP_UPLOAD_DIR` 并仅读取其中 |
| `社交` | `点赞帖子` | 点赞帖子 |
| `社交` | `取消点赞帖子` | 从帖子中删除点赞 |
| `社交` | `点赞评论` | 点赞帖子上的评论 |
| `社交` | `取消点赞评论` | 从评论中删除点赞 |
| `社交` | `点赞回复` | 点赞回复(评论的嵌套答案) |
| `社交` | `取消点赞回复` | 从回复中删除点赞 |
| `社交` | `保存帖子` | 将帖子加入书签 |
| `社交` | `取消保存帖子` | 从已保存的书签中删除帖子 |
| `社交` | `关注帖子` | 订阅帖子的通知 |
| `社交` | `取消关注帖子` | 取消帖子的通知订阅 |
| `社交` | `投票投票` | 对投票选项进行投票 |
| `社交` | `删除投票` | 删除投票选项的投票 |
## 配置
所有配置均来自环境变量 — 无需配置文件,无需携带机密的标志。
| 变量 | 默认值 | 用途 |
|---|---|---|
| `ETORO_API_KEY` | —(必填) | eToro API 密钥,作为 `x-api-key` 头部发送 |
| `ETORO_USER_KEY` | —(必填) | eToro 用户密钥,作为 `x-user-key` 头部发送 |
| `ETORO_ENV` | `demo` | `demo` 或 `real` — 工具调用的交易端点组。eToro 密钥绑定到环境,因此不匹配的密钥在 API 处失败 |
| `ETORO_MCP_TOOLSETS` | 交易核心(参见上表) | 用逗号分隔的工具集名称;`all` 选择所有工具集。未知名称会导致启动失败,并附带有效的名称列表 |
| `ETORO_MCP_ENABLE_TRADING` | 关闭 | `true`/`1`/`yes` 注册交易写入工具:订单下达/取消,仓位关闭,止损/获利编辑 |
| `ETORO_MCP_ENABLE_WRITES` | 关闭 | `true`/`1`/`yes` 注册所有其他写入工具:关注列表/警报修改,通知标记为已读,社交发布和反应 |
| `ETORO_MCP_UPLOAD_DIR` | —(未设置) | `upload_media` 可以从中读取图像的 **唯一** 目录。未设置(默认)使 `upload_media` 未注册,因此服务器永远无法读取本地文件。解析为目录外部的路径和符号链接被拒绝 |
## 入门
使用 [uv](https://docs.astral.sh/uv/) 直接从存储库运行:
```sh
uvx --from git+https://github.com/florinel-chis/etoro-mcp etoro-mcp
```
服务器默认通过 stdio 通信;传递 `--transport http --host 127.0.0.1 --port 8000` 以服务可流式传输的 HTTP,路径为 `/mcp`。
> **警告:** HTTP 端点 **无身份验证** — 任何可以访问端口的人都可以使用您的 API 密钥特权调用每个已注册的工具。因此,服务器 **拒绝绑定非环回 `--host` 除非还传递 `--allow-remote`**;仅在身份验证的反向代理或以其他方式受限的网络(例如下面的 Docker 端口映射)后面使用该标志。
### MCP 客户端配置
将服务器添加到您的 MCP 客户端配置中(确切的文件位置取决于客户端):
```json
{
"mcpServers": {
"etoro": {
"command": "uvx",
"args": ["--from", "git+https://github.com/florinel-chis/etoro-mcp", "etoro-mcp"],
"env": {
"ETORO_API_KEY": "your-api-key",
"ETORO_USER_KEY": "your-user-key",
"ETORO_ENV": "demo"
}
}
}
}
```
或运行 Docker 镜像(首先构建它,参见下文):
```json
{
"mcpServers": {
"etoro": {
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "ETORO_API_KEY", "-e", "ETORO_USER_KEY", "-e", "ETORO_ENV", "etoro-mcp"],
"env": {
"ETORO_API_KEY": "your-api-key",
"ETORO_USER_KEY": "your-user-key",
"ETORO_ENV": "demo"
}
}
}
}
```
## Docker
```sh
docker build -t etoro-mcp .
# stdio(适用于 MCP 客户端配置)
docker run -i --rm -e ETORO_API_KEY -e ETORO_USER_KEY etoro-mcp
# 在 http://127.0.0.1:8000/mcp 进行流式 HTTP 访问
# (-p 127.0.0.1:8000:8000 保持未经身份验证的端点远离外部接口;
# --host 0.0.0.0 指代容器内的接口,并且是必需的,以便端口映射生效,因此 --allow-remote — 主机侧绑定保持环回连接)
docker run --rm -p 127.0.0.1:8000:8000 -e ETORO_API_KEY -e ETORO_USER_KEY \
etoro-mcp --transport http --host 0.0.0.0 --port 8000 --allow-remote
```
## 安全
- 交易工具在设置 `ETORO_ENV=real` 之前调用 **演示** 端点组。密钥绑定到环境,因此演示密钥在实时环境中(或反之亦然)会在 API 处失败,而不是交易错误的账户。
- 写入工具隐藏在 **两个独立的门后** — `ETORO_MCP_ENABLE_TRADING` 用于订单/仓位写入,`ETORO_MCP_ENABLE_WRITES` 用于其他所有内容(关注列表、警报、通知、社交)。受控工具永远不会被注册,MCP 客户端无法发现或调用它们。
- HTTP 传输 **未经身份验证**:任何可以访问端口的人都可以使用您的 API 密钥特权调用每个已注册的工具 — 读取余额和仓位始终如此,并在启用交易时下单或平仓 — 使用您的 API 密钥。服务器在未传递 `--allow-remote` 时拒绝非环回绑定;仅在身份验证的代理或以其他方式受限的网络后面使用该标志(stdio 传输没有此类暴露)。
- `upload_media` 读取本地 JPEG/PNG 文件并返回它们的 **公共 CDN URL** — 一个额外的权限类,超出 API 密钥本身。它因此具有三重门控:社交工具集、`ETORO_MCP_ENABLE_WRITES` 和 `ETORO_MCP_UPLOAD_DIR` 必须全部设置,并且它只在该目录内读取(解析到目录外部的路径和符号链接被拒绝,文件内容必须是 JPEG/PNG,并且在读取之前检查 8 MB 限制)。
- `create_order` **在调用之间不幂等**:每个调用都会生成一个新的 `x-request-id`,这是订单的幂等密钥,因此调用两次会下两个订单。(429 重试会发送相同的 ID,因此重试的速率限制不会重复填充。)在将订单视为已填充之前,请使用 `get_order` 轮询填充状态 — 已接受的订单仍可能被拒绝。
- 蜡烛历史记录上限约为 **每间隔 1000 个柱**,无法进一步分页;使用较粗的间隔(例如 `OneWeek`)获取更深的历史记录。
- API 强制执行 **每组速率配额**(订单执行 20 请求/60 秒;市场数据 120/60 秒;投资组合和其他大多数组 60/60 秒;资格和成本估算 20/60 秒)。每个工具的描述都指出了其配额;429 错误会重试一次,遵守 `Retry-After`。
- 交易杠杆产品存在风险。请自担风险,并在测试模拟账户之前测试所有内容。
## 开发
```sh
uv sync
uv run pytest
uv run ruff check .
```
测试是密封的:所有 HTTP 请求都使用 respx 进行模拟,服务器通过内存 FastMCP 客户端进行测试。无需凭证或网络访问即可运行它们。`scripts/smoke.py` 中有一个手动的只读烟雾检查,针对真实的演示账户。
## 许可证
MIT — 参见 [LICENSE](LICENSE)。