Files

6.7 KiB

MCP 服务(桥内嵌 /mcp 端点)

版本: 1.1 (2026-08-27) 状态: 已完成 关联: docs/设计/整体设计方案_v3.md(单端口 8610 统一方案)、docs/api_spec/openapi.yaml 本次迭代: 在现有 qmt_bridge HTTP 服务器上新增 MCP(Model Context Protocol)端点,使 AI 助手(Claude Desktop / Cursor 等)可直接通过 MCP 调用桥的行情/交易能力


一、已确认的设计决策

1.1 结论:可行,采用"桥内嵌 /mcp 端点"方案

MCP 本质是 JSON-RPC 2.0 应用协议,官方两种传输:

  • stdio:子进程管道,适合"MCP 客户端拉起独立进程"
  • Streamable HTTP(2025-03-26 起取代旧 SSE):POST JSON-RPC,单请求-响应

桥已经手写 raw-socket HTTP 服务器,并已证明可在同一端口处理 WebSocket 长连接(Upgrade 分流)。因此:

  • 选定方案 A(桥内嵌):新增 bridge_mcp_server.py,在 POST /mcp 上实现 JSON-RPC 2.0 分发,工具直接复用 bridge_data_adapter / bridge_util
  • 放弃方案 B(独立 MCP 进程 + 官方 mcp SDK):官方 SDK 要求 Python ≥ 3.10,QMT 内置是 Python 3.6.8 纯标准库(不能装包);方案 B 需额外进程经 HTTP 8610 转发,多一跳且偏离项目"薄桥/零依赖"理念。
  • 传输选型:Streamable HTTP 的"非流式"子集(单请求-响应 application/json),覆盖主流 MCP 客户端。流式(SSE)留待后续。

1.2 约束核对(逐条过项目规范)

硬约束 影响 结论
源码 GBK + 纯 ASCII 新模块同样遵守,无新问题
QMT 函数线程约束 MCP tools/call 跑在 HTTP worker 线程,全部复用现有 adapter 安全模式
单账号 MCP 工具无 account 参数,与 HTTP 一致
单端口 8610 POST /mcp 复用 8610,不新开端口
热重载 qmt_strategy_entry.py_BRIDGE_MODULES 需加 bridge_mcp_server
部署 deploy_elevated.bat 需加 bridge_mcp_server.py

1.3 协议实现范围(MCP 最小集)

MCP 方法 实现 说明
initialize 返回协议版本 + tools capability,记录协商版本
notifications/initialized 空响应(通知类)
ping 返回空 result
tools/list 从内置工具注册表返回 {tools: [...]}(含 inputSchema)
tools/call 校验参数 → 调 adapter → 返回 {content:[{type:"text",text:json}]}

