rag-mcp-server

rag-mcp-server

Enables MCP clients to query a modular RAG knowledge hub with hybrid dense/sparse retrieval, reranking, multimodal image support, and traceable observability, all through natural language tools.

Category
Visit Server

README

RAG-MCP-SERVER

一个可插拔、全链路可观测的模块化 RAG 检索服务。以 MCP(Model Context Protocol)工具的形式对外暴露检索能力,可被 Claude Desktop、GitHub Copilot 等 MCP Client 直接调用。

核心设计目标是解决 RAG 工程中两个具体痛点:

  1. 链路难定位 —— 检索结果不对,问题出在召回、融合还是重排?索引与查询两条链路共 10 个阶段逐阶段记录耗时、候选数、分数以及排名变化,Dashboard 可视化回溯。
  2. 调优靠感觉 —— 换个 Embedding 模型到底变好还是变坏?Hit Rate@K / MRR 与 Ragas Faithfulness / Context Precision 联合评估,基于固定测试集做回归,用指标而非主观判断校准。

目录


架构总览

                    ┌──────────────────────────────────────────┐
  文档 (PDF/DOCX/    │           Ingestion Pipeline             │
  MD/TXT)      ───▶ │  load → split → transform → embed →      │
                    │  upsert                                  │
                    └────────────────┬─────────────────────────┘
                                     │  SHA256 指纹 + SQLite 摄取历史
                                     │  (文档级增量索引 / 幂等)
                                     ▼
                    ┌──────────────────────────────────────────┐
                    │   ChromaDB (Dense)  +  BM25 (Sparse)     │
                    └────────────────┬─────────────────────────┘
                                     ▼
                    ┌──────────────────────────────────────────┐
  查询          ───▶│            Query Engine                  │
                    │  query_processing → dense ┐              │
                    │                            ├→ RRF fusion │
                    │                    sparse ┘      │       │
                    │                                  ▼       │
                    │                              rerank      │
                    │                    (失败回退至 RRF 顺序) │
                    └────────────────┬─────────────────────────┘
                                     ▼
             ┌───────────────┬───────────────┬──────────────────┐
             │  MCP Server   │  CLI Scripts  │  Dashboard       │
             │  (3 tools)    │  (5 scripts)  │  (Streamlit 6页) │
             └───────────────┴───────────────┴──────────────────┘

  贯穿全程:TraceContext(trace → stage)写入 logs/traces.jsonl

可插拔底座

每个核心环节都定义了统一 Base 接口,通过 Factory + YAML 配置切换,替换组件零代码修改:

环节 接口 已实现的 Provider
LLM BaseLLM openai / azure / deepseek / kimi / ollama
Vision LLM BaseVisionLLM openai / azure / kimi
Embedding BaseEmbedding openai / azure / siliconflow / bge / ollama
Vector Store BaseVectorStore chroma
Splitter BaseSplitter recursive
Reranker BaseReranker llm / cross_encoder(BGE)
Evaluator BaseEvaluator custom / ragas / composite
Loader BaseLoader pdf / docx / markdown / text

任何 OpenAI 兼容端点都可以走 provider: "openai" + 自定义 base_url 接入,无需新增代码。


核心能力

混合检索:BM25 稀疏检索负责专有名词精确匹配,Dense 向量检索负责语义匹配,双路召回后 RRF 融合,再由 Reranker 精排。重排后端失败时自动回退到 RRF 融合顺序,不会让一次超时打断整条链路。

增量索引与幂等:SHA256 内容指纹 + SQLite ingestion_history 表实现文档级增量。重复摄取直接跳过,内容变更才重建,重复摄取不产生脏数据。

多模态:PyMuPDF 提取 PDF 内嵌图片并保留原始位置,Vision LLM 生成图片描述缝合进 Chunk,从而复用纯文本 RAG 链路实现"搜文字出图"。MCP 响应以 ImageContent 返回图片。

MCP 工具

Tool 用途
query_knowledge_hub 混合检索 + 重排,返回带引用的结果(含图片)
list_collections 列出所有集合及文档/分块统计
get_document_summary 返回指定文档的摘要与分块概览

Dashboard(Streamlit 六页):系统总览 / 数据浏览 / 摄取管理 / 摄取追踪 / 查询追踪 / 评估面板。


快速开始

环境要求

Python ≥ 3.10。

安装

git clone <your-repo-url>
cd RAG-MCP-SERVER

python -m venv .venv
# Windows
.venv\Scripts\activate
# Linux / macOS
source .venv/bin/activate

pip install -e ".[dev]"

依赖全部带版本上界。mcp 锁在 <2.0(2.x 重命名了 CallToolResult.isError 等字段), langchain-community 锁在 <0.4(0.4 移除了 chat_models.vertexai,会导致 ragas 导入失败)。

配置

cp config/settings.yaml.example config/settings.yaml

编辑 config/settings.yaml 填入自己的 API Key。该文件已被 .gitignore 忽略,不要提交。

摄取文档

python scripts/ingest.py --path ./your_docs --collection my_kb
python scripts/ingest.py --path ./your_docs --collection my_kb --force   # 强制重建
python scripts/ingest.py --path ./your_docs --dry-run                    # 只看会处理哪些文件

查询

python scripts/query.py -q "你的问题" -c my_kb --top-k 5 --verbose

--verbose 会打印 dense / sparse / fusion / rerank 每一步的中间结果。

启动 Dashboard

python scripts/start_dashboard.py

接入 MCP Client

以 Claude Desktop 为例,在 claude_desktop_config.json 中加入:

{
  "mcpServers": {
    "rag-mcp-server": {
      "command": "<绝对路径>/.venv/Scripts/python.exe",
      "args": ["<绝对路径>/main.py"]
    }
  }
}

