Skip to main content
Glama
Mily-Lv
by Mily-Lv

RAG-MCP-SERVER

プラグイン可能で、チェーン全体を可観測にできるモジュール式 RAG 検索サービスです。MCP(Model Context Protocol)ツールの形で検索能力を外部に公開し、Claude Desktop、GitHub Copilot などの MCP Client から直接呼び出すことができます。

中心的な設計目標は、RAG 実装における 2 つの具体的な痛点を解決することです。

  1. チェーン内の問題箇所を特定しにくい —— 検索結果が正しくないとき、問題はリコール・融合・リランキングのどこにあるのか?インデックスチェーンとクエリチェーンの 2 つ、合計 10 ステージで、所要時間・候補数・スコア・順位変動を逐次記録し、Dashboard で可視化して遡れます。

  2. チューニングが感覚頼りになる —— Embedding モデルを変えて、実際に良くなったのか悪くなったのか?Hit Rate@K / MRR と Ragas Faithfulness / Context Precision を組み合わせて評価し、固定テストセットに基づいて回帰を検証し、主観ではなく指標で調整を判断します。


目次


Related MCP server: mcp-rag-assistant

アーキテクチャ概要

                    ┌──────────────────────────────────────────┐
  文档 (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 ベクトル検索は意味的な一致を担当し、2 系統のリコール後に RRF で融合し、最後に Reranker で再順位付けします。リランキングのバックエンドが失敗した場合は自動的に RRF 融合順へフォールバックするため、1 回のタイムアウトでチェーン全体が中断することはありません。

増分インデックスと冪等性:SHA256 でコンテンツの fingerprint を算出し、SQLite の ingestion_history テーブルを使うことでドキュメント単位の増分取り込みを実現します。重複した取り込みは直接スキップし、内容が変更された場合だけ再構築するので、重複取り込みでも不整合なデータを生成しません。

マルチモーダル:PyMuPDF で PDF 内の画像を抽出して元の位置を保持し、Vision LLM が生成した画像説明を Chunk に織り込みます。これにより純テキストの RAG チェーンを再利用して「テキスト検索で画像を取得」できます。MCP 応答では ImageContent として画像を返します。

MCP ツール:

Tool

用途

query_knowledge_hub

ハイブリッド検索+再順位付けし、引用付きの結果(画像含む)を返す

list_collections

全コレクションと文書/チャンクの統計を一覧表示する

get_document_summary

指定した文書の要約とチャンク概要を返す

Dashboard(Streamlit の 6 ページ構成):システム概要/データ閲覧/取り込み管理/取り込みトレース/クエリトレース/評価パネル。


クイックスタート

環境条件

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 で無視されているため、コミットしないでください。 :。0に設定されているため、コミットしないでください &&

ドキュメントの取り込み

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 はベクトル次元に結び付いているためです。


可観測性

取り込みのたび、クエリのたびに 1 件の trace が生成され logs/traces.jsonl に書き込まれます。構造は trace → stages[] であり、各 stage には elapsed_ms とそのステージの data が記録されます。

チェーン

ステージ

Ingestion

load → split → transform → embed → upsert

Query

query_processing → dense_retrieval → sparse_retrieval → fusion → rerank

順位変動の追跡

各ステージ終了時のスコアリストだけを記録しても、「このステージで回収順が本当に改善したのか、どのチャンクを改善したのか」には答えられません。そこで fusion と rerank の 2 ステージでは、順位変動を追加で記録します(src/core/query_engine/rank_tracking.py)。

  • 1 起点で統一し、rank_delta = rank_before - rank_after とします。正値は順位が上がったことを意味します

  • fusion の rank_before には、そのチャンクが 2 系統での最良順位を採用し、「RRF が単系統のリコールより上に引き上げたか」を示します。また dense_rank / sparse_rank も記録し、どの系統で取得されたかを明示します

  • rerank の rank_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 は 2 種のバックエンドを同時に実行し、結果をまとめます。各バックエンドは共有の metrics リストから自分の指標を取り出し、1 つのバックエンドが失敗しても他には影響しません

scripts/experiment.py は A/B それぞれの検索バリアントを比較し、各バリアントの指標と遅延を出力するため、「リランカーを入れてどれだけコストに見合うか」を確認するのに使えます。


テスト

階層化されたテスト、合計 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_writer_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

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    Provides RAG-based knowledge retrieval and document management as MCP tools, supporting hybrid search, reranking, and retrieval process visualization.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    A pluggable, observable modular RAG framework that exposes query knowledge hub, list collections, and get document summary tools via MCP, enabling AI assistants to perform hybrid search and document retrieval with reranking.
    2
    MIT