暂不实现: resources/*prompts/*logging/*completions/*、流式(SSE)。纯工具型最小实现与主流客户端兼容。

1.4 首批工具(9 个,与 HTTP 接口 1:1)

工具名 对应 HTTP 底层
qmt_kline GET /data/kline get_market_data_ex(worker 线程直调 )
qmt_quote GET /data/quote get_full_tick
qmt_tick GET /data/tick get_full_tick(批量)
qmt_instrument GET /data/instrument get_instrument_detail
qmt_trading_dates GET /data/calendar/trading_dates get_trading_dates
qmt_positions GET /trade/positions 读 TRADE_CACHE(策略线程刷新 )
qmt_asset GET /trade/asset 读 TRADE_CACHE
qmt_orders GET /trade/orders 读 TRADE_CACHE(+ 可选过滤)
qmt_trades GET /trade/trades 读 TRADE_CACHE

后续迭代: qmt_order(下单,队列→adjust)、qmt_cancel(撤单)、qmt_subscribe(订阅)。

1.5 工具实现与 HTTP 共用一个内部函数层

为免工具逻辑与 HTTP handler 双写,bridge_mcp_server.py 内置"工具名 → 参数校验 → 结果 dict"的映射,直接 import bridge_data_adapter 的函数(get_market_data_ex / get_full_tick / get_instrument_detail / get_trading_dates / get_trade_data / get_positions),参数语义与 HTTP 完全一致(code 自动补后缀等)。

说明: 本次迭代不把 HTTP handler 重构为共用同一函数层(避免动既有稳定代码);但工具内部复用的 adapter 已是同一函数,行为一致。文档(openapi.yaml)仍是唯一事实来源,工具 schema 与之保持 1:1。

1.6 鉴权与 CORS

  • 鉴权复用桥 TOKEN 机制: X-Token header 或 ?token=(MCP 客户端如 Claude Desktop 支持自定义 header)。
  • 响应带 CORS 头(Access-Control-Allow-Origin: * 等),兼容浏览器类 MCP 客户端 / 调试工具。
  • OPTIONS /mcp 预检返回 204。

1.7 错误语义

  • 非法 JSON / 非法 JSON-RPC: -32700 parse error / -32600 invalid request(HTTP 200, MCP 规范要求 JSON-RPC 错误也走 200)。
  • 未知方法: -32601 method not found。
  • 工具参数错误: -32602 invalid params(带 detail)。
  • 工具执行异常: -32603 internal error(带 detail)。
  • 非 JSON-RPC body(如纯文本): 400 + {"detail": "..."}(桥统一错误格式)。

二、实现记录(已完成)

2.1 新增文件

  • src/bridge_mcp_server.py: JSON-RPC 2.0 分发 + 9 个工具(复用 bridge_data_adapter)+ raw-socket 响应 + CORS 头
  • tests/test_mcp.py: mock 测试(纯标准库,FakeDF 代替 pandas,本机即可跑),覆盖 initialize / tools/list / 9 个 tools/call / 错误路径 / notification 202 / OPTIONS 204

2.2 改动文件

  • src/bridge_http_server.py: POST /mcp 路由 + OPTIONS /mcp CORS 预检(204)
  • src/qmt_strategy_entry.py: _BRIDGE_MODULES 热重载列表加入 bridge_mcp_server
  • deploy_elevated.bat: 部署文件列表加入 bridge_mcp_server.py(7 → 8 个 .py)
  • README.md / docs/项目规范.md(新增 3.8 节)/ docs/迭代记录/index.md: 文档同步

2.3 实现要点

  • 工具与 HTTP 1:1: qmt_kline / qmt_quote / qmt_tick / qmt_instrument / qmt_trading_dates / qmt_positions / qmt_asset / qmt_orders / qmt_trades
  • 协议: initialize(协商 protocolVersion,回显 2025-06-18/2025-03-26/2024-11-05)、notifications/initialized(202 空 body)、pingtools/listtools/call
  • 错误: JSON-RPC 错误走 HTTP 200(parse -32700 / invalid request -32600 / method not found -32601 / invalid params -32602 / internal -32603);非法 body 走 400 {"detail":...}
  • 鉴权/CORS: 复用 TOKEN(X-Token);OPTIONS /mcp 预检 204;响应带 Access-Control-Allow-Origin: *
  • 线程约束: 全部工具经 bridge_data_adapter → 与 HTTP 端点同模式(行情 worker 直调,交易读缓存),无新 QMT 调用形态

2.4 验证结果

  • 编译 + ASCII 检查: 全部通过(纯 ASCII,0 非 ASCII 字节)
  • python tests/test_mcp.py: 17 项断言全部 OK(initialize、9 工具、错误路径、202、204)
  • 回归: test_subscription.py / test_sub_no_ws.py / test_ws_push.py 全部通过(路由改动无影响)

三、待讨论事项

  • 是否需要 SSE 流式(长连接占线程池 worker,参考 WS 的处理;默认不做)
  • 是否需要 qmt_order / qmt_cancel(依赖交易接口后续迭代)
  • 目标 MCP 客户端确认(Claude Desktop / Cursor / DSH 等)