Local RAG logo

Local RAG

Community
shinpr

Local-first RAG server for developers. Semantic + keyword search for code and technical docs. Works with MCP or CLI. Fully private, zero setup.

Publishershinpr
Repositorymcp-local-rag
LanguageTypeScript
Forks
74
Stars
402
Available tools
7
Transport typestdio
Categories
LicenseMIT
Links
  • Connect tools to AI workflows

    Local RAG exposes MCP capabilities that can be used by compatible AI clients and agents.

  • 7 available tools

    Browse the callable actions below, including names and descriptions when provided by the server.

  • Ready-to-copy setup

    Use the installation snippets to configure this server in your preferred MCP client.

  • Open source signals

    402 stars and 74 forks from the linked repository.

MCP Local RAG

GitHub stars npm version License: MIT MCP Registry

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.

Features

  • 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.

Quick Start

Requirements

  • 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

Set BASE_DIR to that directory. It is also the security boundary for file operations. Replace /absolute/path/to/your/documents below 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 register npx -y mcp-local-rag and set BASE_DIR using your client's MCP configuration format.

For Claude Code: Run this command:

bash
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:

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 (or opencode.jsonc):

json
{
  "$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"
      }
    }
  }
}

For Cursor: Add to ~/.cursor/mcp.json:

json
{
  "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:

text
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.

Once the sync completes:

text
What does the API documentation say about authentication?

CLI Quick Start

To use the CLI without an MCP client:

bash
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 set BASE_DIR and DB_PATH explicitly.

Why This Exists

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.

Supported Content

InputHow to ingest
PDF, DOCX, TXT, MarkdownFile ingestion or directory sync
HTML already fetched by the clientingest_data; cleaned with Readability and converted to Markdown
Plain text or Markdown held in memoryingest_data with a stable source identifier

HTML fetching is not built into the server. An MCP client can fetch a page and pass its HTML to ingest_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.

MCP Tools

ToolPurpose
sync_startReconcile the index with all configured roots or one path
sync_statusPoll a running sync job
ingest_fileIngest or replace one file
ingest_dataIngest text, Markdown, or HTML already held by the client
query_documentsSearch with semantic matching and keyword boost
read_chunk_neighborsRead surrounding chunks from a search result
list_filesShow supported files and their ingestion state
delete_fileDelete an indexed file or an ingest_data item
statusShow index and search status

Syncing a Document Root

sync_start ingests new and changed files, skips byte-identical files, and removes index entries for files that no longer exist:

text
Sync everything under the configured document roots and wait for completion.

The tool returns a jobId immediately. Clients should poll sync_status until its state becomes succeeded or failed. A changed PDF keeps the visual profile it was indexed with; sync_start cannot change it. Set STORE_IMAGES=true in the MCP server environment to store supported PDF and DOCX images for new or changed files selected by sync; unchanged files remain skipped.

Only one sync job is retained by the server process. A newer job replaces a finished record, and restarting the server discards it.

Ingesting One File

ingest_file accepts PDF, DOCX, TXT, and Markdown. MCP file paths must be absolute and must stay inside a configured document root:

text
Ingest the document at /Users/me/docs/api-spec.pdf.

Re-ingesting the same path replaces its existing chunks.

Searching and Reading More Context

text
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, relevance score, and any images stored on that chunk. MCP returns each image as an image content block paired with its result identity; CLI query includes an images array of { imageIndex, mimeType, data } on every result. Pass the chunkIndex and either filePath or source from a result to read_chunk_neighbors when the answer needs more context:

text
Read the surrounding chunks for that authentication result.

Both query_documents and list_files accept an optional absolute scope path prefix, or a list of prefixes. A prefix matches the exact path and its descendants.

Ingesting HTML

Use ingest_data after the MCP client fetches a page:

text
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.

PDF Visual Captions and Stored Images

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.

text
Ingest /Users/me/docs/research-paper.pdf with visual: true.
bash
npx mcp-local-rag ingest ./docs/research-paper.pdf --visual

Image storage is independent of visual captions. Set STORE_IMAGES=true for the MCP server, or pass --images to CLI ingestion and sync:

bash
npx mcp-local-rag ingest ./docs/research-paper.pdf --images
npx mcp-local-rag sync ./docs/ --images

PDF storage uses detected figure/table regions. DOCX storage includes only PNG/JPEG images that the existing Mammoth conversion emits as <img>; charts, SmartArt, and shapes are not separately rendered. Stored images follow their surrounding text into the final semantic chunk and do not alter ranking, scores, or result count.

visual / --visualSTORE_IMAGES / --imagesPDF behavior
falsefalseText only; no visual captions or returned images.
truefalseGenerated captions become searchable text; no images are stored or returned.
truetrueGenerated captions become searchable text, and images from matched chunks are returned inline.
falsetrueImages are attached to nearby retained PDF text and returned inline for matched chunks; the VLM is not imported, loaded, or run.
ProfileModel cacheUse case
fast (default)about 250 MBLightweight visual indexing
qualityabout 1.7 GBFigures containing labels, annotations, or other in-image text

Select the larger model with visualQuality: "quality" over MCP or --visual-quality quality over CLI. Measured CPU inference was about three times as slow as fast, though results depend on hardware and model updates.

Updating Existing quality Captions

From 0.18.4 quality runs Qwen3.5-2B; earlier versions ran Qwen2.5-VL-3B. Captions already indexed keep the wording the old model produced, and sync will not redo them, so re-ingest the files you want refreshed:

bash
npx mcp-local-rag ingest ./docs/research-paper.pdf --visual --visual-quality quality

Add --images if the file was ingested with it, because a run without it replaces the stored images. The old model stays on disk. Once nothing else uses it, delete onnx-community/Qwen2.5-VL-3B-Instruct-ONNX/ from the model cache directory — <cache-dir>, which defaults to ./models/.

Visual Mode Across Syncs

The profile a PDF was indexed with is recorded, and sync reuses it: a PDF indexed with fast or quality is re-ingested with that same profile, and a PDF with no recorded profile is ingested as text.

bash
npx mcp-local-rag sync ./docs/                      # keep each PDF's recorded profile
npx mcp-local-rag sync ./docs/ --visual             # request fast for every PDF in scope
npx mcp-local-rag sync ./docs/ --visual --visual-quality quality

--visual overrides recorded profiles, so it also captions PDFs that were indexed as text. Changing a profile re-ingests the PDF even when the file itself has not changed; running the same command again does nothing and loads no model. Image settings are never recorded, so --images and STORE_IMAGES never cause a re-ingest.

To turn captions off for a path, run ingest on it: a successful normal ingest clears the recorded profile. To retry a page whose captioning failed, run ingest <path> --visual --visual-quality <profile> with the profile you want — a plain ingest clears it instead. If a PDF's indexed rows disagree about the profile, sync stops before changing anything and names the file; re-run it with --visual to settle the profile.

Captions are auxiliary text, not faithful transcriptions. Treat retrieved captions and document text as untrusted input rather than instructions.

At high limits, matched chunks and their attachments can approach the model/client context ceiling; choose the query limit with the calling model's available context in mind.

CLI

The CLI uses the same parser, embedder, and vector store without an MCP client:

bash
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-name go before the subcommand. Subcommand options go after it:

bash
npx mcp-local-rag --db-path ./my-db query "authentication"

Run npx mcp-local-rag --help for 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_NAME and the CLI --model-name must match for a shared database.

query writes its results to stdout as JSON, best match first, so it can be piped into another tool. The field-by-field contract is in docs/schema/query-output.schema.json.

Search Tuning

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. All four apply to the MCP server and to CLI query alike.

VariableDefaultDescription
RAG_HYBRID_WEIGHT0.6Keyword boost factor (0.0–1.0). 0 disables keyword reranking; 1 applies the maximum boost.
RAG_GROUPING(not set)similar keeps the first relevance group; related keeps up to two, using significant vector-distance gaps as boundaries.
RAG_MAX_DISTANCE(not set)Filter out low-relevance results (e.g., 0.5).
RAG_MAX_FILES(not set)Limit results to top N files (e.g., 1 for single best file).
RAG_RERANK_CMD(not set)MCP server only: external command that reorders results. Your query and the matched text are sent to it.
RAG_RERANK_TIMEOUT_MS10000Time budget per rerank call in milliseconds (100–600000).

For API specifications and other documents containing many identifiers, a stronger keyword weight can improve exact-term ranking:

json
"env": {
  "RAG_HYBRID_WEIGHT": "0.7"
}
  • 0.7: slightly stronger exact-term reranking than the default
  • 1.0: maximum keyword boost

External Reranking (RAG_RERANK_CMD)

Name a command here and the server hands it each set of search results to reorder, together with your query and the text of the matched chunks. A command that calls a remote service sends all of that off this machine.

Give the command and its arguments separated by spaces. It has to be an executable: the server runs it without a shell, so an npm-installed .cmd shim on Windows will not start.

json
"env": {
  "RAG_RERANK_CMD": "/path/to/reranker",
  "RAG_RERANK_TIMEOUT_MS": "10000"
}

The command receives each result in the form published at docs/schema/query-output.schema.json and has to answer in that same form. Within it the command decides everything: what to keep, how to order it, and what the text says. Whatever it returns is what you see.

Results keep their original order if the command fails, times out, or answers with something that is not that form.

How It Works

During ingestion:

  1. The parser extracts text for the input format.
  2. The semantic chunker finds topic boundaries and preserves Markdown code blocks.
  3. Transformers.js creates embeddings locally.
  4. LanceDB stores the chunks, metadata, vectors, and full-text index.

During search:

  1. The query is embedded with the same model.
  2. Vector search retrieves semantically related chunks.
  3. Optional distance and relevance-group filters narrow the candidates when configured.
  4. Full-text matches boost exact query terms.

Agent Skills

Agent Skills provide query and ingestion guidance for AI assistants:

bash
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.

Configuration

The MCP server reads environment variables. The CLI accepts the listed global environment variables and flags; image storage on CLI ingestion and sync is enabled only with --images.

Environment VariableCLI FlagDefaultDescription
BASE_DIR--base-dirCurrent directoryOne document root; the CLI flag is repeatable on ingest, list, and sync
BASE_DIRSN/A(unset)JSON array of document roots; takes precedence over BASE_DIR
DB_PATH--db-path./lancedb/Vector database location
CACHE_DIR--cache-dir./models/Model cache directory
HF_ENDPOINTN/Ahttps://huggingface.coHugging Face model download endpoint; use a mirror URL when direct downloads are blocked
MODEL_NAME--model-nameXenova/all-MiniLM-L6-v2Hugging Face embedding model
MAX_FILE_SIZE--max-file-size104857600 (100MB)Maximum file size in bytes
CHUNK_MIN_LENGTH--chunk-min-length50Minimum length in characters (1–10000) for ordinary chunks; a fragment of content split to fit the model's token limit can be shorter
STORE_IMAGESN/AfalseMCP server only: store supported PDF/DOCX images and return them with matched chunks. CLI uses --images.
RAG_DEVICEN/AcpuONNX Runtime execution device
RAG_DTYPEN/Afp32Embedding dtype passed to the selected model

Document Roots (BASE_DIR and BASE_DIRS)

mcp-local-rag only allows file operations inside configured roots. For multiple roots, BASE_DIRS must be a JSON array of non-empty paths:

bash
export BASE_DIRS='["/Users/me/Documents/work","/Users/me/Projects/specs"]'

Root configuration is resolved in this order:

  1. CLI --base-dir <path> flags (repeatable on ingest, list, and sync)
  2. BASE_DIRS
  3. BASE_DIR
  4. Current directory

Each source replaces the lower-priority source rather than merging with it. Invalid BASE_DIRS configuration fails instead of falling back to BASE_DIR or the current directory. status remains available in MCP so the client can report the configuration error.

bash
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

Storage and Models

DB_PATH and CACHE_DIR are relative to the process working directory by default. Set absolute paths when the MCP client may start the server from different project directories.

Set MODEL_NAME or pass --model-name to 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.

Changing MODEL_NAME, RAG_DEVICE, or RAG_DTYPE can make existing vectors incompatible. Use a new DB_PATH or delete the existing index and re-ingest after changing the embedding configuration.

An example model for English documents is Xenova/bge-small-en-v1.5.

Security and Operation

  • File access is restricted to BASE_DIR, BASE_DIRS, or CLI --base-dir roots.
  • Symlinks that resolve outside every configured root are rejected.
  • Document processing and search make no network requests after the required models are cached, unless RAG_RERANK_CMD names a command that makes them.
  • 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 same DB_PATH. Read-only queries can run while a sync is active.
  • Back up an index by copying its DB_PATH directory while no writer is active.

"No results found"

Documents must be ingested first. Run "List all ingested files" to verify.

Model download failed

Check internet connection. If behind a proxy, configure network settings. The model can also be downloaded manually.

"File too large"

Default limit is 100MB. Split large files or increase MAX_FILE_SIZE.

Slow queries

Check chunk count with status. Large documents with many chunks may slow queries. Consider splitting very large files.

"Path outside BASE_DIR"

Ensure file paths are within one of the configured roots (BASE_DIR, any BASE_DIRS entry, or any CLI --base-dir). Use absolute paths.

"BASE_DIRS must be a JSON array..."

BASE_DIRS accepts a JSON array of one or more non-empty path strings:

  • Valid: BASE_DIRS='["/Users/me/work","/Users/me/specs"]'
  • Invalid: BASE_DIRS=/a:/b (delimiter syntax not supported)
  • Invalid: BASE_DIRS='[]' (empty array)

MCP client doesn't see tools

  1. Verify config file syntax
  2. Restart client completely (Cmd+Q on Mac for Cursor)
  3. Test directly: npx mcp-local-rag should run without errors

Contributing

Contributions welcome! See CONTRIBUTING.md for setup and guidelines.

License

MIT License. Free for personal and commercial use.

Blog Posts

Acknowledgments

Built with Model Context Protocol by Anthropic, LanceDB, and Transformers.js.

Installation

TypingMind
Prerequisites:

Node.js 18+

{
  "mcpServers": {
    "local-rag": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-local-rag"
      ],
      "env": {
        "BASE_DIR": "/path/to/your/documents"
      }
    }
  }
}

