使用说明
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.优先顺序(最高获胜):
- CLI标志(
--data-dir,--qdrant-mode,--in-memory,--log-level) - 环境变量(
MCPRAG_DATA_DIR,MCPRAG_QDRANT_MODE等等) config.yaml- 默认值
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
