Skip to main content

futu_mcp/tools/
asset_screen.rs

1//! MCP proto-JSON tools for v1.8 cross-asset screeners.
2
3use std::future::Future;
4use std::sync::Arc;
5
6use futu_net::client::FutuClient;
7use rmcp::{RoleServer, handler::server::wrapper::Parameters, service::RequestContext};
8use serde::de::DeserializeOwned;
9
10use crate::handlers;
11use crate::tool_args::ProtoJsonReq;
12
13use super::FutuServer;
14
15async fn run<C2S, F, Fut>(
16    server: &FutuServer,
17    tool_name: &'static str,
18    label: &'static str,
19    req: ProtoJsonReq,
20    req_ctx: RequestContext<RoleServer>,
21    handler: F,
22) -> std::result::Result<String, String>
23where
24    C2S: DeserializeOwned,
25    F: FnOnce(Arc<FutuClient>, C2S) -> Fut,
26    Fut: Future<Output = anyhow::Result<String>>,
27{
28    let c2s = match handlers::proto_json::parse_c2s_json::<C2S>(label, &req.c2s_json) {
29        Ok(c2s) => c2s,
30        Err(error) => return FutuServer::tool_err(error),
31    };
32    let client = server
33        .read_client_or_err(tool_name, &req_ctx, req.api_key.as_deref(), None)
34        .await?;
35    FutuServer::wrap_result(handler(client, c2s).await)
36}
37
38macro_rules! tool_impl {
39    ($fn_name:ident,$module:ident,$tool:literal,$label:literal,$handler:ident) => {
40        async fn $fn_name(
41            &self,
42            Parameters(req): Parameters<ProtoJsonReq>,
43            req_ctx: RequestContext<RoleServer>,
44        ) -> std::result::Result<String, String> {
45            run::<futu_proto::$module::C2s, _, _>(
46                self,
47                $tool,
48                $label,
49                req,
50                req_ctx,
51                |client, c2s| async move { handlers::proto_json::$handler(&client, c2s).await },
52            )
53            .await
54        }
55    };
56}
57
58impl FutuServer {
59    tool_impl!(
60        futu_etf_screen_impl,
61        qot_get_etf_screen,
62        "futu_etf_screen",
63        "etf-screen",
64        etf_screen
65    );
66    tool_impl!(
67        futu_fund_screen_impl,
68        qot_get_fund_screen,
69        "futu_fund_screen",
70        "fund-screen",
71        fund_screen
72    );
73    tool_impl!(
74        futu_future_screen_impl,
75        qot_get_future_screen,
76        "futu_future_screen",
77        "future-screen",
78        future_screen
79    );
80    tool_impl!(
81        futu_bond_screen_impl,
82        qot_get_bond_screen,
83        "futu_bond_screen",
84        "bond-screen",
85        bond_screen
86    );
87}
88
89include!(concat!(
90    env!("OUT_DIR"),
91    "/generated_mcp_routes_asset_screen.rs"
92));