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 transportGET /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.0 与 2.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 账户推送读取顺序¶
- 用
futu_sub_acc_push注册账户推送。成功响应除session_id外还包含唯一的resource_uri,形如futu://push/sub-<session-id>。 - 使用同一、可续用的 API key identity 调
subscriptions/listen,filter 中必须且只能包含该 canonical URI。服务端 ack 只表示接受了 filter;owner/scope/TTL 校验随后执行, 失败会以 final error 结束,且不会 attach listener。 - 收到 resource-updated notification 后,以同一身份调用
resources/read。 每次 read 原子取走当前队列并返回events与累计dropped_events;下一次 read 只看之后到达的事件。 resources/list只返回当前调用者仍有权访问的资源。资源声明为 private、ttlMs=0,客户端不得缓存响应。- 调
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 的强制逐请求凭据;initialize、
tools/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 热重载¶
改了 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 的配置示例。