self_rag_mcp
Motor de Recuperación Self-RAG
Sistema de Generación Aumentada por Recuperación Auto-Reflexiva construido con LangGraph, Qdrant y expuesto como un servidor MCP (Model Context Protocol) sobre transporte SSE.
A diferencia de los pipelines RAG estándar que recuperan y generan a ciegas, Self-RAG hace que el LLM sea un participante activo en su propio control de calidad: decide si recuperar, califica lo recuperado, verifica lo generado y reintenta cuando la respuesta no es lo suficientemente buena.
Tabla de Contenidos
Related MCP server: mcp-rag-agent
¿Qué es Self-RAG?
El RAG estándar tiene un problema fundamental: siempre recupera (incluso cuando no es necesario), nunca verifica si los documentos recuperados son relevantes y nunca comprueba si la respuesta generada está realmente fundamentada en esos documentos.
Self-RAG (introducido en el artículo Self-RAG: Learning to Retrieve, Generate, and Critique Through Self-Reflection) resuelve esto insertando pasos de reflexión en cada etapa:
Etapa | RAG Estándar | Self-RAG |
Decisión de recuperación | Siempre recupera | El LLM decide si la recuperación es necesaria |
Filtrado de documentos | Usa todos los documentos recuperados | El LLM califica cada documento por relevancia |
Generación | Genera una vez | Genera, luego verifica la fundamentación |
Calidad de la respuesta | Sin verificación | El LLM califica la utilidad, reintenta si es necesario |
Esta implementación utiliza LangGraph para modelar el flujo Self-RAG como un grafo dirigido con estado y aristas condicionales, permitiendo enrutamiento dinámico, bucles de reintento y trazabilidad completa del estado.
Resumen de Arquitectura
┌─────────────────────────────────────────────────────────────────┐
│ MCP Client (SSE) │
│ rich interactive terminal │
└──────────────────────────┬──────────────────────────────────────┘
│ SSE http://127.0.0.1:8000/sse
┌──────────────────────────▼──────────────────────────────────────┐
│ MCP Server (SSE) │
│ MCPServer · 3 tools exposed │
│ rag_answer · retrieve · server_health │
└──────────┬──────────────────────────────┬───────────────────────┘
│ │
┌──────────▼──────────┐ ┌───────────▼──────────────────────┐
│ Self-RAG Graph │ │ Hybrid Retriever │
│ (LangGraph) │ │ │
│ │ │ 1. Qdrant Hybrid Search │
│ retrieval_decision │ │ Dense (OpenAI embeddings) │
│ retrieve │ │ Sparse (BM25 / FastEmbed) │
│ relevance_grader │ │ Fusion: RRF │
│ context_builder │ │ │
│ generator │ │ 2. MMR Diversity Reranking │
│ support_grader │ │ │
│ usefulness_grader │ │ 3. FlashRank Cross-Encoder │
│ │ │ (ms-marco-MiniLM-L-12-v2) │
└──────────┬──────────┘ │ │
│ │ 4. Parent Document Expansion │
│ └───────────────┬──────────────────┘
│ │
┌──────────▼──────────────────▼──────────────────────────────────┐
│ Qdrant │
│ │
│ self_rag_documents (child chunks · dense + sparse) │
│ self_rag_parents (parent chunks · dense only) │
└─────────────────────────────────────────────────────────────────┘Flujo del Grafo Self-RAG
flowchart TD
START([START]) --> RD[retrieval_decision]
RD -->|should_retrieve = true| RET[retrieve]
RD -->|should_retrieve = false| GEN[generator]
RET --> REL[relevance_grader]
REL --> CTX[context_builder]
CTX --> GEN
GEN --> SUP[support_grader]
SUP -->|fully_supported\npartially_supported| USE[usefulness_grader]
SUP -->|not_supported\n& retry_count < max_retries| INC1[increment_retry]
SUP -->|not_supported\n& retry_count >= max_retries| USE
INC1 --> GEN
USE -->|useful| END([END])
USE -->|not_useful\n& retry_count >= max_retries| END
USE -->|not_useful\n& retry_count < max_retries| INC2[increment_retry_for_retrieval]
INC2 --> RET
style START fill:#2d6a4f,color:#fff
style END fill:#2d6a4f,color:#fff
style RD fill:#1d3557,color:#fff
style RET fill:#457b9d,color:#fff
style REL fill:#457b9d,color:#fff
style CTX fill:#457b9d,color:#fff
style GEN fill:#e63946,color:#fff
style SUP fill:#f4a261,color:#000
style USE fill:#f4a261,color:#000
style INC1 fill:#6d6875,color:#fff
style INC2 fill:#6d6875,color:#fffReferencia de Nodos
retrieval_decision
El punto de entrada del grafo. El LLM analiza la pregunta del usuario y decide si la recuperación de conocimiento externo es realmente necesaria.
Consultas conversacionales (
"Hola","¿Cuánto es 2+2?") → omitir recuperación, ir directamente ageneratorConsultas factuales / de dominio → proceder a
retrieve
Utiliza salida estructurada: RetrievalDecision { thought: str, answer: "YES" | "NO" }
retrieve
Ejecuta el Pipeline de Recuperación Híbrida completo contra Qdrant:
Búsqueda Híbrida — combina vectores densos (OpenAI
text-embedding-3-small) y dispersos (BM25 vía FastEmbed), fusionados en el servidor con Fusión de Rango Recíproco (RRF)MMR — Reordenamiento de Relevancia Marginal Máxima para diversidad (evita devolver fragmentos casi duplicados)
FlashRank — reordenador de codificador cruzado ONNX ligero (
ms-marco-MiniLM-L-12-v2) para la puntuación final de relevanciaExpansión Parental — los fragmentos hijos se recuperan para precisión, pero el fragmento padre completo se devuelve al LLM para un contexto más rico
relevance_grader
Filtra los documentos recuperados. Cada documento es calificado individualmente por el LLM contra la pregunta.
Documentos calificados como
YES→ se mantienen comorelevant_documentsDocumentos calificados como
NO→ se descartan
Utiliza salida estructurada: RelevanceGrade { thought: str, answer: "YES" | "NO" }
context_builder
Formatea los documentos relevantes en un bloque de contexto XML estructurado optimizado para la atención del LLM:
<context>
<document index="1">
<metadata>Source: hr.pdf | Relevance Score: 0.9821</metadata>
<content>
Human Resource Management (HRM) refers to...
</content>
</document>
</context>generator
El LLM genera una respuesta utilizando solo los hechos del bloque de contexto. El prompt instruye explícitamente al modelo a no usar conocimiento externo y a citar los índices de los documentos ([Doc 1]).
support_grader
Verifica que la respuesta generada esté fundamentada en el contexto. Realiza una auditoría afirmación por afirmación.
Devuelve uno de:
fully_supported— cada afirmación está respaldada por el contextopartially_supported— algunas afirmaciones están fundamentadas, otras nonot_supported— la respuesta contiene alucinaciones o contradice el contexto
Utiliza salida estructurada: SupportGrade { thought: str, label: "fully_supported" | "partially_supported" | "not_supported" }
usefulness_grader
Evalúa si la respuesta realmente resuelve la pregunta del usuario — incluso si está fundamentada, podría ser evasiva o incompleta.
Devuelve uno de:
useful— la respuesta satisface directamente la consultanot_useful— la respuesta está fuera de tema, es incompleta o evasiva
Utiliza salida estructurada: UsefulnessGrade { thought: str, label: "useful" | "not_useful" }
increment_retry / increment_retry_for_retrieval
Nodos de contabilidad que incrementan retry_count en el estado del grafo antes de volver a generator o retrieve respectivamente.
Lógica de Enrutamiento
Router | Condición | Siguiente Nodo |
|
|
|
|
| |
|
|
|
|
| |
|
| |
|
|
|
|
| |
|
|
Pipeline de Recuperación
Query
│
▼
Qdrant Hybrid Search (Dense + BM25 + RRF) k=20 candidates
│
▼
MMR Diversity Reranking k=15 diverse docs
│
▼
FlashRank Cross-Encoder top_k=4 final docs
│
▼
Parent Document Expansion fetch full parent chunks
│
▼
List[Document] → relevance_grader¿Por qué este embudo de múltiples etapas?
La búsqueda híbrida (densa + dispersa) ofrece mejor recall que cualquiera de las dos por separado — la densa captura coincidencias semánticas, BM25 captura coincidencias exactas de palabras clave
MMR evita que el LLM vea 4 fragmentos casi idénticos — fuerza la diversidad
FlashRank (ONNX int8 cuantizado) ofrece calidad de codificador cruzado en ~0.1s frente a ~19s de un CrossEncoder PyTorch completo
La expansión parental significa que la precisión de la recuperación proviene de fragmentos hijos pequeños, pero el LLM recibe el contexto completo circundante
Pipeline de Ingestión
Los documentos se dividen en una jerarquía de fragmentos padre-hijo:
PDF Document
│
├── Parent Chunk 1 (1200 chars, overlap=0) → stored in self_rag_parents
│ ├── Child Chunk 1a (600 chars, overlap=150) → stored in self_rag_documents
│ ├── Child Chunk 1b
│ └── Child Chunk 1c
│
├── Parent Chunk 2
│ ├── Child Chunk 2a
│ └── Child Chunk 2b
...Fragmentos hijos se indexan con vectores densos y dispersos para precisión en la búsqueda híbrida
Fragmentos padres se almacenan solo con vectores densos, utilizados para la expansión de contexto después de la recuperación
Los UUID son deterministas (UUID5) para que la re-ingestión sea idempotente
Servidor y Cliente MCP
El sistema se expone como un servidor MCP sobre transporte SSE, lo que lo hace compatible con cualquier cliente MCP (Claude Desktop, clientes personalizados, etc.).
Herramientas
Herramienta | Descripción |
| Ejecuta el grafo Self-RAG completo — decisión de recuperación → recuperar → calificar → generar → verificar → reintentar |
| Recuperación híbrida cruda solamente, sin generación ni calificación |
| Devuelve el estado operativo de los componentes de recuperación y reordenamiento |
Cliente Interactivo
Se incluye un cliente de terminal enriquecido con una interfaz basada en menús:
╭─────────────────────────────────╮
│ Self-RAG MCP Interactive Client │
│ Connected via SSE Transport │
╰─────────────────────────────────╯
[1] 💬 Ask Question (rag_answer)
[2] 🔍 Raw Search (retrieve)
[3] 🏥 System Health (server_health)
[4] 📋 List Tools
[0] 🚪 ExitEstructura del Proyecto
self_rag_retrieval/
├── src/self_rag/
│ ├── clients/
│ │ ├── llm.py # LiteLLM chat model + OpenAI embeddings (cached)
│ │ └── qdrant.py # Qdrant client singleton
│ ├── core/
│ │ └── config.py # Pydantic settings from .env
│ ├── graph/
│ │ ├── engine.py # Compiled graph singleton (lru_cache)
│ │ ├── routes.py # Conditional edge routing functions
│ │ └── workflow.py # LangGraph StateGraph definition
│ ├── ingestion/
│ │ ├── chunker.py # Parent-child chunk splitting
│ │ ├── indexer.py # Qdrant collection management
│ │ ├── loaders.py # PDF loader
│ │ └── pipeline.py # Ingestion orchestration
│ ├── mcp/
│ │ ├── server.py # MCPServer with 3 tools + startup warmup
│ │ ├── mcp_client.py # Rich interactive terminal client
│ │ └── tools.py # Tool implementations (answer, retrieve, health)
│ ├── models/
│ │ ├── graph_state.py # LangGraph TypedDict state
│ │ └── schemas.py # Pydantic structured output schemas
│ ├── nodes/
│ │ ├── context_builder.py # XML context formatter
│ │ ├── generator.py # LLM answer generation
│ │ ├── relevance_grader.py # Per-document relevance grading
│ │ ├── retrieval_decision.py # Retrieval necessity classifier
│ │ ├── retrieve.py # Retrieval node
│ │ ├── support_grader.py # Hallucination / grounding checker
│ │ └── usefulness_grader.py # Answer quality checker
│ ├── prompts/
│ │ ├── generation.py
│ │ ├── relevance.py
│ │ ├── retrieval.py
│ │ ├── support.py
│ │ └── usefulness.py
│ ├── retrieval/
│ │ ├── mmr.py # Maximal Marginal Relevance
│ │ ├── reranker.py # FlashRank ONNX cross-encoder
│ │ ├── retriever.py # HybridRetriever orchestrator (cached)
│ │ └── vector_store.py # Qdrant vector store (dense + sparse, cached)
│ └── services/
│ └── rag_service.py # Business layer wrapping the graph
├── scripts/
│ └── ingest.py # CLI ingestion script
├── tests/
│ ├── test_mcp_server.py
│ ├── test_mcp_tools.py
│ └── test_routes.py
├── docker-compose.yaml
├── pyproject.toml
└── .envConfiguración e Instalación
Requisitos previos
Python 3.12+
Gestor de paquetes uv
Docker (para Qdrant)
Clave API de OpenRouter
1. Clonar e instalar dependencias
git clone <repo-url>
cd self_rag_retrieval
uv sync2. Configurar el entorno
cp .env.example .envEditar .env:
OPENROUTER_API_KEY=sk-or-v1-...
CHAT_MODEL=openrouter/openai/gpt-4.1-mini
EMBEDDING_MODEL=openai/text-embedding-3-small
QDRANT_URL=http://localhost:6333
QDRANT_COLLECTION=self_rag_documents
QDRANT_PARENT_COLLECTION=self_rag_parents
DATA_DIR=src/self_rag/data3. Iniciar Qdrant
docker compose up -d4. Añadir tus documentos
Coloca archivos PDF en src/self_rag/data/.
5. Ingerir documentos
# First time
uv run python scripts/ingest.py
# Full rebuild (wipes existing collections)
uv run python scripts/ingest.py --resetConfiguración
Todos los ajustes están en .env y son validados por Pydantic. Parámetros clave:
Variable | Default | Descripción |
|
| LLM para todos los nodos de calificación y generación |
|
| Modelo de embeddings densos |
|
| Tamaño de fragmento hijo (caracteres) |
|
| Solapamiento de fragmentos hijos |
|
| Tamaño de fragmento padre (caracteres) |
|
| Pool de candidatos de búsqueda híbrida |
|
| Documentos después del filtro de diversidad MMR |
|
| Documentos finales después de FlashRank |
|
| Máximo de bucles de reintento Self-RAG |
|
| Temperatura del LLM (0 = determinista) |
Ejecución del Sistema
Terminal 1 — Iniciar el servidor MCP
uv run python src/self_rag/mcp/server.pyEl servidor calienta todos los modelos antes de aceptar conexiones:
INFO Warming up retriever...
INFO Warming up reranker...
INFO Warming up graph...
INFO Warmup complete — server ready.
INFO Uvicorn running on http://127.0.0.1:8000Terminal 2 — Iniciar el cliente interactivo
uv run python src/self_rag/mcp/mcp_client.pyPreguntas de ejemplo (dominio de RRHH)
What is Human Resource Management and what are its main objectives?
What are the nine broad areas of HRM activities identified by ASTD?
What is the difference between training and organizational development?
How does compensation and benefits management work in HRM?
What is the role of HRM in the new millennium?
What is the significance of HR planning in an organization?
Explain the scope of HRM and what it covers in an employee's working life.Ejecución de Pruebas
uv run pytest tests/ -vtests/test_routes.py::test_retrieval_decision_retrieve PASSED
tests/test_routes.py::test_retrieval_decision_skip PASSED
tests/test_routes.py::test_support_fully_supported_... PASSED
tests/test_routes.py::test_support_not_supported_retries... PASSED
tests/test_routes.py::test_usefulness_useful_ends PASSED
...
24 passedCobertura de pruebas:
test_routes.py— todas las ramas de enrutamiento (decisión de recuperación, calificación de soporte, calificación de utilidad)test_mcp_tools.py— funciones de herramientas con Qdrant/LLM simulados (entrada vacía, limitación, excepciones, salud)test_mcp_server.py— tipo de servidor, registro de herramientas, descripciones de herramientas
Stack Tecnológico
Componente | Tecnología |
Orquestación de grafos | |
Enrutamiento de LLM | LiteLLM vía OpenRouter |
LLM | OpenAI GPT-4.1-mini (vía OpenRouter) |
Embeddings | OpenAI |
Base de datos vectorial | |
Embeddings dispersos | FastEmbed BM25 |
Reordenador | FlashRank |
Marco MCP | |
Configuración | |
Interfaz de terminal | |
Gestor de paquetes | |
Tiempo de ejecución | Python 3.12 |
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 Servers
- AlicenseNot gradedqualityDmaintenanceAdaptive Retrieval-Augmented Self-Refinement MCP Server — a closed-loop system that lets LLMs iteratively verify and correct their own claims using uncertainty-guided retrieval.111MIT
- AlicenseNot gradedqualityBmaintenanceEnables document-based Q&A with multi-modal RAG, hybrid retrieval, knowledge graph reasoning, and multi-agent orchestration via MCP tools.4MIT
- FlicenseNot gradedqualityBmaintenanceExposes a Retrieval-Augmented Generation pipeline as MCP tools, allowing users to index documents and query them through any MCP-compatible client like Claude or IDEs.
- AlicenseNot gradedqualityBmaintenanceMCP server providing tools for entity extraction, query refinement, and relevance checking to build Agentic RAG applications.MIT
Related MCP Connectors
AI Reasoning Cache & Consensus Layer with 11 MCP tools via Streamable HTTP.
MCP server exposing the Backtest360 engine API as tools for AI agents.
MCP server providing access to the Scorecard API to evaluate and optimize LLM systems.
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/FireWizard-V9/self_rag_mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server