@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.cjs +180 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +176 -41
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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,
|
|
446
|
-
validateWorkspacePath(
|
|
447
|
-
await this.ensureIndex(
|
|
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(
|
|
478
|
+
if (fs3.statSync(path6).isDirectory()) {
|
|
476
479
|
return [];
|
|
477
480
|
}
|
|
478
|
-
const tsconfig = await projectManager.findNearestTsConfig(
|
|
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:
|
|
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(
|
|
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,
|
|
500
|
-
validateWorkspacePath(
|
|
501
|
-
await this.ensureIndex(
|
|
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
|
-
|
|
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,
|
|
552
|
-
validateWorkspacePath(
|
|
553
|
-
await this.ensureIndex(
|
|
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
|
-
|
|
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,
|
|
766
|
+
async function wrapAdapterCall(methodName, symbol, path6, ...args) {
|
|
764
767
|
const method = typescriptAdapter[methodName];
|
|
765
|
-
return await method.apply(typescriptAdapter, [symbol,
|
|
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,
|
|
772
|
+
async function resolveDefinition(symbol, path6) {
|
|
770
773
|
return await wrapAdapterCall(
|
|
771
774
|
"resolveDefinition",
|
|
772
775
|
symbol,
|
|
773
|
-
|
|
776
|
+
path6
|
|
774
777
|
);
|
|
775
778
|
}
|
|
776
779
|
|
|
777
780
|
// src/tools/find-references.ts
|
|
778
|
-
async function findReferences(symbol,
|
|
779
|
-
return await wrapAdapterCall("findReferences", symbol,
|
|
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,
|
|
786
|
+
async function findImplementations(symbol, path6, limit = 50, offset = 0) {
|
|
784
787
|
return await wrapAdapterCall(
|
|
785
788
|
"findImplementations",
|
|
786
789
|
symbol,
|
|
787
|
-
|
|
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(
|
|
828
|
-
return await symbolIndex.buildIndex(
|
|
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:
|
|
1182
|
-
const results = await resolveDefinition(symbol,
|
|
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:
|
|
1191
|
-
const results = await findReferences(symbol,
|
|
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:
|
|
1325
|
+
const { symbol, path: path6, limit, offset } = FindImplementationsSchema.parse(args);
|
|
1200
1326
|
const results = await findImplementations(
|
|
1201
1327
|
symbol,
|
|
1202
|
-
|
|
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:
|
|
1348
|
+
const { pattern, path: path6, filePattern, limit, offset, regex } = SearchCodeSchema.parse(args);
|
|
1223
1349
|
const results = await searchCode(
|
|
1224
1350
|
pattern,
|
|
1225
|
-
|
|
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:
|
|
1239
|
-
const docs = await getSymbolDocs(symbol,
|
|
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:
|
|
1246
|
-
const stats = await buildSymbolIndex(
|
|
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:
|
|
1253
|
-
const hierarchy = await getCallHierarchy(symbol,
|
|
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:
|
|
1262
|
-
const result = await checkSymbolGrounding(symbol,
|
|
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) }
|