@crowley/rag-mcp 1.0.2 → 1.0.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.
@@ -26,6 +26,19 @@ export declare function formatMemoryResults(results: Array<{
26
26
  memory: Record<string, unknown>;
27
27
  score: number;
28
28
  }>, emptyMessage?: string): string;
29
+ /** Format navigate-mode search results as compact navigation pointers */
30
+ export declare function formatNavigationResults(results: Array<{
31
+ file: string;
32
+ lines?: [number, number];
33
+ symbols?: string[];
34
+ imports?: string[];
35
+ connections?: string[];
36
+ layer?: string;
37
+ service?: string;
38
+ preview?: string;
39
+ score: number;
40
+ graphExpanded?: boolean;
41
+ }>): string;
29
42
  /** Format a simple list of files with scores */
30
43
  export declare function formatFileList(files: Array<{
31
44
  file: string;
@@ -60,6 +60,26 @@ export function formatMemoryResults(results, emptyMessage = "No memories found."
60
60
  });
61
61
  return result;
62
62
  }
63
+ /** Format navigate-mode search results as compact navigation pointers */
64
+ export function formatNavigationResults(results) {
65
+ if (!results?.length)
66
+ return "No results found.";
67
+ return results.map(r => {
68
+ const loc = r.lines ? `:${r.lines[0]}-${r.lines[1]}` : '';
69
+ let out = `**${r.file}${loc}** (${pct(r.score)})`;
70
+ if (r.layer)
71
+ out += ` [${r.layer}]`;
72
+ if (r.graphExpanded)
73
+ out += ' _(graph)_';
74
+ if (r.preview)
75
+ out += `\n\`${truncate(r.preview, 100)}\``;
76
+ if (r.symbols?.length)
77
+ out += `\nSymbols: ${r.symbols.join(', ')}`;
78
+ if (r.connections?.length)
79
+ out += `\nConnections: ${r.connections.map(c => '`' + c + '`').join(', ')}`;
80
+ return out;
81
+ }).join('\n\n');
82
+ }
63
83
  /** Format a simple list of files with scores */
