RAG知识库服务器

为任何LLM提供RAG支持的私有知识库和网络搜索功能,文档处理完全本地化,确保数据隐私。

  • by agarwalvishal
  • Python
  • 本地部署
  • 6 星标
  • 更新于
在 GitHub 查看 agarwalvishal/mcp-rag-server

使用说明

mcp-rag服务器

为任何LLM(云或本地)提供RAG支持的私有知识库和网络搜索。 将文档放入文件夹,立即启动服务器和AI助手 成为数据专家——在本地计算嵌入,因此您的文档 永远不要离开你的机器。

它的作用

此MCP服务器向任何连接的AI客户端提供三个工具:

  • knowledge_base_search --对本地文档(markdown、文本、PDF)进行语义搜索。即使查询使用与源不同的单词,也能查找相关内容。
  • web_search --通过Firecrawl进行实时网络搜索。对于没有内置网络访问的本地LLM(Ollama等)来说尤其有价值。
  • ingest_document --在运行时添加新文档,而无需重新启动服务器。

没有单独的摄取命令。 文件在 data/ 在启动时自动加载、分块、嵌入和索引。

是什么让这与众不同

  • 你的文件永远不会离开你的机器 --嵌入是使用Nomic v1.5在本地计算的。没有OpenAI,没有Cohere,没有云嵌入API。KB搜索在初始模型下载后完全脱机工作(~550MB,一次性)。
  • 零仪式设置 --大多数MCP RAG服务器在搜索工作之前需要单独的摄取/索引命令。此服务器自动从以下位置摄取文档 data/ 在启动时。没有额外的步骤。
  • 默认情况下没有Docker --使用开箱即用的基于本地文件的存储运行。Docker可用于扩展。
  • 双刀具模式 --在一台服务器上进行私人知识库搜索+网络搜索。对于没有内置功能的本地LLM来说尤其有价值。
  • 两个可读的Python文件 --在15分钟内了解整个系统。在不学习框架的情况下扩展它。
mcp-rag服务器 LangChain/llama索引 Enterprise rag
文件离开你的机器了吗? 从不 取决于嵌入选择 通常是
启动时自动摄取 ✓ 手动索引步骤 手动/计划
不需要Docker ✓ 变化 通常需要
MCP协议(Claude,Cursor) ✓ ✗ ✗
与当地LLMs(Ollama)合作 ✓ ✓ 很少
包括网络搜索 ✓ 插件/额外 额外服务
要理解的代码库 ~640行 数千行 不适用

用例

团队项目文档 -ADR、API规范、运行手册、入职指南。连接到Claude Desktop或Cursor,询问“对auth中间件的决定是什么?”或“API速率限制是什么?“而不是搜索文件。附带的示例文档通过一家虚构的初创公司的技术文档证明了这一点。

研究与学习 --将研究论文(PDF)和笔记放入 data/。问所有这些问题:“我们应该使用什么缓存策略?”或“第一季度正常运行时间是多少?”结果包括页码,便于参考来源。

小公司知识库 --每个团队成员的人工智能助理都可以搜索内部文档(流程指南、产品规格、合规文档)。对于企业RAG来说太小,对于“只搜索Slack”来说文档太重

本地LLM增强 --运行Ollama或其他本地模型?你的LLM没有任何内置功能——没有文档访问、没有网络搜索、没有工具。该服务器通过MCP提供这三种功能。

步骤1:安装

需要Python 3.10+。

git clone https://github.com/vishalpai/mcp-rag-server.git
cd mcp-rag-server
python3 -m venv venv
source venv/bin/activate    # Windows: venv\Scripts\activate
pip install -r requirements.txt

第二步:添加您的文档

第一轮: 下载Nomic嵌入模型一次(~550MB,缓存到 ~/.cache/huggingface/).之后,KB搜索在本地运行,不需要互联网。网络搜索是独立的,可选的——它需要 FIRECRAWL_API_KEY.

该仓库附带了来自一家虚构初创公司的示例文档——您可以使用这些文档进行测试,然后用自己的文档替换。

步骤3:连接到您的AI客户端

在下面选择您的客户。每个配置都将客户端指向MCP服务器,以便它可以调用工具。

首次运行注意事项: 嵌入模型(约550MB)会自动下载并缓存以备将来运行。

克劳德桌面

