@aiready/ast-mcp-server 0.4.9 → 0.7.0

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
@@ -59,6 +59,9 @@ var CheckSymbolGroundingSchema = z.object({
59
59
  symbol: z.string().describe("Symbol name to assess grounding for"),
60
60
  path: z.string().describe("Project root directory")
61
61
  });
62
+ var CodebaseAuditSchema = z.object({
63
+ path: z.string().describe("Project root directory to audit for debt and bloat")
64
+ });
62
65
 
63
66
  // src/adapters/typescript-adapter.ts
64
67
  import { Node as Node2 } from "ts-morph";
@@ -442,9 +445,9 @@ var TypeScriptAdapter = class {
442
445
  await symbolIndex.buildIndex(searchPath);
443
446
  }
444
447
  }
445
- async resolveDefinition(symbolName, path5) {
446
- validateWorkspacePath(path5);
447
- await this.ensureIndex(path5);
448
+ async resolveDefinition(symbolName, path6) {
449
+ validateWorkspacePath(path6);
450
+ await this.ensureIndex(path6);
448
451
  const indexHits = symbolIndex.lookup(symbolName);
449
452
  if (indexHits.length > 0) {
450
453
  const results = [];
@@ -472,33 +475,33 @@ var TypeScriptAdapter = class {
472
475
  }
473
476
  return results;
474
477
  }
475
- if (fs3.statSync(path5).isDirectory()) {
478
+ if (fs3.statSync(path6).isDirectory()) {
476
479
  return [];
477
480
  }
478
- const tsconfig = await projectManager.findNearestTsConfig(path5);
481
+ const tsconfig = await projectManager.findNearestTsConfig(path6);
479
482
  if (!tsconfig) return [];
480
483
  try {
481
484
  const result = await this.pool.execute(
482
485
  "resolve_definition",
483
486
  {
484
487
  tsconfig,
485
- file: path5,
488
+ file: path6,
486
489
  symbol: symbolName
487
490
  }
488
491
  );
489
492
  return result;
490
493
  } catch {
491
494
  const project = projectManager.ensureProject(tsconfig);
492
- const sourceFile = project.addSourceFileAtPathIfExists(path5);
495
+ const sourceFile = project.addSourceFileAtPathIfExists(path6);
493
496
  if (!sourceFile) return [];
494
497
  const exported = sourceFile.getExportedDeclarations().get(symbolName);
495
498
  if (!exported) return [];
496
499
  return exported.map((decl) => this.mapToDefinitionLocation(decl));
497
500
  }
498
501
  }
499
- async findReferences(symbolName, path5, limit = 50, offset = 0) {
500
- validateWorkspacePath(path5);
501
- await this.ensureIndex(path5);
502
+ async findReferences(symbolName, path6, limit = 50, offset = 0) {
503
+ validateWorkspacePath(path6);
504
+ await this.ensureIndex(path6);
502
505
  const hits = symbolIndex.lookup(symbolName);
503
506
  if (hits.length === 0) return { references: [], total_count: 0 };
504
507
  const hit = hits[0];
@@ -511,7 +514,7 @@ var TypeScriptAdapter = class {
511
514
  const { searchCode: searchCode2 } = await import("./search-code-63QOEFQN.js");
512
515
  const searchResults = await searchCode2(
513
516
  symbolName,
514
- path5,
517
+ path6,
515
518
  "**/*.{ts,tsx,js,jsx}",
516
519
  1e3,
517
520
  false
@@ -548,9 +551,9 @@ var TypeScriptAdapter = class {
548
551
  total_count: unique.length
549
552
  };
550
553
  }
551
- async findImplementations(symbolName, path5, limit = 50, offset = 0) {
552
- validateWorkspacePath(path5);
553
- await this.ensureIndex(path5);
554
+ async findImplementations(symbolName, path6, limit = 50, offset = 0) {
555
+ validateWorkspacePath(path6);
556
+ await this.ensureIndex(path6);
554
557
  const hits = symbolIndex.lookup(symbolName);
555
558
  if (hits.length === 0) return { implementations: [], total_count: 0 };
556
559
  const hit = hits[0];
@@ -581,7 +584,7 @@ var TypeScriptAdapter = class {
581
584
  const { searchCode: searchCode2 } = await import("./search-code-63QOEFQN.js");
582
585
  const searchResults = await searchCode2(
583
586
  symbolName,
584
- path5,
587
+ path6,
585
588
  "**/*.{ts,tsx,js,jsx}",
586
589
  1e3,
587
590
  false
@@ -760,31 +763,31 @@ var TypeScriptAdapter = class {
760
763
  var typescriptAdapter = new TypeScriptAdapter();
761
764
 
762
765
  // src/utils/tool-utils.ts
763
- async function wrapAdapterCall(methodName, symbol, path5, ...args) {
766
+ async function wrapAdapterCall(methodName, symbol, path6, ...args) {
764
767
  const method = typescriptAdapter[methodName];
765
- return await method.apply(typescriptAdapter, [symbol, path5, ...args]);
768
+ return await method.apply(typescriptAdapter, [symbol, path6, ...args]);
766
769
  }
767
770
 
768
771
  // src/tools/resolve-definition.ts
769
- async function resolveDefinition(symbol, path5) {
772
+ async function resolveDefinition(symbol, path6) {
770
773
  return await wrapAdapterCall(
771
774
  "resolveDefinition",
772
775
  symbol,
773
- path5
776
+ path6
774
777
  );
775
778
  }
776
779
 
777
780
  // src/tools/find-references.ts
778
- async function findReferences(symbol, path5, limit = 50, offset = 0) {
779
- return await wrapAdapterCall("findReferences", symbol, path5, limit, offset);
781
+ async function findReferences(symbol, path6, limit = 50, offset = 0) {
782
+ return await wrapAdapterCall("findReferences", symbol, path6, limit, offset);
780
783
  }
781
784
 
782
785
  // src/tools/find-implementations.ts
783
- async function findImplementations(symbol, path5, limit = 50, offset = 0) {
786
+ async function findImplementations(symbol, path6, limit = 50, offset = 0) {
784
787
  return await wrapAdapterCall(
785
788
  "findImplementations",
786
789
  symbol,
787
- path5,
790
+ path6,
788
791
  limit,
789
792
  offset
790
793
  );
@@ -824,8 +827,8 @@ async function getSymbolDocs(symbol, filePath) {
824
827
  }
825
828
 
826
829
  // src/tools/build-symbol-index.ts
827
- async function buildSymbolIndex(path5) {
828
- return await symbolIndex.buildIndex(path5);
830
+ async function buildSymbolIndex(path6) {
831
+ return await symbolIndex.buildIndex(path6);
829
832
  }
830
833
 
831
834
  // src/tools/call-hierarchy.ts
@@ -981,6 +984,115 @@ async function checkSymbolGrounding(symbol, filePath) {
981
984
  };
982
985
  }
983
986
 
987
+ // src/tools/codebase-audit.ts
988
+ import { execFile } from "child_process";
989
+ import { promisify } from "util";
990
+ import { rgPath } from "@vscode/ripgrep";
991
+ import * as fs4 from "fs";
992
+ import * as path5 from "path";
993
+ var execFileAsync = promisify(execFile);
994
+ async function codebaseAudit(rootDir) {
995
+ const safePath = validateWorkspacePath(rootDir);
996
+ let debtMarkers = 0;
997
+ try {
998
+ const { stdout } = await execFileAsync(rgPath, [
999
+ "--count-matches",
1000
+ "--fixed-strings",
1001
+ "-e",
1002
+ "TODO",
1003
+ "-e",
1004
+ "FIXME",
1005
+ "--glob",
1006
+ "!**/node_modules/**",
1007
+ "--glob",
1008
+ "!**/.git/**",
1009
+ "--glob",
1010
+ "!**/dist/**",
1011
+ safePath
1012
+ ]);
1013
+ const lines = stdout.split("\n").filter(Boolean);
1014
+ for (const line of lines) {
1015
+ const match = line.match(/:(\d+)$/);
1016
+ if (match) {
1017
+ debtMarkers += parseInt(match[1], 10);
1018
+ }
1019
+ }
1020
+ } catch (error) {
1021
+ if (error.code !== 1) {
1022
+ console.error("[Audit] Error counting debt markers:", error);
1023
+ }
1024
+ }
1025
+ const emptyDirs = [];
1026
+ const scanEmpty = (dir) => {
1027
+ const files = fs4.readdirSync(dir);
1028
+ if (files.length === 0) {
1029
+ emptyDirs.push(path5.relative(safePath, dir));
1030
+ return;
1031
+ }
1032
+ for (const file of files) {
1033
+ const fullPath = path5.join(dir, file);
1034
+ if (fs4.statSync(fullPath).isDirectory()) {
1035
+ if (["node_modules", ".git", "dist", ".sst", ".turbo", ".next"].includes(
1036
+ file
1037
+ ))
1038
+ continue;
1039
+ scanEmpty(fullPath);
1040
+ }
1041
+ }
1042
+ };
1043
+ scanEmpty(safePath);
1044
+ const orphanedFiles = [];
1045
+ const allFiles = [];
1046
+ const collectFiles = (dir) => {
1047
+ const files = fs4.readdirSync(dir);
1048
+ for (const file of files) {
1049
+ const fullPath = path5.join(dir, file);
1050
+ if (fs4.statSync(fullPath).isDirectory()) {
1051
+ if (["node_modules", ".git", "dist", ".sst", ".turbo", ".next"].includes(
1052
+ file
1053
+ ))
1054
+ continue;
1055
+ collectFiles(fullPath);
1056
+ } else if (file.endsWith(".ts") || file.endsWith(".js") || file.endsWith(".tsx") || file.endsWith(".jsx")) {
1057
+ allFiles.push(fullPath);
1058
+ }
1059
+ }
1060
+ };
1061
+ collectFiles(safePath);
1062
+ for (const file of allFiles) {
1063
+ const base = path5.basename(file, path5.extname(file));
1064
+ if (base === "index" || base.endsWith(".test") || base.endsWith(".spec") || base === "sst.config")
1065
+ continue;
1066
+ let referenced = false;
1067
+ try {
1068
+ const { status } = await execFileAsync(rgPath, [
1069
+ "--quiet",
1070
+ "--fixed-strings",
1071
+ "--word-regexp",
1072
+ "--glob",
1073
+ `!${path5.relative(safePath, file)}`,
1074
+ "--glob",
1075
+ "!**/node_modules/**",
1076
+ "--glob",
1077
+ "!**/.git/**",
1078
+ base,
1079
+ safePath
1080
+ ]);
1081
+ if (status === 0) referenced = true;
1082
+ } catch (e) {
1083
+ if (e.code === 0) referenced = true;
1084
+ }
1085
+ if (!referenced) {
1086
+ orphanedFiles.push(path5.relative(safePath, file));
1087
+ }
1088
+ }
1089
+ return {
1090
+ debtMarkers,
1091
+ emptyDirs,
1092
+ orphanedFiles
1093
+ };
1094
+ }
1095
+
984
1096
  // src/index.ts
985
1097
  import {
986
1098
  ListResourcesRequestSchema,
@@ -1169,6 +1281,20 @@ var ASTExplorerServer = class {
1169
1281
  },
1170
1282
  required: ["symbol", "path"]
1171
1283
  }
1284
+ },
1285
+ {
1286
+ name: "codebase_audit",
1287
+ description: "Performs a codebase-level audit for technical debt (TODOs) and bloat (empty dirs, orphans).",
1288
+ inputSchema: {
1289
+ type: "object",
1290
+ properties: {
1291
+ path: {
1292
+ type: "string",
1293
+ description: "Project root directory to audit"
1294
+ }
1295
+ },
1296
+ required: ["path"]
1297
+ }
1172
1298
  }
1173
1299
  ]
1174
1300
  };
@@ -1178,8 +1304,8 @@ var ASTExplorerServer = class {
1178
1304
  try {
1179
1305
  switch (name) {
1180
1306
  case "resolve_definition": {
1181
- const { symbol, path: path5 } = ResolveDefinitionSchema.parse(args);
1182
- const results = await resolveDefinition(symbol, path5);
1307
+ const { symbol, path: path6 } = ResolveDefinitionSchema.parse(args);
1308
+ const results = await resolveDefinition(symbol, path6);
1183
1309
  return {
1184
1310
  content: [
1185
1311
  { type: "text", text: JSON.stringify(results, null, 2) }
@@ -1187,8 +1313,8 @@ var ASTExplorerServer = class {
1187
1313
  };
1188
1314
  }
1189
1315
  case "find_references": {
1190
- const { symbol, path: path5, limit, offset } = FindReferencesSchema.parse(args);
1191
- const results = await findReferences(symbol, path5, limit, offset);
1316
+ const { symbol, path: path6, limit, offset } = FindReferencesSchema.parse(args);
1317
+ const results = await findReferences(symbol, path6, limit, offset);
1192
1318
  return {
1193
1319
  content: [
1194
1320
  { type: "text", text: JSON.stringify(results, null, 2) }
@@ -1196,10 +1322,10 @@ var ASTExplorerServer = class {
1196
1322
  };
1197
1323
  }
1198
1324
  case "find_implementations": {
1199
- const { symbol, path: path5, limit, offset } = FindImplementationsSchema.parse(args);
1325
+ const { symbol, path: path6, limit, offset } = FindImplementationsSchema.parse(args);
1200
1326
  const results = await findImplementations(
1201
1327
  symbol,
1202
- path5,
1328
+ path6,
1203
1329
  limit,
1204
1330
  offset
1205
1331
  );
@@ -1219,10 +1345,10 @@ var ASTExplorerServer = class {
1219
1345
  };
1220
1346
  }
1221
1347
  case "search_code": {
1222
- const { pattern, path: path5, filePattern, limit, offset, regex } = SearchCodeSchema.parse(args);
1348
+ const { pattern, path: path6, filePattern, limit, offset, regex } = SearchCodeSchema.parse(args);
1223
1349
  const results = await searchCode(
1224
1350
  pattern,
1225
- path5,
1351
+ path6,
1226
1352
  filePattern,
1227
1353
  limit,
1228
1354
  regex,
@@ -1235,22 +1361,22 @@ var ASTExplorerServer = class {
1235
1361
  };
1236
1362
  }
1237
1363
  case "get_symbol_docs": {
1238
- const { symbol, path: path5 } = GetSymbolDocsSchema.parse(args);
1239
- const docs = await getSymbolDocs(symbol, path5);
1364
+ const { symbol, path: path6 } = GetSymbolDocsSchema.parse(args);
1365
+ const docs = await getSymbolDocs(symbol, path6);
1240
1366
  return {
1241
1367
  content: [{ type: "text", text: JSON.stringify(docs, null, 2) }]
1242
1368
  };
1243
1369
  }
1244
1370
  case "build_symbol_index": {
1245
- const { path: path5 } = BuildSymbolIndexSchema.parse(args);
1246
- const stats = await buildSymbolIndex(path5);
1371
+ const { path: path6 } = BuildSymbolIndexSchema.parse(args);
1372
+ const stats = await buildSymbolIndex(path6);
1247
1373
  return {
1248
1374
  content: [{ type: "text", text: JSON.stringify(stats, null, 2) }]
1249
1375
  };
1250
1376
  }
1251
1377
  case "get_call_hierarchy": {
1252
- const { symbol, path: path5, direction } = GetCallHierarchySchema.parse(args);
1253
- const hierarchy = await getCallHierarchy(symbol, path5, direction);
1378
+ const { symbol, path: path6, direction } = GetCallHierarchySchema.parse(args);
1379
+ const hierarchy = await getCallHierarchy(symbol, path6, direction);
1254
1380
  return {
1255
1381
  content: [
1256
1382
  { type: "text", text: JSON.stringify(hierarchy, null, 2) }
@@ -1258,8 +1384,17 @@ var ASTExplorerServer = class {
1258
1384
  };
1259
1385
  }
1260
1386
  case "check_symbol_grounding": {
1261
- const { symbol, path: path5 } = CheckSymbolGroundingSchema.parse(args);
1262
- const result = await checkSymbolGrounding(symbol, path5);
1387
+ const { symbol, path: path6 } = CheckSymbolGroundingSchema.parse(args);
1388
+ const result = await checkSymbolGrounding(symbol, path6);
1389
+ return {
1390
+ content: [
1391
+ { type: "text", text: JSON.stringify(result, null, 2) }
1392
+ ]
1393
+ };
1394
+ }
1395
+ case "codebase_audit": {
1396
+ const { path: path6 } = CodebaseAuditSchema.parse(args);
1397
+ const result = await codebaseAudit(path6);
1263
1398
  return {
1264
1399
  content: [
1265
1400
  { type: "text", text: JSON.stringify(result, null, 2) }