Skip to main content

futu_mcp/tools/
reference_shareholders_insider.rs

1//! MCP v10.6 shareholders and insider reference tools.
2
3use 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_shareholders_insider_tool_router, vis = "pub(crate)")]
12impl FutuServer {
13    #[tool(
14        description = "Shareholder ownership overview for HK/US securities. Futu API v10.6: OpenQuoteContext.get_shareholders_overview."
15    )]
16    async fn futu_get_shareholders_overview(
17        &self,
18        Parameters(req): Parameters<ShareholdersOverviewReq>,
19        req_ctx: RequestContext<RoleServer>,
20    ) -> std::result::Result<String, String> {
21        tracing::info!(
22            tool = "futu_get_shareholders_overview",
23            symbol = %req.symbol,
24            period_id = ?req.period_id
25        );
26        let client = self
27            .read_client_or_err("futu_get_shareholders_overview", &req_ctx, None, None)
28            .await?;
29        Self::wrap_result(
30            handlers::reference::get_shareholders_overview(&client, &req.symbol, req.period_id)
31                .await,
32        )
33    }
34
35    #[tool(
36        description = "Shareholder holding change records for HK/US securities. Futu API v10.6: OpenQuoteContext.get_shareholders_holding_changes."
37    )]
38    async fn futu_get_shareholders_holding_changes(
39        &self,
40        Parameters(req): Parameters<ShareholdersHoldingChangesReq>,
41        req_ctx: RequestContext<RoleServer>,
42    ) -> std::result::Result<String, String> {
43        req.validate()?;
44        tracing::info!(
45            tool = "futu_get_shareholders_holding_changes",
46            symbol = %req.symbol,
47            next_key = ?req.next_key,
48            num = ?req.num,
49            sort_type = ?req.sort_type,
50            sort_column = ?req.sort_column,
51            filter_type = ?req.filter_type
52        );
53        let client = self
54            .read_client_or_err(
55                "futu_get_shareholders_holding_changes",
56                &req_ctx,
57                None,
58                None,
59            )
60            .await?;
61        Self::wrap_result(
62            handlers::reference::get_shareholders_holding_changes(
63                &client,
64                &req.symbol,
65                req.next_key,
66                req.num,
67                req.sort_type,
68                req.sort_column,
69                req.filter_type,
70            )
71            .await,
72        )
73    }
74
75    #[tool(
76        description = "Shareholder holder detail records for HK/US securities. Futu API v10.6: OpenQuoteContext.get_shareholders_holder_detail."
77    )]
78    async fn futu_get_shareholders_holder_detail(
79        &self,
80        Parameters(req): Parameters<ShareholdersHolderDetailReq>,
81        req_ctx: RequestContext<RoleServer>,
82    ) -> std::result::Result<String, String> {
83        req.validate()?;
84        tracing::info!(
85            tool = "futu_get_shareholders_holder_detail",
86            symbol = %req.symbol,
87            request_type = ?req.request_type,
88            next_key = ?req.next_key,
89            num = ?req.num,
90            sort_column = ?req.sort_column,
91            sort_type = ?req.sort_type,
92            period_id = ?req.period_id,
93            holder_id = ?req.holder_id
94        );
95        let client = self
96            .read_client_or_err("futu_get_shareholders_holder_detail", &req_ctx, None, None)
97            .await?;
98        Self::wrap_result(
99            handlers::reference::get_shareholders_holder_detail(
100                &client,
101                &req.symbol,
102                req.request_type,
103                req.next_key,
104                req.num,
105                req.sort_column,
106                req.sort_type,
107                req.period_id,
108                req.holder_id,
109            )
110            .await,
111        )
112    }
113
114    #[tool(
115        description = "Institutional shareholder ownership statistics for HK/US securities. Futu API v10.6: OpenQuoteContext.get_shareholders_institutional."
116    )]
117    async fn futu_get_shareholders_institutional(
118        &self,
119        Parameters(req): Parameters<ShareholdersInstitutionalReq>,
120        req_ctx: RequestContext<RoleServer>,
121    ) -> std::result::Result<String, String> {
122        req.validate()?;
123        tracing::info!(
124            tool = "futu_get_shareholders_institutional",
125            symbol = %req.symbol,
126            next_key = ?req.next_key,
127            num = ?req.num
128        );
129        let client = self
130            .read_client_or_err("futu_get_shareholders_institutional", &req_ctx, None, None)
131            .await?;
132        Self::wrap_result(
133            handlers::reference::get_shareholders_institutional(
134                &client,
135                &req.symbol,
136                req.next_key,
137                req.num,
138            )
139            .await,
140        )
141    }
142
143    #[tool(
144        description = "Insider holder list for US securities. Futu API v10.6: OpenQuoteContext.get_insider_holder_list."
145    )]
146    async fn futu_get_insider_holder_list(
147        &self,
148        Parameters(req): Parameters<InsiderHolderListReq>,
149        req_ctx: RequestContext<RoleServer>,
150    ) -> std::result::Result<String, String> {
151        req.validate()?;
152        tracing::info!(
153            tool = "futu_get_insider_holder_list",
154            symbol = %req.symbol,
155            next_key = ?req.next_key,
156            num = ?req.num
157        );
158        let client = self
159            .read_client_or_err("futu_get_insider_holder_list", &req_ctx, None, None)
160            .await?;
161        Self::wrap_result(
162            handlers::reference::get_insider_holder_list(
163                &client,
164                &req.symbol,
165                req.next_key,
166                req.num,
167            )
168            .await,
169        )
170    }
171
172    #[tool(
173        description = "Insider trade list for US securities. Futu API v10.6: OpenQuoteContext.get_insider_trade_list."
174    )]
175    async fn futu_get_insider_trade_list(
176        &self,
177        Parameters(req): Parameters<InsiderTradeListReq>,
178        req_ctx: RequestContext<RoleServer>,
179    ) -> std::result::Result<String, String> {
180        req.validate()?;
181        tracing::info!(
182            tool = "futu_get_insider_trade_list",
183            symbol = %req.symbol,
184            holder_id = ?req.holder_id,
185            next_key = ?req.next_key,
186            num = ?req.num
187        );
188        let client = self
189            .read_client_or_err("futu_get_insider_trade_list", &req_ctx, None, None)
190            .await?;
191        Self::wrap_result(
192            handlers::reference::get_insider_trade_list(
193                &client,
194                &req.symbol,
195                req.holder_id,
196                req.next_key,
197                req.num,
198            )
199            .await,
200        )
201    }
202}