hybrid-rag-mcp
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., "@hybrid-rag-mcpWhat is the default port for the server?"
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.
hybrid-rag-mcp
Serve MCP com RAG híbrido (Qdrant vetorial + BM25 léxico via RRF), agente multi-step com fallback offline via Ollama e transporte stdio ou streamable HTTP.
Foco: indexar documentos técnicos (Markdown, TXT, PDF) e responder perguntas com fontes citadas, de forma 100% local — o padrão que conecta LLMs a bases locais/corporativas em 2026/2027.
Destaques
Busca híbrida: embedding (Qdrant local, sem Docker) + BM25 próprio (idf suavizado), fundidos por RRF.
Agente multi-step: se o contexto da 1ª busca for insuficiente, o modelo sinaliza
[MORE_CONTEXT], o agente gera uma busca de follow-up e repete com memória incremental de fontes.Re-ranking opcional: cross-encoder (Ollama
/api/rerank, ex.bge-reranker-v2-m3) com degradação graciosa.Fallback resiliente: provedor de nuvem (OpenAI-compatible) na frente, Ollama local como reserva quando a API cai.
Persistência: os chunks ficam no Qdrant; o índice BM25 é restaurado no startup sem re-ingestão.
Rastreabilidade:
tracepor passo do agente +audit.jsonl(pergunta, provedor, iterações, latência, fontes).Mensurável: pipeline de avaliação
recall@k/nDCG@kcom gate de qualidade no CI.Dois transportes: stdio (RPC local) e streamable HTTP (
http://host:port/mcp).
Related MCP server: rag-mcp
Arquitetura
flowchart LR
C[Cliente MCP<br/>stdio ou HTTP] -->|tools: ingest / search / ask| M[MCP Server<br/>hybrid-rag-mcp]
M --> AGE[Agente multi-step<br/>loop com [MORE_CONTEXT]]
M --> I[ingest]
I --> C1[Chunker<br/>seções + sentenças]
C1 --> E[Embeddings<br/>Ollama bge-m3]
E --> Q1[(Qdrant local<br/>busca vetorial)]
C1 --> K[BM25 próprio<br/>busca léxica]
AGE --> RET[Busca híbrida]
RET --> Q1 & K
Q1 & K --> RRF[RRF fusion]
RRF --> RR[Reranker opcional<br/>Ollama /api/rerank]
RR --> LLM[FallbackLLM<br/>nuvem -> Ollama]
LLM --> AUD[audit.jsonl<br/>trace + iterações + fontes]Métricas (gate de qualidade no CI)
Pipeline de avaliação sobre 36 queries — 12 curadas manualmente em eval/dataset.jsonl + 24 geradas automaticamente de documentos reais (eval/dataset.real.jsonl, veja Corpus).
Gatilho do CI: falha se recall@1 < 0.8.
k | recall@k | nDCG@k |
1 | 0.833 | 0.833 |
3 | 1.000 | 0.836 |
5 | 1.000 | 0.907 |
Números honestos sobre texto real: recall@1 = 0.833, mas a fonte certa está sempre no top-3. Rode localmente com python -m hybrid_rag_mcp.eval.
Corpus
examples/corpus/— 11 documentos: 5 fictícios (operations/security/database/infra/events) + 6 livros reais de domínio público (Project Gutenberg): Chekhov, Machado de Assis, Aluísio Azevedo, Eça de Queirós, Jane Austen e Conan Doyle, misturando PT e EN.tools/fetch_corpus.py— baixa o catálogo do Gutenberg e gera o dataset de avaliação automaticamente: cada consulta é um trecho real do documento e o documento esperado é a fonte exata desse trecho (ground-truth auto-supervisionado, sem curadoria manual).
Como rodar
Pré-requisitos: Python 3.11+, Ollama de pé (ollama serve).
# 1. Modelos locais (uma vez)
ollama pull bge-m3 # embeddings
ollama pull qwen3:8b # geração (ou outro)
ollama pull bge-reranker-v2-m3 # opcional: somente Ollama >= 0.36
# 2. Instalar
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
# 3. Indexar + responder (uso direto da engine)
python -c "
from hybrid_rag_mcp.rag.engine import RAGEngine
rag = RAGEngine()
print(rag.ingest()) # indexa examples/corpus
print(rag.search('Qual a porta padrão do servidor?')) # busca híbrida
print(rag.ask('De quantas em quantas horas são os backups?')) # agente com fontes
"Como cliente MCP
stdio: cliente de exemplo — python examples/client.py "Qual a porta padrão?"
HTTP:
# terminal 1
python -m hybrid_rag_mcp --transport http --host 127.0.0.1 --port 8000
# terminal 2
python examples/client_http.py "Qual a porta padrão?"Registre em qualquer cliente MCP (Claude Desktop, editores, agentes):
{
"mcpServers": {
"hybrid-rag": {
"command": ".venv/bin/python",
"args": ["-m", "hybrid_rag_mcp"],
"env": { "PYTHONPATH": "src" }
}
}
}Fallback para nuvem (opcional)
Copie .env.example para .env e preencha CLOUD_BASE_URL + CLOUD_API_KEY + CLOUD_MODEL
(qualquer endpoint OpenAI-compatível). A nuvem assume prioridade; o Ollama responde automaticamente
se a API falhar ou ficar offline.
Ferramentas MCP
Tool | Descrição |
| Indexa |
| Busca híbrida (RRF, com re-ranking opcional) retornando trechos + fontes. |
| Agente multi-step: recupera, gera, detecta contexto insuficiente, refaz a busca e responde citando fontes (com audit log). |
Estrutura
src/hybrid_rag_mcp/
├── server.py # Servidor MCP (stdio + streamable HTTP)
├── config.py # Configuração via .env (pydantic-settings)
├── eval.py # Avaliação recall@k / nDCG@k
├── rag/
│ ├── agent.py # Loop multi-step (memória de fontes, [MORE_CONTEXT])
│ ├── chunker.py # Chunking por seções markdown + sentenças
│ ├── engine.py # Orquestração: ingest → search → ask + audit
│ ├── hybrid.py # Fusão RRF + re-ranking
│ └── ingestion.py # Leitura de md/txt/pdf
├── providers/
│ ├── embed.py # Embeddings via Ollama
│ ├── llm.py # FallbackLLM (nuvem → Ollama)
│ └── rerank.py # Cross-encoder opcional (degradação graciosa)
└── stores/
├── vector.py # Qdrant embarcado (sem Docker, persistente)
└── lexic.py # BM25 com idf suavizadoQualidade
21 testes unitários (
pytest) sem rede/Ollama — chunking, RRF, BM25, persistência, métricas de eval e loop do agente.CI em 2 jobs:
test(ruff + pytest + smoke stdio/HTTP) eeval(Ollama real + gaterecall@1 >= 0.8).docker-compose.ymlintencionalmente ausente: roda só compip install(Qdrant embarcado).
Available Tools
3 toolsaskC
Responde a pergunta com RAG usando o provedor disponível (fallback offline via Ollama).
| Name | Required | Description | Default |
|---|---|---|---|
| top_k | No | ||
| question | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure. It mentions a fallback offline via Ollama, which is useful, but does not explain whether the operation is read-only, whether it requires prior ingestion, or how provider selection behaves beyond the fallback.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single clear, efficient sentence that front-loads the core functionality and includes a behavioral note about the fallback. No unnecessary words, though it slightly sacrifices detail for brevity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has two parameters, no annotations, and a vague description. It lacks usage guidance, parameter semantics, and behavioral details such as return format or prerequisites, making it incomplete for an agent to call correctly in varied contexts.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description does not add meaning for either parameter. It implies 'question' is the input, but 'top_k' is completely undocumented in both the schema and description, leaving the agent without semantic guidance.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool answers a question using RAG, which is a specific verb and resource. It does not explicitly differentiate from sibling 'search', but the phrase 'Responde a pergunta com RAG' gives enough identity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use 'ask' versus sibling tools 'search' or 'ingest'. The description does not mention any conditions, prerequisites, or exclusions, leaving the agent to infer usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ingestA
Indexa documentos (md/txt/pdf) de um diretório nos índices vetorial e BM25.
| Name | Required | Description | Default |
|---|---|---|---|
| corpus_dir | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses the main write behavior (indexing into vector and BM25 stores) but does not mention side effects, such as whether existing documents are replaced, whether indexing is incremental, if the directory is read recursively, or any permission requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence with no wasted words. It front-loads the action and packs in file types and target indexes efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with one parameter and an output schema, the description covers the core purpose and parameter meaning. Gaps remain around usage timing, reindexing behavior, and directory handling, but these are not severe enough to render it unusable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. 'de um diretório' clarifies that corpus_dir is the source directory, adding meaning to the parameter name alone. However, it does not explain the default behavior, path format, or how recursive/required the directory is.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Indexa' - indexes), a clear resource (documents md/txt/pdf from a directory), and the target (vector and BM25 indexes). This clearly differentiates it from siblings 'search' and 'ask', which are query operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use is implied: call this tool to index documents before searching or asking. However, there is no explicit guidance on when to use it versus alternatives, prerequisites, or scenarios where it should not be used.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchA
Busca híbrida (vetorial + BM25 via RRF) no corpus indexado. Retorna trechos e fontes.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| top_k | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It goes beyond a bare 'search' by revealing the hybrid retrieval approach (vector + BM25 via RRF) and specifying that the output contains excerpts and sources. This gives an agent useful expectations about both behavior and returns.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single dense sentence with no filler. It front-loads the core purpose and retrieval method, then immediately gives the return type. Every word contributes meaningful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter search tool with an output schema present, the description is largely complete: it names the corpus, explains the hybrid mechanism, and states what is returned. It could add usage direction relative to siblings, but that gap is already covered under usage guidelines.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description needed to compensate, but it does not explain query or top_k. The parameter names and types are self-explanatory enough for a minimal viable call, and the default for top_k is in the schema, but the agent gets no additional semantic guidance from the description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific operation ('hybrid search') and a clear resource ('the indexed corpus'), and further distinguishes the tool by naming the retrieval mechanism (vector + BM25 via RRF) and the return type (excerpts and sources). This sets it apart from the sibling tools ingest and ask.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use is implied: search over an indexed corpus. However, there is no explicit guidance about when to prefer this tool over ask or ingest, nor any mention of what each sibling is better suited for. The context is reasonably clear but the routing decision is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.0- First observed
ask - First observed
ingest - First observed
search
TDQS
Scored across 3 tools
Cada ferramenta tem um propósito claramente distinto: ingestão, busca híbrida e geração de resposta. 'search' e 'ask' podem parecer próximos, mas as descrições deixam explícito que um retorna trechos/fontes e o outro produz uma resposta via RAG.
Os três nomes seguem o mesmo padrão de verbos imperativos simples: ingest, search, ask. Não há mistura de estilos ou convenções conflitantes.
Com três ferramentas, o servidor cobre exatamente o fluxo central de um RAG híbrido sem excesso ou carência. O escopo é enxuto e cada ferramenta é necessária.
O ciclo principal — ingerir, buscar e responder — é completo e funcional. Faltam operações secundárias como remover/atualizar documentos ou listar o índice, mas o agente consegue realizar as tarefas centrais sem becos sem saída.
Maintenance
Related MCP Connectors
- KumbukaOAuthai.kumbuka
Governed, auditable knowledge your team curates for its AI assistants, self-hostable
Ingest, manage, and retrieve documents for RAG-powered AI applications
Search your knowledge bases from any AI assistant using hybrid RAG.
Versioned documentation registry and semantic search for AI tools and coding assistants.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables intelligent ingestion and querying of PDF, Markdown, and text files using hybrid search that combines keyword matching and semantic embeddings with citations.2-
- FlicenseAqualityDmaintenanceEnables indexing local documents (PDF, Markdown, text, code) into a knowledge base and querying them via semantic search using local embeddings, all running privately on your machine.4-
- AlicenseAqualityCmaintenanceEnables semantic search and question answering over a knowledge base using hybrid retrieval and grounded answers, all running offline with no API keys.4MIT
- AlicenseAqualityAmaintenanceIndexes your project's markdown documentation and exposes it to AI agents via local hybrid search (lexical + semantic) with progressive disclosure tools.3555 npm5MIT