self_rag_mcp
Allows the Self-RAG retrieval engine to use a PostgreSQL database with the pgvector extension as a vector store, enabling hybrid retrieval over pre-indexed collections.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@self_rag_mcpAnswer this question from the docs: What is the cause of the seasons?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Self-RAG Retrieval Engine
Self-Reflective Retrieval-Augmented Generation system built with LangGraph, Qdrant, and exposed as an MCP (Model Context Protocol) server over SSE transport.
Unlike standard RAG pipelines that blindly retrieve and generate, Self-RAG makes the LLM an active participant in its own quality control โ deciding whether to retrieve, grading what it retrieved, verifying what it generated, and retrying when the answer isn't good enough.
Table of Contents
Related MCP server: mcp-rag-agent
What is Self-RAG?
Standard RAG has a fundamental problem: it always retrieves (even when unnecessary), never checks if retrieved documents are relevant, and never verifies if the generated answer is actually grounded in those documents.
Self-RAG (introduced in the paper Self-RAG: Learning to Retrieve, Generate, and Critique Through Self-Reflection) solves this by inserting reflection steps at every stage:
Stage | Standard RAG | Self-RAG |
Retrieval decision | Always retrieves | LLM decides if retrieval is needed |
Document filtering | Uses all retrieved docs | LLM grades each doc for relevance |
Generation | Generate once | Generate, then verify grounding |
Answer quality | No check | LLM grades usefulness, retries if needed |
This implementation uses LangGraph to model the Self-RAG flow as a stateful directed graph with conditional edges, enabling dynamic routing, retry loops, and full state traceability.
Key Features
๐ Plug-and-Play Retrieval Engine
Standalone MCP server works with ANY vector database (Qdrant, Pinecone, Weaviate, Chroma, pgvector)
Connect to existing indexes โ no ingestion pipeline required
Configuration-driven โ change database by editing
.envRetrieval latency ~0.75s end-to-end
๐ฏ Advanced Retrieval Pipeline
Hybrid search โ Dense (semantic) + Sparse (BM25 keywords) fused via RRF
MMR reranking โ Prevents duplicate/similar results while maintaining relevance
Cross-encoder scoring โ FlashRank (ms-marco-MiniLM int8) for final quality ranking
Parent expansion โ Optional hierarchical context expansion
Graceful fallbacks โ Works with or without parent collections, flattens if needed
๐ง Self-RAG Grading
Retrieval decision โ LLM decides if external knowledge is needed
Relevance grading โ Per-document relevance filtering
Support grading โ Detects hallucinations (answer grounded in context?)
Usefulness grading โ Checks if answer resolves the user's question
Automatic retries โ Re-generates or re-retrieves if quality checks fail
๐ ๏ธ Flexible Ingestion (Optional)
Hierarchical chunking โ Parent-child chunk hierarchy with deduplication
Flat ingestion โ Index documents as-is without hierarchy
Idempotent โ UUID5-based deterministic IDs, safe to re-ingest
DB-agnostic โ Works with any vector database
Architecture Overview
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 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 โ
โ โ
โ ๐ Plug-and-Play: Works with ANY vector database & index โ
โโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โโโโโโโโโโโโผโโโโโโโโโโโ โโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโ
โ Self-RAG Graph โ โ Hybrid Retriever Pipeline โ
โ (Optional) โ โ (DB-Agnostic, Standalone) โ
โ โ โ โ
โ retrieval_decision โ โ 1. Hybrid Search (DB) โ
โ retrieve โ โ Dense + Sparse (BM25) โ
โ relevance_grader โ โ Fusion: RRF/Weighted โ
โ context_builder โ โ โ
โ generator โ โ 2. MMR Diversity Reranking โ
โ support_grader โ โ โ
โ usefulness_grader โ โ 3. FlashRank Cross-Encoder โ
โ โ โ (ms-marco-MiniLM-L-12-v2) โ
โโโโโโโโโโโโฌโโโโโโโโโโโ โ โ
โ โ 4. Parent Expansion (Optional) โ
โ โโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโ
โ โ
โโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Vector Database (Any Provider) โ
โ โ
โ โ Qdrant โ Pinecone โ Weaviate โ
โ โ Chroma โ pgvector (adapters ready) โ
โ โ
โ User's Pre-Indexed Collections (No Ingestion Required!) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโKey: Retrieval and ingestion are completely decoupled. The MCP server works as a standalone retrieval engine with any pre-indexed vector database.
Self-RAG Graph Flow
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:#fffNode Reference
retrieval_decision
The entry point of the graph. The LLM analyzes the user's question and decides whether external knowledge retrieval is actually needed.
Conversational queries (
"Hello","What is 2+2") โ skip retrieval, go directly togeneratorFactual / domain queries โ proceed to
retrieve
Uses structured output: RetrievalDecision { thought: str, answer: "YES" | "NO" }
retrieve
Runs the full Hybrid Retrieval Pipeline against Qdrant:
Hybrid Search โ combines dense (OpenAI
text-embedding-3-small) and sparse (BM25 via FastEmbed) vectors, fused server-side with Reciprocal Rank Fusion (RRF)MMR โ Maximal Marginal Relevance reranking for diversity (avoids returning near-duplicate chunks)
FlashRank โ lightweight ONNX cross-encoder reranker (
ms-marco-MiniLM-L-12-v2) for final relevance scoringParent Expansion โ child chunks are retrieved for precision, but the full parent chunk is returned to the LLM for richer context
relevance_grader
Filters retrieved documents. Each document is individually graded by the LLM against the question.
Documents graded
YESโ kept asrelevant_documentsDocuments graded
NOโ discarded
Uses structured output: RelevanceGrade { thought: str, answer: "YES" | "NO" }
context_builder
Formats the relevant documents into a structured XML context block optimized for LLM attention:
<context>
<document index="1">
<metadata>Source: hr.pdf | Relevance Score: 0.9821</metadata>
<content>
Human Resource Management (HRM) refers to...
</content>
</document>
</context>generator
The LLM generates an answer using only the facts in the context block. The prompt explicitly instructs the model not to use outside knowledge and to cite document indices ([Doc 1]).
support_grader
Verifies that the generated answer is grounded in the context. Performs a claim-by-claim audit.
Returns one of:
fully_supportedโ every claim is backed by the contextpartially_supportedโ some claims are grounded, others are notnot_supportedโ answer contains hallucinations or contradicts the context
Uses structured output: SupportGrade { thought: str, label: "fully_supported" | "partially_supported" | "not_supported" }
usefulness_grader
Evaluates whether the answer actually resolves the user's question โ even if it's grounded, it might be evasive or incomplete.
Returns one of:
usefulโ answer directly satisfies the querynot_usefulโ answer is off-topic, incomplete, or evasive
Uses structured output: UsefulnessGrade { thought: str, label: "useful" | "not_useful" }
increment_retry / increment_retry_for_retrieval
Bookkeeping nodes that increment retry_count in the graph state before looping back to generator or retrieve respectively.
Routing Logic
Router | Condition | Next Node |
|
|
|
|
| |
|
|
|
|
| |
|
| |
|
|
|
|
| |
|
|
Retrieval Pipeline
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_graderWhy this multi-stage funnel?
Hybrid search (dense + sparse) gives better recall than either alone โ dense catches semantic matches, BM25 catches exact keyword matches
MMR prevents the LLM from seeing 4 near-identical chunks โ forces diversity
FlashRank (ONNX int8 quantized) gives cross-encoder quality at ~0.1s vs ~19s for a full PyTorch CrossEncoder
Parent expansion means retrieval precision comes from small child chunks, but the LLM gets the full surrounding context
Ingestion Pipeline (Optional)
The ingestion pipeline is optional and independent of retrieval. Choose your ingestion strategy:
Hierarchical Ingestion (Default)
Documents are split into a parent-child chunk hierarchy:
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
...Child chunks are indexed with both dense + sparse vectors for hybrid search precision
Parent chunks are stored with dense vectors only, used for context expansion after retrieval
UUIDs are deterministic (UUID5) so re-ingestion is idempotent
uv run python scripts/ingest.py --reset # Hierarchical mode (default)Flat Ingestion (No Hierarchy)
Documents indexed as-is, no parent-child relationships:
uv run python scripts/ingest.py --reset --flatSingle collection
No parent expansion overhead
Suitable for pre-chunked data or Q&A pairs
No Ingestion (Bring Your Own Index)
Skip ingestion entirely and connect to existing indexed data:
# .env โ Point to your pre-indexed collection
VECTORDB_PROVIDER=pinecone
RETRIEVAL_COLLECTION=your_index_nameuv run python src/self_rag/mcp/server.py # Retrieval onlyMCP Server & Client
The system is exposed as an MCP server over SSE transport, making it compatible with any MCP client (Claude Desktop, custom clients, etc.).
Tools
Tool | Description |
| Runs the full Self-RAG graph โ retrieval decision โ retrieve โ grade โ generate โ verify โ retry |
| Raw hybrid retrieval only, no generation or grading |
| Returns operational status of retriever and reranker components |
Interactive Client
A rich terminal client is included with a menu-driven interface:
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ 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] ๐ช ExitProject Structure
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
โโโ .envSetup & Installation
Prerequisites
Python 3.12+
uv package manager
Optional: Docker (for Qdrant) or external vector database connection details
Optional: OpenRouter API key (if using cloud LLM)
1. Clone and install dependencies
git clone <repo-url>
cd self_rag_retrieval
uv sync2. Configure environment
cp .env.example .envEdit .env based on your use case:
Option A: Full Self-RAG (Ingestion + Retrieval with Qdrant)
OPENROUTER_API_KEY=sk-or-v1-...
CHAT_MODEL=openrouter/openai/gpt-4.1-mini
EMBEDDING_MODEL=openai/text-embedding-3-small
VECTORDB_PROVIDER=qdrant
QDRANT_URL=http://localhost:6333
RETRIEVAL_COLLECTION=self_rag_documents
PARENT_EXPANSION_COLLECTION=self_rag_parents
DATA_DIR=src/self_rag/dataOption B: Pure Retrieval (External Index, No Ingestion)
OPENROUTER_API_KEY=sk-or-v1-...
VECTORDB_PROVIDER=pinecone # or qdrant, weaviate, chroma
PINECONE_API_KEY=pk-xxx
RETRIEVAL_COLLECTION=your_existing_index
PARENT_EXPANSION_COLLECTION=null3. (Optional) Start Qdrant
Only needed if using Qdrant and self-ingestion:
docker compose up -d4. (Optional) Add documents and ingest
Only needed for self-RAG ingestion:
# Add PDFs to src/self_rag/data/
# Ingest hierarchically (default)
uv run python scripts/ingest.py --reset
# Or ingest flat (no parent-child hierarchy)
uv run python scripts/ingest.py --reset --flat5. Start the MCP server
uv run python src/self_rag/mcp/server.pyThe server works whether you ingested data or are connecting to an external index.
Configuration
All settings are in .env and validated by Pydantic.
Database & Collection Settings
Variable | Default | Description |
|
| Vector DB provider: |
|
| Hybrid search strategy: |
|
| Collection name for retrieval (configurable for any index) |
|
| Collection for parent expansion (set to |
Database-Specific Settings
# Qdrant (recommended)
QDRANT_URL=http://localhost:6333
QDRANT_API_KEY=
# Pinecone
PINECONE_API_KEY=pk-xxx
PINECONE_INDEX_NAME=my-index
# Weaviate
WEAVIATE_URL=http://localhost:8080
# Chroma
CHROMA_PERSIST_DIR=./chroma_dataRetrieval Tuning
Variable | Default | Description |
|
| Hybrid search candidate pool |
|
| Docs after MMR diversity filter |
|
| Final docs after FlashRank |
|
| MMR relevance-vs-diversity balance (0-1) |
Ingestion Settings (Optional)
Variable | Default | Description |
|
| Child chunk size (chars) |
|
| Child chunk overlap |
|
| Parent chunk size (chars) |
LLM & Model Settings
Variable | Default | Description |
|
|
|
|
| vLLM OpenAI-compatible endpoint |
|
| Model served by vLLM |
| โ | Required when |
|
| Chat model when routed through OpenRouter |
|
| Dense embedding model (1536-dim) โ always via OpenRouter |
|
| LLM temperature (0 = deterministic) |
|
| Max Self-RAG retry loops |
See LLM Backends: vLLM & OpenRouter for how backend switching and prefix caching work.
LLM Backends: vLLM & OpenRouter
Every LLM call in the graph (retrieval decision, relevance grading, generation, support grading, usefulness grading) goes through a single ChatLiteLLM singleton (src/self_rag/clients/llm.py), so the backend is swapped with one config flag โ no code changes.
Switching backends
Settings.resolve_llm_provider (src/self_rag/core/config.py) picks the endpoint at startup based on USE_VLLM:
# Local GPU inference via vLLM (default)
USE_VLLM=true
VLLM_BASE_URL=http://localhost:8000/v1
VLLM_MODEL=qwen2.5-7b-instruct-awq
VLLM_API_KEY= # not required for local vLLM
# Cloud fallback via OpenRouter
USE_VLLM=false
OPENROUTER_API_KEY=sk-or-v1-...
OPENROUTER_MODEL=openai/gpt-4.1-miniEmbeddings always go through OpenAI (via OpenRouter), independent of USE_VLLM โ only the chat/grading model moves between backends.
Running vLLM locally
vllm/ ships an OpenAI-compatible vLLM V1 server as its own Docker image, wired up in docker-compose.yaml:
docker compose up -d vllm # serves Qwen2.5-7B-Instruct-AWQ on :8001Key serving flags (vllm/entrypoint.sh, configurable via env vars):
Variable | Default | Purpose |
|
| Model to serve (AWQ-quantized for lower VRAM) |
|
| Fraction of GPU memory vLLM is allowed to claim |
|
| Context window |
|
| Max concurrent sequences (batch size) |
|
| Compressed KV cache storage โ more cache capacity per GB of VRAM |
Prefix caching (implemented)
The Self-RAG graph is a heavy repeat-prefix workload: every retrieval-decision, relevance-grading (once per retrieved document), support-grading, and usefulness-grading call re-sends the same system prompt, and relevance_grader alone can fire the grading system prompt up to RETRIEVAL_K_MMR times in a single query. Without prefix reuse, the model would re-run the full prefill pass over that identical system prompt on every one of those calls.
vLLM is started with --enable-prefix-caching (vllm/entrypoint.sh), vLLM V1's automatic prefix caching (APC). It hashes and caches KV blocks for prompt prefixes shared across requests, so once the shared grading/system prompt has been prefilled once, subsequent calls in the same query (and across queries, while the block stays resident) skip straight to the new suffix instead of recomputing the whole prefix. Combined with fp8 KV-cache storage (more cached blocks fit in the same VRAM) and AWQ weight quantization (frees VRAM for cache/batch headroom), this is what keeps the sequential per-document grading loop affordable on a single GPU.
Design note:
vllm.txtalso documents a planned disaggregated prefill/decode (P/D) deployment โ separate prefill and decode vLLM workers connected via NIXL for KV-cache transfer, an optional LMCache tier for offloading KV blocks to CPU/storage, and anllm-drouter doing KV-aware request routing. This is architecture notes for scaling beyond a single GPU, not yet wired intodocker-compose.yamlโ the current compose setup runs vLLMstandalone(VLLM_KV_ROLEunset), withvllm/entrypoint.shalready supportingkv_producer/kv_consumerroles for when that split is turned on.
Plug-and-Play Retrieval (No Ingestion Required)
The MCP server is a standalone retrieval engine that works with ANY pre-indexed vector database. No ingestion pipeline needed.
Quick Start with External Index
# .env โ Point to your existing index
VECTORDB_PROVIDER=pinecone
PINECONE_API_KEY=pk-xxx
RETRIEVAL_COLLECTION=your_existing_index
PARENT_EXPANSION_COLLECTION=null# Start server (connects to your index, no ingestion)
uv run python src/self_rag/mcp/server.py
# Use it
retrieve_documents(query="...", top_k=5, expand_parents=false)Supported Databases
Database | Status | Notes |
Qdrant | โ Full Support | Native hybrid search, parent expansion |
Pinecone | โ Full Support | Dense-only, serverless |
Weaviate | โ Full Support | Open-source, hybrid-capable |
Chroma | โ Full Support | Lightweight, embedded |
pgvector | โ Adapter Ready | PostgreSQL extension |
Just configure .env and connect to your database. No code changes needed.
Running the System
Option 1: Self-RAG Ingestion + Retrieval (Full Pipeline)
Terminal 1 โ Ingest documents
# First time (creates hierarchical chunks)
uv run python scripts/ingest.py
# Or use flat ingestion (no hierarchy)
uv run python scripts/ingest.py --flat
# Full rebuild (wipes collections)
uv run python scripts/ingest.py --resetTerminal 2 โ Start the MCP server
uv run python src/self_rag/mcp/server.pyThe server warms up all models before accepting connections:
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 3 โ Start the interactive client
uv run python src/self_rag/mcp/mcp_client.pyOption 2: Pure Retrieval (No Ingestion, External Index)
Just configure your vector database and collection name in .env, then:
uv run python src/self_rag/mcp/server.pyThe server connects to your pre-indexed database and serves as a retrieval engine. No ingestion needed.
Retrieval Modes
The retrieve_documents MCP tool supports flexible retrieval:
# Mode 1: With parent expansion (hierarchical data)
retrieve_documents(
query="What is our policy?",
top_k=4,
expand_parents=True # Fetches full parent chunks
)
โ Returns: Parent documents (full context)
# Mode 2: Without expansion (flat data or external index)
retrieve_documents(
query="What is our policy?",
top_k=5,
expand_parents=False # Returns ranked docs as-is
)
โ Returns: Ranked documents
# Mode 3: Auto-fallback (graceful)
retrieve_documents(query="...")
# If parent collection missing/disabled โ returns ranked docs automaticallySample questions (HR domain)
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.Running Tests
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 passedTest coverage:
test_routes.pyโ all routing branches (retrieval decision, support grading, usefulness grading)test_mcp_tools.pyโ tool functions with mocked Qdrant/LLM (empty input, clamping, exceptions, health)test_mcp_server.pyโ server type, tool registration, tool descriptions
Tech Stack
Retrieval & Search
Component | Technology |
Graph orchestration | |
Dense embeddings | OpenAI |
Sparse embeddings | FastEmbed BM25 |
Hybrid fusion | RRF (Reciprocal Rank Fusion), Weighted, Semantic |
MMR reranking | Maximal Marginal Relevance (custom implementation) |
Cross-encoder | FlashRank |
Vector Databases (DB-Agnostic)
Database | Status | Support |
โ Full | Native hybrid, parent expansion | |
โ Full | Dense-only, serverless | |
โ Full | Open-source, hybrid-capable | |
โ Full | Lightweight, embedded | |
pgvector | โ Ready | PostgreSQL extension |
AI & LLM
Component | Technology |
LLM routing | LiteLLM (100+ providers) |
LLM (default) | vLLM V1, local GPU, |
LLM (fallback) | OpenRouter ( |
Quantization | AWQ (weights) + fp8 (KV cache) |
Inference optimization | vLLM automatic prefix caching ( |
Structured output | Pydantic schemas + LLM structured output |
Framework & Infrastructure
Component | Technology |
MCP framework | |
Transport | SSE (Server-Sent Events) over HTTP |
Settings | |
Terminal UI | |
Package manager | |
Container runtime | Docker (for Qdrant, optional) |
Python runtime | 3.12+ |
This server cannot be deployed
Maintenance
Related MCP Connectors
AI Reasoning Cache & Consensus Layer with 11 MCP tools via Streamable HTTP.
Generate contextual prompts and reusable agent skills, evaluate prompts with the 16-dimension Prompt Score, and manage saved work in PromptDrive. Twelve MCP tools also provide authorized access to private Memory for source-grounded answers. Connect over Streamable HTTP using OAuth 2.1 and PKCE. Generation consumes account quota and automatically saves successful results; Memory access follows account permissions and plan limits.
Cloud or self-hosted knowledge for AI agents: hybrid search, reranking, GraphRAG, scoped MCP tools.
- WauldoOAuthcom.wauldo
Stateless agentic tools over MCP: concept extraction, long-context, knowledge graph, planning.
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.2 npm1MIT
- AlicenseNot gradedqualityBmaintenanceEnables document-based Q&A with multi-modal RAG, hybrid retrieval, knowledge graph reasoning, and multi-agent orchestration via MCP tools.4MIT
- AlicenseNot gradedqualityBmaintenanceMCP server providing tools for entity extraction, query refinement, and relevance checking to build Agentic RAG applications.MIT
- FlicenseNot gradedqualityCmaintenanceEnables querying internal documents via a FastAPI REST API and MCP server, using retrieval-augmented generation and an agentic loop that can invoke tools like document search and calculations.-