local-rag
local-rag-mcp
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 |
| Semantische Suche: bis zu k Chunks mit Quellpfad, Überschriftpfad, Kosinus-Score, Text |
| 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: supersededim Frontmatter wird durch einewhere-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_fileist 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 searchDas 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 -qKein 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
This server cannot be installed
Maintenance
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.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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