1use 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_list_accounts_impl(
13 &self,
14 Parameters(_req): Parameters<NoArgs>,
15 req_ctx: RequestContext<RoleServer>,
16 ) -> std::result::Result<String, String> {
17 let snap = self.require_acc_read_with_acc_id("futu_list_accounts", &req_ctx, None, None)?;
22 tracing::info!(tool = "futu_list_accounts");
23 let client = self.client_or_err().await?;
24 let allowed_card_nums = snap
29 .rec
30 .as_ref()
31 .and_then(|r| r.allowed_card_nums.as_deref());
32 Self::wrap_result(
33 handlers::trade::list_accounts_filtered(
34 &client,
35 snap.allowed_acc_ids.as_ref(),
36 allowed_card_nums,
37 )
38 .await,
39 )
40 }
41
42 async fn futu_get_funds_impl(
43 &self,
44 Parameters(req): Parameters<TrdAccReq>,
45 req_ctx: RequestContext<RoleServer>,
46 ) -> std::result::Result<String, String> {
47 let resolved = self
48 .resolve_read_trd_account("futu_get_funds", &req, &req_ctx)
49 .await?;
50 tracing::info!(
51 tool = "futu_get_funds",
52 market = %req.market,
53 env = %req.env,
54 currency = ?req.currency,
55 );
56 Self::wrap_result(
58 handlers::trade::get_funds_with_currency(
59 &resolved.client,
60 &req.env,
61 resolved.acc_id,
62 &req.market,
63 req.currency.as_deref(),
64 )
65 .await,
66 )
67 }
68
69 async fn futu_get_positions_impl(
70 &self,
71 Parameters(req): Parameters<PositionReq>,
72 req_ctx: RequestContext<RoleServer>,
73 ) -> std::result::Result<String, String> {
74 let acc_req = req.as_trd_acc_req();
75 let resolved = self
76 .resolve_read_trd_account("futu_get_positions", &acc_req, &req_ctx)
77 .await?;
78 tracing::info!(
79 tool = "futu_get_positions",
80 market = %req.market,
81 currency = ?req.currency,
82 option_strategy_view = req.option_strategy_view,
83 );
84 Self::wrap_result(
85 handlers::trade::get_positions(
86 &resolved.client,
87 &req.env,
88 resolved.acc_id,
89 &req.market,
90 req.currency.as_deref(),
91 req.option_strategy_view,
92 )
93 .await,
94 )
95 }
96
97 async fn futu_get_orders_impl(
98 &self,
99 Parameters(req): Parameters<TrdAccReq>,
100 req_ctx: RequestContext<RoleServer>,
101 ) -> std::result::Result<String, String> {
102 let resolved = self
103 .resolve_read_trd_account("futu_get_orders", &req, &req_ctx)
104 .await?;
105 tracing::info!(tool = "futu_get_orders", market = %req.market);
106 Self::wrap_result(
107 handlers::trade::get_orders(&resolved.client, &req.env, resolved.acc_id, &req.market)
108 .await,
109 )
110 }
111
112 async fn futu_get_deals_impl(
113 &self,
114 Parameters(req): Parameters<TrdAccReq>,
115 req_ctx: RequestContext<RoleServer>,
116 ) -> std::result::Result<String, String> {
117 let resolved = self
118 .resolve_read_trd_account("futu_get_deals", &req, &req_ctx)
119 .await?;
120 tracing::info!(tool = "futu_get_deals", market = %req.market);
121 Self::wrap_result(
122 handlers::trade::get_deals(&resolved.client, &req.env, resolved.acc_id, &req.market)
123 .await,
124 )
125 }
126
127 async fn futu_get_max_trd_qtys_impl(
130 &self,
131 Parameters(req): Parameters<MaxTrdQtysReq>,
132 req_ctx: RequestContext<RoleServer>,
133 ) -> std::result::Result<String, String> {
134 tracing::info!(tool = "futu_get_max_trd_qtys", market = %req.market, code = %req.code);
135 let client = self
136 .read_client_or_err("futu_get_max_trd_qtys", &req_ctx, None, Some(req.acc_id))
137 .await?;
138 Self::wrap_result(
139 handlers::trade::get_max_trd_qtys(
140 &client,
141 handlers::trade::MaxTrdQtysInput {
142 env: &req.env,
143 acc_id: req.acc_id,
144 market: &req.market,
145 order_type: req.order_type,
146 code: &req.code,
147 price: req.price,
148 jp_acc_type: req.jp_acc_type,
149 order_id: req.order_id,
150 },
151 )
152 .await,
153 )
154 }
155
156 async fn futu_get_order_fee_impl(
157 &self,
158 Parameters(req): Parameters<OrderFeeReq>,
159 req_ctx: RequestContext<RoleServer>,
160 ) -> std::result::Result<String, String> {
161 tracing::info!(tool = "futu_get_order_fee", market = %req.market, count = req.order_id_ex_list.len());
162 let client = self
163 .read_client_or_err("futu_get_order_fee", &req_ctx, None, Some(req.acc_id))
164 .await?;
165 Self::wrap_result(
166 handlers::trade::get_order_fee(
167 &client,
168 &req.env,
169 req.acc_id,
170 &req.market,
171 &req.order_id_ex_list,
172 )
173 .await,
174 )
175 }
176
177 async fn futu_get_margin_ratio_impl(
178 &self,
179 Parameters(req): Parameters<MarginRatioReq>,
180 req_ctx: RequestContext<RoleServer>,
181 ) -> std::result::Result<String, String> {
182 tracing::info!(tool = "futu_get_margin_ratio", market = %req.market, count = req.codes.len());
183 let client = self
184 .read_client_or_err("futu_get_margin_ratio", &req_ctx, None, Some(req.acc_id))
185 .await?;
186 Self::wrap_result(
187 handlers::trade::get_margin_ratio(
188 &client,
189 &req.env,
190 req.acc_id,
191 &req.market,
192 &req.codes,
193 )
194 .await,
195 )
196 }
197
198 async fn futu_get_history_orders_impl(
199 &self,
200 Parameters(req): Parameters<HistoryQueryReq>,
201 req_ctx: RequestContext<RoleServer>,
202 ) -> std::result::Result<String, String> {
203 tracing::info!(tool = "futu_get_history_orders", market = %req.market);
204 let client = self
205 .read_client_or_err("futu_get_history_orders", &req_ctx, None, Some(req.acc_id))
206 .await?;
207 Self::wrap_result(
208 handlers::trade::get_history_orders(
209 &client,
210 handlers::trade::HistoryQueryInput {
211 env: &req.env,
212 acc_id: req.acc_id,
213 market: &req.market,
214 code_list: req.code_list,
215 begin_time: req.begin_time,
216 end_time: req.end_time,
217 },
218 )
219 .await,
220 )
221 }
222
223 async fn futu_get_history_deals_impl(
224 &self,
225 Parameters(req): Parameters<HistoryQueryReq>,
226 req_ctx: RequestContext<RoleServer>,
227 ) -> std::result::Result<String, String> {
228 tracing::info!(tool = "futu_get_history_deals", market = %req.market);
229 let client = self
230 .read_client_or_err("futu_get_history_deals", &req_ctx, None, Some(req.acc_id))
231 .await?;
232 Self::wrap_result(
233 handlers::trade::get_history_deals(
234 &client,
235 handlers::trade::HistoryQueryInput {
236 env: &req.env,
237 acc_id: req.acc_id,
238 market: &req.market,
239 code_list: req.code_list,
240 begin_time: req.begin_time,
241 end_time: req.end_time,
242 },
243 )
244 .await,
245 )
246 }
247
248 async fn futu_get_acc_cash_flow_impl(
249 &self,
250 Parameters(req): Parameters<AccCashFlowReq>,
251 req_ctx: RequestContext<RoleServer>,
252 ) -> std::result::Result<String, String> {
253 tracing::info!(
254 tool = "futu_get_acc_cash_flow",
255 env = %req.env,
256 market = %req.market,
257 date = %req.clearing_date
258 );
259 let client = self
260 .read_client_or_err("futu_get_acc_cash_flow", &req_ctx, None, Some(req.acc_id))
261 .await?;
262 Self::wrap_result(
263 handlers::trade::get_acc_cash_flow(
264 &client,
265 &req.env,
266 req.acc_id,
267 &req.market,
268 &req.clearing_date,
269 req.direction,
270 )
271 .await,
272 )
273 }
274
275 async fn futu_get_flow_summary_impl(
286 &self,
287 Parameters(req): Parameters<AccCashFlowReq>,
288 req_ctx: RequestContext<RoleServer>,
289 ) -> std::result::Result<String, String> {
290 tracing::info!(
292 tool = "futu_get_flow_summary",
293 alias_of = "futu_get_acc_cash_flow",
294 env = %req.env,
295 market = %req.market,
296 date = %req.clearing_date
297 );
298 let client = self
299 .read_client_or_err("futu_get_flow_summary", &req_ctx, None, Some(req.acc_id))
300 .await?;
301 Self::wrap_result(
302 handlers::trade::get_acc_cash_flow(
303 &client,
304 &req.env,
305 req.acc_id,
306 &req.market,
307 &req.clearing_date,
308 req.direction,
309 )
310 .await,
311 )
312 }
313
314 async fn futu_get_cash_log_impl(
326 &self,
327 Parameters(req): Parameters<CashLogReq>,
328 req_ctx: RequestContext<RoleServer>,
329 ) -> std::result::Result<String, String> {
330 tracing::info!(
331 tool = "futu_get_cash_log",
332 env = %req.env,
333 market = ?req.market,
334 has_keyword = req.keyword.is_some(),
335 has_symbol = req.symbol.is_some()
336 );
337 let client = self
338 .read_client_or_err("futu_get_cash_log", &req_ctx, None, Some(req.acc_id))
339 .await?;
340 Self::wrap_result(
341 handlers::trade::get_cash_log(
342 &client,
343 handlers::trade::CashLogInput {
344 env: &req.env,
345 acc_id: req.acc_id,
346 begin_time: req.begin_time,
347 end_time: req.end_time,
348 biz_group_id: req.biz_group_id,
349 biz_sub_group_id: req.biz_sub_group_id,
350 in_out: req.in_out,
351 keyword: req.keyword,
352 symbol: req.symbol,
353 stock_id: req.stock_id,
354 log_id: req.log_id,
355 max_cnt: req.max_cnt,
356 currency: req.currency,
357 },
358 )
359 .await,
360 )
361 }
362
363 async fn futu_get_cash_detail_impl(
364 &self,
365 Parameters(req): Parameters<CashDetailReq>,
366 req_ctx: RequestContext<RoleServer>,
367 ) -> std::result::Result<String, String> {
368 tracing::info!(
369 tool = "futu_get_cash_detail",
370 env = %req.env,
371 market = ?req.market,
372 log_id_len = req.log_id.len()
373 );
374 let client = self
375 .read_client_or_err("futu_get_cash_detail", &req_ctx, None, Some(req.acc_id))
376 .await?;
377 Self::wrap_result(
378 handlers::trade::get_cash_detail(&client, &req.env, req.acc_id, req.log_id.clone())
379 .await,
380 )
381 }
382
383 async fn futu_get_biz_group_impl(
384 &self,
385 Parameters(req): Parameters<BizGroupReq>,
386 req_ctx: RequestContext<RoleServer>,
387 ) -> std::result::Result<String, String> {
388 tracing::info!(
389 tool = "futu_get_biz_group",
390 env = %req.env,
391 market = ?req.market
392 );
393 let client = self
394 .read_client_or_err("futu_get_biz_group", &req_ctx, None, Some(req.acc_id))
395 .await?;
396 Self::wrap_result(handlers::trade::get_biz_group(&client, &req.env, req.acc_id).await)
397 }
398
399 async fn futu_get_margin_info_impl(
410 &self,
411 Parameters(req): Parameters<MarginInfoReq>,
412 req_ctx: RequestContext<RoleServer>,
413 ) -> std::result::Result<String, String> {
414 tracing::info!(
415 tool = "futu_get_margin_info",
416 env = %req.env,
417 market = %req.market
418 );
419 let client = self
420 .read_client_or_err("futu_get_margin_info", &req_ctx, None, Some(req.acc_id))
421 .await?;
422 Self::wrap_result(
423 handlers::trade::get_margin_info(&client, &req.env, req.acc_id, &req.market).await,
424 )
425 }
426
427 async fn futu_get_account_flag_impl(
437 &self,
438 Parameters(req): Parameters<AccountFlagReq>,
439 req_ctx: RequestContext<RoleServer>,
440 ) -> std::result::Result<String, String> {
441 tracing::info!(
442 tool = "futu_get_account_flag",
443 env = %req.env,
444 flag_id = req.flag_id
445 );
446 let client = self
447 .read_client_or_err("futu_get_account_flag", &req_ctx, None, Some(req.acc_id))
448 .await?;
449 Self::wrap_result(
450 handlers::trade::get_account_flag(&client, &req.env, req.acc_id, req.flag_id).await,
451 )
452 }
453
454 async fn futu_get_bond_total_asset_impl(
464 &self,
465 Parameters(req): Parameters<BondAccountReq>,
466 req_ctx: RequestContext<RoleServer>,
467 ) -> std::result::Result<String, String> {
468 tracing::info!(
469 tool = "futu_get_bond_total_asset",
470 env = %req.env,
471 market = %req.market
472 );
473 let client = self
474 .read_client_or_err(
475 "futu_get_bond_total_asset",
476 &req_ctx,
477 None,
478 Some(req.acc_id),
479 )
480 .await?;
481 Self::wrap_result(
482 handlers::trade::get_bond_total_asset(&client, &req.env, req.acc_id, &req.market).await,
483 )
484 }
485
486 async fn futu_get_bond_single_asset_impl(
487 &self,
488 Parameters(req): Parameters<BondSymbolReq>,
489 req_ctx: RequestContext<RoleServer>,
490 ) -> std::result::Result<String, String> {
491 tracing::info!(
492 tool = "futu_get_bond_single_asset",
493 env = %req.env,
494 market = %req.market,
495 symbol = %req.symbol
496 );
497 let client = self
498 .read_client_or_err(
499 "futu_get_bond_single_asset",
500 &req_ctx,
501 None,
502 Some(req.acc_id),
503 )
504 .await?;
505 Self::wrap_result(
506 handlers::trade::get_bond_single_asset(
507 &client,
508 &req.env,
509 req.acc_id,
510 &req.market,
511 &req.symbol,
512 )
513 .await,
514 )
515 }
516
517 async fn futu_get_bond_position_list_impl(
518 &self,
519 Parameters(req): Parameters<BondAccountReq>,
520 req_ctx: RequestContext<RoleServer>,
521 ) -> std::result::Result<String, String> {
522 tracing::info!(
523 tool = "futu_get_bond_position_list",
524 env = %req.env,
525 market = %req.market
526 );
527 let client = self
528 .read_client_or_err(
529 "futu_get_bond_position_list",
530 &req_ctx,
531 None,
532 Some(req.acc_id),
533 )
534 .await?;
535 Self::wrap_result(
536 handlers::trade::get_bond_position_list(&client, &req.env, req.acc_id, &req.market)
537 .await,
538 )
539 }
540
541 async fn futu_get_bond_answer_state_impl(
542 &self,
543 Parameters(req): Parameters<BondSymbolReq>,
544 req_ctx: RequestContext<RoleServer>,
545 ) -> std::result::Result<String, String> {
546 tracing::info!(
547 tool = "futu_get_bond_answer_state",
548 env = %req.env,
549 market = %req.market,
550 symbol = %req.symbol
551 );
552 let client = self
553 .read_client_or_err(
554 "futu_get_bond_answer_state",
555 &req_ctx,
556 None,
557 Some(req.acc_id),
558 )
559 .await?;
560 Self::wrap_result(
561 handlers::trade::get_bond_answer_state(
562 &client,
563 &req.env,
564 req.acc_id,
565 &req.market,
566 &req.symbol,
567 )
568 .await,
569 )
570 }
571
572 async fn futu_get_bond_trade_reminder_impl(
573 &self,
574 Parameters(req): Parameters<BondSymbolReq>,
575 req_ctx: RequestContext<RoleServer>,
576 ) -> std::result::Result<String, String> {
577 tracing::info!(
578 tool = "futu_get_bond_trade_reminder",
579 env = %req.env,
580 market = %req.market,
581 symbol = %req.symbol
582 );
583 let client = self
584 .read_client_or_err(
585 "futu_get_bond_trade_reminder",
586 &req_ctx,
587 None,
588 Some(req.acc_id),
589 )
590 .await?;
591 Self::wrap_result(
592 handlers::trade::get_bond_trade_reminder(
593 &client,
594 &req.env,
595 req.acc_id,
596 &req.market,
597 &req.symbol,
598 )
599 .await,
600 )
601 }
602}
603
604include!(concat!(
605 env!("OUT_DIR"),
606 "/generated_mcp_routes_trade_read.rs"
607));