rag-memory-epf-mcp 6.0.1 → 6.3.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/README.md CHANGED
@@ -16,7 +16,7 @@ A **project-local RAG memory** MCP server — knowledge graph + multilingual vec
16
16
  - **38 MCP tools** — knowledge graph CRUD, observation lifecycle (correct / retract / history), document pipeline, hybrid search, multi-hop traversal, graph analytics (centrality / community detection / structure), export/import, temporal queries
17
17
  - **Observations that hold their history** — corrections supersede instead of overwrite, search returns only current facts, and every revision keeps its provenance
18
18
  - **Structure-anchored chunking (c1, v5)** — boundaries anchor to markdown structure (fence-aware, H1–H4 first, block-greedy, exact-token fallback), so editing the top of a file no longer re-embeds the whole document: unchanged text reuses its stored vectors at sync time. Chunk offsets are Unicode codepoints, language-neutral across SQL `substr`, Python slicing, and JS `[...str]` iteration; a publish-time invariant gate locks the gap-free partition. `overlap` is retired (omit or 0).
19
- - **SQLite optimized** — WAL mode, 32MB cache, 256MB mmap, FTS5 triggers, 7 indexes
19
+ - **SQLite optimized** — WAL mode, 32MB cache, FTS5 triggers, 7 indexes; mmap is opt-in (`RAG_MEMORY_MMAP_SIZE`, default 0 since 6.3.0 — see Environment Variables)
20
20
  - **MCP SDK 1.27.1** — Tool Annotations (readOnly/destructive/idempotent), latest protocol 2025-11-25
21
21
 
22
22
  ## Quick Start
@@ -145,7 +145,8 @@ storeDocument(id, content, metadata)
145
145
 
146
146
  | Variable | Default | Description |
147
147
  |----------|---------|-------------|
148
- | `DB_FILE_PATH` | `rag-memory.db` (server dir) | Path to project-local SQLite database |
148
+ | `DB_FILE_PATH` | `rag-memory.db` (server dir) | Path to project-local SQLite database. A **relative** path resolves against the server's working directory (since 6.3.0; before that it resolved against the package install directory, which under `npx` is the npm cache) |
149
+ | `RAG_MEMORY_MMAP_SIZE` | `0` | SQLite `mmap_size` in bytes. **Off by default since 6.3.0** — with mmap on, one writer + two readers on a Google Drive folder (Windows) produced `database disk image is malformed` reads; set e.g. `268435456` to restore the previous behaviour. The applied value is printed in the boot banner (`| mmap <n>`) |
149
150
  | `EMBEDDING_MODEL` | `Xenova/bge-m3` | HuggingFace model ID for embeddings |
150
151
  | `RAG_MEMORY_EMBEDDINGS` | `lazy` | Boot mode: `lazy` (connect instantly, model loads in background), `eager` (wait for model + reconciliation, pre-3.6 behavior), `off` (never load the model — FTS5-only, zero download) |
151
152
  | `RAG_MEMORY_MODEL_CACHE_DIR` | OS user cache | Version-independent model cache location (see `docs/UPDATING.md`) |
@@ -153,6 +154,44 @@ storeDocument(id, content, metadata)
153
154
 
154
155
  ## Changelog
155
156
 
