Metadata-Version: 2.5
Name: bizonquant-mcp
Version: 0.10.0
Summary: BizonQuant MCP server —— 把量化能力面（行情/多因子选股/回测）开放给外部 agent
License: MIT
Requires-Python: >=3.11
Requires-Dist: httpx>=0.27
Requires-Dist: mcp<3,>=2.1
Description-Content-Type: text/markdown

# bizonquant-mcp

BizonQuant 量化平台的 MCP server（客户端形态）：跑在你本机，把平台能力面开放给外部 agent（Claude Code / Cursor / Codex / 自写 agent），**服务器零常驻进程、不开前端**。

## 能力

当前源码提供 **58 个工具**：行情与因子、异步选股诊断、三类回测、批量试参、结果分档与对比、回测另存策略，以及交易面的盯盘复盘只读查询。组合/轮动可内联试参，子策略仍需本人已保存 ID。

**先调 `get_usage_guide_tool` 读随包指南**，或读取只读 resource `bizonquant://guide`；无需访问私仓。写配置前调 `get_config_template_tool(section=...)`，按需取 config、engine_config、rotation、portfolio、formula、caliber_changes（默认 all）。

<!-- tool-map:start -->
### 账号与日历（3）

| 工具 | 什么时候用 |
|---|---|
| `get_me_tool` | 确认当前账号与凭证能否使用 |
| `get_trading_day_info_tool` | 锚定交易日、相邻交易日与当前交易时段 |
| `get_data_coverage_tool` | 写配置或定回测日期前查数据覆盖与元数据 |

### 行情与个股（10）

| 工具 | 什么时候用 |
|---|---|
| `search_stocks_tool` | 将代码或名称转成规范股票代码 |
| `get_market_overview_tool` | 看主要指数与全市场涨跌宽度 |
| `get_daily_klines_tool` | 看单股日/周/月线和区间趋势，先读价格口径说明 |
| `get_klines_batch_tool` | 选股后一次比较1~30只股票的日线摘要 |
| `get_minute_trend_tool` | 看单只股票当日分时，不能用日线替代 |
| `get_fund_flow_tool` | 补充个股日频资金流，非盘中实时流量 |
| `get_market_snapshot_tool` | 看单股实时名义价、盘口与新鲜度 |
| `get_market_snapshots_tool` | 批量看指定股票、自选或持仓的快照 |
| `get_stock_factor_values_tool` | 核对1~20只股票的行业与实际因子量级 |
| `list_watchlist_tool` | 读取账号自选股清单，增删交桌面端 |

### 因子与选股（7）

| 工具 | 什么时候用 |
|---|---|
| `list_factors_tool` | 找合法因子名、参数和阈值单位 |
| `search_sectors_tool` | 查可填入 sector_filter 的板块 value |
| `preview_universe_tool` | 过滤前检查基础股票池与可见成分 |
| `validate_strategy_config_tool` | 提交前校验选股配置并查看配置提醒 |
| `screen_stocks_tool` | 提交选股并有界等待，返回实际数据日名单或任务 ID |
| `get_screen_job_tool` | 按任务 ID 续查选股进度与结果 |
| `cancel_screen_job_tool` | 取消本人排队选股，运行中不会强停 |

### 策略与模板（7）

| 工具 | 什么时候用 |
|---|---|
| `get_usage_guide_tool` | 首次使用先读硬规则，再按节查工作流与边界 |
| `get_config_template_tool` | 写选股、执行、组合或公式配置前取模板 |
| `list_presets_tool` | 查多因子方案摘要，按 preset_id 取完整配置 |
| `save_preset_tool` | 查重后保存多因子策略及执行参数 |
| `list_my_strategies_tool` | 找本人各类策略、运行状态与错误 |
| `get_strategy_detail_tool` | 核对单个已保存策略完整配置 |
| `save_strategy_from_backtest_tool` | 从完成回测快照另存策略，避免复述配置漂移 |

### 回测提交与批量（5）

