Skip to main content

futu_mcp/tools/
qot_3401_plus.rs

1//! MCP raw proto-json tools for public QOT 3401+ APIs.
2
3use std::future::Future;
4use std::sync::Arc;
5
6use futu_net::client::FutuClient;
7use rmcp::{RoleServer, handler::server::wrapper::Parameters, service::RequestContext};
8use serde::de::DeserializeOwned;
9
10use crate::handlers;
11use crate::tool_args::ProtoJsonReq;
12
13use super::FutuServer;
14
15async fn run_qot_proto_json<C2S, F, Fut>(
16    server: &FutuServer,
17    tool_name: &'static str,
18    label: &'static str,
19    req: ProtoJsonReq,
20    req_ctx: RequestContext<RoleServer>,
21    handler: F,
22) -> std::result::Result<String, String>
23where
24    C2S: DeserializeOwned,
25    F: FnOnce(Arc<FutuClient>, C2S) -> Fut,
26    Fut: Future<Output = anyhow::Result<String>>,
27{
28    let c2s = match handlers::proto_json::parse_c2s_json::<C2S>(label, &req.c2s_json) {
29        Ok(c2s) => c2s,
30        Err(err) => return FutuServer::tool_err(err),
31    };
32    let client = server
33        .read_client_or_err(tool_name, &req_ctx, req.api_key.as_deref(), None)
34        .await?;
35    FutuServer::wrap_result(handler(client, c2s).await)
36}
37
38impl FutuServer {
39    async fn futu_get_earnings_calendar_impl(
40        &self,
41        Parameters(req): Parameters<ProtoJsonReq>,
42        req_ctx: RequestContext<RoleServer>,
43    ) -> std::result::Result<String, String> {
44        run_qot_proto_json::<futu_proto::qot_get_earnings_calendar::C2s, _, _>(
45            self,
46            "futu_get_earnings_calendar",
47            "earnings-calendar",
48            req,
49            req_ctx,
50            |client, c2s| async move {
51                handlers::proto_json::earnings_calendar(&client, c2s).await
52            },
53        )
54        .await
55    }
56
57    async fn futu_get_macro_indicator_list_impl(
58        &self,
59        Parameters(req): Parameters<ProtoJsonReq>,
60        req_ctx: RequestContext<RoleServer>,
61    ) -> std::result::Result<String, String> {
62        run_qot_proto_json::<futu_proto::qot_get_macro_indicator_list::C2s, _, _>(
63            self,
64            "futu_get_macro_indicator_list",
65            "macro-indicator-list",
66            req,
67            req_ctx,
68            |client, c2s| async move {
69                handlers::proto_json::macro_indicator_list(&client, c2s).await
70            },
71        )
72        .await
73    }
74
75    async fn futu_get_macro_indicator_history_impl(
76        &self,
77        Parameters(req): Parameters<ProtoJsonReq>,
78        req_ctx: RequestContext<RoleServer>,
79    ) -> std::result::Result<String, String> {
80        run_qot_proto_json::<futu_proto::qot_get_macro_indicator_history::C2s, _, _>(
81            self,
82            "futu_get_macro_indicator_history",
83            "macro-indicator-history",
84            req,
85            req_ctx,
86            |client, c2s| async move {
87                handlers::proto_json::macro_indicator_history(&client, c2s).await
88            },
89        )
90        .await
91    }
92
93    async fn futu_get_fed_watch_target_rate_impl(
94        &self,
95        Parameters(req): Parameters<ProtoJsonReq>,
96        req_ctx: RequestContext<RoleServer>,
97    ) -> std::result::Result<String, String> {
98        run_qot_proto_json::<futu_proto::qot_get_fed_watch_target_rate::C2s, _, _>(
99            self,
100            "futu_get_fed_watch_target_rate",
101            "fed-watch-target-rate",
102            req,
103            req_ctx,
104            |client, c2s| async move {
105                handlers::proto_json::fed_watch_target_rate(&client, c2s).await
106            },
107        )
108        .await
109    }
110
111    async fn futu_get_fed_watch_dot_plot_impl(
112        &self,
113        Parameters(req): Parameters<ProtoJsonReq>,
114        req_ctx: RequestContext<RoleServer>,
115    ) -> std::result::Result<String, String> {
116        run_qot_proto_json::<futu_proto::qot_get_fed_watch_dot_plot::C2s, _, _>(
117            self,
118            "futu_get_fed_watch_dot_plot",
119            "fed-watch-dot-plot",
120            req,
121            req_ctx,
122            |client, c2s| async move {
123                handlers::proto_json::fed_watch_dot_plot(&client, c2s).await
124            },
125        )
126        .await
127    }
128
129    async fn futu_get_earnings_beat_rank_impl(
130        &self,
131        Parameters(req): Parameters<ProtoJsonReq>,
132        req_ctx: RequestContext<RoleServer>,
133    ) -> std::result::Result<String, String> {
134        run_qot_proto_json::<futu_proto::qot_get_earnings_beat_rank::C2s, _, _>(
135            self,
136            "futu_get_earnings_beat_rank",
137            "earnings-beat-rank",
138            req,
139            req_ctx,
140            |client, c2s| async move {
141                handlers::proto_json::earnings_beat_rank(&client, c2s).await
142            },
143        )
144        .await
145    }
146
147    async fn futu_get_dividend_rank_impl(
148        &self,
149        Parameters(req): Parameters<ProtoJsonReq>,
150        req_ctx: RequestContext<RoleServer>,
151    ) -> std::result::Result<String, String> {
152        run_qot_proto_json::<futu_proto::qot_get_dividend_rank::C2s, _, _>(
153            self,
154            "futu_get_dividend_rank",
155            "dividend-rank",
156            req,
157            req_ctx,
158            |client, c2s| async move { handlers::proto_json::dividend_rank(&client, c2s).await },
159        )
160        .await
161    }
162
163    async fn futu_get_dividend_calendar_impl(
164        &self,
165        Parameters(req): Parameters<ProtoJsonReq>,
166        req_ctx: RequestContext<RoleServer>,
167    ) -> std::result::Result<String, String> {
168        run_qot_proto_json::<futu_proto::qot_get_dividend_calendar::C2s, _, _>(
169            self,
170            "futu_get_dividend_calendar",
171            "dividend-calendar",
172            req,
173            req_ctx,
174            |client, c2s| async move {
175                handlers::proto_json::dividend_calendar(&client, c2s).await
176            },
177        )
178        .await
179    }
180
181    async fn futu_get_economic_calendar_impl(
182        &self,
183        Parameters(req): Parameters<ProtoJsonReq>,
184        req_ctx: RequestContext<RoleServer>,
185    ) -> std::result::Result<String, String> {
186        run_qot_proto_json::<futu_proto::qot_get_economic_calendar::C2s, _, _>(
187            self,
188            "futu_get_economic_calendar",
189            "economic-calendar",
190            req,
191            req_ctx,
192            |client, c2s| async move {
193                handlers::proto_json::economic_calendar(&client, c2s).await
194            },
195        )
196        .await
197    }
198
199    async fn futu_get_us_pre_market_rank_impl(
200        &self,
201        Parameters(req): Parameters<ProtoJsonReq>,
202        req_ctx: RequestContext<RoleServer>,
203    ) -> std::result::Result<String, String> {
204        run_qot_proto_json::<futu_proto::qot_get_us_pre_market_rank::C2s, _, _>(
205            self,
206            "futu_get_us_pre_market_rank",
207            "us-pre-market-rank",
208            req,
209            req_ctx,
210            |client, c2s| async move {
211                handlers::proto_json::us_pre_market_rank(&client, c2s).await
212            },
213        )
214        .await
215    }
216
217    async fn futu_get_us_after_hours_rank_impl(
218        &self,
219        Parameters(req): Parameters<ProtoJsonReq>,
220        req_ctx: RequestContext<RoleServer>,
221    ) -> std::result::Result<String, String> {
222        run_qot_proto_json::<futu_proto::qot_get_us_after_hours_rank::C2s, _, _>(
223            self,
224            "futu_get_us_after_hours_rank",
225            "us-after-hours-rank",
226            req,
227            req_ctx,
228            |client, c2s| async move {
229                handlers::proto_json::us_after_hours_rank(&client, c2s).await
230            },
231        )
232        .await
233    }
234
235    async fn futu_get_us_overnight_rank_impl(
236        &self,
237        Parameters(req): Parameters<ProtoJsonReq>,
238        req_ctx: RequestContext<RoleServer>,
239    ) -> std::result::Result<String, String> {
240        run_qot_proto_json::<futu_proto::qot_get_us_overnight_rank::C2s, _, _>(
241            self,
242            "futu_get_us_overnight_rank",
243            "us-overnight-rank",
244            req,
245            req_ctx,
246            |client, c2s| async move {
247                handlers::proto_json::us_overnight_rank(&client, c2s).await
248            },
249        )
250        .await
251    }
252
253    async fn futu_get_top_movers_rank_impl(
254        &self,
255        Parameters(req): Parameters<ProtoJsonReq>,
256        req_ctx: RequestContext<RoleServer>,
257    ) -> std::result::Result<String, String> {
258        run_qot_proto_json::<futu_proto::qot_get_top_movers_rank::C2s, _, _>(
259            self,
260            "futu_get_top_movers_rank",
261            "top-movers-rank",
262            req,
263            req_ctx,
264            |client, c2s| async move { handlers::proto_json::top_movers_rank(&client, c2s).await },
265        )
266        .await
267    }
268
269    async fn futu_get_hot_list_impl(
270        &self,
271        Parameters(req): Parameters<ProtoJsonReq>,
272        req_ctx: RequestContext<RoleServer>,
273    ) -> std::result::Result<String, String> {
274        run_qot_proto_json::<futu_proto::qot_get_hot_list::C2s, _, _>(
275            self,
276            "futu_get_hot_list",
277            "hot-list",
278            req,
279            req_ctx,
280            |client, c2s| async move { handlers::proto_json::hot_list(&client, c2s).await },
281        )
282        .await
283    }
284
285    async fn futu_get_short_selling_rank_impl(
286        &self,
287        Parameters(req): Parameters<ProtoJsonReq>,
288        req_ctx: RequestContext<RoleServer>,
289    ) -> std::result::Result<String, String> {
290        run_qot_proto_json::<futu_proto::qot_get_short_selling_rank::C2s, _, _>(
291            self,
292            "futu_get_short_selling_rank",
293            "short-selling-rank",
294            req,
295            req_ctx,
296            |client, c2s| async move {
297                handlers::proto_json::short_selling_rank(&client, c2s).await
298            },
299        )
300        .await
301    }
302
303    async fn futu_get_period_change_rank_impl(
304        &self,
305        Parameters(req): Parameters<ProtoJsonReq>,
306        req_ctx: RequestContext<RoleServer>,
307    ) -> std::result::Result<String, String> {
308        run_qot_proto_json::<futu_proto::qot_get_period_change_rank::C2s, _, _>(
309            self,
310            "futu_get_period_change_rank",
311            "period-change-rank",
312            req,
313            req_ctx,
314            |client, c2s| async move {
315                handlers::proto_json::period_change_rank(&client, c2s).await
316            },
317        )
318        .await
319    }
320
321    async fn futu_get_high_dividend_soe_rank_impl(
322        &self,
323        Parameters(req): Parameters<ProtoJsonReq>,
324        req_ctx: RequestContext<RoleServer>,
325    ) -> std::result::Result<String, String> {
326        run_qot_proto_json::<futu_proto::qot_get_high_dividend_soe_rank::C2s, _, _>(
327            self,
328            "futu_get_high_dividend_soe_rank",
329            "high-dividend-soe-rank",
330            req,
331            req_ctx,
332            |client, c2s| async move {
333                handlers::proto_json::high_dividend_soe_rank(&client, c2s).await
334            },
335        )
336        .await
337    }
338
339    async fn futu_get_institution_list_impl(
340        &self,
341        Parameters(req): Parameters<ProtoJsonReq>,
342        req_ctx: RequestContext<RoleServer>,
343    ) -> std::result::Result<String, String> {
344        run_qot_proto_json::<futu_proto::qot_get_institution_list::C2s, _, _>(
345            self,
346            "futu_get_institution_list",
347            "institution-list",
348            req,
349            req_ctx,
350            |client, c2s| async move { handlers::proto_json::institution_list(&client, c2s).await },
351        )
352        .await
353    }
354
355    async fn futu_get_institution_profile_impl(
356        &self,
357        Parameters(req): Parameters<ProtoJsonReq>,
358        req_ctx: RequestContext<RoleServer>,
359    ) -> std::result::Result<String, String> {
360        run_qot_proto_json::<futu_proto::qot_get_institution_profile::C2s, _, _>(
361            self,
362            "futu_get_institution_profile",
363            "institution-profile",
364            req,
365            req_ctx,
366            |client, c2s| async move {
367                handlers::proto_json::institution_profile(&client, c2s).await
368            },
369        )
370        .await
371    }
372
373    async fn futu_get_institution_distribution_impl(
374        &self,
375        Parameters(req): Parameters<ProtoJsonReq>,
376        req_ctx: RequestContext<RoleServer>,
377    ) -> std::result::Result<String, String> {
378        run_qot_proto_json::<futu_proto::qot_get_institution_distribution::C2s, _, _>(
379            self,
380            "futu_get_institution_distribution",
381            "institution-distribution",
382            req,
383            req_ctx,
384            |client, c2s| async move {
385                handlers::proto_json::institution_distribution(&client, c2s).await
386            },
387        )
388        .await
389    }
390
391    async fn futu_get_institution_holding_change_impl(
392        &self,
393        Parameters(req): Parameters<ProtoJsonReq>,
394        req_ctx: RequestContext<RoleServer>,
395    ) -> std::result::Result<String, String> {
396        run_qot_proto_json::<futu_proto::qot_get_institution_holding_change::C2s, _, _>(
397            self,
398            "futu_get_institution_holding_change",
399            "institution-holding-change",
400            req,
401            req_ctx,
402            |client, c2s| async move {
403                handlers::proto_json::institution_holding_change(&client, c2s).await
404            },
405        )
406        .await
407    }
408
409    async fn futu_get_institution_holding_list_impl(
410        &self,
411        Parameters(req): Parameters<ProtoJsonReq>,
412        req_ctx: RequestContext<RoleServer>,
413    ) -> std::result::Result<String, String> {
414        run_qot_proto_json::<futu_proto::qot_get_institution_holding_list::C2s, _, _>(
415            self,
416            "futu_get_institution_holding_list",
417            "institution-holding-list",
418            req,
419            req_ctx,
420            |client, c2s| async move {
421                handlers::proto_json::institution_holding_list(&client, c2s).await
422            },
423        )
424        .await
425    }
426
427    async fn futu_get_ark_fund_holding_impl(
428        &self,
429        Parameters(req): Parameters<ProtoJsonReq>,
430        req_ctx: RequestContext<RoleServer>,
431    ) -> std::result::Result<String, String> {
432        run_qot_proto_json::<futu_proto::qot_get_ark_fund_holding::C2s, _, _>(
433            self,
434            "futu_get_ark_fund_holding",
435            "ark-fund-holding",
436            req,
437            req_ctx,
438            |client, c2s| async move { handlers::proto_json::ark_fund_holding(&client, c2s).await },
439        )
440        .await
441    }
442
443    async fn futu_get_ark_stock_dynamic_impl(
444        &self,
445        Parameters(req): Parameters<ProtoJsonReq>,
446        req_ctx: RequestContext<RoleServer>,
447    ) -> std::result::Result<String, String> {
448        run_qot_proto_json::<futu_proto::qot_get_ark_stock_dynamic::C2s, _, _>(
449            self,
450            "futu_get_ark_stock_dynamic",
451            "ark-stock-dynamic",
452            req,
453            req_ctx,
454            |client, c2s| async move { handlers::proto_json::ark_stock_dynamic(&client, c2s).await },
455        )
456        .await
457    }
458
459    async fn futu_get_ark_active_transaction_impl(
460        &self,
461        Parameters(req): Parameters<ProtoJsonReq>,
462        req_ctx: RequestContext<RoleServer>,
463    ) -> std::result::Result<String, String> {
464        run_qot_proto_json::<futu_proto::qot_get_ark_active_transaction::C2s, _, _>(
465            self,
466            "futu_get_ark_active_transaction",
467            "ark-active-transaction",
468            req,
469            req_ctx,
470            |client, c2s| async move {
471                handlers::proto_json::ark_active_transaction(&client, c2s).await
472            },
473        )
474        .await
475    }
476
477    async fn futu_get_rating_change_impl(
478        &self,
479        Parameters(req): Parameters<ProtoJsonReq>,
480        req_ctx: RequestContext<RoleServer>,
481    ) -> std::result::Result<String, String> {
482        run_qot_proto_json::<futu_proto::qot_get_rating_change::C2s, _, _>(
483            self,
484            "futu_get_rating_change",
485            "rating-change",
486            req,
487            req_ctx,
488            |client, c2s| async move { handlers::proto_json::rating_change(&client, c2s).await },
489        )
490        .await
491    }
492
493    async fn futu_get_industrial_chain_list_impl(
494        &self,
495        Parameters(req): Parameters<ProtoJsonReq>,
496        req_ctx: RequestContext<RoleServer>,
497    ) -> std::result::Result<String, String> {
498        run_qot_proto_json::<futu_proto::qot_get_industrial_chain_list::C2s, _, _>(
499            self,
500            "futu_get_industrial_chain_list",
501            "industrial-chain-list",
502            req,
503            req_ctx,
504            |client, c2s| async move {
505                handlers::proto_json::industrial_chain_list(&client, c2s).await
506            },
507        )
508        .await
509    }
510
511    async fn futu_get_industrial_chain_detail_impl(
512        &self,
513        Parameters(req): Parameters<ProtoJsonReq>,
514        req_ctx: RequestContext<RoleServer>,
515    ) -> std::result::Result<String, String> {
516        run_qot_proto_json::<futu_proto::qot_get_industrial_chain_detail::C2s, _, _>(
517            self,
518            "futu_get_industrial_chain_detail",
519            "industrial-chain-detail",
520            req,
521            req_ctx,
522            |client, c2s| async move {
523                handlers::proto_json::industrial_chain_detail(&client, c2s).await
524            },
525        )
526        .await
527    }
528
529    async fn futu_get_industrial_chain_by_plate_impl(
530        &self,
531        Parameters(req): Parameters<ProtoJsonReq>,
532        req_ctx: RequestContext<RoleServer>,
533    ) -> std::result::Result<String, String> {
534        run_qot_proto_json::<futu_proto::qot_get_industrial_chain_by_plate::C2s, _, _>(
535            self,
536            "futu_get_industrial_chain_by_plate",
537            "industrial-chain-by-plate",
538            req,
539            req_ctx,
540            |client, c2s| async move {
541                handlers::proto_json::industrial_chain_by_plate(&client, c2s).await
542            },
543        )
544        .await
545    }
546
547    async fn futu_get_industrial_plate_info_impl(
548        &self,
549        Parameters(req): Parameters<ProtoJsonReq>,
550        req_ctx: RequestContext<RoleServer>,
551    ) -> std::result::Result<String, String> {
552        run_qot_proto_json::<futu_proto::qot_get_industrial_plate_info::C2s, _, _>(
553            self,
554            "futu_get_industrial_plate_info",
555            "industrial-plate-info",
556            req,
557            req_ctx,
558            |client, c2s| async move {
559                handlers::proto_json::industrial_plate_info(&client, c2s).await
560            },
561        )
562        .await
563    }
564
565    async fn futu_get_industrial_plate_stock_impl(
566        &self,
567        Parameters(req): Parameters<ProtoJsonReq>,
568        req_ctx: RequestContext<RoleServer>,
569    ) -> std::result::Result<String, String> {
570        run_qot_proto_json::<futu_proto::qot_get_industrial_plate_stock::C2s, _, _>(
571            self,
572            "futu_get_industrial_plate_stock",
573            "industrial-plate-stock",
574            req,
575            req_ctx,
576            |client, c2s| async move {
577                handlers::proto_json::industrial_plate_stock(&client, c2s).await
578            },
579        )
580        .await
581    }
582
583    async fn futu_get_heat_map_data_impl(
584        &self,
585        Parameters(req): Parameters<ProtoJsonReq>,
586        req_ctx: RequestContext<RoleServer>,
587    ) -> std::result::Result<String, String> {
588        run_qot_proto_json::<futu_proto::qot_get_heat_map_data::C2s, _, _>(
589            self,
590            "futu_get_heat_map_data",
591            "heat-map-data",
592            req,
593            req_ctx,
594            |client, c2s| async move { handlers::proto_json::heat_map_data(&client, c2s).await },
595        )
596        .await
597    }
598
599    async fn futu_get_rise_fall_distribution_impl(
600        &self,
601        Parameters(req): Parameters<ProtoJsonReq>,
602        req_ctx: RequestContext<RoleServer>,
603    ) -> std::result::Result<String, String> {
604        run_qot_proto_json::<futu_proto::qot_get_rise_fall_distribution::C2s, _, _>(
605            self,
606            "futu_get_rise_fall_distribution",
607            "rise-fall-distribution",
608            req,
609            req_ctx,
610            |client, c2s| async move {
611                handlers::proto_json::rise_fall_distribution(&client, c2s).await
612            },
613        )
614        .await
615    }
616}
617
618include!(concat!(
619    env!("OUT_DIR"),
620    "/generated_mcp_routes_qot_3401_plus.rs"
621));