@okx_ai/okx-trade-mcp 1.2.5 → 1.2.6

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
@@ -882,9 +882,9 @@ var OKX_CODE_BEHAVIORS = {
882
882
  "50100": { retry: false, suggestion: "API key lacks required permissions. Update API key permissions." },
883
883
  "50110": { retry: false, suggestion: "API key expired. Generate a new API key." },
884
884
  // Insufficient funds / margin → do not retry
885
- "51008": { retry: false, suggestion: "Insufficient balance. Top up account before retrying." },
886
- "51119": { retry: false, suggestion: "Insufficient margin. Add margin before retrying." },
887
- "51127": { retry: false, suggestion: "Insufficient available margin. Reduce position or add margin." },
885
+ "51008": { retry: false, suggestion: "Insufficient balance in trading account. Check funding account via account_get_asset_balance \u2014 funds may be there. Use account_transfer (from=18, to=6) to move funds to trading account, then retry." },
886
+ "51119": { retry: false, suggestion: "Insufficient margin. Add margin or check funding account (account_get_asset_balance). Transfer via account_transfer (from=18, to=6) if needed." },
887
+ "51127": { retry: false, suggestion: "Insufficient available margin. Reduce position, add margin, or transfer from funding account (account_transfer from=18 to=6)." },
888
888
  // Instrument unavailable → do not retry
889
889
  "51021": { retry: false, suggestion: "Instrument does not exist. Check instId." },
890
890
  "51022": { retry: false, suggestion: "Instrument not available for trading." },
@@ -967,6 +967,15 @@ var OkxRestClient = class {
967
967
  rateLimit
968
968
  });
969
969
  }
