🚀 MCP本地检索增强生成(RAG)
这是一个注重隐私的文档搜索服务器,可完全在本地机器上运行。无需API密钥,不依赖云服务,数据不会离开你的计算机。
该项目基于模型上下文协议(MCP)构建,允许你使用Cursor、Codex、Claude Code或任何MCP客户端,通过语义搜索在本地文档中进行搜索,而无需将任何内容发送到外部服务。
🚀 快速开始
将MCP服务器添加到你的AI编码工具中。请选择以下工具对应的操作:
Cursor
将以下内容添加到 ~/.cursor/mcp.json 文件中:
{
"mcpServers": {
"local-rag": {
"command": "npx",
"args": ["-y", "mcp-local-rag"],
"env": {
"BASE_DIR": "/path/to/your/documents"
}
}
}
}
Codex
将以下内容添加到 ~/.codex/config.toml 文件中:
[mcp_servers.local-rag]
command = "npx"
args = ["-y", "mcp-local-rag"]
[mcp_servers.local-rag.env]
BASE_DIR = "/path/to/your/documents"
Claude Code
运行以下命令:
claude mcp add local-rag --scope user --env BASE_DIR=/path/to/your/documents -- npx -y mcp-local-rag
重启你的工具,然后就可以开始使用了:
"Ingest api-spec.pdf"
"What does this document say about authentication?"
就是这么简单,无需安装,无需使用Docker,也无需复杂的设置。
✨ 主要特性
解决痛点
你可能希望使用AI来搜索文档,这些文档可能是技术规范、研究论文、内部文档或会议记录。然而,大多数解决方案都需要将文件发送到外部API,这会带来三个问题:
- 隐私问题:文档可能包含敏感信息,如客户数据、专有研究或个人笔记。将其发送给第三方服务意味着要将这些数据托付给他们。
- 大规模使用成本高:外部嵌入API按使用次数收费。对于大量文档或频繁搜索,成本会迅速增加。
- 网络依赖性:如果离线或网络连接受限,就无法搜索自己的文档。
本项目通过在本地运行所有操作来解决这些问题,文档不会离开你的机器。嵌入模型只需下载一次,之后即可离线使用,并且可以免费无限次使用。
提供的工具
服务器通过MCP提供了五个工具:
- 文档摄入:支持处理PDF、DOCX、TXT和Markdown文件。指定一个文件后,它会提取文本,将其拆分为可搜索的块,使用本地模型生成嵌入向量,并将所有内容存储在本地向量数据库中。如果再次摄入相同的文件,它会替换旧版本,不会产生重复数据。
- 语义搜索:允许使用自然语言进行查询。它理解语义,而不是简单的关键词匹配。例如,询问 “how does authentication work” 时,即使相关部分使用了 “login flow” 或 “credential validation” 等不同的表述,也能找到相关内容。
- 文件管理:显示已摄入的文件及其摄入时间。你可以查看每个文件生成的块数,并验证所有内容是否已正确索引。
- 文件删除:从向量数据库中删除已摄入的文档。删除文件时,其所有块和嵌入向量将被永久删除。这对于删除过时的文档或不再希望索引的敏感数据非常有用。
- 系统状态:报告数据库的相关信息,如文档数量、总块数和内存使用情况。有助于监控性能或调试问题。
技术选型
所有功能都基于以下技术:
- LanceDB:用于向量存储(基于文件,无需服务器)
- Transformers.js:用于生成嵌入向量(在Node.js中运行,无需Python)
- all-MiniLM-L6-v2 模型:384维,在速度和准确性之间取得了良好的平衡
- RecursiveCharacterTextSplitter:用于智能文本分块
性能表现
在标准笔记本电脑上,即使索引了数千个文档块,查询响应通常也能在3秒内完成。
📦 安装指南
本项目无需复杂的安装过程,按照快速开始部分的步骤将MCP服务器添加到你的AI编码工具中即可。
首次运行
服务器会立即启动,但嵌入模型会在首次使用时(即首次摄入或搜索时)下载:
- 下载大小:约90MB(模型文件)
- 缓存后的磁盘使用量:约120MB(包括ONNX运行时缓存)
- 下载时间:在良好的网络连接下需要1 - 2分钟
- 首次操作延迟:首次摄入或搜索请求将等待模型下载完成
控制台会显示类似 “Initializing model (downloading ~90MB, may take 1 - 2 minutes)…” 的消息。模型会缓存在 CACHE_DIR(默认:./models/)中,以便离线使用。
延迟初始化的原因:这种方式允许服务器立即启动,无需预先加载模型。只有在实际需要时才进行下载,使服务器在快速状态检查或文件管理操作时更具响应性。
离线模式:首次下载后,完全支持离线使用,无需网络连接。
💻 使用示例
配置
服务器默认配置即可使用,但你可以通过环境变量进行自定义。
Codex
将以下内容添加到 ~/.codex/config.toml 文件中:
[mcp_servers.local-rag]
command = "npx"
args = ["-y", "mcp-local-rag"]
[mcp_servers.local-rag.env]
BASE_DIR = "/path/to/your/documents"
DB_PATH = "./lancedb"
CACHE_DIR = "./models"
注意:节名称必须为 mcp_servers(使用下划线)。使用 mcp-servers 或 mcpservers 会导致Codex忽略该配置。
Cursor
在Cursor设置中添加以下内容:
- 全局设置(所有项目):
~/.cursor/mcp.json
- 项目特定设置:项目根目录下的
.cursor/mcp.json
{
"mcpServers": {
"local-rag": {
"command": "npx",
"args": ["-y", "mcp-local-rag"],
"env": {
"BASE_DIR": "/path/to/your/documents",
"DB_PATH": "./lancedb",
"CACHE_DIR": "./models"
}
}
}
}
Claude Code
在项目目录中运行以下命令以启用该项目:
cd /path/to/your/project
claude mcp add local-rag --env BASE_DIR=/path/to/your/documents -- npx -y mcp-local-rag
或者为所有项目全局添加:
claude mcp add local-rag --scope user --env BASE_DIR=/path/to/your/documents -- npx -y mcp-local-rag
使用其他环境变量:
claude mcp add local-rag --scope user \
--env BASE_DIR=/path/to/your/documents \
--env DB_PATH=./lancedb \
--env CACHE_DIR=./models \
-- npx -y mcp-local-rag
环境变量说明
| 变量 |
默认值 |
描述 |
有效范围 |
BASE_DIR |
当前目录 |
文档根目录。服务器仅访问此路径内的文件(防止意外访问系统文件) |
任何有效路径 |
DB_PATH |
./lancedb/ |
向量数据库存储位置。随着文档数量的增加,该目录可能会变得很大 |
任何有效路径 |
CACHE_DIR |
./models/ |
模型缓存目录。首次下载后,模型将保留在此处以便离线使用 |
任何有效路径 |
MODEL_NAME |
Xenova/all-MiniLM-L6-v2 |
HuggingFace模型标识符。必须与Transformers.js兼容。请参阅 可用模型。注意:更改模型需要重新摄入所有文档,因为不同模型的嵌入向量不兼容 |
HF模型ID |
MAX_FILE_SIZE |
104857600(100MB) |
文件最大字节数。为防止内存问题,较大的文件将被拒绝 |
1MB - 500MB |
CHUNK_SIZE |
512 |
每个块的字符数。值越大,上下文信息越多,但处理速度越慢 |
128 - 2048 |
CHUNK_OVERLAP |
100 |
块之间的重叠字符数。用于保留跨边界的上下文信息 |
0 - (CHUNK_SIZE/2) |
操作使用
配置后重启客户端
- Cursor:完全退出并重新启动(在Mac上使用Cmd + Q,而不仅仅是关闭窗口)
- Codex:重启IDE/扩展
- Claude Code:无需重启,更改将立即生效
服务器将作为可用工具显示,供你的AI助手使用。
摄入文档
- Cursor:Composer Agent会在需要时自动使用MCP工具:
"Ingest the document at /Users/me/docs/api-spec.pdf"
- Codex CLI:助手会在需要时自动使用配置好的MCP工具:
codex "Ingest the document at /Users/me/docs/api-spec.pdf into the RAG system"
"Ingest the document at /Users/me/docs/api-spec.pdf"
路径要求:服务器要求使用文件的绝对路径。你的AI助手通常会自动将自然语言请求转换为绝对路径。BASE_DIR 设置出于安全考虑,限制了对该目录树内文件的访问,但你仍需提供完整路径。
服务器会执行以下操作:
- 验证文件是否存在且大小不超过100MB
- 提取文本(支持PDF/DOCX/TXT/MD格式)
- 将文本拆分为块(每个块512个字符,重叠100个字符)
- 为每个块生成嵌入向量
- 将其存储在向量数据库中
在标准笔记本电脑上,每MB文件大约需要5 - 10秒。完成后会显示确认信息,包括生成的块数。
搜索文档
使用自然语言提问:
"What does the API documentation say about authentication?"
"Find information about rate limiting"
"Search for error handling best practices"
服务器会执行以下操作:
- 将查询转换为嵌入向量
- 在向量数据库中搜索相似的块
- 返回前5个匹配结果,并显示相似度得分
结果包括文本内容、文件来源和相关性得分。你的AI助手将使用这些结果回答你的问题。
你可以请求更多结果:
"Search for database optimization tips, return 10 results"
限制参数接受1 - 20个结果。
管理文件
查看已索引的文件:
"List all ingested files"
这将显示每个文件的路径、生成的块数以及摄入时间。
从数据库中删除文件:
"Delete /Users/me/docs/old-spec.pdf from the RAG system"
这将从向量数据库中永久删除该文件及其所有块。该操作是幂等的,即删除不存在的文件不会报错。
检查系统状态:
"Show the RAG server status"
这将报告总文档数、总块数、当前内存使用情况和运行时间。
重新摄入文件
如果你更新了文档,请再次摄入:
"Re-ingest api-spec.pdf with the latest changes"
服务器会在添加新块之前自动删除该文件的旧块,不会产生重复或过时的数据。
📚 详细文档
开发相关
从源代码构建
git clone https://github.com/shinpr/mcp-local-rag.git
cd mcp-local-rag
npm install
运行测试
npm test
npm run test:coverage
npm run test:watch
测试套件包括:
- 每个组件的单元测试
- 完整摄入和搜索流程的集成测试
- 路径遍历保护的安全测试
- 验证查询速度目标的性能测试
代码质量检查
npm run type-check
npm run check:fix
npm run check:deps
npm run check:all
项目结构
src/
index.ts # 入口点,启动MCP服务器
server/ # RAGServer类,MCP工具处理程序
parser/ # 文档解析(PDF、DOCX、TXT、MD)
chunker/ # 文本拆分逻辑
embedder/ # 使用Transformers.js生成嵌入向量
vectordb/ # LanceDB操作
__tests__/ # 测试套件
每个模块都有明确的边界:
- Parser:验证文件路径并提取文本
- Chunker:将文本拆分为重叠的段
- Embedder:生成384维向量
- VectorStore:处理所有数据库操作
- RAGServer:协调所有操作并暴露MCP工具
性能表现
测试环境
MacBook Pro M1(16GB RAM),于2025年1月在Node.js 22上使用v0.1.3版本进行测试。
查询性能
- 平均:对于10,000个索引块(返回5个结果),查询时间为1.2秒
- 目标:p90 < 3秒(已达成)
摄入速度(10MB PDF)
- 总计:约45秒
- PDF解析:约8秒(17%)
- 文本分块:约2秒(4%)
- 嵌入向量生成:约30秒(67%)
- 数据库插入:约5秒(11%)
内存使用
- 基线:空闲时约200MB
- 峰值:摄入50MB文件时约800MB
- 目标:< 1GB(已达成)
并发查询
能够处理5个并行查询而不降低性能。LanceDB的异步API允许非阻塞操作。
注意:实际结果会因硬件而异,尤其是CPU速度(嵌入向量计算在CPU上运行,而非GPU)。
故障排除
"No results found" 搜索无结果
原因:搜索前必须先摄入文档。
解决方案:
- 首先摄入文档:
"Ingest /path/to/document.pdf"
- 验证摄入情况:
"List all ingested files"
- 然后进行搜索:
"Search for [your query]"
常见错误:配置完成后未摄入任何文档就立即进行搜索。
"Model download failed" 模型下载失败
嵌入模型在首次使用时(即首次摄入或搜索时)会从HuggingFace下载。如果你使用了代理或防火墙,可能需要配置网络设置。
出现情况:首次摄入或搜索操作会触发下载。如果下载失败,你会看到详细的错误消息和故障排除指导(网络问题、磁盘空间不足、缓存损坏等)。
解决方法:错误消息会提供具体建议。常见解决方案如下:
- 检查网络连接并重新尝试操作
- 确保有足够的磁盘空间(约120MB)
- 如果问题仍然存在,删除缓存目录并再次尝试
或者手动下载模型:
- 访问 https://huggingface.co/Xenova/all-MiniLM-L6-v2
- 下载模型文件
- 将
CACHE_DIR 设置为你保存模型的位置
"File too large" 文件过大错误
默认限制为100MB。对于较大的文件:
- 可以将其拆分为较小的文档
- 或者在配置中增加
MAX_FILE_SIZE(注意内存使用情况)
查询性能缓慢
如果查询时间比预期长:
- 检查已索引的块数(使用
status 命令)
- 考虑硬件性能(嵌入向量计算对CPU要求较高)
- 尝试减小
CHUNK_SIZE 以减少块数
"Path outside BASE_DIR" 路径超出BASE_DIR错误
为了安全起见,服务器将文件访问限制在 BASE_DIR 内。请确保文件路径在该目录内。检查以下内容:
- MCP配置中
BASE_DIR 设置是否正确
- 相对路径和绝对路径的使用
- 文件路径是否有拼写错误
MCP客户端无法识别工具
Cursor
- 打开设置 → 功能 → 模型上下文协议
- 验证服务器配置是否已保存
- 完全重启Cursor
- 检查状态栏中的MCP连接状态
Codex CLI
- 检查
~/.codex/config.toml 文件以验证配置
- 确保节名称为
[mcp_servers.local-rag](使用下划线)
- 直接测试服务器:
npx mcp-local-rag 应能正常运行且无错误
- 重启Codex CLI或IDE扩展
- 检查Codex启动时的错误消息
Claude Code
- 运行
claude mcp list 查看已配置的服务器
- 验证服务器是否在列表中
- 检查
~/.config/claude/mcp_config.json 文件是否有语法错误
- 直接测试服务器:
npx mcp-local-rag 应能正常运行且无错误
常见问题:
- 配置文件中的JSON语法错误
BASE_DIR 设置中的文件路径错误
- 找不到服务器二进制文件(尝试全局安装:
npm install -g mcp-local-rag)
- 防火墙阻止本地通信
工作原理
当你摄入文档时,解析器会根据文件类型提取文本。PDF使用 pdf-parse,DOCX使用 mammoth,文本文件则直接读取。
分块器使用LangChain的RecursiveCharacterTextSplitter将文本拆分。它会尝试在自然边界(段落、句子)处进行拆分,同时保持每个块约512个字符。相邻块重叠100个字符以保留上下文信息。
每个块会通过Transformers.js嵌入模型,将文本转换为384维向量,以表示其语义含义。为了提高效率,每次处理8个块。
向量存储在LanceDB中,这是一个基于本地文件的列式向量数据库,无需服务器进程,也无需复杂的设置,只是一个包含数据文件的目录。
当你进行搜索时,查询会使用相同的模型转换为向量。LanceDB会使用余弦相似度算法找到与查询向量最相似的块。前几个匹配结果会返回给MCP客户端,并包含原始文本和元数据。
这种方法的优点在于:语义相似的文本即使使用不同的词汇,其向量也会相似。例如,“authentication process” 和 “how users log in” 会相互匹配,这与关键词搜索不同。
常见问题解答
这真的能保证隐私吗?
是的。首次下载模型后,没有任何数据会离开你的机器。你可以使用网络监控工具进行验证,摄入或搜索过程中不会有出站请求。
可以离线使用吗?
可以,模型缓存后即可离线使用。首次运行需要联网下载模型(约90MB),之后所有操作都可以离线进行。
与云RAG服务相比如何?
云服务(如OpenAI、Pinecone等)通常提供更高的准确性和可扩展性。但它们需要将文档发送到外部,有持续的成本,并且依赖网络连接。本项目在一定程度上牺牲了准确性,但保证了完全的隐私和零运行成本。
支持哪些文件格式?
目前支持的文件格式有:
- PDF:
.pdf(使用 pdf-parse)
- Microsoft Word:
.docx(使用 mammoth,不支持 .doc)
- 纯文本:
.txt
- Markdown:
.md, .markdown
目前不支持的文件格式有:
- Excel/CSV:
.xlsx, .csv
- PowerPoint:
.pptx
- 带OCR的图像:
.jpg, .png
- HTML:
.html
- 旧版Word文档:
.doc
如果你需要支持其他格式,请 提交问题 并说明使用场景。
可以自定义嵌入模型吗?
可以,将 MODEL_NAME 设置为HuggingFace上任何与Transformers.js兼容的模型。请注意,不同模型的向量维度不同,因此切换模型后需要重建数据库。
准确性在多大程度上依赖于模型?
all-MiniLM-L6-v2 针对英语进行了优化,对于技术文档表现良好。对于其他语言,可以考虑使用多语言模型,如 multilingual-e5-small。如果需要更高的准确性,可以尝试使用更大的模型,但处理速度会变慢。
支持GPU加速吗?
Transformers.js默认在CPU上运行。GPU支持处于实验阶段,且因平台而异。对于大多数使用场景,CPU性能已经足够(即使没有GPU,嵌入向量计算也相当快)。
多人可以共享数据库吗?
当前设计假设为单用户本地访问。对于多用户场景,需要实现身份验证和访问控制,这超出了本项目注重隐私设计的范围。
如何备份数据?
复制 DB_PATH 目录(默认:./lancedb/),这就是整个向量数据库。复制 BASE_DIR 目录以备份原始文档。两者都是普通文件,无需特殊导出操作。
🔧 技术细节
文档处理流程
- 解析:根据文件类型使用不同的解析器提取文本。
- 分块:使用
RecursiveCharacterTextSplitter 将文本拆分为合适大小的块,并设置重叠部分以保留上下文。
- 嵌入:使用
Transformers.js 和 all-MiniLM-L6-v2 模型将每个块转换为384维向量。
- 存储:将向量存储在
LanceDB 中。
搜索流程
- 查询转换:将查询文本转换为向量。
- 相似度搜索:在
LanceDB 中使用余弦相似度算法查找最相似的向量。
- 结果返回:返回匹配结果及其相关信息。
性能优化
- 批量处理:在生成嵌入向量时,每次处理8个块以提高效率。
- 异步操作:
LanceDB 的异步API允许非阻塞操作,提高并发处理能力。
📄 许可证
本项目采用MIT许可证,详情请参阅 LICENSE 文件。
本项目可免费用于个人和商业用途,无需注明出处,但我们对此表示感谢。
致谢
本项目基于以下技术构建:
本项目是为那些希望在不牺牲隐私的前提下使用AI进行文档搜索的开发者而创建的实用工具。