Search PDFs, DOCX, text, and Markdown with local embeddings and hybrid retrieval. Configure the document root and index path; client privacy remains a separate choice.
mcp-local-rag uses a local embedding model for semantic and keyword search. File ingestion supports PDF, DOCX, TXT and Markdown; pass already-fetched HTML through ingest_data. Text ingestion and search work offline once required models are cached, unless a configured reranker makes network requests.
One-liner. Verify with claude mcp list. Remove with claude mcp remove.
Node.js 22 and a stable document index
Use Node.js 22 or newer. In the existing client example, add BASE_DIR to the server environment and replace the example paths below with absolute paths on your machine. BASE_DIR limits file access; DB_PATH and CACHE_DIR keep the index and model cache stable when the client starts from another working directory.
This Cursor configuration follows the author README. The examples are documentation examples; no package was installed or executed for this guide.
Query confidential contracts / HR docs with local embeddings and a separately chosen client
👤 Legal ops, HR, compliance⏱ ~20 minintermediate
When to use: Documents are too sensitive for OpenAI/Claude cloud embeddings. You need search but can't send content anywhere.
Flow
Ingest
Ingest /secure/contracts/*.pdf into local-rag.✓ Copied
→ Files indexed locally; confirm no network call was made
Query
Which contracts have an auto-renewal clause longer than 12 months?✓ Copied
→ List of candidate contracts with the clause quoted
Outcome: A locally indexed corpus; choose and configure the MCP client separately if retrieved passages must remain on the machine.
Pitfalls
Claude answers still go to Anthropic — the embeddings are local but conversation isn't — If answers must also be local, run with a local LLM via Ollama or LM Studio instead of cloud Claude
Capture JS-rendered pages and ingest their extracted text
Open this SPA, grab the rendered HTML, ingest_data it into local-rag with the URL as source.✓ Copied
Tools
What this MCP exposes
Tool
Inputs
When to call
Cost
ingest_file
filePath: absolute string; one file per call
Add or replace one document file; use sync_start for a directory.
CPU only
ingest_data
content: string; source: stable identifier
Add a raw HTML blob — useful after scraping
CPU only
query_documents
query: string; limit?: number; scope?: absolute prefix or prefixes
Main retrieval call — use before answering user questions
free
list_files
See what's indexed
free
delete_file
filePath?: absolute string, or source?: identifier
Remove a stale/irrelevant file from the index
free
status
Sanity check index size
free
Cost & Limits
What this costs to run
API quota
None — all local
Tokens per call
Bound returned text with limit; inspect passages before requesting a synthesis.
Monetary
Free. One-time ~90MB model download.
Tip
Use the documented limit parameter to bound returned passages, then inspect source context before asking for a synthesis.
Security
Permissions, secrets, blast radius
Credential storage: None — no API keys
Data egress: Document ingestion and search are local after required models are cached, unless RAG_RERANK_CMD invokes a networked command. The MCP client separately controls what it does with returned passages.
Single-user — no multi-user isolation. Don't share the index directory.
Changing the embedding model requires a fresh index at a new DB_PATH and re-ingestion.
Local embeddings and MCP client privacy
The server returns retrieved document text to its MCP client. A local index alone does not determine how the host application handles that context. Review your client and model configuration before querying confidential files. A custom RAG_RERANK_CMD also needs its own network review.
Embedding model is downloading on first run (~90MB). Subsequent calls are fast.
Verify: Check the configured CACHE_DIR (default ./models/), resolved from the server working directory
PDF ingest returns 0 chunks
PDF is likely scanned (image-only). Run ocrmypdf input.pdf output.pdf first.
Verify: pdftotext input.pdf -
Results feel irrelevant
Pure semantic search struggles with short queries. Add more keywords. The hybrid search boosts them already.
Out of memory on large PDFs
Split the PDF first, or raise Node heap: NODE_OPTIONS=--max-old-space-size=8192
Fix empty results and path errors
Start a directory sync with sync_start and poll sync_status until it completes. Then ask the client to list ingested files before querying. If ingestion succeeds but search is empty, confirm both processes use the same absolute DB_PATH.
A Path outside BASE_DIR error means the file is outside the configured roots. BASE_DIRS takes a JSON array of absolute roots, not a colon-separated list. Source-code extensions are not accepted by file ingestion; index supported documentation files instead. For in-memory HTML, use ingest_data with content and a stable source identifier.
Example request to your MCP client
Sync the configured document root and wait for completion.
List the indexed files. Search for the authentication API and show the source passages.