@grec0/memory-bank-mcp 0.0.4 → 0.0.6

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/README.md CHANGED
@@ -153,18 +153,25 @@ Edita tu archivo de configuración de Claude Desktop:
153
153
 
154
154
  ## 📚 Herramientas Disponibles
155
155
 
156
+ > **⚠️ IMPORTANTE**: Todas las herramientas requieren `projectId` obligatorio. Este ID debe coincidir con el definido en tu archivo `AGENTS.md`.
157
+
156
158
  ### `memorybank_index_code`
157
159
 
158
160
  Indexa código semánticamente para permitir búsquedas.
159
161
 
160
162
  **Parámetros:**
163
+ - `projectId` **(REQUERIDO)**: Identificador único del proyecto
161
164
  - `path` (opcional): Ruta relativa o absoluta (default: raíz del workspace)
162
165
  - `recursive` (opcional): Indexar subdirectorios (default: true)
163
166
  - `forceReindex` (opcional): Forzar reindexación completa (default: false)
164
167
 
165
168
  **Ejemplo:**
166
- ```
167
- memorybank_index_code({ path: "src/auth", recursive: true })
169
+ ```json
170
+ {
171
+ "projectId": "my-project",
172
+ "path": "src/auth",
173
+ "recursive": true
174
+ }
168
175
  ```
169
176
 
170
177
  ### `memorybank_search`
@@ -172,6 +179,7 @@ memorybank_index_code({ path: "src/auth", recursive: true })
172
179
  Busca código por similitud semántica.
173
180
 
174
181
  **Parámetros:**
182
+ - `projectId` **(REQUERIDO)**: Identificador del proyecto donde buscar
175
183
  - `query` (requerido): Consulta en lenguaje natural
176
184
  - `topK` (opcional): Número de resultados (default: 10)
177
185
  - `minScore` (opcional): Score mínimo 0-1 (default: 0.4)
@@ -179,12 +187,13 @@ Busca código por similitud semántica.
179
187
  - `filterByLanguage` (opcional): Filtrar por lenguaje
180
188
 
181
189
  **Ejemplo:**
182
- ```
183
- memorybank_search({
184
- query: "función que autentica usuarios con JWT",
185
- topK: 5,
186
- minScore: 0.8
187
- })
190
+ ```json
191
+ {
192
+ "projectId": "my-project",
193
+ "query": "función que autentica usuarios con JWT",
194
+ "topK": 5,
195
+ "minScore": 0.8
196
+ }
188
197
  ```
189
198
 
190
199
  ### `memorybank_read_file`
