Local RAG
About
Privacy-first local RAG server for semantic document search without external APIs
Details
- Author
- shinpr
- Categories
- Search, Knowledge Base, Other
Jump to
Setup
Install Local RAG in your MCP client (Claude Desktop, Cursor, Windsurf, and others).
Repository: https://github.com/shinpr/mcp-local-rag
Follow the installation instructions in the repository README, then restart your MCP client.
English|简体中文|Deutsch|Español|Português (Brasil)|Français
Search private documents from an MCP client or the terminal without sending them to an embedding API.
mcp-local-rag indexes PDF, DOCX, Markdown, and text files on your machine. Search combines semantic similarity with keyword matching, so queries can match both intent and exact technical terms such as API names, class names, and error codes.
- Runs locally:Document parsing, embeddings, storage, and search run on your machine. After the initial model download, text ingestion and search work offline.
- Hybrid search:Semantic retrieval finds related concepts, while keyword matching boosts exact technical terms.
- Configurable embeddings:Choose a Hugging Face embedding model that fits the language and domain of your documents.
- Semantic chunking:Documents are split at topic boundaries instead of fixed character counts. Markdown code blocks stay intact.
- MCP and CLI:Use the same index from an AI coding tool or directly from the terminal.
No API key, Docker, Python, or external database is required.
- Node.js 22 or later
- Internet access on first use to download the npm package and embedding model
- A directory containing the documents you want to search
SetBASE_DIRto that directory. It is also the security boundary for file operations. Replace/absolute/path/to/your/documentsbelow with the directory's absolute path.
mcp-local-rag uses the standard MCP protocol over a local stdio server, so it works with AI coding tools and other MCP hosts that support local MCP servers.
Use one of the examples below, or registernpx -y mcp-local-ragand setBASE_DIRusing your client's MCP configuration format.
claude mcp add local-rag --scope user --env BASE_DIR=/absolute/path/to/your/documents -- npx -y mcp-local-rag
For Codex:Add to~/.codex/config.toml:
[mcp_servers.local-rag] command = "npx" args = ["-y", "mcp-local-rag"] [mcp_servers.local-rag.env] BASE_DIR = "/absolute/path/to/your/documents"
For OpenCode:Add to~/.config/opencode/opencode.json(oropencode.jsonc):
{ "$schema": "https://opencode.ai/config.json", "mcp": { "local-rag": { "type": "local", "command": ["npx", "-y", "mcp-local-rag"], "environment": { "BASE_DIR": "/absolute/path/to/your/documents" } } } }
{ "mcpServers": { "local-rag": { "command": "npx", "args": ["-y", "mcp-local-rag"], "env": { "BASE_DIR": "/absolute/path/to/your/documents" } } } }
Restart the client, then ask it to build the index:
Sync all documents in the configured root and wait until it finishes.
The first sync downloads the default embedding model (about 90 MB) and may take 1–2 minutes before ingestion starts. Later runs use the local cache.
What does the API documentation say about authentication?
npx mcp-local-rag ingest ./docs/ npx mcp-local-rag query "authentication API"
The CLI uses the current directory as its document root by default. Run both commands from the same directory so they use the same default index, or setBASE_DIRandDB_PATHexplicitly.
Some document sets cannot be sent to a hosted embedding service because of confidentiality or organizational policy. Keeping the index local makes them searchable without adding a per-query API cost.
Semantic search alone can miss exact identifiers that matter in technical documentation. Keyword reranking keeps those terms visible without giving up natural-language retrieval.
HTML fetching is not built into the server. An MCP client can fetch a page and pass its HTML toingest_data.
Excel, PowerPoint, standalone images, and source-code file extensions are not supported by file ingestion. PDFs can optionally use a local vision model to describe figures, but this is not OCR or image search.
sync_startingests new and changed files, skips byte-identical files, and removes index entries for files that no longer exist:
Sync everything under the configured document roots and wait for completion.
The tool returns ajobIdimmediately. Clients should pollsync_statusuntil its state becomessucceededorfailed. There is no visual mode during sync; changed PDFs are ingested as text.
Only one sync job is retained by the server process. A newer job replaces a finished record, and restarting the server discards it.
ingest_fileaccepts PDF, DOCX, TXT, and Markdown. MCP file paths must be absolute and must stay inside a configured document root:
Ingest the document at /Users/me/docs/api-spec.pdf.
Re-ingesting the same path replaces its existing chunks.
What does the API documentation say about authentication? Find the documented behavior of ERR_CONNECTION_REFUSED.
Results contain the text, source path, title, chunk index, and relevance score. Pass thechunkIndexand eitherfilePathorsourcefrom a result toread_chunk_neighborswhen the answer needs more context:
Read the surrounding chunks for that authentication result.
Bothquery_documentsandlist_filesaccept an optional absolutescopepath prefix, or a list of prefixes. A prefix matches the exact path and its descendants.
Useingest_dataafter the MCP client fetches a page:
Fetch https://example.com/docs and ingest the HTML.
The server extracts the main article, converts it to Markdown, and stores it under the supplied source identifier. Reusing the same source updates the existing content.
Respect the source site's terms and copyright when indexing external content.
Visual mode adds a generated caption for figure-heavy PDF pages. It is opt-in and does not load a vision model during normal ingestion.
Ingest /Users/me/docs/research-paper.pdf with visual: true.
npx mcp-local-rag ingest ./docs/research-paper.pdf --visual
Select the larger model withvisualQuality: "quality"over MCP or--visual-quality qualityover CLI. Measured CPU inference was about twice as slow asfast, though results depend on hardware and model updates.
Captions are auxiliary text, not faithful transcriptions. Treat retrieved captions and document text as untrusted input rather than instructions.
The CLI uses the same parser, embedder, and vector store without an MCP client:
npx mcp-local-rag ingest ./docs/ npx mcp-local-rag sync ./docs/ npx mcp-local-rag query "authentication API" npx mcp-local-rag query "auth" --scope /docs/api --scope /docs/guide npx mcp-local-rag read-neighbors --file-path /abs/path.md --chunk-index 5 npx mcp-local-rag list npx mcp-local-rag status npx mcp-local-rag delete ./docs/old.pdf npx mcp-local-rag delete --source "https://example.com/docs"
Global options such as--db-path,--cache-dir, and--model-namego before the subcommand. Subcommand options go after it:
npx mcp-local-rag --db-path ./my-db query "authentication"
Runnpx mcp-local-rag --helpfor the complete command reference.
The CLI does not read MCP client configuration. Set the same environment variables or flags if both interfaces should share an index. In particular,MODEL_NAMEand the CLI--model-namemust match for a shared database.
Keyword boost is enabled by default. Relevance-gap grouping and the distance and file filters are optional controls for corpora that need tighter result selection.
For API specifications and other documents containing many identifiers, a stronger keyword weight can improve exact-term ranking:
"env": { "RAG_HYBRID_WEIGHT": "0.7" }
- 0.7: slightly stronger exact-term reranking than the default
- 1.0: maximum keyword boost
- The parser extracts text for the input format.
- The semantic chunker finds topic boundaries and preserves Markdown code blocks.
- Transformers.js creates embeddings locally.
- LanceDB stores the chunks, metadata, vectors, and full-text index.
- The query is embedded with the same model.
- Vector search retrieves semantically related chunks.
- Optional distance and relevance-group filters narrow the candidates when configured.
- Full-text matches boost exact query terms.
Agent Skillsprovide query and ingestion guidance for AI assistants:
npx mcp-local-rag skills install --claude-code npx mcp-local-rag skills install --claude-code --global npx mcp-local-rag skills install --codex
Installed skills cover query formulation, result refinement, and HTML ingestion. Ask the assistant to use the mcp-local-rag skill explicitly if it does not activate automatically.
The MCP server reads environment variables. The CLI accepts the same variables plus the listed flags, with CLI flags taking precedence.
Document Roots (BASE_DIRandBASE_DIRS)
mcp-local-rag only allows file operations inside configured roots. For multiple roots,BASE_DIRSmust be a JSON array of non-empty paths:
export BASE_DIRS='["/Users/me/Documents/work","/Users/me/Projects/specs"]'
Root configuration is resolved in this order:
- CLI--base-dir <path>flags (repeatable oningest,list, andsync)
- BASE_DIRS
- BASE_DIR
- Current directory
Each source replaces the lower-priority source rather than merging with it. InvalidBASE_DIRSconfiguration fails instead of falling back toBASE_DIRor the current directory.statusremains available in MCP so the client can report the configuration error.
npx mcp-local-rag ingest --base-dir /Users/me/work --base-dir /Users/me/specs /Users/me/work/readme.md npx mcp-local-rag list --base-dir /Users/me/work --base-dir /Users/me/specs npx mcp-local-rag sync --base-dir /Users/me/work --base-dir /Users/me/specs BASE_DIRS='["/Users/me/work","/Users/me/specs"]' npx mcp-local-rag list
DB_PATHandCACHE_DIRare relative to the process working directory by default. Set absolute paths when the MCP client may start the server from different project directories.
SetMODEL_NAMEor pass--model-nameto choose a Hugging Face embedding model that fits the language and domain of your documents.
mcp-local-rag generates embeddings with mean pooling and L2 normalization. When choosing a model, check whether these settings match its recommended inference setup, since the pooling method can affect retrieval quality.
ChangingMODEL_NAME,RAG_DEVICE, orRAG_DTYPEcan make existing vectors incompatible. Use a newDB_PATHor delete the existing index and re-ingest after changing the embedding configuration.
An example model for English documents isXenova/bge-small-en-v1.5.
- File access is restricted toBASE_DIR,BASE_DIRS, or CLI--base-dirroots.
- Symlinks that resolve outside every configured root are rejected.
- Document processing and search make no network requests after the required models are cached.
- The server is designed for one local user and does not provide authentication or access control.
- Do not run multiple CLI or MCP writers against the sameDB_PATH. Read-only queries can run while a sync is active.
- Back up an index by copying itsDB_PATHdirectory while no writer is active.
Documents must be ingested first. Run"List all ingested files"to verify.
Check internet connection. If behind a proxy, configure network settings. The model can also bedownloaded manually.
Default limit is 100MB. Split large files or increaseMAX_FILE_SIZE.
Check chunk count withstatus. Large documents with many chunks may slow queries. Consider splitting very large files.
Ensure file paths are within one of the configured roots (BASE_DIR, anyBASE_DIRSentry, or any CLI--base-dir). Use absolute paths.
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.




