Skip to main content
Glama

local-rag-mcp

ci

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

search_corpus(query, k=4)

Búsqueda semántica: hasta k fragmentos con ruta de origen, ruta de encabezado, puntuación de coseno, texto

get_file(path)

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: superseded en su frontmatter se excluye mediante una cláusula where antes 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_file está 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 search

El 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 -q

Sin 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

-
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