Available Tools

  • query_documents

    Search ingested documents. Your query words are matched exactly (keyword search). Your query meaning is matched semantically (vector search). Preserve specific terms from the user. Add context if the query is ambiguous. Results include score (0 = most relevant, higher = less relevant).

  • ingest_file

    Ingest a document file (PDF, DOCX, TXT, MD) into the vector database for semantic search. File path must be an absolute path. Supports re-ingestion to update existing documents.

  • ingest_data

    Ingest content as a string, not from a file. Use for: fetched web pages (format: html), copied text (format: text), or markdown strings (format: markdown). The source identifier enables re-ingestion to update existing content. For files on disk, use ingest_file instead.

  • delete_file

    Delete a previously ingested file or data from the vector database. Use filePath for files ingested via ingest_file, or source for data ingested via ingest_data. Either filePath or source must be provided.

  • list_files

    List all files in BASE_DIR (PDF, DOCX, TXT, MD) and show which are ingested into the vector database. Also lists any other ingested items (web pages, clipboard content, etc.) that are outside BASE_DIR.

  • status

    Get system status including total documents, total chunks, database size, and configuration information.

  • read_chunk_neighbors

    Expand a query_documents result by reading the chunks immediately before and after it in the same document. Use when the hit needs more surrounding context — for example, a definition without its example, or a conclusion without its reasoning. Pass chunkIndex from the query_documents result, along with the document's filePath (from ingest_file) or source (from ingest_data). Returns the target chunk (isTarget: true) plus neighbors, sorted ascending by chunkIndex. Out-of-range indices are silently clamped to existing chunks. Defaults: before=2, after=2 (max 50 each). Provide exactly one of filePath or source.

