@dshtrading/connector-jin10 0.6.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/errors.d.ts +24 -1
- package/lib/errors.js +14 -1
- package/lib/index.d.ts +4 -4
- package/lib/index.js +4 -4
- package/lib/market-data.d.ts +2 -6
- package/lib/market-data.js +16 -24
- package/lib/mcp.d.ts +32 -8
- package/lib/mcp.js +113 -22
- package/lib/tools.js +3 -2
- package/package.json +3 -3
package/lib/errors.d.ts
CHANGED
|
@@ -7,6 +7,29 @@ declare class Jin10Error extends Error {
|
|
|
7
7
|
readonly code: TradingErrorCode;
|
|
8
8
|
constructor(code: TradingErrorCode, message: string, cause?: unknown);
|
|
9
9
|
}
|
|
10
|
+
/** MCP initialize 握手中可机器识别的契约违约种类。 */
|
|
11
|
+
type Jin10McpContractViolationKind = 'initialize_result_invalid' | 'unsupported_protocol_version' | 'missing_capability';
|
|
12
|
+
/** 结构化契约违约载荷:错误码之外,调用方可按 kind 分支处理而不必解析文案。 */
|
|
13
|
+
interface Jin10McpContractViolation {
|
|
14
|
+
readonly kind: Jin10McpContractViolationKind;
|
|
15
|
+
readonly method: string;
|
|
16
|
+
/** unsupported_protocol_version:客户端声明/支持的版本。 */
|
|
17
|
+
readonly requestedVersion?: string;
|
|
18
|
+
readonly negotiatedVersion?: string;
|
|
19
|
+
readonly supportedVersions?: readonly string[];
|
|
20
|
+
/** missing_capability:缺失的服务端能力与触发它的方法。 */
|
|
21
|
+
readonly capability?: 'tools' | 'resources';
|
|
22
|
+
readonly detail?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* MCP 协议契约违约(initialize 结果非法、协商版本不受支持、方法能力未声明)。
|
|
26
|
+
* 错误码沿用统一词汇 TRADING_EXCHANGE_ERROR(本包对上游坏形状的既有口径),
|
|
27
|
+
* 可分支信息放在 violation 上——不新造跨包错误码,也不把契约违约伪装成网络故障。
|
|
28
|
+
*/
|
|
29
|
+
declare class Jin10McpContractError extends Jin10Error {
|
|
30
|
+
readonly violation: Jin10McpContractViolation;
|
|
31
|
+
constructor(violation: Jin10McpContractViolation, message: string);
|
|
32
|
+
}
|
|
10
33
|
/**
|
|
11
34
|
* 上游业务错误消息 → 错误码。
|
|
12
35
|
* 限流文案必须单独识别(决定「今天别再试」的语义);「不支持该品种」= 代码不在
|
|
@@ -15,4 +38,4 @@ declare class Jin10Error extends Error {
|
|
|
15
38
|
*/
|
|
16
39
|
declare function codeForUpstreamMessage(message: string): TradingErrorCode;
|
|
17
40
|
//#endregion
|
|
18
|
-
export { Jin10Error, TOKEN_HINT, codeForUpstreamMessage };
|
|
41
|
+
export { Jin10Error, Jin10McpContractError, Jin10McpContractViolation, Jin10McpContractViolationKind, TOKEN_HINT, codeForUpstreamMessage };
|
package/lib/errors.js
CHANGED
|
@@ -12,6 +12,19 @@ var Jin10Error = class extends Error {
|
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
14
|
/**
|
|
15
|
+
* MCP 协议契约违约(initialize 结果非法、协商版本不受支持、方法能力未声明)。
|
|
16
|
+
* 错误码沿用统一词汇 TRADING_EXCHANGE_ERROR(本包对上游坏形状的既有口径),
|
|
17
|
+
* 可分支信息放在 violation 上——不新造跨包错误码,也不把契约违约伪装成网络故障。
|
|
18
|
+
*/
|
|
19
|
+
var Jin10McpContractError = class extends Jin10Error {
|
|
20
|
+
violation;
|
|
21
|
+
constructor(violation, message) {
|
|
22
|
+
super("TRADING_EXCHANGE_ERROR", message);
|
|
23
|
+
this.name = "Jin10McpContractError";
|
|
24
|
+
this.violation = Object.freeze({ ...violation });
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
15
28
|
* 上游业务错误消息 → 错误码。
|
|
16
29
|
* 限流文案必须单独识别(决定「今天别再试」的语义);「不支持该品种」= 代码不在
|
|
17
30
|
* quote://codes 名册内(本出口实测文案,2026-09-13),映射到 UNSUPPORTED_SYMBOL
|
|
@@ -23,4 +36,4 @@ function codeForUpstreamMessage(message) {
|
|
|
23
36
|
return "TRADING_EXCHANGE_ERROR";
|
|
24
37
|
}
|
|
25
38
|
//#endregion
|
|
26
|
-
export { Jin10Error, TOKEN_HINT, codeForUpstreamMessage };
|
|
39
|
+
export { Jin10Error, Jin10McpContractError, TOKEN_HINT, codeForUpstreamMessage };
|
package/lib/index.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, Jin10McpClient, Jin10McpOptions, McpContentPart,
|
|
1
|
+
import { DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, Jin10McpClient, Jin10McpOptions, McpContentPart, McpToolDescriptor, McpToolResult, PROTOCOL_VERSION_HEADER, SUPPORTED_PROTOCOL_VERSIONS, parseMcpBody } from "./mcp.js";
|
|
2
2
|
import { Jin10ArticleDetail, Jin10ArticleSummary, Jin10CalendarEntry, Jin10Instrument, Jin10Kline, Jin10NewsItem, Jin10NewsPage, Jin10Quote, flashTitle, parseArticle, parseCalendar, parseFlashItems, parseFlashPage, parseJin10Time, parseKlines, parseNewsItems, parseNewsPage, parseQuote, parseQuoteCodes } from "./parse.js";
|
|
3
3
|
import { JIN10_HEAT_LEVELS, JIN10_WEB_APP_ID, JIN10_WEB_FLASH_CHANNELS, JIN10_WEB_FLASH_ENDPOINT, JIN10_WEB_PAGE_SIZE, JIN10_WEB_X_VERSION, Jin10FlashItem, Jin10HeatLevel, Jin10HotFlashOptions, fetchJin10HotFlash, isJin10HeatLevel, parseWebFlashItems } from "./web-flash.js";
|
|
4
4
|
import { JIN10_RATES_APP_ID, JIN10_RATES_ENDPOINT, JIN10_RATES_X_VERSION, Jin10RateEntry, fetchJin10Rates, parseWebRates } from "./web-rates.js";
|
|
5
5
|
import { FLASH_PAGE_SIZE, INSTRUMENT_CACHE_TTL_MS, Jin10PageOptions, Jin10Service, SEARCH_FLASH_MAX } from "./service.js";
|
|
6
6
|
import { Config, apply, inject, name } from "./plugin.js";
|
|
7
|
-
import { Jin10Error, TOKEN_HINT, codeForUpstreamMessage } from "./errors.js";
|
|
7
|
+
import { Jin10Error, Jin10McpContractError, Jin10McpContractViolation, Jin10McpContractViolationKind, TOKEN_HINT, codeForUpstreamMessage } from "./errors.js";
|
|
8
8
|
import { TRADING_FLASH_FEED_KEY, createJin10FlashFeed } from "./flash-service.js";
|
|
9
9
|
import { MACRO_CALENDAR_MAX, TRADING_MACRO_FEED_KEY, createJin10MacroFeed } from "./macro-service.js";
|
|
10
|
-
import { GLOBAL_MARKET, JIN10_PROVIDER, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL,
|
|
10
|
+
import { GLOBAL_MARKET, JIN10_PROVIDER, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL, TRADING_GLOBAL_MARKET_DATA_KEY, aggregateKlines, createJin10GlobalMarketDataService, resolveIntervalMinutes, tickerFromQuote } from "./market-data.js";
|
|
11
11
|
import { JIN10_REGIONS, Jin10Region, regionOfFlagUrl, regionOfTitle } from "./regions.js";
|
|
12
12
|
import { createJin10Tools } from "./tools.js";
|
|
13
|
-
export { Config, DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, FLASH_PAGE_SIZE, GLOBAL_MARKET, INSTRUMENT_CACHE_TTL_MS, JIN10_HEAT_LEVELS, JIN10_PROVIDER, JIN10_RATES_APP_ID, JIN10_RATES_ENDPOINT, JIN10_RATES_X_VERSION, JIN10_REGIONS, JIN10_WEB_APP_ID, JIN10_WEB_FLASH_CHANNELS, JIN10_WEB_FLASH_ENDPOINT, JIN10_WEB_PAGE_SIZE, JIN10_WEB_X_VERSION, Jin10ArticleDetail, Jin10ArticleSummary, Jin10CalendarEntry, Jin10Error, Jin10FlashItem, Jin10HeatLevel, Jin10HotFlashOptions, Jin10Instrument, Jin10Kline, Jin10McpClient, Jin10McpOptions, Jin10NewsItem, Jin10NewsPage, Jin10PageOptions, Jin10Quote, Jin10RateEntry, Jin10Region, Jin10Service, MACRO_CALENDAR_MAX, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL, McpContentPart,
|
|
13
|
+
export { Config, DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, FLASH_PAGE_SIZE, GLOBAL_MARKET, INSTRUMENT_CACHE_TTL_MS, JIN10_HEAT_LEVELS, JIN10_PROVIDER, JIN10_RATES_APP_ID, JIN10_RATES_ENDPOINT, JIN10_RATES_X_VERSION, JIN10_REGIONS, JIN10_WEB_APP_ID, JIN10_WEB_FLASH_CHANNELS, JIN10_WEB_FLASH_ENDPOINT, JIN10_WEB_PAGE_SIZE, JIN10_WEB_X_VERSION, Jin10ArticleDetail, Jin10ArticleSummary, Jin10CalendarEntry, Jin10Error, Jin10FlashItem, Jin10HeatLevel, Jin10HotFlashOptions, Jin10Instrument, Jin10Kline, Jin10McpClient, Jin10McpContractError, Jin10McpContractViolation, Jin10McpContractViolationKind, Jin10McpOptions, Jin10NewsItem, Jin10NewsPage, Jin10PageOptions, Jin10Quote, Jin10RateEntry, Jin10Region, Jin10Service, MACRO_CALENDAR_MAX, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL, McpContentPart, McpToolDescriptor, McpToolResult, PROTOCOL_VERSION_HEADER, SEARCH_FLASH_MAX, SUPPORTED_PROTOCOL_VERSIONS, TOKEN_HINT, TRADING_FLASH_FEED_KEY, TRADING_GLOBAL_MARKET_DATA_KEY, TRADING_MACRO_FEED_KEY, aggregateKlines, apply, codeForUpstreamMessage, createJin10FlashFeed, createJin10GlobalMarketDataService, createJin10MacroFeed, createJin10Tools, fetchJin10HotFlash, fetchJin10Rates, flashTitle, inject, isJin10HeatLevel, name, parseArticle, parseCalendar, parseFlashItems, parseFlashPage, parseJin10Time, parseKlines, parseMcpBody, parseNewsItems, parseNewsPage, parseQuote, parseQuoteCodes, parseWebFlashItems, parseWebRates, regionOfFlagUrl, regionOfTitle, resolveIntervalMinutes, tickerFromQuote };
|
package/lib/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { Jin10Error, TOKEN_HINT, codeForUpstreamMessage } from "./errors.js";
|
|
1
|
+
import { Jin10Error, Jin10McpContractError, TOKEN_HINT, codeForUpstreamMessage } from "./errors.js";
|
|
2
2
|
import { JIN10_REGIONS, regionOfFlagUrl, regionOfTitle } from "./regions.js";
|
|
3
3
|
import { flashTitle, parseArticle, parseCalendar, parseFlashItems, parseFlashPage, parseJin10Time, parseKlines, parseNewsItems, parseNewsPage, parseQuote, parseQuoteCodes } from "./parse.js";
|
|
4
4
|
import { JIN10_HEAT_LEVELS, JIN10_WEB_APP_ID, JIN10_WEB_FLASH_CHANNELS, JIN10_WEB_FLASH_ENDPOINT, JIN10_WEB_PAGE_SIZE, JIN10_WEB_X_VERSION, fetchJin10HotFlash, isJin10HeatLevel, parseWebFlashItems } from "./web-flash.js";
|
|
5
5
|
import { TRADING_FLASH_FEED_KEY, createJin10FlashFeed } from "./flash-service.js";
|
|
6
6
|
import { MACRO_CALENDAR_MAX, TRADING_MACRO_FEED_KEY, createJin10MacroFeed } from "./macro-service.js";
|
|
7
|
-
import { GLOBAL_MARKET, JIN10_PROVIDER, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL,
|
|
8
|
-
import { DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, Jin10McpClient, parseMcpBody } from "./mcp.js";
|
|
7
|
+
import { GLOBAL_MARKET, JIN10_PROVIDER, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL, TRADING_GLOBAL_MARKET_DATA_KEY, aggregateKlines, createJin10GlobalMarketDataService, resolveIntervalMinutes, tickerFromQuote } from "./market-data.js";
|
|
8
|
+
import { DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, Jin10McpClient, PROTOCOL_VERSION_HEADER, SUPPORTED_PROTOCOL_VERSIONS, parseMcpBody } from "./mcp.js";
|
|
9
9
|
import { JIN10_RATES_APP_ID, JIN10_RATES_ENDPOINT, JIN10_RATES_X_VERSION, fetchJin10Rates, parseWebRates } from "./web-rates.js";
|
|
10
10
|
import { FLASH_PAGE_SIZE, INSTRUMENT_CACHE_TTL_MS, Jin10Service, SEARCH_FLASH_MAX } from "./service.js";
|
|
11
11
|
import { createJin10Tools } from "./tools.js";
|
|
12
12
|
import { Config, apply, inject, name } from "./plugin.js";
|
|
13
|
-
export { Config, DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, FLASH_PAGE_SIZE, GLOBAL_MARKET, INSTRUMENT_CACHE_TTL_MS, JIN10_HEAT_LEVELS, JIN10_PROVIDER, JIN10_RATES_APP_ID, JIN10_RATES_ENDPOINT, JIN10_RATES_X_VERSION, JIN10_REGIONS, JIN10_WEB_APP_ID, JIN10_WEB_FLASH_CHANNELS, JIN10_WEB_FLASH_ENDPOINT, JIN10_WEB_PAGE_SIZE, JIN10_WEB_X_VERSION, Jin10Error, Jin10McpClient, Jin10Service, MACRO_CALENDAR_MAX, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL, SEARCH_FLASH_MAX,
|
|
13
|
+
export { Config, DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, FLASH_PAGE_SIZE, GLOBAL_MARKET, INSTRUMENT_CACHE_TTL_MS, JIN10_HEAT_LEVELS, JIN10_PROVIDER, JIN10_RATES_APP_ID, JIN10_RATES_ENDPOINT, JIN10_RATES_X_VERSION, JIN10_REGIONS, JIN10_WEB_APP_ID, JIN10_WEB_FLASH_CHANNELS, JIN10_WEB_FLASH_ENDPOINT, JIN10_WEB_PAGE_SIZE, JIN10_WEB_X_VERSION, Jin10Error, Jin10McpClient, Jin10McpContractError, Jin10Service, MACRO_CALENDAR_MAX, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL, PROTOCOL_VERSION_HEADER, SEARCH_FLASH_MAX, SUPPORTED_PROTOCOL_VERSIONS, TOKEN_HINT, TRADING_FLASH_FEED_KEY, TRADING_GLOBAL_MARKET_DATA_KEY, TRADING_MACRO_FEED_KEY, aggregateKlines, apply, codeForUpstreamMessage, createJin10FlashFeed, createJin10GlobalMarketDataService, createJin10MacroFeed, createJin10Tools, fetchJin10HotFlash, fetchJin10Rates, flashTitle, inject, isJin10HeatLevel, name, parseArticle, parseCalendar, parseFlashItems, parseFlashPage, parseJin10Time, parseKlines, parseMcpBody, parseNewsItems, parseNewsPage, parseQuote, parseQuoteCodes, parseWebFlashItems, parseWebRates, regionOfFlagUrl, regionOfTitle, resolveIntervalMinutes, tickerFromQuote };
|
package/lib/market-data.d.ts
CHANGED
|
@@ -12,16 +12,12 @@ declare const TRADING_GLOBAL_MARKET_DATA_KEY = "tradingGlobalMarketData";
|
|
|
12
12
|
declare const MINUTE_BARS_PER_CALL = 100;
|
|
13
13
|
/** 本仓最多拼的分钟窗口(3 次上游调用);再深的历史上游没有,不做假数据。 */
|
|
14
14
|
declare const MAX_MINUTE_WINDOW = 300;
|
|
15
|
-
/** Ticker 轮询周期(上游无推送通道)。 */
|
|
16
|
-
declare const TICKER_POLL_MS = 5000;
|
|
17
15
|
declare function resolveIntervalMinutes(interval: string): number | undefined;
|
|
18
16
|
/** 按分钟数聚合(桶起点 = 本地时间轴对齐;量能求和,缺量按 0)。 */
|
|
19
17
|
declare function aggregateKlines(bars: readonly Kline[], minutes: number): Kline[];
|
|
20
18
|
/** get_quote → Ticker(缺失最新价 = 上游形状异常,如实报错,不编价格)。 */
|
|
21
19
|
declare function tickerFromQuote(quote: Jin10Quote): Ticker;
|
|
22
20
|
/** global 市场数据面实现(纯对象;与快讯面同款,避免 Service 构造签名的类型漂移)。 */
|
|
23
|
-
declare function createJin10GlobalMarketDataService(feed: Jin10Service
|
|
24
|
-
pollMs?: number;
|
|
25
|
-
}): MarketDataService;
|
|
21
|
+
declare function createJin10GlobalMarketDataService(feed: Jin10Service): MarketDataService;
|
|
26
22
|
//#endregion
|
|
27
|
-
export { GLOBAL_MARKET, JIN10_PROVIDER, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL,
|
|
23
|
+
export { GLOBAL_MARKET, JIN10_PROVIDER, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL, TRADING_GLOBAL_MARKET_DATA_KEY, aggregateKlines, createJin10GlobalMarketDataService, resolveIntervalMinutes, tickerFromQuote };
|
package/lib/market-data.js
CHANGED
|
@@ -10,8 +10,14 @@ const TRADING_GLOBAL_MARKET_DATA_KEY = "tradingGlobalMarketData";
|
|
|
10
10
|
const MINUTE_BARS_PER_CALL = 100;
|
|
11
11
|
/** 本仓最多拼的分钟窗口(3 次上游调用);再深的历史上游没有,不做假数据。 */
|
|
12
12
|
const MAX_MINUTE_WINDOW = 300;
|
|
13
|
-
/**
|
|
14
|
-
|
|
13
|
+
/**
|
|
14
|
+
* 本市场**不提供常驻 ticker 订阅**:`global_quote` / `global_klines` 的 UI/价格
|
|
15
|
+
* 路径预算为 **0 常驻**——上游配额按工具分池,固定间隔轮询按秒折算必然超出一个
|
|
16
|
+
* 数量级。分配口径与折算数值的家是 dsh-trading-bot 的
|
|
17
|
+
* `packages/tradectl/bin/feeds-budget.mjs` 与 `docs/guides/connectors-guide.md`
|
|
18
|
+
* 的「金十额度预算分配」节(本仓只引用规则,不复写数值);GUI 侧节奏执行见
|
|
19
|
+
* client-ui-trading 的 quote-budget.ts。要价格一律按需:`getTicker` / `getKlines`。
|
|
20
|
+
*/
|
|
15
21
|
/** 支持的周期 → 每根分钟数(api Interval 的子集:分钟级来源能诚实支撑的部分)。 */
|
|
16
22
|
const INTERVAL_MINUTES = {
|
|
17
23
|
"1m": 1,
|
|
@@ -88,8 +94,7 @@ function minuteBarToKline(bar) {
|
|
|
88
94
|
};
|
|
89
95
|
}
|
|
90
96
|
/** global 市场数据面实现(纯对象;与快讯面同款,避免 Service 构造签名的类型漂移)。 */
|
|
91
|
-
function createJin10GlobalMarketDataService(feed
|
|
92
|
-
const pollMs = options.pollMs ?? 5e3;
|
|
97
|
+
function createJin10GlobalMarketDataService(feed) {
|
|
93
98
|
const requireCode = (symbol) => {
|
|
94
99
|
const trimmed = symbol.trim().toUpperCase();
|
|
95
100
|
if (trimmed === "") throw new Jin10Error("TRADING_UNKNOWN", "jin10 global: symbol must not be empty");
|
|
@@ -128,25 +133,12 @@ function createJin10GlobalMarketDataService(feed, options = {}) {
|
|
|
128
133
|
const wanted = Math.max(1, Math.min(Math.floor(limit), Math.floor(300 / minutes)));
|
|
129
134
|
return aggregateKlines(await loadMinuteWindow(requireCode(symbol), wanted * minutes), minutes).slice(-wanted);
|
|
130
135
|
},
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
if (!stopped) listener(ticker);
|
|
138
|
-
} catch (error) {
|
|
139
|
-
if (!stopped) console.warn("[dsh-trading] jin10 ticker poll failed for " + symbol + ":", error);
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
tick();
|
|
143
|
-
const timer = setInterval(() => {
|
|
144
|
-
tick();
|
|
145
|
-
}, pollMs);
|
|
146
|
-
return { dispose() {
|
|
147
|
-
stopped = true;
|
|
148
|
-
clearInterval(timer);
|
|
149
|
-
} };
|
|
136
|
+
/**
|
|
137
|
+
* 常驻 ticker 订阅显式拒绝(见模块头注释):本市场没有常驻轮询预算,静默
|
|
138
|
+
* 轮询正是预算失控的形态。要价格请按需 `getTicker`。
|
|
139
|
+
*/
|
|
140
|
+
subscribeTicker(symbol) {
|
|
141
|
+
throw new Jin10Error("TRADING_NOT_IMPLEMENTED", "jin10 global: 不提供常驻 ticker 订阅(global_quote 的 UI/价格路径预算为 0 常驻,见 connectors-guide「金十额度预算分配」);请按需调用 getTicker。symbol=" + symbol);
|
|
150
142
|
},
|
|
151
143
|
async listInstruments() {
|
|
152
144
|
return (await feed.listInstruments()).map((item) => ({
|
|
@@ -157,4 +149,4 @@ function createJin10GlobalMarketDataService(feed, options = {}) {
|
|
|
157
149
|
};
|
|
158
150
|
}
|
|
159
151
|
//#endregion
|
|
160
|
-
export { GLOBAL_MARKET, JIN10_PROVIDER, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL,
|
|
152
|
+
export { GLOBAL_MARKET, JIN10_PROVIDER, MAX_MINUTE_WINDOW, MINUTE_BARS_PER_CALL, TRADING_GLOBAL_MARKET_DATA_KEY, aggregateKlines, createJin10GlobalMarketDataService, resolveIntervalMinutes, tickerFromQuote };
|
package/lib/mcp.d.ts
CHANGED
|
@@ -2,18 +2,22 @@
|
|
|
2
2
|
declare const DEFAULT_ENDPOINT = "https://mcp.jin10.com/mcp";
|
|
3
3
|
declare const DEFAULT_PROTOCOL_VERSION = "2025-11-25";
|
|
4
4
|
declare const DEFAULT_TIMEOUT_MS = 15000;
|
|
5
|
+
/**
|
|
6
|
+
* 本客户端能说的 Streamable HTTP 协议版本(官方 revision):
|
|
7
|
+
* - `2025-11-25`:金十本出口 spike 实测协商版本;
|
|
8
|
+
* - `2025-06-18`:官方首个定义 `MCP-Protocol-Version` 头的 revision。
|
|
9
|
+
* 上游协商出集合之外的版本时按官方「客户端 SHOULD disconnect」报结构化错误,
|
|
10
|
+
* 不降级猜测协议语义。
|
|
11
|
+
*/
|
|
12
|
+
declare const SUPPORTED_PROTOCOL_VERSIONS: readonly string[];
|
|
13
|
+
/** initialize 之后每个 HTTP 请求都必须携带的协商版本头(官方 Streamable HTTP)。 */
|
|
14
|
+
declare const PROTOCOL_VERSION_HEADER = "MCP-Protocol-Version";
|
|
5
15
|
interface McpToolDescriptor {
|
|
6
16
|
name: string;
|
|
7
17
|
description?: string;
|
|
8
18
|
inputSchema?: unknown;
|
|
9
19
|
outputSchema?: unknown;
|
|
10
20
|
}
|
|
11
|
-
interface McpResourceDescriptor {
|
|
12
|
-
uri: string;
|
|
13
|
-
name?: string;
|
|
14
|
-
mimeType?: string;
|
|
15
|
-
description?: string;
|
|
16
|
-
}
|
|
17
21
|
/** 可读文本段(structuredContent 缺席时的兜底来源)。 */
|
|
18
22
|
interface McpContentPart {
|
|
19
23
|
type?: string;
|
|
@@ -33,6 +37,8 @@ interface Jin10McpOptions {
|
|
|
33
37
|
timeoutMs?: number;
|
|
34
38
|
/** 依赖注入的 fetch(测试用 mock;缺省 globalThis.fetch)。 */
|
|
35
39
|
fetchImpl?: typeof globalThis.fetch;
|
|
40
|
+
/** 可选会话级取消信号:与单次请求超时合并,取消报「request aborted」。 */
|
|
41
|
+
signal?: AbortSignal;
|
|
36
42
|
/** 协议版本(缺省 2025-11-25)。 */
|
|
37
43
|
protocolVersion?: string;
|
|
38
44
|
clientName?: string;
|
|
@@ -58,12 +64,16 @@ declare class Jin10McpClient {
|
|
|
58
64
|
private readonly protocolVersion;
|
|
59
65
|
private readonly clientName;
|
|
60
66
|
private readonly clientVersion;
|
|
67
|
+
private readonly signal;
|
|
61
68
|
private nextId;
|
|
62
69
|
private sessionId;
|
|
63
70
|
private handshake;
|
|
71
|
+
/** initialize 协商出的协议版本(其后每个请求的 MCP-Protocol-Version 头来源)。 */
|
|
72
|
+
private negotiatedProtocolVersion;
|
|
73
|
+
/** initialize 声明的服务端能力表(方法族能力闸门的判据)。 */
|
|
74
|
+
private serverCapabilities;
|
|
64
75
|
constructor(options: Jin10McpOptions);
|
|
65
76
|
listTools(): Promise<McpToolDescriptor[]>;
|
|
66
|
-
listResources(): Promise<McpResourceDescriptor[]>;
|
|
67
77
|
/** 读资源正文(quote://codes 等;返回全部 text 段拼接)。 */
|
|
68
78
|
readResource(uri: string): Promise<string>;
|
|
69
79
|
/** 原始 tools/call(不做业务解包;协议/HTTP 错误在此抛出)。 */
|
|
@@ -74,8 +84,22 @@ declare class Jin10McpClient {
|
|
|
74
84
|
*/
|
|
75
85
|
callToolData(tool: string, args?: Record<string, unknown>): Promise<unknown>;
|
|
76
86
|
private ensureHandshake;
|
|
87
|
+
/** 丢弃一次未完成的握手留下的全部状态(initialize 之后、initialized 之前的任何失败)。 */
|
|
88
|
+
private resetHandshakeState;
|
|
77
89
|
private performHandshake;
|
|
90
|
+
/**
|
|
91
|
+
* 校验 initialize 结果并返回服务端能力表;违反官方 lifecycle 契约时抛结构化错误。
|
|
92
|
+
* 依据:官方 revision 2025-11-25 lifecycle——服务端 MUST 回 protocolVersion 与
|
|
93
|
+
* capabilities;客户端不支持的协商版本 SHOULD disconnect。
|
|
94
|
+
*/
|
|
95
|
+
private acceptInitializeResult;
|
|
96
|
+
/** 客户端可接受的协商版本:声明的版本 + 官方可说的版本集合。 */
|
|
97
|
+
private supportedVersions;
|
|
98
|
+
/** 方法族能力闸门:能力未声明时在发请求前抛结构化错误(缺能力 ≠ 上游 4xx)。 */
|
|
99
|
+
private assertMethodCapability;
|
|
100
|
+
/** 单次请求信号:调用方取消信号与超时窗口合并,任一触发都以 AbortError 结束。 */
|
|
101
|
+
private requestSignal;
|
|
78
102
|
private rpc;
|
|
79
103
|
}
|
|
80
104
|
//#endregion
|
|
81
|
-
export { DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, Jin10McpClient, Jin10McpOptions, McpContentPart,
|
|
105
|
+
export { DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, Jin10McpClient, Jin10McpOptions, McpContentPart, McpToolDescriptor, McpToolResult, PROTOCOL_VERSION_HEADER, SUPPORTED_PROTOCOL_VERSIONS, parseMcpBody };
|
package/lib/mcp.js
CHANGED
|
@@ -1,20 +1,42 @@
|
|
|
1
|
-
import { Jin10Error, TOKEN_HINT, codeForUpstreamMessage } from "./errors.js";
|
|
1
|
+
import { Jin10Error, Jin10McpContractError, TOKEN_HINT, codeForUpstreamMessage } from "./errors.js";
|
|
2
2
|
//#region src/mcp.ts
|
|
3
3
|
/**
|
|
4
4
|
* MCP 传输层(Streamable HTTP / JSON-RPC 2.0)。
|
|
5
5
|
*
|
|
6
6
|
* 标准流程(用户 2026-09-13 给定契约,本出口实测复核):
|
|
7
|
-
* initialize → notifications/initialized → tools/list / resources/
|
|
7
|
+
* initialize → notifications/initialized → tools/list / resources/read → tools/call
|
|
8
8
|
* 响应形态两种都要吃:`application/json` 直出 JSON,或 `text/event-stream` 里
|
|
9
9
|
* `event: message` + 单行 `data: {…}`(金十本出口实测为后者)。若上游回
|
|
10
10
|
* `mcp-session-id` 头则后续请求原样回带(本出口当前无会话头,属可选能力)。
|
|
11
11
|
*
|
|
12
12
|
* 结果读取:`result.structuredContent` 优先,`result.content[].text` 仅在
|
|
13
13
|
* structuredContent 缺席时作可读文本兜底(用户契约 3/4)。
|
|
14
|
+
*
|
|
15
|
+
* 握手契约(官方 MCP revision 2025-11-25 / 2025-06-18,本仓 spike 原始证据
|
|
16
|
+
* `spikes/impl-jin10-mcp/EVIDENCE/01-initialize.json`):客户端必须校验 initialize
|
|
17
|
+
* 结果里的 `protocolVersion` 与 `capabilities`;协商版本用于其后每个 HTTP 请求的
|
|
18
|
+
* `MCP-Protocol-Version` 头;未声明 `tools` / `resources` 能力时对应方法族直接报
|
|
19
|
+
* 结构化契约错误,不发业务请求(不重造宿主 MCP、不升级 SDK)。
|
|
14
20
|
*/
|
|
15
21
|
const DEFAULT_ENDPOINT = "https://mcp.jin10.com/mcp";
|
|
16
22
|
const DEFAULT_PROTOCOL_VERSION = "2025-11-25";
|
|
17
23
|
const DEFAULT_TIMEOUT_MS = 15e3;
|
|
24
|
+
/**
|
|
25
|
+
* 本客户端能说的 Streamable HTTP 协议版本(官方 revision):
|
|
26
|
+
* - `2025-11-25`:金十本出口 spike 实测协商版本;
|
|
27
|
+
* - `2025-06-18`:官方首个定义 `MCP-Protocol-Version` 头的 revision。
|
|
28
|
+
* 上游协商出集合之外的版本时按官方「客户端 SHOULD disconnect」报结构化错误,
|
|
29
|
+
* 不降级猜测协议语义。
|
|
30
|
+
*/
|
|
31
|
+
const SUPPORTED_PROTOCOL_VERSIONS = Object.freeze(["2025-11-25", "2025-06-18"]);
|
|
32
|
+
/** initialize 之后每个 HTTP 请求都必须携带的协商版本头(官方 Streamable HTTP)。 */
|
|
33
|
+
const PROTOCOL_VERSION_HEADER = "MCP-Protocol-Version";
|
|
34
|
+
/** 服务端能力 → 依赖它的 JSON-RPC 方法族(缺能力即拒发,不靠上游 4xx 兜底)。 */
|
|
35
|
+
const METHOD_CAPABILITY = Object.freeze({
|
|
36
|
+
"tools/list": "tools",
|
|
37
|
+
"tools/call": "tools",
|
|
38
|
+
"resources/read": "resources"
|
|
39
|
+
});
|
|
18
40
|
/** 把响应体解析成 JSON-RPC 消息(直出 JSON 或 SSE 单行 data 均可)。 */
|
|
19
41
|
function parseMcpBody(text) {
|
|
20
42
|
const trimmed = text.trim();
|
|
@@ -45,10 +67,16 @@ function parseMcpBody(text) {
|
|
|
45
67
|
function isRecord(value) {
|
|
46
68
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
47
69
|
}
|
|
48
|
-
|
|
70
|
+
/**
|
|
71
|
+
* 传输层失败:超时与取消分别显式标注(前者带超时窗口,后者标明调用方取消),
|
|
72
|
+
* 不混成一句 network failure,也不在这里重试(重试由调用方显式发起)。
|
|
73
|
+
*/
|
|
74
|
+
function networkError(method, cause, timeoutMs) {
|
|
49
75
|
const reason = cause instanceof Error ? cause.message : String(cause);
|
|
50
|
-
const
|
|
51
|
-
return new Jin10Error("TRADING_NETWORK", `jin10 mcp ${method}:
|
|
76
|
+
const name = cause instanceof Error ? cause.name : "";
|
|
77
|
+
if (name === "TimeoutError") return new Jin10Error("TRADING_NETWORK", `jin10 mcp ${method}: request timed out after ${timeoutMs}ms`, cause);
|
|
78
|
+
if (name === "AbortError") return new Jin10Error("TRADING_NETWORK", `jin10 mcp ${method}: request aborted before completion — ${reason}`, cause);
|
|
79
|
+
return new Jin10Error("TRADING_NETWORK", `jin10 mcp ${method}: network failure — ${reason}`, cause);
|
|
52
80
|
}
|
|
53
81
|
var Jin10McpClient = class {
|
|
54
82
|
endpoint;
|
|
@@ -58,14 +86,20 @@ var Jin10McpClient = class {
|
|
|
58
86
|
protocolVersion;
|
|
59
87
|
clientName;
|
|
60
88
|
clientVersion;
|
|
89
|
+
signal;
|
|
61
90
|
nextId = 1;
|
|
62
91
|
sessionId;
|
|
63
92
|
handshake;
|
|
93
|
+
/** initialize 协商出的协议版本(其后每个请求的 MCP-Protocol-Version 头来源)。 */
|
|
94
|
+
negotiatedProtocolVersion;
|
|
95
|
+
/** initialize 声明的服务端能力表(方法族能力闸门的判据)。 */
|
|
96
|
+
serverCapabilities;
|
|
64
97
|
constructor(options) {
|
|
65
98
|
this.endpoint = options.endpoint ?? "https://mcp.jin10.com/mcp";
|
|
66
99
|
this.token = options.token;
|
|
67
100
|
this.timeoutMs = options.timeoutMs ?? 15e3;
|
|
68
101
|
this.fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
102
|
+
this.signal = options.signal;
|
|
69
103
|
this.protocolVersion = options.protocolVersion ?? "2025-11-25";
|
|
70
104
|
this.clientName = options.clientName ?? "dsh-trading-connector-jin10";
|
|
71
105
|
this.clientVersion = options.clientVersion ?? "0.2.1";
|
|
@@ -81,17 +115,6 @@ var Jin10McpClient = class {
|
|
|
81
115
|
...tool.outputSchema !== void 0 ? { outputSchema: tool.outputSchema } : {}
|
|
82
116
|
}));
|
|
83
117
|
}
|
|
84
|
-
async listResources() {
|
|
85
|
-
const result = await this.rpc("resources/list", {});
|
|
86
|
-
const resources = isRecord(result) ? result.resources : void 0;
|
|
87
|
-
if (!Array.isArray(resources)) throw new Jin10Error("TRADING_EXCHANGE_ERROR", "jin10 mcp resources/list: unexpected payload (expected result.resources[])");
|
|
88
|
-
return resources.filter(isRecord).map((resource) => ({
|
|
89
|
-
uri: String(resource.uri ?? ""),
|
|
90
|
-
...typeof resource.name === "string" ? { name: resource.name } : {},
|
|
91
|
-
...typeof resource.mimeType === "string" ? { mimeType: resource.mimeType } : {},
|
|
92
|
-
...typeof resource.description === "string" ? { description: resource.description } : {}
|
|
93
|
-
}));
|
|
94
|
-
}
|
|
95
118
|
/** 读资源正文(quote://codes 等;返回全部 text 段拼接)。 */
|
|
96
119
|
async readResource(uri) {
|
|
97
120
|
const result = await this.rpc("resources/read", { uri });
|
|
@@ -131,12 +154,19 @@ var Jin10McpClient = class {
|
|
|
131
154
|
async ensureHandshake() {
|
|
132
155
|
if (this.handshake === void 0) this.handshake = this.performHandshake().catch((error) => {
|
|
133
156
|
this.handshake = void 0;
|
|
157
|
+
this.resetHandshakeState();
|
|
134
158
|
throw error;
|
|
135
159
|
});
|
|
136
160
|
return this.handshake;
|
|
137
161
|
}
|
|
162
|
+
/** 丢弃一次未完成的握手留下的全部状态(initialize 之后、initialized 之前的任何失败)。 */
|
|
163
|
+
resetHandshakeState() {
|
|
164
|
+
this.negotiatedProtocolVersion = void 0;
|
|
165
|
+
this.serverCapabilities = void 0;
|
|
166
|
+
this.sessionId = void 0;
|
|
167
|
+
}
|
|
138
168
|
async performHandshake() {
|
|
139
|
-
await this.rpc("initialize", {
|
|
169
|
+
const result = await this.rpc("initialize", {
|
|
140
170
|
protocolVersion: this.protocolVersion,
|
|
141
171
|
capabilities: {},
|
|
142
172
|
clientInfo: {
|
|
@@ -144,13 +174,73 @@ var Jin10McpClient = class {
|
|
|
144
174
|
version: this.clientVersion
|
|
145
175
|
}
|
|
146
176
|
}, { skipHandshake: true });
|
|
177
|
+
this.serverCapabilities = this.acceptInitializeResult(result);
|
|
147
178
|
await this.rpc("notifications/initialized", void 0, {
|
|
148
179
|
notification: true,
|
|
149
180
|
skipHandshake: true
|
|
150
181
|
});
|
|
151
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* 校验 initialize 结果并返回服务端能力表;违反官方 lifecycle 契约时抛结构化错误。
|
|
185
|
+
* 依据:官方 revision 2025-11-25 lifecycle——服务端 MUST 回 protocolVersion 与
|
|
186
|
+
* capabilities;客户端不支持的协商版本 SHOULD disconnect。
|
|
187
|
+
*/
|
|
188
|
+
acceptInitializeResult(result) {
|
|
189
|
+
if (!isRecord(result)) throw new Jin10McpContractError({
|
|
190
|
+
kind: "initialize_result_invalid",
|
|
191
|
+
method: "initialize",
|
|
192
|
+
detail: "result is not an object"
|
|
193
|
+
}, "jin10 mcp initialize: result is not an object");
|
|
194
|
+
const negotiated = result.protocolVersion;
|
|
195
|
+
if (typeof negotiated !== "string" || negotiated.trim().length === 0) throw new Jin10McpContractError({
|
|
196
|
+
kind: "initialize_result_invalid",
|
|
197
|
+
method: "initialize",
|
|
198
|
+
detail: "missing protocolVersion"
|
|
199
|
+
}, "jin10 mcp initialize: server did not return a protocolVersion");
|
|
200
|
+
const supported = this.supportedVersions();
|
|
201
|
+
if (!supported.includes(negotiated)) throw new Jin10McpContractError({
|
|
202
|
+
kind: "unsupported_protocol_version",
|
|
203
|
+
method: "initialize",
|
|
204
|
+
requestedVersion: this.protocolVersion,
|
|
205
|
+
negotiatedVersion: negotiated,
|
|
206
|
+
supportedVersions: supported
|
|
207
|
+
}, `jin10 mcp initialize: server negotiated unsupported protocol version "${negotiated}" (client supports ${supported.join(", ")})`);
|
|
208
|
+
const capabilities = result.capabilities;
|
|
209
|
+
if (!isRecord(capabilities)) throw new Jin10McpContractError({
|
|
210
|
+
kind: "initialize_result_invalid",
|
|
211
|
+
method: "initialize",
|
|
212
|
+
detail: "missing capabilities"
|
|
213
|
+
}, "jin10 mcp initialize: server did not return a capabilities object");
|
|
214
|
+
this.negotiatedProtocolVersion = negotiated;
|
|
215
|
+
return capabilities;
|
|
216
|
+
}
|
|
217
|
+
/** 客户端可接受的协商版本:声明的版本 + 官方可说的版本集合。 */
|
|
218
|
+
supportedVersions() {
|
|
219
|
+
return SUPPORTED_PROTOCOL_VERSIONS.includes(this.protocolVersion) ? SUPPORTED_PROTOCOL_VERSIONS : Object.freeze([this.protocolVersion, ...SUPPORTED_PROTOCOL_VERSIONS]);
|
|
220
|
+
}
|
|
221
|
+
/** 方法族能力闸门:能力未声明时在发请求前抛结构化错误(缺能力 ≠ 上游 4xx)。 */
|
|
222
|
+
assertMethodCapability(method) {
|
|
223
|
+
const capability = METHOD_CAPABILITY[method];
|
|
224
|
+
if (capability === void 0) return;
|
|
225
|
+
const declared = this.serverCapabilities;
|
|
226
|
+
if (declared !== void 0 && isRecord(declared[capability])) return;
|
|
227
|
+
throw new Jin10McpContractError({
|
|
228
|
+
kind: "missing_capability",
|
|
229
|
+
method,
|
|
230
|
+
capability
|
|
231
|
+
}, `jin10 mcp ${method}: server did not declare the "${capability}" capability during initialize; refusing to send the request`);
|
|
232
|
+
}
|
|
233
|
+
/** 单次请求信号:调用方取消信号与超时窗口合并,任一触发都以 AbortError 结束。 */
|
|
234
|
+
requestSignal() {
|
|
235
|
+
const timeout = AbortSignal.timeout(this.timeoutMs);
|
|
236
|
+
if (this.signal === void 0) return timeout;
|
|
237
|
+
return AbortSignal.any([this.signal, timeout]);
|
|
238
|
+
}
|
|
152
239
|
async rpc(method, params, options = {}) {
|
|
153
|
-
if (options.skipHandshake !== true)
|
|
240
|
+
if (options.skipHandshake !== true) {
|
|
241
|
+
await this.ensureHandshake();
|
|
242
|
+
this.assertMethodCapability(method);
|
|
243
|
+
}
|
|
154
244
|
const token = this.token();
|
|
155
245
|
if (token === void 0 || token.trim().length === 0) throw new Jin10Error("TRADING_CREDENTIALS_MISSING", `jin10 mcp ${method}: missing MCP token. ${TOKEN_HINT}`);
|
|
156
246
|
const payload = {
|
|
@@ -167,13 +257,14 @@ var Jin10McpClient = class {
|
|
|
167
257
|
"content-type": "application/json",
|
|
168
258
|
accept: "application/json, text/event-stream",
|
|
169
259
|
authorization: `Bearer ${token.trim()}`,
|
|
260
|
+
...this.negotiatedProtocolVersion !== void 0 ? { [PROTOCOL_VERSION_HEADER]: this.negotiatedProtocolVersion } : {},
|
|
170
261
|
...this.sessionId !== void 0 ? { "mcp-session-id": this.sessionId } : {}
|
|
171
262
|
},
|
|
172
263
|
body: JSON.stringify(payload),
|
|
173
|
-
signal:
|
|
264
|
+
signal: this.requestSignal()
|
|
174
265
|
});
|
|
175
266
|
} catch (error) {
|
|
176
|
-
throw networkError(method, error);
|
|
267
|
+
throw networkError(method, error, this.timeoutMs);
|
|
177
268
|
}
|
|
178
269
|
const sessionId = response.headers.get("mcp-session-id");
|
|
179
270
|
if (sessionId !== null && sessionId.length > 0) this.sessionId = sessionId;
|
|
@@ -190,7 +281,7 @@ var Jin10McpClient = class {
|
|
|
190
281
|
throw new Jin10Error("TRADING_EXCHANGE_ERROR", `jin10 mcp ${method}: HTTP ${response.status}${body ? ` — ${body.slice(0, 200)}` : ""}`);
|
|
191
282
|
}
|
|
192
283
|
const message = parseMcpBody(await response.text().catch((error) => {
|
|
193
|
-
throw networkError(method, error);
|
|
284
|
+
throw networkError(method, error, this.timeoutMs);
|
|
194
285
|
}));
|
|
195
286
|
if (message === void 0) return void 0;
|
|
196
287
|
if (isRecord(message.error)) {
|
|
@@ -219,4 +310,4 @@ function textEnvelope(result) {
|
|
|
219
310
|
}
|
|
220
311
|
}
|
|
221
312
|
//#endregion
|
|
222
|
-
export { DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, Jin10McpClient, parseMcpBody };
|
|
313
|
+
export { DEFAULT_ENDPOINT, DEFAULT_PROTOCOL_VERSION, DEFAULT_TIMEOUT_MS, Jin10McpClient, PROTOCOL_VERSION_HEADER, SUPPORTED_PROTOCOL_VERSIONS, parseMcpBody };
|
package/lib/tools.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import "./macro-service.js";
|
|
1
2
|
import "./service.js";
|
|
2
3
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
3
4
|
//#region src/tools.ts
|
|
@@ -186,11 +187,11 @@ function createJin10Tools(service) {
|
|
|
186
187
|
description: `Current-week economic calendar from ${SOURCE} (Monday–Sunday, Beijing time): release time, importance stars, consensus / previous / actual values and the stated market impact. Values are the publisher snapshot as of the call — the same release may be revised; treat actual=null as "not published yet". Upstream rate limit: 1500 calls per tool per Beijing calendar day.`,
|
|
187
188
|
parameters: { limit: {
|
|
188
189
|
type: "number",
|
|
189
|
-
description:
|
|
190
|
+
description: `Max entries to return (integer 1..400; default 40, earliest first)`
|
|
190
191
|
} },
|
|
191
192
|
output: textOutput,
|
|
192
193
|
async execute(raw) {
|
|
193
|
-
const limit = readLimit((raw ?? {}).limit, 40,
|
|
194
|
+
const limit = readLimit((raw ?? {}).limit, 40, 400);
|
|
194
195
|
const entries = await service.listCalendar(limit);
|
|
195
196
|
if (entries.length === 0) return "econ_calendar: the upstream calendar is empty for the current week.";
|
|
196
197
|
return [`econ_calendar — ${entries.length} entr(ies) for the current week (Beijing time), source: ${SOURCE}:`, ...entries.map(renderCalendarLine)].join("\n");
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dshtrading/connector-jin10",
|
|
3
3
|
"description": "金十数据 MCP 连接器:把 mcp.jin10.com 的行情/快讯/资讯/财经日历封装成本仓的连接器(市场无关,host 面工具行)",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "./lib/index.d.ts",
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
],
|
|
26
26
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@dshtrading/api": "^0.6.
|
|
28
|
+
"@dshtrading/api": "^0.6.2"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"@deepseek-ai/cordis": ">=4.0.0",
|
|
32
|
-
"@deepseek-ai/dsh-tools": ">=0.2.
|
|
32
|
+
"@deepseek-ai/dsh-tools": ">=0.2.1-rc.2",
|
|
33
33
|
"@deepseek-ai/schemastery": ">=3.18.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|