157
+ ### v6.3.0 (2026-09-16)
158
+
159
+ - **Changed — a relative `DB_FILE_PATH` now resolves against the server's working directory.** It used
160
+ to resolve against the package install directory, which under `npx` is the npm cache: a relative
161
+ value opened a database in a place nobody looks, with no error. Absolute paths and the unset default
162
+ are unchanged. (Framework spec 2026-09-14 §11-1.) If you relied on the old install-directory
163
+ resolution of a relative path, set an absolute path.
164
+ - **Changed — SQLite `mmap_size` is opt-in, default 0.** Measured 2026-09-15 on a Google Drive folder
165
+ (Windows, WAL): with mmap 256 MB, one writer + two readers produced 373,684 `database disk image is
166
+ malformed` reads in 20 s; with mmap 0, none. `RAG_MEMORY_MMAP_SIZE=<bytes>` restores it; the boot
167
+ banner reports the applied value. (Spec §11-2.)
168
+
169
+ ### v6.1.0
170
+
171
+ **Versioning note.** This content was tagged `v6.0.2` locally before release, but npm never received
172
+ a 6.0.2 — it published as **6.1.0**. Coming from any 6.0.x, upgrading to 6.1.0 brings exactly this
173
+ fix.
174
+
175
+ - **Fixed — a failure mid-deletion could leave partial state.** Deleting an entity ran its cleanup
176
+ steps (embeddings → chunk associations → relationships → the entity row) with no wrapping
177
+ transaction, so a failure in the middle committed the earlier steps: embeddings and links purged
178
+ while the entity itself survived. Each entity's deletion is now one transaction — any step fails,
179
+ that entity's whole sequence rolls back. Batch semantics are unchanged: other entities still
180
+ proceed when one fails.
181
+ - **Fixed — deleting an entity left its knowledge-graph chunks behind.** Two gaps compounded: the
182
+ delete path never invoked the entity-chunk sweeper, and KG relationship chunks are keyed by
183
+ `relationship_id`, so once the relationship rows were deleted their ids could no longer be found
184
+ and those chunks dangled forever — still vector-searchable after both of their endpoints were
185
+ gone. Deletion now captures relationship ids *before* removing the rows and sweeps both: stale
186
+ entity chunks via the existing `deleteStaleKgChunks`, captured relationship chunks via the new
187
+ `deleteKgRelationshipChunks` projection helper. Practical exposure today is bounded — the chunk
188
+ generation path is dormant (not tool-exposed) — but once seeded these chunks stay retrievable
189
+ unless swept here.
190
+ - Regression: `test/delete-entities-kg-hygiene.test.mjs` (registered in `verify:engine`) covers both,
191
+ verified RED before the fix; a mutation check confirms that removing the transaction reproduces the
192
+ partial state (`entities_alive=1` with `relationships_left=0`). Full suite green (`npm test`,
193
+ 46-call chain).
194
+
156
195
  ### v6.0.1
157
196
 
158
197
  **Versioning note.** Both changes below stop links from being created that should never have been
package/dist/index.d.ts CHANGED
@@ -4,6 +4,8 @@ import { EmbeddingGate } from './src/embeddingGate.js';
4
4
  import type { EmbedPriority } from './src/embeddingGate.js';
5
5
  import { BackfillCoordinator } from './src/backfillCoordinator.js';
6
6
  export declare function compileFtsLiteralQuery(q: string): string | null;
