1use crate::handlers;
4use crate::tool_args::*;
5use rmcp::{
6 RoleServer, handler::server::wrapper::Parameters, service::RequestContext, tool, tool_router,
7};
8
9use super::FutuServer;
10
11#[tool_router(router = reference_shareholders_insider_tool_router, vis = "pub(crate)")]
12impl FutuServer {
13 #[tool(
14 description = "Shareholder ownership overview for HK/US securities. Futu API v10.6: OpenQuoteContext.get_shareholders_overview."
15 )]
16 async fn futu_get_shareholders_overview(
17 &self,
18 Parameters(req): Parameters<ShareholdersOverviewReq>,
19 req_ctx: RequestContext<RoleServer>,
20 ) -> std::result::Result<String, String> {
21 tracing::info!(
22 tool = "futu_get_shareholders_overview",
23 symbol = %req.symbol,
24 period_id = ?req.period_id
25 );
26 let client = self
27 .read_client_or_err("futu_get_shareholders_overview", &req_ctx, None, None)
28 .await?;
29 Self::wrap_result(
30 handlers::reference::get_shareholders_overview(&client, &req.symbol, req.period_id)
31 .await,
32 )
33 }
34
35 #[tool(
36 description = "Shareholder holding change records for HK/US securities. Futu API v10.6: OpenQuoteContext.get_shareholders_holding_changes."
37 )]
38 async fn futu_get_shareholders_holding_changes(
39 &self,
40 Parameters(req): Parameters<ShareholdersHoldingChangesReq>,
41 req_ctx: RequestContext<RoleServer>,
42 ) -> std::result::Result<String, String> {
43 req.validate()?;
44 tracing::info!(
45 tool = "futu_get_shareholders_holding_changes",
46 symbol = %req.symbol,
47 next_key = ?req.next_key,
48 num = ?req.num,
49 sort_type = ?req.sort_type,
50 sort_column = ?req.sort_column,
51 filter_type = ?req.filter_type
52 );
53 let client = self
54 .read_client_or_err(
55 "futu_get_shareholders_holding_changes",
56 &req_ctx,
57 None,
58 None,
59 )
60 .await?;
61 Self::wrap_result(
62 handlers::reference::get_shareholders_holding_changes(
63 &client,
64 &req.symbol,
65 req.next_key,
66 req.num,
67 req.sort_type,
68 req.sort_column,
69 req.filter_type,
70 )
71 .await,
72 )
73 }
74
75 #[tool(
76 description = "Shareholder holder detail records for HK/US securities. Futu API v10.6: OpenQuoteContext.get_shareholders_holder_detail."
77 )]
78 async fn futu_get_shareholders_holder_detail(
79 &self,
80 Parameters(req): Parameters<ShareholdersHolderDetailReq>,
81 req_ctx: RequestContext<RoleServer>,
82 ) -> std::result::Result<String, String> {
83 req.validate()?;
84 tracing::info!(
85 tool = "futu_get_shareholders_holder_detail",
86 symbol = %req.symbol,
87 request_type = ?req.request_type,
88 next_key = ?req.next_key,
89 num = ?req.num,
90 sort_column = ?req.sort_column,
91 sort_type = ?req.sort_type,
92 period_id = ?req.period_id,
93 holder_id = ?req.holder_id
94 );
95 let client = self
96 .read_client_or_err("futu_get_shareholders_holder_detail", &req_ctx, None, None)
97 .await?;
98 Self::wrap_result(
99 handlers::reference::get_shareholders_holder_detail(
100 &client,
101 &req.symbol,
102 req.request_type,
103 req.next_key,
104 req.num,
105 req.sort_column,
106 req.sort_type,
107 req.period_id,
108 req.holder_id,
109 )
110 .await,
111 )
112 }
113
114 #[tool(
115 description = "Institutional shareholder ownership statistics for HK/US securities. Futu API v10.6: OpenQuoteContext.get_shareholders_institutional."
116 )]
117 async fn futu_get_shareholders_institutional(
118 &self,
119 Parameters(req): Parameters<ShareholdersInstitutionalReq>,
120 req_ctx: RequestContext<RoleServer>,
121 ) -> std::result::Result<String, String> {
122 req.validate()?;
123 tracing::info!(
124 tool = "futu_get_shareholders_institutional",
125 symbol = %req.symbol,
126 next_key = ?req.next_key,
127 num = ?req.num
128 );
129 let client = self
130 .read_client_or_err("futu_get_shareholders_institutional", &req_ctx, None, None)
131 .await?;
132 Self::wrap_result(
133 handlers::reference::get_shareholders_institutional(
134 &client,
135 &req.symbol,
136 req.next_key,
137 req.num,
138 )
139 .await,
140 )
141 }
142
143 #[tool(
144 description = "Insider holder list for US securities. Futu API v10.6: OpenQuoteContext.get_insider_holder_list."
145 )]
146 async fn futu_get_insider_holder_list(
147 &self,
148 Parameters(req): Parameters<InsiderHolderListReq>,
149 req_ctx: RequestContext<RoleServer>,
150 ) -> std::result::Result<String, String> {
151 req.validate()?;
152 tracing::info!(
153 tool = "futu_get_insider_holder_list",
154 symbol = %req.symbol,
155 next_key = ?req.next_key,
156 num = ?req.num
157 );
158 let client = self
159 .read_client_or_err("futu_get_insider_holder_list", &req_ctx, None, None)
160 .await?;
161 Self::wrap_result(
162 handlers::reference::get_insider_holder_list(
163 &client,
164 &req.symbol,
165 req.next_key,
166 req.num,
167 )
168 .await,
169 )
170 }
171
172 #[tool(
173 description = "Insider trade list for US securities. Futu API v10.6: OpenQuoteContext.get_insider_trade_list."
174 )]
175 async fn futu_get_insider_trade_list(
176 &self,
177 Parameters(req): Parameters<InsiderTradeListReq>,
178 req_ctx: RequestContext<RoleServer>,
179 ) -> std::result::Result<String, String> {
180 req.validate()?;
181 tracing::info!(
182 tool = "futu_get_insider_trade_list",
183 symbol = %req.symbol,
184 holder_id = ?req.holder_id,
185 next_key = ?req.next_key,
186 num = ?req.num
187 );
188 let client = self
189 .read_client_or_err("futu_get_insider_trade_list", &req_ctx, None, None)
190 .await?;
191 Self::wrap_result(
192 handlers::reference::get_insider_trade_list(
193 &client,
194 &req.symbol,
195 req.holder_id,
196 req.next_key,
197 req.num,
198 )
199 .await,
200 )
201 }
202}