Skip to content

Commit 6f7ec49

Browse files
committed
v3.0.15
1 parent 11dcdc5 commit 6f7ec49

2 files changed

Lines changed: 86 additions & 55 deletions

File tree

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ napi = { version = "3.2.5", default-features = false }
5656
napi-derive = "3.2.5"
5757
napi-build = "2.2.3"
5858
chrono = "0.4.41"
59-
poem-mcpserver = "0.2.5"
60-
poem-mcpserver-macros = "0.2.5"
59+
poem-mcpserver = "0.3.1"
60+
poem-mcpserver-macros = "0.3.1"
6161
poem = "3.1.12"
6262
schemars = "1.0.4"
6363
clap = "4.5.45"

mcp/src/server.rs

Lines changed: 84 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
use longport::{
22
Decimal, Error, Market, QuoteContext, TradeContext,
3-
quote::{AdjustType, Period, TradeSessions},
3+
quote::{
4+
AdjustType, Candlestick, CapitalDistributionResponse, CapitalFlowLine,
5+
HistoryMarketTemperatureResponse, MarketTemperature, MarketTradingDays, OptionQuote,
6+
ParticipantInfo, Period, SecurityBrokers, SecurityDepth, SecurityQuote, SecurityStaticInfo,
7+
StrikePriceInfo, Trade, TradeSessions,
8+
},
49
trade::{
5-
GetHistoryOrdersOptions, OrderSide, OrderType, OutsideRTH, SubmitOrderOptions,
6-
TimeInForceType,
10+
AccountBalance, FundPositionChannel, GetHistoryOrdersOptions, MarginRatio, Order,
11+
OrderDetail, OrderSide, OrderType, OutsideRTH, StockPositionChannel, SubmitOrderOptions,
12+
SubmitOrderResponse, TimeInForceType,
713
},
814
};
915
use poem_mcpserver::{
1016
Tools,
11-
content::{IntoContent, IntoContents, Json, Text},
17+
content::{Json, Text},
1218
};
1319
use time::{
1420
Date, OffsetDateTime, format_description::BorrowedFormatItem, macros::format_description,
@@ -35,7 +41,7 @@ impl Longport {
3541
#[Tools]
3642
impl Longport {
3743
/// Get current time.
38-
async fn now(&self) -> impl IntoContent {
44+
async fn now(&self) -> Text<String> {
3945
Text(
4046
OffsetDateTime::now_utc()
4147
.format(&time::format_description::well_known::Rfc3339)
@@ -49,7 +55,7 @@ impl Longport {
4955
/// A list of security symbols. (e.g. ["700.HK", "AAPL.US", "000001.SH",
5056
/// "D05.SG"])
5157
symbols: Vec<String>,
52-
) -> Result<impl IntoContents, Error> {
58+
) -> Result<Vec<Json<SecurityStaticInfo>>, Error> {
5359
Ok(self
5460
.quote_context
5561
.static_info(symbols)
@@ -60,7 +66,7 @@ impl Longport {
6066
}
6167

6268
/// Get the latest price of the securities.
63-
async fn quote(&self, symbols: Vec<String>) -> Result<impl IntoContents, Error> {
69+
async fn quote(&self, symbols: Vec<String>) -> Result<Vec<Json<SecurityQuote>>, Error> {
6470
Ok(self
6571
.quote_context
6672
.quote(symbols)
@@ -76,7 +82,7 @@ impl Longport {
7682
/// A list of option symbols. (e.g. ["AAPL230317P160000.US",
7783
/// "AAPL230317C160000.US"]) Maximum 500 symbols per request.
7884
symbols: Vec<String>,
79-
) -> Result<impl IntoContents, Error> {
85+
) -> Result<Vec<Json<OptionQuote>>, Error> {
8086
Ok(self
8187
.quote_context
8288
.option_quote(symbols)
@@ -87,7 +93,7 @@ impl Longport {
8793
}
8894

8995
/// Get the latest depth of the securities.
90-
async fn depth(&self, symbol: String) -> Result<impl IntoContents, Error> {
96+
async fn depth(&self, symbol: String) -> Result<Json<SecurityDepth>, Error> {
9197
Ok(Json(self.quote_context.depth(symbol).await?))
9298
}
9399

@@ -97,8 +103,14 @@ impl Longport {
97103
symbol: String,
98104
/// max 1000
99105
count: usize,
100-
) -> Result<impl IntoContents, Error> {
101-
Ok(Json(self.quote_context.trades(symbol, count).await?))
106+
) -> Result<Vec<Json<Trade>>, Error> {
107+
Ok(self
108+
.quote_context
109+
.trades(symbol, count)
110+
.await?
111+
.into_iter()
112+
.map(Json)
113+
.collect::<Vec<_>>())
102114
}
103115

104116
/// Get the latest n candlesticks of the security.
@@ -117,7 +129,7 @@ impl Longport {
117129
/// - intraday: regular trading hours
118130
/// - all: all trading hours (intraday, pre, post, overnight)
119131
trade_sessions: String,
120-
) -> Result<impl IntoContents, Error> {
132+
) -> Result<Vec<Json<Candlestick>>, Error> {
121133
let period = match period.as_str() {
122134
"1m" => Period::OneMinute,
123135
"2m" => Period::TwoMinute,
@@ -155,21 +167,23 @@ impl Longport {
155167
}
156168
};
157169

158-
Ok(Json(
159-
self.quote_context
160-
.candlesticks(
161-
symbol,
162-
period,
163-
count,
164-
if forward_adjust {
165-
AdjustType::ForwardAdjust
166-
} else {
167-
AdjustType::NoAdjust
168-
},
169-
trade_sessions,
170-
)
171-
.await?,
172-
))
170+
Ok(self
171+
.quote_context
172+
.candlesticks(
173+
symbol,
174+
period,
175+
count,
176+
if forward_adjust {
177+
AdjustType::ForwardAdjust
178+
} else {
179+
AdjustType::NoAdjust
180+
},
181+
trade_sessions,
182+
)
183+
.await?
184+
.into_iter()
185+
.map(Json)
186+
.collect::<Vec<_>>())
173187
}
174188

175189
/// Get the trading days between the specified dates.
@@ -183,7 +197,7 @@ impl Longport {
183197
start_date: String,
184198
/// End date of the trading days. (Format: "yyyy-mm-dd")
185199
end_date: String,
186-
) -> Result<impl IntoContents, Error> {
200+
) -> Result<Json<MarketTradingDays>, Error> {
187201
let market = market.parse::<Market>().map_err(|err| Error::ParseField {
188202
name: "market",
189203
error: err.to_string(),
@@ -206,17 +220,23 @@ impl Longport {
206220
}
207221

208222
/// Returns the real-time broker queue data of security.
209-
async fn broker_queue(&self, symbol: String) -> Result<impl IntoContents, Error> {
223+
async fn broker_queue(&self, symbol: String) -> Result<Json<SecurityBrokers>, Error> {
210224
Ok(Json(self.quote_context.brokers(symbol).await?))
211225
}
212226

213227
/// Returns the participants information.
214-
async fn broker_info(&self) -> Result<impl IntoContents, Error> {
215-
Ok(Json(self.quote_context.participants().await?))
228+
async fn broker_info(&self) -> Result<Vec<Json<ParticipantInfo>>, Error> {
229+
Ok(self
230+
.quote_context
231+
.participants()
232+
.await?
233+
.into_iter()
234+
.map(Json)
235+
.collect::<Vec<_>>())
216236
}
217237

218238
/// Returns the option chain list of the security.
219-
async fn option_chain_list(&self, symbol: String) -> Result<impl IntoContents, Error> {
239+
async fn option_chain_list(&self, symbol: String) -> Result<Vec<Text<String>>, Error> {
220240
Ok(self
221241
.quote_context
222242
.option_chain_expiry_date_list(symbol)
@@ -237,26 +257,37 @@ impl Longport {
237257
symbol: String,
238258
/// format: "yyyy-mm-dd"
239259
expiry_date: String,
240-
) -> Result<impl IntoContents, Error> {
260+
) -> Result<Vec<Json<StrikePriceInfo>>, Error> {
241261
let expiry_date = Date::parse(&expiry_date, format_description!("[year]-[month]-[day]"))
242262
.map_err(|err| Error::ParseField {
243263
name: "expiry_date",
244264
error: err.to_string(),
245265
})?;
246-
Ok(Json(
247-
self.quote_context
248-
.option_chain_info_by_date(symbol, expiry_date)
249-
.await?,
250-
))
266+
Ok(self
267+
.quote_context
268+
.option_chain_info_by_date(symbol, expiry_date)
269+
.await?
270+
.into_iter()
271+
.map(Json)
272+
.collect::<Vec<_>>())
251273
}
252274

253275
// Returns the capital flow of the security.
254-
async fn capital_flow(&self, symbol: String) -> Result<impl IntoContents, Error> {
255-
Ok(Json(self.quote_context.capital_flow(symbol).await?))
276+
async fn capital_flow(&self, symbol: String) -> Result<Vec<Json<CapitalFlowLine>>, Error> {
277+
Ok(self
278+
.quote_context
279+
.capital_flow(symbol)
280+
.await?
281+
.into_iter()
282+
.map(Json)
283+
.collect::<Vec<_>>())
256284
}
257285

258286
/// Returns the capital distribution of the security.
259-
async fn capital_distribution(&self, symbol: String) -> Result<impl IntoContents, Error> {
287+
async fn capital_distribution(
288+
&self,
289+
symbol: String,
290+
) -> Result<Json<CapitalDistributionResponse>, Error> {
260291
Ok(Json(self.quote_context.capital_distribution(symbol).await?))
261292
}
262293

@@ -265,7 +296,7 @@ impl Longport {
265296
&self,
266297
/// Market code. (e.g. "HK", "US", "CN", "SG")
267298
market: String,
268-
) -> Result<impl IntoContents, Error> {
299+
) -> Result<Json<MarketTemperature>, Error> {
269300
let market = market.parse::<Market>().map_err(|err| Error::ParseField {
270301
name: "market",
271302
error: err.to_string(),
@@ -284,7 +315,7 @@ impl Longport {
284315
start: String,
285316
/// format: "yyyy-mm-dd"
286317
end: String,
287-
) -> Result<impl IntoContents, Error> {
318+
) -> Result<Json<HistoryMarketTemperatureResponse>, Error> {
288319
let market = market.parse::<Market>().map_err(|err| Error::ParseField {
289320
name: "market",
290321
error: err.to_string(),
@@ -305,7 +336,7 @@ impl Longport {
305336
}
306337

307338
/// Get the account balance.
308-
async fn account_balance(&self) -> Result<impl IntoContents, Error> {
339+
async fn account_balance(&self) -> Result<Vec<Json<AccountBalance>>, Error> {
309340
Ok(self
310341
.trade_context
311342
.account_balance(None)
@@ -316,7 +347,7 @@ impl Longport {
316347
}
317348

318349
/// Returns the stock positions.
319-
async fn stock_positions(&self) -> Result<impl IntoContents, Error> {
350+
async fn stock_positions(&self) -> Result<Vec<Json<StockPositionChannel>>, Error> {
320351
Ok(self
321352
.trade_context
322353
.stock_positions(None)
@@ -328,7 +359,7 @@ impl Longport {
328359
}
329360

330361
/// Returns the fund positions.
331-
async fn fund_positions(&self) -> Result<impl IntoContents, Error> {
362+
async fn fund_positions(&self) -> Result<Vec<Json<FundPositionChannel>>, Error> {
332363
Ok(self
333364
.trade_context
334365
.fund_positions(None)
@@ -341,7 +372,7 @@ impl Longport {
341372

342373
/// Returns the initial margin ratio, maintain the margin ratio and
343374
/// strengthen the margin ratio of stocks.
344-
async fn magin_ratio(&self, symbol: String) -> Result<impl IntoContents, Error> {
375+
async fn magin_ratio(&self, symbol: String) -> Result<Json<MarginRatio>, Error> {
345376
Ok(Json(self.trade_context.margin_ratio(symbol).await?))
346377
}
347378

@@ -386,7 +417,7 @@ impl Longport {
386417
/// - GTC: Good Till Cancel
387418
/// - GTD: Good Till Date
388419
time_in_force: String,
389-
) -> Result<impl IntoContents, Error> {
420+
) -> Result<Json<SubmitOrderResponse>, Error> {
390421
let mut opts = SubmitOrderOptions::new(
391422
symbol,
392423
order_type
@@ -447,17 +478,17 @@ impl Longport {
447478
self.trade_context.submit_order(opts).await.map(Json)
448479
}
449480

450-
async fn cancel_order(&self, order_id: String) -> Result<impl IntoContents, Error> {
451-
Ok(Json(self.trade_context.cancel_order(order_id).await?))
481+
async fn cancel_order(&self, order_id: String) -> Result<(), Error> {
482+
self.trade_context.cancel_order(order_id).await
452483
}
453484

454485
/// Get the order detail.
455-
async fn order_detail(&self, order_id: String) -> Result<impl IntoContents, Error> {
486+
async fn order_detail(&self, order_id: String) -> Result<Json<OrderDetail>, Error> {
456487
Ok(Json(self.trade_context.order_detail(order_id).await?))
457488
}
458489

459490
/// Get the current account's orders for the day.
460-
async fn today_orders(&self) -> Result<impl IntoContents, Error> {
491+
async fn today_orders(&self) -> Result<Vec<Json<Order>>, Error> {
461492
Ok(self
462493
.trade_context
463494
.today_orders(None)
@@ -478,7 +509,7 @@ impl Longport {
478509
start_at: String,
479510
/// format: RFC3339
480511
end_at: String,
481-
) -> Result<impl IntoContents, Error> {
512+
) -> Result<Vec<Json<Order>>, Error> {
482513
let mut opts = GetHistoryOrdersOptions::new()
483514
.start_at(
484515
OffsetDateTime::parse(&start_at, &time::format_description::well_known::Rfc3339)

0 commit comments

Comments
 (0)