@okx_ai/okx-trade-mcp 1.3.2-beta.5 → 1.3.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
@@ -22,18 +22,21 @@ import {
22
22
  import { homedir as homedir2 } from "os";
23
23
  import { join as join2, dirname } from "path";
24
24
  import { createHmac } from "crypto";
25
+ import { spawn, execFile as execFile2 } from "child_process";
26
+ import { homedir as homedir3 } from "os";
27
+ import { join as join3 } from "path";
25
28
  import fs from "fs";
26
29
  import path from "path";
27
30
  import os from "os";
28
31
  import { writeFileSync as writeFileSync2, renameSync as renameSync2, unlinkSync as unlinkSync2, mkdirSync as mkdirSync2 } from "fs";
29
- import { join as join3, resolve, basename, sep } from "path";
32
+ import { join as join4, resolve, basename, sep } from "path";
30
33
  import { randomUUID } from "crypto";
31
34
  import yauzl from "yauzl";
32
- import { join as join5, dirname as dirname3 } from "path";
33
- import { homedir as homedir3 } from "os";
34
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, existsSync as existsSync3 } from "fs";
35
- import { join as join6, dirname as dirname4 } from "path";
35
+ import { join as join6, dirname as dirname3 } from "path";
36
36
  import { homedir as homedir4 } from "os";
37
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, existsSync as existsSync3 } from "fs";
38
+ import { join as join7, dirname as dirname4 } from "path";
39
+ import { homedir as homedir5 } from "os";
37
40
 
38
41
  // ../../node_modules/.pnpm/smol-toml@1.6.0/node_modules/smol-toml/dist/error.js
39
42
  function getLineColFromPtr(string, ptr) {
@@ -722,8 +725,8 @@ function parse(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
722
725
 
723
726
  // ../core/dist/index.js
724
727
  import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, existsSync as existsSync4 } from "fs";
725
- import { join as join7 } from "path";
726
- import { homedir as homedir5 } from "os";
728
+ import { join as join8 } from "path";
729
+ import { homedir as homedir6 } from "os";
727
730
  import fs2 from "fs";
728
731
  import path2 from "path";
729
732
  import os2 from "os";
@@ -731,6 +734,8 @@ import * as fs3 from "fs";
731
734
  import * as path3 from "path";
732
735
  import * as os3 from "os";
733
736
  import { execFileSync } from "child_process";
737
+ import { join as join12 } from "path";
738
+ import { homedir as homedir10 } from "os";
734
739
  var EXEC_TIMEOUT_MS = 3e4;
735
740
  var ALLOWED_DOMAIN_RE = /^[\w.-]+\.okx\.com$/;
736
741
  var PILOT_BIN_DIR = join(homedir(), ".okx", "bin");
@@ -1042,6 +1047,11 @@ var ConfigError = class extends OkxMcpError {
1042
1047
  super("ConfigError", message, { suggestion });
1043
1048
  }
1044
1049
  };
