Skip to main content

Minimal local RAG MCP server for document folders

Project description

micro-rag-mcp: Minimal local RAG MCP server

Minimal, local Retrieval Augmented Generation indexing and search MCP server for folders of documents. Designed for multiple instances via uvx with different data folders. Stores a persistent FAISS index under each data folder in an index directory.

Goals

  • Minimal and elegant: a single stdio MCP server process with two tools: search and reindex
  • Local only: no network calls; works offline once models are downloaded
  • Fast startup: incremental indexing by file mtime with content checksum verification
  • Low footprint: sentence-transformers all-MiniLM-L6-v2, FAISS IndexFlatIP, numpy

Default behavior

  • Embeddings: sentence-transformers all-MiniLM-L6-v2
  • File types: .txt, .md, .pdf, .docx
  • Chunking: 1000 characters, 200 overlap, paragraph aware
  • Similarity: cosine via L2 normalized vectors and FAISS IndexFlatIP
  • Index location: <data_folder>/index
  • Startup: scan files and apply incremental changes to the index
  • Concurrency: simple file lock index.lock to serialize reindex operations
  • Logging: human logs to stderr; tool results are structured

Minimal architecture

Planned source files

Data flow

flowchart LR
  C[Client] --> S[Micro RAG MCP]
  S --> FS[Data folder]
  S --> E[Embedder]
  S --> I[Index manager]
  I --> FI[FAISS index]
  I --> MF[Manifest jsonl]

Startup sequence

sequenceDiagram
  participant C as Client
  participant S as MCP server
  participant I as Index manager
  C->>S: connect via stdio
  S->>I: open or create index
  I->>I: scan data folder and apply incremental changes
  I-->>S: ready with index
  S-->>C: tools ready

Storage layout under <data_folder>/index

  • faiss.index: serialized FAISS index
  • manifest.jsonl: one JSON record per chunk
  • files.json: per-file summary and last processed state
  • version: schema version string
  • index.lock: lock file during reindex

manifest.jsonl record

{
  "id": 12345,
  "path": "/abs/or/relative/path/to/file.md",
  "ext": ".md",
  "mtime": 1739650000.123,
  "checksum": "sha256:ab...cd",
  "chunk_index": 7,
  "char_start": 4200,
  "char_end": 5200,
  "text": "chunk text...",
  "embedding_dim": 384,
  "deleted": false
}

files.json record

{
  "path": "/abs/or/relative/path/to/file.md",
  "mtime": 1739650000.123,
  "checksum": "sha256:ab...cd",
  "chunk_ids": [1201, 1202, 1203],
  "ext": ".md"
}

Incremental reindex algorithm

  • Acquire index.lock; if exists, fail tool call with a clear error
  • Load files.json and manifest.jsonl into memory maps
  • Walk data folder for allowed extensions
  • For each file
    • If new file, ingest, chunk, embed, add vectors and manifest records
    • If mtime differs or checksum differs, delete old chunks, add new chunks
  • For files in files.json not present on disk, mark their chunks deleted and optionally reclaim ids later
  • Persist FAISS, manifest.jsonl append, files.json
  • Release lock and return counts

Search algorithm

  • Encode query to embedding
  • L2 normalize query and index vectors
  • Top k search via FAISS
  • For each hit, fetch manifest record, compute snippet, return result

MCP tools

Tool name: search

  • Params
    • query: string, required
    • top_k: integer, default 5, min 1, max 50
    • score_threshold: float, default 0.2, 0..1
  • Returns
    • results: array of
      • path: string
      • score: float
      • snippet: string
      • chunk_index: integer
      • char_start: integer
      • char_end: integer
      • mtime: float
      • ext: string
  • Errors
    • if index missing, server returns empty list and logs a warning

Tool name: reindex

  • Params
    • force: boolean, default false
    • path_glob: string, optional shell pattern relative to data folder
  • Returns
    • files_added: integer
    • files_updated: integer
    • files_removed: integer
    • chunks_total: integer
    • elapsed_ms: integer
  • Errors
    • if indexing already in progress, return a busy error

CLI usage via uvx

  • One off run
uvx micro-rag-mcp --data-folder /some/hr_docs
  • Override defaults
uvx micro-rag-mcp --data-folder /some/docs --index-folder /some/docs/index --exts .txt,.md,.pdf,.docx

Local testing before PyPI upload

Before uploading to PyPI, test your package locally to ensure it works correctly with uvx:

1. Development Installation

# Install in development mode for rapid iteration
uv pip install -e .
micro-rag-mcp --help

2. Local uvx Testing

# Test uvx with local package
uvx --from ./ micro-rag-mcp --help

# Create test data and test functionality
mkdir -p test_data
echo "This is a test document about Python programming." > test_data/doc1.txt
echo "Another document about machine learning and AI." > test_data/doc2.md

# Test with real data
uvx --from ./ micro-rag-mcp --data-folder test_data

3. Build and Install Locally

# Build the package
uv build

# Install the built wheel
uv pip install dist/micro_rag_mcp-0.1.0-py3-none-any.whl

# Test uvx with installed package
uvx micro-rag-mcp --help

4. Clean Environment Testing

# Test in isolated virtual environment
uv venv test_env
source test_env/bin/activate
uv pip install dist/micro_rag_mcp-0.1.0-py3-none-any.whl
micro-rag-mcp --help
deactivate

5. Package Validation

# Check package metadata
uv pip show micro-rag-mcp

# Verify entry points
uv pip show -f micro-rag-mcp | grep -A5 "Entry-points"

# Test import
python -c "import micro_rag_mcp; print('Import successful')"

MCP client configuration examples

Claude Desktop settings json

{
  "mcpServers": {
    "hr_rag": {
      "command": "uvx",
      "args": ["micro-rag-mcp", "--data-folder", "/some/hr_docs"]
    },
    "marketing_rag": {
      "command": "uvx",
      "args": ["micro-rag-mcp", "--data-folder", "/some/mktg_docs"]
    }
  }
}

Dependencies to declare in pyproject.toml

  • mcp
  • sentence-transformers
  • faiss-cpu
  • numpy
  • pypdf
  • python-docx
  • pydantic
  • charset-normalizer

Implementation notes

  • Use stdio transport from the Python mcp package
  • Always write human logs to stderr to avoid polluting tool responses
  • Normalize embeddings before adding to IndexFlatIP to approximate cosine
  • Batch embeddings to manage memory; suggested batch size 64
  • For pdf extraction, fall back to text if pages fail; skip images
  • For docx, join paragraphs with double newline
  • Use UTF-8 with errors replace for text files
  • Use SHA256 on normalized text for checksums

Security and privacy

  • Operates only on local folders passed explicitly
  • No network calls at runtime except model downloads on first use
  • No PII leaves the machine

Testing plan

  • Create a sample folder with mixed file types
  • Run uvx micro-rag-mcp --data-folder sample
  • Use search tool from client to validate results and scores
  • Modify a file and rerun reindex tool; ensure updates are reflected
  • Remove a file and rerun reindex; ensure tombstones are applied

Roadmap

  • Background compaction to rebuild faiss and drop tombstones
  • Optional rerankers for improved quality
  • Additional readers for html and csv
  • Hybrid search with BM25 for markdown headings

Repository layout targets

Approval

  • If this design matches expectations, the next steps are to update dependencies, scaffold files, and implement the two tools. See the todo list in this workspace.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

micro_rag_mcp-0.1.4.tar.gz (13.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

micro_rag_mcp-0.1.4-py3-none-any.whl (12.5 kB view details)

Uploaded Python 3

File details

Details for the file micro_rag_mcp-0.1.4.tar.gz.

File metadata

  • Download URL: micro_rag_mcp-0.1.4.tar.gz
  • Upload date:
  • Size: 13.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.11

File hashes

Hashes for micro_rag_mcp-0.1.4.tar.gz
Algorithm Hash digest
SHA256 cd2f019c080b64e034fe48d196b9803678012d68b1c279e4d9d9ab8c0234ccf3
MD5 d3400b2a037b462a3a80cf33dac7a8e7
BLAKE2b-256 e1b554c32554ae2f683bd2ee2518ba61606edc1596b3577436cbae9f019ba8e5

See more details on using hashes here.

File details

Details for the file micro_rag_mcp-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: micro_rag_mcp-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 12.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.11

File hashes

Hashes for micro_rag_mcp-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 17b374d7429f7a03f5ee22403de7561caa13b3092be0a01fceb309ab8697a075
MD5 9055401243d0614b0f2f3f035f6eebff
BLAKE2b-256 0af12b9c25475c0ac250198762481cf7617b8aba6e539ba9dea7ff94af5230ad

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page