Skip to main content

futu_mcp/tool_args/
push.rs

1//! v1.4.110 P1-1: 拆自 `tool_args.rs` 按 handler 域分组.
2
3#![allow(unused_imports)]
4
5use rmcp::schemars;
6use serde::{Deserialize, Serialize};
7
8use crate::tool_enums;
9use crate::tool_enums::ToolEnum;
10
11use super::*;
12
13#[derive(Debug, Deserialize, schemars::JsonSchema)]
14#[serde(deny_unknown_fields)]
15pub struct QuerySubscriptionReq {
16    #[schemars(description = "true=query all connections; false=only this connection (default)")]
17    #[serde(default)]
18    pub is_req_all_conn: bool,
19}
20
21#[derive(Debug, Deserialize, schemars::JsonSchema)]
22#[serde(deny_unknown_fields)]
23pub struct UnsubscribeReq {
24    #[schemars(
25        description = "Security symbols to unsubscribe (ignored if unsub_all=true); alias: stocks / code_list / symbol_list / security_list"
26    )]
27    // v1.4.84 §5 B1
28    #[serde(
29        default,
30        alias = "stocks",
31        alias = "code_list",
32        alias = "symbol_list",
33        alias = "security_list"
34    )]
35    pub symbols: Vec<String>,
36    #[schemars(
37        description = "Sub-type ids to unsubscribe. Accept int (1=Basic, 2=OrderBook, 4=Ticker, \
38                       5=RT, 6=KL_Day, 7=KL_5Min, 8=KL_15Min, 9=KL_30Min, 10=KL_60Min, 11=KL_1Min, \
39                       12=KL_Week, 13=KL_Month, 14=Broker, 15=KL_Quarter, 16=KL_Year, 17=KL_3Min) \
40                       OR string (\"Basic\" / \"OrderBook\" / \"KL_Day\" / \"day\" / ...). Alias: \
41                       sub_type_list. v1.4.84 §5 B2 双接. v1.4.104 eli S-006 P1 fix: 修正 int 表 \
42                       (proto 跳 3, 4=Ticker 不是 3=Ticker; 10=KL_60Min 不是 10=KL_Month)."
43    )]
44    // v1.4.84 §5 B2 field migration: Vec<SubTypeEnum> 双接
45    #[serde(
46        default,
47        alias = "sub_type_list",
48        deserialize_with = "tool_enums::deser_subtype_list_as_vec_i32"
49    )]
50    pub sub_types: Vec<i32>,
51    #[schemars(
52        description = "true=clear all subscriptions on this connection (ignores symbols/sub_types); alias: unsubscribe_all"
53    )]
54    #[serde(default, alias = "unsubscribe_all")]
55    pub unsub_all: bool,
56}
57
58/// v1.4.74 A1 BUG-011 fix: MCP `futu_subscribe` request body(对称于
59/// `UnsubscribeReq`)。
60#[derive(Debug, Deserialize, schemars::JsonSchema)]
61#[serde(deny_unknown_fields)]
62pub struct SubscribeReq {
63    #[schemars(
64        description = "Security symbols to subscribe, e.g. [\"HK.00700\", \"US.AAPL\"]. Alias: stocks / code_list / symbol_list / security_list"
65    )]
66    // v1.4.84 §5 B1
67    #[serde(
68        alias = "stocks",
69        alias = "code_list",
70        alias = "symbol_list",
71        alias = "security_list"
72    )]
73    pub symbols: Vec<String>,
74    #[schemars(
75        description = "Sub-type ids to subscribe. Accept int (1=Basic, 2=OrderBook, 4=Ticker, \
76                       5=RT, 6=KL_Day, 7=KL_5Min, 8=KL_15Min, 9=KL_30Min, 10=KL_60Min, 11=KL_1Min, \
77                       12=KL_Week, 13=KL_Month, 14=Broker, 15=KL_Quarter, 16=KL_Year, 17=KL_3Min) \
78                       OR string (\"Basic\" / \"OrderBook\" / \"KL_Day\" / \"day\" / ...). Alias: \
79                       sub_type_list. v1.4.84 §5 B2 双接. v1.4.104 eli S-006 P1 fix: 修正 int 表 \
80                       对齐 daemon proto (Qot_Common.SubType: 跳 3=None, 4=Ticker, 10=KL_60Min, \
81                       13=KL_Month). 之前 schema 描述 10=KL_Month 与 daemon 不一致, agent 按 \
82                       schema 数字 10 调用实际订到 KL_60Min."
83    )]
84    // v1.4.84 §5 B2 field migration
85    #[serde(
86        alias = "sub_type_list",
87        deserialize_with = "tool_enums::deser_subtype_list_as_vec_i32"
88    )]
89    pub sub_types: Vec<i32>,
90    #[schemars(
91        description = "If true, backend pushes current snapshot immediately after subscribe (useful for agents needing warm state). Default true."
92    )]
93    #[serde(default = "default_is_first_push")]
94    pub is_first_push: bool,
95    #[schemars(
96        description = "If true, register push on this connection (agent will receive push via SSE notification in HTTP mode). Default true."
97    )]
98    #[serde(default = "default_is_reg_push")]
99    pub is_reg_push: bool,
100}
101
102#[derive(Debug, Deserialize, schemars::JsonSchema)]
103#[serde(deny_unknown_fields)]
104pub struct SubAccPushReq {
105    #[schemars(description = "Array of account IDs (u64) to receive order/deal push \
106                       for. ⚠️ Call `futu_list_accounts` first to discover real \
107                       `acc_id` values; do NOT hallucinate 18-digit numbers — \
108                       invalid ids will silently fail to receive push. Alias: account_ids / accounts")]
109    // v1.4.84 §5 B1
110    #[serde(alias = "account_ids", alias = "accounts")]
111    pub acc_ids: Vec<u64>,
112    #[schemars(
113        description = "Optional per-call API key plaintext. Priority: tool args > HTTP Bearer > startup key. Use to scope this push subscription to a specific narrow key."
114    )]
115    #[serde(default)]
116    pub api_key: Option<String>,
117}
118
119/// v1.4.58 Phase A: `futu_unsub_acc_push` request body.
120#[derive(Debug, Deserialize, schemars::JsonSchema)]
121#[serde(deny_unknown_fields)]
122pub struct UnsubAccPushReq {
123    /// session_id from previous `futu_sub_acc_push` response — **required**.
124    /// rmcp 的 Peer<RoleServer> 不实装 PartialEq,无法按 peer 身份批量撤销。
125    #[schemars(description = "Required: session_id returned by `futu_sub_acc_push` \
126                       response (session_id field or unsub_hint). If omitted, \
127                       handler returns an error. If session_id not found (e.g. \
128                       4h auto-purged), removed_count=0 is returned.")]
129    #[serde(default)]
130    pub session_id: Option<String>,
131    #[schemars(
132        description = "Optional per-call API key plaintext. Priority: tool args > HTTP Bearer > startup key. Use the same key that created the push subscription when running in stdio mode with multiple keys."
133    )]
134    #[serde(default)]
135    pub api_key: Option<String>,
136}