@okx_ai/okx-trade-mcp 1.3.2-beta.1 → 1.3.2-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
@@ -733,19 +733,19 @@ import * as os3 from "os";
733
733
  import { execFileSync } from "child_process";
734
734
  var EXEC_TIMEOUT_MS = 3e4;
735
735
  var ALLOWED_DOMAIN_RE = /^[\w.-]+\.okx\.com$/;
736
- var DOH_BIN_DIR = join(homedir(), ".okx", "bin");
737
- function getDohBinaryPath() {
738
- if (process.env.OKX_DOH_BINARY_PATH) {
739
- return process.env.OKX_DOH_BINARY_PATH;
736
+ var PILOT_BIN_DIR = join(homedir(), ".okx", "bin");
737
+ function getPilotBinaryPath() {
738
+ if (process.env.OKX_PILOT_BINARY_PATH) {
739
+ return process.env.OKX_PILOT_BINARY_PATH;
740
740
  }
741
741
  const ext = process.platform === "win32" ? ".exe" : "";
742
- return join(DOH_BIN_DIR, `okx-pilot${ext}`);
742
+ return join(PILOT_BIN_DIR, `okx-pilot${ext}`);
743
743
  }
744
- function execDohBinary(domain, exclude = [], userAgent) {
744
+ function execPilotBinary(domain, exclude = [], userAgent) {
745
745
  if (!ALLOWED_DOMAIN_RE.test(domain)) {
746
746
  return Promise.resolve(null);
747
747
  }
748
- const binPath = getDohBinaryPath();
748
+ const binPath = getPilotBinaryPath();
749
749
  const args = ["--domain", domain];
750
750
  if (exclude.length > 0) {
751
751
  args.push("--exclude", exclude.join(","));
@@ -778,7 +778,7 @@ function execDohBinary(domain, exclude = [], userAgent) {
778
778
  });
779
779
  }
780
780
  function getDefaultCachePath() {
781
- return process.env.OKX_DOH_CACHE_PATH || join2(homedir2(), ".okx", "doh-cache.json");
781
+ return process.env.OKX_PILOT_CACHE_PATH || join2(homedir2(), ".okx", "pilot-cache.json");
782
782
  }
783
783
  function readCache(hostname, cachePath = getDefaultCachePath()) {
784
784
  try {
@@ -832,7 +832,7 @@ function getActiveFailedNodes(nodes) {
832
832
  const now = Date.now();
833
833
  return nodes.filter((n) => now - n.failedAt < FAILED_NODE_TTL_MS);
834
834
  }
835
- function resolveDoh(hostname, cachePath) {
835
+ function resolvePilot(hostname, cachePath) {
836
836
  const entry = readCache(hostname, cachePath);
837
837
  if (entry) {
838
838
  if (entry.mode === "direct") {
@@ -844,53 +844,53 @@ function resolveDoh(hostname, cachePath) {
844
844
  }
845
845
  return { mode: null, node: null };
846
846
  }
847
- async function reResolveDoh(hostname, failedIp, userAgent, cachePath) {
847
+ async function reResolvePilot(hostname, failedIp, userAgent, cachePath) {
848
848
  const entry = readCache(hostname, cachePath);
849
849
  const active = getActiveFailedNodes(entry?.failedNodes);
850
850
  const now = Date.now();
851
851
  const alreadyFailed = failedIp && active.some((n) => n.ip === failedIp);
852
852
  const failedNodes = failedIp && !alreadyFailed ? [...active, { ip: failedIp, failedAt: now }] : active;
853
853
  const excludeIps = failedNodes.map((n) => n.ip);
854
- const node = await execDohBinary(hostname, excludeIps, userAgent);
854
+ const node = await execPilotBinary(hostname, excludeIps, userAgent);
855
855
  return classifyAndCache(node, hostname, failedNodes, cachePath);
856
856
  }
857
857
  function vlog(message) {
858
858
  process.stderr.write(`[verbose] ${message}
859
859
  `);
860
860
  }
861
- var DohManager = class {
861
+ var PilotManager = class {
862
862
  opts;
863
- // DoH proxy state (lazy-resolved on first request)
864
- dohResolved = false;
865
- dohRetried = false;
863
+ // Pilot proxy state (lazy-resolved on first request)
864
+ pilotResolved = false;
865
+ pilotRetried = false;
866
866
  directUnverified = false;
867
867
  // The first direct connection has not yet been verified
868
- dohNode = null;
869
- dohAgent = null;
870
- dohBaseUrl = null;
868
+ pilotNode = null;
869
+ pilotAgent = null;
870
+ pilotBaseUrl = null;
871
871
  constructor(opts) {
872
872
  this.opts = opts;
873
873
  }
874
874
  /**
875
- * Lazily resolve the DoH proxy node on the first request.
875
+ * Lazily resolve the Pilot proxy node on the first request.
876
876
  * Uses cache-first strategy via the resolver.
877
877
  */
878
- prepareDoh() {
879
- if (this.dohResolved || this.opts.hasCustomProxy) return;
880
- this.dohResolved = true;
878
+ preparePilot() {
879
+ if (this.pilotResolved || this.opts.hasCustomProxy) return;
880
+ this.pilotResolved = true;
881
881
  try {
882
882
  const { hostname, protocol } = new URL(this.opts.baseUrl);
883
- const result = resolveDoh(hostname);
883
+ const result = resolvePilot(hostname);
884
884
  if (!result.mode) {
885
885
  this.directUnverified = true;
886
886
  if (this.opts.verbose) {
887
- vlog("DoH: no cache, trying direct connection first");
887
+ vlog("Pilot: no cache, trying direct connection first");
888
888
  }
889
889
  return;
890
890
  }
891
891
  if (result.mode === "direct") {
892
892
  if (this.opts.verbose) {
893
- vlog("DoH: mode=direct (overseas or cached), using direct connection");
893
+ vlog("Pilot: mode=direct (overseas or cached), using direct connection");
894
894
  }
895
895
  return;
896
896
  }
@@ -900,57 +900,57 @@ var DohManager = class {
900
900
  } catch (err) {
901
901
  if (this.opts.verbose) {
902
902
  const cause = err instanceof Error ? err.message : String(err);
903
- vlog(`DoH resolution failed, falling back to direct: ${cause}`);
903
+ vlog(`Pilot resolution failed, falling back to direct: ${cause}`);
904
904
  }
905
905
  }
906
906
  }
907
907
  /** Get connection parameters for the current request. */
908
908
  getConnectionParams() {
909
- const baseUrl = this.dohNode ? this.dohBaseUrl : this.opts.baseUrl;
909
+ const baseUrl = this.pilotNode ? this.pilotBaseUrl : this.opts.baseUrl;
910
910
  const result = { baseUrl };
911
- if (this.dohAgent) {
912
- result.dispatcher = this.dohAgent;
911
+ if (this.pilotAgent) {
912
+ result.dispatcher = this.pilotAgent;
913
913
  }
914
- if (this.dohNode) {
915
- result.userAgent = this.dohUserAgent;
914
+ if (this.pilotNode) {
915
+ result.userAgent = this.pilotUserAgent;
916
916
  }
917
917
  return result;
918
918
  }
919
- /** Whether a DoH proxy node is currently active. */
919
+ /** Whether a Pilot proxy node is currently active. */
920
920
  get isProxyActive() {
921
- return this.dohNode !== null;
921
+ return this.pilotNode !== null;
922
922
  }
923
923
  /** Whether we have already retried after network failure. */
924
924
  get hasRetried() {
925
- return this.dohRetried;
925
+ return this.pilotRetried;
926
926
  }
927
927
  /**
928
928
  * Handle network failure: re-resolve with --exclude and retry once.
929
929
  * Returns true if retry should proceed, false if already retried.
930
930
  */
931
931
  async handleNetworkFailure() {
932
- if (this.dohRetried) return false;
933
- this.dohRetried = true;
934
- const failedIp = this.dohNode?.ip ?? "";
932
+ if (this.pilotRetried) return false;
933
+ this.pilotRetried = true;
934
+ const failedIp = this.pilotNode?.ip ?? "";
935
935
  const { hostname, protocol } = new URL(this.opts.baseUrl);
936
- this.dohNode = null;
937
- this.dohAgent = null;
938
- this.dohBaseUrl = null;
936
+ this.pilotNode = null;
937
+ this.pilotAgent = null;
938
+ this.pilotBaseUrl = null;
939
939
  if (!failedIp) this.directUnverified = false;
940
940
  if (this.opts.verbose) {
941
- vlog(failedIp ? `DoH: proxy node ${failedIp} failed, re-resolving with --exclude` : "DoH: direct connection failed, calling binary for DoH resolution");
941
+ vlog(failedIp ? `Pilot: proxy node ${failedIp} failed, re-resolving with --exclude` : "Pilot: direct connection failed, calling binary for Pilot resolution");
942
942
  }
943
943
  try {
944
- const result = await reResolveDoh(hostname, failedIp, this.dohUserAgent);
944
+ const result = await reResolvePilot(hostname, failedIp, this.pilotUserAgent);
945
945
  if (result.mode === "proxy" && result.node) {
946
946
  this.applyNode(result.node, protocol);
947
- this.dohRetried = false;
947
+ this.pilotRetried = false;
948
948
  return true;
949
949
  }
950
950
  } catch {
951
951
  }
952
952
  if (this.opts.verbose) {
953
- vlog("DoH: re-resolution failed or switched to direct, retrying with direct connection");
953
+ vlog("Pilot: re-resolution failed or switched to direct, retrying with direct connection");
954
954
  }
955
955
  return true;
956
956
  }
@@ -959,7 +959,7 @@ var DohManager = class {
959
959
  * (Even if the business response is an error, the network path is valid.)
960
960
  */
961
961
  cacheDirectIfNeeded() {
962
- if (!this.directUnverified || this.dohNode) return;
962
+ if (!this.directUnverified || this.pilotNode) return;
963
963
  this.directUnverified = false;
964
964
  const { hostname } = new URL(this.opts.baseUrl);
965
965
  writeCache(hostname, {
@@ -969,25 +969,25 @@ var DohManager = class {
969
969
  updatedAt: Date.now()
970
970
  });
971
971
  if (this.opts.verbose) {
972
- vlog("DoH: direct connection succeeded, cached mode=direct");
972
+ vlog("Pilot: direct connection succeeded, cached mode=direct");
973
973
  }
974
974
  }
975
- /** User-Agent for DoH proxy requests: OKX/@okx_ai/{packageName}/{version} */
976
- get dohUserAgent() {
975
+ /** User-Agent for Pilot proxy requests: OKX/@okx_ai/{packageName}/{version} */
976
+ get pilotUserAgent() {
977
977
  return `OKX/@okx_ai/${this.opts.packageUserAgent ?? "unknown"}`;
978
978
  }
979
979
  /**
980
- * Apply a DoH node: set up the custom Agent + base URL.
980
+ * Apply a Pilot node: set up the custom Agent + base URL.
981
981
  *
982
982
  * node.ip may be a real IP or a domain (CNAME like *.aliyunddos1021.com).
983
983
  * - Real IP → use directly in lookup callback
984
984
  * - Domain → dns.lookup on every connection to get a fresh IP
985
985
  */
986
986
  applyNode(node, protocol) {
987
- this.dohNode = node;
988
- this.dohBaseUrl = `${protocol}//${node.host}`;
987
+ this.pilotNode = node;
988
+ this.pilotBaseUrl = `${protocol}//${node.host}`;
989
989
  const nodeIpIsRealIp = !!isIP(node.ip);
990
- this.dohAgent = new Agent({
990
+ this.pilotAgent = new Agent({
991
991
  connect: {
992
992
  lookup: (_hostname, options, callback) => {
993
993
  if (nodeIpIsRealIp) {
@@ -1011,7 +1011,7 @@ var DohManager = class {
1011
1011
  }
1012
1012
  });
1013
1013
  if (this.opts.verbose) {
1014
- vlog(`DoH proxy active: \u2192 ${node.host} (${node.ip}), ttl=${node.ttl}s`);
1014
+ vlog(`Pilot proxy active: \u2192 ${node.host} (${node.ip}), ttl=${node.ttl}s`);
1015
1015
  }
1016
1016
  }
1017
1017
  };
@@ -1233,14 +1233,14 @@ var OkxRestClient = class _OkxRestClient {
1233
1233
  config;
1234
1234
  rateLimiter;
1235
1235
  dispatcher;
1236
- doh;
1236
+ pilot;
1237
1237
  constructor(config) {
1238
1238
  this.config = config;
1239
1239
  this.rateLimiter = new RateLimiter(3e4, config.verbose);
1240
1240
  if (config.proxyUrl) {
1241
1241
  this.dispatcher = new ProxyAgent(config.proxyUrl);
1242
1242
  }
1243
- this.doh = new DohManager({
1243
+ this.pilot = new PilotManager({
1244
1244
  baseUrl: config.baseUrl,
1245
1245
  packageUserAgent: config.userAgent,
1246
1246
  verbose: config.verbose,
@@ -1423,12 +1423,12 @@ var OkxRestClient = class _OkxRestClient {
1423
1423
  * Security: validates Content-Type and enforces maxBytes limit.
1424
1424
  */
1425
1425
  async privatePostBinary(path4, body, opts) {
1426
- this.doh.prepareDoh();
1426
+ this.pilot.preparePilot();
1427
1427
  const maxBytes = opts?.maxBytes ?? _OkxRestClient.DEFAULT_MAX_BYTES;
1428
1428
  const expectedCT = opts?.expectedContentType ?? "application/octet-stream";
1429
1429
  const bodyJson = body ? JSON.stringify(body) : "";
1430
1430
  const endpoint = `POST ${path4}`;
1431
- const conn = this.doh.getConnectionParams();
1431
+ const conn = this.pilot.getConnectionParams();
1432
1432
  this.logRequest("POST", `${conn.baseUrl}${path4}`, "private");
1433
1433
  const reqConfig = { method: "POST", path: path4, auth: "private" };
1434
1434
  const headers = this.buildHeaders(reqConfig, path4, bodyJson, getNow());
@@ -1440,13 +1440,15 @@ var OkxRestClient = class _OkxRestClient {
1440
1440
  try {
1441
1441
  response = await this.fetchBinary(path4, endpoint, headers, bodyJson, t0);
1442
1442
  } catch (error) {
1443
- this.doh.handleNetworkFailure().catch(() => {
1444
- });
1443
+ try {
1444
+ await this.pilot.handleNetworkFailure();
1445
+ } catch {
1446
+ }
1445
1447
  throw error;
1446
1448
  }
1447
1449
  const elapsed = Date.now() - t0;
1448
1450
  const traceId = extractTraceId(response.headers);
1449
- this.doh.cacheDirectIfNeeded();
1451
+ this.pilot.cacheDirectIfNeeded();
1450
1452
  if (!response.ok) {
1451
1453
  const text = await response.text();
1452
1454
  this.logResponse(response.status, text.length, elapsed, traceId, String(response.status));
@@ -1472,15 +1474,15 @@ var OkxRestClient = class _OkxRestClient {
1472
1474
  /**
1473
1475
  * Send an unauthenticated GET request and return the raw binary response.
1474
1476
  * Used for pre-signed download URLs where auth is embedded in the token.
1475
- * Inherits proxy, timeout, DoH, and verbose capabilities from the client.
1477
+ * Inherits proxy, timeout, Pilot, and verbose capabilities from the client.
1476
1478
  */
1477
1479
  async publicGetBinary(path4, query, opts) {
1478
- this.doh.prepareDoh();
1480
+ this.pilot.preparePilot();
1479
1481
  const maxBytes = opts?.maxBytes ?? _OkxRestClient.DEFAULT_MAX_BYTES;
1480
1482
  const expectedCT = opts?.expectedContentType ?? "application/octet-stream";
1481
1483
  const queryString = buildQueryString(query);
1482
1484
  const requestPath = queryString ? `${path4}?${queryString}` : path4;
1483
- const conn = this.doh.getConnectionParams();
1485
+ const conn = this.pilot.getConnectionParams();
1484
1486
  const url = `${conn.baseUrl}${requestPath}`;
1485
1487
  this.logRequest("GET", url, "public");
1486
1488
  const headers = new Headers({ Accept: "application/octet-stream" });
@@ -1496,13 +1498,15 @@ var OkxRestClient = class _OkxRestClient {
1496
1498
  dispatcher: this.dispatcher ?? conn.dispatcher
1497
1499
  });
1498
1500
  } catch (error) {
1499
- this.doh.handleNetworkFailure().catch(() => {
1500
- });
1501
+ try {
1502
+ await this.pilot.handleNetworkFailure();
1503
+ } catch {
1504
+ }
1501
1505
  throw new NetworkError(`Failed to call OKX endpoint GET ${path4}.`, `GET ${path4}`, error);
1502
1506
  }
1503
1507
  const elapsed = Date.now() - t0;
1504
1508
  const traceId = extractTraceId(response.headers);
1505
- this.doh.cacheDirectIfNeeded();
1509
+ this.pilot.cacheDirectIfNeeded();
1506
1510
  if (!response.ok) {
1507
1511
  const text = await response.text();
1508
1512
  this.logResponse(response.status, text.length, elapsed, traceId, String(response.status));
@@ -1527,7 +1531,7 @@ var OkxRestClient = class _OkxRestClient {
1527
1531
  }
1528
1532
  /** Execute fetch for binary endpoint, wrapping network errors. */
1529
1533
  async fetchBinary(path4, endpoint, headers, bodyJson, t0) {
1530
- const conn = this.doh.getConnectionParams();
1534
+ const conn = this.pilot.getConnectionParams();
1531
1535
  try {
1532
1536
  const fetchOptions = {
1533
1537
  method: "POST",
@@ -1574,16 +1578,16 @@ var OkxRestClient = class _OkxRestClient {
1574
1578
  // JSON request
1575
1579
  // ---------------------------------------------------------------------------
1576
1580
  /**
1577
- * Handle network error during a JSON request: refresh DoH and maybe retry.
1581
+ * Handle network error during a JSON request: refresh Pilot and maybe retry.
1578
1582
  * Always either returns a retry result or throws NetworkError.
1579
1583
  */
1580
1584
  async handleRequestNetworkError(error, reqConfig, requestPath, t0) {
1581
- if (!this.doh.hasRetried) {
1585
+ if (!this.pilot.hasRetried) {
1582
1586
  if (this.config.verbose) {
1583
1587
  const cause = error instanceof Error ? error.message : String(error);
1584
- vlog2(`Network failure, refreshing DoH: ${cause}`);
1588
+ vlog2(`Network failure, refreshing Pilot: ${cause}`);
1585
1589
  }
1586
- const shouldRetry = await this.doh.handleNetworkFailure();
1590
+ const shouldRetry = await this.pilot.handleNetworkFailure();
1587
1591
  if (shouldRetry && (reqConfig.method === "GET" || reqConfig.retryOnNetworkError)) {
1588
1592
  return this.request(reqConfig);
1589
1593
  }
@@ -1600,10 +1604,10 @@ var OkxRestClient = class _OkxRestClient {
1600
1604
  );
1601
1605
  }
1602
1606
  async request(reqConfig) {
1603
- this.doh.prepareDoh();
1607
+ this.pilot.preparePilot();
1604
1608
  const queryString = buildQueryString(reqConfig.query);
1605
1609
  const requestPath = queryString.length > 0 ? `${reqConfig.path}?${queryString}` : reqConfig.path;
1606
- const conn = this.doh.getConnectionParams();
1610
+ const conn = this.pilot.getConnectionParams();
1607
1611
  const url = `${conn.baseUrl}${requestPath}`;
1608
1612
  const bodyJson = reqConfig.body ? JSON.stringify(reqConfig.body) : "";
1609
1613
  const timestamp = getNow();
@@ -1632,7 +1636,7 @@ var OkxRestClient = class _OkxRestClient {
1632
1636
  const rawText = await response.text();
1633
1637
  const elapsed = Date.now() - t0;
1634
1638
  const traceId = extractTraceId(response.headers);
1635
- this.doh.cacheDirectIfNeeded();
1639
+ this.pilot.cacheDirectIfNeeded();
1636
1640
  return this.processResponse(rawText, response, elapsed, traceId, reqConfig, requestPath);
1637
1641
  }
1638
1642
  };
@@ -2211,6 +2215,10 @@ function registerAccountTools() {
2211
2215
  showValuation: {
2212
2216
  type: "boolean",
2213
2217
  description: "Include total asset valuation breakdown by account type (trading/funding/earn). Default false."
2218
+ },
2219
+ valuationCcy: {
2220
+ type: "string",
2221
+ description: "Currency used to denominate the total asset valuation (e.g. USDT, BTC). Default USDT. Only applies when showValuation=true."
2214
2222
  }
2215
2223
  }
2216
2224
  },
@@ -2218,6 +2226,7 @@ function registerAccountTools() {
2218
2226
  const args = asRecord(rawArgs);
2219
2227
  const ccy = readString(args, "ccy");
2220
2228
  const showValuation = readBoolean(args, "showValuation");
2229
+ const valuationCcy = readString(args, "valuationCcy") ?? "USDT";
2221
2230
  if (showValuation) {
2222
2231
  const balanceResp2 = await context.client.privateGet(
2223
2232
  "/api/v5/asset/balances",
@@ -2225,16 +2234,26 @@ function registerAccountTools() {
2225
2234
  privateRateLimit("account_get_asset_balance", 6)
2226
2235
  );
2227
2236
  let valuationData = null;
2237
+ let valuationError;
2228
2238
  try {
2229
2239
  const valuationResp = await context.client.privateGet(
2230
2240
  "/api/v5/asset/asset-valuation",
2231
- {},
2241
+ { ccy: valuationCcy },
2232
2242
  privateRateLimit("account_get_asset_valuation", 1)
2233
2243
  );
2234
2244
  valuationData = valuationResp.data;
2235
- } catch {
2245
+ } catch (err) {
2246
+ valuationError = err instanceof Error ? err.message : String(err);
2247
+ }
2248
+ const valuationResult = {
2249
+ ...normalizeResponse(balanceResp2),
2250
+ valuation: valuationData,
2251
+ valuationCcy
2252
+ };
2253
+ if (valuationError !== void 0) {
2254
+ valuationResult["valuationError"] = valuationError;
2236
2255
  }
2237
- return { ...normalizeResponse(balanceResp2), valuation: valuationData };
2256
+ return valuationResult;
2238
2257
  }
2239
2258
  const balanceResp = await context.client.privateGet(
2240
2259
  "/api/v5/asset/balances",
@@ -6214,9 +6233,9 @@ function registerEventContractTools() {
6214
6233
  var PATH_LEADERBOARD = "/api/v5/orbit/public/leaderboard";
6215
6234
  var PATH_POSITION_CURRENT = "/api/v5/orbit/public/position-current";
6216
6235
  var PATH_TRADE_RECORDS = "/api/v5/orbit/public/trade-records";
6217
- var PATH_OVERVIEW = "/api/v5/journal/public/smartmoney/overview";
6218
- var PATH_SIGNAL = "/api/v5/journal/public/smartmoney/signal";
6219
- var PATH_SIGNAL_HISTORY = "/api/v5/journal/public/smartmoney/signal-history";
6236
+ var PATH_OVERVIEW = "/api/v5/journal/smartmoney/overview";
6237
+ var PATH_SIGNAL = "/api/v5/journal/smartmoney/signal";
6238
+ var PATH_SIGNAL_HISTORY = "/api/v5/journal/smartmoney/signal-history";
6220
6239
  var SIGNAL_POOL_FILTER_PROPS = {
6221
6240
  sortType: {
6222
6241
  type: "string",
@@ -6286,23 +6305,6 @@ function extractLeaderboardData(data) {
6286
6305
  }
6287
6306
  return [];
6288
6307
  }
6289
- var SMARTMONEY_DEMO_MESSAGE = "Smart Money features are not available in demo/simulated trading mode.";
6290
- var SMARTMONEY_DEMO_SUGGESTION = "Switch to a live profile to use Smart Money features.";
6291
- function withSmartmoneyDemoGuard(tool) {
6292
- const originalHandler = tool.handler;
6293
- return {
6294
- ...tool,
6295
- handler: async (args, context) => {
6296
- if (context.config.demo) {
6297
- throw new ConfigError(
6298
- SMARTMONEY_DEMO_MESSAGE,
6299
- SMARTMONEY_DEMO_SUGGESTION
6300
- );
6301
- }
6302
- return originalHandler(args, context);
6303
- }
6304
- };
6305
- }
6306
6308
  function registerSmartmoneyTools() {
6307
6309
  const tools = [
6308
6310
  /* ---------- 1. Overview ---------- */
@@ -6373,18 +6375,18 @@ function registerSmartmoneyTools() {
6373
6375
  {
6374
6376
  name: "smartmoney_get_signal",
6375
6377
  module: "smartmoney",
6376
- description: "Single-currency consensus signal: long/short ratio, entry prices, trend, capital flow. Requires instId or instCcy. Pass ts=Date.now() for latest data, or dataVersion from a prior call. For multi-currency overview, use smartmoney_get_overview. For timeline, use smartmoney_get_signal_history.",
6378
+ description: "Single-currency consensus signal: long/short ratio, entry prices, trend, capital flow. Prefer instId (e.g. BTC-USDT-SWAP); instCcy is accepted but may return empty \u2014 use instId for reliable results. Pass ts=Date.now() for latest data, or dataVersion from a prior call. For multi-currency overview, use smartmoney_get_overview. For timeline, use smartmoney_get_signal_history.",
6377
6379
  isWrite: false,
6378
6380
  inputSchema: {
6379
6381
  type: "object",
6380
6382
  properties: {
6381
6383
  instId: {
6382
6384
  type: "string",
6383
- description: "e.g. BTC-USDT-SWAP (or use instCcy)"
6385
+ description: "Recommended. e.g. BTC-USDT-SWAP"
6384
6386
  },
6385
6387
  instCcy: {
6386
6388
  type: "string",
6387
- description: "e.g. BTC, SPOT/SWAP only (or use instId)"
6389
+ description: "e.g. BTC, SPOT/SWAP only. May return empty \u2014 prefer instId."
6388
6390
  },
6389
6391
  dataVersion: {
6390
6392
  type: "string",
@@ -6456,11 +6458,11 @@ function registerSmartmoneyTools() {
6456
6458
  },
6457
6459
  granularity: {
6458
6460
  type: "string",
6459
- description: "1h or 1d"
6461
+ description: "1h or 1d (default 1h)"
6460
6462
  },
6461
6463
  limit: {
6462
6464
  type: "string",
6463
- description: "Data points 1-500"
6465
+ description: "Data points 1-500 (default 24)"
6464
6466
  },
6465
6467
  ...SIGNAL_POOL_FILTER_PROPS
6466
6468
  },
@@ -6604,7 +6606,7 @@ function registerSmartmoneyTools() {
6604
6606
  }
6605
6607
  }
6606
6608
  ];
6607
- return tools.map(withSmartmoneyDemoGuard);
6609
+ return tools;
6608
6610
  }
6609
6611
  function buildContractTradeTools(cfg) {
6610
6612
  const { prefix, module, label, instTypes, instIdExample } = cfg;
@@ -10383,7 +10385,7 @@ var _require = createRequire(import.meta.url);
10383
10385
  var pkg = _require("../package.json");
10384
10386
  var SERVER_NAME = "okx-trade-mcp";
10385
10387
  var SERVER_VERSION = pkg.version;
10386
- var GIT_HASH = true ? "d5c8ab1" : "dev";
10388
+ var GIT_HASH = true ? "e0ee5a96" : "dev";
10387
10389
 
10388
10390
  // src/server.ts
10389
10391
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";