编辑 ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)或 %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "rag-knowledge-base": {
      "command": "/absolute/path/to/mcp-rag-server/venv/bin/python",
      "args": ["/absolute/path/to/mcp-rag-server/mcp_server.py"],
      "env": {
        "FIRECRAWL_API_KEY": "your-key-here"
      }
    }
  }
}

重新启动克劳德桌面。工具会自动显示。

FIRECRAWL_API_KEY 只需要 web_search.省略 env 如果你不需要,就屏蔽它。

提示: 将此添加到您的Claude Desktop项目说明中,以获得最佳效果: “在根据自己的知识回答之前,一定要使用破布知识库工具搜索我的文档。”

克劳德代码(CLI)

添加 .mcp.json 在项目根目录中:

{
  "mcpServers": {
    "rag-knowledge-base": {
      "command": "/absolute/path/to/mcp-rag-server/venv/bin/python",
      "args": ["/absolute/path/to/mcp-rag-server/mcp_server.py"]
    }
  }
}

提示: 添加到您的项目 CLAUDE.md: “在根据自己的知识回答之前,一定要使用破布知识库工具搜索我的文档。”

光标/VS代码

添加 .cursor/mcp.json 在您的项目中:

{
  "mcpServers": {
    "rag-knowledge-base": {
      "command": "/absolute/path/to/mcp-rag-server/venv/bin/python",
      "args": ["/absolute/path/to/mcp-rag-server/mcp_server.py"]
    }
  }
}

提示: 添加 .cursorrules 在您的项目中: “在根据自己的知识回答之前,请务必使用破布知识库工具搜索我的文档。”

本地LLM(Ollama+Continue.dev)

这就是服务器真正闪耀的地方。你的本地LLM没有内置工具——没有文档访问,没有网络搜索,什么都没有。该服务器通过单个MCP连接提供语义文档搜索和网络搜索。

随着 Continue.dev 在VS代码中:

{
  "models": [{ "provider": "ollama", "model": "llama3.1" }],
  "mcpServers": [
    {
      "name": "rag-knowledge-base",
      "command": "/absolute/path/to/mcp-rag-server/venv/bin/python",
      "args": ["/absolute/path/to/mcp-rag-server/mcp_server.py"]
    }
  ]
}

其他与MCP兼容的本地LLM客户端(Open WebUI,msty)遵循类似的模式——将它们指向 mcp_server.py 作为stdio服务器。

第四步:提问

就是这样。开始在你的人工智能客户端中提问——它会自动搜索你的知识库。

如果您正在使用附带的示例文档,请尝试:

查询 预期来源 测试内容
“团队选择了什么身份验证方法?” adr-auth-middleware.md adr文档上的语义匹配
“API的费率限制是多少?” API-reference.md 精确的技术细节检索
“如何设置我的开发环境?” onboarding-guide.md 自然语言到结构化指南
“是什么导致了2月份API中断?” infrastructure-report.pdf 带页面引用的pdf搜索
“Redis与Memcached比较” research-notes.txt 跨文档语义搜索
“如何煮意大利面” 没有结果 正确过滤了不相关的查询

添加文档

启动时: 掉落 .md, .txt, .pdf 文件位于 data/。它们会自动加载、分块、嵌入和索引。每次启动时都会重新构建集合,因此可以在中进行编辑、重命名和删除 data/ 自动拾取——不会累积过时的数据。

运行时: 使用 ingest_document 来自您的AI客户端的工具:

ingest_document(filepath="/path/to/new-doc.pdf", title="API Reference")

该文档可立即搜索当前会话。要使其永久,请将文件添加到 data/ --它将被纳入未来的每一家初创公司。

将文件添加到 data/ 当服务器正在运行时 在下次重新启动之前无效。服务器读取 data/ 一旦启动。要在会话中途索引新文件而不重新启动,请使用 ingest_document 工具。

文件类型支持:

