# MCP 研究接入 MCP 让外部助手直接查询数据元信息、查回测历史、提交固定候选、执行本地自相关检查并读取结果。无需先建立特征、模板、变体或 QuantFlow。执行仍由网页共用的持久队列负责,回测页保存同一个运行。 ## 启用与令牌 应用依赖官方 `mcp==2.2.0`,锁文件固定版本。增量迁移 `0010` 增加 `mcp_tokens`、`research_requests` 和 `mcp_audits`,不重写旧业务记录。 默认 `MCP_ENABLED=false`,入口返回 404。需要启用时,在目标部署配置中显式设置为 true,按该环境既有升级流程迁移并重建后端。生产仍限一个后端 worker。入口为 `PUBLIC_ORIGIN/api/v1/mcp/`;无尾斜杠地址会重定向。公网须使用 HTTPS,代理保留原始 Host。现有 Caddy 已保持 Host;Vite 开发代理也显式保持。 本功能不实现 OAuth;客户端必须能够自行配置 `Authorization: Bearer `。PAT 不能作为 Cookie,也不能访问网页管理接口。无需添加 `X-WQ-Request`。若请求包含 Origin,须与 PUBLIC_ORIGIN 一致。 先在网页连接并确认 WorldQuant 账户身份。进入侧栏 **系统管理 → MCP Key**,填写名称、有效期并选择权限,即可创建 Key。默认只读、90 天;创建后明文仅显示一次,关闭、刷新或离开页面后无法找回。列表支持分页查看权限、到期时间和状态,并可撤销 Key。页面同时显示连接地址和 MCP 服务是否启用;管理页面不会自动打开服务开关。 管理接口沿用管理员 Cookie 会话和网页请求保护,MCP PAT 不能创建、查看或撤销 Key。明文不写入浏览器存储,也不传给网页研究助手。 也可在所需环境执行管理命令。以下是命令模板,不会由文档自动执行: ```bash # 默认只读,90 天;--days 支持 1–365。 python -m app.cli mcp-token-create --name research-reader # 需要对应业务权限时显式列出;必须包含 research:read。 python -m app.cli mcp-token-create --name research-executor \ --scope research:read --scope research:refresh \ --scope backtests:execute --scope backtests:control python -m app.cli mcp-token-list python -m app.cli mcp-token-revoke TOKEN_ID ``` 容器中使用相应 Compose 配置的 `exec backend` 执行。签发成功后明文只输出一次,保管在客户端凭据存储中,不放入聊天、仓库或请求 ID。数据库只保存令牌哈希及绑定信息。每次 HTTP 请求重新验证过期、撤销、管理员和平台账户绑定。密码重置同时撤销 PAT;仅撤销 PAT 不会取消已受理的回测。 | 权限 | 可调用能力 | | --- | --- | | research:read | 能力、数据目录、元数据、历史、运行、结果、证据、刷新及自相关任务查询、自相关结果读取 | | research:refresh | 显式更新元数据及 PnL 缓存、发起本地自相关检查;同时要求 read | | backtests:execute | 直接提交固定候选;同时要求 read | | backtests:control | 暂停、继续、停止、恢复采集;同时要求 read | `tools/list` 只显示当前令牌可用的工具,实际调用仍再次验证权限。缺失/失效令牌返回 401,缺权限返回 403。 ## 工具输入与返回 工具 schema 由 `tools/list` 提供,未知参数拒绝。所有业务返回为 `structuredContent`,并保留等价文本 JSON。业务失败置 `isError=true`,error 包含 code、message、retryable、retry_after、affected_items;HTTP 认证错误不伪装为正常工具结果。 | 工具 | 输入要点 | | --- | --- | | get_research_capabilities | `{}`,含单次候选上限及完整候选 schema | | search_catalog | `{filters:{region,universe,delay,...},dataset_id?}`;省略 dataset_id 查数据集,提供则查字段 | | get_research_metadata | `{query:{kind,...}}`;kind 为 scopes/settings/operators/field_availability | | refresh_research_data | `{query:{kind,...}}`;kind 为 catalog/operators/settings/field_availability/pnl | | get_refresh_job | `{job_id,limit?,offset?}`;查询刷新或自相关任务,错误列表独立分页 | | check_self_correlation | `{alpha_ids:[...]}`,1–100 个已导入 Alpha ID;异步返回 job_id | | get_self_correlation | `{alpha_id}`;只读最新本地结果,含缓存和 stale 状态 | | search_backtests | 来源、reference、status、带时区起止时间、scope、q、候选精确匹配及分页 | | submit_backtests | `{name,candidates,idempotency_key,duplicate_policy?,source?}` | | get_backtest | `{run_id,after?,event_limit?}`,after 为事件游标 | | get_backtest_results | `{run_id,item_ids?,limit?,offset?}` | | get_backtest_artifact | `{item_id,kind,limit?,offset?,date_from?,date_to?}`,kind 为 snapshot/pnl | | control_backtest | `{run_id,action,expected_version,idempotency_key}` | metadata 的 operators 支持 q/category 和分页;settings 支持分页;field_availability 要求 field_id 和 scope。refresh 的 catalog 要求 scope,可选 dataset_id;pnl 要求 alpha_ids;availability 与读取使用相同范围字段。目录和 PnL 刷新返回 job_id,查询不会隐式刷新;另外三种刷新最多等待 30 秒,成功只返回快照引用,完整内容用读取工具获取。失败不发布半成品。 列表默认 25 项、最多 100 项;返回 total、offset、limit、has_more。快照证据按顶层 key/value 分页,嵌套内容完整保留;PnL 按日期过滤和分页。元数据仅提供字段与算子资料,不提供原始财务时间序列。 ## 本地自相关检查 目标 Alpha 必须已导入;比较基准为本地已同步的同地区已提交 Alpha,排除自身。建议先在网页全量同步已提交 Alpha。MCP 不隐式导入 Alpha 或同步基准列表。 1. 调用 `check_self_correlation`,例如 `{"alpha_ids":["LL977PqL"]}`,获取 `job_id`。目标去重排序,相同目标集合的活动任务会复用;完成后再次调用会重新计算。 2. 用 `get_refresh_job` 查询进度、失败原因与分页错误。受理后客户端断开不影响后台任务;取消及重试可在网页任务面板执行。 3. 完成后调用 `get_self_correlation`,例如 `{"alpha_id":"LL977PqL"}`。返回 `source=local`,`status` 为 `not_cached`、`available` 或 `stale`;没有结果时 `cached=false`、`result=null`,读取不会隐式启动检查。 检查优先使用已有 PnL 缓存,缺失时由后台自动补取并落库,等待遵循平台 Retry-After。计算使用累计 PnL 的日变化、目标最新数据日前四年的共同窗口、至少 30 个有效样本,取带符号最大的 Pearson 相关系数,阈值为 0.7。结果包含比较数、跳过数、最相关 Alpha、窗口、样本和缓存时间;最多列出前 10 个匹配及前 100 个跳过原因。缺少基准或有效样本会明确报告数据不足,不能当作通过。 `result.stale=true` 表示缓存已待重算;新任务执行期间读取仍可能返回上一次结果,应同时查看任务状态和 `calculated_at`。这是本地研究规则,不调用 WorldQuant 的提交检查,也不代表平台提交资格。`get_research_capabilities.self_correlation` 提供工具名及当前规则。已有包含 `research:refresh` 的 Key 可直接发起检查;只读 Key 只能查看结果。 ## 一轮研究示例 先读取能力和设置快照,发现字段并检查历史。用户授权本批执行后,提交以下形态的固定输入;设置仅为结构示例,实际范围需依据平台选项选择: ```json { "name": "价格排序基线", "idempotency_key": "research-round-001", "duplicate_policy": "reject", "source": {"reference": "conversation-reference", "hypothesis": "基线对照"}, "candidates": [{ "client_item_id": "baseline", "expression": "rank(close)", "alpha_type": "REGULAR", "settings": { "instrumentType": "EQUITY", "region": "USA", "universe": "TOP3000", "delay": 1, "decay": 0, "neutralization": "INDUSTRY", "truncation": 0.08, "pasteurization": "ON", "unitHandling": "VERIFY", "nanHandling": "OFF", "language": "FASTEXPR", "visualization": false, "maxTrade": "OFF", "maxPosition": "OFF" } }] } ``` 单次 1–100 项,client_item_id 唯一,每项设置完整,不做批次级参数合并。输入结构及已缓存设置组合参与校验;缺设置缓存时返回 validation=unknown,不宣称验证了平台组合、表达式语义或字段可用性。可先显式刷新设置消除这类未知。 提交自动保存固定预览和运行,返回 backtest_run_id、输入摘要、数量和 web_url。打开 web_url 可定位网页详情;来源显示“MCP 研究”,可以按来源筛选。后续 get_backtest 和 get_backtest_results 读取进度与结果。PnL 未缓存时返回 not_cached,通过显式刷新再读取。下一批可设置 source.parent_run_id 关联前一批。 ## 幂等、重复与状态 - 成功请求按账户、操作和幂等键固定首次响应。相同请求重试返回原响应,不重新提交;换令牌不改变该范围。同键不同内容返回 IDEMPOTENCY_CONFLICT。失败校验不占用幂等键。 - 幂等判断先于重复查询。规范化摘要包含完整候选、顺序、设置、名称、来源说明和重复策略,不包含链路请求 ID 和令牌。 - 重复按平台完整输入指纹匹配,不判断数学等价。默认 reject 整批拒绝;返回历史记录及其状态,历史失败或跳过也属于输入匹配。明确 rerun 才创建新运行,不自动复用或跳过。匹配记录超页时通过 search_backtests 继续读取。 - 返回 ID 表示已持久化受理,不表示平台完成。执行继续使用原来的限流、退避与重启恢复;客户端断开不取消已受理运行。 - 保留平台、采集和持久化三层状态。completed 不等于检查 PASS。检查包含原始非通过内容及未知状态;指标缺失为 null。 - 历史指标来自当次固定快照,后续 Alpha 同步不改写。PnL 是另行采集的缓存,必须同时阅读 fetched_at,不能视为当次回测同时抓取。 - pause 阻止后续新提交;stop 跳过未提交项,已提交模拟继续采集,不能远程取消。停止后的剩余项须明确新建重跑。 - recover 只根据已有回执恢复采集,不重发未知模拟。无回执的 submission_unknown 仍需在网页核对原模拟。 - resume 保留解除账户级无期限调度阻塞的行为,响应 impact 明确是否解除;不会清除 Retry-After 截止时间。 - 控制使用 expected_version 和独立幂等键;成功重试不重复追加控制事件。统计区分候选、尝试、POST 请求和确认/未知接受数量,实际平台额度消耗保持未知。 审计只记录身份 ID、输入摘要、哈希后的链路请求标识、业务引用、结果码和耗时。关闭 MCP 开关不删除记录,也不停止已受理队列。备份需包含新增表;恢复后旧成功幂等键仍有效。 ## 验证和限制 本地测试只使用模拟平台。后端 `uv run pytest -q tests/test_mcp.py` 包含官方 MCP ClientSession 的 HTTP 工具往返;浏览器测试在临时数据库里验证实际 MCP 提交的运行链接和来源。 独立 PostgreSQL 检查只接受本机 `wq_mcp_test` 数据库: ```bash # backend 目录;变量必须指向专用、可丢弃的测试库。 MCP_TEST_DATABASE_URL=postgresql+asyncpg://USER:PASSWORD@127.0.0.1:PORT/wq_mcp_test \ uv run python -m tests.mcp_postgres ``` 该脚本执行迁移、并发提交/控制、重启重放、回退及重升级,不用于个人库或生产库。生产启用、真实平台兼容性、真实额度和客户端实际凭据配置仍需另行授权验证。本功能不会恢复任何定时研究。