Skip to main content

futu_mcp/tools/
reference_f10.rs

1//! MCP F10, financials, research, and valuation reference tools.
2
3use crate::handlers;
4use crate::tool_args::*;
5use rmcp::{RoleServer, handler::server::wrapper::Parameters, service::RequestContext};
6
7use super::FutuServer;
8
9impl FutuServer {
10    async fn futu_get_company_operational_efficiency_impl(
11        &self,
12        Parameters(req): Parameters<CompanyOperationalEfficiencyReq>,
13        req_ctx: RequestContext<RoleServer>,
14    ) -> std::result::Result<String, String> {
15        req.validate()?;
16        tracing::info!(
17            tool = "futu_get_company_operational_efficiency",
18            symbol = %req.symbol,
19            next_key = %crate::state::audit_fmt::opt_str(req.next_key.as_deref()),
20            num = ?req.num,
21            currency_code = %crate::state::audit_fmt::opt_str(req.currency_code.as_deref()),
22            financial_type = ?req.financial_type
23        );
24        let client = self
25            .read_client_or_err(
26                "futu_get_company_operational_efficiency",
27                &req_ctx,
28                None,
29                None,
30            )
31            .await?;
32        Self::wrap_result(
33            handlers::reference::get_company_operational_efficiency(
34                &client,
35                &req.symbol,
36                req.next_key.as_deref(),
37                req.num,
38                req.currency_code.as_deref(),
39                req.financial_type,
40            )
41            .await,
42        )
43    }
44
45    async fn futu_get_financials_earnings_price_move_impl(
46        &self,
47        Parameters(req): Parameters<FinancialsEarningsPriceMoveReq>,
48        req_ctx: RequestContext<RoleServer>,
49    ) -> std::result::Result<String, String> {
50        req.validate()?;
51        tracing::info!(
52            tool = "futu_get_financials_earnings_price_move",
53            symbol = %req.symbol,
54            period_count = ?req.period_count
55        );
56        let client = self
57            .read_client_or_err(
58                "futu_get_financials_earnings_price_move",
59                &req_ctx,
60                None,
61                None,
62            )
63            .await?;
64        Self::wrap_result(
65            handlers::reference::get_financials_earnings_price_move(
66                &client,
67                &req.symbol,
68                req.period_count,
69            )
70            .await,
71        )
72    }
73
74    async fn futu_get_financials_earnings_price_history_impl(
75        &self,
76        Parameters(req): Parameters<FinancialsEarningsPriceHistoryReq>,
77        req_ctx: RequestContext<RoleServer>,
78    ) -> std::result::Result<String, String> {
79        tracing::info!(
80            tool = "futu_get_financials_earnings_price_history",
81            symbol = %req.symbol
82        );
83        let client = self
84            .read_client_or_err(
85                "futu_get_financials_earnings_price_history",
86                &req_ctx,
87                None,
88                None,
89            )
90            .await?;
91        Self::wrap_result(
92            handlers::reference::get_financials_earnings_price_history(&client, &req.symbol).await,
93        )
94    }
95
96    async fn futu_get_financial_calendar_impl(
97        &self,
98        Parameters(req): Parameters<FinancialCalendarReq>,
99        req_ctx: RequestContext<RoleServer>,
100    ) -> std::result::Result<String, String> {
101        req.validate()?;
102        tracing::info!(
103            tool = "futu_get_financial_calendar",
104            begin_date = %req.begin_date,
105            end_date = %req.end_date,
106            markets = ?req.market_list,
107            count = ?req.count,
108            watchlist_stock_ids = req.watchlist_stock_ids.len(),
109            holding_stock_ids = req.holding_stock_ids.len()
110        );
111        let client = self
112            .read_client_or_err("futu_get_financial_calendar", &req_ctx, None, None)
113            .await?;
114        Self::wrap_result(
115            handlers::reference::get_financial_calendar(&client, req.to_proto()).await,
116        )
117    }
118
119    async fn futu_search_target_financial_calendar_impl(
120        &self,
121        Parameters(req): Parameters<TargetFinancialCalendarReq>,
122        req_ctx: RequestContext<RoleServer>,
123    ) -> std::result::Result<String, String> {
124        req.validate()?;
125        tracing::info!(
126            tool = "futu_search_target_financial_calendar",
127            stock_ids = req.stock_id.len(),
128            markets = ?req.market_list,
129            size = req.size,
130            start = ?req.start
131        );
132        let client = self
133            .read_client_or_err(
134                "futu_search_target_financial_calendar",
135                &req_ctx,
136                None,
137                None,
138            )
139            .await?;
140        Self::wrap_result(
141            handlers::reference::search_target_financial_calendar(&client, req.to_proto()).await,
142        )
143    }
144
145    async fn futu_get_financials_statements_impl(
146        &self,
147        Parameters(req): Parameters<FinancialsStatementsReq>,
148        req_ctx: RequestContext<RoleServer>,
149    ) -> std::result::Result<String, String> {
150        req.validate()?;
151        tracing::info!(
152            tool = "futu_get_financials_statements",
153            symbol = %req.symbol,
154            statement_type = ?req.statement_type,
155            financial_type = ?req.financial_type,
156            currency_code = ?req.currency_code,
157            next_key = ?req.next_key,
158            num = ?req.num
159        );
160        let client = self
161            .read_client_or_err("futu_get_financials_statements", &req_ctx, None, None)
162            .await?;
163        Self::wrap_result(
164            handlers::reference::get_financials_statements(
165                &client,
166                &req.symbol,
167                req.statement_type,
168                req.financial_type,
169                req.currency_code.as_deref(),
170                req.next_key.as_deref(),
171                req.num,
172            )
173            .await,
174        )
175    }
176
177    async fn futu_get_financials_revenue_breakdown_impl(
178        &self,
179        Parameters(req): Parameters<FinancialsRevenueBreakdownReq>,
180        req_ctx: RequestContext<RoleServer>,
181    ) -> std::result::Result<String, String> {
182        req.validate()?;
183        tracing::info!(
184            tool = "futu_get_financials_revenue_breakdown",
185            symbol = %req.symbol,
186            date = ?req.date,
187            financial_type = ?req.financial_type,
188            currency_code = ?req.currency_code
189        );
190        let client = self
191            .read_client_or_err(
192                "futu_get_financials_revenue_breakdown",
193                &req_ctx,
194                None,
195                None,
196            )
197            .await?;
198        Self::wrap_result(
199            handlers::reference::get_financials_revenue_breakdown(
200                &client,
201                &req.symbol,
202                req.date,
203                req.financial_type,
204                req.currency_code.as_deref(),
205            )
206            .await,
207        )
208    }
209
210    async fn futu_get_research_analyst_consensus_impl(
211        &self,
212        Parameters(req): Parameters<ResearchAnalystConsensusReq>,
213        req_ctx: RequestContext<RoleServer>,
214    ) -> std::result::Result<String, String> {
215        tracing::info!(
216            tool = "futu_get_research_analyst_consensus",
217            symbol = %req.symbol
218        );
219        let client = self
220            .read_client_or_err("futu_get_research_analyst_consensus", &req_ctx, None, None)
221            .await?;
222        Self::wrap_result(
223            handlers::reference::get_research_analyst_consensus(&client, &req.symbol).await,
224        )
225    }
226
227    async fn futu_get_research_rating_summary_impl(
228        &self,
229        Parameters(req): Parameters<ResearchRatingSummaryReq>,
230        req_ctx: RequestContext<RoleServer>,
231    ) -> std::result::Result<String, String> {
232        req.validate()?;
233        let research_uid_fp = req
234            .uid
235            .as_deref()
236            .map(futu_core::log_redact::account_log_fingerprint);
237        tracing::info!(
238            tool = "futu_get_research_rating_summary",
239            symbol = %req.symbol,
240            rating_dimension_type = ?req.rating_dimension_type,
241            research_uid_fp = ?research_uid_fp,
242            next_key = ?req.next_key,
243            num = ?req.num
244        );
245        let client = self
246            .read_client_or_err("futu_get_research_rating_summary", &req_ctx, None, None)
247            .await?;
248        Self::wrap_result(
249            handlers::reference::get_research_rating_summary(
250                &client,
251                &req.symbol,
252                req.rating_dimension_type,
253                req.uid.as_deref(),
254                req.next_key.as_deref(),
255                req.num,
256            )
257            .await,
258        )
259    }
260
261    async fn futu_get_research_morningstar_report_impl(
262        &self,
263        Parameters(req): Parameters<ResearchMorningstarReportReq>,
264        req_ctx: RequestContext<RoleServer>,
265    ) -> std::result::Result<String, String> {
266        tracing::info!(
267            tool = "futu_get_research_morningstar_report",
268            symbol = %req.symbol
269        );
270        let client = self
271            .read_client_or_err("futu_get_research_morningstar_report", &req_ctx, None, None)
272            .await?;
273        Self::wrap_result(
274            handlers::reference::get_research_morningstar_report(&client, &req.symbol).await,
275        )
276    }
277
278    async fn futu_get_valuation_detail_impl(
279        &self,
280        Parameters(req): Parameters<ValuationDetailReq>,
281        req_ctx: RequestContext<RoleServer>,
282    ) -> std::result::Result<String, String> {
283        req.validate()?;
284        tracing::info!(
285            tool = "futu_get_valuation_detail",
286            symbol = %req.symbol,
287            valuation_type = ?req.valuation_type,
288            interval_type = ?req.interval_type
289        );
290        let client = self
291            .read_client_or_err("futu_get_valuation_detail", &req_ctx, None, None)
292            .await?;
293        Self::wrap_result(
294            handlers::reference::get_valuation_detail(
295                &client,
296                &req.symbol,
297                req.valuation_type,
298                req.interval_type,
299            )
300            .await,
301        )
302    }
303
304    async fn futu_get_valuation_plate_stock_list_impl(
305        &self,
306        Parameters(req): Parameters<ValuationPlateStockListReq>,
307        req_ctx: RequestContext<RoleServer>,
308    ) -> std::result::Result<String, String> {
309        req.validate()?;
310        tracing::info!(
311            tool = "futu_get_valuation_plate_stock_list",
312            symbol = %req.symbol,
313            valuation_type = ?req.valuation_type,
314            next_key = ?req.next_key,
315            num = ?req.num,
316            sort_type = ?req.sort_type,
317            sort_id = ?req.sort_id,
318            filter_security = ?req.filter_security
319        );
320        let client = self
321            .read_client_or_err("futu_get_valuation_plate_stock_list", &req_ctx, None, None)
322            .await?;
323        Self::wrap_result(
324            handlers::reference::get_valuation_plate_stock_list(
325                &client,
326                &req.symbol,
327                req.valuation_type,
328                req.next_key.as_deref(),
329                req.num,
330                req.sort_type,
331                req.sort_id,
332                req.filter_security.as_deref(),
333            )
334            .await,
335        )
336    }
337}
338
339include!(concat!(
340    env!("OUT_DIR"),
341    "/generated_mcp_routes_reference_f10.rs"
342));