Universal RAG MCP Server
Ingests Google Drive files via drive:// for indexing, semantic retrieval, and cited answers.
Connects to a local Ollama OpenAI-compatible endpoint for LLM-based answer generation.
Uses OpenAI-compatible chat completion endpoints for answer generation over retrieved chunks, including verifiable citations.
Ingests YouTube videos by URL, transcribes their audio locally with ASR, and enables semantic search with minute-level citations.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
Universal RAG
🧩 Pipeline plugable de Retrieval-Augmented Generation — ingesta universal (texto, archivos, URLs, audio, video, YouTube, Drive, S3/MinIO, Notion), búsqueda vectorial o híbrida (BM25 + vectores) con reranking (cross-encoder o LLM), streaming SSE, caché semántica, workbench web, extracción de tablas, evaluación de calidad, colecciones múltiples, jobs asíncronos, auth por API key y respuestas con citas verificables, incluidas citas por minuto en audio/video.
Hermano de Universal MCP: misma filosofía "universal" — núcleo estable, capacidades que se agregan soltando carpetas, sin tocar el servidor.
✨ Características
Pieza | Qué hace |
🔌 Conectores plugables | Fase 1: |
✂️ Chunker configurable | División con conciencia de párrafos/frases/palabras y solapamiento; para audio/video, troceado temporal acotado por minuto. |
🧠 Embeddings locales |
|
🗄️ ChromaDB embebido | Persistente, sin servidor; intercambiable por otro store (incl. uno en memoria para tests). |
🔍 Búsqueda semántica | Recuperación con scores de similitud y filtros por metadatos ( |
⚡ Búsqueda híbrida (Fase 3) | BM25 (léxico, cero dependencias) + vectores con fusión RRF o ponderada — atrapa códigos, nombres propios y términos exactos que los embeddings diluyen. |
🎯 Reranking (Fase 3/5) | Reranker plugable: cross-encoder local ( |
📊 Evaluación (Fase 3) | Golden sets JSONL con precision/recall/MRR/hit-rate — mide la calidad antes de tocar producción. |
📋 Extracción de tablas (Fase 5) | Las tablas de DOCX, HTML y PDF (opcional |
🖥️ Streaming SSE (Fase 6) |
|
⚡ Caché semántica (Fase 6) | Preguntas repetidas o parafraseadas se sirven de caché por similitud coseno (LRU + TTL opcional), sin repetir recuperación ni LLM. Se invalida sola al cambiar el índice y responde |
🧰 Workbench web (Fase 6) | Consola completa en |
🏢 Conectores empresariales (Fase 7) | Confluence (espacios, páginas y búsquedas CQL; Basic/Bearer) y SharePoint (Microsoft Graph, client credentials, librerías de documentos con extracción PDF/DOCX/TXT/MD/CSV). |
💬 Memoria conversacional (Fase 7) | Preguntas de seguimiento con |
⏱️ Sincronización programada (Fase 7) | Registra fuentes con un intervalo ( |
🤖 Agente multi-hop (Fase 8) | Preguntas complejas en varios pasos: plan de sub-consultas (LLM o heurística determinista), búsquedas con refinamiento de consultas sin resultados, fusión de fragmentos (dedupe) y síntesis con citas sobre el ranking combinado. Pasos trazables en API, CLI ( |
🗨️ Mini chat UI (Fase 3) | Chat web minimalista (ahora en |
📚 Colecciones múltiples (Fase 4) | Bases de conocimiento aisladas ( |
🔄 Jobs asíncronos (Fase 4) |
|
🔐 Auth por API key (Fase 4) | Protege la API con |
📈 Métricas runtime (Fase 4) | Contadores de peticiones/consultas/ingestas/errores y uptime en |
🪶 Ingesta incremental (Fase 4) | Huella de contenido ( |
🐳 Docker incluido (Fase 4) |
|
💬 Generación plugable | Cualquier endpoint compatible OpenAI (OpenAI, z-ai, Ollama, LM Studio, vLLM…) o modo extractivo sin LLM. |
📎 Citas verificables | Cada respuesta referencia sus fuentes con |
🎙️ ASR local (Fase 2) | faster-whisper corre en tu máquina: MP3/WAV/M4A/MP4/MKV… → transcripción con citas |
🖥️ 3 interfaces | API REST (FastAPI) + CLI (Typer) + servidor MCP (para Claude Desktop / Universal MCP). |
Related MCP server: RAG MCP Server
🚀 Inicio rápido
pip install universal-rag # núcleo (embeddings deterministas)
pip install "universal-rag[local]" # + embeddings neuronales locales
pip install "universal-rag[media]" # + audio/video/youtube (faster-whisper, yt-dlp)
pip install "universal-rag[s3]" # + S3/MinIO (boto3)
pip install "universal-rag[tables]" # + tablas en PDF (pdfplumber)
pip install "universal-rag[local,media,s3,tables]" # todoCLI
# Ingesta (el conector se resuelve automáticamente por esquema/extensión/dominio)
universal-rag ingest ./docs/manual.pdf
universal-rag ingest "https://es.wikipedia.org/wiki/Energía_solar"
universal-rag ingest "./informes/*.md" # globs = ingesta masiva
universal-rag ingest ./podcast.mp3 # → transcripción local + minutos
universal-rag ingest ./clase.mp4 # → pista de audio → ASR + minutos
universal-rag ingest "https://youtu.be/abc123" # → YouTube → ASR + minutos
universal-rag ingest "drive://<fileId>" # → Google Drive (público/compartido)
# Fase 5: S3/MinIO y Notion
universal-rag ingest "s3://mi-bucket/informes/" # → prefijo: ingesta todos los soportados
universal-rag ingest "s3://mi-bucket/informe.pdf" # → objeto concreto (MinIO: endpoint_url=…)
universal-rag ingest "notion://<page-id>" # → página de Notion (requiere RAG_NOTION_TOKEN)
universal-rag ingest "notion://database/<db-id>" # → cada fila = un documento
universal-rag ingest "notion://search/manual faq" # → primer resultado de la búsqueda
# Fase 7: Confluence y SharePoint (empresariales)
universal-rag ingest "confluence://space/DEV" # → todas las páginas del espacio
universal-rag ingest "confluence://page/12345" # → una página concreta
universal-rag ingest "confluence://cql/text ~ \"seguridad\"" # → búsqueda CQL
universal-rag ingest "https://acme.atlassian.net/wiki/spaces/DEV" # → URL directa
universal-rag ingest "sharepoint://contoso.sharepoint.com/sites/Marketing"
universal-rag ingest "https://contoso.sharepoint.com/sites/Marketing" -o folder=/General/2024
# Consulta con citas (en media, con minuto exacto)
universal-rag query "¿cada cuánto se limpian los paneles?"
# Fase 7: memoria conversacional multi-turno
universal-rag query "¿qué es RAG?" --conversation demo
universal-rag query "¿y cómo se compara con LangChain?" --conversation demo # recuerda el turno anterior
universal-rag conversations # lista conversaciones vivas
universal-rag conversations --show demo # historial de una conversación
universal-rag conversations --clear all # borra todas
# Fase 8: agente multi-hop (plan + pasos trazables)
universal-rag ask "¿Qué mantenimiento necesita un panel solar y cuánto dura el inversor?"
universal-rag ask "…" --max-steps 3 --planning heuristic --quiet
# Chat interactivo multi-turno (memoria activada por defecto)
universal-rag chat
universal-rag chat --conversation demo # reanuda la conversación 'demo'
# Fase 7: sincronización programada
universal-rag sync add "https://ejemplo.com/docs" --interval 600
universal-rag sync list # estado de las fuentes
universal-rag sync run <job-id> # ejecución inmediata
universal-rag sync remove <job-id>
# Colecciones (Fase 4): bases de conocimiento aisladas
universal-rag ingest ./contratos/2025.pdf --collection legal
universal-rag query "¿cláusula de penalización?" --collection legal
universal-rag collections # lista colecciones activas
# Chat interactivo en la terminal
universal-rag chat
# Evaluación de calidad con un golden set (precision/recall/MRR)
universal-rag eval examples/golden.jsonl --k 5
universal-rag eval examples/golden.jsonl --json # reporte completo en JSON
# Administración
universal-rag documents # lista lo ingestado
universal-rag stats # documentos, fragmentos, conectores, modo de búsquedaAPI REST
universal-rag serve --port 8100
# → http://localhost:8100/ workbench web (Fase 6: chat streaming + gestión)
# → http://localhost:8100/chat mini chat clásico
# → http://localhost:8100/docs Swagger UIcurl -X POST localhost:8100/ingest -H 'Content-Type: application/json' \
-d '{"source": "https://ejemplo.com/articulo"}'
curl -X POST localhost:8100/ingest -H 'Content-Type: application/json' \
-d '{"source": "./entrevista.mp3", "options": {"language": "es", "asr_model": "small"}}'
curl -X POST localhost:8100/query -H 'Content-Type: application/json' \
-d '{"question": "¿qué dijo sobre costos?", "k": 4}'
# Fase 4 — colecciones y jobs asíncronos
curl -X POST localhost:8100/ingest/text -H 'Content-Type: application/json' \
-d '{"text": "…", "title": "Nota", "collection": "legal"}'
curl -X POST localhost:8100/ingest/async -H 'Content-Type: application/json' \
-d '{"source": "./podcast-largo.mp3"}' # → {"job_id": …}
curl localhost:8100/jobs/<job_id> # → estado del job
# Fase 4 — con autenticación (si RAG_API_KEY está definida)
curl localhost:8100/stats -H 'X-API-Key: <tu-key>'
# Fase 6 — streaming SSE (eventos: meta → token* → done)
curl -N -X POST localhost:8100/query/stream -H 'Content-Type: application/json' \
-d '{"question": "¿qué dijo sobre costos?"}'
# Fase 7 — memoria conversacional multi-turno (mismo conversation_id = contexto compartido)
curl -X POST localhost:8100/query -H 'Content-Type: application/json' \
-d '{"question": "¿qué es RAG?", "conversation_id": "sesion-web-1"}'
curl -X POST localhost:8100/query -H 'Content-Type: application/json' \
-d '{"question": "¿y sus desventajas?", "conversation_id": "sesion-web-1"}'
curl localhost:8100/conversations # conversaciones vivas
curl localhost:8100/conversations/sesion-web-1 # historial (user/assistant)
curl -X DELETE localhost:8100/conversations/sesion-web-1
# Fase 7 — sincronización programada
curl -X POST localhost:8100/sync -H 'Content-Type: application/json' \
-d '{"source": "https://ejemplo.com/docs", "interval": 600}'
curl localhost:8100/sync # jobs + último estado
curl -X POST localhost:8100/sync/<job_id>/run # ejecución inmediata
curl -X DELETE localhost:8100/sync/<job_id>
# Fase 8 — agente multi-hop (plan → búsquedas → síntesis con pasos trazables)
curl -X POST localhost:8100/query/agent -H 'Content-Type: application/json' \
-d '{"question": "¿Qué mantenimiento necesita un panel solar y cuánto dura el inversor?"}'
# Fase 8 — streaming del agente (SSE: plan → step* → synthesize → token* → done)
curl -N -X POST localhost:8100/query/agent/stream -H 'Content-Type: application/json' \
-d '{"question": "…", "max_steps": 3, "planning": "heuristic"}'Endpoints: / (workbench) · /chat · /health · /stats · /ingest · /ingest/text · /ingest/async · /jobs · /jobs/{id} · /query · /query/stream (SSE) · /query/agent · /query/agent/stream (SSE, Fase 8) · /conversations · /sync · /documents · /collections.
Como servidor MCP (Claude Desktop, Universal MCP…)
universal-rag mcp # stdio
universal-rag mcp --transport streamable-http --port 8200Herramientas MCP: rag_ingest, rag_ingest_text, rag_query, rag_stats, rag_list_documents, rag_delete_document, rag_list_collections — todas aceptan collection (Fase 4).
Docker (Fase 4)
docker compose up -d --build
curl http://localhost:8100/healthDetalles de despliegue (auth, volúmenes, extras [local]/[media]) en docs/DEPLOYMENT.md.
🧪 Python
from universal_rag import CollectionManager, RAGPipeline
rag = RAGPipeline()
rag.ingest("./docs/contrato.pdf")
rag.ingest("./entrevista.mp3", language="es", asr_model="small")
answer = rag.query("¿cuál es la cláusula de penalización?")
print(answer.answer)
for citation in answer.citations:
minute = f" {citation.timestamp}" if citation.timestamp else ""
print(f" [{citation.source}{minute}] {citation.title} → {citation.quote[:80]}")
# [audio 03:12–04:05] Entrevista → ...sobre la cláusula de penalización...
# Fase 6: streaming token a token + caché semántica
for event in rag.stream_query("¿cuál es la cláusula de penalización?"):
if event["type"] == "token":
print(event["value"], end="", flush=True)
elif event["type"] == "done":
print("\ncitas:", len(event["answer"]["citations"]))
rag.query("¿cuál es la cláusula de penalización?").cached # → True (⚡ caché)
# Fase 4: colecciones aisladas que comparten embedder/generator
manager = CollectionManager()
manager.get("legal").ingest("./docs/contrato.pdf")
manager.get("faq").ingest_text("¿Horario? De 9 a 17.", title="FAQ")
manager.get("faq").query("¿cuál es el horario?")
print(manager.list_collections()) # resumen por colección
# Fase 7: memoria conversacional multi-turno
rag.query("¿qué es RAG?", conversation_id="demo")
answer = rag.query("¿y cómo se compara con LangChain?", conversation_id="demo") # recuerda el turno previo
print(rag.memory.conversations()) # [{"id": "demo", "turns": 2, …}]
print(rag.memory.history("demo")) # mensajes user/assistant para inspección
# Fase 7: sincronización programada
from universal_rag.core.sync import SyncScheduler
scheduler = SyncScheduler(rag, tick=5.0, state_path="data/sync_state.json")
scheduler.register("https://ejemplo.com/docs", interval=600)
scheduler.start() # hilo de fondo; con la API: RAG_SYNC_ENABLED=1⚙️ Configuración (variables RAG_*)
Variable | Default | Descripción |
|
|
|
|
| Modelo local multilingüe |
|
|
|
|
| Persistencia del índice |
|
| Troceado |
| (vacío → modo extractivo) | Endpoint compatible OpenAI |
| — / | Credenciales y modelo |
|
| Fragmentos recuperados |
|
|
|
|
|
|
|
| Peso vectorial en |
|
| Candidatos antes de rerank/top-k |
|
|
|
|
| Cross-encoder multilingüe |
| (usa | Modelo del LLM cuando |
| — | Token de integración de Notion (o |
| — | MinIO/R2/Spaces y región (o |
|
| Whisper: |
| (auto) |
|
| — | Directorios con conectores externos |
|
| Colección activa si no se indica otra (Fase 4) |
| (vacío = sin auth) | Si se define, la API exige |
|
| Hilos del pool de ingesta asíncrona (Fase 4) |
|
| Jobs recordados en memoria (Fase 4) |
|
| Caché semántica de consultas por colección (Fase 6) |
|
| Similitud coseno mínima para servir de caché (Fase 6) |
|
| Entradas máximas (LRU) de la caché (Fase 6) |
| (vacío = sin TTL) | Segundos de vida de cada entrada de caché (Fase 6) |
|
| Turnos recordados por conversación (Fase 7) |
|
| LRU de conversaciones vivas (Fase 7) |
|
| Arranca el planificador de sincronización con la API (Fase 7) |
|
| Granularidad del bucle del planificador, en segundos (Fase 7) |
| (vacío = en memoria) | JSON para persistir los jobs (CLI usa |
| — | Base URL de Confluence ( |
| — | Email para Basic auth en Cloud; vacío = Bearer/PAT para Server (Fase 7) |
| — | Token de API (Cloud) o PAT (Server/DC) (Fase 7) |
| — | Id o dominio del tenant Entra ID ( |
| — | Id de cliente de la app (permiso de aplicación |
| — | Secreto de la app (Fase 7) |
Ejemplo con Ollama local:
export RAG_LLM_BASE_URL=http://localhost:11434/v1
export RAG_LLM_MODEL=llama3.1🏗️ Arquitectura
fuente ──▶ ConnectorRegistry (auto-descubrimiento + prioridad) ──▶ Document
│ text/file/url (F1) │ audio/video/youtube/drive (F2: ASR local)
│ │ s3/notion (F5) │ segments (start, end, text)
│ │ confluence/sharepoint (F7: APIs oficiales)
│ └ tablas DOCX/HTML/PDF → Markdown (F5)
▼
Chunker ──▶ Chunks ──▶ Embedder ──▶ VectorStore (Chroma)
(texto: párrafos) (media: por minuto [mm:ss])
│
pregunta ──▶ Caché semántica (F6, coseno ≥ threshold) ──▶ hit: tokens desde caché
│ miss (F7: se omite si la consulta es conversacional)
▼
Retriever ◀────────────────────────────────────┘
│ │ vectorial (coseno)
│ └ híbrido: + BM25 (F3) ── fusión RRF/weighted
│ RetrievedChunks ──▶ Reranker (F3: cross-encoder · F5: LLM, opcionales)
▼
Generator (OpenAI-compat / echo) ──▶ Answer + Citations [1][2]… [00:00–01:05]
│ ▲ historial user/assistant por conversation_id (F7, LRU)
│ query(): Answer completo
└ stream_query(): meta → token* → done (SSE, F6)
SyncScheduler (F7): re-ingesta periódica de fuentes registradas → pipeline.ingest()
(hilo de fondo con RAG_SYNC_ENABLED=1; estado JSON opcional)Detalles en docs/ARCHITECTURE.md · Búsqueda híbrida y evaluación en docs/RETRIEVAL.md · Cómo agregar conectores en docs/ADDING_CONNECTORS.md.
🗺️ Hoja de ruta
Fase 1 (✅ v0.1.0) — núcleo + conectores
text/file/url+ ChromaDB + embeddings locales + API/CLI/MCP.Fase 2 (✅ v0.2.0) — conectores
audio(MP3),video(MP4),youtubeydrivecon ASR faster-whisper local y citas por minuto.Fase 3 (✅ v0.3.0) — búsqueda híbrida (BM25 + vectores, fusión RRF/weighted), reranking (cross-encoder local), evaluación (precision/recall/MRR con golden sets) y mini chat UI.
Fase 4 (✅ v0.4.0) — producción y escalado: colecciones múltiples, jobs asíncronos con polling, auth por API key, métricas runtime, ingesta incremental (skip sin cambios) y despliegue Docker.
Fase 5 (✅ v0.5.0) — ecosistema de fuentes y calidad: conector S3/MinIO (objetos y prefijos), conector Notion (páginas, bases de datos y búsqueda vía API oficial), reranking con LLM (
RAG_RERANKER=llm, degradación elegante) y extracción de tablas a Markdown en DOCX/HTML/PDF.Fase 6 (✅ v0.6.0) — experiencia en tiempo real: streaming SSE (
/query/stream+--streamen CLI, con o sin LLM), caché semántica (coseno + LRU + TTL, invalidación automática) y workbench web completo (chat streaming, gestión de documentos, ingesta desde el navegador y panel de estado).Fase 7 (✅ v0.7.0) — empresarial y conversacional: conectores Confluence (espacios/páginas/CQL, Basic/Bearer) y SharePoint (Microsoft Graph client credentials), memoria conversacional multi-turno (
conversation_iden API/CLI/Python, LRU, caché consciente) y sincronización programada (/sync+syncen CLI, planificador de fondo con estado persistente).Fase 8 (futuro) — GraphRAG ligero (entidades y relaciones), ingestores de imágenes (OCR) y SDK de cliente Python (reintentos + streaming).
💡 Calidad del ASR: el modelo
basees rápido y ligero; para español u otros idiomas no ingleses recomendamosRAG_ASR_MODEL=small(omedium) — la precisión mejora notablemente. Audio con música de fondo o voces sintéticas degrada la precisión de cualquier Whisper.
🧰 Desarrollo
git clone https://github.com/rtostudioco/universal-rag && cd universal-rag
pip install -e ".[dev]"
pytest # 306 tests (sin red, sin modelos pesados)
ruff check .📄 Licencia
MIT — Universal RAG Contributors.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
This server cannot be deployed
Maintenance
Related MCP Connectors
Ingest, manage, and retrieve documents for RAG-powered AI applications
OCR, transcription, file extraction, and image generation for AI agents via MCP.
Self-hosted AI workspace: semantic RAG document search, long-term memory, and AI chat via MCP.
Your personal library, readable by AI agents: durable snapshots, hybrid search, 46 MCP tools.
Related MCP Servers
- AlicenseAqualityDmaintenanceProvides local Retrieval-Augmented Generation (RAG) capabilities using Ollama for embeddings and ChromaDB for vector storage. It enables users to ingest and perform semantic searches across PDF, Markdown, and TXT documents within MCP-compatible clients.429 npmMIT
- FlicenseNot gradedqualityDmaintenanceProvides tools for ingesting documents into a local vector database and retrieving relevant information via semantic search, enabling retrieval-augmented generation for MCP clients.6-
- FlicenseCqualityDmaintenanceProvides RAG tools with local vector retrieval and web fallback using Firecrawl, enabling document ingestion and querying through MCP stdio transport.3-
- AlicenseNot gradedqualityCmaintenanceA local-first RAG engine that ingests documents (PDF, Markdown, images, etc.) and provides hybrid search, reranking, and LLM answer synthesis via MCP for AI agent integration.46 PyPI3MIT