内容
# @mgcrea/mcp-tastytrade
适用于 [TastyTrade](https://tastytrade.com) 券商 API 的模型上下文协议服务器。作为 MCP 工具公开账户、余额、仓位、订单、交易、工具、市场指标、观察列表和按需 DXLink 报价快照,供 Claude Desktop、Claude Code 或任何兼容 MCP 的客户端使用。
## 功能
- **OAuth2 个人授权** 认证(client_secret + refresh_token),过期和 401 自动刷新。
- **原生 `fetch`** HTTP 客户端。无 axios,无 `@tastytrade/api` 依赖。
- **TastyTrade dash-case ↔ camelCase** 透明转换。
- **DXLink 报价快照** 通过长寿命 WebSocket — `get_quote(symbol)` 重用连接并缓存最近的值,因此重复查询在 <50ms 内返回,而不是支付 ~3–5s 的认证/设置费用。连接在 `TASTYTRADE_DXLINK_IDLE_TIMEOUT_MS` (默认 30 秒)空闲后关闭,并在下一次调用时重新连接。
- **REST 备用模式** — 设置 `TASTYTRADE_DISABLE_DXLINK=1` 以完全跳过 WebSocket,并通过 Tastytrade REST `/market-data/by-type` 端点路由 `get_quote`、`get_quotes`、`get_chain_with_greeks` 和 `get_position_greeks`。希腊字母(`delta`/`gamma`/…字段)通过 REST 不可用,始终在此模式下为 `null`。`get_expected_move` 抛出明确的错误。在 DXLink 认证损坏或需要无状态部署时很有用。
- **交易是可选的**。变异工具(`place_order`、`cancel_order`、`replace_order`、`create_watchlist`、`update_watchlist`、`delete_watchlist`)仅在 `TASTYTRADE_ALLOW_TRADING=1` 时注册。订单放置工具还需要在调用参数中设置 `confirm: true`;否则,它们将返回一个 dry-run 预览。设置 `TASTYTRADE_DANGEROUSLY_ALLOW_TRADING=1` 以将 `confirm` 默认值翻转为 `true`(自动提交)— 仅在您信任驱动 MCP 的内容时使用。
## 技术栈
- Node 22+,ESM,`pnpm`
- TypeScript(严格,NodeNext,ES2023)
- [`tsdown`](https://tsdown.dev) 用于构建
- [`oxlint`](https://oxc.rs) + [`oxfmt`](https://oxc.rs) 用于 lint/format
- [`vitest`](https://vitest.dev) 用于测试
- [`@modelcontextprotocol/sdk`](https://github.com/modelcontextprotocol/typescript-sdk),[`zod`](https://zod.dev),[`ws`](https://github.com/websockets/ws)
## 安装
```bash
pnpm install
pnpm build
```
## 配置
通过 TastyTrade 开发者门户(https://developer.tastytrade.com/oauth/)提供个人 OAuth 授权,并复制 `.env.example` 到 `.env`:
```
TASTYTRADE_CLIENT_SECRET=...
TASTYTRADE_REFRESH_TOKEN=...
TASTYTRADE_SCOPE=read trade
TASTYTRADE_ENV=prod # 或 "cert" 用于沙盒
TASTYTRADE_ALLOW_TRADING= # "1" 以注册变异工具(仍由每次调用的 confirm:true 控制)
TASTYTRADE_DANGEROUSLY_ALLOW_TRADING= # "1" 还将每次调用的 confirm 默认值翻转为 true(自动提交)
TASTYTRADE_DXLINK_IDLE_TIMEOUT_MS= # 在最后一次报价调用后保持 DXLink WS 打开的时间(默认 30000)
TASTYTRADE_DISABLE_DXLINK= # "1" 以跳过 DXLink 并使用 REST /market-data/by-type(无希腊字母)
```
## 运行
```bash
pnpm start # 通过 stdio 发送 JSON-RPC
```
## 连接到 Claude Code / Claude Desktop
在 `~/.claude.json` (或桌面配置)中:
```json
{
"mcpServers": {
"tastytrade": {
"command": "node",
"args": ["/absolute/path/to/mcp-tastytrade/dist/cli.js"],
"env": {
"TASTYTRADE_CLIENT_SECRET": "...",
"TASTYTRADE_REFRESH_TOKEN": "...",
"TASTYTRADE_SCOPE": "read trade",
"TASTYTRADE_ENV": "prod"
}
}
}
}
```
或,在 `pnpm link --global` 之后:
```json
{ "command": "tastytrade-mcp", "args": [], "env": { "...": "..." } }
```
使用官方检查器检查工具连接:
```bash
npx @modelcontextprotocol/inspector node dist/cli.js
```
## 通过 Docker 运行
一个多阶段的 [Dockerfile](./Dockerfile) 随项目一起提供。CI 在每次推送到 `main` 和 `v*.*.*` 标签时将多架构镜像(`linux/amd64`,`linux/arm64`)发布到 GHCR:
```bash
docker pull ghcr.io/mgcrea/mcp-tastytrade:latest
```
容器运行 `node /app/dist/cli.js` 作为 PID 1,并通过 stdio 发送 JSON-RPC。通过 `-e VAR` (从启动 shell 传递)或 `--env-file` 传递凭证。
`.mcp.json` 用于 Claude Code(项目范围)/ Claude Desktop:
```json
{
"mcpServers": {
"tastytrade": {
"type": "stdio",
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"-e",
"TASTYTRADE_CLIENT_SECRET",
"-e",
"TASTYTRADE_REFRESH_TOKEN",
"-e",
"TASTYTRADE_SCOPE",
"-e",
"TASTYTRADE_ENV",
"-e",
"TASTYTRADE_ALLOW_TRADING",
"ghcr.io/mgcrea/mcp-tastytrade:latest"
],
"env": {
"TASTYTRADE_CLIENT_SECRET": "...",
"TASTYTRADE_REFRESH_TOKEN": "...",
"TASTYTRADE_SCOPE": "read trade openid",
"TASTYTRADE_ENV": "prod"
}
}
}
}
```
注意:
- `-i` 保持 stdin 打开(必需);不要添加 `-t` — Claude Code 在没有 TTY 的情况下启动进程。
- `-e VAR` (无 `=value`)从主机环境中转发值,这是 Claude Code 从上面的 `env` 块设置的。不要在参数中放置机密。
- `--rm` 在每个 MCP 会话后清理容器。
- 省略 `TASTYTRADE_ALLOW_TRADING` (或保持未设置)以不注册订单放置 / 观察列表变异工具。
如果您不想将机密提交到 `.mcp.json`,请将 `--env-file` 指向本地 `.env`:
```json
"args": ["run", "--rm", "-i", "--env-file", "/abs/path/to/.env", "ghcr.io/mgcrea/mcp-tastytrade:latest"]
```
### 本地构建
```bash
pnpm docker:build # 单架构本地镜像
pnpm docker:buildx # 多架构(linux/amd64,linux/arm64)
pnpm docker:release # 多架构 + 推送到 Docker Hub(mgcrea/mcp-tastytrade)
```
构建脚本将 `GIT_COMMIT` / `GIT_COMMIT_DATE` 作为构建参数传递,以便 bundle 包含实际的 git 信息,即使 `.git` 未被复制到构建上下文中。
## 工具
### 只读(始终可用)
| 工具 | 描述 |
| ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `list_accounts` | 客户账户。 |
| `get_account` | 单个账户详情。 |
| `get_customer` | 客户资料。 |
| `get_balances` | 现金 + 保证金余额。 |
| `get_positions` | 开仓 / 平仓。 |
| `get_position_greeks` | 每仓位的希腊字母 + 每底层和投资组合净值总额(带符号数量 × 乘数 × 每合约希腊字母)。 |
| `list_orders`, `get_order` | 订单历史 / 查询。 |
| `get_complex_order` | 获取单个复杂订单(OTOCO/OCO/OTO 括号)及其所有关联的子订单。 |
| `list_transactions`, `get_transaction` | 账户交易。 |
| `search_symbols` | 按前缀搜索符号。 |
| `get_equity`, `get_equity_option`, `get_future`, `get_cryptocurrency` | 工具元数据。 |
| `get_option_chain_summary` | 每到期日的汇总(行权次数,最小/最大行权价)。精简载荷。 |
| `get_option_chain` | 筛选的链切片(按到期日 / 行权价范围 / 类型),每个调用/认购的 flat leg 具有 OCC 和 DXLink 符号。 |
| `get_market_metrics` | IV 排名/百分位,beta,流动性,IV 期限结构。 |
| `get_expected_move` | 在给定到期日下,底层资产的 ATM 跨式预期 ±1σ 移动(现货,ATM 行权价,call/put 中价,跨式,IV 隐含移动)。 |
| `get_chain_with_greeks` | 链切片(默认 ATM±20 行权价)使用引用的报价(bid/ask/mid)+ 每个腿的希腊字母,批量调用。 |
| `find_strikes_by_delta` | 对于每个目标 delta,返回链中实际 delta 最接近的行权价。正值 → call,负值 → put。铁凝乳翼选择器。 |
| `get_earnings_calendar` | 捆绑的 `{symbol, expectedReportDate, timeOfDay, estimatedEarnings}`,适用于一批符号,可选日期过滤器。 |
| `get_diagnostics` | 检查服务器状态 + 最后 ~200 日志行(市场数据提供者模式/状态,OAuth 新鲜度,最近的警告/错误)。使用 self-debug。 |
| `get_dividend_history`, `get_earnings_history` | 公司事件历史。 |
| `list_watchlists`, `get_watchlist`, `list_public_watchlists`, `get_public_watchlist` | 观察列表。 |
| `get_quote` | 单个符号的快照。引用的报价(bid/ask/sizes)+ 希腊字母(DXLink 模式);REST 模式下仅 bid/ask。接受 OCC 或 DXLink 格式。 |
| `get_quotes` | 许多符号的批量快照。DXLink 模式下包含希腊字母,REST 模式下为 null。 |
### 变异(仅当 `TASTYTRADE_ALLOW_TRADING=1`)
| 工具 | 描述 |
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `place_order` | 提交订单。无 `confirm: true`,返回 dry-run 预览。 |
| `cancel_order` | 取消开仓订单。需要 `confirm: true`。 |
| `cancel_all_orders` | 批量取消所有开仓订单(可选 `underlyingSymbol` 过滤器)。无 `confirm: true`,返回将取消的列表。返回 `{cancelled, failed}` 以便在提交时显示每个订单的失败情况。 |
| `replace_order` | 替换开仓订单。无 `confirm: true`,dry-run 替换。 |
| `place_complex_order` | 提交 OTOCO 括号(入口 + 链接的获利 + 止损),OCo 对已有的仓位,或 OTO 链。无 `confirm: true`,返回 dry-run 预览。 |
| `cancel_complex_order` | 取消复杂订单及其所有链接的子订单。需要 `confirm: true`。 |
| `create_watchlist`, `update_watchlist`, `delete_watchlist` | 私有观察列表管理。 |
### 括号订单 / 止损
要将止损(和可选的获利)附加到仓位入口,使用 `place_complex_order`,类型为 `"OTOCO"`。填充或取消一个子订单将取消另一个,因此止损不能在入口填充时被孤立。
```jsonc
// place_complex_order
{
"accountNumber": "5WX12345",
"order": {
"type": "OTOCO",
"triggerOrder": {
"timeInForce": "Day",
"orderType": "Market",
"legs": [
{ "instrumentType": "Equity", "symbol": "SPY", "quantity": 1, "action": "Buy to Open" },
],
},
"orders": [
{
"timeInForce": "GTC",
"orderType": "Limit",
"price": 620,
"priceEffect": "Credit",
"legs": [
{ "instrumentType": "Equity", "symbol": "SPY", "quantity": 1, "action": "Sell to Close" },
],
},
{
"timeInForce": "GTC",
"orderType": "Stop",
"stopTrigger": 540,
"legs": [
{ "instrumentType": "Equity", "symbol": "SPY", "quantity": 1, "action": "Sell to Close" },
],
},
],
},
"confirm": false,
}
```
对于附加到您已持有的仓位的 OCO 对,省略 `triggerOrder` 并使用 `type: "OCO"` 和两个退出订单。
## 开发
```bash
pnpm dev # tsdown --watch
pnpm test # vitest run
pnpm typecheck # tsc --noEmit
pnpm lint # oxlint
pnpm format # oxfmt --write .
```
## 许可证
MIT © Olivier Louvignes
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器