Skip to main content
Glama

local-rag-mcp

ci

Ein schreibgeschützter MCP-Server für semantische Suche über ein lokales Dokumentenkorpus – On-Device-Embeddings (Ollama), ein lokaler Chroma-Store, nichts verlässt den Host. Gebaut für Umgebungen, in denen der Korpusinhalt nicht an eine Cloud-API gehen darf, und identisch für jeden MCP-Client bereitgestellt (Claude Code, Codex, alles, was das Protokoll spricht).

Dies ist das MCP-bereitgestellte Geschwister von claude-code-session-memory: gleiches Embedding-Modell, gleiche Instruction-Prefix-Regelung, gleiche Messmethodik – ein Retrieval-Substrat, zwei Konsumenten. Die Session-Memory-README trägt die vollständige Eval-Geschichte (vorab festgelegte Schwellen, adversariale Abfragesätze, Regressionszuordnung); dieses Repo wendet dieselbe Disziplin auf einen Server statt auf einen Hook an.

Tools

Tool

Was es tut

search_corpus(query, k=4)

Semantische Suche: bis zu k Chunks mit Quellpfad, Überschriftpfad, Kosinus-Score, Text

get_file(path)

Text eines indizierten Dokuments (auf 50 k Zeichen begrenzt) – bewusst kein allgemeiner Dateisystem-Leser

Beide sind als schreibgeschützt annotiert. Fehler geben strukturierte {"error": ...}-Payloads zurück – eine ausgefallene Abhängigkeit degradiert das Tool, nie die Sitzung.

Schnellstart

git clone https://github.com/wesglockzin/local-rag-mcp
cd local-rag-mcp
python3 -m venv .venv && ./.venv/bin/pip install -r requirements.txt
ollama pull embeddinggemma

# Index the included sample corpus (or point RAG_CORPUS_DIR at your own)
./.venv/bin/python ingest.py

# Register with Claude Code — ABSOLUTE paths on both sides: the MCP client
# launches the server from its own working directory, so relative paths are
# the #1 install failure.
claude mcp add local-rag -- "$PWD/.venv/bin/python" "$PWD/server.py"

Dann frag Claude Code etwas, das das Korpus weiß – „Wer wird bei einem Sev-1 angepingt?" – und beobachte, wie es search_corpus aufruft.

Die Konfiguration besteht aus drei Umgebungsvariablen: RAG_CORPUS_DIR (Standard: ./sample-corpus), RAG_STORE_DIR (Standard: ~/.local-rag-mcp/store), OLLAMA_HOST.

Designentscheidungen, die sich bewähren

  • Der Server ist schreibgeschützt und erstellt nie Stores. Die Aufnahme (Ingestion) besitzt die Erstellung. Ein schreibgeschützter Server, der stillschweigend einen leeren Store initialisiert, verwandelt „Du hast vergessen zu ingestieren" in „Suche liefert nichts" – der schlechtere Fehler, weil er wie eine Antwort aussieht.

  • Embed-then-swap-Aufnahme. Die alten Chunks einer Datei werden erst gelöscht, nachdem jeder neue Chunk erfolgreich eingebettet wurde; ein Ollama-Fehler mitten in einer Datei lässt diese Datei nie aus dem Index verschwinden.

  • Zurückgezogene Dokumente werden vorab gefiltert, nicht nachträglich. Ein Dokument mit lifecycle: superseded im Frontmatter wird durch eine where-Klausel vor der Vektorsuche ausgeschlossen, sodass es nie einen Ergebnisplatz belegt. Die Aufnahme schreibt den Lifecycle-Schlüssel explizit auf jeden Chunk – bei einigen Versionen des Stores schlüpft ein fehlender Schlüssel durch $ne, daher ist Abwesenheit kein sicherer Standard. (Das Original dieser Regel existiert, weil eine erneute Aufnahme einmal stillschweigend den Marker löschte und ein zurückgezogenes Dokument wieder in den Ergebnissen auftauchte; ein Regressionstest fixiert das jetzt.)

  • get_file ist symlink-gehärtet. Nur indizierte Pfade sind lesbar, und ein Pfad, der an einen anderen Ort auflöst als zum Zeitpunkt der Aufnahme, wird abgelehnt – sonst kann jeder, der eine Korpusdatei gegen einen Symlink austauscht, außerhalb des Korpus durch den Server lesen. Wenn die Datei auf der Festplatte fehlt (verschobenes Korpus, andere Maschine), werden stattdessen die indizierten Chunk-Texte in Chunk-Reihenfolge geliefert.

  • Der Store ist immer maschinenlokal. Es ist eine Live-SQLite-Datenbank; Cloud-Synchronisierung macht Ganzdatei-Ersetzung ohne transaktionales Bewusstsein, und der Fehlermodus ist ein stillschweigend beschädigter Index auf der Maschine, die nicht geschrieben hat. Synchronisiere das Korpus und dieses Rezept; jede Maschine baut ihren eigenen Store.

  • Jede Aufnahme stempelt den Git-Commit des Korpus in ihre Ausgabe, sodass ein Index-Build exakt auf den Korpuszustand festgelegt werden kann, der ihn erzeugt hat („nicht committete Änderungen vorhanden" ist selbst ein Warnlabel).

  • Asymmetrische Embedding-Präfixe (EmbeddingGemmas dokumentierte Query/Doc- Instruction-Präfixe) auf beiden Seiten der Suche, passend zum gemessenen Regime des Begleitprojekts – präfixierte schlagen rohes Retrieval dort um zweistellige Prozentpunkte, und gemischte präfixierte/rohe Vektoren liegen in einem unkalibrierten Band.

Korpus-Konventionen

Jedes Verzeichnis mit *.md-Dateien funktioniert. Drei optionale Frontmatter-Schlüssel:

rag: false            # exclude this file from the index entirely
rag_chunk: headings   # heading-split a long document (default: whole-file)
lifecycle: superseded # keep the file, hide it from search

Das committete sample-corpus/ übt alle drei plus eine einfache Datei – sechs fiktive Plattform-Team-Dokumente, generiert von tools/gen_sample_corpus.py (CI verifiziert, dass das committete Korpus mit dem Generator übereinstimmt).

Tests

pip install pytest && python -m pytest -q

Kein Ollama, kein Store: Der Embedder ist gestubbt und die Sammlung ist ein Fake, das Aufrufe aufzeichnet. Getestet werden die Verträge – Argumentvalidierung, der Lifecycle-Vorfilter, der den Store als where-Klausel erreicht, die Schreibschutz-Garantie ohne Erstellung, Symlink-Ablehnung, die Embed-then-swap-Reihenfolge (einschließlich des Embedder-down-Pfads), der mtime-Toleranz-Übersprung und das Merge- und Übergrößen-Split-Verhalten des Chunkers.

Bekannte Einschränkungen

  • Vertrauensmodell: Der Server liest, was auch immer du als Korpus angibst, und Clients injizieren abgerufenen Text in den Modellkontext. Indiziere nur Inhalte, denen du vertraust – ein feindliches Dokument ist ein Prompt-Injection-Vektor; der Server ruft ab, er desinfiziert nicht. Stdio-MCP hat keine Authentifizierungsschicht; es erbt das Vertrauen des Prozesses, der es gestartet hat.

  • Scores sind nur innerhalb eines Embedding-Regimes vergleichbar; ein kalibrierter „schwache Übereinstimmung"-Boden ist korpusspezifisch (das Begleitrepo dokumentiert die Kalibrierungsmethode).

  • Ein Store, eine Sammlung – Multi-Korpus-Routing ist hier außerhalb des Rahmens.

  • Keine hybride Stichwort+Vektor-Stufe; Paraphrasen-Spielraum ist gemessen und im Begleitrepo dokumentiert.

Lizenz

MIT – siehe LICENSE.

Autor

Wes Glockzin

-
license - not tested
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Securely search and manage workspace context files for AI agents and teams.

  • Search and reason over your Obsidian-style Markdown vault, right from ChatGPT.

  • Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/wesglockzin/local-rag-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server