@crowley/rag-mcp 1.0.0

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.
Files changed (49) hide show
  1. package/dist/api-client.d.ts +4 -0
  2. package/dist/api-client.js +19 -0
  3. package/dist/context-enrichment.d.ts +44 -0
  4. package/dist/context-enrichment.js +190 -0
  5. package/dist/formatters.d.ts +33 -0
  6. package/dist/formatters.js +70 -0
  7. package/dist/index.d.ts +13 -0
  8. package/dist/index.js +109 -0
  9. package/dist/tool-registry.d.ts +20 -0
  10. package/dist/tool-registry.js +123 -0
  11. package/dist/tools/advanced.d.ts +9 -0
  12. package/dist/tools/advanced.js +315 -0
  13. package/dist/tools/agents.d.ts +8 -0
  14. package/dist/tools/agents.js +97 -0
  15. package/dist/tools/analytics.d.ts +9 -0
  16. package/dist/tools/analytics.js +261 -0
  17. package/dist/tools/architecture.d.ts +5 -0
  18. package/dist/tools/architecture.js +720 -0
  19. package/dist/tools/ask.d.ts +9 -0
  20. package/dist/tools/ask.js +256 -0
  21. package/dist/tools/cache.d.ts +5 -0
  22. package/dist/tools/cache.js +98 -0
  23. package/dist/tools/clustering.d.ts +9 -0
  24. package/dist/tools/clustering.js +251 -0
  25. package/dist/tools/confluence.d.ts +9 -0
  26. package/dist/tools/confluence.js +147 -0
  27. package/dist/tools/database.d.ts +5 -0
  28. package/dist/tools/database.js +429 -0
  29. package/dist/tools/feedback.d.ts +9 -0
  30. package/dist/tools/feedback.js +220 -0
  31. package/dist/tools/guidelines.d.ts +5 -0
  32. package/dist/tools/guidelines.js +146 -0
  33. package/dist/tools/indexing.d.ts +9 -0
  34. package/dist/tools/indexing.js +129 -0
  35. package/dist/tools/memory.d.ts +9 -0
  36. package/dist/tools/memory.js +565 -0
  37. package/dist/tools/pm.d.ts +9 -0
  38. package/dist/tools/pm.js +680 -0
  39. package/dist/tools/review.d.ts +8 -0
  40. package/dist/tools/review.js +213 -0
  41. package/dist/tools/search.d.ts +9 -0
  42. package/dist/tools/search.js +377 -0
  43. package/dist/tools/session.d.ts +10 -0
  44. package/dist/tools/session.js +386 -0
  45. package/dist/tools/suggestions.d.ts +9 -0
  46. package/dist/tools/suggestions.js +301 -0
  47. package/dist/types.d.ts +32 -0
  48. package/dist/types.js +4 -0
  49. package/package.json +40 -0