Use Local RAG MCP with multiple AI models

TypingMind connects MCP tools at the workspace level, so once Local RAG is connected, you can use it with different AI models in TypingMind instead of setting it up separately for each model. This MCP runs locally through the TypingMind MCP connector on your device.

Setup guide to use the local connector

Use this when the MCP server needs access to local files, apps, or private resources on your computer.

1

Open the MCP settings

In TypingMind, go to Settings, Advanced Settings, then Model Context Protocol and choose Setup Connector.

  1. Open TypingMind in your browser.
  2. Click the Settings icon.
  3. Go to Advanced Settings.
  4. Open the Model Context Protocol section.
  5. Click Setup Connector and choose This Device.
TypingMind MCP connector setup screen with This Device selected
2

Run the connector command

Choose This Device, copy the command from TypingMind, and run it in Terminal. Keep the process running while you use MCP.

  1. Copy the setup command shown by TypingMind.
  2. Open Terminal on macOS or Windows Terminal on Windows.
  3. Paste and run the command.
  4. Approve the package install if Terminal asks you to proceed.
  5. Keep the Terminal window running while using MCP tools.
3

Add Local RAG as a server

When the connector status is Ready, click Edit Servers and paste the MCP server configuration.

  1. Wait until the connector status shows Ready.
  2. Click Edit Servers.
  3. Paste the Local RAG MCP server configuration.
  4. Save the server list.
  5. Refresh if you want to confirm the connector is still ready.
