@okx_ai/okx-trade-mcp 1.2.8 → 1.2.9-beta.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/dist/index.js CHANGED
@@ -2049,6 +2049,59 @@ function registerAccountTools() {
2049
2049
  }
2050
2050
  ];
2051
2051
  }
2052
+ async function resolveQuoteCcySz(instId, sz, tgtCcy, instType, client) {
2053
+ if (tgtCcy !== "quote_ccy") {
2054
+ return { sz, tgtCcy, conversionNote: void 0 };
2055
+ }
2056
+ const [instrumentsRes, tickerRes] = await Promise.all([
2057
+ client.publicGet("/api/v5/public/instruments", {
2058
+ instType,
2059
+ instId
2060
+ }),
2061
+ client.publicGet("/api/v5/market/ticker", { instId })
2062
+ ]);
2063
+ const instruments = Array.isArray(instrumentsRes.data) ? instrumentsRes.data : [];
2064
+ if (instruments.length === 0) {
2065
+ throw new Error(
2066
+ `Failed to fetch instrument info for ${instId}: empty instrument list. Cannot determine ctVal for quote_ccy conversion.`
2067
+ );
2068
+ }
2069
+ const ctValStr = String(instruments[0].ctVal ?? "");
2070
+ const ctVal = parseFloat(ctValStr);
2071
+ if (!isFinite(ctVal) || ctVal <= 0) {
2072
+ throw new Error(
2073
+ `Invalid ctVal "${ctValStr}" for ${instId}. ctVal must be a positive number for quote_ccy conversion.`
2074
+ );
2075
+ }
2076
+ const tickers = Array.isArray(tickerRes.data) ? tickerRes.data : [];
2077
+ if (tickers.length === 0) {
2078
+ throw new Error(
2079
+ `Failed to fetch ticker price for ${instId}: empty ticker response. Cannot determine last price for quote_ccy conversion.`
2080
+ );
2081
+ }
2082
+ const lastStr = String(tickers[0].last ?? "");
2083
+ const lastPx = parseFloat(lastStr);
2084
+ if (!isFinite(lastPx) || lastPx <= 0) {
2085
+ throw new Error(
2086
+ `Invalid last price "${lastStr}" for ${instId}. Last price must be a positive number for quote_ccy conversion.`
2087
+ );
2088
+ }
2089
+ const usdtAmount = parseFloat(sz);
2090
+ const contractValue = ctVal * lastPx;
2091
+ const contracts = Math.floor(usdtAmount / contractValue);
2092
+ if (contracts <= 0) {
2093
+ const minUsdt = contractValue.toFixed(2);
2094
+ throw new Error(
2095
+ `sz=${sz} USDT is too small to buy even 1 contract of ${instId}. Minimum amount required is at least ${minUsdt} USDT (ctVal=${ctValStr}, lastPx=${lastStr}, 1 contract = ${minUsdt} USDT).`
2096
+ );
2097
+ }
2098
+ const conversionNote = `Converting ${sz} USDT \u2192 ${contracts} contracts (ctVal=${ctValStr}, lastPx=${lastStr}, formula: floor(${sz} / (${ctValStr} \xD7 ${lastStr})) = ${contracts})`;
2099
+ return {
2100
+ sz: String(contracts),
2101
+ tgtCcy: void 0,
2102
+ conversionNote
2103
+ };
2104
+ }
2052
2105
  function registerAlgoTradeTools() {
2053
2106
  return [
2054
2107
  {
@@ -2144,6 +2197,13 @@ function registerAlgoTradeTools() {
2144
2197
  handler: async (rawArgs, context) => {
2145
2198
  const args = asRecord(rawArgs);
2146
2199
  const reduceOnly = args.reduceOnly;
2200
+ const resolved = await resolveQuoteCcySz(
2201
+ requireString(args, "instId"),
2202
+ requireString(args, "sz"),
2203
+ readString(args, "tgtCcy"),
2204
+ "SWAP",
2205
+ context.client
2206
+ );
2147
2207
  const response = await context.client.privatePost(
2148
2208
  "/api/v5/trade/order-algo",
2149
2209
  compactObject({
@@ -2152,8 +2212,8 @@ function registerAlgoTradeTools() {
2152
2212
  side: requireString(args, "side"),
2153
2213
  posSide: readString(args, "posSide"),
2154
2214
  ordType: requireString(args, "ordType"),
2155
- sz: requireString(args, "sz"),
2156
- tgtCcy: readString(args, "tgtCcy"),
2215
+ sz: resolved.sz,
2216
+ tgtCcy: resolved.tgtCcy,
2157
2217
  tpTriggerPx: readString(args, "tpTriggerPx"),
2158
2218
  tpOrdPx: readString(args, "tpOrdPx"),
2159
2219
  tpTriggerPxType: readString(args, "tpTriggerPxType"),
@@ -2169,7 +2229,11 @@ function registerAlgoTradeTools() {
2169
2229
  }),
2170
2230
  privateRateLimit("swap_place_algo_order", 20)
2171
2231
  );
2172
- return normalizeResponse(response);
2232
+ const result = normalizeResponse(response);
2233
+ if (resolved.conversionNote) {
2234
+ result._conversion = resolved.conversionNote;
2235
+ }
2236
+ return result;
2173
2237
  }
2174
2238
  },
2175
2239
  {
@@ -2477,6 +2541,13 @@ function registerFuturesAlgoTools() {
2477
2541
  handler: async (rawArgs, context) => {
2478
2542
  const args = asRecord(rawArgs);
2479
2543
  const reduceOnly = args.reduceOnly;
2544
+ const resolved = await resolveQuoteCcySz(
2545
+ requireString(args, "instId"),
2546
+ requireString(args, "sz"),
2547
+ readString(args, "tgtCcy"),
2548
+ "FUTURES",
2549
+ context.client
2550
+ );
2480
2551
  const response = await context.client.privatePost(
2481
2552
  "/api/v5/trade/order-algo",
2482
2553
  compactObject({
@@ -2485,8 +2556,8 @@ function registerFuturesAlgoTools() {
2485
2556
  side: requireString(args, "side"),
2486
2557
  posSide: readString(args, "posSide"),
2487
2558
  ordType: requireString(args, "ordType"),
2488
- sz: requireString(args, "sz"),
2489
- tgtCcy: readString(args, "tgtCcy"),
2559
+ sz: resolved.sz,
2560
+ tgtCcy: resolved.tgtCcy,
2490
2561
  tpTriggerPx: readString(args, "tpTriggerPx"),
2491
2562
  tpOrdPx: readString(args, "tpOrdPx"),
2492
2563
  tpTriggerPxType: readString(args, "tpTriggerPxType"),
@@ -2502,7 +2573,11 @@ function registerFuturesAlgoTools() {
2502
2573
  }),
2503
2574
  privateRateLimit("futures_place_algo_order", 20)
2504
2575
  );
2505
- return normalizeResponse(response);
2576
+ const result = normalizeResponse(response);
2577
+ if (resolved.conversionNote) {
2578
+ result._conversion = resolved.conversionNote;
2579
+ }
2580
+ return result;
2506
2581
  }
2507
2582
  },
2508
2583
  {
@@ -2911,7 +2986,7 @@ function registerSkillsTools() {
2911
2986
  {
2912
2987
  name: "skills_download",
2913
2988
  module: "skills",
2914
- description: "Download a skill zip file from OKX Skills Marketplace to a local directory. Always call skills_search first to confirm the skill name exists. Downloads the latest approved version. NOTE: This only downloads the zip \u2014 it does NOT install to agents. For full installation use CLI: okx skill add <name>. Use when the user wants to inspect or manually install a skill package.",
2989
+ description: "Download a skill zip file from OKX Skills Marketplace to a local directory. Always call skills_search first to confirm the skill name exists. Downloads the latest approved version. NOTE: Downloads third-party developer content as a zip \u2014 does NOT install to agents. For full installation use CLI: okx skill add <name>. Use when the user wants to inspect or manually install a skill package.",
2915
2990
  inputSchema: {
2916
2991
  type: "object",
2917
2992
  properties: {
@@ -4432,6 +4507,13 @@ function buildContractTradeTools(cfg) {
4432
4507
  const args = asRecord(rawArgs);
4433
4508
  const reduceOnly = args.reduceOnly;
4434
4509
  const attachAlgoOrds = buildAttachAlgoOrds(args);
4510
+ const resolved = await resolveQuoteCcySz(
4511
+ requireString(args, "instId"),
4512
+ requireString(args, "sz"),
4513
+ readString(args, "tgtCcy"),
4514
+ defaultType,
4515
+ context.client
4516
+ );
4435
4517
  const response = await context.client.privatePost(
4436
4518
  "/api/v5/trade/order",
4437
4519
  compactObject({
@@ -4440,8 +4522,8 @@ function buildContractTradeTools(cfg) {
4440
4522
  side: requireString(args, "side"),
4441
4523
  posSide: readString(args, "posSide"),
4442
4524
  ordType: requireString(args, "ordType"),
4443
- sz: requireString(args, "sz"),
4444
- tgtCcy: readString(args, "tgtCcy"),
4525
+ sz: resolved.sz,
4526
+ tgtCcy: resolved.tgtCcy,
4445
4527
  px: readString(args, "px"),
4446
4528
  reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
4447
4529
  clOrdId: readString(args, "clOrdId"),
@@ -4450,7 +4532,11 @@ function buildContractTradeTools(cfg) {
4450
4532
  }),
4451
4533
  privateRateLimit(n("place_order"), 60)
4452
4534
  );
4453
- return normalizeResponse(response);
4535
+ const result = normalizeResponse(response);
4536
+ if (resolved.conversionNote) {
4537
+ result._conversion = resolved.conversionNote;
4538
+ }
4539
+ return result;
4454
4540
  }
4455
4541
  },
4456
4542
  // ── cancel_order ─────────────────────────────────────────────────────────
@@ -5525,7 +5611,7 @@ function registerOptionAlgoTools() {
5525
5611
  tgtCcy: {
5526
5612
  type: "string",
5527
5613
  enum: ["base_ccy", "quote_ccy"],
5528
- description: "Size unit. base_ccy(default): sz in contracts, quote_ccy: sz in USDT (may not be supported for options)"
5614
+ description: "Size unit. base_ccy(default): sz in contracts, quote_ccy: sz in USDT (auto-converted to contracts)"
5529
5615
  },
5530
5616
  reduceOnly: {
5531
5617
  type: "boolean",
@@ -5541,6 +5627,13 @@ function registerOptionAlgoTools() {
5541
5627
  handler: async (rawArgs, context) => {
5542
5628
  const args = asRecord(rawArgs);
5543
5629
  const reduceOnly = readBoolean(args, "reduceOnly");
5630
+ const resolved = await resolveQuoteCcySz(
5631
+ requireString(args, "instId"),
5632
+ requireString(args, "sz"),
5633
+ readString(args, "tgtCcy"),
5634
+ "OPTION",
5635
+ context.client
5636
+ );
5544
5637
  const response = await context.client.privatePost(
5545
5638
  "/api/v5/trade/order-algo",
5546
5639
  compactObject({
@@ -5548,8 +5641,8 @@ function registerOptionAlgoTools() {
5548
5641
  tdMode: requireString(args, "tdMode"),
5549
5642
  side: requireString(args, "side"),
5550
5643
  ordType: requireString(args, "ordType"),
5551
- sz: requireString(args, "sz"),
5552
- tgtCcy: readString(args, "tgtCcy"),
5644
+ sz: resolved.sz,
5645
+ tgtCcy: resolved.tgtCcy,
5553
5646
  tpTriggerPx: readString(args, "tpTriggerPx"),
5554
5647
  tpOrdPx: readString(args, "tpOrdPx"),
5555
5648
  tpTriggerPxType: readString(args, "tpTriggerPxType"),
@@ -7384,7 +7477,7 @@ var _require = createRequire(import.meta.url);
7384
7477
  var pkg = _require("../package.json");
7385
7478
  var SERVER_NAME = "okx-trade-mcp";
7386
7479
  var SERVER_VERSION = pkg.version;
7387
- var GIT_HASH = true ? "0b9b3b7" : "dev";
7480
+ var GIT_HASH = true ? "5f833a2" : "dev";
7388
7481
 
7389
7482
  // src/server.ts
7390
7483
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";