@@ -0,0 +1,565 @@
1
+ /**
2
+ * Memory tools module - Agent memory management tools.
3
+ *
4
+ * Tools: remember, recall, list_memories, forget, update_todo,
5
+ * batch_remember, validate_memory, review_memories,
6
+ * promote_memory, run_quality_gates, memory_maintenance
7
+ */
8
+ import { formatMemoryResults, truncate, PREVIEW } from "../formatters.js";
9
+ const typeEmojis = {
10
+ decision: "\u{1F3AF}",
11
+ insight: "\u{1F4A1}",
12
+ context: "\u{1F4CC}",
13
+ todo: "\u{1F4CB}",
14
+ conversation: "\u{1F4AC}",
15
+ note: "\u{1F4DD}",
16
+ };
17
+ const statusEmojis = {
18
+ pending: "\u23F3",
19
+ in_progress: "\u{1F504}",
20
+ done: "\u2705",
21
+ cancelled: "\u274C",
22
+ };
23
+ export function createMemoryTools(projectName) {
24
+ const tools = [
25
+ {
26
+ name: "remember",
27
+ description: "Store important information in agent memory. Use this to save decisions, insights, context, todos, or important conversations for future reference.",
28
+ inputSchema: {
29
+ type: "object",
30
+ properties: {
31
+ content: {
32
+ type: "string",
33
+ description: "Information to remember",
34
+ },
35
+ type: {
36
+ type: "string",
37
+ enum: [
38
+ "decision",
39
+ "insight",
40
+ "context",
41
+ "todo",
42
+ "conversation",
43
+ "note",
44
+ ],
45
+ description: "Type of memory (default: note)",
46
+ default: "note",
47
+ },
48
+ tags: {
49
+ type: "array",
50
+ items: { type: "string" },
51
+ description: "Tags for categorization (e.g., ['feature-x', 'important'])",
52
+ },
53
+ relatedTo: {
54
+ type: "string",
55
+ description: "Related feature or topic",
56
+ },
57
+ },
58
+ required: ["content"],
59
+ },
60
+ },
61
+ {
62
+ name: "recall",
63
+ description: "Retrieve relevant memories based on context. Searches agent memory for past decisions, insights, and notes related to the query.",
64
+ inputSchema: {
65
+ type: "object",
66
+ properties: {
67
+ query: {
68
+ type: "string",
69
+ description: "What to recall (semantic search)",
70
+ },
71
+ type: {
72
+ type: "string",
73
+ enum: [
74
+ "decision",
75
+ "insight",
76
+ "context",
77
+ "todo",
78
+ "conversation",
79
+ "note",
80
+ "all",
81
+ ],
82
+ description: "Filter by memory type (default: all)",
83
+ default: "all",
84
+ },
85
+ limit: {
86
+ type: "number",
87
+ description: "Max memories to retrieve (default: 5)",
88
+ default: 5,
89
+ },
90
+ },
91
+ required: ["query"],
92
+ },
93
+ },
94
+ {
95
+ name: "list_memories",
96
+ description: "List recent memories or filter by type/tags. Shows what the agent has remembered.",
97
+ inputSchema: {
98
+ type: "object",
99
+ properties: {
100
+ type: {
101
+ type: "string",
102
+ enum: [
103
+ "decision",
104
+ "insight",
105
+ "context",
106
+ "todo",
107
+ "conversation",
108
+ "note",
109
+ "all",
110
+ ],
111
+ description: "Filter by type",
112
+ default: "all",
113
+ },
114
+ tag: {
115
+ type: "string",
116
+ description: "Filter by tag",
117
+ },
118
+ limit: {
119
+ type: "number",
120
+ description: "Max results (default: 10)",
121
+ default: 10,
122
+ },
123
+ },
124
+ },
125
+ },
126
+ {
127
+ name: "forget",
128
+ description: "Delete a specific memory by ID or clear memories by type.",
129
+ inputSchema: {
130
+ type: "object",
131
+ properties: {
132
+ memoryId: {
133
+ type: "string",
134
+ description: "Specific memory ID to delete",
135
+ },
136
+ type: {
137
+ type: "string",
138
+ enum: [
139
+ "decision",
140
+ "insight",
141
+ "context",
142
+ "todo",
143
+ "conversation",
144
+ "note",
145
+ ],
146
+ description: "Delete all memories of this type",
147
+ },
148
+ olderThanDays: {
149
+ type: "number",
150
+ description: "Delete memories older than N days",
151
+ },
152
+ },
153
+ },
154
+ },
155
+ {
156
+ name: "update_todo",
157
+ description: "Update status of a todo/task in memory.",
158
+ inputSchema: {
159
+ type: "object",
160
+ properties: {
161
+ todoId: {
162
+ type: "string",
163
+ description: "Todo memory ID",
164
+ },
165
+ status: {
166
+ type: "string",
167
+ enum: ["pending", "in_progress", "done", "cancelled"],
168
+ description: "New status",
169
+ },
170
+ note: {
171
+ type: "string",
172
+ description: "Optional note about the update",
173
+ },
174
+ },
175
+ required: ["todoId", "status"],
176
+ },
177
+ },
178
+ {
179
+ name: "batch_remember",
180
+ description: `Efficiently store multiple memories at once in ${projectName}. Faster than individual remember calls.`,
181
+ inputSchema: {
182
+ type: "object",
183
+ properties: {
184
+ items: {
185
+ type: "array",
186
+ items: {
187
+ type: "object",
188
+ properties: {
189
+ content: {
190
+ type: "string",
191
+ description: "Content to remember",
192
+ },
193
+ type: {
194
+ type: "string",
195
+ enum: [
196
+ "decision",
197
+ "insight",
198
+ "context",
199
+ "todo",
200
+ "conversation",
201
+ "note",
202
+ ],
203
+ description: "Memory type (default: note)",
204
+ },
205
+ tags: {
206
+ type: "array",
207
+ items: { type: "string" },
208
+ description: "Tags for categorization",
209
+ },
210
+ relatedTo: {
211
+ type: "string",
212
+ description: "Related feature or topic",
213
+ },
214
+ },
215
+ required: ["content"],
216
+ },
217
+ description: "Array of memories to store",
218
+ },
219
+ },
220
+ required: ["items"],
221
+ },
222
+ },
223
+ {
224
+ name: "validate_memory",
225
+ description: `Validate or reject an auto-extracted memory in ${projectName}. Helps improve future extraction accuracy.`,
226
+ inputSchema: {
227
+ type: "object",
228
+ properties: {
229
+ memoryId: {
230
+ type: "string",
231
+ description: "ID of the memory to validate",
232
+ },
233
+ validated: {
234
+ type: "boolean",
235
+ description: "true to confirm the memory is valuable, false to reject it",
236
+ },
237
+ },
238
+ required: ["memoryId", "validated"],
239
+ },
240
+ },
241
+ {
242
+ name: "review_memories",
243
+ description: `Get auto-extracted memories pending review in ${projectName}. Shows unvalidated learnings that need human confirmation.`,
244
+ inputSchema: {
245
+ type: "object",
246
+ properties: {
247
+ limit: {
248
+ type: "number",
249
+ description: "Max memories to return (default: 20)",
250
+ default: 20,
251
+ },
252
+ },
253
+ },
254
+ },
255
+ {
256
+ name: "promote_memory",
257
+ description: `Promote a quarantine memory to durable storage in ${projectName}. Requires a reason for promotion. Optionally runs quality gates before promotion.`,
258
+ inputSchema: {
259
+ type: "object",
260
+ properties: {
261
+ memoryId: {
262
+ type: "string",
263
+ description: "ID of the memory to promote",
264
+ },
265
+ reason: {
266
+ type: "string",
267
+ enum: ["human_validated", "pr_merged", "tests_passed"],
268
+ description: "Reason for promotion",
269
+ },
270
+ evidence: {
271
+ type: "string",
272
+ description: "Optional evidence supporting the promotion",
273
+ },
274
+ runGates: {
275
+ type: "boolean",
276
+ description: "Run quality gates before promotion (default: false)",
277
+ },
278
+ affectedFiles: {
279
+ type: "array",
280
+ items: { type: "string" },
281
+ description: "Files affected by this memory (for quality gate checking)",
282
+ },
283
+ },
284
+ required: ["memoryId", "reason"],
285
+ },
286
+ },
287
+ {
288
+ name: "run_quality_gates",
289
+ description: `Run quality gates (typecheck, tests, blast radius) for ${projectName}.`,
290
+ inputSchema: {
291
+ type: "object",
292
+ properties: {
293
+ affectedFiles: {
294
+ type: "array",
295
+ items: { type: "string" },
296
+ description: "Files to check (for related tests and blast radius)",
297
+ },
298
+ skipGates: {
299
+ type: "array",
300
+ items: { type: "string" },
301
+ description: "Gates to skip (typecheck, test, blast_radius)",
302
+ },
303
+ },
304
+ },
305
+ },
306
+ {
307
+ name: "memory_maintenance",
308
+ description: `Run feedback-driven memory maintenance for ${projectName}: auto-promote memories with 3+ positive feedback, auto-prune memories with 2+ incorrect feedback.`,
309
+ inputSchema: {
310
+ type: "object",
311
+ properties: {},
312
+ },
313
+ },
314
+ ];
315
+ const handlers = {
316
+ // ----- remember -----
317
+ async remember(args, ctx) {
318
+ const content = args.content;
319
+ const type = args.type || "note";
320
+ const tags = args.tags || [];
321
+ const relatedTo = args.relatedTo;
322
+ const response = await ctx.api.post("/api/memory", {
323
+ projectName: ctx.projectName,
324
+ content,
325
+ type,
326
+ tags,
327
+ relatedTo,
328
+ });
329
+ const memory = response.data.memory;
330
+ return (`\u2705 **Memory stored**\n\n` +
331
+ `- **ID:** ${memory.id}\n` +
332
+ `- **Type:** ${memory.type}\n` +
333
+ `- **Content:** ${truncate(content, 200)}\n` +
334
+ (tags.length > 0 ? `- **Tags:** ${tags.join(", ")}\n` : "") +
335
+ (relatedTo ? `- **Related to:** ${relatedTo}\n` : "") +
336
+ `- **Created:** ${new Date(memory.createdAt).toLocaleString()}`);
337
+ },
338
+ // ----- recall -----
339
+ async recall(args, ctx) {
340
+ const query = args.query;
341
+ const type = args.type || "all";
342
+ const limit = args.limit || 5;
343
+ const response = await ctx.api.post("/api/memory/recall", {
344
+ projectName: ctx.projectName,
345
+ query,
346
+ type,
347
+ limit,
348
+ });
349
+ const results = response.data.results || [];
350
+ if (results.length === 0) {
351
+ return `\u{1F50D} No memories found for: "${query}"`;
352
+ }
353
+ const header = `\u{1F9E0} **Recalled Memories** (${results.length} found)\n\n`;
354
+ return header + formatMemoryResults(results);
355
+ },
356
+ // ----- list_memories -----
357
+ async list_memories(args, ctx) {
358
+ const type = args.type || "all";
359
+ const tag = args.tag;
360
+ const limit = args.limit || 10;
361
+ const params = new URLSearchParams({
362
+ projectName: ctx.projectName,
363
+ limit: limit.toString(),
364
+ });
365
+ if (type && type !== "all")
366
+ params.append("type", type);
367
+ if (tag)
368
+ params.append("tag", tag);
369
+ const response = await ctx.api.get(`/api/memory/list?${params}`);
370
+ const memories = response.data.memories || [];
371
+ if (memories.length === 0) {
372
+ return `\u{1F4ED} No memories found${type !== "all" ? ` of type "${type}"` : ""}`;
373
+ }
374
+ let result = `\u{1F4DA} **Agent Memories** (${memories.length})\n\n`;
375
+ memories.forEach((m, i) => {
376
+ const emoji = typeEmojis[m.type] || "\u{1F4DD}";
377
+ const statusStr = m.status ? ` [${m.status}]` : "";
378
+ result += `${i + 1}. ${emoji} **${m.type}**${statusStr}: ${truncate(m.content, PREVIEW.SHORT)}\n`;
379
+ result += ` ID: \`${m.id}\` | ${new Date(m.createdAt).toLocaleDateString()}\n\n`;
380
+ });
381
+ return result;
382
+ },
383
+ // ----- forget -----
384
+ async forget(args, ctx) {
385
+ const memoryId = args.memoryId;
386
+ const type = args.type;
387
+ if (memoryId) {
388
+ const response = await ctx.api.delete(`/api/memory/${memoryId}?projectName=${ctx.projectName}`);
389
+ return response.data.success
390
+ ? `\u{1F5D1}\uFE0F Memory deleted: ${memoryId}`
391
+ : `\u274C Failed to delete memory: ${memoryId}`;
392
+ }
393
+ if (type) {
394
+ await ctx.api.delete(`/api/memory/type/${type}?projectName=${ctx.projectName}`);
395
+ return `\u{1F5D1}\uFE0F Deleted all memories of type: ${type}`;
396
+ }
397
+ return "Please specify memoryId or type to delete.";
398
+ },
399
+ // ----- update_todo -----
400
+ async update_todo(args, ctx) {
401
+ const todoId = args.todoId;
402
+ const status = args.status;
403
+ const note = args.note;
404
+ const response = await ctx.api.patch(`/api/memory/todo/${todoId}`, {
405
+ projectName: ctx.projectName,
406
+ status,
407
+ note,
408
+ });
409
+ if (!response.data.memory) {
410
+ return `\u274C Todo not found: ${todoId}`;
411
+ }
412
+ return (`${statusEmojis[status] || "\u{1F4CB}"} **Todo updated**\n\n` +
413
+ `- **ID:** ${todoId}\n` +
414
+ `- **Status:** ${status}\n` +
415
+ (note ? `- **Note:** ${note}\n` : "") +
416
+ `- **Content:** ${response.data.memory.content}`);
417
+ },
418
+ // ----- batch_remember -----
419
+ async batch_remember(args, ctx) {
420
+ const items = args.items;
421
+ const response = await ctx.api.post("/api/memory/batch", {
422
+ items,
423
+ });
424
+ const { savedCount, errors, memories } = response.data;
425
+ let result = `# \u{1F4E6} Batch Memory Result\n\n`;
426
+ result += `**Saved**: ${savedCount} memories\n\n`;
427
+ if (memories && memories.length > 0) {
428
+ result += `## Stored Memories\n`;
429
+ memories.forEach((m) => {
430
+ result += `- [${m.type}] ${truncate(m.content, 80)}\n`;
431
+ result += ` ID: \`${m.id}\`\n`;
432
+ });
433
+ }
434
+ if (errors && errors.length > 0) {
435
+ result += `\n## \u26A0\uFE0F Errors\n`;
436
+ errors.forEach((e) => {
437
+ result += `- ${e}\n`;
438
+ });
439
+ }
440
+ return result;
441
+ },
442
+ // ----- validate_memory -----
443
+ async validate_memory(args, ctx) {
444
+ const memoryId = args.memoryId;
445
+ const validated = args.validated;
446
+ const response = await ctx.api.patch(`/api/memory/${memoryId}/validate`, {
447
+ validated,
448
+ });
449
+ const { memory } = response.data;
450
+ return (`\u2705 Memory ${validated ? "validated" : "rejected"}\n\n` +
451
+ `- **ID**: ${memory.id}\n` +
452
+ `- **Type**: ${memory.type}\n` +
453
+ `- **Content**: ${truncate(memory.content, PREVIEW.SHORT)}\n` +
454
+ `- **Validated**: ${memory.validated}`);
455
+ },
456
+ // ----- promote_memory -----
457
+ async promote_memory(args, ctx) {
458
+ const memoryId = args.memoryId;
459
+ const reason = args.reason;
460
+ const evidence = args.evidence;
461
+ const runGates = args.runGates;
462
+ const affectedFiles = args.affectedFiles;
463
+ const response = await ctx.api.post("/api/memory/promote", {
464
+ projectName: ctx.projectName,
465
+ memoryId,
466
+ reason,
467
+ evidence,
468
+ runGates: runGates || false,
469
+ projectPath: runGates ? ctx.projectPath : undefined,
470
+ affectedFiles: runGates ? affectedFiles : undefined,
471
+ });
472
+ const { memory } = response.data;
473
+ return (`\u2705 **Memory promoted to durable storage**\n\n` +
474
+ `- **ID:** ${memory.id}\n` +
475
+ `- **Type:** ${memory.type}\n` +
476
+ `- **Reason:** ${reason}\n` +
477
+ (evidence ? `- **Evidence:** ${evidence}\n` : "") +
478
+ (runGates ? `- **Quality Gates:** passed\n` : "") +
479
+ `- **Content:** ${truncate(memory.content, 200)}`);
480
+ },
481
+ // ----- run_quality_gates -----
482
+ async run_quality_gates(args, ctx) {
483
+ const affectedFiles = args.affectedFiles;
484
+ const skipGates = args.skipGates;
485
+ const response = await ctx.api.post("/api/quality/run", {
486
+ projectName: ctx.projectName,
487
+ projectPath: ctx.projectPath,
488
+ affectedFiles,
489
+ skipGates,
490
+ });
491
+ const report = response.data;
492
+ let result = `**Quality Report**: ${report.passed ? "\u2705 All gates passed" : "\u274C Some gates failed"}\n\n`;
493
+ for (const gate of report.gates) {
494
+ const icon = gate.passed ? "\u2705" : "\u274C";
495
+ result += `${icon} **${gate.gate}** (${(gate.duration / 1000).toFixed(1)}s)\n`;
496
+ result += ` ${gate.details.slice(0, 500)}\n\n`;
497
+ }
498
+ if (report.blastRadius) {
499
+ result += `\n**Blast Radius**: ${report.blastRadius.affectedFiles.length} files, depth ${report.blastRadius.depth}\n`;
500
+ if (report.blastRadius.affectedFiles.length > 0) {
501
+ result += report.blastRadius.affectedFiles
502
+ .slice(0, 10)
503
+ .map((f) => ` - ${f}`)
504
+ .join("\n");
505
+ if (report.blastRadius.affectedFiles.length > 10) {
506
+ result += `\n ... and ${report.blastRadius.affectedFiles.length - 10} more`;
507
+ }
508
+ }
509
+ }
510
+ return result;
511
+ },
512
+ // ----- memory_maintenance -----
513
+ async memory_maintenance(args, ctx) {
514
+ const response = await ctx.api.post("/api/memory/maintenance", {
515
+ projectName: ctx.projectName,
516
+ });
517
+ const { promoted, pruned, errors } = response.data;
518
+ let result = `# \u{1F9F9} Memory Maintenance Results\n\n`;
519
+ if (promoted.length > 0) {
520
+ result += `**Promoted** (${promoted.length}): memories with 3+ positive feedback moved to durable\n`;
521
+ promoted.forEach((id) => { result += ` \u2705 ${id}\n`; });
522
+ result += `\n`;
523
+ }
524
+ if (pruned.length > 0) {
525
+ result += `**Pruned** (${pruned.length}): memories with 2+ incorrect feedback removed\n`;
526
+ pruned.forEach((id) => { result += ` \u{1F5D1}\u{FE0F} ${id}\n`; });
527
+ result += `\n`;
528
+ }
529
+ if (errors.length > 0) {
530
+ result += `**Errors** (${errors.length}):\n`;
531
+ errors.forEach((e) => { result += ` \u26A0\u{FE0F} ${e}\n`; });
532
+ result += `\n`;
533
+ }
534
+ if (promoted.length === 0 && pruned.length === 0) {
535
+ result += `No memories needed maintenance. All feedback thresholds are below auto-action levels.\n`;
536
+ }
537
+ return result;
538
+ },
539
+ // ----- review_memories -----
540
+ async review_memories(args, ctx) {
541
+ const limit = args.limit || 20;
542
+ const response = await ctx.api.get(`/api/memory/quarantine?limit=${limit}`);
543
+ const { memories, count } = response.data;
544
+ if (count === 0) {
545
+ return "No unvalidated memories to review. All auto-extracted learnings have been reviewed.";
546
+ }
547
+ let result = `# \u{1F4CB} Memories Pending Review (${count})\n\n`;
548
+ result += `These are auto-extracted learnings that need validation.\n\n`;
549
+ memories.forEach((m, i) => {
550
+ result += `## ${i + 1}. ${m.type.toUpperCase()}\n`;
551
+ result += `**ID**: \`${m.id}\`\n`;
552
+ result += `**Confidence**: ${((m.confidence || 0) * 100).toFixed(0)}%\n`;
553
+ result += `**Source**: ${m.source || "unknown"}\n`;
554
+ result += `**Content**: ${m.content}\n`;
555
+ if (m.tags && m.tags.length > 0) {
556
+ result += `**Tags**: ${m.tags.join(", ")}\n`;
557
+ }
558
+ result += `\nTo validate: \`validate_memory(memoryId="${m.id}", validated=true)\`\n`;
559
+ result += `To reject: \`validate_memory(memoryId="${m.id}", validated=false)\`\n\n`;
560
+ });
561
+ return result;
562
+ },
563
+ };
564
+ return { tools, handlers };
565
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * PM tools module - Product Management, requirements analysis, feature estimation,
3
+ * spec generation, and project status tools.
4
+ */
5
+ import type { ToolModule } from "../types.js";
6
+ /**
7
+ * Create the PM tools module with project-specific descriptions.
8
+ */
9
+ export declare function createPmTools(projectName: string): ToolModule;