配置说明

关键配置段(完整注释见 config/settings.yaml.example):

retrieval:
  dense_top_k: 20
  sparse_top_k: 20
  fusion_top_k: 10
  rrf_k: 60
  # 路由开关,用于 A/B 基线:只测 dense 则 enable_sparse: false,反之亦然
  enable_dense: true
  enable_sparse: true

rerank:
  enabled: true
  provider: "llm"           # 走已配置的 LLM,零额外依赖
  # provider: "cross_encoder"  # 本地 BGE cross-encoder,需 pip install sentence-transformers
  top_k: 5

evaluation:
  enabled: true
  provider: "composite"     # 同时跑检索指标与生成指标
  backends: ["custom", "ragas"]
  metrics: ["hit_rate", "mrr", "faithfulness", "context_precision"]

embedding.dimensions 一旦首次摄取完成就不能再改 —— 已存在的 Chroma collection 与向量维度绑定。


可观测性

每次摄取和查询都会生成一条 trace 写入 logs/traces.jsonl,结构为 trace → stages[],每个 stage 记录 elapsed_ms 与该阶段的 data

链路 阶段
Ingestion loadsplittransformembedupsert
Query query_processingdense_retrievalsparse_retrievalfusionrerank

排名变化追踪

只记录每个阶段结束后的分数列表,无法回答"这一阶段到底改善了排序吗、改善了哪个分块"。因此 fusionrerank 两个阶段额外记录排名变化(src/core/query_engine/rank_tracking.py):

  • 约定 1-based,rank_delta = rank_before - rank_after正值表示排名上升
  • fusionrank_before 取该分块在双路中的最优排名,回答"RRF 是否把它提升到了单路召回之上";同时记录 dense_rank / sparse_rank,显示它由哪条路召回
  • rerankrank_before 是交给重排器的融合列表位置,精确显示重排器提升/打压了谁
  • 新进入的分块上报 None 而非伪造的排名提升
  • 阶段级汇总:moved_up / moved_down / unchanged / new / max_gain / max_drop / dropped

实际 trace 片段:

stage=fusion   elapsed=0.2ms
  rank_changes: {moved_up: 3, moved_down: 1, unchanged: 1, max_gain: 2, dropped: 18}
  rank=2  before=4  delta=+2   dense_rank=4  sparse_rank=4

stage=rerank   elapsed=12231ms
  rank_changes: {moved_up: 1, moved_down: 1, unchanged: 3, max_gain: 1}
  rank=1  before=2  delta=+1

Dashboard 的「查询追踪」页会把这些渲染成阶段瀑布图 + 排名变化表。


评估体系

python scripts/evaluate.py --collection my_kb
python scripts/experiment.py --variants dense,sparse,hybrid,hybrid_rerank
  • 检索指标CustomEvaluator):Hit Rate@K、MRR —— 需要测试集提供 expected_chunk_ids 作为 ground truth
  • 生成指标RagasEvaluator):Faithfulness、Answer Relevancy、Context Precision
  • CompositeEvaluator 同时跑两类后端并合并结果;每个后端各自从共享的 metrics 列表中挑出属于自己的指标,单个后端失败不影响其余

scripts/experiment.py 用于 A/B 对比不同检索变体,输出各变体的指标与延迟,用来回答"加上 rerank 到底值不值这 12 秒"。


测试

分层测试,共 1456 个用例:

pytest tests/unit                      # 1298 passed, 1 skipped
pytest tests/integration -m "not llm"  #   94 passed, 10 skipped
pytest tests/e2e -m "not llm"          #   30 passed,  2 skipped

-m "not llm" 排除需要真实 LLM API 调用的用例。缺少某个 Provider 的凭证时,相关用例会 skip 并给出原因,而不是失败。

关键分支都有针对性覆盖:

关注点 测试
RRF 融合 test_fusion_rrf.py
重排降级路径 test_reranker_fallback.py
幂等写入 test_vector_upserter_idempotency.py
排名变化追踪 test_rank_tracking.py
分词器索引/查询一致性 test_sparse_encoder.py / test_query_processor.py
Chroma 客户端并发构建 test_chroma_client.py
向量存储契约 test_vector_store_contract.py

项目结构

src/
├── core/
│   ├── query_engine/       # 混合检索:dense / sparse / RRF fusion / rerank
│   │   └── rank_tracking.py  # 排名变化计算(融合与重排共用)
│   ├── response/           # 响应组装、引用生成、多模态拼装
│   ├── trace/              # TraceContext:trace → stage
│   ├── tokenization.py     # BM25 分词器(索引端与查询端唯一实现)
│   └── settings.py         # YAML 配置加载与校验
├── ingestion/
│   ├── chunking/ embedding/ storage/ transform/
│   ├── pipeline.py         # 五阶段摄取流水线
│   └── document_manager.py # 文档删除(跨 Chroma / BM25 / 图片 / 摄取历史)
├── libs/                   # 可插拔底座:base_*.py + *_factory.py
│   ├── llm/ embedding/ loader/ reranker/ splitter/ vector_store/ evaluator/
├── mcp_server/             # MCP 协议与 3 个 Tool
└── observability/
    ├── dashboard/          # Streamlit 六页
    └── evaluation/         # ragas / composite / eval_runner

scripts/   ingest / query / evaluate / experiment / start_dashboard
config/    settings.yaml.example + prompts/
tests/     unit / integration / e2e

data/(Chroma、BM25 索引、抽取出的图片、摄取历史)与 logs/(trace)都是运行时 生成的本地产物,已被 .gitignore 忽略,不随仓库分发;首次运行时会自动创建。


License

MIT

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured