跳转至

MCP

Model Context Protocol server:把网关的工具暴露给 LLM 客户端。两种 transport:stdio / HTTP。

完整工具参数级文档

本页是工具清单概览. 每个 tool 的完整参数 (含 v1.4.83/84 alias + enum 双接 + deny_unknown_fields + runtime validate) / JSON-RPC 调用示例见 API 参考 → MCP 工具 (v1.4.85 新增).

工具清单

行情(qot:read)

工具 说明
futu_ping ping 网关,返回 RTT
futu_get_quote 实时报价(自动订阅 Basic)
futu_get_snapshot 快照(含 52 周高低、换手率、买卖档)
futu_get_kline 历史 K 线(日 / 周 / 月 / 1-60 分钟)
futu_get_orderbook 买卖盘(自动订阅 OrderBook)
futu_get_ticker 逐笔成交
futu_get_rt 分时图
futu_get_static 静态信息(名称、每手股数、上市日)
futu_get_broker 经纪商队列(港股)
futu_list_plates 板块列表
futu_plate_stocks 板块成分股
futu_get_capital_flow v1.4.25+:资金流时间序列(主力资金进出)
futu_get_capital_distribution v1.4.25+:资金分布(超大 / 大 / 中 / 小单)
futu_get_market_state v1.4.25+:市场状态(开盘 / 休市 / 午休)
futu_get_history_kline v1.4.26+:历史 K 线(支持 rehab_type + 大数据量 max_count)
futu_get_owner_plate v1.4.26+:股票所属板块(行业 / 概念 / 地域)
futu_get_reference v1.4.26+:关联证券(正股↔涡轮/期货/期权)
futu_get_option_chain v1.4.26+:期权链(按到期日聚合 call/put)
futu_get_warrant v1.4.29+:涡轮列表(按成交量排序,可指定正股)
futu_get_ipo_list v1.4.29+:新股 IPO 列表(港/美/A/新/日/马按市场)
futu_get_ipo_calendar v1.5.3+:把 IPO 列表投影为日历事件(上市 / 申购 / 中签 / 日本 IPO 询价等)
futu_get_financial_calendar v1.5.3+:财报日历全市场视图;支持市场、日期、事件类型和移动端 calendar 筛选
futu_search_target_financial_calendar v1.5.3+:按股票 ID 查询目标股票财报日历(mobile/moomoo CMD20426)
futu_get_future_info v1.4.29+:期货合约资料(合约大小、最后交易日、交易时段)
futu_get_user_security_group v1.4.29+:自选股分组列表(自定义 / 系统)
futu_get_stock_filter v1.4.29+:条件选股(最小参数;高级 filter 走 REST)
futu_get_trading_days v1.4.30+:交易日列表
futu_get_rehab v1.4.30+:复权因子(长期 K 线对齐 / 回测必用)
futu_get_suspend v1.4.30+:停牌日
futu_get_user_security v1.4.30+:自选股分组下的股票
futu_get_global_state v1.4.30+:网关全局状态(市场开闭 / 登录状态 / 服务器版本)
futu_get_user_info v1.4.30+:用户信息(各市场行情权限 / 订阅配额)
futu_get_delay_statistics v1.4.30+:延迟统计概要
futu_get_history_kl_quota v1.4.30+:历史 K 线已用 / 剩余 / 总下载配额,并返回额度来源说明
futu_get_used_quota v1.5.3+:当前已用订阅额度和历史 K 线额度
futu_get_holding_change v1.4.30+:持股变动(高管 / 机构 / 基金)
futu_modify_user_security v1.4.30+:修改自选股分组(add / del / move-out)
futu_get_code_change v1.4.30+:代码变更 / 临时代码(目前港股)
futu_set_price_reminder v1.4.30+:设置到价提醒
futu_get_price_reminder v1.4.30+:查询到价提醒
futu_get_option_expiration_date v1.4.30+:期权到期日列表
futu_query_subscription v1.4.30+:查询当前订阅状态
futu_unsubscribe v1.4.30+:反订阅行情(支持 unsub_all)

账户只读(acc:read)

工具 说明
futu_list_accounts 交易账户列表
futu_get_funds 资金概览
futu_get_positions 持仓
futu_get_orders 当日订单
futu_get_deals 当日成交
futu_get_max_trd_qtys v1.4.25+:下单前算最大可买卖量
futu_get_order_fee v1.4.25+:手续费明细
futu_get_margin_ratio v1.4.25+:融资融券比率
futu_get_history_orders v1.4.25+:历史订单
futu_get_history_deals v1.4.25+:历史成交
futu_sub_acc_push v1.4.30+:订阅账户推送(订单 / 成交更新)
futu_get_acc_cash_flow v1.4.30+:账户资金流水(按清算日)

交易(trade:real / trade:simulate)

工具 说明 额外参数
futu_place_order 下单 api_key? per-call 覆盖
futu_modify_order 改单(含撤单) api_key?
futu_cancel_order 撤单(简化版) api_key?
futu_reconfirm_order 二次确认订单 api_key?
futu_cancel_all_order v1.4.30+:全部撤单(指定市场或全账户) api_key?

解锁交易(trade:unlock,v1.4+)

工具 说明 额外参数
futu_unlock_trade 解锁 / 锁回真实交易 unlock: bool(默认 true);v1.4.31+ otp: String 可选(2FA 账户);v1.4.47+ security_firm: i32 可选(1-7 / FutuHK / hk),只解该券商;v1.4.47+ acc_ids: Vec<u64> 可选,只解列表内账户(和 security_firm 取交集,解决影子子账户)
  • 明文密码永不入 LLM prompt:服务端先读 FUTU_TRADE_PWD(显式运行时 override,首尾空白会 trim),再兼容读取账号级 / legacy OS credential store。
  • macOS 发布包的 binary 使用不同 ad-hoc signing identity,不能可靠共享无人值守 Keychain 条目;请给 futu-mcp 设置 FUTU_TRADE_PWD。Linux / Windows 可继续用 futucli set-trade-pwd --account <login-account>。credential-store 读取最多等待 3 秒,超时返回可恢复错误,不会让 MCP 卡住。
  • MD5 在服务端本地计算后再发给 gateway
  • 解锁后 gateway 进程级缓存 cipher,直到 gateway 重启;下单不需要每次重解锁
  • v1.4.31+ per-broker 解锁 + 细粒度返回:响应 JSON 带 total_requested / total_unlocked / failed_accounts,出部分失败时 ok=false 会明确指出哪个账户没解锁(常见原因:该账户品种权限未开通 / 影子子账户)
  • v1.4.31+ 2FA(令牌动态密码)账户:服务端返 need_otp=true 时 LLM 应提示用户输入 OTP,再调一次带 otp 字段

启动

export FUTU_MCP_API_KEY="fc_xxxx..."
./futu-mcp \
  --gateway 127.0.0.1:11111 \
  --keys-file ~/.config/futu/keys.json

stdin / stdout 传 JSON-RPC 帧,由 LLM 客户端启动子进程。

./futu-mcp \
  --gateway 127.0.0.1:11111 \
  --keys-file ~/.config/futu/keys.json \
  --http-listen 127.0.0.1:38765
  • POST /mcp —— rmcp streamable HTTP transport
  • GET /metrics —— Prometheus(无需 token)
  • GET /.well-known/oauth-protected-resource —— OAuth2 Protected Resource Metadata(RFC 9728,v1.4+;让 MCP 客户端自动发现 scope 要求)

协议版本与生命周期(v1.6+)

stdio 与 streamable HTTP(POST /mcp)使用同一份版本合同:

MCP 协议日期 生命周期 服务端 capabilities 账户推送
2024-11-05 legacy initialize tools + logging logging notification
2025-03-26 legacy initialize tools + logging logging notification
2025-06-18 legacy initialize tools + logging logging notification
2025-11-25 legacy initialize tools + logging logging notification
2026-07-28 modern discover tools;可续用 acc:read identity 再加 resources/subscriptions private push resource(条件启用)

rmcp 1.5.02.2.0 代表客户端已分别通过 stdio/HTTP 的真实 futu-mcp 进程互操作测试。这是两个代表版本的证据,不表示所有第三方 MCP SDK 都已验证。HTTP transport 只提供 /mcp;旧 HTTP+SSE /sse 不在支持范围内。

2026 discovery 会按当前调用者投影 capability:HTTP Bearer 或 stdio startup key 必须仍满足 machine binding、expiry 与 acc:read,才会广告 resources;no-key 或 权限不足时只广告 tools,未广告的 resource 方法 fail-closed。

