vcluster-yaml-mcp-server 1.4.0 → 1.4.2

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.
@@ -283,14 +283,35 @@ export function searchYaml(allInfo, searchTerm) {
283
283
  }
284
284
  }
285
285
  else {
286
- // Keyword-based search
287
- const keywords = searchTerm.split(/\s+/);
286
+ // Keyword-based search with stop word filtering
287
+ const stopWords = new Set([
288
+ 'how', 'to', 'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been',
289
+ 'being', 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',
290
+ 'should', 'may', 'might', 'must', 'shall', 'can', 'need', 'dare', 'ought',
291
+ 'used', 'for', 'from', 'with', 'about', 'against', 'between', 'into', 'through',
292
+ 'during', 'before', 'after', 'above', 'below', 'up', 'down', 'in', 'out', 'on',
293
+ 'off', 'over', 'under', 'again', 'further', 'then', 'once', 'here', 'there',
294
+ 'when', 'where', 'why', 'what', 'which', 'who', 'whom', 'this', 'that', 'these',
295
+ 'those', 'am', 'and', 'but', 'if', 'or', 'because', 'as', 'until', 'while',
296
+ 'of', 'at', 'by', 'i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves',
297
+ 'you', 'your', 'yours', 'yourself', 'yourselves', 'he', 'him', 'his', 'himself',
298
+ 'she', 'her', 'hers', 'herself', 'it', 'its', 'itself', 'they', 'them', 'their',
299
+ 'theirs', 'themselves', 'each', 'few', 'more', 'most', 'other', 'some', 'such',
300
+ 'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too', 'very', 's', 't',
301
+ 'just', 'don', 'now', 'get', 'set', 'use', 'using', 'configure', 'configuration'
302
+ ]);
303
+ // Filter out stop words and short words
304
+ const allWords = searchTerm.split(/\s+/);
305
+ const keywords = allWords.filter(kw => kw.length > 2 && !stopWords.has(kw));
306
+ // If all words were stop words, fall back to original (but filter very short ones)
307
+ const effectiveKeywords = keywords.length > 0 ? keywords : allWords.filter(w => w.length > 2);
288
308
  for (const item of allInfo) {
289
309
  const pathLower = item.path.toLowerCase();
290
310
  const keyLower = item.key.toLowerCase();
291
311
  const valueStr = JSON.stringify(item.value).toLowerCase();
292
- const allKeywordsMatch = keywords.every(kw => pathLower.includes(kw) || keyLower.includes(kw) || valueStr.includes(kw));
293
- if (allKeywordsMatch) {
312
+ // Match if ANY meaningful keyword matches (more lenient for natural language)
313
+ const anyKeywordMatch = effectiveKeywords.some(kw => pathLower.includes(kw) || keyLower.includes(kw) || valueStr.includes(kw));
314
+ if (anyKeywordMatch) {
294
315
  results.push(item);
295
316
  }
296
317
  }
@@ -322,26 +343,51 @@ export function sortByRelevance(results, searchTerm) {
322
343
  });
323
344
  }
324
345
  /**
325
- * Rank search result
326
- * Pure function
346
+ * Rank search result - multi-keyword aware
327
347
  */
328
348
  function rankResult(item, searchTerm) {
329
349
  let score = 0;
330
350
  const pathLower = item.path.toLowerCase();
331
351
  const keyLower = item.key.toLowerCase();
332
- // Exact path match (highest priority)
333
- if (pathLower === searchTerm)
334
- score += 100;
335
- // Exact key match
336
- if (keyLower === searchTerm)
337
- score += 50;
338
- // Path contains exact term
339
- if (pathLower.includes(searchTerm))
340
- score += 20;
341
- // Key contains term
342
- if (keyLower.includes(searchTerm))
343
- score += 10;
344
- // Leaf nodes are more relevant
352
+ const termLower = searchTerm.toLowerCase();
353
+ if (termLower.includes('.')) {
354
+ if (pathLower === termLower)
355
+ score += 100;
356
+ if (pathLower.includes(termLower))
357
+ score += 20;
358
+ if (item.isLeaf)
359
+ score += 5;
360
+ return score;
361
+ }
362
+ const stopWords = new Set([
363
+ 'how', 'to', 'the', 'a', 'an', 'is', 'are', 'from', 'what', 'which',
364
+ 'for', 'with', 'in', 'on', 'at', 'by', 'and', 'or', 'of', 'do', 'does'
365
+ ]);
366
+ const keywords = searchTerm.split(/\s+/).filter(w => w.length > 2 && !stopWords.has(w));
367
+ if (keywords.length > 1) {
368
+ let matchCount = 0;
369
+ for (const kw of keywords) {
370
+ if (pathLower.includes(kw) || keyLower.includes(kw)) {
371
+ matchCount++;
372
+ if (keyLower.includes(kw))
373
+ score += 15;
374
+ }
375
+ }
376
+ score += matchCount * 25;
377
+ if (matchCount === keywords.length)
378
+ score += 50;
379
+ }
380
+ else {
381
+ const term = keywords[0] ?? searchTerm;
382
+ if (pathLower === term)
383
+ score += 100;
384
+ if (keyLower === term)
385
+ score += 50;
386
+ if (pathLower.includes(term))
387
+ score += 20;
388
+ if (keyLower.includes(term))
389
+ score += 10;
390
+ }
345
391
  if (item.isLeaf)
346
392
  score += 5;
347
393
  return score;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vcluster-yaml-mcp-server",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "MCP server for querying vcluster YAML configurations using jq",
5
5
  "repository": {
6
6
  "type": "git",