7
+ export declare function resolveDbFilePath(envValue: string | undefined, cwd: string, serverDir: string): string;
8
+ export declare function parseMmapSize(raw: string | undefined): number;
7
9
  interface Entity {
8
10
  name: string;
9
11
  entityType: string;
@@ -71,6 +73,7 @@ export declare class RAGKnowledgeGraphManager {
71
73
  grandfatherAllowed: boolean;
72
74
  coordinator: BackfillCoordinator | null;
73
75
  readonly calendarTimeZone: string;
76
+ mmapApplied: number;
74
77
  private embeddingCache;
75
78
  private readonly EMBEDDING_CACHE_MAX;
76
79
  private dictionaryCache;
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ import { getAllMCPTools, validateToolArgs, getSystemInfo } from './src/tools/too
22
22
  // Import migration system
23
23
  import { MigrationManager } from './src/migrations/migration-manager.js';
24
24
  import { backupBeforeMigration } from './src/backup/preflight.js';
25
- import { rebuildProjection, deleteStaleKgChunks } from './src/observations/projection.js';
25
+ import { rebuildProjection, deleteStaleKgChunks, deleteKgRelationshipChunks } from './src/observations/projection.js';
26
26
  import { addRevision, correctRevision, transitionStatus, linkSources, nextProjectionOrder } from './src/observations/lifecycle.js';
27
27
  import { getObservationHistory } from './src/observations/history.js';
28
28
  // Import chunk text algorithm (extracted for publish-time invariant testing)
@@ -59,7 +59,7 @@ function sanitizeErrorMessage(msg) {
59
59
  }
60
60
  // v3.6: startup self-report banner (version reliability — spec §8).
61
61
  function printBanner(opts) {
62
- console.error(`🚀 rag-memory-epf-mcp v${PKG_VERSION} | node v${process.versions.node} | model ${opts.model}@${opts.revision} (${opts.dtype}) | cache ${opts.cachePath} | db ${opts.dbPath}`);
62
+ console.error(`🚀 rag-memory-epf-mcp v${PKG_VERSION} | node v${process.versions.node} | model ${opts.model}@${opts.revision} (${opts.dtype}) | cache ${opts.cachePath} | db ${opts.dbPath} | mmap ${opts.mmap}`);
63
63
  }
64
64
  // v3.6 (spec §5): ONE FTS5 literal-query compiler shared by chunk and entity
65
65
  // search — raw user input can never produce MATCH syntax errors or trigger
@@ -79,13 +79,36 @@ export function compileFtsLiteralQuery(q) {
79
79
  if (env.backends?.onnx?.wasm) {
80
80
  env.backends.onnx.wasm.wasmPaths = './node_modules/@huggingface/transformers/dist/';
81
81
  }
82
- // Define database file path using environment variable with fallback
83
- const defaultDbPath = path.join(path.dirname(fileURLToPath(import.meta.url)), 'rag-memory.db');
84
- const DB_FILE_PATH = process.env.DB_FILE_PATH
85
- ? path.isAbsolute(process.env.DB_FILE_PATH)
86
- ? process.env.DB_FILE_PATH
87
- : path.join(path.dirname(fileURLToPath(import.meta.url)), process.env.DB_FILE_PATH)
88
- : defaultDbPath;
82
+ // Define database file path using environment variable with fallback.
83
+ // Next release (major candidate; the version is set at release time — framework spec
84
+ // 2026-09-14-universal-mcp-config-design §11-1): a RELATIVE DB_FILE_PATH
85
+ // resolves against the server's working directory (process.cwd()), the way every other CLI tool
86
+ // reads a relative path. Before this it resolved against the package's own install directory —
87
+ // under npx that is the npm cache, so a relative value silently opened a database nobody could
88
+ // find (measured 2026-09-14 on 6.1.0 dist/index.js:83-88) and every framework config had to carry
89
+ // a machine-specific absolute path. The UNSET default is deliberately unchanged (README contract:
90
+ // `rag-memory.db` next to the server); the framework always sets DB_FILE_PATH explicitly instead.
91
+ // Exported so the contract is unit-testable without writing a database into dist/.
92
+ export function resolveDbFilePath(envValue, cwd, serverDir) {
93
+ if (!envValue)
94
+ return path.join(serverDir, 'rag-memory.db');
95
+ return path.isAbsolute(envValue) ? envValue : path.resolve(cwd, envValue);
96
+ }
97
+ const DB_FILE_PATH = resolveDbFilePath(process.env.DB_FILE_PATH, process.cwd(), path.dirname(fileURLToPath(import.meta.url)));
98
+ // Next release (spec §11-2): SQLite mmap is opt-in, default 0 (off). Measured 2026-09-15 (Windows, Google
99
+ // Drive G:, WAL, mmap 256 MB): one writer + two readers -> 373,684 `database disk image is
100
+ // malformed` reads in 20 s; mmap 0 -> 0 errors; local disk -> 0 either way. On macOS Drive the same
101
+ // probe read clean but the WAL grew to ~4 GB in 20 s with mmap on (n=1). The framework opens one
102
+ // DB from several CLIs on synced folders, so correctness wins over an unmeasured read-speed gain.
103
+ // RAG_MEMORY_MMAP_SIZE=<bytes> turns it back on; garbage or negative values count as 0. The value
104
+ // SQLite actually applied is read back and printed in the boot banner (`| mmap <n>`).
105
+ export function parseMmapSize(raw) {
106
+ if (raw === undefined || raw.trim() === '')
107
+ return 0;
108
+ const n = Number(raw);
109
+ return Number.isFinite(n) && n >= 0 ? Math.floor(n) : 0;
110
+ }
111
+ const MMAP_SIZE = parseMmapSize(process.env.RAG_MEMORY_MMAP_SIZE);
89
112
  const EMBEDDING_MODEL = process.env.EMBEDDING_MODEL || 'Xenova/bge-m3';
90
113
  // v3.5 default model config — grandfathering legacy vectors is only automatic
91
114
  // when the current config matches this (spec §6b custom-model guard). An
@@ -183,6 +206,8 @@ export class RAGKnowledgeGraphManager {
183
206
  // The calendar that date-only human labels are written in. Resolved once, here, so an invalid
184
207
  // zone fails at construction instead of quietly writing wrong days for weeks.
185
208
  calendarTimeZone = resolveCalendarTimeZone(process.env.RAG_MEMORY_CALENDAR_TZ);
209
+ // The mmap_size SQLite actually applied at initialize() (-1 until then). Banner-only.
210
+ mmapApplied = -1;
186
211
  embeddingCache = new Map();
187
212
  EMBEDDING_CACHE_MAX = 500;
188
213
  dictionaryCache = null;
@@ -201,7 +226,10 @@ export class RAGKnowledgeGraphManager {
201
226
  this.db.pragma('busy_timeout = 5000');
202
227
  this.db.pragma('cache_size = -32000');
203
228
  this.db.pragma('temp_store = MEMORY');
204
- this.db.pragma('mmap_size = 268435456');
229
+ // Opt-in mmap (see MMAP_SIZE above). Read the applied value back so the banner reports
230
+ // what SQLite did, not what we asked for (a compile-time cap can lower it silently).
231
+ this.db.pragma(`mmap_size = ${MMAP_SIZE}`);
232
+ this.mmapApplied = Number(this.db.pragma('mmap_size', { simple: true }));
205
233
  this.db.pragma('foreign_keys = ON');
206
234
  // spec §5.2: 관찰 lifecycle 의 무결성은 전부 FK CASCADE 를 전제한다 — root 를 지우면
207
235
  // revision 이, revision 을 지우면 source 가 따라가야 history 가 고아로 남지 않는다.
@@ -843,58 +871,76 @@ export class RAGKnowledgeGraphManager {
843
871
  console.error(`🗑️ Deleting entities: ${entityNames.join(', ')}`);
844
872
  for (const name of entityNames) {
845
873
  const entityId = `entity_${name.toLowerCase().replace(/[^\p{L}\p{N}]/gu, '_')}`;
874
+ // One entity = one transaction. The four deletion steps are a single unit:
875
+ // a mid-sequence failure must roll back, not leave embeddings/links purged while
876
+ // the entity itself survives (2026-08-24 audit finding; regression =
877
+ // test/delete-entities-kg-hygiene.test.mjs ⓒ). Batch semantics are preserved —
878
+ // other entities still proceed when one fails.
846
879
  try {
847
- // Check if entity exists first
848
- const entityExists = this.db.prepare(`
849
- SELECT id FROM entities WHERE id = ?
850
- `).get(entityId);
851
- if (!entityExists) {
852
- console.warn(`⚠️ Entity '${name}' not found, skipping`);
853
- continue;
854
- }
855
- // Step 0: Delete entity embeddings
856
- const embeddingMetadata = this.db.prepare(`
857
- SELECT rowid FROM entity_embedding_metadata WHERE entity_id = ?
858
- `).get(entityId);
859
- if (embeddingMetadata) {
860
- const embeddings = this.db.prepare(`
861
- DELETE FROM entity_embeddings WHERE rowid = ?
862
- `).run(embeddingMetadata.rowid);
863
- const metadata = this.db.prepare(`
864
- DELETE FROM entity_embedding_metadata WHERE entity_id = ?
865
- `).run(entityId);
866
- if (embeddings.changes > 0 || metadata.changes > 0) {
867
- console.error(` ├─ Removed entity embeddings for '${name}'`);
880
+ const deleted = this.db.transaction((eid) => {
881
+ // Check if entity exists first
882
+ const entityExists = this.db.prepare(`
883
+ SELECT id FROM entities WHERE id = ?
884
+ `).get(eid);
885
+ if (!entityExists)
886
+ return false;
887
+ // Step 0: Delete entity embeddings
888
+ const embeddingMetadata = this.db.prepare(`
889
+ SELECT rowid FROM entity_embedding_metadata WHERE entity_id = ?
890
+ `).get(eid);
891
+ if (embeddingMetadata) {
892
+ const embeddings = this.db.prepare(`
893
+ DELETE FROM entity_embeddings WHERE rowid = ?
894
+ `).run(embeddingMetadata.rowid);
895
+ const metadata = this.db.prepare(`
896
+ DELETE FROM entity_embedding_metadata WHERE entity_id = ?
897
+ `).run(eid);
898
+ if (embeddings.changes > 0 || metadata.changes > 0) {
899
+ console.error(` ├─ Removed entity embeddings for '${name}'`);
900
+ }
868
901
  }
869
- }
870
- // Step 1: Delete chunk-entity associations
871
- const chunkAssociations = this.db.prepare(`
872
- DELETE FROM chunk_entities WHERE entity_id = ?
873
- `).run(entityId);
874
- if (chunkAssociations.changes > 0) {
875
- console.error(` ├─ Removed ${chunkAssociations.changes} chunk associations for '${name}'`);
876
- }
877
- // Step 2: Delete relationships where this entity is involved
878
- const relationships = this.db.prepare(`
879
- DELETE FROM relationships
880
- WHERE source_entity = ? OR target_entity = ?
881
- `).run(entityId, entityId);
882
- if (relationships.changes > 0) {
883
- console.error(` ├─ Removed ${relationships.changes} relationships for '${name}'`);
884
- }
885
- // Step 3: Finally delete the entity itself
886
- const entity = this.db.prepare(`
887
- DELETE FROM entities WHERE id = ?
888
- `).run(entityId);
889
- if (entity.changes > 0) {
902
+ // Step 1: Delete chunk-entity associations
903
+ const chunkAssociations = this.db.prepare(`
904
+ DELETE FROM chunk_entities WHERE entity_id = ?
905
+ `).run(eid);
906
+ if (chunkAssociations.changes > 0) {
907
+ console.error(` ├─ Removed ${chunkAssociations.changes} chunk associations for '${name}'`);
908
+ }
909
+ // Step 2: Capture relationship ids BEFORE deleting the rows — KG relationship
910
+ // chunks are keyed by relationship_id, so after the DELETE they could no
911
+ // longer be found and would dangle forever.
912
+ const relIds = this.db.prepare(`
913
+ SELECT id FROM relationships
914
+ WHERE source_entity = ? OR target_entity = ?
915
+ `).all(eid, eid);
916
+ const relationships = this.db.prepare(`
917
+ DELETE FROM relationships
918
+ WHERE source_entity = ? OR target_entity = ?
919
+ `).run(eid, eid);
920
+ if (relationships.changes > 0) {
921
+ console.error(` ├─ Removed ${relationships.changes} relationships for '${name}'`);
922
+ }
923
+ // Step 2b: KG hygiene — sweep stale entity chunks and chunks of the captured
924
+ // relationships. The generation path is dormant today (generateKnowledgeGraphChunks
925
+ // is not tool-exposed), but once seeded these chunks stay vector-searchable after
926
+ // deletion unless swept here (same fail-closed rationale as deleteStaleKgChunks).
927
+ deleteStaleKgChunks(this.db, eid);
928
+ deleteKgRelationshipChunks(this.db, relIds.map(r => r.id));
929
+ // Step 3: Finally delete the entity itself (FK CASCADE takes observation lifecycle rows)
930
+ const entity = this.db.prepare(`
931
+ DELETE FROM entities WHERE id = ?
932
+ `).run(eid);
933
+ return entity.changes > 0;
934
+ })(entityId);
935
+ if (deleted) {
890
936
  console.error(` └─ Deleted entity '${name}' successfully`);
891
937
  }
892
938
  else {
893
- console.warn(` └─ Entity '${name}' was not deleted (possibly already removed)`);
939
+ console.warn(`⚠️ Entity '${name}' not found, skipping`);
894
940
  }
895
941
  }
896
942
  catch (error) {
897
- console.error(`❌ Failed to delete entity '${name}':`, error);
943
+ console.error(`❌ Failed to delete entity '${name}' (transaction rolled back, continuing):`, error);
898
944
  // Continue with other entities instead of failing completely
899
945
  }
900
946
  }
@@ -4157,6 +4203,7 @@ async function main() {
4157
4203
  model: EMBEDDING_MODEL, revision: MODEL_REVISION, dtype: MODEL_DTYPE,
4158
4204
  cachePath: resolveModelCacheDir(process.env, process.platform, os.homedir()),
4159
4205
  dbPath: DB_FILE_PATH,
4206
+ mmap: ragKgManager.mmapApplied,
4160
4207
  });
4161
4208
  if (ragKgManager.embeddingsMode === 'eager') {
4162
4209
  // eager = wait for BOTH the first model load attempt and reconciliation to
@@ -1,3 +1,4 @@
1
1
  import type Database from 'better-sqlite3';
2
2
  export declare function rebuildProjection(db: Database.Database, entityId: string): void;
3
3
  export declare function deleteStaleKgChunks(db: Database.Database, entityId: string): number;
4
+ export declare function deleteKgRelationshipChunks(db: Database.Database, relationshipIds: string[]): number;
@@ -29,3 +29,20 @@ export function deleteStaleKgChunks(db, entityId) {
29
29
  }
30
30
  return n;
31
31
  }
32
+ // relationship 청크는 relationship_id 키라 엔티티 삭제만으로는 잡을 수 없다 —
33
+ // 호출자가 relationships 행을 지우기 전에 id 를 캡처해서 넘겨야 한다(deleteEntities 계약).
34
+ // 넘어온 id 중 이미 없는 것은 무시한다(멱등). 벡터 행을 먼저 지우는 것은 deleteStaleKgChunks 와 같다.
35
+ export function deleteKgRelationshipChunks(db, relationshipIds) {
36
+ if (relationshipIds.length === 0)
37
+ return 0;
38
+ let n = 0;
39
+ for (const rid of relationshipIds) {
40
+ const chunks = db.prepare(`SELECT rowid FROM chunk_metadata WHERE chunk_type = 'relationship' AND relationship_id = ?`).all(rid);
41
+ for (const c of chunks) {
42
+ db.exec(`DELETE FROM chunks WHERE rowid = ${Number(c.rowid)}`);
43
+ db.prepare(`DELETE FROM chunk_metadata WHERE rowid = ?`).run(c.rowid);
44
+ n++;
45
+ }
46
+ }
47
+ return n;
48
+ }
package/package.json CHANGED
@@ -1,71 +1,71 @@
1
1
  {
2
- "name": "rag-memory-epf-mcp",
3
- "version": "6.0.1",
4
- "engines": {
5
- "node": ">=24"
6
- },
7
- "description": "Project-local RAG memory MCP server — knowledge graph + multilingual vector + FTS5 in a single SQLite file. Per-project isolation, 38 MCP tools, codepoint-safe chunking (Korean/CJK/emoji).",
8
- "keywords": [
9
- "mcp",
10
- "model-context-protocol",
11
- "rag",
12
- "knowledge-graph",
13
- "vector-search",
14
- "fts5",
15
- "sqlite",
16
- "embeddings",
17
- "bge-m3",
18
- "multilingual",
19
- "korean",
20
- "claude-code",
21
- "gemini-cli",
22
- "codex-cli",
23
- "memory",
24
- "agent-memory"
25
- ],
26
- "license": "MIT",
27
- "author": "bripin123",
28
- "homepage": "https://github.com/bripin123/rag-memory-epf-mcp",
29
- "bugs": "https://github.com/bripin123/rag-memory-epf-mcp/issues",
30
- "repository": {
31
- "type": "git",
32
- "url": "git+https://github.com/bripin123/rag-memory-epf-mcp.git"
33
- },
34
- "type": "module",
35
- "main": "dist/index.js",
36
- "bin": {
37
- "rag-memory-mcp": "dist/index.js"
38
- },
39
- "files": [
40
- "dist",
41
- "docs/UPDATING.md"
42
- ],
43
- "scripts": {
44
- "build": "tsc && shx chmod +x dist/*.js",
45
- "prepare": "npm run build",
46
- "watch": "tsc --watch",
47
- "verify:invariants": "node test/chunk-invariants.test.mjs",
48
- "verify:engine": "node test/engine-smoke.test.mjs && node test/launch-smoke.test.mjs && node test/sync-atomicity.test.mjs && node test/dedup.test.mjs && node test/search-degradation.test.mjs && node test/entity-embed-cap.test.mjs && node test/migration12.test.mjs && node test/model-cache.test.mjs && node test/embedding-gate.test.mjs && node test/lazy-boot.test.mjs && node test/reconciliation.test.mjs && node test/backfill.test.mjs && node test/fts-query.test.mjs && node test/search-contracts.test.mjs && node test/tool-contracts.test.mjs && node test/bounded-exit.test.mjs && node test/observation-schema.test.mjs && node test/search-graph-default.test.mjs && node test/observation-migration.test.mjs && node test/observation-lifecycle.test.mjs && node test/observation-contracts.test.mjs && node test/observation-search.test.mjs && node test/observation-cascade.test.mjs && node test/observation-realdata.test.mjs && node test/chunker-c.test.mjs && node test/migration14.test.mjs && node test/chunk-params-validation.test.mjs && node test/vector-reuse.test.mjs && node test/entity-range-linking.test.mjs && node test/alias-link-gate.test.mjs && node test/entity-name-boundary.test.mjs && node test/stats-chunking.test.mjs && node test/migration14-realdata.test.mjs && node test/migration14-realdata-sync.test.mjs && node test/search-summaries-off.test.mjs && node test/document-return-contracts.test.mjs && node test/observation-date-prefix.test.mjs && node test/delete-entities-cascade.test.mjs && node test/backup-publish-portable.test.mjs && node test/graph-context-explain.test.mjs && node test/eval-graph-role-libs.test.mjs && node test/eval-graph-role-t5b.test.mjs && node --test test/eval-graph-role-t8-fix.test.mjs && node --test test/eval-graph-role-t7-upstream.test.mjs && node --test test/eval-graph-role-t11-decision.test.mjs && node --test test/eval-graph-role-prereq-fix.test.mjs",
49
- "test": "npm run build && npm run verify:invariants && npm run verify:engine",
50
- "prepublishOnly": "npm run build && npm run verify:invariants && npm run verify:engine"
51
- },
52
- "dependencies": {
53
- "@huggingface/transformers": "^3.5.1",
54
- "@modelcontextprotocol/sdk": "^1.27.1",
55
- "better-sqlite3": "^12.8.0",
56
- "graphology": "^0.26.0",
57
- "graphology-communities-louvain": "^2.0.2",
58
- "graphology-metrics": "^2.4.0",
59
- "graphology-shortest-path": "^2.1.0",
60
- "graphology-types": "^0.24.8",
61
- "sqlite-vec": "^0.1.7",
62
- "tiktoken": "^1.0.17",
63
- "zod": "^3.25.28"
64
- },
65
- "devDependencies": {
66
- "@types/better-sqlite3": "^7.6.12",
67
- "@types/node": "^24",
68
- "shx": "^0.3.4",
69
- "typescript": "^5.6.2"
70
- }
2
+ "name": "rag-memory-epf-mcp",
3
+ "version": "6.3.0",
4
+ "engines": {
5
+ "node": ">=24"
6
+ },
7
+ "description": "Project-local RAG memory MCP server — knowledge graph + multilingual vector + FTS5 in a single SQLite file. Per-project isolation, 38 MCP tools, codepoint-safe chunking (Korean/CJK/emoji).",
8
+ "keywords": [
9
+ "mcp",
10
+ "model-context-protocol",
11
+ "rag",
12
+ "knowledge-graph",
13
+ "vector-search",
14
+ "fts5",
15
+ "sqlite",
16
+ "embeddings",
17
+ "bge-m3",
18
+ "multilingual",
19
+ "korean",
20
+ "claude-code",
21
+ "gemini-cli",
22
+ "codex-cli",
23
+ "memory",
24
+ "agent-memory"
25
+ ],
26
+ "license": "MIT",
27
+ "author": "bripin123",
28
+ "homepage": "https://github.com/bripin123/rag-memory-epf-mcp",
29
+ "bugs": "https://github.com/bripin123/rag-memory-epf-mcp/issues",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/bripin123/rag-memory-epf-mcp.git"
33
+ },
34
+ "type": "module",
35
+ "main": "dist/index.js",
36
+ "bin": {
37
+ "rag-memory-mcp": "dist/index.js"
38
+ },
39
+ "files": [
40
+ "dist",
41
+ "docs/UPDATING.md"
42
+ ],
43
+ "scripts": {
44
+ "build": "tsc && shx chmod +x dist/*.js",
45
+ "prepare": "npm run build",
46
+ "watch": "tsc --watch",
47
+ "verify:invariants": "node test/chunk-invariants.test.mjs",
48
+ "verify:engine": "node test/engine-smoke.test.mjs && node test/launch-smoke.test.mjs && node test/sync-atomicity.test.mjs && node test/dedup.test.mjs && node test/search-degradation.test.mjs && node test/entity-embed-cap.test.mjs && node test/migration12.test.mjs && node test/model-cache.test.mjs && node test/embedding-gate.test.mjs && node test/lazy-boot.test.mjs && node test/reconciliation.test.mjs && node test/backfill.test.mjs && node test/fts-query.test.mjs && node test/search-contracts.test.mjs && node test/tool-contracts.test.mjs && node test/bounded-exit.test.mjs && node test/observation-schema.test.mjs && node test/search-graph-default.test.mjs && node test/observation-migration.test.mjs && node test/observation-lifecycle.test.mjs && node test/observation-contracts.test.mjs && node test/observation-search.test.mjs && node test/observation-cascade.test.mjs && node test/observation-realdata.test.mjs && node test/chunker-c.test.mjs && node test/migration14.test.mjs && node test/chunk-params-validation.test.mjs && node test/vector-reuse.test.mjs && node test/entity-range-linking.test.mjs && node test/alias-link-gate.test.mjs && node test/entity-name-boundary.test.mjs && node test/stats-chunking.test.mjs && node test/migration14-realdata.test.mjs && node test/migration14-realdata-sync.test.mjs && node test/search-summaries-off.test.mjs && node test/document-return-contracts.test.mjs && node test/observation-date-prefix.test.mjs && node test/delete-entities-cascade.test.mjs && node test/delete-entities-kg-hygiene.test.mjs && node test/backup-publish-portable.test.mjs && node test/graph-context-explain.test.mjs && node test/eval-graph-role-libs.test.mjs && node test/eval-graph-role-t5b.test.mjs && node --test test/eval-graph-role-t8-fix.test.mjs && node --test test/eval-graph-role-t7-upstream.test.mjs && node --test test/eval-graph-role-t11-decision.test.mjs && node --test test/eval-graph-role-prereq-fix.test.mjs && node test/db-path.test.mjs && node test/mmap-option.test.mjs",
49
+ "test": "npm run build && npm run verify:invariants && npm run verify:engine",
50
+ "prepublishOnly": "npm run build && npm run verify:invariants && npm run verify:engine"
51
+ },
52
+ "dependencies": {
53
+ "@huggingface/transformers": "^3.5.1",
54
+ "@modelcontextprotocol/sdk": "^1.27.1",
55
+ "better-sqlite3": "^12.8.0",
56
+ "graphology": "^0.26.0",
57
+ "graphology-communities-louvain": "^2.0.2",
58
+ "graphology-metrics": "^2.4.0",
59
+ "graphology-shortest-path": "^2.1.0",
60
+ "graphology-types": "^0.24.8",
61
+ "sqlite-vec": "^0.1.7",
62
+ "tiktoken": "^1.0.17",
63
+ "zod": "^3.25.28"
64
+ },
65
+ "devDependencies": {
66
+ "@types/better-sqlite3": "^7.6.12",
67
+ "@types/node": "^24",
68
+ "shx": "^0.3.4",
69
+ "typescript": "^5.6.2"
70
+ }
71
71
  }