2026-07-28 账户推送读取顺序

  1. futu_sub_acc_push 注册账户推送。成功响应除 session_id 外还包含唯一的 resource_uri,形如 futu://push/sub-<session-id>
  2. 使用同一、可续用的 API key identity 调 subscriptions/listen,filter 中必须且只能包含该 canonical URI。服务端 ack 只表示接受了 filter;owner/scope/TTL 校验随后执行, 失败会以 final error 结束,且不会 attach listener。
  3. 收到 resource-updated notification 后,以同一身份调用 resources/read。 每次 read 原子取走当前队列并返回 events 与累计 dropped_events;下一次 read 只看之后到达的事件。
  4. resources/list 只返回当前调用者仍有权访问的资源。资源声明为 private、 ttlMs=0,客户端不得缓存响应。
  5. futu_unsub_acc_push 显式清理;未清理的 handle 最长保留 4 小时。

每个资源 FIFO 上限为 64;慢消费者溢出时丢弃最旧事件并增加 dropped_events。进程最多同时保留 128 个 modern handle,容量不足会在请求网关 前失败。key 被撤销/过期、机器绑定失效,或账户/市场 scope 收窄后, list/listen/read 均 fail-closed,旧队列不会泄漏给新身份。

OAuth metadata 端点(v1.4+)

未带 Authorization: Bearer 头的 /mcp 请求会返回 401 + WWW-Authenticate: Bearer resource_metadata="/.well-known/oauth-protected-resource" 头。 客户端按这个 URL 拉 JSON 即可知道要带什么 scope:

{
  "resource": "/mcp",
  "bearer_methods_supported": ["header"],
  "scopes_supported": [
    "qot:read",
    "acc:read",
    "trade:simulate",
    "trade:real",
    "trade:unlock"
  ],
  "resource_name": "FutuOpenD-rs MCP",
  "resource_documentation": "https://futuapi.com/guide/mcp/"
}

为什么不是完整 OAuth server?

Futu 的 API key 是人工配置的长期凭据,没有 interactive consent 流程。 RFC 9728 正是为"只声明鉴权要求、不做授权流程"的资源服务器设计。 实际 token(= API key)仍由运维线下发放,写进 MCP client 配置里 的 Authorization 头。

API key 来源与优先级(v1.1+)

HTTP transport:每个 /mcp 请求必须携带 Authorization: Bearer <token>(不回退启动 key)
stdio transport:tool schema 显式声明的 api_key > 启动时 --api-key / FUTU_MCP_API_KEY

Authorization header 是 HTTP transport 的强制逐请求凭据;initializetools/list、工具调用和 session DELETE 都在创建或访问 MCP session 前验证。 启动时 --api-key / FUTU_MCP_API_KEY 只用于 stdio,不会替 HTTP 请求兜底。 api_key 并不是 所有工具共有的隐藏参数:只有参考文档和 schema 明确列出该字段的工具才接受参数级 覆盖。HTTP 模式下多个 LLM 可以各带自己的 Bearer token,audit / 限额各记各的。

scope 中央注册表

guard::scope_for_tool(name) -> Option<ToolScope> 是唯一真源。加新 #[tool] 必须同步更新这里,否则 handler 返回 unknown MCP tool;测试 all_known_tools_have_scopes 会挂。

SIGHUP 热重载

kill -HUP $(pgrep futu-mcp)

改了 keys.json 里某把 key 的 scope / 限额 / expires_at / 吊销后立刻对 MCP 生效(v0.8+ 起 MCP 按 key_id 每次请求现查 KeyStore)。

交易工具的安全边界

  • unlock_trade 工具不接受密码参数(v1.4+)—— futu_unlock_trade 只有 unlock: bool 入参;密码由服务端从 OS keychain / 环境变量读。LLM prompt 和工具调用日志里永远看不到密码
  • simulate 默认 —— PlaceOrderReq.env 默认值是 "simulate",LLM 要显式写 "real" 才走真实账户
  • scope 隔离 —— trade:simulate 永远不能下真实单(即使把 env 写成 real 也会被 require_trading 拒)
  • 限额必过 —— handler 层走 full CheckCtx:market / symbol / value / side / daily 全套检查
  • WS 推送防御深度(v1.4+)—— 就算订阅门禁漏了,push 分发前也会按 scope 再过一遍,过滤掉的推送打 futu_ws_push_filtered_total 指标

MCP 客户端对接

完整教程 → MCP 接入 LLM 包含 Claude Desktop / Cursor / Continue 的配置示例。