64
84
  export function formatFileList(files, emptyMessage = "No files found.") {
65
85
  if (!files || files.length === 0)
@@ -2,7 +2,7 @@
2
2
  * Search tools module - codebase search, similarity search, grouped/hybrid search,
3
3
  * documentation search, and project statistics.
4
4
  */
5
- import { formatCodeResults, truncate, pct } from "../formatters.js";
5
+ import { formatCodeResults, formatNavigationResults, truncate } from "../formatters.js";
6
6
  /**
7
7
  * Create the search tools module with project-specific descriptions.
8
8
  */
@@ -10,7 +10,7 @@ export function createSearchTools(projectName) {
10
10
  const tools = [
11
11
  {
12
12
  name: "search_codebase",
13
- description: `Search the ${projectName} codebase for relevant code. Returns matching files with code snippets and relevance scores.`,
13
+ description: `Search the ${projectName} codebase. Returns file locations, symbols, and graph connections. Use Read tool to view the actual code at returned locations.`,
14
14
  inputSchema: {
15
15
  type: "object",
16
16
  properties: {
@@ -64,7 +64,7 @@ export function createSearchTools(projectName) {
64
64
  },
65
65
  {
66
66
  name: "grouped_search",
67
- description: `Search ${projectName} codebase with results grouped by file. Returns one best match per file instead of multiple chunks.`,
67
+ description: `Search ${projectName} codebase grouped by file. Returns file locations with symbols and connections. Use Read tool to view the actual code.`,
68
68
  inputSchema: {
69
69
  type: "object",
70
70
  properties: {
@@ -100,7 +100,7 @@ export function createSearchTools(projectName) {
100
100
  },
101
101
  {
102
102
  name: "hybrid_search",
103
- description: `Hybrid search combining keyword matching and semantic similarity for ${projectName}. Better for finding exact terms + related concepts.`,
103
+ description: `Hybrid search combining keyword matching and semantic similarity for ${projectName}. Returns file locations with symbols and connections. Use Read tool to view code.`,
104
104
  inputSchema: {
105
105
  type: "object",
106
106
  properties: {
@@ -186,7 +186,7 @@ export function createSearchTools(projectName) {
186
186
  },
187
187
  {
188
188
  name: "search_graph",
189
- description: `Search ${projectName} codebase with graph expansion. Finds semantically similar code plus connected files via import/call relationships.`,
189
+ description: `Search ${projectName} codebase with graph expansion. Returns file locations plus connected files via import/call relationships. Use Read tool to view code.`,
190
190
  inputSchema: {
191
191
  type: "object",
192
192
  properties: {
@@ -216,13 +216,14 @@ export function createSearchTools(projectName) {
216
216
  collection: `${ctx.collectionPrefix}codebase`,
217
217
  query,
218
218
  limit,
219
+ mode: "navigate",
219
220
  filters: { language, path, layer, service },
220
221
  });
221
222
  const results = response.data.results;
222
223
  if (!results || results.length === 0) {
223
224
  return "No results found for this query.";
224
225
  }
225
- return formatCodeResults(results, 500);
226
+ return formatNavigationResults(results);
226
227
  },
227
228
  search_similar: async (args, ctx) => {
228
229
  const { code, limit = 5 } = args;
@@ -246,23 +247,15 @@ export function createSearchTools(projectName) {
246
247
  query,
247
248
  groupBy,
248
249
  limit,
250
+ mode: "navigate",
249
251
  filters: hasFilters ? filters : undefined,
250
252
  });
251
253
  const groups = response.data.groups;
252
254
  if (!groups || groups.length === 0) {
253
255
  return "No results found.";
254
256
  }
255
- return groups
256
- .map((g) => {
257
- const r = g.results[0];
258
- return (`**${g[groupBy]}** (score: ${pct(r.score)})\n` +
259
- "```" +
260
- (r.language || "") +
261
- "\n" +
262
- truncate(r.content, 300) +
263
- "\n```");
264
- })
265
- .join("\n\n---\n\n");
257
+ const allResults = groups.flatMap((g) => g.results);
258
+ return formatNavigationResults(allResults);
266
259
  },
267
260
  hybrid_search: async (args, ctx) => {
268
261
  const { query, limit = 10, semanticWeight = 0.7, language, layer, service } = args;
@@ -273,20 +266,14 @@ export function createSearchTools(projectName) {
273
266
  query,
274
267
  limit,
275
268
  semanticWeight,
269
+ mode: "navigate",
276
270
  filters: hasFilters ? filters : undefined,
277
271
  });
278
272
  const results = response.data.results;
279
273
  if (!results || results.length === 0) {
280
274
  return "No results found.";
281
275
  }
282
- return results
283
- .map((r) => `**${r.file}** (combined: ${pct(r.score)}${r.semanticScore != null ? `, semantic: ${pct(r.semanticScore)}` : ''}${r.keywordScore != null ? `, keyword: ${pct(r.keywordScore)}` : ''})\n` +
284
- "```" +
285
- (r.language || "") +
286
- "\n" +
287
- truncate(r.content, 300) +
288
- "\n```")
289
- .join("\n\n---\n\n");
276
+ return formatNavigationResults(results);
290
277
  },
291
278
  search_docs: async (args, ctx) => {
292
279
  const { query, limit = 5 } = args;
@@ -329,27 +316,20 @@ export function createSearchTools(projectName) {
329
316
  query,
330
317
  limit,
331
318
  expandHops,
319
+ mode: "navigate",
332
320
  });
333
321
  const { results, graphExpanded, expandedFiles } = response.data;
322
+ if ((!results || results.length === 0) && (!graphExpanded || graphExpanded.length === 0)) {
323
+ return "No results found.";
324
+ }
334
325
  let output = "";
335
326
  if (results && results.length > 0) {
336
327
  output += "**Direct matches:**\n\n";
337
- output += results
338
- .map((r) => `**${r.file}** (score: ${pct(r.score)})\n` +
339
- "```" + (r.language || "") + "\n" +
340
- truncate(r.content, 300) + "\n```")
341
- .join("\n\n");
328
+ output += formatNavigationResults(results);
342
329
  }
343
330
  if (graphExpanded && graphExpanded.length > 0) {
344
331
  output += "\n\n---\n\n**Graph-connected files:**\n\n";
345
- output += graphExpanded
346
- .map((r) => `**${r.file}** (score: ${pct(r.score)})\n` +
347
- "```" + (r.language || "") + "\n" +
348
- truncate(r.content, 300) + "\n```")
349
- .join("\n\n");
350
- }
351
- if (!output) {
352
- return "No results found.";
332
+ output += formatNavigationResults(graphExpanded);
353
333
  }
354
334
  if (expandedFiles && expandedFiles.length > 0) {
355
335
  output += `\n\n_Graph expanded to ${expandedFiles.length} additional files._`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowley/rag-mcp",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Universal RAG MCP Server for any project",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",