| 工具 | 什么时候用 |
|---|---|
| `submit_backtest_tool` | 以完整配置、方案或历史快照提交多因子回测 |
| `submit_backtest_batch_tool` | 公共来源加逐项补丁，自动排队扫描参数 |
| `get_backtest_batch_tool` | 跟进服务端持久批次或本地队列，取进度与榜单 |
| `cancel_backtest_batch_tool` | 服务端取消须确认同时取消已提交回测；本地可只清队列 |
| `cancel_backtest_tool` | 取消本人排队或运行的单条回测，非交易撤单 |

### 回测结果与对比（8）

| 工具 | 什么时候用 |
|---|---|
| `get_backtest_status_tool` | 不等待地查询状态、阶段、进度与队列信息 |
| `wait_backtest_tool` | 有界等待一条回测并取终态诊断 |
| `wait_backtests_tool` | 同一预算等待已有多个 ID，并取候选榜单 |
| `list_backtests_tool` | 找历史结果，按状态/类型筛选或翻页找名称前缀 |
| `get_backtest_result_tool` | 按 summary/curves/trades/orders/config 分档诊断 |
| `get_backtest_logs_tool` | 回测失败或慢时读有时效的日志尾窗 |
| `compare_backtests_tool` | 比较2~8条回测指标，先检查与首条的口径兼容性 |
| `get_benchmark_curve_tool` | 读取区间基准指数收盘序列作研究对照 |

### 组合与轮动（5）

| 工具 | 什么时候用 |
|---|---|
| `list_rotation_indices_tool` | 写条件前查真实可用价格/PE指数与覆盖 |
| `get_rotation_indicator_tool` | 看轮动指标现值、单位与分布后定阈值 |
| `list_composite_strategies_tool` | 查组合/轮动摘要、查重或按 ID 取完整配置 |
| `submit_composite_backtest_tool` | 对已存组合或 kind+config 内联配置试参 |
| `save_composite_strategy_tool` | 满意后保存组合/轮动及组合级执行参数 |

### 盯盘与复盘（13）

| 工具 | 什么时候用 |
|---|---|
| `get_simulation_account_tool` | 看模拟盘资金、持仓及分页 |
| `get_real_account_tool` | 看实盘资金、持仓与通道可用性 |
| `get_ptrade_overview_tool` | 看 PTrade 脚本在线状态、订阅和当日信号 |
| `get_trading_status_tool` | 查托管运行状态、调仓安排、出票与等待原因 |
| `list_hosted_tasks_tool` | 查最近执行任务，判断今天是否调仓或失败 |
| `get_hosted_task_tool` | 查逐票计划、卖出理由与可选任务日志 |
| `list_signal_runs_tool` | 查选股批次，区分成功 empty 与无 run |
| `get_signal_run_signals_tool` | 核对某批次信号、权重、名次与质量标记 |
| `list_orders_tool` | 按模式、创建日期、股票或状态查委托与原因 |
| `list_trades_tool` | 核对实际成交，按返回成交时间自行选日 |
| `get_equity_curve_tool` | 看模拟盘或实盘逐日资产与盈亏曲线 |
| `get_simulation_review_tool` | 查调仓计划、持仓变化、回放、现金账本或成交统计 |
| `list_notifications_tool` | 用近30天通知补充信号、成交、回测与系统告警 |
<!-- tool-map:end -->

> 交易面全部只读：下单/撤单/启停实盘/删方案/删策略/删回测不在能力面内，永远不会开放给 agent。

## 状态与边界

- 本地测试覆盖协议握手、工具调用和模板契约；测试结果以当前 CI/本次执行为准。本地通过不等于真实凭证与线上链路可用。
- 托管 Streamable HTTP、QuantBot/Python MCP 工具单源化、真实凭证 E2E、工具调用审计与更完整用户级限流仍需分别验证或建设。

三类回测共用每用户提交闸，排队+执行上限默认 **3 个**，与桌面端共享。提交429且提示并发上限时先等已有任务。`degraded` 是可取结果的终态，解读时保留质量标志。

