@grec0/memory-bank-mcp 0.1.1 → 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.js CHANGED
@@ -20,6 +20,11 @@ import { getStats } from "./tools/getStats.js";
20
20
  import { analyzeCoverage } from "./tools/analyzeCoverage.js";
21
21
  import { generateProjectDocs, generateProjectDocsToolDefinition } from "./tools/generateProjectDocs.js";
22
22
  import { getProjectDocs, getProjectDocsToolDefinition } from "./tools/getProjectDocs.js";
23
+ // Import new context management tools
24
+ import { initializeMemoryBank, initializeMemoryBankToolDefinition } from "./tools/initializeMemoryBank.js";
25
+ import { updateContext, updateContextToolDefinition } from "./tools/updateContext.js";
26
+ import { recordDecision, recordDecisionToolDefinition } from "./tools/recordDecision.js";
27
+ import { trackProgress, trackProgressToolDefinition } from "./tools/trackProgress.js";
23
28
  import { VERSION } from "./common/version.js";
24
29
  // Global services
25
30
  let embeddingService;
@@ -33,24 +38,31 @@ const server = new McpServer({
33
38
  version: VERSION,
34
39
  });
35
40
  // Tool: Index Code
36
- server.tool("memorybank_index_code", "Indexa semánticamente código de un directorio o archivo específico para permitir búsquedas semánticas. El projectId es OBLIGATORIO y debe coincidir con el definido en AGENTS.md", {
41
+ server.tool("memorybank_index_code", `Indexa semánticamente código de un DIRECTORIO para búsquedas semánticas.
42
+
43
+ ⚠️ IMPORTANTE:
44
+ - El path debe ser una RUTA ABSOLUTA a un DIRECTORIO (no archivo)
45
+ - Ejemplo correcto: "C:/workspaces/mi-proyecto/src/components"
46
+ - Ejemplo incorrecto: "src/components" (ruta relativa)
47
+ - Ejemplo incorrecto: "C:/workspaces/mi-proyecto/src/file.ts" (archivo, no directorio)
48
+
49
+ Si quieres indexar un archivo específico, usa el directorio que lo contiene.`, {
37
50
  projectId: z
38
51
  .string()
39
- .describe("Identificador único del proyecto (OBLIGATORIO). Debe coincidir con el definido en AGENTS.md del proyecto"),
52
+ .describe("Identificador único del proyecto (OBLIGATORIO). Debe coincidir con el definido en AGENTS.md"),
40
53
  path: z
41
54
  .string()
42
- .optional()
43
- .describe("Ruta relativa o absoluta del directorio/archivo a indexar (por defecto: raíz del workspace)"),
55
+ .describe("RUTA ABSOLUTA al DIRECTORIO a indexar. Ejemplo: 'C:/workspaces/proyecto/src'. NO usar rutas relativas. NO usar rutas a archivos."),
44
56
  recursive: z
45
57
  .boolean()
46
58
  .optional()
47
59
  .default(true)
48
- .describe("Indexar recursivamente subdirectorios"),
60
+ .describe("Indexar recursivamente subdirectorios (default: true)"),
49
61
  forceReindex: z
50
62
  .boolean()
51
63
  .optional()
52
64
  .default(false)
53
- .describe("Forzar reindexación completa aunque no haya cambios"),
65
+ .describe("RARAMENTE NECESARIO. El sistema detecta cambios por hash automáticamente. Solo usa true si necesitas regenerar embeddings sin cambios en archivos."),
54
66
  }, async (args) => {
55
67
  const result = await indexCode({
56
68
  projectId: args.projectId,
@@ -102,18 +114,21 @@ server.tool("memorybank_search", "Busca código relevante mediante búsqueda sem
102
114
  };
103
115
  });
104
116
  // Tool: Read File
105
- server.tool("memorybank_read_file", "Lee el contenido de un archivo específico del workspace. Usa esta herramienta para obtener contexto adicional cuando los fragmentos de búsqueda no son suficientes", {
117
+ server.tool("memorybank_read_file", `Lee el contenido de un archivo específico. Usa para obtener contexto adicional.
118
+
119
+ ⚠️ Preferir RUTA ABSOLUTA para evitar errores.
120
+ Ejemplo: "C:/workspaces/proyecto/src/index.ts"`, {
106
121
  path: z
107
122
  .string()
108
- .describe("Ruta relativa o absoluta del archivo a leer"),
123
+ .describe("Ruta al archivo. Preferir ABSOLUTA: 'C:/workspaces/proyecto/src/file.ts'"),
109
124
  startLine: z
110
125
  .number()
111
126
  .optional()
112
- .describe("Línea inicial para leer un rango específico (opcional)"),
127
+ .describe("Línea inicial (opcional)"),
113
128
  endLine: z
114
129
  .number()
115
130
  .optional()
116
- .describe("Línea final para leer un rango específico (opcional)"),
131
+ .describe("Línea final (opcional)"),
117
132
  }, async (args) => {
118
133
  const result = await readFile({
119
134
  path: args.path,
@@ -125,21 +140,24 @@ server.tool("memorybank_read_file", "Lee el contenido de un archivo específico
125
140
  };
126
141
  });
127
142
  // Tool: Write File
128
- server.tool("memorybank_write_file", "Escribe o modifica un archivo y automáticamente lo reindexa en el Memory Bank para mantener la consistencia. El projectId es OBLIGATORIO para la reindexación correcta", {
143
+ server.tool("memorybank_write_file", `Escribe un archivo y automáticamente lo reindexa en el Memory Bank.
144
+
145
+ ⚠️ Preferir RUTA ABSOLUTA para evitar errores.
146
+ Ejemplo path: "C:/workspaces/proyecto/src/nuevo.ts"`, {
129
147
  projectId: z
130
148
  .string()
131
- .describe("Identificador del proyecto (OBLIGATORIO). Necesario para la auto-reindexación correcta"),
149
+ .describe("Identificador del proyecto (OBLIGATORIO)"),
132
150
  path: z
133
151
  .string()
134
- .describe("Ruta relativa o absoluta del archivo a escribir"),
152
+ .describe("Ruta al archivo. Preferir ABSOLUTA: 'C:/workspaces/proyecto/src/file.ts'"),
135
153
  content: z
136
154
  .string()
137
- .describe("Contenido completo del archivo a escribir"),
155
+ .describe("Contenido COMPLETO del archivo"),
138
156
  autoReindex: z
139
157
  .boolean()
140
158
  .optional()
141
159
  .default(true)
142
- .describe("Reindexar automáticamente el archivo después de escribirlo"),
160
+ .describe("Auto-reindexar después de escribir (default: true)"),
143
161
  }, async (args) => {
144
162
  const result = await writeFile({
145
163
  projectId: args.projectId,
@@ -159,13 +177,18 @@ server.tool("memorybank_get_stats", "Obtiene estadísticas del Memory Bank: arch
159
177
  };
160
178
  });
161
179
  // Tool: Analyze Coverage
162
- server.tool("memorybank_analyze_coverage", "Analiza la cobertura de indexación del proyecto. Muestra qué carpetas/archivos están indexados, cuáles no, y cuáles tienen cambios pendientes. OBLIGATORIO: projectId y path (ruta absoluta del workspace). NOTA: Puede tardar en workspaces grandes", {
180
+ server.tool("memorybank_analyze_coverage", `Analiza la cobertura de indexación del proyecto.
181
+
182
+ ⚠️ IMPORTANTE:
183
+ - path debe ser RUTA ABSOLUTA al DIRECTORIO raíz del workspace
184
+ - Ejemplo: "C:/workspaces/mi-proyecto" (NO rutas relativas)
185
+ - Puede tardar en workspaces grandes`, {
163
186
  projectId: z
164
187
  .string()
165
- .describe("Identificador del proyecto a analizar (OBLIGATORIO)"),
188
+ .describe("Identificador del proyecto (OBLIGATORIO)"),
166
189
  path: z
167
190
  .string()
168
- .describe("Ruta absoluta del workspace a analizar (OBLIGATORIO). Ejemplo: 'C:/workspaces/mi-proyecto'"),
191
+ .describe("RUTA ABSOLUTA al directorio raíz del workspace. Ejemplo: 'C:/workspaces/mi-proyecto'"),
169
192
  }, async (args) => {
170
193
  try {
171
194
  const targetPath = args.path;
@@ -252,6 +275,343 @@ server.tool(getProjectDocsToolDefinition.name, getProjectDocsToolDefinition.desc
252
275
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
253
276
  };
254
277
  });
278
+ // ==========================================
279
+ // Context Management Tools (Cline-style)
280
+ // ==========================================
281
+ // Tool: Initialize Memory Bank
282
+ server.tool(initializeMemoryBankToolDefinition.name, initializeMemoryBankToolDefinition.description + `
283
+
284
+ ⚠️ projectPath debe ser RUTA ABSOLUTA. Ejemplo: "C:/workspaces/mi-proyecto"`, {
285
+ projectId: z
286
+ .string()
287
+ .describe("Identificador único del proyecto (OBLIGATORIO)"),
288
+ projectPath: z
289
+ .string()
290
+ .describe("RUTA ABSOLUTA al proyecto. Ejemplo: 'C:/workspaces/mi-proyecto'"),
291
+ projectName: z
292
+ .string()
293
+ .optional()
294
+ .describe("Nombre legible del proyecto (opcional)"),
295
+ description: z
296
+ .string()
297
+ .optional()
298
+ .describe("Descripción inicial del proyecto (opcional)"),
299
+ }, async (args) => {
300
+ const storagePath = process.env.MEMORYBANK_STORAGE_PATH || ".memorybank";
301
+ const result = await initializeMemoryBank({
302
+ projectId: args.projectId,
303
+ projectPath: args.projectPath,
304
+ projectName: args.projectName,
305
+ description: args.description,
306
+ }, storagePath);
307
+ return {
308
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
309
+ };
310
+ });
311
+ // Tool: Update Context
312
+ server.tool(updateContextToolDefinition.name, updateContextToolDefinition.description, {
313
+ projectId: z
314
+ .string()
315
+ .describe("Identificador único del proyecto (OBLIGATORIO)"),
316
+ currentSession: z
317
+ .object({
318
+ date: z.string().optional().describe("Fecha de la sesión (YYYY-MM-DD)"),
319
+ mode: z.string().optional().describe("Modo de trabajo: development, debugging, refactoring, etc."),
320
+ task: z.string().optional().describe("Descripción de la tarea actual"),
321
+ })
322
+ .optional()
323
+ .describe("Información de la sesión actual"),
324
+ recentChanges: z
325
+ .array(z.string())
326
+ .optional()
327
+ .describe("Lista de cambios recientes realizados"),
328
+ openQuestions: z
329
+ .array(z.string())
330
+ .optional()
331
+ .describe("Preguntas pendientes de resolver"),
332
+ nextSteps: z
333
+ .array(z.string())
334
+ .optional()
335
+ .describe("Próximos pasos planificados"),
336
+ notes: z
337
+ .string()
338
+ .optional()
339
+ .describe("Notas adicionales o consideraciones"),
340
+ }, async (args) => {
341
+ const storagePath = process.env.MEMORYBANK_STORAGE_PATH || ".memorybank";
342
+ const result = await updateContext({
343
+ projectId: args.projectId,
344
+ currentSession: args.currentSession,
345
+ recentChanges: args.recentChanges,
346
+ openQuestions: args.openQuestions,
347
+ nextSteps: args.nextSteps,
348
+ notes: args.notes,
349
+ }, storagePath);
350
+ return {
351
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
352
+ };
353
+ });
354
+ // Tool: Record Decision
355
+ server.tool(recordDecisionToolDefinition.name, recordDecisionToolDefinition.description, {
356
+ projectId: z
357
+ .string()
358
+ .describe("Identificador único del proyecto (OBLIGATORIO)"),
359
+ decision: z
360
+ .object({
361
+ title: z.string().describe("Título corto y descriptivo de la decisión"),
362
+ description: z.string().describe("Descripción detallada de lo que se decidió"),
363
+ rationale: z.string().describe("Por qué se tomó esta decisión"),
364
+ alternatives: z.array(z.string()).optional().describe("Alternativas consideradas"),
365
+ impact: z.string().optional().describe("Impacto esperado de la decisión"),
366
+ category: z.string().optional().describe("Categoría: architecture, technology, dependencies, etc."),
367
+ date: z.string().optional().describe("Fecha de la decisión (YYYY-MM-DD)"),
368
+ })
369
+ .describe("Información de la decisión a registrar"),
370
+ }, async (args) => {
371
+ const storagePath = process.env.MEMORYBANK_STORAGE_PATH || ".memorybank";
372
+ const result = await recordDecision({
373
+ projectId: args.projectId,
374
+ decision: args.decision,
375
+ }, storagePath);
376
+ return {
377
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
378
+ };
379
+ });
380
+ // Tool: Track Progress
381
+ server.tool(trackProgressToolDefinition.name, trackProgressToolDefinition.description, {
382
+ projectId: z
383
+ .string()
384
+ .describe("Identificador único del proyecto (OBLIGATORIO)"),
385
+ progress: z
386
+ .object({
387
+ completed: z.array(z.string()).optional().describe("Tareas completadas"),
388
+ inProgress: z.array(z.string()).optional().describe("Tareas en progreso"),
389
+ blocked: z.array(z.string()).optional().describe("Tareas bloqueadas"),
390
+ upcoming: z.array(z.string()).optional().describe("Próximas tareas"),
391
+ })
392
+ .optional()
393
+ .describe("Tareas a actualizar"),
394
+ milestone: z
395
+ .object({
396
+ name: z.string().describe("Nombre del milestone"),
397
+ status: z.enum(["pending", "in_progress", "completed"]).describe("Estado del milestone"),
398
+ targetDate: z.string().optional().describe("Fecha objetivo"),
399
+ notes: z.string().optional().describe("Notas adicionales"),
400
+ })
401
+ .optional()
402
+ .describe("Milestone a añadir o actualizar"),
403
+ blockers: z
404
+ .array(z.object({
405
+ description: z.string().describe("Descripción del blocker"),
406
+ severity: z.enum(["low", "medium", "high"]).describe("Severidad"),
407
+ }))
408
+ .optional()
409
+ .describe("Blockers a registrar"),
410
+ phase: z
411
+ .string()
412
+ .optional()
413
+ .describe("Fase actual del proyecto"),
414
+ phaseStatus: z
415
+ .string()
416
+ .optional()
417
+ .describe("Estado de la fase"),
418
+ }, async (args) => {
419
+ const storagePath = process.env.MEMORYBANK_STORAGE_PATH || ".memorybank";
420
+ const result = await trackProgress({
421
+ projectId: args.projectId,
422
+ progress: args.progress,
423
+ milestone: args.milestone,
424
+ blockers: args.blockers,
425
+ phase: args.phase,
426
+ phaseStatus: args.phaseStatus,
427
+ }, storagePath);
428
+ return {
429
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
430
+ };
431
+ });
432
+ // ==========================================
433
+ // MCP Resources (Direct document access)
434
+ // ==========================================
435
+ // Resource: Project Active Context
436
+ server.resource("memory://*/active", "Contexto activo del proyecto: sesión actual, cambios recientes, próximos pasos", async (uri) => {
437
+ const projectId = uri.pathname.split("/")[0] || uri.host;
438
+ if (!projectKnowledgeService) {
439
+ return {
440
+ contents: [{
441
+ uri: uri.href,
442
+ mimeType: "text/plain",
443
+ text: "Error: Project Knowledge Service not initialized",
444
+ }],
445
+ };
446
+ }
447
+ const content = projectKnowledgeService.getProjectDocument(projectId, "activeContext");
448
+ if (!content) {
449
+ return {
450
+ contents: [{
451
+ uri: uri.href,
452
+ mimeType: "text/plain",
453
+ text: `No active context found for project "${projectId}". Run memorybank_initialize first.`,
454
+ }],
455
+ };
456
+ }
457
+ return {
458
+ contents: [{
459
+ uri: uri.href,
460
+ mimeType: "text/markdown",
461
+ text: content,
462
+ }],
463
+ };
464
+ });
465
+ // Resource: Project Progress
466
+ server.resource("memory://*/progress", "Seguimiento de progreso: tareas completadas, en progreso, bloqueadas y milestones", async (uri) => {
467
+ const projectId = uri.pathname.split("/")[0] || uri.host;
468
+ if (!projectKnowledgeService) {
469
+ return {
470
+ contents: [{
471
+ uri: uri.href,
472
+ mimeType: "text/plain",
473
+ text: "Error: Project Knowledge Service not initialized",
474
+ }],
475
+ };
476
+ }
477
+ const content = projectKnowledgeService.getProjectDocument(projectId, "progress");
478
+ if (!content) {
479
+ return {
480
+ contents: [{
481
+ uri: uri.href,
482
+ mimeType: "text/plain",
483
+ text: `No progress tracking found for project "${projectId}". Run memorybank_initialize first.`,
484
+ }],
485
+ };
486
+ }
487
+ return {
488
+ contents: [{
489
+ uri: uri.href,
490
+ mimeType: "text/markdown",
491
+ text: content,
492
+ }],
493
+ };
494
+ });
495
+ // Resource: Project Decisions
496
+ server.resource("memory://*/decisions", "Log de decisiones técnicas: historial de decisiones arquitectónicas y técnicas", async (uri) => {
497
+ const projectId = uri.pathname.split("/")[0] || uri.host;
498
+ if (!projectKnowledgeService) {
499
+ return {
500
+ contents: [{
501
+ uri: uri.href,
502
+ mimeType: "text/plain",
503
+ text: "Error: Project Knowledge Service not initialized",
504
+ }],
505
+ };
506
+ }
507
+ const content = projectKnowledgeService.getProjectDocument(projectId, "decisionLog");
508
+ if (!content) {
509
+ return {
510
+ contents: [{
511
+ uri: uri.href,
512
+ mimeType: "text/plain",
513
+ text: `No decision log found for project "${projectId}". Run memorybank_initialize first.`,
514
+ }],
515
+ };
516
+ }
517
+ return {
518
+ contents: [{
519
+ uri: uri.href,
520
+ mimeType: "text/markdown",
521
+ text: content,
522
+ }],
523
+ };
524
+ });
525
+ // Resource: Project Context (Brief + Tech)
526
+ server.resource("memory://*/context", "Contexto completo del proyecto: descripción general y stack tecnológico", async (uri) => {
527
+ const projectId = uri.pathname.split("/")[0] || uri.host;
528
+ if (!projectKnowledgeService) {
529
+ return {
530
+ contents: [{
531
+ uri: uri.href,
532
+ mimeType: "text/plain",
533
+ text: "Error: Project Knowledge Service not initialized",
534
+ }],
535
+ };
536
+ }
537
+ const content = projectKnowledgeService.getProjectContext(projectId);
538
+ if (!content) {
539
+ return {
540
+ contents: [{
541
+ uri: uri.href,
542
+ mimeType: "text/plain",
543
+ text: `No project context found for project "${projectId}". Run memorybank_initialize first.`,
544
+ }],
545
+ };
546
+ }
547
+ return {
548
+ contents: [{
549
+ uri: uri.href,
550
+ mimeType: "text/markdown",
551
+ text: content,
552
+ }],
553
+ };
554
+ });
555
+ // Resource: System Patterns
556
+ server.resource("memory://*/patterns", "Patrones de sistema: arquitectura, patrones de diseño y organización del código", async (uri) => {
557
+ const projectId = uri.pathname.split("/")[0] || uri.host;
558
+ if (!projectKnowledgeService) {
559
+ return {
560
+ contents: [{
561
+ uri: uri.href,
562
+ mimeType: "text/plain",
563
+ text: "Error: Project Knowledge Service not initialized",
564
+ }],
565
+ };
566
+ }
567
+ const content = projectKnowledgeService.getProjectDocument(projectId, "systemPatterns");
568
+ if (!content) {
569
+ return {
570
+ contents: [{
571
+ uri: uri.href,
572
+ mimeType: "text/plain",
573
+ text: `No system patterns found for project "${projectId}". Run memorybank_initialize or memorybank_generate_project_docs first.`,
574
+ }],
575
+ };
576
+ }
577
+ return {
578
+ contents: [{
579
+ uri: uri.href,
580
+ mimeType: "text/markdown",
581
+ text: content,
582
+ }],
583
+ };
584
+ });
585
+ // Resource: Project Brief
586
+ server.resource("memory://*/brief", "Descripción del proyecto: propósito, objetivos y audiencia", async (uri) => {
587
+ const projectId = uri.pathname.split("/")[0] || uri.host;
588
+ if (!projectKnowledgeService) {
589
+ return {
590
+ contents: [{
591
+ uri: uri.href,
592
+ mimeType: "text/plain",
593
+ text: "Error: Project Knowledge Service not initialized",
594
+ }],
595
+ };
596
+ }
597
+ const content = projectKnowledgeService.getProjectDocument(projectId, "projectBrief");
598
+ if (!content) {
599
+ return {
600
+ contents: [{
601
+ uri: uri.href,
602
+ mimeType: "text/plain",
603
+ text: `No project brief found for project "${projectId}". Run memorybank_initialize or memorybank_generate_project_docs first.`,
604
+ }],
605
+ };
606
+ }
607
+ return {
608
+ contents: [{
609
+ uri: uri.href,
610
+ mimeType: "text/markdown",
611
+ text: content,
612
+ }],
613
+ };
614
+ });
255
615
  /**
256
616
  * Validates and initializes environment
257
617
  */
@@ -328,16 +688,29 @@ async function startStdioServer() {
328
688
  await server.connect(transport);
329
689
  console.error("\n=== MCP Server Ready ===");
330
690
  console.error("Available tools:");
331
- console.error(" Core Memory Bank:");
691
+ console.error(" Core Memory Bank (Cursor-style):");
332
692
  console.error(" - memorybank_index_code: Indexar código semánticamente");
333
693
  console.error(" - memorybank_search: Buscar código por similitud semántica");
334
694
  console.error(" - memorybank_read_file: Leer archivos del workspace");
335
695
  console.error(" - memorybank_write_file: Escribir archivos y reindexar");
336
696
  console.error(" - memorybank_get_stats: Obtener estadísticas del índice");
337
697
  console.error(" - memorybank_analyze_coverage: Analizar cobertura de indexación");
338
- console.error(" Project Knowledge Layer:");
698
+ console.error(" Project Knowledge Layer (AI Docs):");
339
699
  console.error(" - memorybank_generate_project_docs: Generar documentación con IA");
340
700
  console.error(" - memorybank_get_project_docs: Leer documentación del proyecto");
701
+ console.error(" Context Management (Cline-style):");
702
+ console.error(" - memorybank_initialize: Inicializar Memory Bank para un proyecto");
703
+ console.error(" - memorybank_update_context: Actualizar contexto de sesión");
704
+ console.error(" - memorybank_record_decision: Registrar decisiones técnicas");
705
+ console.error(" - memorybank_track_progress: Actualizar progreso del proyecto");
706
+ console.error("");
707
+ console.error("Available resources:");
708
+ console.error(" - memory://{projectId}/active: Contexto activo");
709
+ console.error(" - memory://{projectId}/progress: Seguimiento de progreso");
710
+ console.error(" - memory://{projectId}/decisions: Log de decisiones");
711
+ console.error(" - memory://{projectId}/context: Contexto del proyecto");
712
+ console.error(" - memory://{projectId}/patterns: Patrones de sistema");
713
+ console.error(" - memory://{projectId}/brief: Descripción del proyecto");
341
714
  console.error("");
342
715
  console.error("Ready to accept requests...\n");
343
716
  }
@@ -177,7 +177,7 @@ function generateRecommendations(stats, tree) {
177
177
  }
178
178
  // Pending reindex
179
179
  if (stats.pendingReindexFiles > 0) {
180
- recommendations.push(`🔄 Hay ${stats.pendingReindexFiles} archivo(s) con cambios pendientes de reindexación. Ejecuta memorybank_index_code({ forceReindex: true })`);
180
+ recommendations.push(`🔄 Hay ${stats.pendingReindexFiles} archivo(s) con cambios pendientes. Ejecuta memorybank_index_code con el path del directorio - los cambios se detectan automáticamente por hash.`);
181
181
  }
182
182
  // Language-specific recommendations
183
183
  const unindexedLanguages = Object.entries(stats.languageBreakdown)