1050
+ var NotLoggedInError = class extends ConfigError {
1051
+ constructor(suggestion = "Run `okx auth login` to authenticate.") {
1052
+ super("Not logged in.", suggestion);
1053
+ }
1054
+ };
1045
1055
  var ValidationError = class extends OkxMcpError {
1046
1056
  constructor(message, suggestion) {
1047
1057
  super("ValidationError", message, { suggestion });
@@ -1094,6 +1104,97 @@ function toToolErrorPayload(error, fallbackEndpoint) {
1094
1104
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1095
1105
  };
1096
1106
  }
1107
+ var EXIT_CODES = {
1108
+ SUCCESS: 0,
1109
+ UNAUTHORIZED_CALLER: 1,
1110
+ NOT_LOGGED_IN: 2,
1111
+ REFRESH_FAILED: 3
1112
+ };
1113
+ var EXEC_TIMEOUT_MS2 = 5e3;
1114
+ var AUTH_BIN_DIR = join3(homedir3(), ".okx", "bin");
1115
+ function getAuthBinaryPath() {
1116
+ if (process.env.OKX_AUTH_BIN) {
1117
+ return process.env.OKX_AUTH_BIN;
1118
+ }
1119
+ const ext = process.platform === "win32" ? ".exe" : "";
1120
+ return join3(AUTH_BIN_DIR, `okx-auth${ext}`);
1121
+ }
1122
+ function execAuthToken() {
1123
+ const binPath = getAuthBinaryPath();
1124
+ return new Promise((resolve3, reject) => {
1125
+ const child = spawn(binPath, ["token"], {
1126
+ stdio: ["ignore", "ignore", "inherit", "pipe"]
1127
+ // stdin stdout stderr fd3 (pipe)
1128
+ });
1129
+ const chunks = [];
1130
+ const fd3 = child.stdio[3];
1131
+ fd3.on("data", (chunk) => chunks.push(chunk));
1132
+ child.on("error", (err) => {
1133
+ reject(new ConfigError(
1134
+ `Failed to spawn okx-auth: ${err.message}`,
1135
+ "Ensure the okx-auth binary exists and is executable."
1136
+ ));
1137
+ });
1138
+ child.on("close", (code) => {
1139
+ if (code === EXIT_CODES.SUCCESS) {
1140
+ const token = Buffer.concat(chunks).toString("utf-8").trim();
1141
+ if (!token) {
1142
+ reject(new AuthenticationError(
1143
+ "okx-auth returned empty token.",
1144
+ "Run `okx auth login` to re-authenticate."
1145
+ ));
1146
+ return;
1147
+ }
1148
+ resolve3(token);
1149
+ return;
1150
+ }
1151
+ if (code === EXIT_CODES.NOT_LOGGED_IN) {
1152
+ reject(new NotLoggedInError());
1153
+ return;
1154
+ }
1155
+ if (code === EXIT_CODES.UNAUTHORIZED_CALLER) {
1156
+ reject(new AuthenticationError(
1157
+ "okx-auth rejected the caller (unauthorized).",
1158
+ "Ensure you are running from a trusted OKX tool."
1159
+ ));
1160
+ return;
1161
+ }
1162
+ if (code === EXIT_CODES.REFRESH_FAILED) {
1163
+ reject(new AuthenticationError(
1164
+ "Token refresh failed.",
1165
+ "Run `okx auth login` to re-authenticate."
1166
+ ));
1167
+ return;
1168
+ }
1169
+ reject(new AuthenticationError(
1170
+ `okx-auth token exited with code ${code}.`,
1171
+ "Run `okx auth login` to re-authenticate."
1172
+ ));
1173
+ });
1174
+ });
1175
+ }
1176
+ function execAuthStatus() {
1177
+ const binPath = getAuthBinaryPath();
1178
+ return new Promise((resolve3) => {
1179
+ execFile2(
1180
+ binPath,
1181
+ ["status", "--json"],
1182
+ { timeout: EXEC_TIMEOUT_MS2, encoding: "utf-8" },
1183
+ (error, stdout) => {
1184
+ if (error) {
1185
+ resolve3(null);
1186
+ return;
1187
+ }
1188
+ try {
1189
+ const result = JSON.parse(stdout);
1190
+ resolve3(result);
1191
+ } catch {
1192
+ resolve3(null);
1193
+ }
1194
+ }
1195
+ );
1196
+ });
1197
+ }
1097
1198
  function sleep(ms) {
1098
1199
  return new Promise((resolve3) => {
1099
1200
  setTimeout(resolve3, ms);
@@ -1225,6 +1326,7 @@ function maskKey(key) {
1225
1326
  if (key.length <= 8) return "***";
1226
1327
  return `${key.slice(0, 3)}***${key.slice(-3)}`;
1227
1328
  }
1329
+ var TOKEN_CACHE_TTL_MS = 6e4;
1228
1330
  function vlog2(message) {
1229
1331
  process.stderr.write(`[verbose] ${message}
1230
1332
  `);
@@ -1233,6 +1335,8 @@ var OkxRestClient = class _OkxRestClient {
1233
1335
  config;
1234
1336
  rateLimiter;
1235
1337
  dispatcher;
1338
+ cachedAccessToken;
1339
+ cachedAccessTokenAt = 0;
1236
1340
  pilot;
1237
1341
  constructor(config) {
1238
1342
  this.config = config;
@@ -1247,6 +1351,51 @@ var OkxRestClient = class _OkxRestClient {
1247
1351
  hasCustomProxy: !!config.proxyUrl
1248
1352
  });
1249
1353
  }
1354
+ /**
1355
+ * Resolve OAuth access token via the okx-auth binary (fd3 pipe).
1356
+ * Caches the token for 60 s to avoid spawning the binary on every
1357
+ * request. The binary handles refresh internally (300s TTL lead),
1358
+ * so periodic re-calls let it serve a fresh token when needed.
1359
+ * Returns null when not logged in.
1360
+ */
1361
+ async resolveAccessToken() {
1362
+ if (this.cachedAccessToken && Date.now() - this.cachedAccessTokenAt < TOKEN_CACHE_TTL_MS) {
1363
+ return this.cachedAccessToken;
1364
+ }
1365
+ try {
1366
+ const token = await execAuthToken();
1367
+ this.cachedAccessToken = token;
1368
+ this.cachedAccessTokenAt = Date.now();
1369
+ return token;
1370
+ } catch (e) {
1371
+ if (e instanceof NotLoggedInError) {
1372
+ return null;
1373
+ }
1374
+ throw e;
1375
+ }
1376
+ }
1377
+ /**
1378
+ * Dynamic auth — determines auth method per request.
1379
+ *
1380
+ * 1. API key in config → HMAC signing (no OAuth fallback)
1381
+ * 2. OAuth token via okx-auth binary → Bearer token
1382
+ * 3. Neither → throw ConfigError
1383
+ */
1384
+ async applyAuth(headers, method, requestPath, bodyJson, timestamp) {
1385
+ if (this.config.apiKey && this.config.secretKey && this.config.passphrase) {
1386
+ this.setAuthHeaders(headers, method, requestPath, bodyJson, timestamp);
1387
+ return;
1388
+ }
1389
+ const accessToken = await this.resolveAccessToken();
1390
+ if (accessToken) {
1391
+ headers.set("Authorization", `Bearer ${accessToken}`);
1392
+ return;
1393
+ }
1394
+ throw new ConfigError(
1395
+ "No credentials found.",
1396
+ "Run `okx auth login` to authenticate, or configure API key credentials."
1397
+ );
1398
+ }
1250
1399
  /** The canonical base URL for this client (e.g. https://www.okx.com). */
1251
1400
  get baseUrl() {
1252
1401
  return this.config.baseUrl;
@@ -1305,18 +1454,6 @@ var OkxRestClient = class _OkxRestClient {
1305
1454
  });
1306
1455
  }
1307
1456
  setAuthHeaders(headers, method, requestPath, bodyJson, timestamp) {
1308
- if (!this.config.hasAuth) {
1309
- throw new ConfigError(
1310
- "Private endpoint requires API credentials.",
1311
- "Configure OKX_API_KEY, OKX_SECRET_KEY and OKX_PASSPHRASE."
1312
- );
1313
- }
1314
- if (!this.config.apiKey || !this.config.secretKey || !this.config.passphrase) {
1315
- throw new ConfigError(
1316
- "Invalid private API credentials state.",
1317
- "Ensure all OKX credentials are set."
1318
- );
1319
- }
1320
1457
  const payload = `${timestamp}${method.toUpperCase()}${requestPath}${bodyJson}`;
1321
1458
  const signature = signOkxPayload(payload, this.config.secretKey);
1322
1459
  headers.set("OK-ACCESS-KEY", this.config.apiKey);
@@ -1431,7 +1568,7 @@ var OkxRestClient = class _OkxRestClient {
1431
1568
  const conn = this.pilot.getConnectionParams();
1432
1569
  this.logRequest("POST", `${conn.baseUrl}${path4}`, "private");
1433
1570
  const reqConfig = { method: "POST", path: path4, auth: "private" };
1434
- const headers = this.buildHeaders(reqConfig, path4, bodyJson, getNow());
1571
+ const headers = await this.buildHeaders(reqConfig, path4, bodyJson, getNow());
1435
1572
  if (conn.userAgent) {
1436
1573
  headers.set("User-Agent", conn.userAgent);
1437
1574
  }
@@ -1552,7 +1689,7 @@ var OkxRestClient = class _OkxRestClient {
1552
1689
  // Header building
1553
1690
  // ---------------------------------------------------------------------------
1554
1691
  /** Build HTTP headers. reqConfig.extraHeaders must NOT contain auth keys (OK-ACCESS-*). */
1555
- buildHeaders(reqConfig, requestPath, bodyJson, timestamp) {
1692
+ async buildHeaders(reqConfig, requestPath, bodyJson, timestamp) {
1556
1693
  const headers = new Headers({
1557
1694
  "Content-Type": "application/json",
1558
1695
  Accept: "application/json"
@@ -1561,7 +1698,7 @@ var OkxRestClient = class _OkxRestClient {
1561
1698
  headers.set("User-Agent", this.config.userAgent);
1562
1699
  }
1563
1700
  if (reqConfig.auth === "private") {
1564
- this.setAuthHeaders(headers, reqConfig.method, requestPath, bodyJson, timestamp);
1701
+ await this.applyAuth(headers, reqConfig.method, requestPath, bodyJson, timestamp);
1565
1702
  }
1566
1703
  const useSimulated = reqConfig.simulatedTrading !== void 0 ? reqConfig.simulatedTrading : this.config.demo;
1567
1704
  if (useSimulated) {
@@ -1615,7 +1752,7 @@ var OkxRestClient = class _OkxRestClient {
1615
1752
  if (reqConfig.rateLimit) {
1616
1753
  await this.rateLimiter.consume(reqConfig.rateLimit);
1617
1754
  }
1618
- const headers = this.buildHeaders(reqConfig, requestPath, bodyJson, timestamp);
1755
+ const headers = await this.buildHeaders(reqConfig, requestPath, bodyJson, timestamp);
1619
1756
  if (conn.userAgent) {
1620
1757
  headers.set("User-Agent", conn.userAgent);
1621
1758
  }
@@ -2042,8 +2179,6 @@ function registerIndicatorTools() {
2042
2179
  ];
2043
2180
  }
2044
2181
  var DEFAULT_SOURCE_TAG = "MCP";
2045
- var TOKEN_REGEX = /^[A-Z2-7]{12}$/;
2046
- var TAG_JOIN = "";
2047
2182
  var OKX_SITES = {
2048
2183
  global: {
2049
2184
  label: "Global",
@@ -2057,7 +2192,7 @@ var OKX_SITES = {
2057
2192
  },
2058
2193
  us: {
2059
2194
  label: "US",
2060
- apiBaseUrl: "https://app.okx.com",
2195
+ apiBaseUrl: "https://us.okx.com",
2061
2196
  webUrl: "https://app.okx.com"
2062
2197
  }
2063
2198
  };
@@ -2973,8 +3108,7 @@ function registerAlgoTradeTools() {
2973
3108
  callBackSpread: readString(args, "callbackSpread"),
2974
3109
  activePx: readString(args, "activePx"),
2975
3110
  reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
2976
- clOrdId: readString(args, "clOrdId"),
2977
- tag: context.config.sourceTag
3111
+ clOrdId: readString(args, "clOrdId")
2978
3112
  }),
2979
3113
  privateRateLimit("swap_place_move_stop_order", 20)
2980
3114
  );
@@ -3319,8 +3453,7 @@ function registerFuturesAlgoTools() {
3319
3453
  callBackSpread: readString(args, "callbackSpread"),
3320
3454
  activePx: readString(args, "activePx"),
3321
3455
  reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
3322
- clOrdId: readString(args, "clOrdId"),
3323
- tag: context.config.sourceTag
3456
+ clOrdId: readString(args, "clOrdId")
3324
3457
  }),
3325
3458
  privateRateLimit("futures_place_move_stop_order", 20)
3326
3459
  );
@@ -3578,7 +3711,7 @@ function safeWriteFile(targetDir, fileName, data) {
3578
3711
  throw new Error(`Invalid file name: "${fileName}"`);
3579
3712
  }
3580
3713
  const resolvedDir = resolve(targetDir);
3581
- const filePath = join3(resolvedDir, safeName);
3714
+ const filePath = join4(resolvedDir, safeName);
3582
3715
  const resolvedPath = resolve(filePath);
3583
3716
  if (!resolvedPath.startsWith(resolvedDir + sep)) {
3584
3717
  throw new Error(`Path traversal detected: "${fileName}" resolves outside target directory`);
@@ -3621,7 +3754,7 @@ async function downloadSkillZip(client, name, targetDir, format = "zip") {
3621
3754
  return filePath;
3622
3755
  }
3623
3756
  var DEFAULT_MAX_TOTAL_BYTES = 100 * 1024 * 1024;
3624
- var DEFAULT_REGISTRY_PATH = join5(homedir3(), ".okx", "skills", "registry.json");
3757
+ var DEFAULT_REGISTRY_PATH = join6(homedir4(), ".okx", "skills", "registry.json");
3625
3758
  function registerSkillsTools() {
3626
3759
  return [
3627
3760
  {
@@ -10006,7 +10139,7 @@ function toMcpTool(tool) {
10006
10139
  };
10007
10140
  }
10008
10141
  function configFilePath() {
10009
- return join6(homedir4(), ".okx", "config.toml");
10142
+ return join7(homedir5(), ".okx", "config.toml");
10010
10143
  }
10011
10144
  function readFullConfig() {
10012
10145
  const path4 = configFilePath();
@@ -10025,11 +10158,6 @@ Or re-run: okx config init`
10025
10158
  );
10026
10159
  }
10027
10160
  }
10028
- function readTomlProfile(profileName) {
10029
- const config = readFullConfig();
10030
- const name = profileName ?? config.default_profile ?? "default";
10031
- return config.profiles?.[name] ?? {};
10032
- }
10033
10161
  function expandShorthand(moduleId) {
10034
10162
  if (moduleId === "all") return [...MODULES];
10035
10163
  if (moduleId === "earn" || moduleId === "earn.all") return [...EARN_SUB_MODULE_IDS];
@@ -10063,18 +10191,24 @@ function parseModuleList(rawModules) {
10063
10191
  }
10064
10192
  return Array.from(deduped);
10065
10193
  }
10066
- function loadCredentials(toml) {
10194
+ async function loadCredentials(toml) {
10067
10195
  const apiKey = process.env.OKX_API_KEY?.trim() ?? toml.api_key;
10068
10196
  const secretKey = process.env.OKX_SECRET_KEY?.trim() ?? toml.secret_key;
10069
10197
  const passphrase = process.env.OKX_PASSPHRASE?.trim() ?? toml.passphrase;
10070
- const hasAuth = Boolean(apiKey && secretKey && passphrase);
10198
+ const hasApiKey = Boolean(apiKey && secretKey && passphrase);
10071
10199
  const partialAuth = Boolean(apiKey) || Boolean(secretKey) || Boolean(passphrase);
10072
- if (partialAuth && !hasAuth) {
10200
+ if (partialAuth && !hasApiKey) {
10073
10201
  throw new ConfigError(
10074
10202
  "Partial API credentials detected.",
10075
10203
  "Set OKX_API_KEY, OKX_SECRET_KEY and OKX_PASSPHRASE together (env vars or config.toml profile)."
10076
10204
  );
10077
10205
  }
10206
+ let hasOAuth = false;
10207
+ if (!hasApiKey) {
10208
+ const status = await execAuthStatus();
10209
+ hasOAuth = status?.status === "logged_in";
10210
+ }
10211
+ const hasAuth = hasOAuth || hasApiKey;
10078
10212
  return { apiKey, secretKey, passphrase, hasAuth };
10079
10213
  }
10080
10214
  function resolveSite(cliSite, tomlSite) {
@@ -10097,30 +10231,6 @@ function resolveBaseUrl(site, tomlBaseUrl) {
10097
10231
  }
10098
10232
  return rawBaseUrl.replace(/\/+$/, "");
10099
10233
  }
10100
- function resolveSourceTag(cli, defaultTag, opts = {}) {
10101
- const readEnv = opts.readEnv !== false;
10102
- const cliSkill = cli.skill?.trim();
10103
- if (cliSkill) {
10104
- if (isValidToken(cliSkill)) return composeTag(defaultTag, cliSkill);
10105
- console.warn("--skill value format invalid (expected 12-char Base32), ignoring");
10106
- }
10107
- if (readEnv) {
10108
- const envToken = process.env.OKX_SKILL_TOKEN?.trim();
10109
- if (envToken) {
10110
- if (isValidToken(envToken)) return composeTag(defaultTag, envToken);
10111
- console.warn("OKX_SKILL_TOKEN format invalid, ignoring");
10112
- }
10113
- }
10114
- const sourceTag = cli.sourceTag?.trim();
10115
- if (sourceTag) return sourceTag;
10116
- return defaultTag;
10117
- }
10118
- function composeTag(defaultTag, token) {
10119
- return `${defaultTag}${TAG_JOIN}${token}`;
10120
- }
10121
- function isValidToken(s) {
10122
- return TOKEN_REGEX.test(s);
10123
- }
10124
10234
  function resolveDemo(cli, toml) {
10125
10235
  if (cli.demo && cli.live) {
10126
10236
  throw new ConfigError(
@@ -10132,9 +10242,11 @@ function resolveDemo(cli, toml) {
10132
10242
  if (cli.demo === true) return true;
10133
10243
  return process.env.OKX_DEMO === "1" || process.env.OKX_DEMO === "true" || (toml.demo ?? false);
10134
10244
  }
10135
- function loadConfig(cli, opts = {}) {
10136
- const toml = readTomlProfile(cli.profile);
10137
- const creds = loadCredentials(toml);
10245
+ async function loadConfig(cli) {
10246
+ const config = readFullConfig();
10247
+ const profileName = cli.profile ?? config.default_profile ?? "default";
10248
+ const toml = config.profiles?.[profileName] ?? {};
10249
+ const creds = await loadCredentials(toml);
10138
10250
  const demo = resolveDemo(cli, toml);
10139
10251
  const site = resolveSite(cli.site, toml.site);
10140
10252
  const baseUrl = resolveBaseUrl(site, toml.base_url);
@@ -10152,9 +10264,9 @@ function loadConfig(cli, opts = {}) {
10152
10264
  "proxy_url must start with http:// or https://. SOCKS proxies are not supported."
10153
10265
  );
10154
10266
  }
10155
- const defaultTag = opts.entryPrefix ?? DEFAULT_SOURCE_TAG;
10156
10267
  return {
10157
10268
  ...creds,
10269
+ profile: profileName,
10158
10270
  baseUrl,
10159
10271
  timeoutMs: Math.floor(rawTimeout),
10160
10272
  modules: parseModuleList(cli.modules),
@@ -10162,14 +10274,12 @@ function loadConfig(cli, opts = {}) {
10162
10274
  demo,
10163
10275
  site,
10164
10276
  userAgent: cli.userAgent,
10165
- // sourceTag resolution: --skill > OKX_SKILL_TOKEN > --source-tag > defaultTag
10166
- // MCP entry passes { readEnv: false } to honour the "MCP path not attributed" contract.
10167
- sourceTag: resolveSourceTag(cli, defaultTag, { readEnv: opts.readEnv }),
10277
+ sourceTag: cli.sourceTag ?? DEFAULT_SOURCE_TAG,
10168
10278
  proxyUrl: rawProxyUrl || void 0,
10169
10279
  verbose: cli.verbose ?? false
10170
10280
  };
10171
10281
  }
10172
- var CACHE_FILE = join7(homedir5(), ".okx", "update-check.json");
10282
+ var CACHE_FILE = join8(homedir6(), ".okx", "update-check.json");
10173
10283
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
10174
10284
  function readCache2() {
10175
10285
  try {
@@ -10182,7 +10292,7 @@ function readCache2() {
10182
10292
  }
10183
10293
  function writeCache2(cache) {
10184
10294
  try {
10185
- mkdirSync6(join7(homedir5(), ".okx"), { recursive: true });
10295
+ mkdirSync6(join8(homedir6(), ".okx"), { recursive: true });
10186
10296
  writeFileSync5(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8");
10187
10297
  } catch {
10188
10298
  }
@@ -10336,13 +10446,13 @@ function findMsStoreClaudePath() {
10336
10446
  }
10337
10447
  function getConfigPath(client) {
10338
10448
  const home = os3.homedir();
10339
- const platform2 = process.platform;
10449
+ const platform3 = process.platform;
10340
10450
  switch (client) {
10341
10451
  case "claude-desktop":
10342
- if (platform2 === "win32") {
10452
+ if (platform3 === "win32") {
10343
10453
  return findMsStoreClaudePath() ?? path3.join(appData(), "Claude", CLAUDE_CONFIG_FILE);
10344
10454
  }
10345
- if (platform2 === "darwin") {
10455
+ if (platform3 === "darwin") {
10346
10456
  return path3.join(home, "Library", "Application Support", "Claude", CLAUDE_CONFIG_FILE);
10347
10457
  }
10348
10458
  return path3.join(process.env.XDG_CONFIG_HOME ?? path3.join(home, ".config"), "Claude", CLAUDE_CONFIG_FILE);
@@ -10444,6 +10554,8 @@ function runSetup(options) {
10444
10554
  `);
10445
10555
  }
10446
10556
  }
10557
+ var CACHE_PATH = join12(homedir10(), ".okx", "auth-binary-check.json");
10558
+ var CHECK_INTERVAL_MS2 = 2 * 60 * 60 * 1e3;
10447
10559
 
10448
10560
  // src/constants.ts
10449
10561
  import { createRequire } from "module";
@@ -10451,7 +10563,7 @@ var _require = createRequire(import.meta.url);
10451
10563
  var pkg = _require("../package.json");
10452
10564
  var SERVER_NAME = "okx-trade-mcp";
10453
10565
  var SERVER_VERSION = pkg.version;
10454
- var GIT_HASH = true ? "7acf49fb" : "dev";
10566
+ var GIT_HASH = true ? "1bb94dcd" : "dev";
10455
10567
 
10456
10568
  // src/server.ts
10457
10569
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -10728,25 +10840,16 @@ async function main() {
10728
10840
  `);
10729
10841
  return;
10730
10842
  }
10731
- const config = loadConfig(
10732
- {
10733
- modules: cli.modules,
10734
- profile: cli.profile,
10735
- site: cli.site,
10736
- readOnly: cli.readOnly,
10737
- demo: cli.demo,
10738
- live: cli.live,
10739
- userAgent: `${SERVER_NAME}/${SERVER_VERSION}`,
10740
- sourceTag: "MCP"
10741
- },
10742
- // MCP path: never read OKX_SKILL_TOKEN from env — the MCP path is not
10743
- // attributed; skill token should only flow from SKILL.md-injected --skill
10744
- // in the CLI path (design doc §1.3). `entryPrefix:"MCP"` is set for
10745
- // semantic completeness: if a future change flips `readEnv:true`, the
10746
- // composeTag branch would correctly produce `MCP<token>` rather than
10747
- // relying on DEFAULT_SOURCE_TAG as an implicit default.
10748
- { readEnv: false, entryPrefix: "MCP" }
10749
- );
10843
+ const config = await loadConfig({
10844
+ modules: cli.modules,
10845
+ profile: cli.profile,
10846
+ site: cli.site,
10847
+ readOnly: cli.readOnly,
10848
+ demo: cli.demo,
10849
+ live: cli.live,
10850
+ userAgent: `${SERVER_NAME}/${SERVER_VERSION}`,
10851
+ sourceTag: "MCP"
10852
+ });
10750
10853
  const logger = cli.noLog ? void 0 : new TradeLogger(cli.logLevel);
10751
10854
  const server = createServer(config, logger);
10752
10855
  const transport = new StdioServerTransport();