@okx_ai/okx-trade-mcp 1.3.8-beta.3 → 1.3.8-beta.4
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/dist/index.js +232 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2374,7 +2374,7 @@ function registerIndicatorTools() {
|
|
|
2374
2374
|
params: {
|
|
2375
2375
|
type: "array",
|
|
2376
2376
|
items: { type: "number" },
|
|
2377
|
-
description: "Indicator-specific parameters as a number array. Examples: MA/EMA [14] (period), MACD [12,26,9] (fast,slow,signal), BB [20,2] (period,stdDev), RSI [14] (period).
|
|
2377
|
+
description: "Indicator-specific parameters as a number array. Examples: MA/EMA [14] (period), MACD [12,26,9] (fast,slow,signal), BB [20,2] (period,stdDev), RSI [14] (period). Omit to use server defaults."
|
|
2378
2378
|
},
|
|
2379
2379
|
returnList: {
|
|
2380
2380
|
type: "boolean",
|
|
@@ -2480,6 +2480,203 @@ var MODULES = [
|
|
|
2480
2480
|
"skills"
|
|
2481
2481
|
];
|
|
2482
2482
|
var DEFAULT_MODULES = ["spot", "swap", "option", "account", ...BOT_DEFAULT_SUB_MODULES, "skills"];
|
|
2483
|
+
var AGGREGATE_ENDPOINT = "/api/v5/aigc/forward/balance-aggregate";
|
|
2484
|
+
var TRADING_ENDPOINT = "/api/v5/account/balance";
|
|
2485
|
+
var FUNDING_ENDPOINT = "/api/v5/asset/balances";
|
|
2486
|
+
var VALUATION_ENDPOINT = "/api/v5/asset/asset-valuation";
|
|
2487
|
+
function parseParams(rawArgs) {
|
|
2488
|
+
const args = asRecord(rawArgs);
|
|
2489
|
+
const accounts = readString(args, "accounts") ?? "trading,funding";
|
|
2490
|
+
return {
|
|
2491
|
+
ccy: readString(args, "ccy"),
|
|
2492
|
+
accounts,
|
|
2493
|
+
requestedAccounts: accounts.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean),
|
|
2494
|
+
showValuation: readBoolean(args, "showValuation") ?? true,
|
|
2495
|
+
valuationCcy: readString(args, "valuationCcy") ?? "USDT",
|
|
2496
|
+
preferParallel: readBoolean(args, "preferParallel") ?? false
|
|
2497
|
+
};
|
|
2498
|
+
}
|
|
2499
|
+
function normalizeSubError(error) {
|
|
2500
|
+
if (!error || typeof error !== "object") {
|
|
2501
|
+
return void 0;
|
|
2502
|
+
}
|
|
2503
|
+
const e = error;
|
|
2504
|
+
return {
|
|
2505
|
+
code: e["code"] === void 0 || e["code"] === null ? "UNKNOWN" : String(e["code"]),
|
|
2506
|
+
msg: typeof e["msg"] === "string" ? e["msg"] : String(e["msg"] ?? "")
|
|
2507
|
+
};
|
|
2508
|
+
}
|
|
2509
|
+
function toIsoTimestamp(value, fallbackMs) {
|
|
2510
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2511
|
+
return new Date(value).toISOString();
|
|
2512
|
+
}
|
|
2513
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
2514
|
+
return value;
|
|
2515
|
+
}
|
|
2516
|
+
return new Date(fallbackMs).toISOString();
|
|
2517
|
+
}
|
|
2518
|
+
function normalizeAggregate(agg, params, startTime) {
|
|
2519
|
+
const result = {};
|
|
2520
|
+
const trading = agg["trading"];
|
|
2521
|
+
if (trading) {
|
|
2522
|
+
result.trading = compactObject({
|
|
2523
|
+
available: trading["available"] ?? false,
|
|
2524
|
+
totalEq: trading["totalEq"],
|
|
2525
|
+
adjEq: trading["adjEq"],
|
|
2526
|
+
details: Array.isArray(trading["details"]) ? trading["details"] : [],
|
|
2527
|
+
error: normalizeSubError(trading["error"])
|
|
2528
|
+
});
|
|
2529
|
+
}
|
|
2530
|
+
const funding = agg["funding"];
|
|
2531
|
+
if (funding) {
|
|
2532
|
+
result.funding = compactObject({
|
|
2533
|
+
available: funding["available"] ?? false,
|
|
2534
|
+
details: Array.isArray(funding["details"]) ? funding["details"] : [],
|
|
2535
|
+
error: normalizeSubError(funding["error"])
|
|
2536
|
+
});
|
|
2537
|
+
}
|
|
2538
|
+
const valuation = agg["valuation"];
|
|
2539
|
+
if (valuation) {
|
|
2540
|
+
result.valuation = compactObject({
|
|
2541
|
+
available: valuation["available"] ?? false,
|
|
2542
|
+
valuationCcy: valuation["valuationCcy"] ?? params.valuationCcy,
|
|
2543
|
+
totalBal: valuation["totalBal"] ?? "0",
|
|
2544
|
+
details: Array.isArray(valuation["details"]) ? valuation["details"] : [],
|
|
2545
|
+
error: normalizeSubError(valuation["error"])
|
|
2546
|
+
});
|
|
2547
|
+
}
|
|
2548
|
+
const meta = agg["meta"] ?? {};
|
|
2549
|
+
result.meta = compactObject({
|
|
2550
|
+
requestedAt: toIsoTimestamp(meta["requestedAt"], startTime),
|
|
2551
|
+
elapsedMs: typeof meta["elapsedMs"] === "number" ? meta["elapsedMs"] : Date.now() - startTime,
|
|
2552
|
+
partialFailure: Boolean(meta["partialFailure"]),
|
|
2553
|
+
site: typeof meta["site"] === "string" ? meta["site"] : void 0,
|
|
2554
|
+
source: "aggregate"
|
|
2555
|
+
});
|
|
2556
|
+
return result;
|
|
2557
|
+
}
|
|
2558
|
+
async function queryAggregate(context, params, startTime) {
|
|
2559
|
+
const resp = await context.client.privateGet(
|
|
2560
|
+
AGGREGATE_ENDPOINT,
|
|
2561
|
+
compactObject({
|
|
2562
|
+
ccy: params.ccy,
|
|
2563
|
+
accounts: params.accounts,
|
|
2564
|
+
showValuation: params.showValuation,
|
|
2565
|
+
valuationCcy: params.valuationCcy
|
|
2566
|
+
}),
|
|
2567
|
+
privateRateLimit("account_get_balance_all", 5)
|
|
2568
|
+
);
|
|
2569
|
+
const data = resp.data;
|
|
2570
|
+
const agg = Array.isArray(data) ? data[0] : void 0;
|
|
2571
|
+
if (!agg || agg["trading"] === void 0 && agg["funding"] === void 0) {
|
|
2572
|
+
throw new OkxApiError("Aggregate endpoint returned no usable data", {
|
|
2573
|
+
code: "AGG_EMPTY",
|
|
2574
|
+
endpoint: `GET ${AGGREGATE_ENDPOINT}`
|
|
2575
|
+
});
|
|
2576
|
+
}
|
|
2577
|
+
return normalizeAggregate(agg, params, startTime);
|
|
2578
|
+
}
|
|
2579
|
+
var REQUESTED_KEYS = /* @__PURE__ */ new Set(["trading", "funding"]);
|
|
2580
|
+
function buildBalanceTasks(context, params) {
|
|
2581
|
+
const { ccy, requestedAccounts, showValuation, valuationCcy } = params;
|
|
2582
|
+
const tasks = [];
|
|
2583
|
+
if (requestedAccounts.includes("trading")) {
|
|
2584
|
+
tasks.push({
|
|
2585
|
+
key: "trading",
|
|
2586
|
+
run: () => context.client.privateGet(TRADING_ENDPOINT, compactObject({ ccy }), privateRateLimit("account_get_balance", 10)).then((resp) => resp.data)
|
|
2587
|
+
});
|
|
2588
|
+
}
|
|
2589
|
+
if (requestedAccounts.includes("funding")) {
|
|
2590
|
+
tasks.push({
|
|
2591
|
+
key: "funding",
|
|
2592
|
+
run: () => context.client.privateGet(FUNDING_ENDPOINT, compactObject({ ccy }), privateRateLimit("account_get_asset_balance", 6)).then((resp) => resp.data)
|
|
2593
|
+
});
|
|
2594
|
+
}
|
|
2595
|
+
if (showValuation) {
|
|
2596
|
+
tasks.push({
|
|
2597
|
+
key: "valuation",
|
|
2598
|
+
run: () => context.client.privateGet(VALUATION_ENDPOINT, { ccy: valuationCcy }, privateRateLimit("account_get_asset_valuation", 1)).then((resp) => resp.data)
|
|
2599
|
+
});
|
|
2600
|
+
}
|
|
2601
|
+
return tasks;
|
|
2602
|
+
}
|
|
2603
|
+
async function settleBalanceTasks(tasks) {
|
|
2604
|
+
return Promise.all(
|
|
2605
|
+
tasks.map(async (task) => {
|
|
2606
|
+
try {
|
|
2607
|
+
return { key: task.key, data: await task.run() };
|
|
2608
|
+
} catch (error) {
|
|
2609
|
+
return { key: task.key, error };
|
|
2610
|
+
}
|
|
2611
|
+
})
|
|
2612
|
+
);
|
|
2613
|
+
}
|
|
2614
|
+
function buildSuccessSection(key, data, valuationCcy) {
|
|
2615
|
+
const rows = Array.isArray(data) ? data : [];
|
|
2616
|
+
const first = rows[0];
|
|
2617
|
+
if (key === "funding") {
|
|
2618
|
+
return { available: true, details: rows };
|
|
2619
|
+
}
|
|
2620
|
+
if (key === "valuation") {
|
|
2621
|
+
return { available: true, valuationCcy, totalBal: first?.["totalBal"] ?? "0", details: rows };
|
|
2622
|
+
}
|
|
2623
|
+
return {
|
|
2624
|
+
available: true,
|
|
2625
|
+
totalEq: first?.["totalEq"] ?? "0",
|
|
2626
|
+
adjEq: first?.["adjEq"] ?? "0",
|
|
2627
|
+
details: first && Array.isArray(first["details"]) ? first["details"] : []
|
|
2628
|
+
};
|
|
2629
|
+
}
|
|
2630
|
+
function buildErrorSection(error) {
|
|
2631
|
+
return {
|
|
2632
|
+
available: false,
|
|
2633
|
+
error: {
|
|
2634
|
+
code: error instanceof OkxApiError ? error.code ?? "UNKNOWN" : "UNKNOWN",
|
|
2635
|
+
msg: error.message
|
|
2636
|
+
}
|
|
2637
|
+
};
|
|
2638
|
+
}
|
|
2639
|
+
async function queryParallel(context, params, startTime) {
|
|
2640
|
+
const tasks = buildBalanceTasks(context, params);
|
|
2641
|
+
const outcomes = await settleBalanceTasks(tasks);
|
|
2642
|
+
const authFailure = outcomes.find((o) => o.error instanceof AuthenticationError);
|
|
2643
|
+
if (authFailure?.error) {
|
|
2644
|
+
throw authFailure.error;
|
|
2645
|
+
}
|
|
2646
|
+
const result = {};
|
|
2647
|
+
for (const outcome of outcomes) {
|
|
2648
|
+
result[outcome.key] = outcome.error ? buildErrorSection(outcome.error) : buildSuccessSection(outcome.key, outcome.data, params.valuationCcy);
|
|
2649
|
+
}
|
|
2650
|
+
const requestedCount = tasks.filter((t) => REQUESTED_KEYS.has(t.key)).length;
|
|
2651
|
+
const requestedFailures = outcomes.filter((o) => o.error && REQUESTED_KEYS.has(o.key)).length;
|
|
2652
|
+
if (requestedCount > 0 && requestedFailures >= requestedCount) {
|
|
2653
|
+
throw new OkxApiError("Both balance queries failed", { code: "-30001" });
|
|
2654
|
+
}
|
|
2655
|
+
const site = typeof context.config?.site === "string" ? context.config.site : void 0;
|
|
2656
|
+
result.meta = compactObject({
|
|
2657
|
+
requestedAt: new Date(startTime).toISOString(),
|
|
2658
|
+
elapsedMs: Date.now() - startTime,
|
|
2659
|
+
partialFailure: requestedFailures > 0,
|
|
2660
|
+
site,
|
|
2661
|
+
source: "fallback"
|
|
2662
|
+
});
|
|
2663
|
+
return result;
|
|
2664
|
+
}
|
|
2665
|
+
async function buildBalanceAll(rawArgs, context) {
|
|
2666
|
+
const params = parseParams(rawArgs);
|
|
2667
|
+
const startTime = Date.now();
|
|
2668
|
+
if (params.preferParallel) {
|
|
2669
|
+
return queryParallel(context, params, startTime);
|
|
2670
|
+
}
|
|
2671
|
+
try {
|
|
2672
|
+
return await queryAggregate(context, params, startTime);
|
|
2673
|
+
} catch (error) {
|
|
2674
|
+
if (error instanceof AuthenticationError) {
|
|
2675
|
+
throw error;
|
|
2676
|
+
}
|
|
2677
|
+
return queryParallel(context, params, startTime);
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2483
2680
|
function registerAccountTools() {
|
|
2484
2681
|
return [
|
|
2485
2682
|
{
|
|
@@ -3059,6 +3256,39 @@ function registerAccountTools() {
|
|
|
3059
3256
|
);
|
|
3060
3257
|
return normalizeResponse(response);
|
|
3061
3258
|
}
|
|
3259
|
+
},
|
|
3260
|
+
{
|
|
3261
|
+
name: "account_get_balance_all",
|
|
3262
|
+
title: "Get Aggregate Balance Snapshot",
|
|
3263
|
+
module: "account",
|
|
3264
|
+
description: "One-shot snapshot of all OKX assets: trading-account equity + funding-account balances + optional cross-account valuation. Use when the user asks for total assets / net worth / \u603B\u8D44\u4EA7 / all balances. Prefer this over calling account_get_balance + account_get_asset_balance separately. Returns {trading, funding, valuation, meta} with per-section error so partial failures don't block the rest.",
|
|
3265
|
+
isWrite: false,
|
|
3266
|
+
inputSchema: {
|
|
3267
|
+
type: "object",
|
|
3268
|
+
properties: {
|
|
3269
|
+
ccy: {
|
|
3270
|
+
type: "string",
|
|
3271
|
+
description: "Filter by currency, comma-separated (e.g. BTC,ETH). Omit for all. Applied to trading + funding queries only."
|
|
3272
|
+
},
|
|
3273
|
+
accounts: {
|
|
3274
|
+
type: "string",
|
|
3275
|
+
description: "Comma-separated accounts to query: 'trading','funding'. Default 'trading,funding'."
|
|
3276
|
+
},
|
|
3277
|
+
showValuation: {
|
|
3278
|
+
type: "boolean",
|
|
3279
|
+
description: "Include cross-account asset valuation. Default true."
|
|
3280
|
+
},
|
|
3281
|
+
valuationCcy: {
|
|
3282
|
+
type: "string",
|
|
3283
|
+
description: "Currency for valuation (e.g. USDT, BTC). Default USDT. Only effective when showValuation=true."
|
|
3284
|
+
},
|
|
3285
|
+
preferParallel: {
|
|
3286
|
+
type: "boolean",
|
|
3287
|
+
description: "Skip the server-side aggregate endpoint and query trading/funding/valuation directly in parallel. Default false. Use when you need the per-account valuation breakdown or a non-USD valuation currency."
|
|
3288
|
+
}
|
|
3289
|
+
}
|
|
3290
|
+
},
|
|
3291
|
+
handler: (rawArgs, context) => buildBalanceAll(rawArgs, context)
|
|
3062
3292
|
}
|
|
3063
3293
|
];
|
|
3064
3294
|
}
|
|
@@ -12397,7 +12627,7 @@ var _require = createRequire(import.meta.url);
|
|
|
12397
12627
|
var pkg = _require("../package.json");
|
|
12398
12628
|
var SERVER_NAME = "okx-trade-mcp";
|
|
12399
12629
|
var SERVER_VERSION = pkg.version;
|
|
12400
|
-
var GIT_HASH = true ? "
|
|
12630
|
+
var GIT_HASH = true ? "9beb3ee8" : "dev";
|
|
12401
12631
|
|
|
12402
12632
|
// src/server.ts
|
|
12403
12633
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|