970
+ async publicPost(path4, body, rateLimit) {
971
+ return this.request({
972
+ method: "POST",
973
+ path: path4,
974
+ auth: "public",
975
+ body,
976
+ rateLimit
977
+ });
978
+ }
970
979
  async privatePost(path4, body, rateLimit) {
971
980
  return this.request({
972
981
  method: "POST",
@@ -1121,46 +1130,6 @@ var OkxRestClient = class {
1121
1130
  return this.processResponse(rawText, response, elapsed, traceId, reqConfig, requestPath);
1122
1131
  }
1123
1132
  };
1124
- var DEFAULT_SOURCE_TAG = "MCP";
1125
- var OKX_SITES = {
1126
- global: {
1127
- label: "Global",
1128
- apiBaseUrl: "https://www.okx.com",
1129
- webUrl: "https://www.okx.com"
1130
- },
1131
- eea: {
1132
- label: "EEA",
1133
- apiBaseUrl: "https://eea.okx.com",
1134
- webUrl: "https://my.okx.com"
1135
- },
1136
- us: {
1137
- label: "US",
1138
- apiBaseUrl: "https://app.okx.com",
1139
- webUrl: "https://app.okx.com"
1140
- }
1141
- };
1142
- var SITE_IDS = Object.keys(OKX_SITES);
1143
- var BOT_SUB_MODULE_IDS = [
1144
- "bot.grid",
1145
- "bot.dca"
1146
- ];
1147
- var BOT_DEFAULT_SUB_MODULES = ["bot.grid"];
1148
- var EARN_SUB_MODULE_IDS = [
1149
- "earn.savings",
1150
- "earn.onchain",
1151
- "earn.dcd"
1152
- ];
1153
- var MODULES = [
1154
- "market",
1155
- "spot",
1156
- "swap",
1157
- "futures",
1158
- "option",
1159
- "account",
1160
- ...EARN_SUB_MODULE_IDS,
1161
- ...BOT_SUB_MODULE_IDS
1162
- ];
1163
- var DEFAULT_MODULES = ["spot", "swap", "option", "account", ...BOT_DEFAULT_SUB_MODULES];
1164
1133
  function asRecord(value) {
1165
1134
  if (!value || typeof value !== "object" || Array.isArray(value)) {
1166
1135
  return {};
@@ -1285,6 +1254,152 @@ function assertNotDemo(config, endpoint) {
1285
1254
  );
1286
1255
  }
1287
1256
  }
1257
+ var INDICATOR_BARS = [
1258
+ "3m",
1259
+ "5m",
1260
+ "15m",
1261
+ "1H",
1262
+ "4H",
1263
+ "12Hutc",
1264
+ "1Dutc",
1265
+ "3Dutc",
1266
+ "1Wutc"
1267
+ ];
1268
+ var INDICATOR_CODE_OVERRIDES = {
1269
+ "rainbow": "BTCRAINBOW",
1270
+ "range-filter": "RANGEFILTER",
1271
+ "stoch-rsi": "STOCHRSI",
1272
+ "pi-cycle-top": "PI_CYCLE_TOP",
1273
+ "pi-cycle-bottom": "PI_CYCLE_BOTTOM",
1274
+ // boll is an alias for bb; server supports BB not BOLL
1275
+ "boll": "BB"
1276
+ };
1277
+ function resolveIndicatorCode(name) {
1278
+ const lower = name.toLowerCase();
1279
+ return INDICATOR_CODE_OVERRIDES[lower] ?? name.toUpperCase().replace(/-/g, "_");
1280
+ }
1281
+ function readNumberArray(args, key) {
1282
+ const value = args[key];
1283
+ if (value === void 0 || value === null) return void 0;
1284
+ if (!Array.isArray(value)) return void 0;
1285
+ return value.map((item) => Number(item));
1286
+ }
1287
+ function registerIndicatorTools() {
1288
+ return [
1289
+ {
1290
+ name: "market_get_indicator",
1291
+ module: "market",
1292
+ description: "Get technical indicator values for an instrument (MA, EMA, RSI, MACD, BB, KDJ, SUPERTREND, AHR999, BTCRAINBOW, and more). No credentials required.",
1293
+ isWrite: false,
1294
+ inputSchema: {
1295
+ type: "object",
1296
+ properties: {
1297
+ instId: {
1298
+ type: "string",
1299
+ description: "Instrument ID, e.g. BTC-USDT"
1300
+ },
1301
+ indicator: {
1302
+ type: "string",
1303
+ description: "Indicator name (case-insensitive). Examples: ma, ema, rsi, macd, bb, kdj, supertrend, ahr999, rainbow, pi-cycle-top, pi-cycle-bottom, mayer, envelope, halftrend, alphatrend, pmax, waddah, tdi, qqe, range-filter"
1304
+ },
1305
+ bar: {
1306
+ type: "string",
1307
+ enum: [...INDICATOR_BARS],
1308
+ description: "Timeframe. Default: 1H"
1309
+ },
1310
+ params: {
1311
+ type: "array",
1312
+ items: { type: "number" },
1313
+ description: "Indicator parameters, e.g. [5, 20] for MA with periods 5 and 20"
1314
+ },
1315
+ returnList: {
1316
+ type: "boolean",
1317
+ description: "Return a historical list instead of the latest value only. Default: false"
1318
+ },
1319
+ limit: {
1320
+ type: "integer",
1321
+ minimum: 1,
1322
+ maximum: 100,
1323
+ description: "Number of historical records to return (only used when returnList=true). Default: 10"
1324
+ },
1325
+ backtestTime: {
1326
+ type: "integer",
1327
+ description: "Backtest timestamp in milliseconds. Omit for live (real-time) mode"
1328
+ }
1329
+ },
1330
+ required: ["instId", "indicator"]
1331
+ },
1332
+ handler: async (rawArgs, context) => {
1333
+ const args = asRecord(rawArgs);
1334
+ const instId = requireString(args, "instId");
1335
+ const indicator = requireString(args, "indicator");
1336
+ const bar = readString(args, "bar") ?? "1H";
1337
+ const params = readNumberArray(args, "params");
1338
+ const returnList = readBoolean(args, "returnList") ?? false;
1339
+ const limit = readNumber(args, "limit") ?? 10;
1340
+ const backtestTime = readNumber(args, "backtestTime");
1341
+ const apiCode = resolveIndicatorCode(indicator);
1342
+ const indicatorConfig = compactObject({
1343
+ paramList: params && params.length > 0 ? params : void 0,
1344
+ returnList,
1345
+ limit: returnList ? limit : void 0
1346
+ });
1347
+ const body = compactObject({
1348
+ instId,
1349
+ timeframes: [bar],
1350
+ indicators: { [apiCode]: indicatorConfig },
1351
+ backtestTime
1352
+ });
1353
+ const response = await context.client.publicPost(
1354
+ "/api/v5/aigc/mcp/indicators",
1355
+ body,
1356
+ publicRateLimit("market_get_indicator", 5)
1357
+ );
1358
+ return normalizeResponse(response);
1359
+ }
1360
+ }
1361
+ ];
1362
+ }
1363
+ var DEFAULT_SOURCE_TAG = "MCP";
1364
+ var OKX_SITES = {
1365
+ global: {
1366
+ label: "Global",
1367
+ apiBaseUrl: "https://www.okx.com",
1368
+ webUrl: "https://www.okx.com"
1369
+ },
1370
+ eea: {
1371
+ label: "EEA",
1372
+ apiBaseUrl: "https://eea.okx.com",
1373
+ webUrl: "https://my.okx.com"
1374
+ },
1375
+ us: {
1376
+ label: "US",
1377
+ apiBaseUrl: "https://app.okx.com",
1378
+ webUrl: "https://app.okx.com"
1379
+ }
1380
+ };
1381
+ var SITE_IDS = Object.keys(OKX_SITES);
1382
+ var BOT_SUB_MODULE_IDS = [
1383
+ "bot.grid",
1384
+ "bot.dca"
1385
+ ];
1386
+ var BOT_DEFAULT_SUB_MODULES = ["bot.grid"];
1387
+ var EARN_SUB_MODULE_IDS = [
1388
+ "earn.savings",
1389
+ "earn.onchain",
1390
+ "earn.dcd"
1391
+ ];
1392
+ var MODULES = [
1393
+ "market",
1394
+ "spot",
1395
+ "swap",
1396
+ "futures",
1397
+ "option",
1398
+ "account",
1399
+ ...EARN_SUB_MODULE_IDS,
1400
+ ...BOT_SUB_MODULE_IDS
1401
+ ];
1402
+ var DEFAULT_MODULES = ["spot", "swap", "option", "account", ...BOT_DEFAULT_SUB_MODULES];
1288
1403
  function registerAccountTools() {
1289
1404
  return [
1290
1405
  {
@@ -3922,7 +4037,12 @@ function buildContractTradeTools(cfg) {
3922
4037
  },
3923
4038
  sz: {
3924
4039
  type: "string",
3925
- description: "Contracts count (NOT USDT). Use market_get_instruments for ctVal."
4040
+ description: "Contracts count by default. Set tgtCcy=quote_ccy to use USDT amount instead."
4041
+ },
4042
+ tgtCcy: {
4043
+ type: "string",
4044
+ enum: ["base_ccy", "quote_ccy"],
4045
+ description: "Size unit. base_ccy(default): sz in contracts, quote_ccy: sz in USDT"
3926
4046
  },
3927
4047
  px: { type: "string", description: "Required for limit/post_only/fok/ioc" },
3928
4048
  reduceOnly: {
@@ -3950,6 +4070,7 @@ function buildContractTradeTools(cfg) {
3950
4070
  posSide: readString(args, "posSide"),
3951
4071
  ordType: requireString(args, "ordType"),
3952
4072
  sz: requireString(args, "sz"),
4073
+ tgtCcy: readString(args, "tgtCcy"),
3953
4074
  px: readString(args, "px"),
3954
4075
  reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
3955
4076
  clOrdId: readString(args, "clOrdId"),
@@ -5605,6 +5726,11 @@ function registerSpotTradeTools() {
5605
5726
  type: "string",
5606
5727
  description: "Buy market: quote amount, all others: base amount"
5607
5728
  },
5729
+ tgtCcy: {
5730
+ type: "string",
5731
+ enum: ["base_ccy", "quote_ccy"],
5732
+ description: "Size unit. base_ccy(default): sz in base (e.g. BTC), quote_ccy: sz in quote (e.g. USDT)"
5733
+ },
5608
5734
  px: {
5609
5735
  type: "string",
5610
5736
  description: "Required for limit/post_only/fok/ioc"
@@ -5643,6 +5769,7 @@ function registerSpotTradeTools() {
5643
5769
  side: requireString(args, "side"),
5644
5770
  ordType: requireString(args, "ordType"),
5645
5771
  sz: requireString(args, "sz"),
5772
+ tgtCcy: readString(args, "tgtCcy"),
5646
5773
  px: readString(args, "px"),
5647
5774
  clOrdId: readString(args, "clOrdId"),
5648
5775
  tag: context.config.sourceTag,
@@ -6371,6 +6498,7 @@ function registerSwapTradeTools() {
6371
6498
  function allToolSpecs() {
6372
6499
  return [
6373
6500
  ...registerMarketTools(),
6501
+ ...registerIndicatorTools(),
6374
6502
  ...registerSpotTradeTools(),
6375
6503
  ...registerSwapTradeTools(),
6376
6504
  ...registerFuturesTools(),
@@ -6412,7 +6540,18 @@ function readFullConfig() {
6412
6540
  const path4 = configFilePath();
6413
6541
  if (!existsSync(path4)) return { profiles: {} };
6414
6542
  const raw = readFileSync(path4, "utf-8");
6415
- return parse(raw);
6543
+ try {
6544
+ return parse(raw);
6545
+ } catch (err) {
6546
+ throw new ConfigError(
6547
+ `Failed to parse ${path4}: ${err instanceof Error ? err.message : String(err)}`,
6548
+ `If your passphrase or keys contain special characters:
6549
+ - Contains # \\ " \u2192 use single quotes: passphrase = 'your#pass'
6550
+ - Contains ' \u2192 use double quotes: passphrase = "your'pass"
6551
+ - Contains both \u2192 use triple quotes: passphrase = '''your'#pass'''
6552
+ Or re-run: okx config init`
6553
+ );
6554
+ }
6416
6555
  }
6417
6556
  function readTomlProfile(profileName) {
6418
6557
  const config = readFullConfig();
@@ -6802,7 +6941,7 @@ var _require = createRequire(import.meta.url);
6802
6941
  var pkg = _require("../package.json");
6803
6942
  var SERVER_NAME = "okx-trade-mcp";
6804
6943
  var SERVER_VERSION = pkg.version;
6805
- var GIT_HASH = true ? "c00f777" : "dev";
6944
+ var GIT_HASH = true ? "9f66f84" : "dev";
6806
6945
 
6807
6946
  // src/server.ts
6808
6947
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";