Skip to main content

futu_mcp/tools/
reference_price_reminder.rs

1//! MCP price-reminder and option-expiration reference tools.
2
3use 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_set_price_reminder_impl(
11        &self,
12        Parameters(req): Parameters<SetPriceReminderReq>,
13        req_ctx: RequestContext<RoleServer>,
14    ) -> std::result::Result<String, String> {
15        // v1.4.104 codex round 1 F2 (P1) fix: 改 caller-specific scope check
16        // (之前 require_tool_scope 只看 startup key, HTTP Bearer 调用方权限
17        // 没真核, narrow Bearer 仍能修改 / 删除全局 price reminder 状态).
18        // v1.4.84 §5 B4: op-conditional required field check
19        req.validate()?;
20        tracing::info!(
21            tool = "futu_set_price_reminder",
22            symbol = %req.symbol,
23            op = req.op
24        );
25        let client = self
26            .read_client_or_err("futu_set_price_reminder", &req_ctx, None, None)
27            .await?;
28        Self::wrap_result(
29            handlers::reference::set_price_reminder(
30                &client,
31                handlers::reference::SetPriceReminderInput {
32                    symbol: &req.symbol,
33                    op: req.op,
34                    key: req.key,
35                    reminder_type: req.reminder_type,
36                    freq: req.freq,
37                    value: req.value,
38                    note: req.note.as_deref(),
39                    reminder_session_list: &req.reminder_session_list,
40                },
41            )
42            .await,
43        )
44    }
45
46    async fn futu_get_price_reminder_impl(
47        &self,
48        Parameters(req): Parameters<GetPriceReminderReq>,
49        req_ctx: RequestContext<RoleServer>,
50    ) -> std::result::Result<String, String> {
51        // v1.4.84 §5 B4: symbol XOR market required
52        req.validate()?;
53        tracing::info!(
54            tool = "futu_get_price_reminder",
55            // v1.4.90 P2-C: Option<String> / Option<i32> 都 flatten,避免 record_debug 编 string
56            symbol = %crate::state::audit_fmt::opt_str(req.symbol.as_deref()),
57            market = crate::state::audit_fmt::opt_i32(req.market)
58        );
59        let client = self
60            .read_client_or_err("futu_get_price_reminder", &req_ctx, None, None)
61            .await?;
62        Self::wrap_result(
63            handlers::reference::get_price_reminder(&client, req.symbol.as_deref(), req.market)
64                .await,
65        )
66    }
67
68    async fn futu_get_option_expiration_date_impl(
69        &self,
70        Parameters(req): Parameters<OptionExpirationDateReq>,
71        req_ctx: RequestContext<RoleServer>,
72    ) -> std::result::Result<String, String> {
73        tracing::info!(
74            tool = "futu_get_option_expiration_date",
75            owner = %req.owner_symbol
76        );
77        let client = self
78            .read_client_or_err("futu_get_option_expiration_date", &req_ctx, None, None)
79            .await?;
80        Self::wrap_result(
81            handlers::reference::get_option_expiration_date(
82                &client,
83                &req.owner_symbol,
84                req.index_option_type,
85            )
86            .await,
87        )
88    }
89}
90
91include!(concat!(
92    env!("OUT_DIR"),
93    "/generated_mcp_routes_reference_price_reminder.rs"
94));