Metadata-Version: 2.4
Name: smartoption-mcp
Version: 0.4.0
Summary: MCP server exposing the smartoption-ai customer APIs (copy-trading, agent ops, signal history, data center, quant strategy R&D) as tools for AI agents (Claude Desktop / Claude Code / any MCP client).
Author-email: SmartOption <service.smartoption@gmail.com>
License: Proprietary
Project-URL: Homepage, https://github.com/SmartOption/smartoption-ai
Project-URL: Repository, https://github.com/SmartOption/smartoption-ai
Project-URL: Issues, https://github.com/SmartOption/smartoption-ai/issues
Keywords: mcp,smartoption,claude,auto-trade,copy-trading
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: mcp>=1.2.0
Requires-Dist: httpx>=0.27.0

# smartoption-mcp

MCP server exposing smartoption-ai customer APIs as tools for AI agents
(Claude Desktop, Claude Code, any MCP client). **37 tools** spanning
copy-trading rules, agent ops, broker config, signal history, virtual
ledger, quant strategy products, quant strategy R&D, and the data
center (dark-pool / option flow / trader feeds).

## Architecture

```
Claude / Agent
   │  MCP stdio
   ▼
smartoption-mcp  ──HTTP + Bearer JWT──▶  backend  /api/customer/*
```

Thin wrapper: each tool maps to one customer API endpoint, authenticated
with a per-user JWT (or long-lived API token) loaded from env at startup.

## Install

```bash
pip install smartoption-mcp
# or, in an isolated venv:
python3.11 -m venv ~/.smartoption-mcp && ~/.smartoption-mcp/bin/pip install smartoption-mcp
```