日 K 仅查本地数据，不触发外部补数。研究池的特征写入链尚不完整，未接空壳工具。QuantBot 内置工具另有实现。

四条 MCP prompts 提供研究步骤：`design_multifactor_strategy`、`diagnose_backtest`、`design_composite_strategy`、`review_trading_account`；均引用现有工具，交易面只读。

## 批量回测与盯盘复盘

`submit_backtest_batch_tool` 以公共 config/preset_id/base_backtest_id 加1~30个唯一 label 的补丁项试参；组合/轮动可用 kind+config，子策略须已保存 ID。对象深合并，null 删键、数组整体替换；解析失败项 rejected，不发服务端。能力支持时采用服务端持久批次（mode=server），MCP 退出仍继续运行，重启后按 batch_id 查询和取消。max_parallel 默认2、范围1~3，实际在途=min(max_parallel, 用户上限−1)，上限1可占唯一名额、0不设用户闸。24小时未派发项取消，30天清理；每用户5个活跃批次、60个待派发项；单项256KiB、整批2MiB。

保存 batch_id，用 `get_backtest_batch_tool` 等待取榜单；已有多个 ID 用 `wait_backtests_tool`。榜单不代表口径可比，先用 `compare_backtests_tool` 核对，再读结果与质量标记。服务端摘要每次最多补4项，wait_s=0 立即返回，summary_pending=true 时用 wait_s>0 续查补摘要。满意后可从回测另存策略。服务端取消一定同时取消已提交未终态回测：默认 false 只读检查，已终态原样返回，未终态要求确认后传 cancel_submitted=true。

仅能力读取成功但缺字段、或接口404算明确不支持，可回退本地内存编排，返回 mode=local 与 reason=BATCH_UNSUPPORTED；其它4xx（含401/403）、5xx、超时、解析失败均为暂不可读，不回退，保留网关reason/hint，无reason时取detail.code；非429的4xx且源错误retryable=false时仍为false。建批最终BATCH_UNSUPPORTED/accepted=no只在本次新建unsent条目时回退；已有unsent条目遇能力明确不支持可删除并回退。maybe_accepted或墓碑遇能力暂不可读或明确不支持，均为unknown/retryable=false，避免自动重试或本地单发重复受理，须先核对。管理员暂停不得回退。能力成功与404缓存15秒，其它故障不缓存；已知本地/服务端ID查询及取消直接走对应模式。

先按原始输入（name_prefix.strip()）规范化摘要查条目，未命中再按请求体摘要查，命中均复用键与实际前缀。POST前登记键、前缀、首次及最近尝试墙钟时间、首次请求体摘要和项数、label/kind序列；状态unsent或maybe_accepted只升不降。发出后取消、unknown、超时、STORE_UNAVAILABLE、LOCK_TIMEOUT、CONFLICT、回执异常均为maybe_accepted。合法2xx回执（含回放）或锁内复查后的LIMIT_EXCEEDED/accepted=no清除；UNSUPPORTED、PAUSED、ITEM_INVALID、TOO_LARGE且accepted=no只在本次新建且仍unsent时清除，已有条目保留、结论照常返回。删除先比较本次键；非确定结局回写自己的条目。全部解析失败专用BATCH_ALL_REJECTED，列各项错误并写明「本次未发送」；命中前次条目另写「前次同参提交仍未确定，原键已保留」。漂移仍发原键，冲突明确写「原键已建批（本次解析结果与首次不同）」。

仅在结果不确定之后、本MCP进程内、首次尝试23小时内同参重提复用原键，本进程最多保留20条；已成功的批次再提会新建。重试不续期；unsent到期删除，maybe_accepted到期转墓碑，返回unknown/retryable=false，写明「超过23小时，原键可能已过服务端有效期，重提会新建批次，须先核对」。满额先淘汰unsent、再淘汰最老墓碑、最后淘汰最老maybe_accepted；后两类留下仅含输入摘要、请求体摘要、首次时间的最小墓碑，另限50条，保留到进程结束或被淘汰。**先用文本里的候选batch_id调get_backtest_batch_tool核对；list_backtests_tool查不到不能证明未受理（服务端批次可能排队未派发，最长24小时）。宿主重启后勿据空历史重提。**

最终accepted=unknown不回退；解析、能力读取、POST与候选查询共用55秒总预算。候选按首次请求签名的前缀/项数/label和kind序列从第一页匹配，时间窗下界为首次尝试−5分钟，Date头校准时钟，最多核对3个详情；未核验标unverified，已知请求体摘要不同标mismatch、不计入已核验。候选和前缀写入文本，区分查询失败/超时、无匹配和预算不足。确认取消共用40秒预算，重试只用剩余时间；不确定统一unknown/retryable=true：「取消幂等，可用同一batch_id查询或再次确认取消」，因取消不会新建批次而例外允许重试；查询及取消404为no/false。**本地回退批次重启丢未提交项与状态**；已提交任务按历史名称前缀翻页找回。本地默认取消仅清未提交项，true才取消已提交项。

“今天调了吗／为何没调”从运行状态查托管任务与日志；“为什么卖了这只”查任务计划、信号 run、委托备注和实际成交；“分红到账了吗”查模拟盘现金账本。`get_simulation_review_tool` 还支持调仓计划、持仓变化、指定日回放和成交统计；各有历史窗口，空页不等于从未发生。批量快照可看自选/持仓新鲜度。**部署、启动、停止托管必须由用户在桌面端操作。**

## 安装与运行

0.10.0 服务端批次能力需先上线 P1-5 后端，再由协调者发布包；旧后端仍支持本地回退。本次源码升级不执行发版。

### 0.10.0 变更

- 三件批量工具优先薄调用服务端批次，旧后端保留本地回退；工具名、参数名与58件工具总数不变，托管工具集不变。与0.9.0相比，提交、未知batch_id查询及取消都会读能力；成功与404缓存15秒，命中不再请求，暂不可读不缓存；已知本地/服务端批次查询与取消不增加读取。
- 本地回退返回新增mode/reason；能力暂不可读不再回退本地。解析、能力读取、POST和候选查询新增55秒总时限。
- 建批复用P1-10自动键与同键重试；仅结果不确定后、本MCP进程内、首次尝试23小时内、最多20条同参复用，成功后再提会新建；到期和淘汰用墓碑防静默新建。先核对候选batch_id，历史为空不能证明未受理（可能排队24小时）。暂停不回退，取消需显式确认并受40秒总预算约束。stdio自动带键；托管版提交工具可传idempotency_key。
- 查询兼容榜单形状；服务端模式items[].state改用服务端状态名，degraded改看run_status/degraded，uncertain是非终态。新增暂停原因、计数及摘要待补标记；解析拒绝项与配置提示仅在本进程缓存最近20批。

### 0.9.0 变更

- 三类回测及三个保存入口自动使用随机幂等键，批量每项持续复用同一键。ConnectError / ConnectTimeout / PoolTimeout / ProxyError 表示请求未发出，返回 `accepted=no/retryable=true`，单发可同键退避重试两次、批量继续排队，不依赖能力探测。
- ReadError / ReadTimeout / WriteError / WriteTimeout / RemoteProtocolError，以及无语义字段的网关 502/504 表示结果不确定；仅当 `research_writes.idempotency_key` 严格为 true 时，单次调用内同键重试一次。语义不确定错误（入队/保存结局未知、仍在处理、已换代）不在单次调用内重发；最终 `accepted=unknown/retryable=false` 时先查状态或历史，勿再次调用提交/保存工具。成功回放输出 `replayed:true`。
- 批量不确定项保持 pending 并占名额，退避后确认能力才同键重试；能力暂不可读时只重新探测，不盲目重发，最多 20 次后标 unknown。候选 ID 跟随最新不确定回执，取消只针对当前候选。`IDEMPOTENCY_STORE_UNAVAILABLE` 在单次预算内同键按 1、2、4 秒退避（服务端等待下限超过4秒时直接返回可重试错误，交给队列退避），最多重试 3 次；配额禁用不重试。
- 错误输出保留 `isError` 和结构化 reason/accepted/retryable/context；`retryable=false` 时不提示等待秒数，retry_after 为 null。批量行的 `error` 仍是人读字符串（无错误时省略），结构化字段放 `error_info`（dict 或 null），失败终态的 message 给最终失败原因；区分并发限制、配额禁用、保存结果不确定及选股 expired。
- 保存映射 `overwrite` 到 `on_conflict`，确认后端能力后使用原子 reject；旧后端保留先查后写和执行参数继承。
- 包重构为传输、身份与 `ClientState` 分层；测试与锁文件为 2.3.0，依赖范围 `mcp>=2.1,<3`。`BIZONQUANT_TOOLSETS` 可选择工具组，默认仍为 58 个工具；批量仍由客户端调度。

0.8.0 的分档权限与停用原因提示需配套 P0-b 后端，先升级后端，再按 P0-c 发布 MCP 与 PWA，之后切换新建 key 默认为研究档。旧后端 whoami 返回 404 时自动回落旧身份接口并剔除邮箱；403 不回落。权限隔离由后端执行。

```bash
# PyPI 安装，无需 clone；新增接口需要配套后端更新
uvx bizonquant-mcp@latest init     # 录入 key 并自检（写入 ~/.config/bizonquant-mcp/config.json，0600）
uvx bizonquant-mcp@latest doctor   # 探链路：health / token / whoami / 数据面

# 从源码运行
cd mcp-server && uv sync
uv run bizonquant-mcp doctor
```

## 接入 Claude Code（stdio）

```jsonc
// ~/.claude.json 的 mcpServers —— uvx 形态（推荐，无需本机有仓库）
"bizonquant": {
  "command": "uvx",
  "args": ["bizonquant-mcp@latest"],
  "env": {
    "BIZONQUANT_ACCESS_KEY": "bq_live_xxx",
    "BIZONQUANT_SECRET_KEY": "sk_yyy",
    "BIZONQUANT_BASE_URL": "https://bizon.naiyu.xyz:8443"
  }
}

// 仓库形态（开发调试用）
// "command": "uv", "args": ["--directory", "<仓库路径>/mcp-server", "run", "bizonquant-mcp"]
```

也支持单变量 `BIZONQUANT_API_KEY=access_key.secret_key`。

| 环境变量 | 含义 |
|---|---|
| `BIZONQUANT_TOOLSETS` | 可选，逗号分隔工具组：`market`、`market_realtime`、`research`、`backtest`、`batch`、`strategy_write`、`account`、`signal`。未设置时注册全部 58 个工具；例如 `research,backtest`。去除空白与重复项，区分大小写；设置为空或含未知组名时启动失败。仅过滤工具，指南资源、4 个 prompt 与 instructions 保持不变。 |

环境变量凭证缺失时，服务端会读取 `init` 写入的配置文件：默认 `~/.config/bizonquant-mcp/config.json`，可用 `BIZONQUANT_CONFIG` 指定路径（空字符串仍用默认路径）。环境变量优先，缺项从配置文件补齐；base_url 也优先取环境变量，再取文件，最后取内置地址。不要把 secret 放进命令行或提交进仓库。

## 宿主超时与网络环境

宿主可能在工具返回前超时，MCP 的 HTTP 超时和宿主工具超时是两层限制。单条/多条等待默认总预算50秒，`BIZONQUANT_WAIT_BUDGET_S` 可调整默认值（最大600秒），显式 max_wait_s 优先；批次查询的 wait_s 默认50秒，实际取 wait_s、环境预算、600秒三者最小值，0为立即返回。放宽前也要调整宿主允许的工具时长，或保持短等待并续调。

