rag-memory-epf-mcp 3.3.6 → 3.4.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.
package/dist/index.js CHANGED
@@ -1170,6 +1170,46 @@ class RAGKnowledgeGraphManager {
1170
1170
  throw new Error('Embedding model not initialized. The server may still be loading the model — retry in a few seconds.');
1171
1171
  }
1172
1172
  // === NEW SEPARATE TOOLS ===
1173
+ async syncDocumentFromFile(filePath, documentId, options = {}) {
1174
+ if (!this.db)
1175
+ throw new Error('Database not initialized');
1176
+ // 1. Resolve content: raw file verbatim (default) or explicit override.
1177
+ // Content is read on the server and never routed through the model context.
1178
+ const content = options.content !== undefined
1179
+ ? options.content
1180
+ : fsSync.readFileSync(filePath, 'utf-8');
1181
+ const bytes = Buffer.byteLength(content, 'utf-8');
1182
+ // 2. Metadata: default source=path, updated=today (YYYY-MM-DD); caller can override either.
1183
+ const today = new Date().toISOString().slice(0, 10);
1184
+ const metadata = { source: filePath, updated: today, ...(options.metadata || {}) };
1185
+ console.error(`🔄 syncDocumentFromFile: ${documentId} <- ${filePath} (${bytes} bytes)`);
1186
+ // 3. delete -> store -> chunk -> embed, reusing the existing pipeline methods.
1187
+ await this.deleteDocuments(documentId);
1188
+ await this.storeDocument(documentId, content, metadata);
1189
+ const chunkResult = await this.chunkDocument(documentId, options.chunkParams || {});
1190
+ const embedResult = await this.embedChunks(documentId);
1191
+ // 4. Optional explicit entity links (in addition to auto term-matching in embedChunks).
1192
+ let explicitlyLinked;
1193
+ if (options.entityNames && options.entityNames.length > 0) {
1194
+ const linkResult = await this.linkEntitiesToDocument(documentId, options.entityNames);
1195
+ explicitlyLinked = linkResult.linkedEntities;
1196
+ }
1197
+ const linkedEntities = embedResult.linkedEntities ?? 0;
1198
+ // 5. Terse summary only (no chunk text / content echo) to keep caller context flat.
1199
+ const result = {
1200
+ documentId,
1201
+ bytes,
1202
+ chunks: chunkResult.chunks.length,
1203
+ embeddedChunks: embedResult.embeddedChunks,
1204
+ linkedEntities,
1205
+ ...(explicitlyLinked !== undefined ? { explicitlyLinked } : {}),
1206
+ };
1207
+ if (linkedEntities === 0 && explicitlyLinked === undefined) {
1208
+ result.warning = 'linkedEntities=0: ensure the file content contains entity-name literals (e.g. a wiki anchor line "RAG entity: ...") so term-matching can link entities.';
1209
+ }
1210
+ console.error(`✅ syncDocumentFromFile done: ${documentId} (${result.chunks} chunks, ${result.embeddedChunks} embedded, ${linkedEntities} linked)`);
1211
+ return result;
1212
+ }
1173
1213
  async storeDocument(id, content, metadata = {}) {
1174
1214
  if (!this.db)
1175
1215
  throw new Error('Database not initialized');
@@ -2474,6 +2514,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
2474
2514
  return { content: [{ type: "text", text: JSON.stringify(await ragKgManager.deleteDocuments(validatedArgs.documentIds), null, 2) }] };
2475
2515
  case "listDocuments":
2476
2516
  return { content: [{ type: "text", text: JSON.stringify(await ragKgManager.listDocuments(validatedArgs.includeMetadata !== false), null, 2) }] };
2517
+ case "syncDocumentFromFile":
2518
+ return { content: [{ type: "text", text: JSON.stringify(await ragKgManager.syncDocumentFromFile(validatedArgs.path, validatedArgs.documentId, {
2519
+ metadata: validatedArgs.metadata,
2520
+ content: validatedArgs.content,
2521
+ entityNames: validatedArgs.entityNames,
2522
+ chunkParams: validatedArgs.chunkParams,
2523
+ }), null, 2) }] };
2477
2524
  // NEW: Entity embedding tools
2478
2525
  case "embedAllEntities":
2479
2526
  return { content: [{ type: "text", text: JSON.stringify(await ragKgManager.embedAllEntities(), null, 2) }] };
@@ -7,6 +7,7 @@ export declare const linkEntitiesToDocumentTool: ToolDefinition;
7
7
  export declare const getKnowledgeGraphStatsTool: ToolDefinition;
8
8
  export declare const deleteDocumentsTool: ToolDefinition;
9
9
  export declare const listDocumentsTool: ToolDefinition;
10
+ export declare const syncDocumentFromFileTool: ToolDefinition;
10
11
  export declare const ragTools: {
11
12
  storeDocument: ToolDefinition;
12
13
  chunkDocument: ToolDefinition;
@@ -16,4 +17,5 @@ export declare const ragTools: {
16
17
  getKnowledgeGraphStats: ToolDefinition;
17
18
  deleteDocuments: ToolDefinition;
18
19
  listDocuments: ToolDefinition;
20
+ syncDocumentFromFile: ToolDefinition;
19
21
  };
@@ -516,6 +516,93 @@ export const listDocumentsTool = {
516
516
  schema: listDocumentsSchema,
517
517
  annotations: { readOnlyHint: true },
518
518
  };
519
+ // === SYNC DOCUMENT FROM FILE TOOL ===
520
+ const syncDocumentFromFileCapability = {
521
+ description: 'Read a file server-side and run the full document sync pipeline (delete, store, chunk, embed, link) in one call, returning only a terse summary',
522
+ parameters: {
523
+ type: 'object',
524
+ properties: {
525
+ path: {
526
+ type: 'string',
527
+ description: 'Absolute path of the file to sync. Content is read server-side and never routed through the model context.'
528
+ },
529
+ documentId: {
530
+ type: 'string',
531
+ description: 'RAG document ID to (re)create from the file'
532
+ },
533
+ metadata: {
534
+ type: 'object',
535
+ description: 'Metadata merged into the stored document (source defaults to path, updated defaults to today)',
536
+ additionalProperties: true,
537
+ optional: true
538
+ },
539
+ content: {
540
+ type: 'string',
541
+ description: 'Optional content override; if provided, this is stored instead of reading the file',
542
+ optional: true
543
+ },
544
+ entityNames: {
545
+ type: 'array',
546
+ description: 'Optional entities to explicitly link in addition to automatic term-matching',
547
+ items: { type: 'string' },
548
+ optional: true
549
+ },
550
+ chunkParams: {
551
+ type: 'object',
552
+ description: 'Optional chunking parameters { maxTokens, overlap }',
553
+ additionalProperties: true,
554
+ optional: true
555
+ }
556
+ },
557
+ required: ['path', 'documentId'],
558
+ },
559
+ };
560
+ const syncDocumentFromFileDescription = () => `<description>
561
+ Read a file on the server and perform the entire document sync pipeline in a single call:
562
+ deleteDocuments -> storeDocument -> chunkDocument -> embedChunks -> (optional) linkEntitiesToDocument.
563
+ **The file content is read server-side and is NOT routed through the model context**, and only a
564
+ terse summary is returned (no chunk text). This collapses the usual 5 tool calls per document into
565
+ one and keeps the conversation context flat, which is the dominant cost of large /sync runs.
566
+ </description>
567
+
568
+ <importantNotes>
569
+ - (!important!) **Content is read from \`path\` on the server** - it does not pass through the model context
570
+ - (!important!) **Stores the raw file verbatim** by default (higher search fidelity); pass \`content\` to override
571
+ - (!important!) **Idempotent** - the target documentId is fully re-synced (delete + recreate) each call
572
+ - (!important!) **Returns terse counts only** - { documentId, bytes, chunks, embeddedChunks, linkedEntities }
573
+ - (!important!) **Entity linking** happens automatically via term-matching during embedding; \`entityNames\` adds explicit links
574
+ </importantNotes>
575
+
576
+ <whenToUseThisTool>
577
+ - During /sync to persist a Markdown/SSOT file into the RAG store without paying the context cost of reading it into the model
578
+ - When re-syncing decision logs, current-focus, wiki pages, or any file-backed document
579
+ - As a one-call replacement for the manual storeDocument + chunkDocument + embedChunks + linkEntitiesToDocument sequence
580
+ </whenToUseThisTool>
581
+
582
+ <bestPractices>
583
+ - Use the document's canonical ID (e.g. \`current-focus\`, \`wiki-project-context\`)
584
+ - Keep an entity-name literal (e.g. wiki anchor line "RAG entity: ...") in the file so term-matching can link entities; a warning is returned if linkedEntities is 0
585
+ - Pass \`metadata.updated\` (YYYY-MM-DD) for change tracking
586
+ </bestPractices>
587
+
588
+ <examples>
589
+ - Sync current-focus: {"path": "/abs/decisions/current-focus.md", "documentId": "current-focus", "metadata": {"updated": "2026-05-23"}}
590
+ - With explicit links: {"path": "/abs/wiki/project-context.md", "documentId": "wiki-project-context", "entityNames": ["Ultimate AI Personal Assistant"]}
591
+ </examples>`;
592
+ const syncDocumentFromFileSchema = {
593
+ path: z.string().describe('Absolute path of the file to sync (read server-side)'),
594
+ documentId: z.string().describe('RAG document ID to (re)create from the file'),
595
+ metadata: z.record(z.any()).optional().describe('Metadata merged into the stored document'),
596
+ content: z.string().optional().describe('Optional content override; stored instead of reading the file'),
597
+ entityNames: z.array(z.string()).optional().describe('Optional entities to explicitly link'),
598
+ chunkParams: z.record(z.any()).optional().describe('Optional chunking parameters { maxTokens, overlap }'),
599
+ };
600
+ export const syncDocumentFromFileTool = {
601
+ capability: syncDocumentFromFileCapability,
602
+ description: syncDocumentFromFileDescription,
603
+ schema: syncDocumentFromFileSchema,
604
+ annotations: { idempotentHint: true },
605
+ };
519
606
  // Export all RAG tools
520
607
  export const ragTools = {
521
608
  storeDocument: storeDocumentTool,
@@ -526,4 +613,5 @@ export const ragTools = {
526
613
  getKnowledgeGraphStats: getKnowledgeGraphStatsTool,
527
614
  deleteDocuments: deleteDocumentsTool,
528
615
  listDocuments: listDocumentsTool,
616
+ syncDocumentFromFile: syncDocumentFromFileTool,
529
617
  };
@@ -20,6 +20,7 @@ export declare const allTools: {
20
20
  getKnowledgeGraphStats: ToolDefinition;
21
21
  deleteDocuments: ToolDefinition;
22
22
  listDocuments: ToolDefinition;
23
+ syncDocumentFromFile: ToolDefinition;
23
24
  createEntities: ToolDefinition;
24
25
  createRelations: ToolDefinition;
25
26
  addObservations: ToolDefinition;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rag-memory-epf-mcp",
3
- "version": "3.3.6",
3
+ "version": "3.4.0",
4
4
  "description": "Project-local RAG memory MCP server — knowledge graph + multilingual vector + FTS5 in a single SQLite file. Per-project isolation, 30 MCP tools, codepoint-safe chunking (Korean/CJK/emoji).",
5
5
  "keywords": [
6
6
  "mcp",