Published on [PyPI](https://pypi.org/project/smartoption-mcp/). Installs
the `smartoption-mcp` CLI. Upgrade with `pip install -U smartoption-mcp`.

Local dev from this repo:

```bash
cd mcp-server
python3.11 -m venv .venv && source .venv/bin/activate
pip install -e .
```

## Configure auth

Log into [portal.smartoption.ai](https://portal.smartoption.ai) →
个人中心 → "API Token（用于 MCP / 脚本）" → 起个名字 → 复制 token.
1-year expiry, revocable any time from the same page.

Set:

- `SMARTOPTION_JWT` — the token (no `Bearer ` prefix)
- `SMARTOPTION_API_BASE` — `https://api.smartoption.ai`

Smoke test:

```bash
export SMARTOPTION_API_BASE="https://api.smartoption.ai"
export SMARTOPTION_JWT="eyJ..."
.venv/bin/python -c "from smartoption_mcp.client import SmartoptionClient; \
  print(SmartoptionClient().list_agents())"
```

## Register with Claude Code / Claude Desktop

**Claude Code** — edit `~/.claude.json`, add under `mcpServers`:

```json
{
  "mcpServers": {
    "smartoption": {
      "command": "smartoption-mcp",
      "env": {
        "SMARTOPTION_API_BASE": "https://api.smartoption.ai",
        "SMARTOPTION_JWT": "eyJ..."
      }
    }
  }
}
```

Restart Claude Code. All 37 `smartoption` tools should appear.

**Claude Desktop** — same JSON shape at
`~/Library/Application Support/Claude/claude_desktop_config.json`.
Restart the app after editing.

Once registered, you can ask things like:

- "查一下最近一周苹果相关的喊单"
- "我现在的虚拟仓有哪些标的？"
- "我的跟单 agent 在线吗？最近一次心跳是什么时候？"
- "今天 agent 跑了几条信号，有没有被跳过的？"
- "帮我写一个 MA crossover 策略，先 validate 一遍"
- "解读一下今天 NVDA 的暗盘大单"

## Tools

### Copy-trading rules

| Tool | Endpoint | Purpose |
|---|---|---|
| `list_copy_rules` | `GET /copy-rules` | Current copy-trading rules + toggles |
| `update_copy_rules` | `PUT /copy-rules` | Replace full settings; **confirmed-gated** with structured diff |

### Agent provisioning & ops

| Tool | Endpoint | Purpose |
|---|---|---|
| `ensure_agent` | `POST /agents/ensure` | Create / provision the user's agent pod (idempotent; `force_redeploy` gated) |
| `get_agent_status` | `GET /agents` | Online / heartbeat / broker snapshot summary |
| `get_agent_logs` | `GET /agents/<id>/logs` | Tail recent agent-pod stdout |
| `restart_agent_client` | `POST /agents/<id>/restart-client` | Restart in-pod agent process — **gated** |
| `stop_agent` | `POST /agents/<id>/stop` | Scale agent deployment to 0 — **gated** |

### Broker configuration

| Tool | Endpoint | Purpose |
|---|---|---|
| `list_broker_configurations` | `GET /broker-configurations` | All saved brokers + active flag (no creds returned) |
| `get_active_broker` | `GET /broker-configurations` | Just the active broker name + display name |
| `set_active_broker` | `PUT /active-broker` | Switch active broker — **gated** |
| `test_broker_connection` | `POST /broker-configurations/test-{ib,tiger,futu,moomoo}` | Verify creds against broker; does NOT save |
| `refresh_broker_snapshot` | `POST /broker-account-snapshot/refresh` | Ask agent to push fresh broker snapshot |

### Signal history & run logs

| Tool | Endpoint | Purpose |
|---|---|---|
| `query_signal_history` | `GET /signal-history` | Search parsed alerts (大单 / 喊单) |
| `get_signal_detail` | `GET /signal-history/<id>` | Full SignalForwardRecord for one signal |
| `get_signal_chain` | `GET /signal-history/<id>/chain-slots` | Paired / chained signal context (ROLL_UP pairs etc.) |
| `list_run_logs` | `GET /copy-run-logs` | Per-signal execution outcomes |

### Virtual ledger & followers

| Tool | Endpoint | Purpose |
|---|---|---|
| `list_virtual_lots` | `GET /virtual-ledger` | Open virtual lots + qty_by_key |
| `list_virtual_followers` | `GET /virtual-followers` | User's virtual-follower accounts + equity summary |

### Quant strategy products (copy-trade catalog)

| Tool | Endpoint | Purpose |
|---|---|---|
| `list_quant_strategies` | `GET /quant-strategies/list` | Available / subscribed quant strategies |
| `get_quant_strategy_snapshot` | `GET /quant-strategies/<id>/snapshot` | One strategy's positions + canonical valuation |

### Quant strategy R&D

| Tool | Endpoint | Purpose |
|---|---|---|
| `validate_strategy_code` | `POST /strategy-ai/strategies/validate` | RestrictedPython compile + protocol check (mirrors deploy gate) |
| `create_strategy` | `POST /strategy-ai/strategies` | New draft + dedicated VirtualAccount |
| `list_strategies` | `GET /strategy-ai/strategies` | User's strategies + per-strategy account summary |
| `get_strategy` | `GET /strategy-ai/strategies/<id>` | One strategy's full doc (draft_code, deployed_code, state) |
| `save_strategy_draft` | `POST /strategy-ai/strategies/<id>/save-draft` | Persist editor source; does NOT disturb running runner |
| `run_strategy_backtest` | `POST /strategy-ai/strategies/<id>/backtest` | Submit backtest (queued, returns run_id) |
| `get_backtest_run` | `GET /strategy-ai/strategies/<id>/backtest-runs/<run_id>` | Summary mode (KPI + equity + capped trades + last 5 days' decisions); `mode='full'` or `decisions_for_day=YYYY-MM-DD` for deeper dives |
| `cancel_backtest_run` | `POST /strategy-ai/strategies/<id>/backtest-runs/<run_id>/cancel` | Cooperative cancel |
| `deploy_strategy` | `POST /strategy-ai/strategies/<id>/deploy` | Promote draft → deployed + lift K8s runner pod — **gated** |
| `stop_strategy` | `POST /strategy-ai/strategies/<id>/stop` | Scale runner to 0 — **gated** |

Paired with the `develop-quant-strategy` skill (in `.claude/skills/`),
this lets Claude take a strategy from "natural-language intent" to
"deployed runner" entirely from chat: validate → create → save_draft →
run_backtest → poll `get_backtest_run` → deploy (with dry-run + operator
approval) → observe via `list_quant_strategies` +
`get_quant_strategy_snapshot`. `get_backtest_run` defaults to a
summary mode (≤100KB) tuned for LLM context; raw replay payloads can be
multi-MB.

### Data Center (暗盘大单 / 期权大单 / 交易员)

| Tool | Endpoint | Purpose |
|---|---|---|
| `list_data_center_tags` | `GET /data-center/overview` | Available tags + counts |
| `list_data_center_channels` | `GET /data-center/overview` | Active channels under one tag |
| `list_data_center_messages` | `GET /data-center/messages` | Paged messages with filters |
| `get_data_center_message_detail` | `GET /data-center/messages/<id>` | One message by id |
| `interpret_data_center_message` | `POST /data-center/messages/<id>/interpret` (SSE) | LLM "解读"; stream collected server-side |
| `chat_about_data_center_message` | `POST /data-center/messages/<id>/chat` (SSE) | Per-message free-form chat |
| `list_data_center_message_chat_history` | `GET /data-center/messages/<id>/chat` | Prior chat turns + quota |

## Confirmation model

Destructive writes accept a `confirmed: bool` argument, defaulting to
`False` (dry-run):

- `update_copy_rules(new_settings, confirmed=False)` → returns a
  structured diff (toggle changes + rules added / removed / modified by
  `rule_id`). Nothing is written. Show the diff, then re-call with
  `confirmed=True`.
- `ensure_agent(force_redeploy=True, confirmed=False)` → returns a
  description of the redeploy. Default `force_redeploy=False` is
  idempotent and skips the gate.
- `set_active_broker`, `restart_agent_client`, `stop_agent` — same
  dry-run pattern.
- `deploy_strategy`, `stop_strategy` — same dry-run pattern. Deploy
  also surfaces the current vs target `runtime_symbols` and
  `deployment_state` for the operator preview.
- `refresh_broker_snapshot`, `cancel_backtest_run` — no gate
  (non-destructive / reversible).

The host (Claude Code / Desktop) also shows tool arguments before each
call, so `confirmed=True` is always visible in the approval UI — the
in-tool flag is belt + suspenders.

**Full-doc replacement.** `update_copy_rules` rejects partial settings:
the proposed doc must contain `auto_buy_enabled`, `auto_sell_enabled`,
`use_all_matched_rules`, and `rules`. Start from `list_copy_rules`,
mutate locally, pass the full doc back — preserving every rule's
`rule_id` so the diff stays stable.

## SSE tools

`interpret_data_center_message` and `chat_about_data_center_message`
hit a backend SSE endpoint but collect the full stream and return one
payload:

```
{status, content, duration_ms, event_count}     # interpret
{status, content, duration_ms, event_count,
 remaining_quota}                                # chat
```

`status` ∈ `done` / `cached` / `error` / `quota_exceeded`. Time inputs
(`start_at` / `end_at`) are pass-through ISO 8601 — include timezone
offset (e.g. `-04:00` for ET); the server does not normalize "today" /
"now-7d".

## Roadmap

- **Remote MCP server (OAuth 2.1)** — deferred until a multi-user use
  case justifies the operational cost. Until then, each user runs
  `smartoption-mcp` locally with their own API token.