TypingMind MCP settings showing active server and Edit Servers button
{
  "mcpServers": {
    "local-rag": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-local-rag"
      ]
    }
  }
}
4

Use it across models

Save the server list, open Plugins, enable the Local RAG MCP tools, then select any supported AI model in TypingMind and use the tools in chat or assign them to an AI agent.

  1. Open the Plugins page in TypingMind.
  2. Enable the Local RAG MCP tools.
  3. Start a chat and choose the AI model you want to use.
  4. Use the MCP tools in chat or assign them to an AI agent.
  5. Switch to another AI model whenever needed without reconnecting MCP.
TypingMind chat using enabled MCP tools with a selected AI model
Can you use Local RAG to help me with this task?
Local RAG
Sure. I read it.
Here is what I found using Local RAG.

Frequently asked questions

What is the Local RAG MCP server used for?

Local RAG is an MCP server that lets compatible AI clients connect to external tools and context. In TypingMind, you can add this MCP server once and make its tools available in your AI workspace.

Can I use Local RAG MCP with multiple AI models in TypingMind?

Yes. TypingMind connects MCP tools at the workspace level, so you can use Local RAG with different AI models such as Claude, ChatGPT, Gemini, or other models you have configured in TypingMind without setting up the MCP server separately for each model.

Why use Local RAG MCP with TypingMind?

TypingMind is one of the best frontends for LLM chat because it brings multiple AI models, prompts, plugins, AI agents, API keys, and MCP tools into one workspace. With Local RAG connected, you can use its MCP tools across your preferred models while keeping your chat workflow organized in TypingMind.

How do I connect Local RAG MCP to TypingMind?

Local RAG runs through the TypingMind local MCP connector. This is best when the MCP server needs access to local files, desktop apps, command-line tools, or private resources on your computer.

What tools does Local RAG MCP provide in TypingMind?

Local RAG exposes 7 MCP tools that can be enabled from the TypingMind Plugins page and used in chat or assigned to AI agents.

Do I need to share my API keys with TypingMind to use Local RAG MCP?

No. TypingMind is local-first and lets you keep your model providers, API keys, prompts, and MCP configuration under your control. If Local RAG requires authentication, add the required headers, OAuth settings, or local configuration for that MCP server when you create the connection.

Related MCP Servers

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