local-rag
local-rag-mcp
Un servidor MCP de solo lectura para búsqueda semántica sobre un corpus de documentos local: incrustaciones en el dispositivo (Ollama), un almacén Chroma local, nada sale del host. Diseñado para entornos donde el contenido del corpus no puede ir a una API en la nube, y servido de forma idéntica a cualquier cliente MCP (Claude Code, Codex, cualquier cosa que hable el protocolo).
Este es el hermano servido por MCP de claude-code-session-memory: mismo modelo de incrustación, mismo régimen de prefijos de instrucción, misma metodología de medición: un sustrato de recuperación, dos consumidores. El README de session-memory lleva la historia completa de evaluación (barras pre-committed, conjuntos de consultas adversarias, atribución de regresiones); este repositorio aplica la misma disciplina a un servidor en lugar de un hook.
Herramientas
Herramienta | Qué hace |
| Búsqueda semántica: hasta k fragmentos con ruta de origen, ruta de encabezado, puntuación de coseno, texto |
| Texto de un documento indexado (limitado a 50 k caracteres) — deliberadamente no un lector general de sistema de archivos |
Ambas están anotadas como de solo lectura. Los fallos devuelven cargas útiles estructuradas {"error": ...}
— una dependencia caída degrada la herramienta, nunca la sesión.
Inicio rápido
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"Luego pregúntale a Claude Code algo que el corpus sepa — "¿a quién se le pagina por un
sev-1?" — y observa cómo llama a search_corpus.
La configuración son tres variables de entorno: RAG_CORPUS_DIR (por defecto:
./sample-corpus), RAG_STORE_DIR (por defecto: ~/.local-rag-mcp/store),
OLLAMA_HOST.
Decisiones de diseño que valen la pena
El servidor es de solo lectura y nunca crea almacenes. La ingesta es dueña de la creación. Un servidor de solo lectura que inicializa silenciosamente un almacén vacío convierte "olvidaste ingerir" en "la búsqueda no devuelve nada" — el peor fallo, porque parece una respuesta.
Ingesta de incrustar-luego-intercambiar. Los fragmentos antiguos de un archivo se eliminan solo después de que cada fragmento nuevo se haya incrustado con éxito; un fallo de Ollama a mitad de archivo nunca deja ese archivo ausente del índice.
Los documentos retirados se pre-filtran, no se post-filtran. Un documento con
lifecycle: supersededen su frontmatter se excluye mediante una cláusulawhereantes de la búsqueda vectorial, por lo que nunca ocupa un lugar en los resultados. La ingesta escribe la clave de ciclo de vida explícitamente en cada fragmento — en algunas versiones de la tienda, una clave faltante se cuela a través de$ne, por lo que la ausencia no es un valor predeterminado seguro. (El original de esta regla existe porque una re-ingesta una vez borró silenciosamente el marcador y un documento retirado reapareció en los resultados; una prueba de regresión ahora lo fija.)get_fileestá endurecido contra enlaces simbólicos. Solo las rutas indexadas son legibles, y una ruta que se resuelve en un lugar diferente al que tenía en el momento de la ingesta se rechaza — de lo contrario, cualquiera que pueda intercambiar un archivo del corpus por un enlace simbólico lee fuera del corpus a través del servidor. Si el archivo no está presente en el disco (corpus movido, máquina diferente), se sirve el texto del fragmento indexado en su lugar, en orden de fragmento.El almacén es local a la máquina, siempre. Es una base de datos viva respaldada por SQLite; la sincronización en la nube hace reemplazo de archivo completo sin conciencia transaccional, y el modo de fallo es un índice silenciosamente corrupto en la máquina que no lo escribió. Sincroniza el corpus y esta receta; cada máquina construye su propio almacén.
Cada ingesta sella el commit git del corpus en su salida, para que una compilación de índice pueda fijarse exactamente al estado del corpus que la produjo ("cambios no confirmados presentes" es en sí mismo una etiqueta de advertencia).
Prefijos de incrustación asimétricos (los prefijos de instrucción de consulta/documento documentados de EmbeddingGemma) en ambos lados de la búsqueda, coincidiendo con el régimen medido del proyecto compañero — el prefijado superó a la recuperación cruda por doble dígito allí, y los vectores mixtos prefijados/crudos puntúan en una banda no calibrada.
Convenciones del corpus
Cualquier directorio de archivos *.md funciona. Tres claves opcionales de frontmatter:
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 searchEl sample-corpus/ confirmado ejercita las tres más un archivo plano — seis
documentos ficticios del equipo de plataforma, generados por tools/gen_sample_corpus.py
(CI verifica que el corpus confirmado coincida con el generador).
Pruebas
pip install pytest && python -m pytest -qSin Ollama, sin almacén: el incrustador está simulado y la colección es un falso
que registra llamadas. Bajo prueba están los contratos — validación de argumentos, el
pre-filtro de ciclo de vida que llega al almacén como una cláusula where, la garantía de solo lectura sin creación, el rechazo de enlaces simbólicos, el orden de incrustar-luego-intercambiar (incluyendo
la ruta de incrustador caído), la omisión por tolerancia de mtime, y el comportamiento del fragmentador
de fusión y división por tamaño excesivo.
Limitaciones conocidas
Modelo de confianza: el servidor lee cualquier corpus al que lo apuntes, y los clientes inyectan texto recuperado en el contexto del modelo. Indexa solo contenido en el que confíes — un documento hostil es un vector de inyección de prompt; el servidor recupera, no sanitiza. MCP stdio no tiene capa de autenticación; hereda la confianza del proceso que lo lanzó.
Las puntuaciones son comparables solo dentro de un régimen de incrustación; un piso calibrado de "coincidencia débil" es específico del corpus (el repositorio compañero documenta el método de calibración).
Un almacén, una colección — el enrutamiento multi-corpus está fuera de alcance aquí.
Sin etapa híbrida de palabras clave + vector; el margen de paráfrasis se mide y documenta en el repositorio compañero.
Licencia
MIT — ver 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