maven-indexer-mcp 1.0.8 → 1.0.9
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/build/index.js +27 -5
- package/build/indexer.js +36 -29
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -20,6 +20,7 @@ const indexer = Indexer.getInstance();
|
|
|
20
20
|
// We trigger indexing but don't await it so server can start
|
|
21
21
|
indexer.index().then(() => {
|
|
22
22
|
// Start watching for changes after initial index
|
|
23
|
+
indexer.startSchedule();
|
|
23
24
|
return indexer.startWatch();
|
|
24
25
|
}).catch(err => console.error("Initial indexing failed:", err));
|
|
25
26
|
server.registerTool("get_class_details", {
|
|
@@ -154,9 +155,9 @@ server.registerTool("get_class_details", {
|
|
|
154
155
|
return { content: [{ type: "text", text: results.join("\n\n") }] };
|
|
155
156
|
});
|
|
156
157
|
server.registerTool("search_artifacts", {
|
|
157
|
-
description: "Search for internal company artifacts and libraries in the local Maven repository and Gradle caches by coordinate (groupId, artifactId) or
|
|
158
|
+
description: "Search for internal company artifacts and libraries in the local Maven repository and Gradle caches by coordinate (groupId, artifactId), keyword, or class name. Use this primarily for internal company packages or to find available versions of internal projects that are locally built. Also supports searching third-party libraries in the local cache. Supports batch queries.",
|
|
158
159
|
inputSchema: z.object({
|
|
159
|
-
query: z.string().optional().describe("Search query (groupId, artifactId, or
|
|
160
|
+
query: z.string().optional().describe("Search query (groupId, artifactId, keyword, or class name)"),
|
|
160
161
|
queries: z.array(z.string()).optional().describe("Batch search queries"),
|
|
161
162
|
}),
|
|
162
163
|
}, async ({ query, queries }) => {
|
|
@@ -169,13 +170,34 @@ server.registerTool("search_artifacts", {
|
|
|
169
170
|
return { content: [{ type: "text", text: "No query provided." }] };
|
|
170
171
|
}
|
|
171
172
|
const results = allQueries.map(q => {
|
|
172
|
-
|
|
173
|
+
let allMatches = [];
|
|
174
|
+
let searchType = "artifact";
|
|
175
|
+
// First try class search (for both simple and fully qualified class names)
|
|
176
|
+
const classSearchResults = indexer.searchClass(q);
|
|
177
|
+
if (classSearchResults.length > 0) {
|
|
178
|
+
// Extract unique artifacts from class search results
|
|
179
|
+
const artifactMap = new Map();
|
|
180
|
+
classSearchResults.forEach(result => {
|
|
181
|
+
result.artifacts.forEach(artifact => {
|
|
182
|
+
const key = `${artifact.groupId}:${artifact.artifactId}:${artifact.version}`;
|
|
183
|
+
if (!artifactMap.has(key)) {
|
|
184
|
+
artifactMap.set(key, artifact);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
allMatches = Array.from(artifactMap.values());
|
|
189
|
+
searchType = "class";
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
// Fallback to artifact search if class search finds nothing
|
|
193
|
+
allMatches = indexer.search(q);
|
|
194
|
+
}
|
|
173
195
|
// Limit results to avoid overflow
|
|
174
|
-
const limitedMatches =
|
|
196
|
+
const limitedMatches = allMatches.slice(0, 20);
|
|
175
197
|
const text = limitedMatches.length > 0
|
|
176
198
|
? limitedMatches.map(a => `${a.groupId}:${a.artifactId}:${a.version} (Has Source: ${a.hasSource})`).join("\n")
|
|
177
199
|
: "No artifacts found matching the query.";
|
|
178
|
-
return `### Results for "${q}" (Found ${
|
|
200
|
+
return `### Results for "${q}" (Found ${allMatches.length} via ${searchType} search${allMatches.length > 20 ? ', showing first 20' : ''}):\n${text}`;
|
|
179
201
|
});
|
|
180
202
|
return {
|
|
181
203
|
content: [
|
package/build/indexer.js
CHANGED
|
@@ -15,7 +15,7 @@ export class Indexer {
|
|
|
15
15
|
isIndexing = false;
|
|
16
16
|
watcher = null;
|
|
17
17
|
debounceTimer = null;
|
|
18
|
-
|
|
18
|
+
scheduleTimer = null;
|
|
19
19
|
constructor() {
|
|
20
20
|
}
|
|
21
21
|
static getInstance() {
|
|
@@ -25,8 +25,7 @@ export class Indexer {
|
|
|
25
25
|
return Indexer.instance;
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
|
-
* Starts watching the local repository for changes
|
|
29
|
-
* Just watch the root directories without recursion
|
|
28
|
+
* Starts watching the local repository for changes.
|
|
30
29
|
*/
|
|
31
30
|
async startWatch() {
|
|
32
31
|
const config = await Config.getInstance();
|
|
@@ -42,65 +41,73 @@ export class Indexer {
|
|
|
42
41
|
console.error("No repository paths found, skipping watch mode.");
|
|
43
42
|
return;
|
|
44
43
|
}
|
|
45
|
-
if (this.watcher
|
|
44
|
+
if (this.watcher) {
|
|
46
45
|
return;
|
|
47
46
|
}
|
|
48
|
-
console.error(`🔍 Starting
|
|
47
|
+
console.error(`🔍 Starting file watcher on: ${watchPaths.join(', ')}`);
|
|
49
48
|
try {
|
|
50
|
-
//
|
|
49
|
+
// Watch for .jar and .pom files changes deep in the repository
|
|
51
50
|
this.watcher = chokidar.watch(watchPaths, {
|
|
52
|
-
// Watch
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
// Watch for jar and pom files
|
|
52
|
+
ignored: [
|
|
53
|
+
/(^|[\/\\])\../, // ignore dotfiles
|
|
54
|
+
/node_modules/,
|
|
55
|
+
/target/,
|
|
56
|
+
/build/,
|
|
57
|
+
],
|
|
58
|
+
persistent: true,
|
|
55
59
|
ignoreInitial: true,
|
|
56
|
-
// Wait for files to finish writing before triggering
|
|
57
60
|
awaitWriteFinish: {
|
|
58
61
|
stabilityThreshold: 2000,
|
|
59
62
|
pollInterval: 100
|
|
60
63
|
},
|
|
61
|
-
// Don't crash on permission errors
|
|
62
64
|
ignorePermissionErrors: true
|
|
63
65
|
});
|
|
64
|
-
//
|
|
65
|
-
// This will catch when new directories are created (which means new artifacts)
|
|
66
|
+
// Watch for file additions and changes
|
|
66
67
|
this.watcher
|
|
68
|
+
.on('add', (filePath) => {
|
|
69
|
+
if (filePath.endsWith('.jar') || filePath.endsWith('.pom')) {
|
|
70
|
+
console.error(`📄 New file detected: ${path.basename(filePath)}`);
|
|
71
|
+
this.triggerReindex();
|
|
72
|
+
}
|
|
73
|
+
})
|
|
67
74
|
.on('addDir', (dirPath) => {
|
|
68
|
-
console.error(
|
|
75
|
+
console.error(`📁 New directory detected: ${path.basename(dirPath)}`);
|
|
69
76
|
this.triggerReindex();
|
|
77
|
+
})
|
|
78
|
+
.on('unlink', (filePath) => {
|
|
79
|
+
if (filePath.endsWith('.jar') || filePath.endsWith('.pom')) {
|
|
80
|
+
console.error(`🗑️ File removed: ${path.basename(filePath)}`);
|
|
81
|
+
this.triggerReindex();
|
|
82
|
+
}
|
|
70
83
|
})
|
|
71
84
|
.on('unlinkDir', (dirPath) => {
|
|
72
|
-
console.error(`🗑️
|
|
85
|
+
console.error(`🗑️ Directory removed: ${path.basename(dirPath)}`);
|
|
73
86
|
this.triggerReindex();
|
|
74
87
|
})
|
|
75
88
|
.on('error', (error) => {
|
|
76
89
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
77
90
|
console.error(`❌ Watcher error: ${errorMessage}`);
|
|
78
|
-
this.fallbackToPolling();
|
|
79
91
|
});
|
|
80
|
-
console.error('✅
|
|
92
|
+
console.error('✅ File watcher started successfully');
|
|
81
93
|
}
|
|
82
94
|
catch (error) {
|
|
83
95
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
84
96
|
console.error(`❌ Failed to start watcher: ${errorMessage}`);
|
|
85
|
-
this.fallbackToPolling();
|
|
86
97
|
}
|
|
87
98
|
}
|
|
88
99
|
/**
|
|
89
|
-
*
|
|
90
|
-
* Polls the repository every 1 min
|
|
100
|
+
* Starts a scheduled job to reindex every 1 hour.
|
|
91
101
|
*/
|
|
92
|
-
|
|
93
|
-
if (this.
|
|
102
|
+
startSchedule() {
|
|
103
|
+
if (this.scheduleTimer) {
|
|
94
104
|
return;
|
|
95
105
|
}
|
|
96
|
-
console.error('
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
this.watcher = null;
|
|
100
|
-
}
|
|
101
|
-
this.pollingTimer = setInterval(() => {
|
|
106
|
+
console.error('⏰ Starting scheduled reindex job (every 1 hour)...');
|
|
107
|
+
this.scheduleTimer = setInterval(() => {
|
|
108
|
+
console.error('⏰ Scheduled reindex triggered...');
|
|
102
109
|
this.index().catch(console.error);
|
|
103
|
-
},
|
|
110
|
+
}, 3600000); // 1 hour
|
|
104
111
|
}
|
|
105
112
|
/**
|
|
106
113
|
* Trigger reindexing with debouncing (wait a bit for multiple changes)
|