1use crate::handlers;
4use crate::tool_args::*;
5use rmcp::{RoleServer, handler::server::wrapper::Parameters, service::RequestContext};
6
7use super::FutuServer;
8
9mod option_chain;
10use option_chain::option_chain_data_filter;
11
12impl FutuServer {
13 async fn futu_get_capital_flow_impl(
16 &self,
17 Parameters(req): Parameters<CapitalFlowReq>,
18 req_ctx: RequestContext<RoleServer>,
19 ) -> std::result::Result<String, String> {
20 tracing::info!(tool = "futu_get_capital_flow", symbol = %req.symbol);
21 let client = self
22 .read_client_or_err("futu_get_capital_flow", &req_ctx, None, None)
23 .await?;
24 Self::wrap_result(
25 handlers::analysis::get_capital_flow(
26 &client,
27 &req.symbol,
28 req.period_type,
29 req.begin_time,
30 req.end_time,
31 )
32 .await,
33 )
34 }
35
36 async fn futu_get_capital_distribution_impl(
37 &self,
38 Parameters(req): Parameters<SymbolReq>,
39 req_ctx: RequestContext<RoleServer>,
40 ) -> std::result::Result<String, String> {
41 tracing::info!(tool = "futu_get_capital_distribution", symbol = %req.symbol);
42 let client = self
43 .read_client_or_err("futu_get_capital_distribution", &req_ctx, None, None)
44 .await?;
45 Self::wrap_result(handlers::analysis::get_capital_distribution(&client, &req.symbol).await)
46 }
47
48 async fn futu_get_company_profile_impl(
49 &self,
50 Parameters(req): Parameters<SymbolReq>,
51 req_ctx: RequestContext<RoleServer>,
52 ) -> std::result::Result<String, String> {
53 tracing::info!(tool = "futu_get_company_profile", symbol = %req.symbol);
54 let client = self
55 .read_client_or_err("futu_get_company_profile", &req_ctx, None, None)
56 .await?;
57 Self::wrap_result(handlers::reference::get_company_profile(&client, &req.symbol).await)
58 }
59
60 async fn futu_get_company_executives_impl(
61 &self,
62 Parameters(req): Parameters<SymbolReq>,
63 req_ctx: RequestContext<RoleServer>,
64 ) -> std::result::Result<String, String> {
65 tracing::info!(tool = "futu_get_company_executives", symbol = %req.symbol);
66 let client = self
67 .read_client_or_err("futu_get_company_executives", &req_ctx, None, None)
68 .await?;
69 Self::wrap_result(handlers::reference::get_company_executives(&client, &req.symbol).await)
70 }
71
72 async fn futu_get_company_executive_background_impl(
73 &self,
74 Parameters(req): Parameters<CompanyExecutiveBackgroundReq>,
75 req_ctx: RequestContext<RoleServer>,
76 ) -> std::result::Result<String, String> {
77 tracing::info!(
78 tool = "futu_get_company_executive_background",
79 symbol = %req.symbol,
80 leader_name = %req.leader_name
81 );
82 let client = self
83 .read_client_or_err(
84 "futu_get_company_executive_background",
85 &req_ctx,
86 None,
87 None,
88 )
89 .await?;
90 Self::wrap_result(
91 handlers::reference::get_company_executive_background(
92 &client,
93 &req.symbol,
94 &req.leader_name,
95 )
96 .await,
97 )
98 }
99
100 async fn futu_get_market_state_impl(
101 &self,
102 Parameters(req): Parameters<MarketStateReq>,
103 req_ctx: RequestContext<RoleServer>,
104 ) -> std::result::Result<String, String> {
105 tracing::info!(tool = "futu_get_market_state", count = req.symbols.len());
106 let client = self
107 .read_client_or_err("futu_get_market_state", &req_ctx, None, None)
108 .await?;
109 Self::wrap_result(handlers::analysis::get_market_state(&client, &req.symbols).await)
110 }
111
112 async fn futu_get_history_kline_impl(
115 &self,
116 Parameters(req): Parameters<HistoryKLineReq>,
117 req_ctx: RequestContext<RoleServer>,
118 ) -> std::result::Result<String, String> {
119 let max_count = req.validated_max_count()?;
120 let session = req.validated_session()?;
121 let next_req_key = req.decoded_next_req_key()?;
122 tracing::info!(
123 tool = "futu_get_history_kline",
124 symbol = %req.symbol,
125 kl_type = %req.kl_type,
126 rehab = %req.rehab_type,
127 extended_time = ?req.extended_time,
128 session = ?session,
129 has_next_req_key = next_req_key.is_some(),
130 );
131 let client = self
132 .read_client_or_err("futu_get_history_kline", &req_ctx, None, None)
133 .await?;
134 Self::wrap_result(
135 handlers::analysis::get_history_kline(
136 &client,
137 &req.symbol,
138 &req.kl_type,
139 &req.rehab_type,
140 &req.begin,
141 &req.end,
142 max_count,
143 req.need_kl_fields_flag,
144 req.extended_time,
145 session,
146 next_req_key.as_deref(),
147 )
148 .await,
149 )
150 }
151
152 async fn futu_get_owner_plate_impl(
153 &self,
154 Parameters(req): Parameters<SymbolListReq>,
155 req_ctx: RequestContext<RoleServer>,
156 ) -> std::result::Result<String, String> {
157 tracing::info!(tool = "futu_get_owner_plate", count = req.symbols.len());
158 let client = self
159 .read_client_or_err("futu_get_owner_plate", &req_ctx, None, None)
160 .await?;
161 Self::wrap_result(handlers::analysis::get_owner_plate(&client, &req.symbols).await)
162 }
163
164 async fn futu_get_reference_impl(
165 &self,
166 Parameters(req): Parameters<ReferenceReq>,
167 req_ctx: RequestContext<RoleServer>,
168 ) -> std::result::Result<String, String> {
169 tracing::info!(
170 tool = "futu_get_reference",
171 symbol = %req.symbol,
172 reference_type = %req.reference_type
173 );
174 let client = self
175 .read_client_or_err("futu_get_reference", &req_ctx, None, None)
176 .await?;
177 Self::wrap_result(
178 handlers::analysis::get_reference(&client, &req.symbol, &req.reference_type).await,
179 )
180 }
181
182 async fn futu_get_option_chain_impl(
183 &self,
184 Parameters(req): Parameters<OptionChainReq>,
185 req_ctx: RequestContext<RoleServer>,
186 ) -> std::result::Result<String, String> {
187 req.validate()?;
188 tracing::info!(
189 tool = "futu_get_option_chain",
190 owner = %req.owner_symbol,
191 begin = %req.begin_time,
192 end = %req.end_time
193 );
194 let client = self
195 .read_client_or_err("futu_get_option_chain", &req_ctx, None, None)
196 .await?;
197 let data_filter = option_chain_data_filter(&req);
199 Self::wrap_result(
200 handlers::analysis::get_option_chain(
201 &client,
202 handlers::analysis::OptionChainInput {
203 owner_symbol: &req.owner_symbol,
204 begin_time: &req.begin_time,
205 end_time: &req.end_time,
206 option_type_str: req.option_type.as_deref(),
207 data_filter,
208 },
209 )
210 .await,
211 )
212 }
213
214 async fn futu_get_warrant_impl(
217 &self,
218 Parameters(req): Parameters<WarrantReq>,
219 req_ctx: RequestContext<RoleServer>,
220 ) -> std::result::Result<String, String> {
221 req.validate()?;
222 tracing::info!(
223 tool = "futu_get_warrant",
224 owner = %crate::state::audit_fmt::opt_str(req.owner_symbol.as_deref()),
226 begin = req.begin,
227 num = req.num
228 );
229 let client = self
230 .read_client_or_err("futu_get_warrant", &req_ctx, None, None)
231 .await?;
232 Self::wrap_result(
233 handlers::reference::get_warrant(
234 &client,
235 req.owner_symbol.as_deref(),
236 req.begin,
237 req.num,
238 )
239 .await,
240 )
241 }
242
243 async fn futu_get_ipo_list_impl(
244 &self,
245 Parameters(req): Parameters<IpoListReq>,
246 req_ctx: RequestContext<RoleServer>,
247 ) -> std::result::Result<String, String> {
248 req.validate()?;
249 tracing::info!(tool = "futu_get_ipo_list", market = req.market);
250 let client = self
251 .read_client_or_err("futu_get_ipo_list", &req_ctx, None, None)
252 .await?;
253 Self::wrap_result(handlers::reference::get_ipo_list(&client, req.market).await)
254 }
255
256 async fn futu_get_ipo_calendar_impl(
257 &self,
258 Parameters(req): Parameters<IpoCalendarReq>,
259 req_ctx: RequestContext<RoleServer>,
260 ) -> std::result::Result<String, String> {
261 req.validate()?;
262 tracing::info!(
263 tool = "futu_get_ipo_calendar",
264 market = req.market,
265 event_types = ?req.event_types,
266 begin_date = ?req.begin_date,
267 end_date = ?req.end_date
268 );
269 let client = self
270 .read_client_or_err("futu_get_ipo_calendar", &req_ctx, None, None)
271 .await?;
272 Self::wrap_result(
273 handlers::reference::get_ipo_calendar(
274 &client,
275 req.market,
276 &req.event_types,
277 req.begin_date.as_deref(),
278 req.end_date.as_deref(),
279 )
280 .await,
281 )
282 }
283
284 async fn futu_get_future_info_impl(
285 &self,
286 Parameters(req): Parameters<FutureInfoReq>,
287 req_ctx: RequestContext<RoleServer>,
288 ) -> std::result::Result<String, String> {
289 tracing::info!(tool = "futu_get_future_info", count = req.symbols.len());
290 let client = self
291 .read_client_or_err("futu_get_future_info", &req_ctx, None, None)
292 .await?;
293 Self::wrap_result(handlers::reference::get_future_info(&client, &req.symbols).await)
294 }
295
296 async fn futu_get_user_security_group_impl(
297 &self,
298 Parameters(req): Parameters<UserSecurityGroupReq>,
299 req_ctx: RequestContext<RoleServer>,
300 ) -> std::result::Result<String, String> {
301 req.validate()?;
302 tracing::info!(
303 tool = "futu_get_user_security_group",
304 group_type = req.group_type
305 );
306 let client = self
307 .read_client_or_err("futu_get_user_security_group", &req_ctx, None, None)
308 .await?;
309 Self::wrap_result(
310 handlers::reference::get_user_security_group(&client, req.group_type).await,
311 )
312 }
313
314 async fn futu_get_stock_filter_impl(
315 &self,
316 Parameters(req): Parameters<StockFilterReq>,
317 req_ctx: RequestContext<RoleServer>,
318 ) -> std::result::Result<String, String> {
319 req.validate()?;
320 tracing::info!(
321 tool = "futu_get_stock_filter",
322 market = req.market,
323 begin = req.begin,
324 num = req.num
325 );
326 let client = self
327 .read_client_or_err("futu_get_stock_filter", &req_ctx, None, None)
328 .await?;
329 Self::wrap_result(
330 handlers::reference::get_stock_filter(&client, req.market, req.begin, req.num).await,
331 )
332 }
333
334 async fn futu_get_trading_days_impl(
337 &self,
338 Parameters(req): Parameters<TradingDaysReq>,
339 req_ctx: RequestContext<RoleServer>,
340 ) -> std::result::Result<String, String> {
341 req.validate()?;
342 tracing::info!(
343 tool = "futu_get_trading_days",
344 market = req.market,
345 begin = %req.begin_time,
346 end = %req.end_time
347 );
348 let client = self
349 .read_client_or_err("futu_get_trading_days", &req_ctx, None, None)
350 .await?;
351 Self::wrap_result(
352 handlers::reference::get_trading_days(
353 &client,
354 req.market,
355 &req.begin_time,
356 &req.end_time,
357 )
358 .await,
359 )
360 }
361
362 async fn futu_get_rehab_impl(
363 &self,
364 Parameters(req): Parameters<SymbolReq>,
365 req_ctx: RequestContext<RoleServer>,
366 ) -> std::result::Result<String, String> {
367 tracing::info!(tool = "futu_get_rehab", symbol = %req.symbol);
368 let client = self
369 .read_client_or_err("futu_get_rehab", &req_ctx, None, None)
370 .await?;
371 Self::wrap_result(handlers::reference::get_rehab(&client, &req.symbol).await)
372 }
373
374 async fn futu_get_suspend_impl(
375 &self,
376 Parameters(req): Parameters<SuspendReq>,
377 req_ctx: RequestContext<RoleServer>,
378 ) -> std::result::Result<String, String> {
379 tracing::info!(
380 tool = "futu_get_suspend",
381 count = req.symbols.len(),
382 begin = %req.begin_time,
383 end = %req.end_time
384 );
385 let client = self
386 .read_client_or_err("futu_get_suspend", &req_ctx, None, None)
387 .await?;
388 Self::wrap_result(
389 handlers::reference::get_suspend(&client, &req.symbols, &req.begin_time, &req.end_time)
390 .await,
391 )
392 }
393
394 async fn futu_get_user_security_impl(
395 &self,
396 Parameters(req): Parameters<UserSecurityReq>,
397 req_ctx: RequestContext<RoleServer>,
398 ) -> std::result::Result<String, String> {
399 tracing::info!(tool = "futu_get_user_security", group = %req.group_name);
400 let client = self
401 .read_client_or_err("futu_get_user_security", &req_ctx, None, None)
402 .await?;
403 Self::wrap_result(handlers::reference::get_user_security(&client, &req.group_name).await)
404 }
405
406 async fn futu_get_global_state_impl(
409 &self,
410 Parameters(_req): Parameters<NoArgs>,
411 req_ctx: RequestContext<RoleServer>,
412 ) -> std::result::Result<String, String> {
413 tracing::info!(tool = "futu_get_global_state");
414 let client = self
415 .read_client_or_err("futu_get_global_state", &req_ctx, None, None)
416 .await?;
417 Self::wrap_result(handlers::core::get_global_state(&client).await)
418 }
419
420 async fn futu_get_user_info_impl(
421 &self,
422 Parameters(_req): Parameters<NoArgs>,
423 req_ctx: RequestContext<RoleServer>,
424 ) -> std::result::Result<String, String> {
425 tracing::info!(tool = "futu_get_user_info");
426 let client = self
427 .read_client_or_err("futu_get_user_info", &req_ctx, None, None)
428 .await?;
429 Self::wrap_result(handlers::core::get_user_info(&client).await)
430 }
431
432 async fn futu_get_quote_rights_impl(
433 &self,
434 Parameters(req): Parameters<QuoteRightsReq>,
435 req_ctx: RequestContext<RoleServer>,
436 ) -> std::result::Result<String, String> {
437 tracing::info!(
438 tool = "futu_get_quote_rights",
439 refresh = req.refresh.unwrap_or(false)
440 );
441 let client = self
442 .read_client_or_err("futu_get_quote_rights", &req_ctx, None, None)
443 .await?;
444 Self::wrap_result(
445 handlers::core::get_quote_rights(&client, req.refresh.unwrap_or(false)).await,
446 )
447 }
448
449 async fn futu_get_delay_statistics_impl(
450 &self,
451 Parameters(_req): Parameters<NoArgs>,
452 req_ctx: RequestContext<RoleServer>,
453 ) -> std::result::Result<String, String> {
454 tracing::info!(tool = "futu_get_delay_statistics");
455 let client = self
456 .read_client_or_err("futu_get_delay_statistics", &req_ctx, None, None)
457 .await?;
458 Self::wrap_result(handlers::core::get_delay_statistics(&client).await)
459 }
460
461 async fn futu_get_token_state_impl(
462 &self,
463 Parameters(_req): Parameters<NoArgs>,
464 req_ctx: RequestContext<RoleServer>,
465 ) -> std::result::Result<String, String> {
466 tracing::info!(tool = "futu_get_token_state");
467 let client = self
468 .read_client_or_err("futu_get_token_state", &req_ctx, None, None)
469 .await?;
470 Self::wrap_result(handlers::core::get_token_state(&client, None).await)
472 }
473
474 async fn futu_get_risk_free_rate_impl(
475 &self,
476 Parameters(_req): Parameters<NoArgs>,
477 req_ctx: RequestContext<RoleServer>,
478 ) -> std::result::Result<String, String> {
479 tracing::info!(tool = "futu_get_risk_free_rate");
480 let client = self
481 .read_client_or_err("futu_get_risk_free_rate", &req_ctx, None, None)
482 .await?;
483 Self::wrap_result(handlers::core::get_risk_free_rate(&client).await)
484 }
485
486 async fn futu_get_spread_table_impl(
487 &self,
488 Parameters(_req): Parameters<NoArgs>,
489 req_ctx: RequestContext<RoleServer>,
490 ) -> std::result::Result<String, String> {
491 tracing::info!(tool = "futu_get_spread_table");
492 let client = self
493 .read_client_or_err("futu_get_spread_table", &req_ctx, None, None)
494 .await?;
495 Self::wrap_result(handlers::core::get_spread_table(&client).await)
496 }
497
498 async fn futu_get_ticker_statistic_impl(
499 &self,
500 Parameters(req): Parameters<TickerStatisticReq>,
501 req_ctx: RequestContext<RoleServer>,
502 ) -> std::result::Result<String, String> {
503 tracing::info!(tool = "futu_get_ticker_statistic", symbol = %req.symbol);
504 let client = self
505 .read_client_or_err("futu_get_ticker_statistic", &req_ctx, None, None)
506 .await?;
507 Self::wrap_result(
508 handlers::core::get_ticker_statistic(
509 &client,
510 &req.symbol,
511 req.ticker_type,
512 req.stat_type,
513 )
514 .await,
515 )
516 }
517
518 async fn futu_get_ticker_statistic_detail_impl(
519 &self,
520 Parameters(req): Parameters<TickerStatisticDetailReq>,
521 req_ctx: RequestContext<RoleServer>,
522 ) -> std::result::Result<String, String> {
523 req.validate()?;
524 tracing::info!(tool = "futu_get_ticker_statistic_detail", symbol = %req.symbol);
525 let client = self
526 .read_client_or_err("futu_get_ticker_statistic_detail", &req_ctx, None, None)
527 .await?;
528 Self::wrap_result(
529 handlers::core::get_ticker_statistic_detail(
530 &client,
531 handlers::core::TickerStatisticDetailInput {
532 symbol: &req.symbol,
533 ticker_type: req.ticker_type,
534 ticker_time: req.ticker_time,
535 select_num: req.select_num,
536 data_from: req.data_from,
537 data_max_count: req.data_max_count,
538 stat_type: req.stat_type,
539 },
540 )
541 .await,
542 )
543 }
544
545 async fn futu_get_history_kl_quota_impl(
550 &self,
551 Parameters(req): Parameters<HistoryKlQuotaReq>,
552 req_ctx: RequestContext<RoleServer>,
553 ) -> std::result::Result<String, String> {
554 tracing::info!(tool = "futu_get_history_kl_quota", detail = req.get_detail);
555 let client = self
556 .read_client_or_err("futu_get_history_kl_quota", &req_ctx, None, None)
557 .await?;
558 Self::wrap_result(handlers::reference::get_history_kl_quota(&client, req.get_detail).await)
559 }
560
561 async fn futu_get_holding_change_impl(
562 &self,
563 Parameters(req): Parameters<HoldingChangeReq>,
564 req_ctx: RequestContext<RoleServer>,
565 ) -> std::result::Result<String, String> {
566 tracing::info!(
567 tool = "futu_get_holding_change",
568 symbol = %req.symbol,
569 category = req.holder_category
570 );
571 let client = self
572 .read_client_or_err("futu_get_holding_change", &req_ctx, None, None)
573 .await?;
574 Self::wrap_result(
575 handlers::reference::get_holding_change(
576 &client,
577 &req.symbol,
578 req.holder_category,
579 req.begin_time.as_deref(),
580 req.end_time.as_deref(),
581 )
582 .await,
583 )
584 }
585
586 async fn futu_modify_user_security_impl(
587 &self,
588 Parameters(req): Parameters<ModifyUserSecurityReq>,
589 req_ctx: RequestContext<RoleServer>,
590 ) -> std::result::Result<String, String> {
591 req.validate()?;
592 tracing::info!(
598 tool = "futu_modify_user_security",
599 group = %req.group_name,
600 op = req.op,
601 count = req.symbols.len()
602 );
603 let client = self
604 .read_client_or_err("futu_modify_user_security", &req_ctx, None, None)
605 .await?;
606 Self::wrap_result(
607 handlers::reference::modify_user_security(
608 &client,
609 &req.group_name,
610 req.op,
611 &req.symbols,
612 )
613 .await,
614 )
615 }
616
617 async fn futu_get_code_change_impl(
618 &self,
619 Parameters(req): Parameters<CodeChangeReq>,
620 req_ctx: RequestContext<RoleServer>,
621 ) -> std::result::Result<String, String> {
622 tracing::info!(tool = "futu_get_code_change", count = req.symbols.len());
623 let client = self
624 .read_client_or_err("futu_get_code_change", &req_ctx, None, None)
625 .await?;
626 Self::wrap_result(handlers::reference::get_code_change(&client, &req.symbols).await)
627 }
628
629 async fn futu_get_option_volatility_impl(
630 &self,
631 Parameters(req): Parameters<OptionVolatilityReq>,
632 req_ctx: RequestContext<RoleServer>,
633 ) -> std::result::Result<String, String> {
634 req.validate()?;
635 tracing::info!(
636 tool = "futu_get_option_volatility",
637 symbol = %req.symbol,
638 query_time_period = ?req.query_time_period,
639 hv_time_period = ?req.hv_time_period
640 );
641 let client = self
642 .read_client_or_err("futu_get_option_volatility", &req_ctx, None, None)
643 .await?;
644 Self::wrap_result(
645 handlers::reference::get_option_volatility(
646 &client,
647 &req.symbol,
648 req.query_time_period,
649 req.hv_time_period,
650 )
651 .await,
652 )
653 }
654
655 async fn futu_get_option_exercise_probability_impl(
656 &self,
657 Parameters(req): Parameters<OptionExerciseProbabilityReq>,
658 req_ctx: RequestContext<RoleServer>,
659 ) -> std::result::Result<String, String> {
660 tracing::info!(tool = "futu_get_option_exercise_probability", symbol = %req.symbol);
661 let client = self
662 .read_client_or_err("futu_get_option_exercise_probability", &req_ctx, None, None)
663 .await?;
664 Self::wrap_result(
665 handlers::reference::get_option_exercise_probability(&client, &req.symbol).await,
666 )
667 }
668}
669
670include!(concat!(
671 env!("OUT_DIR"),
672 "/generated_mcp_routes_reference.rs"
673));