Power your agent
คำสั่งของผู้เผยแพร่เอง ไม่ใช่เอนด์พอยต์ของ PlugMCP
Host a copy with our keys and logs.
npx -y [email protected]Claude Code ไม่มีลิงก์ติดตั้งสำหรับคำสั่งแบบโลคัล ให้คัดลอกคำสั่งด้านล่างแล้วรันในเทอร์มินัล
claude mcp add rag-memory-epf-mcp -- npx -y rag-memory-epf-mcp@6.4.6รันในเทอร์มินัล
{ "mcpServers": { "rag-memory-epf-mcp": { "command": "npx", "args": [ "-y", "[email protected]" ] } }}claude_desktop_config.json
URL แบบรีโมตหรือคำสั่งบนเครื่องของคุณ? การติดตั้งสองแบบต่างกันอย่างไร
รันบน PlugMCP
A new server you create. It is not this listing's official endpoint. Use the publisher install when you want their URL and their credentials.
เปิดA project-local RAG memory MCP server — knowledge graph + multilingual vector search + FTS5 full-text search, all in a single SQLite file per project.
.memory/rag-memory.db. Multiple projects run simultaneously without interference.substr, Python slicing, and JS [...str] iteration; a publish-time invariant gate locks the gap-free partition. overlap is retired (omit or 0).RAG_MEMORY_MMAP_SIZE, default 0 since 6.3.0 — see Environment Variables){
"mcpServers": {
"rag-memory": {
"command": "npx",
"args": ["-y", "rag-memory-epf-mcp@latest"],
"env": {
"DB_FILE_PATH": "/path/to/your-project/.memory/rag-memory.db"
}
}
}
}
Place this .mcp.json in each project folder with its own DB_FILE_PATH. Each project maintains completely isolated memory.
storeDocument(id, content, metadata)
→ chunkDocument(documentId, maxTokens) # overlap retired in v5 (omit or 0)
→ embedChunks(documentId)
├── generates vector embeddings for each chunk
├── auto-links entities to chunks (word boundary + CJK aware)
└── returns { embeddedChunks, linkedEntities }
┌─────────────────────────────────────────────┐
│ MCP Client (Claude Code, Gemini CLI, etc) │
└──────────────────┬──────────────────────────┘
│ stdio (MCP SDK 1.27.1)
┌──────────────────▼──────────────────────────┐
│ rag-memory-epf-mcp │
│ ┌────────────┐ ┌─────────────┐ ┌────────┐ │
│ │ Knowledge │ │ RAG Document│ │ Search │ │
│ │ Graph CRUD │ │ Pipeline │ │ Engine │ │
│ └─────┬──────┘ └──────┬──────┘ └───┬────┘ │
│ │ │ │ │
│ ┌─────▼───────────────▼────────────▼─────┐ │
│ │ SQLite (WAL mode, per-project file) │ │
│ │ ├── entities + relationships │ │
│ │ ├── documents + chunk_metadata │ │
│ │ ├── chunks (sqlite-vec, 1024-dim) │ │
│ │ ├── entity_embeddings (sqlite-vec) │ │
│ │ ├── entities_fts + chunks_fts (FTS5) │ │
│ │ ├── observation lifecycle (4 tables) │ │
│ │ └── 13 migrations (auto-applied) │ │
│ └────────────────────────────────────────┘ │
│ │
│ bge-m3 (ONNX, 100+ langs) │
└──────────────────────────────────────────────┘
generateRelationEvidenceChunks(items, { formatVersion: 'evidence-v1' }).
items is the whole set of relationships that should have a relationship chunk: on success every relationship KG
chunk is replaced by evidence-backed chunks for that set, built from verified quotes (document chunk codepoint
ranges) and current active observations; relationships outside the set get no chunk, and entity chunks and
relationship rows are untouched. Caps: 1–8 evidence entries per item, ≤ 4,000 codepoints per quote, ≤ 8,000
codepoints of final body — over-cap input rejects the whole call without writes, never truncated. Not exposed over
MCP and does not change search defaults. The no-argument generator generateKnowledgeGraphChunks() keeps the
previous entity/triplet bodies, IDs, metadata and counts (the lifecycle and atomicity fixes below still apply);
calling it replaces existing evidence relationship chunks with triplet chunks. "Evidence-backed" means
caller-selected evidence whose references the engine verified exist verbatim, not an independent proof.getDetailedContext resolves KG chunks. Entity chunks return the entity and its active observations;
relationship chunks return the relationship plus evidence_status (claim_only / refs_available /
refs_unavailable) and per-reference available / missing / mismatch, with document_id: null and
document_title: null in this branch only. Document detail and all hybridSearch fields are unchanged, except that
full_context_available is now false for a KG chunk whose entity or relationship row is gone.importGraph requires string ids for documents and observation sources. A documents[i].id or an
observation_sources[i].observation_id that is not a string (a number, null, or missing) rejects the whole import
before anything is written. Previously such a value was bound as-is: a number such as 7.5 could replace the
document whose TEXT id is '7.5' while the evidence chunks citing it stayed in search.deleteEntities refreshes cached coverage after at least one entity was deleted, so the coverage figures
and search_mode reported by hybridSearch and stats reflect the deletion without waiting for another write.raw/measurements/2026-10-16-kg-relation-evidence/C6-BENCH.md, one synthetic input per size on one Mac,
Node 24.12.0 — not a guarantee for every input). Inputs that never reach this fallback keep their previous
boundaries. The chunking signature now says fallback=cp-window-N; documents stamped cp-exact-N stay current
format. A signature change alone does not re-chunk an unchanged document that still has chunk metadata (missing
vectors are re-queued without re-chunking; if no chunks remain, the normal path runs).limit sets both the maximum result count and the retrieval depth (each query variant requests up
to limit × 3 vector and up to limit × 3 FTS candidates, then merged), so results for different limits can
differ. No algorithm change.(Published first as 6.4.0-rc.1 on the next dist-tag; promoted to latest after a canary of the published
artifact against a backup copy of a real project database: version and model as expected, hybrid mode on all
probes, the identifier probe's answer at rank 4 and the known-item probe's at rank 1, every score <= 2/61,
query-cold median 445 ms, query_prefix_version 2, entity/relation/document/chunk counts unchanged, no errors.)
Changed hybridSearch default ranking = reciprocal rank fusion of the vector and FTS5 candidate lists
(k=60). A chunk that only FTS5 finds — typically an exact identifier, filename or setting key — can now reach
the top; before, it scored at most 0.0164 and sat under every vector candidate in the measured corpora.
relevance_score on the default call is a rank score (at most 2/61, comparable only within one call). Measured on frozen snapshots: exact-identifier hit@10 7/20 → 18/20; worse on 0 of
203 queries across three corpora.
Changed the per-result summary path is opt-in (RAG_MEMORY_SEARCH_SUMMARIES=on). It embedded every
sentence fragment of every candidate (median 121 s per search) and its context boost pushed vector-0 chunks
to rank 1. off keeps working. Legacy paths (summaries=on, useGraph: true) keep the 6.3.2 formula.
Changed with the default model (bge-m3) queries are embedded as raw text: the bge-v1.5 instruction the loader
prepended to every query is gone (bge-m3 needs none; stored vectors never had it). A custom EMBEDDING_MODEL keeps
the previous query instruction. Paraphrase hit@10 7 → 9 of 20, identifier hit@1 7 → 8,
document known-item (hybridSearch) unchanged or +1; entity known-item (searchNodes) hit@10 unchanged,
hit@1 -1 / -1 / +1 (hub / uap / hal). No re-index.
Details and rollout: docs/UPDATING.md, specs/changes/search-fusion-rrf/proposal.md.
-wal and -shm out of cloud sync. It sets
com.apple.fileprovider.ignore#P = 1 on both files after every open (SQLite recreates them after the
last connection closes, so once is not enough). Measured with Google Drive for desktop: the client
treated -wal as a synced item and put a new file at the path while the engine held the old one open
(lsof -p showed the descriptor inside FileProvider/…/wharf/delete/); from then on every write
failed with SQLITE_IOERR ("disk I/O error") until the engine restarted — 10 s to 3 min after start,
with one engine attached. With the attribute set, the same live database kept the same -wal for
25 min of use. The main database file still syncs. Other platforms: no-op.-wal/-shm inodes with the ones recorded at open (two consecutive mismatches) and reopens with the
same configuration; an SQLITE_IOERR* from a checkpoint or a tool call reopens too. A tool that hit
the I/O error is retried once only if repeating it changes nothing (reads, createEntities,
createRelations, addObservations, deleteEntities, deleteRelations); other tools get the
error back after the reopen. A reopen waits for running tool calls, is not done while shutting
down, and is braked after 3 in 10 s. A failed reopen retries with backoff and, after 10 failures,
shuts the server down so the host shows it as failed. A reconciliation cut by a reopen reruns.walsz-before=).wal_checkpoint(TRUNCATE) is unchanged. RESTART (± journal_size_limit) was measured and
rejected: after SIGKILL its WAL replayed onto a foreign main file 3/3 times.specs/changes/wal-sidecar-guard/.wal_checkpoint(TRUNCATE) itself:
on a 1 s tick whenever the -wal file has bytes in it, ~200 ms after a tool call, first thing in the
signal handler, and before closing. SQLite folds the WAL only when the last connection closes and
only if that close gets to run; with several engines on one file, or a host that kills the engine
(measured: codex-cli 0.155.1 sends SIGTERM and SIGKILLs ~185 ms later; Windows terminates children
outright), frames stayed in the WAL — on 6.3.0 a fresh database sat at 4 KB main + 663 KB WAL for as
long as the engine ran. In a cloud-synced folder such a WAL can be replayed onto a main file written
by another machine. A write made in the last ~1 s before a hard kill can still be in the WAL; a 0-byte
-wal and a -shm left behind by a hard kill are harmless. Running engines on two machines against
the same synced file at the same time is still unsafe.DB_FILE_PATH now resolves against the server's working directory. It used
to resolve against the package install directory, which under npx is the npm cache: a relative
value opened a database in a place nobody looks, with no error. Absolute paths and the unset default
are unchanged. (Framework spec 2026-09-14 §11-1.) If you relied on the old install-directory
resolution of a relative path, set an absolute path.mmap_size is opt-in, default 0. Measured 2026-09-15 on a Google Drive folder
(Windows, WAL): with mmap 256 MB, one writer + two readers produced 373,684 database disk image is malformed reads in 20 s; with mmap 0, none. RAG_MEMORY_MMAP_SIZE=<bytes> restores it; the boot
banner reports the applied value. (Spec §11-2.)Versioning note. This content was tagged v6.0.2 locally before release, but npm never received
a 6.0.2 — it published as 6.1.0. Coming from any 6.0.x, upgrading to 6.1.0 brings exactly this
fix.
relationship_id, so once the relationship rows were deleted their ids could no longer be found
and those chunks dangled forever — still vector-searchable after both of their endpoints were
gone. Deletion now captures relationship ids before removing the rows and sweeps both: stale
entity chunks via the existing deleteStaleKgChunks, captured relationship chunks via the new
deleteKgRelationshipChunks projection helper. Practical exposure today is bounded — the chunk
generation path is dormant (not tool-exposed) — but once seeded these chunks stay retrievable
unless swept here.test/delete-entities-kg-hygiene.test.mjs (registered in verify:engine) covers both,
verified RED before the fix; a mutation check confirms that removing the transaction reproduces the
partial state (entities_alive=1 with relationships_left=0). Full suite green (npm test,
46-call chain).Versioning note. Both changes below stop links from being created that should never have been created, and restore links that should have been. No tool signature, return shape or schema changes, so this is a patch: derived-link density is not part of the compatibility contract. Read the entries as "linking got more precise", not as an API break.
log_coverage.py occurs in 64 chunks and belongs to an entity
about exactly that file. The name condition is structural: no threshold, same meaning at any
corpus size.\b<name>\b. \b asserts a transition between a word character and a non-word character, so when
the name itself starts or ends with punctuation — Widget Review (2026-05-27), --build-flag —
there is no transition to assert and the pattern cannot match however the text reads. Measured on
a live 2,913-chunk / 312-name corpus: 23 standalone occurrences across 13 names were invisible.
Both the chunk matcher and the document range finder now accept an occurrence whose neighbours on
both sides are non-word. Not a widening: both sides must still be non-word, so Data continues
not to match inside Database. The scan runs on the original text rather than a lowercased copy,
because folding can change length (İ becomes two units) and the range finder converts these
indices to codepoints.test/alias-link-gate.test.mjs (magnet case) and test/entity-name-boundary.test.mjs,
both registered in verify:engine and both verified to fail without their fix.autoLinkEntities used to take every
stem.ext token appearing anywhere in an entity's observations and link that entity to every chunk
containing the token as a substring. Measured on a live 2,891-chunk / 604-entity corpus: 65,388 of
66,841 chunk_entities rows (97.8%) existed only because of such a hit, and one token — agents.md,
held by 88 entities — accounted for 39,248 of the 80,096 distinct (chunk, entity) pairs any alias
could reach (49.0%). The regex also accepted things that are not filenames at all (v3.3,
gpt-5.6, 1.7mb, github.com, os.path).
A token now has to (a) look like a filename — extension whitelist, stem ≥ 3 chars, non-numeric
stem — and (b) be held by at most 3 entities, and it must match on token boundaries so foo.py no
longer matches inside notfoo.pyc. Effect on the same corpus: alias links 100% → 4.0%. Filtering by
extension alone leaves 92.3%, so the owner cap is what does the work. The cap is a judgement, not a
discovered boundary — the sweep is smooth (owners<=1 1.6% … <=10 19.9%) — and it is a cap, not a
ban: a filename named by one to three records still links, which is what the alias path was for.chunk_entities stay, and new ingests simply link far less. Links have always been a function of
when a document was last processed (nothing re-links older documents when entities are added), and
chunk_entities has no provenance column, so old alias rows cannot be told apart from name matches
after the fact. If you want the old noise gone you have to clean it offline, before or after
upgrading. Callers that assumed dense chunk_entities coverage will see sparser graphs.test/alias-link-gate.test.mjs (registered in verify:engine), verified to fail
without the gate.5.3.0-rc.1 on the next dist-tag; promoted to latest after a canary run of the published artifact against a real project database: default call carries no graph_boost and equals explicit useGraph:false, the known-item probe from the 2026-08-17 measurement returns the correct gotcha at rank 1, opt-in true still exposes graph_boost, schema/MCP defaults read false.)hybridSearch graph re-ranking is now opt-in (useGraph default true → false; tool schema, MCP exposure and the manager signature agree). Omitting the argument now means "no graph re-ranking" — a behavior change for callers that relied on the old default, hence a release-candidate first (next dist-tag, fleet canary) before stable. Measured 2026-08-17 on three real corpora (self-retrieval, usable samples 120/117/120, summaries off): with the additive graph boost on, the known-item chunk got worse in 46/49/52 samples and better in 3/2/0 (sign test p < 7e-11 per corpus), 106 targets left the top-10 entirely; reproduced on the summaries-on product path (HAL, 20 paired samples: hit@1 10→7, hit@5 18→13). Mechanism: only query-matched/connected entities score, but the per-entity boost saturates the cap quickly, so heavily-linked chunks can outrank the exact chunk even at vector_similarity 0. This is a harm-reduced default, not a validated graph improvement: the boost path is unchanged for useGraph: true (legacy/experimental re-ranker for back-compat and evaluation; the graph does not generate candidates — for relationship exploration use openNodes → getNeighbors). Regression lock: test/search-graph-default.test.mjs.docs/UPDATING.md.)Observation lifecycle (schema v13). Observations used to be a JSON array of strings on the
entity row. A correction overwrote a string, so the fact that it was a correction disappeared —
and if you deleted the wrong duplicate, nothing recorded that either. Observations now have stable
ids, provenance, and a status, and entities.observations becomes a projection synthesised from
the active revisions.
correctObservation(observation_id, content, change_kind, reason)
marks the old revision superseded and inserts a new one that inherits its position in the array,
so a correction does not reorder anything.active revisions only. A retracted or superseded fact stops coming back from
openNodes / searchNodes / readGraph / getNeighbors without being destroyed.getObservationHistory({entity_name | observation_id | root_id}) is the only history surface.
It always returns { roots: [...] }, one root per logical observation, revisions oldest-first.retract / restore / approve / decline.
superseded is terminal. Anything outside the table is rejected.addObservations and createEntities accept sources: [{source_kind, source_ref, source_hash?}].
Repeated content from a new source adds evidence to the existing revision instead of a duplicate.
Unknown provenance is zero source rows — the engine does not invent one.observation_ids: addObservations and createEntities return ids aligned 1:1 with the input,
null where no revision was created (dedup or source-only).purgeObservation(observation_id, 'PURGE') physically deletes, as a suffix purge from the
target to the newest revision of that root. It is separate, explicit, and almost never what you want.deleteObservations is deprecated. It now performs a soft retract instead of
a delete, and a batch where any item matches two or more active revisions aborts with zero
mutations — v3.6 deleted every duplicate and carried on, but a machine cannot tell which
revision was meant. Use retractObservation(observation_id) to say which one.<db>.v12.bak) using the SQLite Online Backup API,
and verifies it — quick_check plus FTS5's own integrity-check, because a snapshot can be
structurally valid and still have a broken full-text index. An existing one is never
overwritten: the next attempt writes .bak.1, then .bak.2. Every file in that rotation was
taken before any schema change, so each is a valid pre-migration snapshot on its own and nothing
has to prove which matches the live database. Slots are bounded and a full set refuses to migrate.
Conversion runs in one transaction with two gates: PRAGMA foreign_key_check, then a byte-exact
comparison of the rebuilt projection against the original array. foreign_keys is checked at boot
and the server refuses to migrate without it. Restore and slot-exhaustion runbook:
docs/UPDATING.md.deleteObservations left stale entity vectors behind.search_mode (hybrid / hybrid-partial / fts-only), model state, provenance coverage and a degradation_reason; searchNodes gains a lexical FTS fallback so entities never disappear from search while embeddings catch up. getKnowledgeGraphStats gains a server block (version, node, states, coverage) for update-reliability checks.hybridSearch now returns an envelope {results, search_mode, model_state, coverage, degradation_reason?} instead of a bare array (per-item search_mode removed). (2) deleteObservations returns {results: [{entityName, deleted, embedding_status}], total_deleted} instead of a success string. Error responses now set isError: true. Migration/rollback and fleet-rollout guidance: docs/UPDATING.md.syncDocumentFromFile: embeddings are computed before any DB write, then applied in a single synchronous transaction, so a failed embedding (e.g. model still loading) leaves the existing document fully intact instead of a half-deleted or partially-embedded state.content_hash dedup: unchanged files short-circuit the delete/chunk/embed pipeline (skipped: true), with a completeness gate that still re-processes a partially-embedded document.hybridSearch returns BM25 (full-text) results tagged search_mode: 'fts-only' instead of failing the whole query.syncDocumentFromFile: one-call server-side document sync - reads a file on the server and runs the full pipeline (deleteDocuments → storeDocument → chunkDocument → embedChunks → linkEntitiesToDocument) in a single call, returning only a terse summary { documentId, bytes, chunks, embeddedChunks, linkedEntities, warning? }. File content is read server-side and never routed through the model context, collapsing the usual 5 tool calls per document into one and keeping conversation context flat (the dominant cost of large sync runs). 30 → 31 tools.npm run verify:invariants (wired as prepublishOnly) catches chunkText offset regressions before they ship. Tests ASCII / Korean / emoji-heavy / mixed CJK + supplementary plane / pure supplementary inputs against the codepoint-slice contract.chunkText extracted to src/chunkText.ts — algorithm now testable in isolation. The class method is a thin wrapper. No user-facing API change.start_pos/end_pos that disagreed with SQL substr and Python slicing for any chunk crossing a supplementary character. chunkText now maintains parallel UTF-16 + codepoint cursors and reports codepoint offsets.chunk_metadata.start_pos/end_pos from UTF-16 units to codepoints by re-locating each chunk via indexOf and counting codepoints.ALTER TABLE idempotency guards — some databases from early v3.x experiments (Ollama dimension swap) had recorded a migration at version 9, causing the new v9 migration to silently no-op. Bumped to version 10 and added PRAGMA table_info guards so the column-add is safe to re-run.chunk_metadata — added start_token/end_token columns. Existing start_pos/end_pos are reinterpreted as character offsets into documents.content. Backfill migration recomputes char offsets via indexOf with a per-document cursor; misses leave NULL so callers can re-chunk to repair.getGraphMetrics (degree / betweenness / closeness / pagerank), detectCommunities (Louvain + modularity), analyzeGraphStructure (density / components / clustering). 27 → 30 tools.autoLinkEntities silent failure — was JOINing a non-existent observations table (observations are stored as JSON array column in entities). Changed to direct column select + JSON.parse().linkEntitiesToDocument — entities are now linked only to chunks where they actually appear (using buildEntityMatcher word-boundary/CJK matching), instead of blanket-linking to all chunks. Fixes search result domination by heavily-linked documents.@huggingface/transformers with bge-m3 (1024-dim). No external services required..memory/dictionary.json for custom translation pairssrc/tools/ with structured registrysrc/migrations/ with versioned schema upgradesgetNeighbors tool with WITH RECURSIVE CTE, depth 1-5, cycle detection, bidirectionalEMBEDDING_MODEL env var to use alternative embedding modelsembedAllEntities processes 32 entities in parallelsearchNodes with since/until ISO 8601 date filterssafeRowid() validation for vec0 operations[YYYY-MM-DD] prefix for staleness trackinggit clone https://github.com/bripin123/rag-memory-epf-mcp.git
cd rag-memory-epf-mcp
npm install
npm run build
npm test # build + invariant verification
npm run verify:invariants # standalone invariant test (assumes dist/ built)
npm publish automatically runs prepublishOnly (build + verify:invariants); a chunk-offset regression blocks the publish at the source.
MIT License. See LICENSE.
Model weights are downloaded at runtime and not bundled in this package.
Built with: TypeScript, SQLite (WAL + FTS5 + sqlite-vec), bge-m3, MCP SDK 1.27.1
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).
{ "mcpServers": { "rag-memory-epf-mcp": { "command": "npx", "args": [ "-y", "[email protected]" ] } }}เครื่องมือ
ยังไม่มีรายการเครื่องมือ เซิร์ฟเวอร์แบบรีโมตจะได้รายการหลังการตรวจสอบสถานะครั้งแรก
FAQ
คัดลอกคอนฟิก stdio สำหรับ Cursor, Claude Desktop, Claude Code หรือ VS Code ได้ในหน้านี้ คอนฟิกนี้ใช้การติดตั้งของผู้เผยแพร่ ไม่ใช่พร็อกซีของ PlugMCP
ระเบียนนี้ไม่ได้ระบุตัวแปรสภาพแวดล้อมที่จำเป็น
Rag Memory Epf ทำงานแบบโลคัลผ่าน stdio
ตรวจสอบล่าสุดเมื่อ 2026-11-13 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).