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_f10_tool_router, vis = "pub(crate)")]
12impl FutuServer {
13 #[tool(
14 description = "Company operational efficiency metrics such as employees and per-capita income/profit. Futu API v10.6: OpenQuoteContext.get_company_operational_efficiency."
15 )]
16 async fn futu_get_company_operational_efficiency(
17 &self,
18 Parameters(req): Parameters<CompanyOperationalEfficiencyReq>,
19 req_ctx: RequestContext<RoleServer>,
20 ) -> std::result::Result<String, String> {
21 req.validate()?;
22 tracing::info!(
23 tool = "futu_get_company_operational_efficiency",
24 symbol = %req.symbol,
25 next_key = %crate::state::audit_fmt::opt_str(req.next_key.as_deref()),
26 num = ?req.num,
27 currency_code = %crate::state::audit_fmt::opt_str(req.currency_code.as_deref()),
28 financial_type = ?req.financial_type
29 );
30 let client = self
31 .read_client_or_err(
32 "futu_get_company_operational_efficiency",
33 &req_ctx,
34 None,
35 None,
36 )
37 .await?;
38 Self::wrap_result(
39 handlers::reference::get_company_operational_efficiency(
40 &client,
41 &req.symbol,
42 req.next_key.as_deref(),
43 req.num,
44 req.currency_code.as_deref(),
45 req.financial_type,
46 )
47 .await,
48 )
49 }
50
51 #[tool(
52 description = "Price move around financial earnings announcement dates. Futu API v10.6: OpenQuoteContext.get_financials_earnings_price_move."
53 )]
54 async fn futu_get_financials_earnings_price_move(
55 &self,
56 Parameters(req): Parameters<FinancialsEarningsPriceMoveReq>,
57 req_ctx: RequestContext<RoleServer>,
58 ) -> std::result::Result<String, String> {
59 req.validate()?;
60 tracing::info!(
61 tool = "futu_get_financials_earnings_price_move",
62 symbol = %req.symbol,
63 period_count = ?req.period_count
64 );
65 let client = self
66 .read_client_or_err(
67 "futu_get_financials_earnings_price_move",
68 &req_ctx,
69 None,
70 None,
71 )
72 .await?;
73 Self::wrap_result(
74 handlers::reference::get_financials_earnings_price_move(
75 &client,
76 &req.symbol,
77 req.period_count,
78 )
79 .await,
80 )
81 }
82
83 #[tool(
84 description = "Price history around financial earnings announcement dates. Futu API v10.6: OpenQuoteContext.get_financials_earnings_price_history."
85 )]
86 async fn futu_get_financials_earnings_price_history(
87 &self,
88 Parameters(req): Parameters<FinancialsEarningsPriceHistoryReq>,
89 req_ctx: RequestContext<RoleServer>,
90 ) -> std::result::Result<String, String> {
91 tracing::info!(
92 tool = "futu_get_financials_earnings_price_history",
93 symbol = %req.symbol
94 );
95 let client = self
96 .read_client_or_err(
97 "futu_get_financials_earnings_price_history",
98 &req_ctx,
99 None,
100 None,
101 )
102 .await?;
103 Self::wrap_result(
104 handlers::reference::get_financials_earnings_price_history(&client, &req.symbol).await,
105 )
106 }
107
108 #[tool(
109 description = "Financial statements. Futu API v10.6: OpenQuoteContext.get_financials_statements."
110 )]
111 async fn futu_get_financials_statements(
112 &self,
113 Parameters(req): Parameters<FinancialsStatementsReq>,
114 req_ctx: RequestContext<RoleServer>,
115 ) -> std::result::Result<String, String> {
116 req.validate()?;
117 tracing::info!(
118 tool = "futu_get_financials_statements",
119 symbol = %req.symbol,
120 statement_type = ?req.statement_type,
121 financial_type = ?req.financial_type,
122 currency_code = ?req.currency_code,
123 next_key = ?req.next_key,
124 num = ?req.num
125 );
126 let client = self
127 .read_client_or_err("futu_get_financials_statements", &req_ctx, None, None)
128 .await?;
129 Self::wrap_result(
130 handlers::reference::get_financials_statements(
131 &client,
132 &req.symbol,
133 req.statement_type,
134 req.financial_type,
135 req.currency_code.as_deref(),
136 req.next_key.as_deref(),
137 req.num,
138 )
139 .await,
140 )
141 }
142
143 #[tool(
144 description = "Financials revenue breakdown. Futu API v10.6: OpenQuoteContext.get_financials_revenue_breakdown."
145 )]
146 async fn futu_get_financials_revenue_breakdown(
147 &self,
148 Parameters(req): Parameters<FinancialsRevenueBreakdownReq>,
149 req_ctx: RequestContext<RoleServer>,
150 ) -> std::result::Result<String, String> {
151 req.validate()?;
152 tracing::info!(
153 tool = "futu_get_financials_revenue_breakdown",
154 symbol = %req.symbol,
155 date = ?req.date,
156 financial_type = ?req.financial_type,
157 currency_code = ?req.currency_code
158 );
159 let client = self
160 .read_client_or_err(
161 "futu_get_financials_revenue_breakdown",
162 &req_ctx,
163 None,
164 None,
165 )
166 .await?;
167 Self::wrap_result(
168 handlers::reference::get_financials_revenue_breakdown(
169 &client,
170 &req.symbol,
171 req.date,
172 req.financial_type,
173 req.currency_code.as_deref(),
174 )
175 .await,
176 )
177 }
178
179 #[tool(
180 description = "Research analyst consensus. Futu API v10.6: OpenQuoteContext.get_research_analyst_consensus."
181 )]
182 async fn futu_get_research_analyst_consensus(
183 &self,
184 Parameters(req): Parameters<ResearchAnalystConsensusReq>,
185 req_ctx: RequestContext<RoleServer>,
186 ) -> std::result::Result<String, String> {
187 tracing::info!(
188 tool = "futu_get_research_analyst_consensus",
189 symbol = %req.symbol
190 );
191 let client = self
192 .read_client_or_err("futu_get_research_analyst_consensus", &req_ctx, None, None)
193 .await?;
194 Self::wrap_result(
195 handlers::reference::get_research_analyst_consensus(&client, &req.symbol).await,
196 )
197 }
198
199 #[tool(
200 description = "Research rating summary/detail list. Futu API v10.6: OpenQuoteContext.get_research_rating_summary."
201 )]
202 async fn futu_get_research_rating_summary(
203 &self,
204 Parameters(req): Parameters<ResearchRatingSummaryReq>,
205 req_ctx: RequestContext<RoleServer>,
206 ) -> std::result::Result<String, String> {
207 req.validate()?;
208 tracing::info!(
209 tool = "futu_get_research_rating_summary",
210 symbol = %req.symbol,
211 rating_dimension_type = ?req.rating_dimension_type,
212 uid = ?req.uid,
213 next_key = ?req.next_key,
214 num = ?req.num
215 );
216 let client = self
217 .read_client_or_err("futu_get_research_rating_summary", &req_ctx, None, None)
218 .await?;
219 Self::wrap_result(
220 handlers::reference::get_research_rating_summary(
221 &client,
222 &req.symbol,
223 req.rating_dimension_type,
224 req.uid.as_deref(),
225 req.next_key.as_deref(),
226 req.num,
227 )
228 .await,
229 )
230 }
231
232 #[tool(
233 description = "Morningstar research report. Futu API v10.6: OpenQuoteContext.get_research_morningstar_report."
234 )]
235 async fn futu_get_research_morningstar_report(
236 &self,
237 Parameters(req): Parameters<ResearchMorningstarReportReq>,
238 req_ctx: RequestContext<RoleServer>,
239 ) -> std::result::Result<String, String> {
240 tracing::info!(
241 tool = "futu_get_research_morningstar_report",
242 symbol = %req.symbol
243 );
244 let client = self
245 .read_client_or_err("futu_get_research_morningstar_report", &req_ctx, None, None)
246 .await?;
247 Self::wrap_result(
248 handlers::reference::get_research_morningstar_report(&client, &req.symbol).await,
249 )
250 }
251
252 #[tool(
253 description = "Valuation detail for a stock or index. Futu API v10.6: OpenQuoteContext.get_valuation_detail."
254 )]
255 async fn futu_get_valuation_detail(
256 &self,
257 Parameters(req): Parameters<ValuationDetailReq>,
258 req_ctx: RequestContext<RoleServer>,
259 ) -> std::result::Result<String, String> {
260 req.validate()?;
261 tracing::info!(
262 tool = "futu_get_valuation_detail",
263 symbol = %req.symbol,
264 valuation_type = ?req.valuation_type,
265 interval_type = ?req.interval_type
266 );
267 let client = self
268 .read_client_or_err("futu_get_valuation_detail", &req_ctx, None, None)
269 .await?;
270 Self::wrap_result(
271 handlers::reference::get_valuation_detail(
272 &client,
273 &req.symbol,
274 req.valuation_type,
275 req.interval_type,
276 )
277 .await,
278 )
279 }
280
281 #[tool(
282 description = "Valuation stock list for a plate or index. Futu API v10.6: OpenQuoteContext.get_valuation_plate_stock_list."
283 )]
284 async fn futu_get_valuation_plate_stock_list(
285 &self,
286 Parameters(req): Parameters<ValuationPlateStockListReq>,
287 req_ctx: RequestContext<RoleServer>,
288 ) -> std::result::Result<String, String> {
289 req.validate()?;
290 tracing::info!(
291 tool = "futu_get_valuation_plate_stock_list",
292 symbol = %req.symbol,
293 valuation_type = ?req.valuation_type,
294 next_key = ?req.next_key,
295 num = ?req.num,
296 sort_type = ?req.sort_type,
297 sort_id = ?req.sort_id,
298 filter_security = ?req.filter_security
299 );
300 let client = self
301 .read_client_or_err("futu_get_valuation_plate_stock_list", &req_ctx, None, None)
302 .await?;
303 Self::wrap_result(
304 handlers::reference::get_valuation_plate_stock_list(
305 &client,
306 &req.symbol,
307 req.valuation_type,
308 req.next_key.as_deref(),
309 req.num,
310 req.sort_type,
311 req.sort_id,
312 req.filter_security.as_deref(),
313 )
314 .await,
315 )
316 }
317}