MCP Local RAG

Local semantic and keyword search over your own PDF, DOCX, Markdown and text files

By shinpr (individual) TypeScript Local · stdio Knowledge and memoryFiles and storage

67 popularity score ★ 428 ↓ 4.1k/wk

Connect your client

Local (npm)

Add in one click

Opens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.

Or add it by command or config

It needs BASE_DIR. Replace each <NAME> with your value.

Claude CodeTerminal
claude mcp add local-rag -e BASE_DIR=<BASE_DIR> -- npx -y mcp-local-rag
Claude Desktopclaude_desktop_config.json
{
  "mcpServers": {
    "local-rag": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-local-rag"
      ],
      "env": {
        "BASE_DIR": "<BASE_DIR>"
      }
    }
  }
}
Cursor~/.cursor/mcp.json
{
  "mcpServers": {
    "local-rag": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-local-rag"
      ],
      "env": {
        "BASE_DIR": "<BASE_DIR>"
      }
    }
  }
}
VS Code.vscode/mcp.json
{
  "servers": {
    "local-rag": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "mcp-local-rag"
      ],
      "env": {
        "BASE_DIR": "<BASE_DIR>"
      }
    }
  }
}
Codex~/.codex/config.toml
[mcp_servers.local-rag]
command = "npx"
args = ["-y", "mcp-local-rag"]

[mcp_servers.local-rag.env]
BASE_DIR = "<BASE_DIR>"
Gemini CLITerminal
gemini mcp add --scope user -e BASE_DIR=<BASE_DIR> local-rag npx -- -y mcp-local-rag

Settings 12

Set together: document roots
BASE_DIR Required: Absolute path of the document folder and the boundary for file access. Default the working directory.
BASE_DIRS Optional: JSON array of several document folders; takes precedence over BASE_DIR.
IGNORE_PATHS Optional: JSON array of glob patterns, relative to each root, for files to keep out of the index; sync also drops matches already indexed. For sync_start.
DB_PATH Optional: Where the LanceDB index is stored; set an absolute path. Default ./lancedb/.
CACHE_DIR Optional: Where downloaded models are cached; set an absolute path. Default ./models/.
MODEL_NAME Optional: Hugging Face embedding model; changing it needs a new DB_PATH. Default Xenova/all-MiniLM-L6-v2.
MAX_FILE_SIZE Optional: Largest file to ingest in bytes, at most 524288000. Default 104857600.
RAG_HYBRID_WEIGHT Optional: Keyword boost from 0.0 to 1.0. Default 0.6. For query_documents.
RAG_MAX_FILES Optional: Keep results from only the top N files. For query_documents.
RAG_RERANK_CMD Optional: External command that reorders results; it receives matched text on stdin. For query_documents.
STORE_IMAGES Optional: Set true to store PDF figures and DOCX images with matching text. Default false.
RAG_DEVICE Optional: ONNX Runtime device for embeddings. Default cpu.

What it does

MCP Local RAG builds a search index of documents on your own machine and lets an MCP client query it. It splits PDF, DOCX, Markdown and plain-text files into chunks, embeds them with a Hugging Face model run locally through Transformers.js, and stores the vectors in an embedded LanceDB database on disk. Queries mix vector similarity with a keyword boost, so exact terms such as error codes or class names still rank well, and each hit comes back with its source passage and, where it can tell, the heading, line or page.

The server exposes nine tools: a background sync that reconciles the index with the document folders, single-file and in-memory ingestion (text, Markdown, or HTML the client has already fetched), search, reading the chunks around a hit, listing files and their indexed state, deletion, and a status report. The same package also works as a command-line tool for ingesting and querying without an MCP client, with JSON output.

No API key or external service is needed. After the embedding model (about 90 MB by default) is downloaded once, ingestion and search run offline. Optional extras include local captioning of PDF figures with a vision model (about 250 MB, or 1.7 GB for the quality profile), storing images alongside text, passing results through an external rerank command you supply, and IGNORE_PATHS, a JSON list of glob patterns for files to keep out of the index.

