Skip to main content

futu_mcp/tools/
reference_screen_unusual.rs

1//! MCP v10.6 screen and unusual-move reference tools.
2
3use 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_screen_unusual_tool_router, vis = "pub(crate)")]
12impl FutuServer {
13    #[tool(
14        description = "Stock screener. Futu API v10.6: OpenQuoteContext.stock_screen. The c2s argument is the full Qot_StockScreen C2S JSON object."
15    )]
16    async fn futu_stock_screen(
17        &self,
18        Parameters(req): Parameters<StockScreenReq>,
19        req_ctx: RequestContext<RoleServer>,
20    ) -> std::result::Result<String, String> {
21        tracing::info!(tool = "futu_stock_screen");
22        let client = self
23            .read_client_or_err("futu_stock_screen", &req_ctx, None, None)
24            .await?;
25        Self::wrap_result(handlers::reference::stock_screen(&client, req.c2s).await)
26    }
27
28    #[tool(
29        description = "Option screener. Futu API v10.6: OpenQuoteContext.option_screen. The c2s argument is the full Qot_OptionScreen C2S JSON object."
30    )]
31    async fn futu_option_screen(
32        &self,
33        Parameters(req): Parameters<OptionScreenReq>,
34        req_ctx: RequestContext<RoleServer>,
35    ) -> std::result::Result<String, String> {
36        tracing::info!(tool = "futu_option_screen");
37        let client = self
38            .read_client_or_err("futu_option_screen", &req_ctx, None, None)
39            .await?;
40        Self::wrap_result(handlers::reference::option_screen(&client, req.c2s).await)
41    }
42
43    #[tool(
44        description = "Warrant screener. Futu API v10.6: OpenQuoteContext.warrant_screen. The c2s argument is the full Qot_WarrantScreen C2S JSON object."
45    )]
46    async fn futu_warrant_screen(
47        &self,
48        Parameters(req): Parameters<WarrantScreenReq>,
49        req_ctx: RequestContext<RoleServer>,
50    ) -> std::result::Result<String, String> {
51        tracing::info!(tool = "futu_warrant_screen");
52        let client = self
53            .read_client_or_err("futu_warrant_screen", &req_ctx, None, None)
54            .await?;
55        Self::wrap_result(handlers::reference::warrant_screen(&client, req.c2s).await)
56    }
57
58    #[tool(
59        description = "Technical indicator unusual-move summary. Futu API v10.6: OpenQuoteContext.get_technical_unusual."
60    )]
61    async fn futu_get_technical_unusual(
62        &self,
63        Parameters(req): Parameters<TechnicalUnusualReq>,
64        req_ctx: RequestContext<RoleServer>,
65    ) -> std::result::Result<String, String> {
66        tracing::info!(
67            tool = "futu_get_technical_unusual",
68            stock_symbol = %req.stock_symbol,
69            time_range = ?req.time_range,
70            indicator_filter_count = req.indicator_filters.len(),
71            language_id = ?req.language_id
72        );
73        let client = self
74            .read_client_or_err("futu_get_technical_unusual", &req_ctx, None, None)
75            .await?;
76        Self::wrap_result(
77            handlers::reference::get_technical_unusual(
78                &client,
79                &req.stock_symbol,
80                req.time_range,
81                req.indicator_filters,
82                req.language_id,
83            )
84            .await,
85        )
86    }
87
88    #[tool(
89        description = "Financial unusual-change summary. Futu API v10.6: OpenQuoteContext.get_financial_unusual."
90    )]
91    async fn futu_get_financial_unusual(
92        &self,
93        Parameters(req): Parameters<FinancialUnusualReq>,
94        req_ctx: RequestContext<RoleServer>,
95    ) -> std::result::Result<String, String> {
96        tracing::info!(
97            tool = "futu_get_financial_unusual",
98            stock_symbol = %req.stock_symbol,
99            time_range = ?req.time_range,
100            analysis_dimension_count = req.analysis_dimensions.len(),
101            language_id = ?req.language_id
102        );
103        let client = self
104            .read_client_or_err("futu_get_financial_unusual", &req_ctx, None, None)
105            .await?;
106        Self::wrap_result(
107            handlers::reference::get_financial_unusual(
108                &client,
109                &req.stock_symbol,
110                req.time_range,
111                req.analysis_dimensions,
112                req.language_id,
113            )
114            .await,
115        )
116    }
117
118    #[tool(
119        description = "Derivative unusual-change summary. Futu API v10.6: OpenQuoteContext.get_derivative_unusual."
120    )]
121    async fn futu_get_derivative_unusual(
122        &self,
123        Parameters(req): Parameters<DerivativeUnusualReq>,
124        req_ctx: RequestContext<RoleServer>,
125    ) -> std::result::Result<String, String> {
126        tracing::info!(
127            tool = "futu_get_derivative_unusual",
128            stock_symbol = %req.stock_symbol,
129            time_range = ?req.time_range,
130            analysis_dimension_count = req.analysis_dimensions.len(),
131            language_id = ?req.language_id
132        );
133        let client = self
134            .read_client_or_err("futu_get_derivative_unusual", &req_ctx, None, None)
135            .await?;
136        Self::wrap_result(
137            handlers::reference::get_derivative_unusual(
138                &client,
139                &req.stock_symbol,
140                req.time_range,
141                req.analysis_dimensions,
142                req.language_id,
143            )
144            .await,
145        )
146    }
147}