格式 章节标题 页码 注释
.md 是的(# headers) 否 最适合结构化文档
.pdf 是(通过pymupdf4llm基于字体) 是 从字体大小层次结构检测到的标题
.txt 否 否 仅基于段落的分块

搜索结果包括元数据(如果可用): [Source: title | Section: heading | Page: 3 | Relevance: 0.82]

存储模式

模式 Docker? 坚持? 最适合
local (默认) 否 是(./qdrant_data/) 大多数用户只是工作,重启后幸存下来
memory 否 否 试用,CI/CD测试
server 是 是(Qdrant容器) 团队、多客户端访问、大型集合

通过CLI切换模式:

# Default — local file-based storage, no Docker
python mcp_server.py

# In-memory — no persistence, great for trying it out
python mcp_server.py --in-memory

# Server mode — connect to a running Qdrant instance
docker compose up qdrant -d
python mcp_server.py --qdrant-mode server --qdrant-url http://localhost:6333

或设置 qdrant_mode 在 config.yaml:

qdrant_mode: "server"
qdrant_url: "http://localhost:6333"

配置

中的所有设置 config.yaml.优先顺序(最高获胜):

  1. CLI标志(--data-dir, --qdrant-mode, --in-memory, --log-level)
  2. 环境变量(MCPRAG_DATA_DIR, MCPRAG_QDRANT_MODE等等)
  3. config.yaml
  4. 默认值
data_dir: "./data"                          # Directory containing documents
file_types: [md, txt, pdf]                  # File types to load
qdrant_mode: "local"                        # local, memory, or server
qdrant_local_path: "./qdrant_data"          # Storage path for local mode
qdrant_url: "http://localhost:6333"         # Qdrant server URL (server mode only)
collection_name: "knowledge_base"           # Qdrant collection name
embedding_model: "nomic-ai/nomic-embed-text-v1.5"  # Sentence-transformers model
                                            # Also accepts a local directory path for airgapped setups
chunk_size: 500                             # Target chunk size (characters)
chunk_overlap: 50                           # Overlap between chunks
search_top_k: 3                             # Results per search
search_score_threshold: 0.66                # Minimum relevance (0-1)
log_level: "INFO"                           # DEBUG, INFO, WARNING, ERROR

每个设置都可以通过以下方式覆盖 MCPRAG_ 前缀env变量(例如。, MCPRAG_CHUNK_SIZE=1000).

工作原理——智能刀具路径

该服务器专为智能刀具路由而设计。你的法学硕士首先会检查知识库。如果相关性得分低于阈值(0.66),响应会明确表示“我找不到相关答案”——LLM会识别出这一点,并自动退回到网络搜索。没有硬编码的路由逻辑;工具描述和服务器指令指导LLM的决策。

这对本地LLM尤其重要:像Claude这样的云模型有内置的网络搜索,但本地Ollama模型什么都没有。此服务器通过单个MCP连接为他们提供私人文档访问和web访问。

重要提示: 服务器通过MCP协议发送指令,要求LLM始终首先检查知识库。然而,MCP的指示是建议性的——客户决定是否遵循这些指示。为了获得最可靠的体验,请向您的AI客户端添加自定义说明(请参阅上面设置中的步骤3)。

User question
    │
    ▼
LLM calls knowledge_base_search
    │
    ├── Relevant results found → LLM answers from KB
    │
    └── "I couldn't find..." → LLM calls web_search → answers from web

为什么会出现这些技术故障?

为什么选择Nomic v1.5? --具有任务类型前缀的非对称嵌入模型(search_document: 对比 search_query:).文档和查询以不同的方式嵌入,以便更好地检索。在MTEB基准测试中一直表现强劲。本地运行,不需要API密钥。

为什么段落边界分块? --拆分打开 \n\n 边界,而不是固定的字符数。保持语义连贯性。可配置块大小和重叠。

为什么是UUID 5确定性ID? --重新摄取同一文档是幂等的。重新启动服务器10次,你会得到相同的块,而不是重复的块。

为什么分数阈值为0.66? --通过将相关和不相关查询的分数分布与包含的示例文档进行映射,根据经验确定。相关查询得分0.66-0.81,无关查询得分0.48-0.67。阈值位于分离点:足够高以过滤噪声,足够低以捕获所有相关结果。为LLM提供一个干净的“无应答”信号,用于范围外查询——这对KB到web的回退路由至关重要。

为什么选择Qdrant? --运行嵌入式(本地模式)或作为服务器的生产向量数据库。从小处着手,必要时扩大规模。无论哪种方式都是相同的API。

建筑

┌─────────────────┐     stdio      ┌──────────────────┐
│  AI Client      │◄──────────────►│  mcp_server.py   │
│  (Claude,       │                │  ┌──────────────┐ │
│   Cursor,       │                │  │ FastMCP      │ │
│   Ollama, etc.) │                │  │ 3 tools      │ │
└─────────────────┘                │  └──────┬───────┘ │
                                   └─────────┼─────────┘
                                             │
                              ┌──────────────┼──────────────┐
                              │              │              │
                    ┌─────────▼───┐  ┌───────▼────┐  ┌─────▼───────┐
                    │ KB Search   │  │ Web Search │  │ Ingest Doc  │
                    │ knowledge_  │  │ Firecrawl  │  │ knowledge_  │
                    │ base.py     │  │            │  │ base.py     │
                    └─────────┬───┘  └────────────┘  └─────┬───────┘
                              │                            │
                    ┌─────────▼────────────────────────────▼──┐
                    │         Qdrant Vector DB                 │
                    │  local: ./qdrant_data/ (default)        │
                    │  memory: in-process, no persistence     │
                    │  server: http://localhost:6333           │
                    │                                          │
                    │  • COSINE distance                      │
                    │  • UUID5 deterministic IDs (idempotent)  │
                    │  • Nomic v1.5 embeddings (768d)         │
                    └──────────────────────────────────────────┘

用例

团队项目文档 -ADR、API规范、运行手册、入职指南。连接到Claude Desktop或Cursor,询问“对auth中间件的决定是什么?”或“API速率限制是什么?“而不是搜索文件。附带的示例文档通过一家虚构的初创公司的技术文档证明了这一点。

研究与学习 --将研究论文(PDF)和笔记放入 data/。问所有这些问题:“我们应该使用什么缓存策略?”或“第一季度正常运行时间是多少?”结果包括页码,便于参考来源。

小公司知识库 --每个团队成员的人工智能助理都可以搜索内部文档(流程指南、产品规格、合规文档)。对于企业RAG来说太小,对于“只搜索Slack”来说文档太重

本地LLM增强 --运行Ollama或其他本地模型?你的LLM没有任何内置功能——没有文档访问、没有网络搜索、没有工具。该服务器通过MCP提供这三种功能。

这不是给谁的: 企业级(10000多个文档)、非开发人员(无UI)或需要自定义分块/嵌入的高度专业化领域(法律、医疗)。

为什么会出现这些技术故障?

为什么选择Nomic v1.5? --具有任务类型前缀的非对称嵌入模型(search_document: 对比 search_query:).文档和查询以不同的方式嵌入,以便更好地检索。在MTEB基准测试中一直表现强劲。本地运行,不需要API密钥。

为什么段落边界分块? --拆分打开 \n\n 边界,而不是固定的字符数。保持语义连贯性。可配置块大小和重叠。

为什么是UUID 5确定性ID? --重新摄取同一文档是幂等的。重新启动服务器10次,你会得到相同的块,而不是重复的块。

为什么分数阈值为0.66? --通过将相关和不相关查询的分数分布与包含的示例文档进行映射,根据经验确定。相关查询得分0.66-0.81,无关查询得分0.48-0.67。阈值位于分离点:足够高以过滤噪声,足够低以捕获所有相关结果。为LLM提供一个干净的“无应答”信号,用于范围外查询——这对KB到web的回退路由至关重要。

为什么选择Qdrant? --运行嵌入式(本地模式)或作为服务器的生产向量数据库。从小处着手,必要时扩大规模。无论哪种方式都是相同的API。

是什么让这与众不同

  • 零仪式设置 --大多数MCP RAG服务器在搜索工作之前需要单独的摄取/索引命令。此服务器自动从以下位置摄取文档 data/ 在启动时。没有额外的步骤。
  • 默认情况下没有Docker --使用开箱即用的基于本地文件的存储运行。Docker可用于扩展。
  • 双刀具模式 --在一台服务器上进行私人知识库搜索+网络搜索。对于没有内置功能的本地LLM来说尤其有价值。
  • 没有用于嵌入的API密钥 --通过句子转换器在本地运行Nomic v1.5。你的数据永远不会离开你的机器。
  • 两个可读的Python文件 --在15分钟内了解整个系统。在不学习框架的情况下扩展它。

发展

# Run unit tests (no Qdrant or Docker needed — uses in-memory mode)
python -m pytest tests/test_loaders.py -v

# Run search tests (self-contained — uses in-memory Qdrant and test fixtures)
python -m pytest tests/test_search.py -v

# Run all tests
python -m pytest tests/ -v

# Debug with MCP Inspector
pnpx @modelcontextprotocol/inspector python3 mcp_server.py

许可证

麻省理工学院