@@ -206,16 +215,18 @@ memorybank_read_file({ path: "src/auth/service.ts", startLine: 50, endLine: 100
206
215
  Escribe un archivo y lo reindexa automáticamente.
207
216
 
208
217
  **Parámetros:**
218
+ - `projectId` **(REQUERIDO)**: Identificador del proyecto para reindexación
209
219
  - `path` (requerido): Ruta del archivo
210
220
  - `content` (requerido): Contenido del archivo
211
221
  - `autoReindex` (opcional): Auto-reindexar (default: true)
212
222
 
213
223
  **Ejemplo:**
214
- ```
215
- memorybank_write_file({
216
- path: "src/utils/validator.ts",
217
- content: "export function validateEmail(email: string) { ... }"
218
- })
224
+ ```json
225
+ {
226
+ "projectId": "my-project",
227
+ "path": "src/utils/validator.ts",
228
+ "content": "export function validateEmail(email: string) { ... }"
229
+ }
219
230
  ```
220
231
 
221
232
  ### `memorybank_get_stats`
@@ -231,9 +242,15 @@ memorybank_get_stats({})
231
242
 
232
243
  Analiza la cobertura de indexación del proyecto.
233
244
 
245
+ **Parámetros:**
246
+ - `projectId` **(REQUERIDO)**: Identificador del proyecto a analizar
247
+ - `path` (opcional): Ruta específica a analizar
248
+
234
249
  **Ejemplo:**
235
- ```
236
- memorybank_analyze_coverage({})
250
+ ```json
251
+ {
252
+ "projectId": "my-project"
253
+ }
237
254
  ```
238
255
 
239
256
  ### `memorybank_generate_project_docs` 🆕
@@ -241,12 +258,15 @@ memorybank_analyze_coverage({})
241
258
  Genera documentación estructurada del proyecto usando IA con razonamiento (gpt-5-mini).
242
259
 
243
260
  **Parámetros:**
244
- - `projectId` (opcional): ID del proyecto
261
+ - `projectId` **(REQUERIDO)**: Identificador del proyecto
245
262
  - `force` (opcional): Forzar regeneración (default: false)
246
263
 
247
264
  **Ejemplo:**
248
- ```
249
- memorybank_generate_project_docs({ force: true })
265
+ ```json
266
+ {
267
+ "projectId": "my-project",
268
+ "force": true
269
+ }
250
270
  ```
251
271
 
252
272
  Genera 6 documentos markdown:
@@ -262,16 +282,119 @@ Genera 6 documentos markdown:
262
282
  Lee la documentación del proyecto generada por IA.
263
283
 
264
284
  **Parámetros:**
285
+ - `projectId` **(REQUERIDO)**: Identificador del proyecto
265
286
  - `document` (opcional): Documento específico o "all"/"summary" (default: "summary")
266
287
  - `format` (opcional): "full" o "summary" (default: "full")
267
288
 
268
289
  **Ejemplo:**
269
- ```
290
+ ```json
270
291
  // Obtener resumen de todos los docs
271
- memorybank_get_project_docs({ document: "summary" })
292
+ {
293
+ "projectId": "my-project",
294
+ "document": "summary"
295
+ }
272
296
 
273
297
  // Obtener documento específico
274
- memorybank_get_project_docs({ document: "systemPatterns" })
298
+ {
299
+ "projectId": "my-project",
300
+ "document": "systemPatterns"
301
+ }
302
+ ```
303
+
304
+ ## 📋 Plantillas de Instrucciones para Agentes
305
+
306
+ Memory Bank incluye plantillas de instrucciones en dos formatos:
307
+ - **AGENTS.md** - Estándar [agents.md](https://agents.md/) (compatible con múltiples agentes)
308
+ - **VSCode/Copilot** - Formato `.github/copilot-instructions.md` para VS Code
309
+
310
+ ### Instalación - Formato AGENTS.md
311
+
312
+ Copia la plantilla que prefieras a la raíz de tu proyecto:
313
+
314
+ ```bash
315
+ # Elegir una plantilla
316
+ cp node_modules/@grec0/memory-bank-mcp/templates/AGENTS.basic.md ./AGENTS.md
317
+
318
+ # Editar los placeholders
319
+ # Reemplaza {{PROJECT_ID}} con tu ID de proyecto
320
+ # Reemplaza {{WORKSPACE_PATH}} con la ruta del workspace
321
+ ```
322
+
323
+ ### Instalación - Formato VS Code
324
+
325
+ Para VS Code con GitHub Copilot, usa el formato `copilot-instructions.md`:
326
+
327
+ ```bash
328
+ # Crear carpeta .github si no existe
329
+ mkdir -p .github
330
+
331
+ # Elegir una plantilla
332
+ cp node_modules/@grec0/memory-bank-mcp/templates/vscode/copilot-instructions.basic.md ./.github/copilot-instructions.md
333
+
334
+ # Habilitar en VS Code settings.json:
335
+ # "github.copilot.chat.codeGeneration.useInstructionFiles": true
336
+ ```
337
+
338
+ También puedes usar el archivo `.instructions.md` con aplicación condicional:
339
+
340
+ ```bash
341
+ # Crear carpeta de instrucciones
342
+ mkdir -p .github/instructions
343
+
344
+ # Copiar instrucciones base
345
+ cp node_modules/@grec0/memory-bank-mcp/templates/vscode/memory-bank.instructions.md ./.github/instructions/
346
+ ```
347
+
348
+ ### 1. Basic Mode (`AGENTS.basic.md`)
349
+
350
+ **Para proyectos donde quieres control total.**
351
+
352
+ - ✅ El agente SIEMPRE consulta el Memory Bank antes de actuar
353
+ - ✅ Solo indexa cuando el usuario lo solicita explícitamente
354
+ - ✅ Pide permiso antes de modificar código
355
+ - ✅ Sugiere reindexar después de cambios
356
+
357
+ **Ideal para**: Proyectos críticos, revisión de código, onboarding.
358
+
359
+ ### 2. Auto-Index Mode (`AGENTS.auto-index.md`)
360
+
361
+ **Para desarrollo activo con sincronización automática.**
362
+
363
+ - ✅ El agente consulta el Memory Bank automáticamente
364
+ - ✅ Reindexa CADA archivo después de modificarlo
365
+ - ✅ Mantiene el Memory Bank siempre actualizado
366
+ - ✅ Puede leer/escribir archivos directamente
367
+
368
+ **Ideal para**: Desarrollo activo, iteración rápida, equipos.
369
+
370
+ ### 3. Sandboxed Mode (`AGENTS.sandboxed.md`)
371
+
372
+ **Para entornos sin acceso directo al sistema de archivos.**
373
+
374
+ - ✅ NO tiene acceso directo a archivos
375
+ - ✅ DEBE usar `memorybank_read_file` para leer
376
+ - ✅ DEBE usar `memorybank_write_file` para escribir
377
+ - ✅ Auto-reindexa automáticamente en cada escritura
378
+
379
+ **Ideal para**: Entornos restringidos, desarrollo remoto, seguridad.
380
+
381
+ ### Ejemplo de `AGENTS.md` Configurado
382
+
383
+ ```markdown
384
+ # AGENTS.md
385
+
386
+ ## Project Configuration
387
+ - **Project ID**: `my-awesome-app`
388
+ - **Workspace**: `/home/user/projects/my-awesome-app`
389
+
390
+ ## Memory Bank Instructions
391
+
392
+ ### CRITICAL: Always Consult Before Acting
393
+ Before any action, call `memorybank_search` with projectId="my-awesome-app"
394
+
395
+ ### Auto-Indexing Policy
396
+ AFTER every file modification:
397
+ memorybank_index_code({ projectId: "my-awesome-app", path: "<modified_file>" })
275
398
  ```
276
399
 
277
400
  ## 🎯 Casos de Uso
@@ -279,13 +402,13 @@ memorybank_get_project_docs({ document: "systemPatterns" })
279
402
  ### 1. Primera Indexación
280
403
 
281
404
  ```
282
- Usuario: Hola, quiero que me ayudes con mi proyecto
405
+ Usuario: Hola, quiero que me ayudes con mi proyecto. El projectId es "my-app"
283
406
  Claude: [ejecuta memorybank_get_stats]
284
407
  Veo que no hay código indexado aún.
285
408
  ¿Deseas que indexe el proyecto para poder ayudarte mejor?
286
409
 
287
410
  Usuario: Sí
288
- Claude: [ejecuta memorybank_index_code({})]
411
+ Claude: [ejecuta memorybank_index_code({ projectId: "my-app" })]
289
412
  He indexado 145 archivos (1,234 chunks) en 45 segundos.
290
413
  ¿En qué puedo ayudarte?
291
414
  ```
@@ -294,7 +417,7 @@ Claude: [ejecuta memorybank_index_code({})]
294
417
 
295
418
  ```
296
419
  Usuario: ¿Cómo funciona la autenticación en este proyecto?
297
- Claude: [ejecuta memorybank_search({ query: "autenticación login usuarios" })]
420
+ Claude: [ejecuta memorybank_search({ projectId: "my-app", query: "autenticación login usuarios" })]
298
421
 
299
422
  La autenticación se implementa en src/auth/authService.ts (líneas 23-87):
300
423
 
@@ -308,11 +431,11 @@ Claude: [ejecuta memorybank_search({ query: "autenticación login usuarios" })]
308
431
 
309
432
  ```
310
433
  Usuario: Añade validación de email al formulario de registro
311
- Claude: [busca formulario de registro]
312
- [busca validadores existentes]
434
+ Claude: [busca formulario de registro con projectId]
435
+ [busca validadores existentes con projectId]
313
436
  [lee archivo actual]
314
437
  [genera código respetando estilo del proyecto]
315
- [escribe archivo con memorybank_write_file]
438
+ [escribe archivo con memorybank_write_file({ projectId: "my-app", ... })]
316
439
 
317
440
  He añadido la validación de email en src/forms/RegisterForm.tsx línea 45.
318
441
  Usa el validador existente de emailValidator.ts para mantener consistencia.
@@ -440,16 +563,32 @@ El sistema maneja automáticamente rate limits con exponential backoff, pero si
440
563
 
441
564
  ### Índice desactualizado
442
565
 
443
- ```
566
+ ```json
444
567
  memorybank_get_stats({})
445
568
  ```
446
569
 
447
570
  Si `pendingFiles` muestra archivos pendientes:
448
571
 
572
+ ```json
573
+ {
574
+ "projectId": "my-project",
575
+ "forceReindex": true
576
+ }
449
577
  ```
450
- memorybank_index_code({ forceReindex: true })
578
+
579
+ ### Error: "projectId is required"
580
+
581
+ **Solución**: Todas las herramientas requieren `projectId`. Asegúrate de incluirlo en cada llamada:
582
+
583
+ ```json
584
+ {
585
+ "projectId": "my-project",
586
+ "query": "..."
587
+ }
451
588
  ```
452
589
 
590
+ Tip: Define el `projectId` en tu archivo `AGENTS.md` para que el agente lo use consistentemente.
591
+
453
592
  ## 🤝 Contribución
454
593
 
455
594
  ¡Contribuciones son bienvenidas!
@@ -462,7 +601,16 @@ memorybank_index_code({ forceReindex: true })
462
601
 
463
602
  ## 📖 Documentación Adicional
464
603
 
465
- - [AGENT_INSTRUCTIONS.md](AGENT_INSTRUCTIONS.md): Guía completa para agentes de IA
604
+ - [templates/](templates/): Plantillas de instrucciones para agentes
605
+ - **Formato AGENTS.md** (estándar multi-agente):
606
+ - `AGENTS.basic.md`: Modo básico (indexación manual)
607
+ - `AGENTS.auto-index.md`: Modo auto-indexación
608
+ - `AGENTS.sandboxed.md`: Modo sin acceso directo a archivos
609
+ - **Formato VS Code** (`templates/vscode/`):
610
+ - `copilot-instructions.basic.md`: Modo básico para Copilot
611
+ - `copilot-instructions.auto-index.md`: Modo auto-indexación para Copilot
612
+ - `copilot-instructions.sandboxed.md`: Modo sandboxed para Copilot
613
+ - `memory-bank.instructions.md`: Instrucciones con aplicación condicional
466
614
  - [wiki/Developer-Guide.md](wiki/Developer-Guide.md): Guía para desarrolladores
467
615
  - [wiki/API-Reference.md](wiki/API-Reference.md): Referencia completa de API
468
616
 
@@ -6,6 +6,12 @@ import * as fs from "fs";
6
6
  import * as path from "path";
7
7
  import { scanFiles, scanSingleFile } from "./fileScanner.js";
8
8
  import { chunkCode } from "./chunker.js";
9
+ /**
10
+ * Normalizes a path to use forward slashes for consistent cross-platform behavior
11
+ */
12
+ function normalizePath(filePath) {
13
+ return filePath.split(path.sep).join('/');
14
+ }
9
15
  /**
10
16
  * Index manager coordinating the entire indexing pipeline
11
17
  */
@@ -43,9 +49,16 @@ export class IndexManager {
43
49
  */
44
50
  loadMetadata() {
45
51
  try {
52
+ console.error(`Loading metadata from: ${this.metadataPath}`);
46
53
  if (fs.existsSync(this.metadataPath)) {
47
54
  const data = fs.readFileSync(this.metadataPath, "utf-8");
48
- return JSON.parse(data);
55
+ const metadata = JSON.parse(data);
56
+ const fileCount = Object.keys(metadata.files || {}).length;
57
+ console.error(`Loaded metadata: ${fileCount} files tracked`);
58
+ return metadata;
59
+ }
60
+ else {
61
+ console.error(`Metadata file not found: ${this.metadataPath}`);
49
62
  }
50
63
  }
51
64
  catch (error) {
@@ -66,7 +79,9 @@ export class IndexManager {
66
79
  if (!fs.existsSync(dir)) {
67
80
  fs.mkdirSync(dir, { recursive: true });
68
81
  }
82
+ const fileCount = Object.keys(this.metadata.files).length;
69
83
  fs.writeFileSync(this.metadataPath, JSON.stringify(this.metadata, null, 2));
84
+ console.error(` Saved metadata: ${fileCount} files tracked → ${this.metadataPath}`);
70
85
  }
71
86
  catch (error) {
72
87
  console.error(`Warning: Could not save index metadata: ${error}`);
@@ -79,11 +94,21 @@ export class IndexManager {
79
94
  if (forceReindex) {
80
95
  return true;
81
96
  }
82
- const fileInfo = this.metadata.files[file.path];
97
+ // Use normalized path for consistent lookup
98
+ const normalizedPath = normalizePath(file.path);
99
+ const fileInfo = this.metadata.files[normalizedPath];
83
100
  if (!fileInfo) {
101
+ // Debug: show first few new files
102
+ const trackedCount = Object.keys(this.metadata.files).length;
103
+ if (trackedCount === 0) {
104
+ console.error(` New file (no metadata): ${normalizedPath}`);
105
+ }
84
106
  return true; // New file
85
107
  }
86
108
  if (fileInfo.hash !== file.hash) {
109
+ console.error(` Changed file: ${normalizedPath}`);
110
+ console.error(` Stored hash: ${fileInfo.hash.substring(0, 16)}...`);
111
+ console.error(` Current hash: ${file.hash.substring(0, 16)}...`);
87
112
  return true; // File changed
88
113
  }
89
114
  return false;
@@ -128,11 +153,12 @@ export class IndexManager {
128
153
  // Prepare chunk records for storage (using snake_case for LanceDB)
129
154
  // Note: All fields must have non-undefined values for LanceDB Arrow conversion
130
155
  const timestamp = Date.now();
131
- console.error(` Storing chunks with project_id: '${projectId}'`);
156
+ const normalizedFilePath = normalizePath(file.path);
157
+ console.error(` Storing chunks with project_id: '${projectId}', file: '${normalizedFilePath}'`);
132
158
  const chunkRecords = chunks.map((chunk, i) => ({
133
159
  id: chunk.id,
134
160
  vector: embeddings[i].vector,
135
- file_path: chunk.filePath,
161
+ file_path: normalizedFilePath, // Use normalized path for consistency
136
162
  content: chunk.content,
137
163
  start_line: chunk.startLine,
138
164
  end_line: chunk.endLine,
@@ -144,13 +170,13 @@ export class IndexManager {
144
170
  context: chunk.context || "", // Ensure non-undefined for LanceDB
145
171
  project_id: projectId,
146
172
  }));
147
- // Delete old chunks for this file
148
- await this.vectorStore.deleteChunksByFile(file.path);
173
+ // Delete old chunks for this file using normalized path
174
+ await this.vectorStore.deleteChunksByFile(normalizedFilePath);
149
175
  // Insert new chunks
150
176
  await this.vectorStore.insertChunks(chunkRecords);
151
177
  console.error(` Stored ${chunkRecords.length} chunks in vector store`);
152
- // Update metadata
153
- this.metadata.files[file.path] = {
178
+ // Update metadata with normalized path for consistent lookups
179
+ this.metadata.files[normalizedFilePath] = {
154
180
  hash: file.hash,
155
181
  lastIndexed: timestamp,
156
182
  chunkCount: chunks.length,
@@ -191,19 +217,36 @@ export class IndexManager {
191
217
  const shouldAutoUpdateDocs = options.autoUpdateDocs !== undefined
192
218
  ? options.autoUpdateDocs
193
219
  : this.autoUpdateDocs;
220
+ // Use workspaceRoot for consistent path normalization, fallback to rootPath
221
+ const workspaceRoot = options.workspaceRoot || options.rootPath;
194
222
  console.error(`\n=== Starting indexing process ===`);
195
223
  console.error(`Root path: ${options.rootPath}`);
224
+ console.error(`Workspace root: ${workspaceRoot}`);
196
225
  console.error(`Project ID: ${projectId}`);
197
226
  console.error(`Force reindex: ${options.forceReindex || false}`);
198
227
  console.error(`Auto-update docs: ${shouldAutoUpdateDocs}`);
199
228
  // Initialize vector store
200
229
  await this.vectorStore.initialize();
201
- // Scan files
230
+ // Scan files - always use workspaceRoot for consistent relative paths
202
231
  console.error(`\nScanning files...`);
203
232
  const files = scanFiles({
204
233
  rootPath: options.rootPath,
205
234
  recursive: options.recursive !== undefined ? options.recursive : true,
206
235
  });
236
+ // Normalize paths to be relative to workspaceRoot, not rootPath
237
+ // This ensures consistent paths in metadata regardless of which subfolder was indexed
238
+ if (workspaceRoot !== options.rootPath) {
239
+ const rootPathResolved = path.resolve(options.rootPath);
240
+ const workspaceRootResolved = path.resolve(workspaceRoot);
241
+ for (const file of files) {
242
+ // Convert path from relative-to-rootPath to relative-to-workspaceRoot
243
+ const absolutePath = path.join(rootPathResolved, file.path);
244
+ file.path = path.relative(workspaceRootResolved, absolutePath);
245
+ // Use forward slashes for consistency
246
+ file.path = file.path.split(path.sep).join('/');
247
+ }
248
+ console.error(` Normalized ${files.length} file paths to workspace root`);
249
+ }
207
250
  if (files.length === 0) {
208
251
  console.error("No files found to index");
209
252
  return {
@@ -351,6 +394,7 @@ export class IndexManager {
351
394
  const queryVector = await this.embeddingService.generateQueryEmbedding(query);
352
395
  // Search vector store
353
396
  const results = await this.vectorStore.search(queryVector, {
397
+ filterByProject: options.projectId,
354
398
  topK: options.topK || 10,
355
399
  minScore: options.minScore || 0.0,
356
400
  filterByFile: options.filterByFile,
package/dist/index.js CHANGED
@@ -33,7 +33,10 @@ const server = new McpServer({
33
33
  version: VERSION,
34
34
  });
35
35
  // 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", {
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", {
37
+ projectId: z
38
+ .string()
39
+ .describe("Identificador único del proyecto (OBLIGATORIO). Debe coincidir con el definido en AGENTS.md del proyecto"),
37
40
  path: z
38
41
  .string()
39
42
  .optional()
@@ -50,6 +53,7 @@ server.tool("memorybank_index_code", "Indexa semánticamente código de un direc
50
53
  .describe("Forzar reindexación completa aunque no haya cambios"),
51
54
  }, async (args) => {
52
55
  const result = await indexCode({
56
+ projectId: args.projectId,
53
57
  path: args.path,
54
58
  recursive: args.recursive,
55
59
  forceReindex: args.forceReindex,
@@ -59,7 +63,10 @@ server.tool("memorybank_index_code", "Indexa semánticamente código de un direc
59
63
  };
60
64
  });
61
65
  // Tool: Search Memory Bank
62
- server.tool("memorybank_search", "Busca código relevante mediante búsqueda semántica vectorial. Usa esta herramienta SIEMPRE que necesites información sobre el código", {
66
+ server.tool("memorybank_search", "Busca código relevante mediante búsqueda semántica vectorial. Usa esta herramienta SIEMPRE que necesites información sobre el código. El projectId es OBLIGATORIO", {
67
+ projectId: z
68
+ .string()
69
+ .describe("Identificador del proyecto donde buscar (OBLIGATORIO). Debe coincidir con el usado al indexar"),
63
70
  query: z
64
71
  .string()
65
72
  .describe("Consulta semántica: describe qué estás buscando en lenguaje natural (ej: 'función de autenticación', '¿cómo se validan los emails?')"),
@@ -83,6 +90,7 @@ server.tool("memorybank_search", "Busca código relevante mediante búsqueda sem
83
90
  .describe("Filtrar resultados por lenguaje de programación (ej: 'typescript', 'python')"),
84
91
  }, async (args) => {
85
92
  const result = await searchMemory({
93
+ projectId: args.projectId,
86
94
  query: args.query,
87
95
  topK: args.topK,
88
96
  minScore: args.minScore,
@@ -117,7 +125,10 @@ server.tool("memorybank_read_file", "Lee el contenido de un archivo específico
117
125
  };
118
126
  });
119
127
  // Tool: Write File
120
- server.tool("memorybank_write_file", "Escribe o modifica un archivo y automáticamente lo reindexa en el Memory Bank para mantener la consistencia", {
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", {
129
+ projectId: z
130
+ .string()
131
+ .describe("Identificador del proyecto (OBLIGATORIO). Necesario para la auto-reindexación correcta"),
121
132
  path: z
122
133
  .string()
123
134
  .describe("Ruta relativa o absoluta del archivo a escribir"),
@@ -131,6 +142,7 @@ server.tool("memorybank_write_file", "Escribe o modifica un archivo y automátic
131
142
  .describe("Reindexar automáticamente el archivo después de escribirlo"),
132
143
  }, async (args) => {
133
144
  const result = await writeFile({
145
+ projectId: args.projectId,
134
146
  path: args.path,
135
147
  content: args.content,
136
148
  autoReindex: args.autoReindex,
@@ -147,9 +159,17 @@ server.tool("memorybank_get_stats", "Obtiene estadísticas del Memory Bank: arch
147
159
  };
148
160
  });
149
161
  // Tool: Analyze Coverage
150
- 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. Perfecto para visualizar el estado del conocimiento del agente sobre el proyecto. NOTA: Puede tardar en workspaces grandes", {}, async () => {
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", {
163
+ projectId: z
164
+ .string()
165
+ .describe("Identificador del proyecto a analizar (OBLIGATORIO)"),
166
+ path: z
167
+ .string()
168
+ .describe("Ruta absoluta del workspace a analizar (OBLIGATORIO). Ejemplo: 'C:/workspaces/mi-proyecto'"),
169
+ }, async (args) => {
151
170
  try {
152
- const result = await analyzeCoverage(indexManager, vectorStore, workspaceRoot);
171
+ const targetPath = args.path;
172
+ const result = await analyzeCoverage(indexManager, vectorStore, targetPath, args.projectId);
153
173
  return {
154
174
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
155
175
  };
@@ -189,11 +209,10 @@ server.tool("memorybank_analyze_coverage", "Analiza la cobertura de indexación
189
209
  }
190
210
  });
191
211
  // Tool: Generate Project Docs
192
- server.tool(generateProjectDocsToolDefinition.name, generateProjectDocsToolDefinition.description, {
212
+ server.tool(generateProjectDocsToolDefinition.name, generateProjectDocsToolDefinition.description + ". El projectId es OBLIGATORIO", {
193
213
  projectId: z
194
214
  .string()
195
- .optional()
196
- .describe("ID del proyecto (opcional, usa 'default' si no se especifica)"),
215
+ .describe("Identificador del proyecto (OBLIGATORIO). Debe coincidir con el usado al indexar"),
197
216
  force: z
198
217
  .boolean()
199
218
  .optional()
@@ -209,7 +228,10 @@ server.tool(generateProjectDocsToolDefinition.name, generateProjectDocsToolDefin
209
228
  };
210
229
  });
211
230
  // Tool: Get Project Docs
212
- server.tool(getProjectDocsToolDefinition.name, getProjectDocsToolDefinition.description, {
231
+ server.tool(getProjectDocsToolDefinition.name, getProjectDocsToolDefinition.description + ". El projectId es OBLIGATORIO", {
232
+ projectId: z
233
+ .string()
234
+ .describe("Identificador del proyecto (OBLIGATORIO). Debe coincidir con el usado al generar los docs"),
213
235
  document: z
214
236
  .string()
215
237
  .optional()
@@ -222,6 +244,7 @@ server.tool(getProjectDocsToolDefinition.name, getProjectDocsToolDefinition.desc
222
244
  .describe("Formato de salida: 'full' devuelve contenido completo, 'summary' devuelve resumen de todos los docs"),
223
245
  }, async (args) => {
224
246
  const result = await getProjectDocs({
247
+ projectId: args.projectId,
225
248
  document: args.document,
226
249
  format: args.format,
227
250
  }, projectKnowledgeService);
@@ -203,10 +203,13 @@ function generateRecommendations(stats, tree) {
203
203
  /**
204
204
  * Analyzes indexation coverage of the project
205
205
  */
206
- export async function analyzeCoverage(indexManager, vectorStore, workspaceRoot) {
206
+ export async function analyzeCoverage(indexManager, vectorStore, workspaceRoot, projectId) {
207
207
  try {
208
208
  console.error("\n=== Analizando cobertura de indexación ===");
209
209
  console.error(`Workspace root: ${workspaceRoot}`);
210
+ if (projectId) {
211
+ console.error(`Project ID: ${projectId}`);
212
+ }
210
213
  // 1. Scan all code files in workspace with timeout protection
211
214
  console.error("Escaneando archivos del workspace...");
212
215
  // Add timeout and file limit protection
@@ -15,12 +15,15 @@ export async function indexCode(params, indexManager, workspaceRoot) {
15
15
  : path.join(workspaceRoot, params.path)
16
16
  : workspaceRoot;
17
17
  console.error(`\nIndexing code at: ${targetPath}`);
18
+ console.error(`Project ID: ${params.projectId}`);
18
19
  console.error(`Workspace root: ${workspaceRoot}`);
19
20
  console.error(`Recursive: ${params.recursive !== false}`);
20
21
  console.error(`Force reindex: ${params.forceReindex || false}`);
21
- // Run indexing
22
+ // Run indexing - pass workspaceRoot for consistent path normalization
22
23
  const result = await indexManager.indexFiles({
24
+ projectId: params.projectId,
23
25
  rootPath: targetPath,
26
+ workspaceRoot: workspaceRoot, // Always normalize paths relative to workspace
24
27
  recursive: params.recursive !== false,
25
28
  forceReindex: params.forceReindex || false,
26
29
  });
@@ -17,6 +17,7 @@ export async function searchMemory(params, indexManager) {
17
17
  };
18
18
  }
19
19
  console.error(`\nSearching Memory Bank for: "${params.query}"`);
20
+ console.error(`Project ID: ${params.projectId}`);
20
21
  console.error(`Top K: ${params.topK || 10}`);
21
22
  console.error(`Min score: ${params.minScore || 0.4}`);
22
23
  if (params.filterByFile) {
@@ -27,6 +28,7 @@ export async function searchMemory(params, indexManager) {
27
28
  }
28
29
  // Search
29
30
  const results = await indexManager.search(params.query, {
31
+ projectId: params.projectId,
30
32
  topK: params.topK || 10,
31
33
  minScore: params.minScore !== undefined ? params.minScore : 0.4,
32
34
  filterByFile: params.filterByFile,
@@ -28,8 +28,8 @@ export async function writeFile(params, indexManager, workspaceRoot) {
28
28
  let chunksCreated = 0;
29
29
  if (autoReindex) {
30
30
  try {
31
- console.error(`Auto-reindexing ${params.path}...`);
32
- const reindexResult = await indexManager.reindexFile(filePath, workspaceRoot);
31
+ console.error(`Auto-reindexing ${params.path} for project ${params.projectId}...`);
32
+ const reindexResult = await indexManager.reindexFile(filePath, workspaceRoot, params.projectId);
33
33
  if (reindexResult.success) {
34
34
  reindexed = true;
35
35
  chunksCreated = reindexResult.chunksCreated;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grec0/memory-bank-mcp",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "MCP server for semantic code indexing with Memory Bank - AI-powered codebase understanding",
5
5
  "license": "MIT",
6
6
  "author": "@grec0",