What the code at v0.23.1 adds to the README: query_documents returns 10 results by default and takes a limit from 1 to 100. read_chunk_neighbors fetches 2 chunks either side by default, up to 50, and folder scans stop 10 levels deep (src/utils/limits.ts). The server also refuses to use /etc, /usr, /sys, /proc, /var, ~/.ssh or ~/.gnupg as a document root, and every tool that needs a root then fails with that error (src/utils/sensitive-path.ts, src/server-main.ts).

What it needs

RuntimeNode.js 22.20+
Runs onmacOS, Windows, Linux
Also
  • About 90 MB of disk for the default embedding model, more for figure captioning

The README asks for Node.js 22.20 or later, but package.json at v0.23.1 declares ^22.23.4, ^24.22.1 or >=26.12.1, so use a current 22, 24 or 26 release. Internet access is needed on first run to fetch the npm package and the embedding model from Hugging Face (HF_ENDPOINT can point at a mirror). PDF figure captioning downloads a further 250 MB or 1.7 GB model when first used. Give the document folder by absolute path in BASE_DIR or BASE_DIRS. Runs on CPU by default.

Limits

  • Not covered File ingestion takes PDF, DOCX, TXT and Markdown only. Excel, PowerPoint, standalone images and source code are not supported.
  • Not covered The server does not fetch web pages itself. The client passes fetched HTML to ingest_data.
  • Limit Figure captions are generated descriptions, not OCR, and PDF section headings may be wrong.
  • Limit Only one sync job is kept, and it is lost when the server exits.
  • Limit Changing the embedding model needs a fresh index at a new DB_PATH. Changing RAG_DTYPE or a prefix option needs a full re-ingest.
  • Limit Only one writer may use a DB_PATH at a time.
  • Limit Unset or relative DB_PATH and CACHE_DIR resolve from the working directory, so each project start can create its own index.
  • Size cap MAX_FILE_SIZE defaults to 100 MB. A value above 500 MB or not a whole number is ignored with a warning and the default is used.
  • Limit An invalid IGNORE_PATHS stops the server at start. Its * and ** patterns skip names starting with a dot unless written out.
  • Platform RAG_RERANK_CMD runs without a shell, so a Windows .cmd shim will not start.

File ingestion handles only PDF, DOCX, TXT and Markdown; Excel, PowerPoint, standalone images and source-code files are not supported, and the server does not fetch web pages itself. Figure captions are generated descriptions, not OCR. PDF section headings may be wrong. Only one sync job is kept and it is lost when the server exits. Changing the embedding model needs a fresh index at a new DB_PATH; changing RAG_DTYPE or the prefix options needs a full re-ingest. Only one writer may use a DB_PATH at a time. Unset DB_PATH and CACHE_DIR resolve from the working directory, so each project can get its own index. RAG_RERANK_CMD runs without a shell, so a Windows .cmd shim will not start.

Who it suits

Suits a single developer or researcher who wants an assistant to search a private folder of manuals, specs, papers or notes without sending text to an embedding API, and who can run a recent Node 22 or later locally. Hybrid scoring helps with technical material full of exact identifiers. It is not built for shared or multi-user use: it has no authentication and assumes one writer per index. Pick something else to search spreadsheets, slide decks or code files, to crawl the web, or to index scanned PDFs that need OCR.

Tools 9

5 only read, 4 change things. A ? marks an optional parameter.

sync_start changes
Starts a background job that brings the index in line with the files on disk, for all roots or one pathpath?: string
sync_status
Reports progress and the outcome of a sync jobjobId: string
ingest_file changes
Indexes or replaces one file, optionally captioning PDF figuresfilePath: stringvisual?: booleanvisualQuality?: enum
ingest_data changes
Indexes text, Markdown or HTML passed in by the client under a source identifiercontent: stringmetadata: object
query_documents
Searches the index with vector similarity plus a keyword boost; 10 results by default, up to 100query: stringlimit?: numberscope?: any
read_chunk_neighbors
Returns the chunks before and after a search hitfilePath?: stringsource?: stringchunkIndex: numberbefore?: numberafter?: number
list_files
Lists supported files under the roots and whether each is indexed, plus ingested data sourcesscope?: any
delete_file changes
Removes an indexed file or ingested data item from the index, leaving the source file alonefilePath?: stringsource?: string
status
Shows index size and search settings

Similar servers