选股提交后台任务，一次工具调用最多等待50秒；未完成返回 `job_id`，用 `get_screen_job_tool` 续查。同账号、同数据版本、相同请求会复用任务；终态最多保存15分钟：单账号超过16条记录或全局容量满时可能提前回收，engine重启也会丢失；返回404后原参数重新提交。旧同步 `/screen` 的55秒预算与 `BIZONQUANT_SCREEN_TIMEOUT_S` 仅供兼容路径使用。回测提交超时先按名称查历史，不能据超时断言未提交。指标预览 HTTP 超时120秒，宿主可能更早结束。

默认沿用系统代理环境；`BIZONQUANT_TRUST_ENV=0` 让 httpx 不读取环境代理等配置，适用于系统代理不可用或协议不支持的情况。它不改变网关地址、凭证权限或 HTTPS 校验要求。

## 拿凭证

在桌面端设置 → 账号安全 → Agent 接入创建 key；默认研究档 `mcp.research`，按需勾选账户读取 `mcp.account` 或策略写入 `mcp.strategy_write`。secret 只展示一次，可复制配置片段。平台分阶段切换新建 key 的默认值，过渡期间以设置页与 `get_me_tool` 返回为准。

存量 `mcp.*` / `mcp.read` / `mcp.write` 为 legacy 档，保留既有能力；可以收紧为分档权限，不能回升为 legacy。`doctor` 会显示权限档位并提示 legacy key 可收紧；连旧后端时提示先升级后端。平台暂停接入和本账号停用分别提示管理员联系路径与设置页启用路径，不要因此轮换 key。

**一个宿主一把 key**：即使在同一台电脑，不同宿主进程也应分配独立 Key。

## 客户端纪律（内置，无需配置）

- 默认拒绝 `http://` 明文网关（`BIZONQUANT_ALLOW_INSECURE=1` 可解锁内网场景）
- token 只走 Authorization 头；401 自动换发一次，仍 401 即停（key 撤销后不打风暴）
- UA 带 `bizonquant-mcp/{version}`，服务端可审计

## 安全模型

- 凭证是 API Key（access_key + secret），不是账号密码；按需授权并妥善保管。
- **研究档**：行情、因子、选股、校验、策略研究配置、回测提交/取消/读取/对比；不包含账户读取或保存策略。**账户读取**另行开放账户、持仓、委托、成交、通知、托管任务和信号；**策略写入**另行开放方案/组合/轮动保存与回测另存。两项可选权限相互独立，业务归属鉴权仍生效。
- **不可读**：LLM 配置与凭证、API Key 管理、后台管理。
- **不可做**：任何交易与资金写（含下单、撤单、部署/启停托管）及删除。研究写操作仅限网关白名单，如保存多因子/组合/轮动策略、回测单次或批量提交与取消、完成回测另存策略。已部署策略（托管或实盘运行中、被 PTrade 订阅（含暂停中）、被已部署的组合引用）服务端拒绝 agent 覆盖（409），只能另存新名；覆盖其它同名策略前须征得用户明确同意。
- 删除 Key、停用或轮换 secret 可撤销对应访问；停止本机进程不等于服务端吊销凭证。
- `revoke` 命令 = 同 key 再换发一次（互踢规则下旧会话全灭）；永久吊销请在桌面端删 key

## 开发

```bash
uv run python -m pytest -q  # 全量测试（含网关 scope 与工具路径对拍、真实 stdio）
uv run bizonquant-mcp --version
```

对拍闸：`tests/test_conformance.py` 断言本包工具的 (method, path) ⊆ 网关 `AGENT_WRITE_ALLOWLIST` ∪ GET——网关收窄或工具新增写路径而网关未放行时，测试立即红。

`tests/test_templates.py` 以 AST 双向对拍后端字段与枚举，无需安装后端依赖；`tests/test_guide.py` 断言包内指南与仓库指南逐字节一致，并验证 resource/prompts。
