@aiready/ast-mcp-server 0.1.2 → 0.1.3
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 +193 -82
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +187 -82
- package/dist/index.js.map +1 -1
- package/dist/worker/ast-worker.cjs +158 -0
- package/dist/worker/ast-worker.cjs.map +1 -0
- package/dist/worker/ast-worker.d.cts +2 -0
- package/dist/worker/ast-worker.d.ts +2 -0
- package/dist/worker/ast-worker.js +156 -0
- package/dist/worker/ast-worker.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// src/worker/ast-worker.ts
|
|
2
|
+
import { parentPort } from "worker_threads";
|
|
3
|
+
import { Project } from "ts-morph";
|
|
4
|
+
var projects = /* @__PURE__ */ new Map();
|
|
5
|
+
function getProject(tsconfigPath) {
|
|
6
|
+
if (!projects.has(tsconfigPath)) {
|
|
7
|
+
projects.set(
|
|
8
|
+
tsconfigPath,
|
|
9
|
+
new Project({
|
|
10
|
+
tsConfigFilePath: tsconfigPath,
|
|
11
|
+
skipAddingFilesFromTsConfig: true
|
|
12
|
+
})
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
return projects.get(tsconfigPath);
|
|
16
|
+
}
|
|
17
|
+
parentPort?.on("message", async (msg) => {
|
|
18
|
+
try {
|
|
19
|
+
let result;
|
|
20
|
+
switch (msg.type) {
|
|
21
|
+
case "resolve_definition": {
|
|
22
|
+
const { tsconfig, file, symbol } = msg.payload;
|
|
23
|
+
const project = getProject(tsconfig);
|
|
24
|
+
const sf = project.addSourceFileAtPath(file);
|
|
25
|
+
if (!sf) {
|
|
26
|
+
result = [];
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
const exported = sf.getExportedDeclarations().get(symbol);
|
|
30
|
+
if (!exported || exported.length === 0) {
|
|
31
|
+
result = [];
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
result = exported.map((decl) => {
|
|
35
|
+
const sourceFile = decl.getSourceFile();
|
|
36
|
+
const lineAndColumn = sourceFile.getLineAndColumnAtPos(
|
|
37
|
+
decl.getStart()
|
|
38
|
+
);
|
|
39
|
+
return {
|
|
40
|
+
file: sourceFile.getFilePath(),
|
|
41
|
+
line: lineAndColumn.line,
|
|
42
|
+
column: lineAndColumn.column,
|
|
43
|
+
kind: decl.getKindName(),
|
|
44
|
+
snippet: decl.getText(),
|
|
45
|
+
documentation: getJsDoc(decl)
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
case "find_references": {
|
|
51
|
+
const { tsconfig, file, symbol } = msg.payload;
|
|
52
|
+
const project = getProject(tsconfig);
|
|
53
|
+
const sf = project.addSourceFileAtPath(file);
|
|
54
|
+
if (!sf) {
|
|
55
|
+
result = { references: [], total_count: 0 };
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
const exported = sf.getExportedDeclarations().get(symbol);
|
|
59
|
+
if (!exported || exported.length === 0) {
|
|
60
|
+
result = { references: [], total_count: 0 };
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
const targetNode = exported[0];
|
|
64
|
+
const refSymbols = targetNode.findReferences?.();
|
|
65
|
+
if (!refSymbols) {
|
|
66
|
+
result = { references: [], total_count: 0 };
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
const results = [];
|
|
70
|
+
for (const refSymbol of refSymbols) {
|
|
71
|
+
for (const ref of refSymbol.getReferences()) {
|
|
72
|
+
const refSf = ref.getSourceFile();
|
|
73
|
+
const lc = refSf.getLineAndColumnAtPos(
|
|
74
|
+
ref.getTextSpan().getStart()
|
|
75
|
+
);
|
|
76
|
+
results.push({
|
|
77
|
+
file: refSf.getFilePath(),
|
|
78
|
+
line: lc.line,
|
|
79
|
+
column: lc.column,
|
|
80
|
+
text: ref.getNode().getParent()?.getText() || ref.getNode().getText()
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const unique = deduplicateLocations(results);
|
|
85
|
+
result = {
|
|
86
|
+
references: unique.slice(0, 50),
|
|
87
|
+
total_count: unique.length
|
|
88
|
+
};
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
case "find_implementations": {
|
|
92
|
+
const { tsconfig, file, symbol } = msg.payload;
|
|
93
|
+
const project = getProject(tsconfig);
|
|
94
|
+
const sf = project.addSourceFileAtPath(file);
|
|
95
|
+
if (!sf) {
|
|
96
|
+
result = { implementations: [], total_count: 0 };
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
const exported = sf.getExportedDeclarations().get(symbol);
|
|
100
|
+
if (!exported || exported.length === 0) {
|
|
101
|
+
result = { implementations: [], total_count: 0 };
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
const targetNode = exported[0];
|
|
105
|
+
const implementations = targetNode.getImplementations?.();
|
|
106
|
+
if (!implementations) {
|
|
107
|
+
result = { implementations: [], total_count: 0 };
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
const results = [];
|
|
111
|
+
for (const impl of implementations) {
|
|
112
|
+
const implSf = impl.getSourceFile();
|
|
113
|
+
const lc = implSf.getLineAndColumnAtPos(
|
|
114
|
+
impl.getTextSpan().getStart()
|
|
115
|
+
);
|
|
116
|
+
results.push({
|
|
117
|
+
file: implSf.getFilePath(),
|
|
118
|
+
line: lc.line,
|
|
119
|
+
column: lc.column,
|
|
120
|
+
text: impl.getNode().getParent()?.getText() || impl.getNode().getText()
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
const unique = deduplicateLocations(results);
|
|
124
|
+
result = {
|
|
125
|
+
implementations: unique.slice(0, 50),
|
|
126
|
+
total_count: unique.length
|
|
127
|
+
};
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
default:
|
|
131
|
+
throw new Error(`Unknown task type: ${msg.type}`);
|
|
132
|
+
}
|
|
133
|
+
parentPort?.postMessage({ id: msg.id, result });
|
|
134
|
+
} catch (error) {
|
|
135
|
+
parentPort?.postMessage({ id: msg.id, error: error.message });
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
function getJsDoc(node) {
|
|
139
|
+
if (node.getJsDocs) {
|
|
140
|
+
const docs = node.getJsDocs();
|
|
141
|
+
if (docs.length > 0) {
|
|
142
|
+
return docs[0].getCommentText();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return void 0;
|
|
146
|
+
}
|
|
147
|
+
function deduplicateLocations(locations) {
|
|
148
|
+
const seen = /* @__PURE__ */ new Set();
|
|
149
|
+
return locations.filter((loc) => {
|
|
150
|
+
const key = `${loc.file}:${loc.line}:${loc.column}`;
|
|
151
|
+
if (seen.has(key)) return false;
|
|
152
|
+
seen.add(key);
|
|
153
|
+
return true;
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=ast-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/worker/ast-worker.ts"],"sourcesContent":["import { parentPort } from 'worker_threads';\nimport { Project } from 'ts-morph';\nimport { validateWorkspacePath } from '../security.js';\n\nconst projects = new Map<string, Project>();\n\nfunction getProject(tsconfigPath: string): Project {\n if (!projects.has(tsconfigPath)) {\n projects.set(\n tsconfigPath,\n new Project({\n tsConfigFilePath: tsconfigPath,\n skipAddingFilesFromTsConfig: true,\n })\n );\n }\n return projects.get(tsconfigPath)!;\n}\n\ninterface WorkerMessage {\n id: string;\n type: string;\n payload: any;\n}\n\ninterface DefinitionLocation {\n file: string;\n line: number;\n column: number;\n kind: string;\n snippet: string;\n documentation?: string;\n}\n\ninterface ReferenceLocation {\n file: string;\n line: number;\n column: number;\n text: string;\n}\n\nparentPort?.on('message', async (msg: WorkerMessage) => {\n try {\n let result: unknown;\n\n switch (msg.type) {\n case 'resolve_definition': {\n const { tsconfig, file, symbol } = msg.payload;\n const project = getProject(tsconfig);\n const sf = project.addSourceFileAtPath(file);\n if (!sf) {\n result = [];\n break;\n }\n\n const exported = sf.getExportedDeclarations().get(symbol);\n if (!exported || exported.length === 0) {\n result = [];\n break;\n }\n\n result = exported.map((decl) => {\n const sourceFile = decl.getSourceFile();\n const lineAndColumn = sourceFile.getLineAndColumnAtPos(\n decl.getStart()\n );\n return {\n file: sourceFile.getFilePath(),\n line: lineAndColumn.line,\n column: lineAndColumn.column,\n kind: decl.getKindName(),\n snippet: decl.getText(),\n documentation: getJsDoc(decl),\n };\n });\n break;\n }\n\n case 'find_references': {\n const { tsconfig, file, symbol } = msg.payload;\n const project = getProject(tsconfig);\n const sf = project.addSourceFileAtPath(file);\n if (!sf) {\n result = { references: [], total_count: 0 };\n break;\n }\n\n const exported = sf.getExportedDeclarations().get(symbol);\n if (!exported || exported.length === 0) {\n result = { references: [], total_count: 0 };\n break;\n }\n\n const targetNode = exported[0];\n const refSymbols = (targetNode as any).findReferences?.();\n if (!refSymbols) {\n result = { references: [], total_count: 0 };\n break;\n }\n\n const results: ReferenceLocation[] = [];\n for (const refSymbol of refSymbols) {\n for (const ref of refSymbol.getReferences()) {\n const refSf = ref.getSourceFile();\n const lc = refSf.getLineAndColumnAtPos(\n ref.getTextSpan().getStart()\n );\n results.push({\n file: refSf.getFilePath(),\n line: lc.line,\n column: lc.column,\n text:\n ref.getNode().getParent()?.getText() || ref.getNode().getText(),\n });\n }\n }\n\n const unique = deduplicateLocations(results);\n result = {\n references: unique.slice(0, 50),\n total_count: unique.length,\n };\n break;\n }\n\n case 'find_implementations': {\n const { tsconfig, file, symbol } = msg.payload;\n const project = getProject(tsconfig);\n const sf = project.addSourceFileAtPath(file);\n if (!sf) {\n result = { implementations: [], total_count: 0 };\n break;\n }\n\n const exported = sf.getExportedDeclarations().get(symbol);\n if (!exported || exported.length === 0) {\n result = { implementations: [], total_count: 0 };\n break;\n }\n\n const targetNode = exported[0];\n const implementations = (targetNode as any).getImplementations?.();\n if (!implementations) {\n result = { implementations: [], total_count: 0 };\n break;\n }\n\n const results: ReferenceLocation[] = [];\n for (const impl of implementations) {\n const implSf = impl.getSourceFile();\n const lc = implSf.getLineAndColumnAtPos(\n impl.getTextSpan().getStart()\n );\n results.push({\n file: implSf.getFilePath(),\n line: lc.line,\n column: lc.column,\n text:\n impl.getNode().getParent()?.getText() || impl.getNode().getText(),\n });\n }\n\n const unique = deduplicateLocations(results);\n result = {\n implementations: unique.slice(0, 50),\n total_count: unique.length,\n };\n break;\n }\n\n default:\n throw new Error(`Unknown task type: ${msg.type}`);\n }\n\n parentPort?.postMessage({ id: msg.id, result });\n } catch (error: any) {\n parentPort?.postMessage({ id: msg.id, error: error.message });\n }\n});\n\nfunction getJsDoc(node: any): string | undefined {\n if (node.getJsDocs) {\n const docs = node.getJsDocs();\n if (docs.length > 0) {\n return docs[0].getCommentText();\n }\n }\n return undefined;\n}\n\nfunction deduplicateLocations<\n T extends { file: string; line: number; column: number },\n>(locations: T[]): T[] {\n const seen = new Set<string>();\n return locations.filter((loc) => {\n const key = `${loc.file}:${loc.line}:${loc.column}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/ast-mcp-server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "The AIReady AST-aware Model Context Protocol (MCP) Server. Explore and navigate multi-project TypeScript/JavaScript codebases with high precision using AST and type information.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"aiready",
|