@aiready/ast-mcp-server 0.1.0 → 0.1.1

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 ADDED
@@ -0,0 +1,771 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ ASTExplorerServer: () => ASTExplorerServer
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+ var import_server = require("@modelcontextprotocol/sdk/server/index.js");
37
+ var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
38
+ var import_types = require("@modelcontextprotocol/sdk/types.js");
39
+
40
+ // src/schemas.ts
41
+ var import_zod = require("zod");
42
+ var ResolveDefinitionSchema = import_zod.z.object({
43
+ symbol: import_zod.z.string().describe(
44
+ "Symbol name to resolve (function, class, type, interface, etc.)"
45
+ ),
46
+ path: import_zod.z.string().describe("Project root or target directory")
47
+ });
48
+ var FindReferencesSchema = import_zod.z.object({
49
+ symbol: import_zod.z.string().describe("Symbol name to find references for"),
50
+ path: import_zod.z.string().describe("Project root directory"),
51
+ limit: import_zod.z.number().optional().default(50).describe("Max results per page (default 50)"),
52
+ offset: import_zod.z.number().optional().default(0).describe("Pagination offset")
53
+ });
54
+ var FindImplementationsSchema = import_zod.z.object({
55
+ symbol: import_zod.z.string().describe("Interface or abstract class name to find implementations for"),
56
+ path: import_zod.z.string().describe("Project root directory"),
57
+ limit: import_zod.z.number().optional().default(50).describe("Max results per page"),
58
+ offset: import_zod.z.number().optional().default(0).describe("Pagination offset")
59
+ });
60
+ var GetFileStructureSchema = import_zod.z.object({
61
+ file: import_zod.z.string().describe("Absolute path to the file to analyze")
62
+ });
63
+ var SearchCodeSchema = import_zod.z.object({
64
+ pattern: import_zod.z.string().describe("Search pattern (regex)"),
65
+ path: import_zod.z.string().describe("Directory to search in"),
66
+ filePattern: import_zod.z.string().optional().describe('Glob filter (e.g., "*.ts")'),
67
+ limit: import_zod.z.number().optional().default(50).describe("Max matches to return")
68
+ });
69
+ var GetSymbolDocsSchema = import_zod.z.object({
70
+ symbol: import_zod.z.string().describe("Symbol name to get documentation for"),
71
+ path: import_zod.z.string().describe("Project root directory")
72
+ });
73
+ var BuildSymbolIndexSchema = import_zod.z.object({
74
+ path: import_zod.z.string().describe("Project root directory to index")
75
+ });
76
+
77
+ // src/adapters/typescript-adapter.ts
78
+ var import_ts_morph2 = require("ts-morph");
79
+
80
+ // src/project-manager.ts
81
+ var import_ts_morph = require("ts-morph");
82
+ var import_path = __toESM(require("path"), 1);
83
+ var import_fs = __toESM(require("fs"), 1);
84
+ var import_glob = require("glob");
85
+ var ProjectManager = class {
86
+ projects = /* @__PURE__ */ new Map();
87
+ tsconfigCache = /* @__PURE__ */ new Map();
88
+ /**
89
+ * Find all tsconfig.json files in a directory (recursive)
90
+ */
91
+ async findTsConfigs(rootDir) {
92
+ if (this.tsconfigCache.has(rootDir)) {
93
+ return this.tsconfigCache.get(rootDir);
94
+ }
95
+ const configs = await (0, import_glob.glob)("**/tsconfig.json", {
96
+ cwd: rootDir,
97
+ absolute: true,
98
+ ignore: ["**/node_modules/**", "**/dist/**"]
99
+ });
100
+ this.tsconfigCache.set(rootDir, configs);
101
+ return configs;
102
+ }
103
+ /**
104
+ * Get or create a Project for a specific file path
105
+ */
106
+ async getProjectForFile(filePath) {
107
+ const tsconfigPath = await this.findNearestTsConfig(filePath);
108
+ if (!tsconfigPath) return void 0;
109
+ return this.getOrCreateProject(tsconfigPath);
110
+ }
111
+ /**
112
+ * Get or create a Project for a tsconfig path
113
+ */
114
+ getOrCreateProject(tsconfigPath) {
115
+ if (this.projects.has(tsconfigPath)) {
116
+ return this.projects.get(tsconfigPath);
117
+ }
118
+ const project = new import_ts_morph.Project({
119
+ tsConfigFilePath: tsconfigPath,
120
+ skipAddingFilesFromTsConfig: false
121
+ });
122
+ this.projects.set(tsconfigPath, project);
123
+ return project;
124
+ }
125
+ /**
126
+ * Find the nearest tsconfig.json for a file
127
+ */
128
+ async findNearestTsConfig(filePath) {
129
+ let currentDir = import_path.default.dirname(filePath);
130
+ const root = import_path.default.parse(currentDir).root;
131
+ while (currentDir !== root) {
132
+ const tsconfigPath = import_path.default.join(currentDir, "tsconfig.json");
133
+ if (import_fs.default.existsSync(tsconfigPath)) {
134
+ return tsconfigPath;
135
+ }
136
+ currentDir = import_path.default.dirname(currentDir);
137
+ }
138
+ return void 0;
139
+ }
140
+ /**
141
+ * Get all projects that might contain a file or serve a path
142
+ */
143
+ async getProjectsForPath(rootDir) {
144
+ const configs = await this.findTsConfigs(rootDir);
145
+ return configs.map((config) => this.getOrCreateProject(config));
146
+ }
147
+ /**
148
+ * Dispose all projects to free memory
149
+ */
150
+ disposeAll() {
151
+ for (const project of this.projects.values()) {
152
+ project.getLanguageService().compilerObject.dispose();
153
+ }
154
+ this.projects.clear();
155
+ }
156
+ };
157
+ var projectManager = new ProjectManager();
158
+
159
+ // src/adapters/typescript-adapter.ts
160
+ var TypeScriptAdapter = class {
161
+ /**
162
+ * Resolve definition of a symbol at a path
163
+ */
164
+ async resolveDefinition(symbolName, path2) {
165
+ const projects = await projectManager.getProjectsForPath(path2);
166
+ const results = [];
167
+ for (const project of projects) {
168
+ const sourceFiles = project.getSourceFiles();
169
+ for (const sourceFile of sourceFiles) {
170
+ const nodes = sourceFile.getDescendantsOfKind(import_ts_morph2.SyntaxKind.Identifier).filter((id) => id.getText() === symbolName);
171
+ for (const node of nodes) {
172
+ const definitions = node.getDefinitionNodes();
173
+ for (const defNode of definitions) {
174
+ results.push(this.mapToDefinitionLocation(defNode));
175
+ }
176
+ }
177
+ }
178
+ }
179
+ return this.deduplicateLocations(results);
180
+ }
181
+ /**
182
+ * Find references to a symbol
183
+ */
184
+ async findReferences(symbolName, path2, limit = 50, offset = 0) {
185
+ const projects = await projectManager.getProjectsForPath(path2);
186
+ const results = [];
187
+ for (const project of projects) {
188
+ const sourceFiles = project.getSourceFiles();
189
+ for (const sourceFile of sourceFiles) {
190
+ const nodes = sourceFile.getDescendantsOfKind(import_ts_morph2.SyntaxKind.Identifier).filter((id) => id.getText() === symbolName);
191
+ for (const node of nodes) {
192
+ const referencedSymbols = node.findReferences();
193
+ for (const referencedSymbol of referencedSymbols) {
194
+ const references = referencedSymbol.getReferences();
195
+ for (const ref of references) {
196
+ const sourceFile2 = ref.getSourceFile();
197
+ const lineAndColumn = sourceFile2.getLineAndColumnAtPos(
198
+ ref.getTextSpan().getStart()
199
+ );
200
+ results.push({
201
+ file: sourceFile2.getFilePath(),
202
+ line: lineAndColumn.line,
203
+ column: lineAndColumn.column,
204
+ text: ref.getNode().getParent()?.getText() || ref.getNode().getText()
205
+ });
206
+ }
207
+ }
208
+ }
209
+ }
210
+ }
211
+ const uniqueResults = this.deduplicateLocations(results);
212
+ return {
213
+ references: uniqueResults.slice(offset, offset + limit),
214
+ total_count: uniqueResults.length
215
+ };
216
+ }
217
+ /**
218
+ * Find implementations for a symbol
219
+ */
220
+ async findImplementations(symbolName, path2, limit = 50, offset = 0) {
221
+ const projects = await projectManager.getProjectsForPath(path2);
222
+ const results = [];
223
+ for (const project of projects) {
224
+ const sourceFiles = project.getSourceFiles();
225
+ for (const sourceFile of sourceFiles) {
226
+ const nodes = sourceFile.getDescendantsOfKind(import_ts_morph2.SyntaxKind.Identifier).filter((id) => id.getText() === symbolName);
227
+ for (const node of nodes) {
228
+ const implementations = node.getImplementations();
229
+ for (const impl of implementations) {
230
+ const sourceFile2 = impl.getSourceFile();
231
+ const lineAndColumn = sourceFile2.getLineAndColumnAtPos(
232
+ impl.getTextSpan().getStart()
233
+ );
234
+ results.push({
235
+ file: sourceFile2.getFilePath(),
236
+ line: lineAndColumn.line,
237
+ column: lineAndColumn.column,
238
+ text: impl.getNode().getParent()?.getText() || impl.getNode().getText()
239
+ });
240
+ }
241
+ }
242
+ }
243
+ }
244
+ const uniqueResults = this.deduplicateLocations(results);
245
+ return {
246
+ implementations: uniqueResults.slice(offset, offset + limit),
247
+ total_count: uniqueResults.length
248
+ };
249
+ }
250
+ /**
251
+ * Get file structure overview
252
+ */
253
+ async getFileStructure(filePath) {
254
+ const project = await projectManager.getProjectForFile(filePath);
255
+ if (!project) return void 0;
256
+ const sourceFile = project.getSourceFile(filePath);
257
+ if (!sourceFile) return void 0;
258
+ const structure = {
259
+ file: filePath,
260
+ imports: sourceFile.getImportDeclarations().map((imp) => ({
261
+ module: imp.getModuleSpecifierValue(),
262
+ names: imp.getNamedImports().map((ni) => ni.getName())
263
+ })),
264
+ exports: sourceFile.getExportSymbols().map((sym) => ({
265
+ name: sym.getName(),
266
+ kind: this.mapSymbolKind(sym)
267
+ })),
268
+ classes: sourceFile.getClasses().map((cls) => this.mapToClassInfo(cls)),
269
+ functions: sourceFile.getFunctions().map((fn) => this.mapToFunctionInfo(fn)),
270
+ interfaces: sourceFile.getInterfaces().map((itf) => this.mapToInterfaceInfo(itf)),
271
+ typeAliases: sourceFile.getTypeAliases().map((ta) => this.mapToTypeAliasInfo(ta)),
272
+ enums: sourceFile.getEnums().map((enm) => this.mapToEnumInfo(enm))
273
+ };
274
+ return structure;
275
+ }
276
+ /**
277
+ * Helper: Map ts-morph Node (Declaration) to DefinitionLocation
278
+ */
279
+ mapToDefinitionLocation(node) {
280
+ const sourceFile = node.getSourceFile();
281
+ const lineAndColumn = sourceFile.getLineAndColumnAtPos(node.getStart());
282
+ return {
283
+ file: sourceFile.getFilePath(),
284
+ line: lineAndColumn.line,
285
+ column: lineAndColumn.column,
286
+ kind: this.mapNodeToSymbolKind(node),
287
+ snippet: node.getText(),
288
+ documentation: this.getJsDoc(node)
289
+ };
290
+ }
291
+ /**
292
+ * Helper: Map ts-morph Node to SymbolKind
293
+ */
294
+ mapNodeToSymbolKind(node) {
295
+ if (import_ts_morph2.Node.isClassDeclaration(node)) return "class";
296
+ if (import_ts_morph2.Node.isFunctionDeclaration(node)) return "function";
297
+ if (import_ts_morph2.Node.isInterfaceDeclaration(node)) return "interface";
298
+ if (import_ts_morph2.Node.isTypeAliasDeclaration(node)) return "type_alias";
299
+ if (import_ts_morph2.Node.isEnumDeclaration(node)) return "enum";
300
+ if (import_ts_morph2.Node.isVariableDeclaration(node)) return "variable";
301
+ if (import_ts_morph2.Node.isMethodDeclaration(node)) return "method";
302
+ if (import_ts_morph2.Node.isPropertyDeclaration(node)) return "property";
303
+ if (import_ts_morph2.Node.isParameterDeclaration(node)) return "parameter";
304
+ return "variable";
305
+ }
306
+ /**
307
+ * Helper: Map Symbol to SymbolKind
308
+ */
309
+ mapSymbolKind(symbol) {
310
+ const decls = symbol.getDeclarations();
311
+ if (decls.length > 0) return this.mapNodeToSymbolKind(decls[0]);
312
+ return "variable";
313
+ }
314
+ /**
315
+ * Helper: Get JSDoc from Node
316
+ */
317
+ getJsDoc(node) {
318
+ if (import_ts_morph2.Node.isJSDocable(node)) {
319
+ const docs = node.getJsDocs();
320
+ if (docs.length > 0) {
321
+ return docs[0].getCommentText();
322
+ }
323
+ }
324
+ return void 0;
325
+ }
326
+ /**
327
+ * Helper: Get full JSDoc info (with tags)
328
+ */
329
+ getSymbolDocs(node) {
330
+ if (import_ts_morph2.Node.isJSDocable(node)) {
331
+ const docs = node.getJsDocs();
332
+ if (docs.length > 0) {
333
+ const doc = docs[0];
334
+ return {
335
+ documentation: doc.getCommentText(),
336
+ tags: doc.getTags().map((tag) => ({
337
+ name: tag.getTagName(),
338
+ text: tag.getCommentText() || ""
339
+ }))
340
+ };
341
+ }
342
+ }
343
+ return void 0;
344
+ }
345
+ mapToClassInfo(cls) {
346
+ return {
347
+ name: cls.getName() || "anonymous",
348
+ ...this.getSymbolDocs(cls),
349
+ methods: cls.getMethods().map((m) => this.mapToFunctionInfo(m)),
350
+ properties: cls.getProperties().map((p) => this.mapToPropertyInfo(p))
351
+ };
352
+ }
353
+ mapToFunctionInfo(fn) {
354
+ return {
355
+ name: fn.getName() || "anonymous",
356
+ ...this.getSymbolDocs(fn),
357
+ params: fn.getParameters().map((p) => ({
358
+ name: p.getName(),
359
+ type: p.getType().getText()
360
+ })),
361
+ returnType: fn.getReturnType().getText()
362
+ };
363
+ }
364
+ mapToPropertyInfo(p) {
365
+ return {
366
+ name: p.getName(),
367
+ type: p.getType().getText(),
368
+ ...this.getSymbolDocs(p)
369
+ };
370
+ }
371
+ mapToInterfaceInfo(itf) {
372
+ return {
373
+ name: itf.getName(),
374
+ ...this.getSymbolDocs(itf),
375
+ properties: itf.getProperties().map((p) => this.mapToPropertyInfo(p)),
376
+ methods: itf.getMethods().map((m) => this.mapToFunctionInfo(m))
377
+ };
378
+ }
379
+ mapToTypeAliasInfo(ta) {
380
+ return {
381
+ name: ta.getName(),
382
+ type: ta.getType().getText(),
383
+ ...this.getSymbolDocs(ta)
384
+ };
385
+ }
386
+ mapToEnumInfo(enm) {
387
+ return {
388
+ name: enm.getName(),
389
+ ...this.getSymbolDocs(enm),
390
+ members: enm.getMembers().map((m) => m.getName())
391
+ };
392
+ }
393
+ /**
394
+ * Helper: Deduplicate locations
395
+ */
396
+ deduplicateLocations(locations) {
397
+ const seen = /* @__PURE__ */ new Set();
398
+ return locations.filter((loc) => {
399
+ const key = `${loc.file}:${loc.line}:${loc.column}`;
400
+ if (seen.has(key)) return false;
401
+ seen.add(key);
402
+ return true;
403
+ });
404
+ }
405
+ };
406
+ var typescriptAdapter = new TypeScriptAdapter();
407
+
408
+ // src/tools/resolve-definition.ts
409
+ async function resolveDefinition(symbol, path2) {
410
+ return await typescriptAdapter.resolveDefinition(symbol, path2);
411
+ }
412
+
413
+ // src/tools/find-references.ts
414
+ async function findReferences(symbol, path2, limit = 50, offset = 0) {
415
+ return await typescriptAdapter.findReferences(symbol, path2, limit, offset);
416
+ }
417
+
418
+ // src/tools/find-implementations.ts
419
+ async function findImplementations(symbol, path2, limit = 50, offset = 0) {
420
+ return await typescriptAdapter.findImplementations(
421
+ symbol,
422
+ path2,
423
+ limit,
424
+ offset
425
+ );
426
+ }
427
+
428
+ // src/tools/get-file-structure.ts
429
+ async function getFileStructure(file) {
430
+ return await typescriptAdapter.getFileStructure(file);
431
+ }
432
+
433
+ // src/tools/search-code.ts
434
+ var import_child_process = require("child_process");
435
+ var import_util = require("util");
436
+ var import_ripgrep = require("@vscode/ripgrep");
437
+ var execFileAsync = (0, import_util.promisify)(import_child_process.execFile);
438
+ async function searchCode(pattern, searchPath, filePattern, limit = 50) {
439
+ const args = [
440
+ "--json",
441
+ "--max-count",
442
+ limit.toString(),
443
+ "--fixed-strings",
444
+ // Default to fixed strings unless we want regex
445
+ pattern,
446
+ searchPath
447
+ ];
448
+ if (filePattern) {
449
+ args.push("--glob", filePattern);
450
+ }
451
+ args.push("--glob", "!**/node_modules/**");
452
+ args.push("--glob", "!**/dist/**");
453
+ args.push("--glob", "!**/.git/**");
454
+ try {
455
+ const { stdout } = await execFileAsync(import_ripgrep.rgPath, args);
456
+ const lines = stdout.split("\n").filter(Boolean);
457
+ const results = [];
458
+ for (const line of lines) {
459
+ const data = JSON.parse(line);
460
+ if (data.type === "match") {
461
+ const file = data.data.path.text;
462
+ const lineNumber = data.data.line_number;
463
+ const submatches = data.data.submatches;
464
+ for (const submatch of submatches) {
465
+ results.push({
466
+ file,
467
+ line: lineNumber,
468
+ column: submatch.start,
469
+ text: data.data.lines.text.trim()
470
+ });
471
+ }
472
+ }
473
+ }
474
+ return results.slice(0, limit);
475
+ } catch (error) {
476
+ if (error.code === 1) {
477
+ return [];
478
+ }
479
+ throw error;
480
+ }
481
+ }
482
+
483
+ // src/tools/get-symbol-docs.ts
484
+ var import_ts_morph3 = require("ts-morph");
485
+ async function getSymbolDocs(symbol, filePath) {
486
+ const projects = await projectManager.getProjectsForPath(filePath);
487
+ for (const project of projects) {
488
+ const sourceFile = project.getSourceFile(filePath);
489
+ if (sourceFile) {
490
+ const node = sourceFile.getDescendantsOfKind(import_ts_morph3.SyntaxKind.Identifier).find((id) => id.getText() === symbol);
491
+ if (node) {
492
+ const decls = node.getSymbol()?.getDeclarations();
493
+ if (decls && decls.length > 0) {
494
+ const docs = typescriptAdapter.getSymbolDocs(decls[0]);
495
+ if (docs) {
496
+ return {
497
+ symbol,
498
+ file: sourceFile.getFilePath(),
499
+ line: sourceFile.getLineAndColumnAtPos(decls[0].getStart()).line,
500
+ ...docs
501
+ };
502
+ }
503
+ }
504
+ }
505
+ }
506
+ }
507
+ return void 0;
508
+ }
509
+
510
+ // src/index/symbol-index.ts
511
+ var SymbolIndex = class {
512
+ /**
513
+ * Build/Warm the index for a given path
514
+ */
515
+ async buildIndex(rootDir) {
516
+ const startTime = Date.now();
517
+ const projects = await projectManager.getProjectsForPath(rootDir);
518
+ let fileCount = 0;
519
+ let functionCount = 0;
520
+ let classCount = 0;
521
+ let interfaceCount = 0;
522
+ let typeCount = 0;
523
+ for (const project of projects) {
524
+ const sourceFiles = project.getSourceFiles();
525
+ fileCount += sourceFiles.length;
526
+ for (const sourceFile of sourceFiles) {
527
+ functionCount += sourceFile.getFunctions().length;
528
+ classCount += sourceFile.getClasses().length;
529
+ interfaceCount += sourceFile.getInterfaces().length;
530
+ typeCount += sourceFile.getTypeAliases().length;
531
+ }
532
+ }
533
+ const duration = Date.now() - startTime;
534
+ const memoryUsage = process.memoryUsage().heapUsed / 1024 / 1024;
535
+ return {
536
+ indexed: {
537
+ files: fileCount,
538
+ functions: functionCount,
539
+ classes: classCount,
540
+ interfaces: interfaceCount,
541
+ types: typeCount
542
+ },
543
+ duration_ms: duration,
544
+ memory_mb: Math.round(memoryUsage)
545
+ };
546
+ }
547
+ };
548
+ var symbolIndex = new SymbolIndex();
549
+
550
+ // src/tools/build-symbol-index.ts
551
+ async function buildSymbolIndex(path2) {
552
+ return await symbolIndex.buildIndex(path2);
553
+ }
554
+
555
+ // src/index.ts
556
+ var ASTExplorerServer = class {
557
+ server;
558
+ version = "0.1.0";
559
+ constructor() {
560
+ this.server = new import_server.Server(
561
+ {
562
+ name: "ast-explorer-server",
563
+ version: this.version
564
+ },
565
+ {
566
+ capabilities: {
567
+ tools: {}
568
+ }
569
+ }
570
+ );
571
+ this.setupHandlers();
572
+ this.server.onerror = (error) => {
573
+ console.error("[MCP Error]", error);
574
+ };
575
+ }
576
+ setupHandlers() {
577
+ this.server.setRequestHandler(import_types.ListToolsRequestSchema, async () => {
578
+ return {
579
+ tools: [
580
+ {
581
+ name: "resolve_definition",
582
+ description: "Find where a symbol is defined using TypeScript AST.",
583
+ inputSchema: {
584
+ type: "object",
585
+ properties: {
586
+ symbol: {
587
+ type: "string",
588
+ description: "Symbol name (e.g., function, class)"
589
+ },
590
+ path: {
591
+ type: "string",
592
+ description: "Project root or target directory"
593
+ }
594
+ },
595
+ required: ["symbol", "path"]
596
+ }
597
+ },
598
+ {
599
+ name: "find_references",
600
+ description: "Find all usages of a symbol across the project.",
601
+ inputSchema: {
602
+ type: "object",
603
+ properties: {
604
+ symbol: { type: "string", description: "Symbol name" },
605
+ path: { type: "string", description: "Project root" },
606
+ limit: { type: "number", default: 50 },
607
+ offset: { type: "number", default: 0 }
608
+ },
609
+ required: ["symbol", "path"]
610
+ }
611
+ },
612
+ {
613
+ name: "find_implementations",
614
+ description: "Find implementations of interfaces or abstract classes.",
615
+ inputSchema: {
616
+ type: "object",
617
+ properties: {
618
+ symbol: { type: "string", description: "Interface/Class name" },
619
+ path: { type: "string", description: "Project root" },
620
+ limit: { type: "number", default: 50 },
621
+ offset: { type: "number", default: 0 }
622
+ },
623
+ required: ["symbol", "path"]
624
+ }
625
+ },
626
+ {
627
+ name: "get_file_structure",
628
+ description: "Get structural overview of a file (imports, exports, symbols).",
629
+ inputSchema: {
630
+ type: "object",
631
+ properties: {
632
+ file: { type: "string", description: "Absolute path to file" }
633
+ },
634
+ required: ["file"]
635
+ }
636
+ },
637
+ {
638
+ name: "search_code",
639
+ description: "Fast regex search via bundled ripgrep.",
640
+ inputSchema: {
641
+ type: "object",
642
+ properties: {
643
+ pattern: { type: "string", description: "Search pattern" },
644
+ path: { type: "string", description: "Directory to search" },
645
+ filePattern: { type: "string", description: "Glob filter" },
646
+ limit: { type: "number", default: 50 }
647
+ },
648
+ required: ["pattern", "path"]
649
+ }
650
+ },
651
+ {
652
+ name: "get_symbol_docs",
653
+ description: "Get JSDoc/TSDoc for a specific symbol.",
654
+ inputSchema: {
655
+ type: "object",
656
+ properties: {
657
+ symbol: { type: "string", description: "Symbol name" },
658
+ path: { type: "string", description: "Project root" }
659
+ },
660
+ required: ["symbol", "path"]
661
+ }
662
+ },
663
+ {
664
+ name: "build_symbol_index",
665
+ description: "Warm the symbol index for faster navigation.",
666
+ inputSchema: {
667
+ type: "object",
668
+ properties: {
669
+ path: { type: "string", description: "Project root to index" }
670
+ },
671
+ required: ["path"]
672
+ }
673
+ }
674
+ ]
675
+ };
676
+ });
677
+ this.server.setRequestHandler(import_types.CallToolRequestSchema, async (request) => {
678
+ const { name, arguments: args } = request.params;
679
+ try {
680
+ switch (name) {
681
+ case "resolve_definition": {
682
+ const { symbol, path: path2 } = ResolveDefinitionSchema.parse(args);
683
+ const results = await resolveDefinition(symbol, path2);
684
+ return {
685
+ content: [
686
+ { type: "text", text: JSON.stringify(results, null, 2) }
687
+ ]
688
+ };
689
+ }
690
+ case "find_references": {
691
+ const { symbol, path: path2, limit, offset } = FindReferencesSchema.parse(args);
692
+ const results = await findReferences(symbol, path2, limit, offset);
693
+ return {
694
+ content: [
695
+ { type: "text", text: JSON.stringify(results, null, 2) }
696
+ ]
697
+ };
698
+ }
699
+ case "find_implementations": {
700
+ const { symbol, path: path2, limit, offset } = FindImplementationsSchema.parse(args);
701
+ const results = await findImplementations(
702
+ symbol,
703
+ path2,
704
+ limit,
705
+ offset
706
+ );
707
+ return {
708
+ content: [
709
+ { type: "text", text: JSON.stringify(results, null, 2) }
710
+ ]
711
+ };
712
+ }
713
+ case "get_file_structure": {
714
+ const { file } = GetFileStructureSchema.parse(args);
715
+ const structure = await getFileStructure(file);
716
+ return {
717
+ content: [
718
+ { type: "text", text: JSON.stringify(structure, null, 2) }
719
+ ]
720
+ };
721
+ }
722
+ case "search_code": {
723
+ const { pattern, path: path2, filePattern, limit } = SearchCodeSchema.parse(args);
724
+ const results = await searchCode(pattern, path2, filePattern, limit);
725
+ return {
726
+ content: [
727
+ { type: "text", text: JSON.stringify(results, null, 2) }
728
+ ]
729
+ };
730
+ }
731
+ case "get_symbol_docs": {
732
+ const { symbol, path: path2 } = GetSymbolDocsSchema.parse(args);
733
+ const docs = await getSymbolDocs(symbol, path2);
734
+ return {
735
+ content: [{ type: "text", text: JSON.stringify(docs, null, 2) }]
736
+ };
737
+ }
738
+ case "build_symbol_index": {
739
+ const { path: path2 } = BuildSymbolIndexSchema.parse(args);
740
+ const stats = await buildSymbolIndex(path2);
741
+ return {
742
+ content: [{ type: "text", text: JSON.stringify(stats, null, 2) }]
743
+ };
744
+ }
745
+ default:
746
+ throw new Error(`Unknown tool: ${name}`);
747
+ }
748
+ } catch (error) {
749
+ return {
750
+ content: [{ type: "text", text: `Error: ${error.message}` }],
751
+ isError: true
752
+ };
753
+ }
754
+ });
755
+ }
756
+ async run() {
757
+ const transport = new import_stdio.StdioServerTransport();
758
+ await this.server.connect(transport);
759
+ console.error("AST Explorer MCP Server started");
760
+ }
761
+ };
762
+ var server = new ASTExplorerServer();
763
+ server.run().catch((error) => {
764
+ console.error("Fatal error starting AST Explorer MCP Server:", error);
765
+ process.exit(1);
766
+ });
767
+ // Annotate the CommonJS export names for ESM import in node:
768
+ 0 && (module.exports = {
769
+ ASTExplorerServer
770
+ });
771
+ //# sourceMappingURL=index.cjs.map