The index is built under directories you nominate and the sync pass keeps it level with what is on disk, so a folder you already maintain stays searchable without being re-added file by file. Reading the neighbouring chunks matters more than it sounds: a single retrieved chunk is often too little to answer from.
A retrieval server over an index held on your own machine. Parsing, embedding, storage and search all run locally, so the documents never reach an embedding API — after the model downloads once, it works offline.
- Hybrid keyword and semantic search, so a query matches both the idea and the exact API name, class name or error code
- Ingestion of PDF, DOCX, TXT and MD files by absolute path, where re-ingesting the same path replaces what was there
- In-memory content ingested as a string under a source identifier, so a web page or a clipboard paste that never became a file is still searchable
- Chunking at topic boundaries rather than fixed character counts, with Markdown code blocks left intact
- Neighbour reads: pass the chunk index from a result and get the chunks around it, for when one chunk is not enough to answer from
- A reconciliation pass that ingests new and changed files, leaves unchanged ones alone and prunes entries for files that are gone, returning a job id you poll for progress
- Index status with document and chunk counts, memory usage, uptime, and whether the full-text index is on
- A listing of supported files under the base directories that marks which are ingested
- The embedding model swapped for one that suits your language or domain, with the search tuned by distance threshold, grouping and keyword weight
Node.js 22 or later, and BASE_DIR pointing at the directory holding your documents — that directory is also the boundary for file operations, and anything you ingest by path must be given absolutely. No API key, no Docker, no Python and no external database; internet access is needed once, to fetch the package and the embedding model. Changing the embedding model or its quantization changes the embedding space, so re-ingest what is already indexed. MIT.
One command — npx -y mcp-local-rag
