hvip-mcp-server 0.2.50 → 0.2.51

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.
Files changed (2) hide show
  1. package/dist/index.js +404 -257
  2. package/package.json +1 -2
package/dist/index.js CHANGED
@@ -101,8 +101,8 @@ var require_package = __commonJS({
101
101
  // node_modules/dotenv/lib/main.js
102
102
  var require_main = __commonJS({
103
103
  "node_modules/dotenv/lib/main.js"(exports2, module2) {
104
- var fs2 = require("fs");
105
- var path2 = require("path");
104
+ var fs3 = require("fs");
105
+ var path3 = require("path");
106
106
  var os2 = require("os");
107
107
  var crypto5 = require("crypto");
108
108
  var packageJson = require_package();
@@ -210,7 +210,7 @@ var require_main = __commonJS({
210
210
  if (options && options.path && options.path.length > 0) {
211
211
  if (Array.isArray(options.path)) {
212
212
  for (const filepath of options.path) {
213
- if (fs2.existsSync(filepath)) {
213
+ if (fs3.existsSync(filepath)) {
214
214
  possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
215
215
  }
216
216
  }
@@ -218,15 +218,15 @@ var require_main = __commonJS({
218
218
  possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
219
219
  }
220
220
  } else {
221
- possibleVaultPath = path2.resolve(process.cwd(), ".env.vault");
221
+ possibleVaultPath = path3.resolve(process.cwd(), ".env.vault");
222
222
  }
223
- if (fs2.existsSync(possibleVaultPath)) {
223
+ if (fs3.existsSync(possibleVaultPath)) {
224
224
  return possibleVaultPath;
225
225
  }
226
226
  return null;
227
227
  }
228
228
  function _resolveHome(envPath) {
229
- return envPath[0] === "~" ? path2.join(os2.homedir(), envPath.slice(1)) : envPath;
229
+ return envPath[0] === "~" ? path3.join(os2.homedir(), envPath.slice(1)) : envPath;
230
230
  }
231
231
  function _configVault(options) {
232
232
  const debug = Boolean(options && options.debug);
@@ -243,7 +243,7 @@ var require_main = __commonJS({
243
243
  return { parsed };
244
244
  }
245
245
  function configDotenv(options) {
246
- const dotenvPath = path2.resolve(process.cwd(), ".env");
246
+ const dotenvPath = path3.resolve(process.cwd(), ".env");
247
247
  let encoding = "utf8";
248
248
  const debug = Boolean(options && options.debug);
249
249
  const quiet = options && "quiet" in options ? options.quiet : true;
@@ -267,13 +267,13 @@ var require_main = __commonJS({
267
267
  }
268
268
  let lastError;
269
269
  const parsedAll = {};
270
- for (const path3 of optionPaths) {
270
+ for (const path4 of optionPaths) {
271
271
  try {
272
- const parsed = DotenvModule.parse(fs2.readFileSync(path3, { encoding }));
272
+ const parsed = DotenvModule.parse(fs3.readFileSync(path4, { encoding }));
273
273
  DotenvModule.populate(parsedAll, parsed, options);
274
274
  } catch (e) {
275
275
  if (debug) {
276
- _debug(`Failed to load ${path3} ${e.message}`);
276
+ _debug(`Failed to load ${path4} ${e.message}`);
277
277
  }
278
278
  lastError = e;
279
279
  }
@@ -288,7 +288,7 @@ var require_main = __commonJS({
288
288
  const shortPaths = [];
289
289
  for (const filePath of optionPaths) {
290
290
  try {
291
- const relative = path2.relative(process.cwd(), filePath);
291
+ const relative = path3.relative(process.cwd(), filePath);
292
292
  shortPaths.push(relative);
293
293
  } catch (e) {
294
294
  if (debug) {
@@ -3385,7 +3385,7 @@ var require_compile = __commonJS({
3385
3385
  const schOrFunc = root.refs[ref];
3386
3386
  if (schOrFunc)
3387
3387
  return schOrFunc;
3388
- let _sch = resolve.call(this, root, ref);
3388
+ let _sch = resolve2.call(this, root, ref);
3389
3389
  if (_sch === void 0) {
3390
3390
  const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
3391
3391
  const { schemaId } = this.opts;
@@ -3412,7 +3412,7 @@ var require_compile = __commonJS({
3412
3412
  function sameSchemaEnv(s1, s2) {
3413
3413
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
3414
3414
  }
3415
- function resolve(root, ref) {
3415
+ function resolve2(root, ref) {
3416
3416
  let sch;
3417
3417
  while (typeof (sch = this.refs[ref]) == "string")
3418
3418
  ref = sch;
@@ -3630,8 +3630,8 @@ var require_utils = __commonJS({
3630
3630
  }
3631
3631
  return ind;
3632
3632
  }
3633
- function removeDotSegments(path2) {
3634
- let input = path2;
3633
+ function removeDotSegments(path3) {
3634
+ let input = path3;
3635
3635
  const output = [];
3636
3636
  let nextSlash = -1;
3637
3637
  let len = 0;
@@ -3883,8 +3883,8 @@ var require_schemes = __commonJS({
3883
3883
  wsComponent.secure = void 0;
3884
3884
  }
3885
3885
  if (wsComponent.resourceName) {
3886
- const [path2, query] = wsComponent.resourceName.split("?");
3887
- wsComponent.path = path2 && path2 !== "/" ? path2 : void 0;
3886
+ const [path3, query] = wsComponent.resourceName.split("?");
3887
+ wsComponent.path = path3 && path3 !== "/" ? path3 : void 0;
3888
3888
  wsComponent.query = query;
3889
3889
  wsComponent.resourceName = void 0;
3890
3890
  }
@@ -4043,7 +4043,7 @@ var require_fast_uri = __commonJS({
4043
4043
  }
4044
4044
  return uri;
4045
4045
  }
4046
- function resolve(baseURI, relativeURI, options) {
4046
+ function resolve2(baseURI, relativeURI, options) {
4047
4047
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
4048
4048
  const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
4049
4049
  schemelessOptions.skipEscape = true;
@@ -4301,7 +4301,7 @@ var require_fast_uri = __commonJS({
4301
4301
  var fastUri = {
4302
4302
  SCHEMES,
4303
4303
  normalize,
4304
- resolve,
4304
+ resolve: resolve2,
4305
4305
  resolveComponent,
4306
4306
  equal,
4307
4307
  serialize,
@@ -7277,12 +7277,12 @@ var require_dist = __commonJS({
7277
7277
  throw new Error(`Unknown format "${name}"`);
7278
7278
  return f;
7279
7279
  };
7280
- function addFormats(ajv, list, fs2, exportName) {
7280
+ function addFormats(ajv, list, fs3, exportName) {
7281
7281
  var _a;
7282
7282
  var _b;
7283
7283
  (_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
7284
7284
  for (const f of list)
7285
- ajv.addFormat(f, fs2[f]);
7285
+ ajv.addFormat(f, fs3[f]);
7286
7286
  }
7287
7287
  module2.exports = exports2 = formatsPlugin;
7288
7288
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -10969,40 +10969,6 @@ var require_websocket_server = __commonJS({
10969
10969
  }
10970
10970
  });
10971
10971
 
10972
- // node_modules/@colbymchenry/codegraph/npm-sdk.js
10973
- var require_npm_sdk = __commonJS({
10974
- "node_modules/@colbymchenry/codegraph/npm-sdk.js"(exports2, module2) {
10975
- "use strict";
10976
- var path2 = require("path");
10977
- var os2 = require("os");
10978
- var fs2 = require("fs");
10979
- var target = process.platform + "-" + process.arch;
10980
- var pkg = "@colbymchenry/codegraph-" + target;
10981
- module2.exports = require(resolveLibrary());
10982
- function resolveLibrary() {
10983
- try {
10984
- return require.resolve(pkg + "/lib/dist/index.js");
10985
- } catch (e) {
10986
- }
10987
- var cached2 = cachedLibrary();
10988
- if (cached2) return cached2;
10989
- throw new Error(
10990
- "codegraph: the programmatic API is unavailable because the platform bundle\n(" + pkg + ") is not installed.\nThe compiled library ships inside that per-platform optional dependency.\nFixes:\n - install from the official npm registry so the matching bundle is fetched:\n npm i @colbymchenry/codegraph --registry=https://registry.npmjs.org\n - or run the CLI once (e.g. `npx @colbymchenry/codegraph status`) to\n self-heal the bundle into ~/.codegraph, then require() will find it."
10991
- );
10992
- }
10993
- function cachedLibrary() {
10994
- try {
10995
- var version2 = require(path2.join(__dirname, "package.json")).version;
10996
- var base = process.env.CODEGRAPH_INSTALL_DIR || path2.join(os2.homedir(), ".codegraph");
10997
- var lib = path2.join(base, "bundles", target + "-" + version2, "lib", "dist", "index.js");
10998
- if (fs2.existsSync(lib)) return lib;
10999
- } catch (e) {
11000
- }
11001
- return null;
11002
- }
11003
- }
11004
- });
11005
-
11006
10972
  // node_modules/dotenv/config.js
11007
10973
  (function() {
11008
10974
  require_main().config(
@@ -11495,8 +11461,8 @@ function getErrorMap() {
11495
11461
 
11496
11462
  // node_modules/zod/v3/helpers/parseUtil.js
11497
11463
  var makeIssue = (params) => {
11498
- const { data, path: path2, errorMaps, issueData } = params;
11499
- const fullPath = [...path2, ...issueData.path || []];
11464
+ const { data, path: path3, errorMaps, issueData } = params;
11465
+ const fullPath = [...path3, ...issueData.path || []];
11500
11466
  const fullIssue = {
11501
11467
  ...issueData,
11502
11468
  path: fullPath
@@ -11612,11 +11578,11 @@ var errorUtil;
11612
11578
 
11613
11579
  // node_modules/zod/v3/types.js
11614
11580
  var ParseInputLazyPath = class {
11615
- constructor(parent, value, path2, key) {
11581
+ constructor(parent, value, path3, key) {
11616
11582
  this._cachedPath = [];
11617
11583
  this.parent = parent;
11618
11584
  this.data = value;
11619
- this._path = path2;
11585
+ this._path = path3;
11620
11586
  this._key = key;
11621
11587
  }
11622
11588
  get path() {
@@ -15253,10 +15219,10 @@ function assignProp(target, prop, value) {
15253
15219
  configurable: true
15254
15220
  });
15255
15221
  }
15256
- function getElementAtPath(obj, path2) {
15257
- if (!path2)
15222
+ function getElementAtPath(obj, path3) {
15223
+ if (!path3)
15258
15224
  return obj;
15259
- return path2.reduce((acc, key) => acc?.[key], obj);
15225
+ return path3.reduce((acc, key) => acc?.[key], obj);
15260
15226
  }
15261
15227
  function promiseAllObject(promisesObj) {
15262
15228
  const keys = Object.keys(promisesObj);
@@ -15576,11 +15542,11 @@ function aborted(x, startIndex = 0) {
15576
15542
  }
15577
15543
  return false;
15578
15544
  }
15579
- function prefixIssues(path2, issues) {
15545
+ function prefixIssues(path3, issues) {
15580
15546
  return issues.map((iss) => {
15581
15547
  var _a;
15582
15548
  (_a = iss).path ?? (_a.path = []);
15583
- iss.path.unshift(path2);
15549
+ iss.path.unshift(path3);
15584
15550
  return iss;
15585
15551
  });
15586
15552
  }
@@ -23110,7 +23076,7 @@ var Protocol = class {
23110
23076
  return;
23111
23077
  }
23112
23078
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
23113
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
23079
+ await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
23114
23080
  options?.signal?.throwIfAborted();
23115
23081
  }
23116
23082
  } catch (error2) {
@@ -23127,7 +23093,7 @@ var Protocol = class {
23127
23093
  */
23128
23094
  request(request3, resultSchema, options) {
23129
23095
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
23130
- return new Promise((resolve, reject) => {
23096
+ return new Promise((resolve2, reject) => {
23131
23097
  const earlyReject = (error2) => {
23132
23098
  reject(error2);
23133
23099
  };
@@ -23205,7 +23171,7 @@ var Protocol = class {
23205
23171
  if (!parseResult.success) {
23206
23172
  reject(parseResult.error);
23207
23173
  } else {
23208
- resolve(parseResult.data);
23174
+ resolve2(parseResult.data);
23209
23175
  }
23210
23176
  } catch (error2) {
23211
23177
  reject(error2);
@@ -23466,12 +23432,12 @@ var Protocol = class {
23466
23432
  }
23467
23433
  } catch {
23468
23434
  }
23469
- return new Promise((resolve, reject) => {
23435
+ return new Promise((resolve2, reject) => {
23470
23436
  if (signal.aborted) {
23471
23437
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
23472
23438
  return;
23473
23439
  }
23474
- const timeoutId = setTimeout(resolve, interval);
23440
+ const timeoutId = setTimeout(resolve2, interval);
23475
23441
  signal.addEventListener("abort", () => {
23476
23442
  clearTimeout(timeoutId);
23477
23443
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -24571,7 +24537,7 @@ var McpServer = class {
24571
24537
  let task = createTaskResult.task;
24572
24538
  const pollInterval = task.pollInterval ?? 5e3;
24573
24539
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
24574
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
24540
+ await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
24575
24541
  const updatedTask = await extra.taskStore.getTask(taskId);
24576
24542
  if (!updatedTask) {
24577
24543
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -25220,12 +25186,12 @@ var StdioServerTransport = class {
25220
25186
  this.onclose?.();
25221
25187
  }
25222
25188
  send(message) {
25223
- return new Promise((resolve) => {
25189
+ return new Promise((resolve2) => {
25224
25190
  const json = serializeMessage(message);
25225
25191
  if (this._stdout.write(json)) {
25226
- resolve();
25192
+ resolve2();
25227
25193
  } else {
25228
- this._stdout.once("drain", resolve);
25194
+ this._stdout.once("drain", resolve2);
25229
25195
  }
25230
25196
  });
25231
25197
  }
@@ -25724,7 +25690,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
25724
25690
  });
25725
25691
  if (!chunk) {
25726
25692
  if (i === 1) {
25727
- await new Promise((resolve) => setTimeout(resolve));
25693
+ await new Promise((resolve2) => setTimeout(resolve2));
25728
25694
  maxReadCount = 3;
25729
25695
  continue;
25730
25696
  }
@@ -26224,9 +26190,9 @@ data:
26224
26190
  const initRequest = messages.find((m) => isInitializeRequest(m));
26225
26191
  const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
26226
26192
  if (this._enableJsonResponse) {
26227
- return new Promise((resolve) => {
26193
+ return new Promise((resolve2) => {
26228
26194
  this._streamMapping.set(streamId, {
26229
- resolveJson: resolve,
26195
+ resolveJson: resolve2,
26230
26196
  cleanup: () => {
26231
26197
  this._streamMapping.delete(streamId);
26232
26198
  }
@@ -26559,8 +26525,8 @@ var StreamableHTTPServerTransport = class {
26559
26525
  // src/adapters/okx.ts
26560
26526
  var import_node_crypto = __toESM(require("node:crypto"));
26561
26527
  var BASE = "https://www.okx.com";
26562
- function sign(ts, method, path2, body, secret) {
26563
- const msg = ts + method + path2 + body;
26528
+ function sign(ts, method, path3, body, secret) {
26529
+ const msg = ts + method + path3 + body;
26564
26530
  return import_node_crypto.default.createHmac("sha256", secret).update(msg).digest("base64");
26565
26531
  }
26566
26532
  function timestamp() {
@@ -26573,9 +26539,9 @@ function buildQuery(params) {
26573
26539
  }
26574
26540
  return p.size ? "?" + p.toString() : "";
26575
26541
  }
26576
- async function request(method, path2, options = {}) {
26542
+ async function request(method, path3, options = {}) {
26577
26543
  const query = options.params ? buildQuery(options.params) : "";
26578
- const fullPath = path2 + query;
26544
+ const fullPath = path3 + query;
26579
26545
  const bodyStr = options.body ? JSON.stringify(options.body) : "";
26580
26546
  const headers = {
26581
26547
  "Content-Type": "application/json",
@@ -26964,12 +26930,12 @@ var privateApi = {
26964
26930
 
26965
26931
  // src/adapters/hrails.ts
26966
26932
  var DEFAULT_BASE = "https://api-staging.hwallet.vip";
26967
- async function request2(path2, params = {}, apiKey, base) {
26933
+ async function request2(path3, params = {}, apiKey, base) {
26968
26934
  const filtered = Object.entries(params).filter(([, v]) => v !== void 0 && v !== "");
26969
26935
  const p = new URLSearchParams();
26970
26936
  for (const [k, v] of filtered) p.append(k, String(v));
26971
26937
  const query = p.size ? "?" + p.toString() : "";
26972
- const res = await fetch(base + path2 + query, {
26938
+ const res = await fetch(base + path3 + query, {
26973
26939
  headers: {
26974
26940
  "Accept": "application/json",
26975
26941
  "Authorization": `Bearer ${apiKey}`
@@ -26981,7 +26947,7 @@ async function request2(path2, params = {}, apiKey, base) {
26981
26947
  return json.data ?? json;
26982
26948
  }
26983
26949
  function createHRailsClient(apiKey, baseUrl = DEFAULT_BASE) {
26984
- const get = (path2, params) => request2(path2, params, apiKey, baseUrl);
26950
+ const get = (path3, params) => request2(path3, params, apiKey, baseUrl);
26985
26951
  return {
26986
26952
  health: () => fetch(baseUrl + "/health").then((r) => r.json()),
26987
26953
  listEvents: (params) => {
@@ -35613,7 +35579,7 @@ var XLayerWSManager = class {
35613
35579
  async connect() {
35614
35580
  if (this.ws?.readyState === wrapper_default.OPEN) return;
35615
35581
  if (this.connectPromise) return this.connectPromise;
35616
- this.connectPromise = new Promise((resolve, reject) => {
35582
+ this.connectPromise = new Promise((resolve2, reject) => {
35617
35583
  const ws = new wrapper_default(WS_URL);
35618
35584
  ws.on("open", () => {
35619
35585
  this.ws = ws;
@@ -35621,7 +35587,7 @@ var XLayerWSManager = class {
35621
35587
  this.pingTimer = setInterval(() => {
35622
35588
  if (ws.readyState === wrapper_default.OPEN) ws.ping();
35623
35589
  }, 3e4);
35624
- resolve();
35590
+ resolve2();
35625
35591
  });
35626
35592
  ws.on("message", (raw) => {
35627
35593
  try {
@@ -35674,12 +35640,12 @@ var XLayerWSManager = class {
35674
35640
  await this.connect();
35675
35641
  const ws = this.ws;
35676
35642
  const id = ++this.idCounter;
35677
- return new Promise((resolve, reject) => {
35643
+ return new Promise((resolve2, reject) => {
35678
35644
  const timer = setTimeout(() => {
35679
35645
  this.pending.delete(id);
35680
35646
  reject(new Error(`RPC \u8C03\u7528\u8D85\u65F6: ${method}`));
35681
35647
  }, 3e4);
35682
- this.pending.set(id, { resolve, reject, timer });
35648
+ this.pending.set(id, { resolve: resolve2, reject, timer });
35683
35649
  ws.send(JSON.stringify({ jsonrpc: "2.0", id, method, params }));
35684
35650
  });
35685
35651
  }
@@ -35985,7 +35951,7 @@ var WsManager = class {
35985
35951
  return count;
35986
35952
  }
35987
35953
  connect(url, auth, type) {
35988
- return new Promise((resolve, reject) => {
35954
+ return new Promise((resolve2, reject) => {
35989
35955
  const ws = new wrapper_default(url);
35990
35956
  const timeout = setTimeout(() => {
35991
35957
  ws.close();
@@ -36012,7 +35978,7 @@ var WsManager = class {
36012
35978
  }, 25e3);
36013
35979
  this.setPing(type, timer);
36014
35980
  this.setWs(type, ws);
36015
- resolve();
35981
+ resolve2();
36016
35982
  });
36017
35983
  ws.on("message", (raw) => {
36018
35984
  try {
@@ -36845,75 +36811,213 @@ function registerAgentHubTools(server) {
36845
36811
  }
36846
36812
 
36847
36813
  // src/tools/codegraph.ts
36848
- var _cg = null;
36849
- var _cgInitError = null;
36850
- var _cgInitDone = false;
36851
- async function getCodeGraph() {
36852
- if (_cgInitDone) return _cg;
36814
+ var path2 = __toESM(require("node:path"));
36815
+ var fs2 = __toESM(require("node:fs"));
36816
+ var DatabaseSync = null;
36817
+ var _sqliteAvailable = null;
36818
+ function isSqliteAvailable() {
36819
+ if (_sqliteAvailable !== null) return _sqliteAvailable;
36853
36820
  try {
36854
- const mod = await Promise.resolve().then(() => __toESM(require_npm_sdk()));
36855
- const CodeGraph = mod.CodeGraph || mod.default?.CodeGraph;
36856
- _cg = await CodeGraph.open(".");
36857
- _cgInitDone = true;
36858
- return _cg;
36859
- } catch (e) {
36860
- _cgInitError = e.message || String(e);
36861
- _cgInitDone = true;
36821
+ const sqlite = require("node:sqlite");
36822
+ DatabaseSync = sqlite.DatabaseSync;
36823
+ _sqliteAvailable = true;
36824
+ return true;
36825
+ } catch {
36826
+ _sqliteAvailable = false;
36827
+ return false;
36828
+ }
36829
+ }
36830
+ function getDBPath() {
36831
+ return path2.resolve(".codegraph", "codegraph.db");
36832
+ }
36833
+ function openDB() {
36834
+ if (!isSqliteAvailable()) return null;
36835
+ const dbPath = getDBPath();
36836
+ if (!fs2.existsSync(dbPath)) return null;
36837
+ try {
36838
+ return new DatabaseSync(dbPath, { readonly: true });
36839
+ } catch {
36862
36840
  return null;
36863
36841
  }
36864
36842
  }
36843
+ function safeGet(db, sql, ...params) {
36844
+ try {
36845
+ const stmt = db.prepare(sql);
36846
+ return stmt.get(...params.length ? params : []);
36847
+ } catch {
36848
+ return null;
36849
+ }
36850
+ }
36851
+ function safeAll(db, sql, limit, ...params) {
36852
+ try {
36853
+ const stmt = db.prepare(sql);
36854
+ const all = stmt.all(...params.length ? params : []);
36855
+ return (Array.isArray(all) ? all : []).slice(0, limit);
36856
+ } catch {
36857
+ return [];
36858
+ }
36859
+ }
36860
+ function findNodes(db, name, limit = 5) {
36861
+ const exact = safeAll(
36862
+ db,
36863
+ "SELECT * FROM nodes WHERE name = ? LIMIT ?",
36864
+ limit,
36865
+ name,
36866
+ limit
36867
+ );
36868
+ if (exact.length > 0) return exact;
36869
+ return safeAll(
36870
+ db,
36871
+ "SELECT * FROM nodes WHERE name LIKE ? LIMIT ?",
36872
+ limit,
36873
+ `%${name}%`,
36874
+ limit
36875
+ );
36876
+ }
36877
+ function getCallers(db, nodeId, limit = 50) {
36878
+ return safeAll(db, `
36879
+ SELECT n.name, n.kind, n.file_path, n.start_line, e.line, e.kind as edge_kind
36880
+ FROM edges e
36881
+ JOIN nodes n ON e.source = n.id
36882
+ WHERE e.target = ? AND e.kind = 'calls'
36883
+ ORDER BY n.file_path, n.start_line
36884
+ LIMIT ?
36885
+ `, limit, nodeId, limit);
36886
+ }
36887
+ function getCallees(db, nodeId, limit = 50) {
36888
+ return safeAll(db, `
36889
+ SELECT n.name, n.kind, n.file_path, n.start_line, e.line, e.kind as edge_kind
36890
+ FROM edges e
36891
+ JOIN nodes n ON e.target = n.id
36892
+ WHERE e.source = ? AND e.kind = 'calls'
36893
+ ORDER BY n.file_path, n.start_line
36894
+ LIMIT ?
36895
+ `, limit, nodeId, limit);
36896
+ }
36897
+ function getImpact(db, nodeId, maxDepth = 2, limit = 50) {
36898
+ const direct = getCallers(db, nodeId, limit);
36899
+ const indirectMap = /* @__PURE__ */ new Map();
36900
+ for (const d of direct.slice(0, 10)) {
36901
+ const node = safeGet(
36902
+ db,
36903
+ "SELECT id, name, kind, file_path FROM nodes WHERE name = ? AND file_path = ? LIMIT 1",
36904
+ d.name,
36905
+ d.file_path
36906
+ );
36907
+ if (node) {
36908
+ const indirect = safeAll(db, `
36909
+ SELECT n.name, n.kind, n.file_path, n.start_line
36910
+ FROM edges e JOIN nodes n ON e.source = n.id
36911
+ WHERE e.target = ? AND e.kind = 'calls'
36912
+ LIMIT 5
36913
+ `, 5, node.id);
36914
+ for (const idr of indirect) {
36915
+ const key = `${idr.name}@${idr.file_path}`;
36916
+ if (!indirectMap.has(key)) indirectMap.set(key, idr);
36917
+ }
36918
+ }
36919
+ }
36920
+ return { direct, indirect: [...indirectMap.values()].slice(0, limit) };
36921
+ }
36865
36922
  function registerCodeGraphTools(server) {
36866
36923
  server.tool(
36867
36924
  "codegraph_status",
36868
- "CAT:[\u4EE3\u7801\u667A\u80FD] | ## \u529F\u80FD\uFF1A\u68C0\u67E5\u4EE3\u7801\u77E5\u8BC6\u56FE\u8C31\u72B6\u6001\u2014\u2014\u8282\u70B9\u6570\u3001\u8FB9\u6570\u3001\u8986\u76D6\u6587\u4EF6\u3001\u88AB\u8C03\u7528\u6700\u591A\u7684\u51FD\u6570\n## \u573A\u666F\uFF1AAgent \u9996\u6B21\u8FDE\u63A5\u65F6\u786E\u8BA4\u56FE\u8C31\u662F\u5426\u5C31\u7EEA\uFF0C\u6216\u7528\u6237\u95EE\u300Chvip \u4EE3\u7801\u7ED3\u6784\u80FD\u67E5\u5417\u300D\u65F6\u786E\u8BA4\n## \u5173\u952E\u8BCD\uFF1A\u4EE3\u7801\u56FE\u8C31, codegraph, \u77E5\u8BC6\u56FE\u8C31, \u7D22\u5F15\u72B6\u6001, \u8C03\u7528\u6392\u884C\n## \u53C2\u6570\uFF1A\u65E0\n## \u9274\u6743\uFF1APUBLIC \u2014 \u672C\u5730\u8BFB\u6570\u636E\u5E93\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~800B\n## \u5173\u8054\uFF1A\u672C\u5DE5\u5177\u786E\u8BA4\u72B6\u6001 \u2192 codegraph_query \u8FFD\u8E2A\u8C03\u7528\u94FE/\u641C\u7D22\u7B26\u53F7",
36925
+ "CAT:[\u4EE3\u7801\u667A\u80FD] | ## \u529F\u80FD\uFF1A\u68C0\u67E5\u4EE3\u7801\u77E5\u8BC6\u56FE\u8C31\u72B6\u6001\u2014\u2014\u8282\u70B9\u6570\u3001\u8FB9\u6570\u3001\u8986\u76D6\u6587\u4EF6\u3001\u88AB\u8C03\u6700\u591A\u7684\u51FD\u6570\n## \u573A\u666F\uFF1AAgent \u9996\u6B21\u8FDE\u63A5\u65F6\u786E\u8BA4\u56FE\u8C31\u5C31\u7EEA\n## \u5173\u952E\u8BCD\uFF1A\u4EE3\u7801\u56FE\u8C31, codegraph, \u77E5\u8BC6\u56FE\u8C31, \u7D22\u5F15\u72B6\u6001, \u8C03\u7528\u6392\u884C\n## \u53C2\u6570\uFF1A\u65E0\n## \u9274\u6743\uFF1APUBLIC \u2014 \u672C\u5730\u8BFB DB\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~1KB\n## \u5173\u8054\uFF1A\u786E\u8BA4\u72B6\u6001 \u2192 codegraph_query \u8FFD\u8E2A\u8C03\u7528\u94FE",
36869
36926
  {},
36870
36927
  async () => {
36871
36928
  try {
36872
- const cg = await getCodeGraph();
36873
- if (!cg) {
36929
+ if (!isSqliteAvailable()) {
36930
+ const nodeVersion = process.versions.node;
36874
36931
  return toResult({
36875
36932
  status: "unavailable",
36876
- reason: _cgInitError || "CodeGraph \u5F15\u64CE\u52A0\u8F7D\u5931\u8D25",
36877
- how_to_setup: "npm i @colbymchenry/codegraph && codegraph index",
36878
- alternatives: "\u56FE\u8C31\u4E0D\u53EF\u7528\u65F6\uFF0C\u4ECD\u53EF\u7528\u672C\u5DE5\u5177\u8FD4\u56DE\u7684\u8282\u70B9\u6570\u548C\u8FB9\u6570\u4E86\u89E3\u4EE3\u7801\u89C4\u6A21",
36933
+ reason: `Node.js ${nodeVersion} \u4E0D\u652F\u6301\u5185\u7F6E sqlite\uFF0C\u9700\u8981 Node >= 22.5.0`,
36934
+ nodeVersion,
36935
+ tsIso: (/* @__PURE__ */ new Date()).toISOString(),
36936
+ _summary: `\u4EE3\u7801\u56FE\u8C31\u4E0D\u53EF\u7528\uFF1A\u9700 Node >= 22.5.0\uFF0C\u5F53\u524D ${nodeVersion}`
36937
+ });
36938
+ }
36939
+ const dbPath = getDBPath();
36940
+ if (!fs2.existsSync(dbPath)) {
36941
+ return toResult({
36942
+ status: "no_db",
36943
+ reason: `.codegraph/codegraph.db \u4E0D\u5B58\u5728`,
36944
+ how_to_setup: [
36945
+ "1. npm i -g @colbymchenry/codegraph",
36946
+ "2. cd \u5230\u9879\u76EE\u6839\u76EE\u5F55\u8FD0\u884C codegraph index",
36947
+ "3. \u91CD\u542F MCP Server",
36948
+ "\uFF08Claude Code \u7528\u6237\uFF1A\u56FE\u8C31\u7531 CodeGraph \u529F\u80FD\u81EA\u52A8\u751F\u6210\uFF09"
36949
+ ].join("\n"),
36950
+ tsIso: (/* @__PURE__ */ new Date()).toISOString(),
36951
+ _summary: "\u4EE3\u7801\u56FE\u8C31\u672A\u751F\u6210\u3002\u8FD0\u884C codegraph index \u540E\u53EF\u7528\u3002"
36952
+ });
36953
+ }
36954
+ const db = openDB();
36955
+ if (!db) {
36956
+ return toResult({
36957
+ status: "error",
36958
+ reason: "\u65E0\u6CD5\u6253\u5F00\u4EE3\u7801\u56FE\u8C31\u6570\u636E\u5E93\uFF08\u53EF\u80FD\u88AB\u9501\u5B9A\uFF09",
36959
+ dbPath,
36879
36960
  tsIso: (/* @__PURE__ */ new Date()).toISOString(),
36880
- _summary: "\u4EE3\u7801\u56FE\u8C31\u672A\u5C31\u7EEA\u3002\u8BF7\u8FD0\u884C codegraph index \u751F\u6210\u6570\u636E\u5E93\u3002"
36961
+ _summary: "\u4EE3\u7801\u56FE\u8C31\u6570\u636E\u5E93\u6253\u5F00\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002"
36881
36962
  });
36882
36963
  }
36883
- const stats = await cg.getStats();
36884
- let topCalled = [];
36885
36964
  try {
36886
- const allExported = await cg.getNodesByKind("function").then((nodes) => nodes.filter((n) => n.isExported)).catch(() => []);
36887
- const sample = allExported.slice(0, 50);
36888
- const withCounts = await Promise.all(
36889
- sample.map(async (n) => {
36890
- try {
36891
- const callers = await cg.getCallers(n.id, 1);
36892
- return { name: n.name, file: n.filePath, callers: callers?.length || 0 };
36893
- } catch {
36894
- return { name: n.name, file: n.filePath, callers: 0 };
36895
- }
36896
- })
36965
+ const nodeCount = safeGet(db, "SELECT count(*) as n FROM nodes")?.n || 0;
36966
+ const edgeCount = safeGet(db, "SELECT count(*) as n FROM edges")?.n || 0;
36967
+ const fileCount = safeGet(db, "SELECT count(*) as n FROM files")?.n || 0;
36968
+ const byLang = safeAll(
36969
+ db,
36970
+ "SELECT language, count(*) as n FROM files GROUP BY language ORDER BY n DESC",
36971
+ 20
36897
36972
  );
36898
- topCalled = withCounts.sort((a, b) => b.callers - a.callers).slice(0, 5);
36899
- } catch {
36973
+ const byKind = safeAll(
36974
+ db,
36975
+ "SELECT kind, count(*) as n FROM nodes GROUP BY kind ORDER BY n DESC",
36976
+ 20
36977
+ );
36978
+ let topCalled = [];
36979
+ try {
36980
+ topCalled = safeAll(db, `
36981
+ SELECT n.name, n.kind, n.file_path, count(e.id) as caller_count
36982
+ FROM edges e
36983
+ JOIN nodes n ON e.target = n.id
36984
+ WHERE e.kind = 'calls'
36985
+ GROUP BY e.target
36986
+ ORDER BY caller_count DESC
36987
+ LIMIT 5
36988
+ `, 5) || [];
36989
+ } catch {
36990
+ }
36991
+ const lastIndexed = safeGet(
36992
+ db,
36993
+ "SELECT max(indexed_at) as ts FROM files"
36994
+ )?.ts;
36995
+ db.close();
36996
+ const status = {
36997
+ status: "ready",
36998
+ dbPath,
36999
+ database: { nodeCount, edgeCount, fileCount },
37000
+ languages: byLang.reduce((acc, r) => ({ ...acc, [r.language]: r.n }), {}),
37001
+ nodesByKind: byKind.reduce((acc, r) => ({ ...acc, [r.kind]: r.n }), {}),
37002
+ lastIndexed: lastIndexed ? new Date(lastIndexed).toISOString() : "unknown",
37003
+ topCalledFunctions: topCalled.map((r) => ({
37004
+ name: r.name,
37005
+ kind: r.kind,
37006
+ file: r.file_path,
37007
+ callers: r.caller_count
37008
+ })),
37009
+ queryHint: "codegraph_query { mode: 'callers', symbol: 'toResult' }",
37010
+ tsIso: (/* @__PURE__ */ new Date()).toISOString(),
37011
+ _summary: `\u4EE3\u7801\u56FE\u8C31\u5C31\u7EEA\u3002${nodeCount} \u4E2A\u8282\u70B9\uFF0C${edgeCount} \u6761\u5173\u7CFB\uFF0C${fileCount} \u4E2A\u6587\u4EF6\u3002${topCalled.length ? `\u88AB\u8C03\u6700\u591A: ${topCalled.slice(0, 3).map((f) => f.name).join("\u3001")}` : ""}`
37012
+ };
37013
+ return toResult(status);
37014
+ } catch (e) {
37015
+ try {
37016
+ db.close();
37017
+ } catch {
37018
+ }
37019
+ throw e;
36900
37020
  }
36901
- const status = {
36902
- status: "ready",
36903
- stats: {
36904
- nodes: stats.nodeCount,
36905
- edges: stats.edgeCount,
36906
- files: stats.fileCount,
36907
- byKind: stats.nodesByKind,
36908
- byLanguage: stats.filesByLanguage,
36909
- dbSize: stats.dbSizeBytes ? `${(stats.dbSizeBytes / 1024 / 1024).toFixed(1)} MB` : "unknown"
36910
- },
36911
- topCalled,
36912
- queryHint: "\u7528 codegraph_query \u67E5\u8C03\u7528\u94FE\u3002\u4F8B: codegraph_query({ mode: 'callers', symbol: 'toResult' })",
36913
- tsIso: (/* @__PURE__ */ new Date()).toISOString(),
36914
- _summary: `\u4EE3\u7801\u77E5\u8BC6\u56FE\u8C31\u5C31\u7EEA\u3002${stats.nodeCount} \u4E2A\u8282\u70B9\uFF0C${stats.edgeCount} \u6761\u5173\u7CFB\uFF0C\u8986\u76D6 ${stats.fileCount} \u4E2A\u6587\u4EF6\u3002${topCalled.length ? `\u88AB\u8C03\u6700\u591A: ${topCalled.slice(0, 3).map((f) => f.name).join("\u3001")}` : ""}`
36915
- };
36916
- return toResult(status);
36917
37021
  } catch (e) {
36918
37022
  return toError(e);
36919
37023
  }
@@ -36921,143 +37025,186 @@ function registerCodeGraphTools(server) {
36921
37025
  );
36922
37026
  server.tool(
36923
37027
  "codegraph_query",
36924
- "CAT:[\u4EE3\u7801\u667A\u80FD] | ## \u529F\u80FD\uFF1A\u67E5\u8BE2\u4EE3\u7801\u77E5\u8BC6\u56FE\u8C31\u2014\u2014\u8FFD\u8E2A\u8C03\u7528\u94FE\u3001\u641C\u7D22\u7B26\u53F7\u3001\u63A2\u7D22\u6A21\u5757\u4F9D\u8D56\u3001\u6309\u6587\u4EF6\u5217\u51FA\u7B26\u53F7\n## \u573A\u666F\uFF1AAgent \u56DE\u7B54\u300CtoResult \u88AB\u54EA\u4E9B\u5DE5\u5177\u8C03\u7528\u300D\u300CregisterMarketTools \u7684\u4E0A\u4E0B\u6E38\u300D\u300C\u4EE3\u7801\u91CC\u54EA\u91CC\u5904\u7406\u4E86 WebSocket\u300D\u65F6\u8C03\u7528\n## \u5173\u952E\u8BCD\uFF1Acodegraph, \u8C03\u7528\u94FE, callers, callees, \u4F9D\u8D56, \u4EE3\u7801\u641C\u7D22, \u7B26\u53F7\u67E5\u8BE2, \u4E0A\u4E0B\u6E38, \u5F71\u54CD\u5206\u6790\n## \u53C2\u6570\uFF1A\n## - mode: \u67E5\u8BE2\u6A21\u5F0F\u3002callers=\u8C01\u8C03\u7528\u5B83, callees=\u5B83\u8C03\u7528\u8C01, search=\u5168\u6587\u641C\u7D22, file=\u6309\u6587\u4EF6\u5217\u51FA\n## - symbol: \u7B26\u53F7\u540D/\u8282\u70B9ID (callers/callees/file \u6A21\u5F0F)\n## - query: \u641C\u7D22\u8BCD (search \u6A21\u5F0F)\n## - limit: \u8FD4\u56DE\u6570\uFF0C\u9ED8\u8BA4 15\n## \u9274\u6743\uFF1APUBLIC \u2014 \u672C\u5730\u8BFB\u6570\u636E\u5E93\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~2KB\n## \u5173\u8054\uFF1Acodegraph_status \u770B\u72B6\u6001 \u2192 \u672C\u5DE5\u5177\u67E5\u8BE2 \u2192 Agent \u5B9A\u4F4D\u6E90\u7801",
37028
+ "CAT:[\u4EE3\u7801\u667A\u80FD] | ## \u529F\u80FD\uFF1A\u67E5\u8BE2\u4EE3\u7801\u77E5\u8BC6\u56FE\u8C31\u2014\u2014\u8FFD\u8E2A\u8C03\u7528\u94FE\uFF08callers/callees\uFF09\u3001\u641C\u7D22\u7B26\u53F7\u3001\u6309\u6587\u4EF6\u5217\u7B26\u53F7\u3001\u5F71\u54CD\u5206\u6790\n## \u573A\u666F\uFF1AAgent \u56DE\u7B54\u300CtoResult \u88AB\u54EA\u4E9B\u5DE5\u5177\u8C03\u7528\u300D\u300C\u6539 shared.ts \u5F71\u54CD\u54EA\u4E9B\u6A21\u5757\u300D\u300CWebSocket \u5728\u54EA\u4E9B\u6587\u4EF6\u91CC\u300D\u65F6\u8C03\u7528\n## \u5173\u952E\u8BCD\uFF1Acodegraph, \u8C03\u7528\u94FE, callers, callees, \u641C\u7D22, \u5F71\u54CD\u5206\u6790, \u4F9D\u8D56\n## \u53C2\u6570\uFF1A\n## - mode: \u67E5\u8BE2\u6A21\u5F0F\u3002callers / callees / search / file / impact\n## - symbol: \u7B26\u53F7\u540D\u6216\u6587\u4EF6\u540D\n## - limit: \u8FD4\u56DE\u6570\uFF0C\u9ED8\u8BA4 15\n## \u9274\u6743\uFF1APUBLIC \u2014 \u672C\u5730\u8BFB DB\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~2KB\n## \u5173\u8054\uFF1Acodegraph_status \u2192 codegraph_query",
36925
37029
  {
36926
- mode: external_exports.enum(["callers", "callees", "search", "file"]).describe("callers=\u8C01\u8C03\u7528\u5B83, callees=\u5B83\u8C03\u7528\u8C01, search=\u5168\u6587\u641C\u7D22, file=\u6309\u6587\u4EF6\u5217\u51FA\u7B26\u53F7"),
36927
- symbol: external_exports.string().optional().describe("\u7B26\u53F7\u540D\uFF08\u5982 toResult\uFF09\u6216\u6587\u4EF6\u540D\uFF08\u5982 agent-utils.ts\uFF09"),
36928
- query: external_exports.string().optional().describe("\u641C\u7D22\u8BCD\uFF08search \u6A21\u5F0F\uFF09\uFF0C\u5982 'websocket \u8FDE\u63A5'"),
37030
+ mode: external_exports.enum(["callers", "callees", "search", "file", "impact"]).describe("callers=\u8C01\u8C03\u7528\u5B83, callees=\u5B83\u8C03\u7528\u8C01, search=\u641C\u7B26\u53F7, file=\u6309\u6587\u4EF6, impact=2\u8DF3\u5F71\u54CD\u5206\u6790"),
37031
+ symbol: external_exports.string().optional().describe("\u7B26\u53F7\u540D\uFF08\u5982 toResult\uFF09\u6216\u6587\u4EF6\u540D\uFF08\u5982 agent-utils.ts\uFF09\u6216\u641C\u7D22\u8BCD"),
36929
37032
  limit: external_exports.number().int().min(1).max(100).optional().describe("\u8FD4\u56DE\u6570\uFF0C\u9ED8\u8BA4 15")
36930
37033
  },
36931
- async ({ mode, symbol, query, limit }) => {
37034
+ async ({ mode, symbol, limit }) => {
36932
37035
  try {
36933
- const cg = await getCodeGraph();
36934
- if (!cg) return toError("\u4EE3\u7801\u56FE\u8C31\u4E0D\u53EF\u7528\u3002\u8BF7\u5148\u8C03 codegraph_status \u68C0\u67E5\u72B6\u6001\u3002");
37036
+ const db = openDB();
37037
+ if (!db) return toError("\u4EE3\u7801\u56FE\u8C31\u4E0D\u53EF\u7528\u3002\u8BF7\u8C03 codegraph_status \u68C0\u67E5\u72B6\u6001\u3002");
36935
37038
  const n = limit || 15;
36936
- if (mode === "search") {
36937
- const q = query || symbol || "";
36938
- if (!q) return toError("search \u6A21\u5F0F\u9700\u8981 query \u6216 symbol \u53C2\u6570");
36939
- const results = await cg.searchNodes(q, { limit: n });
36940
- if (!results?.length) {
37039
+ try {
37040
+ if (mode === "search") {
37041
+ if (!symbol) return toError("search \u6A21\u5F0F\u9700\u8981 symbol \u53C2\u6570");
37042
+ const q = symbol;
37043
+ let rows = safeAll(db, `
37044
+ SELECT n.id, n.name, n.kind, n.file_path, n.start_line, n.signature,
37045
+ n.docstring, n.qualified_name
37046
+ FROM nodes_fts f
37047
+ JOIN nodes n ON f.id = n.id
37048
+ WHERE nodes_fts MATCH ?
37049
+ ORDER BY rank
37050
+ LIMIT ?
37051
+ `, n, q, n);
37052
+ if (!rows || rows.length === 0) {
37053
+ rows = safeAll(db, `
37054
+ SELECT id, name, kind, file_path, start_line, signature, docstring, qualified_name
37055
+ FROM nodes
37056
+ WHERE name LIKE ? OR qualified_name LIKE ?
37057
+ ORDER BY name
37058
+ LIMIT ?
37059
+ `, n, `%${q}%`, `%${q}%`, n);
37060
+ }
37061
+ if (!rows || rows.length === 0) {
37062
+ return toResult({
37063
+ mode: "search",
37064
+ query: q,
37065
+ found: false,
37066
+ hint: `\u672A\u627E\u5230 "${q}"\u3002\u8BD5\u8BD5\u51FD\u6570\u540D\uFF08\u5982 registerTools\uFF09\u6216\u6587\u4EF6\u540D\u7247\u6BB5\u3002`,
37067
+ tsIso: (/* @__PURE__ */ new Date()).toISOString()
37068
+ });
37069
+ }
37070
+ const items = rows.slice(0, n).map((r) => ({
37071
+ name: r.name,
37072
+ kind: r.kind,
37073
+ file: r.file_path,
37074
+ line: r.start_line,
37075
+ signature: r.signature?.slice(0, 120),
37076
+ docstring: r.docstring?.slice(0, 100)
37077
+ }));
36941
37078
  return toResult({
36942
37079
  mode: "search",
36943
37080
  query: q,
36944
- found: false,
36945
- hint: `\u672A\u627E\u5230\u4E0E "${q}" \u76F8\u5173\u7684\u7B26\u53F7\u3002\u8BD5\u8BD5\u51FD\u6570\u540D\uFF08\u5982 registerTools\uFF09\u6216\u6587\u4EF6\u540D\u3002`,
37081
+ total: rows.length,
37082
+ results: items,
37083
+ _summary: `\u641C\u7D22 "${q}" \u627E\u5230 ${rows.length} \u4E2A\u7B26\u53F7\u3002${items.slice(0, 3).map((i) => `${i.name}(${i.kind})`).join(" | ")}`,
37084
+ hint: `\u627E\u5230\u540E: codegraph_query({ mode: 'callers', symbol: '<name>' })`,
36946
37085
  tsIso: (/* @__PURE__ */ new Date()).toISOString()
36947
37086
  });
36948
37087
  }
36949
- const items = await Promise.all(results.slice(0, n).map(async (r) => {
36950
- const node = r.node || r;
36951
- let callerCount = 0, calleeCount = 0;
36952
- try {
36953
- callerCount = (await cg.getCallers(node.id, 1))?.length || 0;
36954
- } catch {
37088
+ if (mode === "callers") {
37089
+ if (!symbol) return toError("callers \u6A21\u5F0F\u9700\u8981 symbol");
37090
+ const nodes = findNodes(db, symbol, 3);
37091
+ if (!nodes.length) {
37092
+ return toResult({ mode: "callers", symbol, found: false, tsIso: (/* @__PURE__ */ new Date()).toISOString() });
36955
37093
  }
36956
- try {
36957
- calleeCount = (await cg.getCallees(node.id, 1))?.length || 0;
36958
- } catch {
37094
+ const results = nodes.map((node) => {
37095
+ const callers = getCallers(db, node.id, n);
37096
+ return {
37097
+ target: { id: node.id, name: node.name, kind: node.kind, file: node.file_path, line: node.start_line },
37098
+ callers: callers.map((c) => ({
37099
+ name: c.name,
37100
+ kind: c.kind,
37101
+ file: c.file_path,
37102
+ line: c.start_line
37103
+ })),
37104
+ total: callers.length
37105
+ };
37106
+ });
37107
+ const total = results.reduce((s, r) => s + r.total, 0);
37108
+ return toResult({
37109
+ mode: "callers",
37110
+ symbol,
37111
+ matched: nodes.length,
37112
+ results,
37113
+ _summary: `"${symbol}" \u5339\u914D ${nodes.length} \u4E2A\u7B26\u53F7\uFF0C\u5171 ${total} \u4E2A\u8C03\u7528\u8005\u3002`,
37114
+ tsIso: (/* @__PURE__ */ new Date()).toISOString()
37115
+ });
37116
+ }
37117
+ if (mode === "callees") {
37118
+ if (!symbol) return toError("callees \u6A21\u5F0F\u9700\u8981 symbol");
37119
+ const nodes = findNodes(db, symbol, 3);
37120
+ if (!nodes.length) {
37121
+ return toResult({ mode: "callees", symbol, found: false, tsIso: (/* @__PURE__ */ new Date()).toISOString() });
36959
37122
  }
36960
- return {
36961
- id: node.id,
36962
- name: node.name,
36963
- kind: node.kind,
36964
- file: node.filePath,
36965
- line: node.startLine,
36966
- signature: node.signature?.slice(0, 120),
36967
- stats: { callers: callerCount, callees: calleeCount }
36968
- };
36969
- }));
36970
- return toResult({
36971
- mode: "search",
36972
- query: q,
36973
- total: results.length,
36974
- results: items,
36975
- _summary: `\u641C\u7D22 "${q}" \u627E\u5230 ${results.length} \u4E2A\u7B26\u53F7\u3002${items.slice(0, 3).map((i) => `${i.name}(${i.kind})`).join(" | ")}`,
36976
- hint: `\u627E\u5230\u5177\u4F53\u7B26\u53F7\u540E\uFF0C\u7528 codegraph_query({ mode: 'callers', symbol: '<id>' }) \u8FFD\u8E2A\u8C03\u7528\u94FE\u3002`,
36977
- tsIso: (/* @__PURE__ */ new Date()).toISOString()
36978
- });
36979
- }
36980
- if (mode === "callers") {
36981
- if (!symbol) return toError("callers \u6A21\u5F0F\u9700\u8981 symbol \u53C2\u6570");
36982
- const nodes = await cg.getNodesByName(symbol);
36983
- if (!nodes?.length) {
36984
- return toResult({ mode: "callers", symbol, found: false, tsIso: (/* @__PURE__ */ new Date()).toISOString() });
37123
+ const results = nodes.map((node) => {
37124
+ const callees = getCallees(db, node.id, n);
37125
+ return {
37126
+ source: { id: node.id, name: node.name, kind: node.kind, file: node.file_path, line: node.start_line },
37127
+ callees: callees.map((c) => ({
37128
+ name: c.name,
37129
+ kind: c.kind,
37130
+ file: c.file_path,
37131
+ line: c.start_line
37132
+ })),
37133
+ total: callees.length
37134
+ };
37135
+ });
37136
+ const total = results.reduce((s, r) => s + r.total, 0);
37137
+ return toResult({
37138
+ mode: "callees",
37139
+ symbol,
37140
+ matched: nodes.length,
37141
+ results,
37142
+ _summary: `"${symbol}" \u5339\u914D ${nodes.length} \u4E2A\u7B26\u53F7\uFF0C\u5171\u8C03\u7528 ${total} \u4E2A\u4E0B\u6E38\u3002`,
37143
+ tsIso: (/* @__PURE__ */ new Date()).toISOString()
37144
+ });
36985
37145
  }
36986
- const results = await Promise.all(nodes.slice(0, 5).map(async (node) => {
36987
- const callers = await cg.getCallers(node.id, 1);
36988
- return {
36989
- target: { id: node.id, name: node.name, kind: node.kind, file: node.filePath, line: node.startLine },
36990
- callers: (callers || []).slice(0, n).map((c) => ({
37146
+ if (mode === "file") {
37147
+ if (!symbol) return toError("file \u6A21\u5F0F\u9700\u8981 symbol\uFF08\u6587\u4EF6\u540D\uFF09");
37148
+ const file = safeGet(
37149
+ db,
37150
+ "SELECT * FROM files WHERE path LIKE ? LIMIT 1",
37151
+ `%${symbol}%`
37152
+ );
37153
+ const nodes = safeAll(db, `
37154
+ SELECT name, kind, start_line, signature, is_exported
37155
+ FROM nodes WHERE file_path LIKE ?
37156
+ ORDER BY start_line LIMIT ?
37157
+ `, n, `%${symbol}%`, n);
37158
+ return toResult({
37159
+ mode: "file",
37160
+ file: symbol,
37161
+ fileInfo: file ? { path: file.path, language: file.language, size: file.size, nodeCount: file.node_count } : null,
37162
+ symbols: nodes.map((r) => ({
37163
+ name: r.name,
37164
+ kind: r.kind,
37165
+ line: r.start_line,
37166
+ signature: r.signature?.slice(0, 120),
37167
+ exported: r.is_exported === 1
37168
+ })),
37169
+ _summary: `\u6587\u4EF6 "${symbol}" \u5305\u542B ${nodes.length} \u4E2A\u7B26\u53F7\u3002`,
37170
+ tsIso: (/* @__PURE__ */ new Date()).toISOString()
37171
+ });
37172
+ }
37173
+ if (mode === "impact") {
37174
+ if (!symbol) return toError("impact \u6A21\u5F0F\u9700\u8981 symbol");
37175
+ const nodes = findNodes(db, symbol, 1);
37176
+ if (!nodes.length) {
37177
+ return toResult({ mode: "impact", symbol, found: false, tsIso: (/* @__PURE__ */ new Date()).toISOString() });
37178
+ }
37179
+ const node = nodes[0];
37180
+ const { direct, indirect } = getImpact(db, node.id, 2, n);
37181
+ return toResult({
37182
+ mode: "impact",
37183
+ symbol,
37184
+ node: { id: node.id, name: node.name, kind: node.kind, file: node.file_path, line: node.start_line },
37185
+ directlyAffected: direct.map((c) => ({
36991
37186
  name: c.name,
36992
37187
  kind: c.kind,
36993
- file: c.filePath,
36994
- line: c.line,
36995
- relation: c.edgeKind
37188
+ file: c.file_path,
37189
+ line: c.start_line
36996
37190
  })),
36997
- total: callers?.length || 0
36998
- };
36999
- }));
37000
- const total = results.reduce((s, r) => s + r.total, 0);
37001
- return toResult({
37002
- mode: "callers",
37003
- symbol,
37004
- matched: nodes.length,
37005
- results,
37006
- _summary: `"${symbol}" \u5339\u914D ${nodes.length} \u4E2A\u7B26\u53F7\uFF0C\u5171 ${total} \u4E2A\u8C03\u7528\u8005\u3002`,
37007
- tsIso: (/* @__PURE__ */ new Date()).toISOString()
37008
- });
37009
- }
37010
- if (mode === "callees") {
37011
- if (!symbol) return toError("callees \u6A21\u5F0F\u9700\u8981 symbol \u53C2\u6570");
37012
- const nodes = await cg.getNodesByName(symbol);
37013
- if (!nodes?.length) {
37014
- return toResult({ mode: "callees", symbol, found: false, tsIso: (/* @__PURE__ */ new Date()).toISOString() });
37015
- }
37016
- const results = await Promise.all(nodes.slice(0, 5).map(async (node) => {
37017
- const callees = await cg.getCallees(node.id, 1);
37018
- return {
37019
- source: { id: node.id, name: node.name, kind: node.kind, file: node.filePath, line: node.startLine },
37020
- callees: (callees || []).slice(0, n).map((c) => ({
37191
+ indirectlyAffected: indirect.map((c) => ({
37021
37192
  name: c.name,
37022
37193
  kind: c.kind,
37023
- file: c.filePath,
37024
- line: c.line,
37025
- relation: c.edgeKind
37194
+ file: c.file_path,
37195
+ line: c.start_line
37026
37196
  })),
37027
- total: callees?.length || 0
37028
- };
37029
- }));
37030
- const total = results.reduce((s, r) => s + r.total, 0);
37031
- return toResult({
37032
- mode: "callees",
37033
- symbol,
37034
- matched: nodes.length,
37035
- results,
37036
- _summary: `"${symbol}" \u5339\u914D ${nodes.length} \u4E2A\u7B26\u53F7\uFF0C\u5171\u8C03\u7528 ${total} \u4E2A\u4E0B\u6E38\u3002`,
37037
- tsIso: (/* @__PURE__ */ new Date()).toISOString()
37038
- });
37039
- }
37040
- if (mode === "file") {
37041
- if (!symbol) return toError("file \u6A21\u5F0F\u9700\u8981 symbol \u53C2\u6570\uFF08\u6587\u4EF6\u540D\uFF09");
37042
- const files = await cg.getFiles({ pattern: symbol });
37043
- const fileInfo = files?.[0];
37044
- const symbols = fileInfo ? await cg.getNodesInFile(fileInfo.path) : [];
37045
- return toResult({
37046
- mode: "file",
37047
- file: symbol,
37048
- fileInfo: fileInfo ? { path: fileInfo.path, language: fileInfo.language, size: fileInfo.size } : null,
37049
- symbols: (symbols || []).slice(0, n).map((s) => ({
37050
- name: s.name,
37051
- kind: s.kind,
37052
- line: s.startLine,
37053
- signature: s.signature?.slice(0, 120),
37054
- exported: s.isExported
37055
- })),
37056
- _summary: `\u6587\u4EF6 "${symbol}" \u5305\u542B ${symbols?.length || 0} \u4E2A\u7B26\u53F7\u3002`,
37057
- tsIso: (/* @__PURE__ */ new Date()).toISOString()
37058
- });
37197
+ _summary: `\u4FEE\u6539 "${symbol}" \u76F4\u63A5\u5F71\u54CD ${direct.length} \u4E2A\u8C03\u7528\u8005\uFF0C\u95F4\u63A5\u5F71\u54CD ${indirect.length} \u4E2A\u4E0B\u6E38\u3002`,
37198
+ tsIso: (/* @__PURE__ */ new Date()).toISOString()
37199
+ });
37200
+ }
37201
+ return toError(`\u672A\u77E5\u6A21\u5F0F: ${mode}`);
37202
+ } finally {
37203
+ try {
37204
+ db.close();
37205
+ } catch {
37206
+ }
37059
37207
  }
37060
- return toError(`\u672A\u77E5\u6A21\u5F0F: ${mode}`);
37061
37208
  } catch (e) {
37062
37209
  return toError(e);
37063
37210
  }
@@ -37213,7 +37360,7 @@ async function startStdio(server, version2, auth, readOnly, skipped, skipLog) {
37213
37360
  await server.connect(transport);
37214
37361
  }
37215
37362
  async function main() {
37216
- const VERSION = "0.2.50";
37363
+ const VERSION = "0.2.51";
37217
37364
  const auth = getAuth();
37218
37365
  const mode = resolveTransportMode();
37219
37366
  const exec = resolveExecutionMode();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hvip-mcp-server",
3
- "version": "0.2.50",
3
+ "version": "0.2.51",
4
4
  "description": "hvip MCP Server — 365 工具覆盖 97.7% OKX REST API,含交易/行情/资金/策略/预测市场/技术指标/Smart Money(非 OKX 官方产品)",
5
5
  "homepage": "https://github.com/okx-wallet-H/hvip-mcp",
6
6
  "repository": {
@@ -42,7 +42,6 @@
42
42
  "typecheck": "tsc --noEmit"
43
43
  },
44
44
  "dependencies": {
45
- "@colbymchenry/codegraph": "^1.0.1",
46
45
  "@modelcontextprotocol/sdk": "^1.29.0",
47
46
  "dotenv": "^16.4.0",
48
47
  "ws": "^8.21.0",