关于 opensolr-mcp
opensolr-mcp 为 AI Agent 提供托管 Apache Solr 搜索和文档处理能力,结合 BM25 与向量检索、服务端嵌入、本地文件索引、图像和 OCR 处理,以及基于检索内容的 RAG 回答。
主要功能
- 01BM25 与向量混合搜索
- 02服务端嵌入与索引
- 03按 PDF 页面搜索和阅读
- 04本地文件提取与 OCR
- 05图像搜索及有依据的 RAG 回答
适用场景
- 01用关键词和语义匹配搜索文档
- 02索引 PDF 与扫描件文件夹
- 03通过照片查找目录商品
- 04生成基于已索引文档的回答
MCP 相关
该 MCP 服务向 MCP 客户端提供 Opensolr 搜索、索引、文档、图像及索引管理工具。连接 Opensolr 账户需使用邮箱和 API 密钥。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
uvx opensolr-mcpOPENSOLR_EMAILOpensolr account email; try the shared demo account [email protected], whose indexes are deleted after 3 days and can be changed or deleted by anyone else using it, or get your own at https://opensolr.com/register (free forever, no card)OPENSOLR_API_KEY密钥Opensolr API key, found under Account > API in the control panel; the shared demo account's key is 420b8b23e7b12dc8ab838932145a5065 (preloaded index mcp_demo_d1__dense with 300 news articles, limits per index are 200 MB bandwidth and 50 MB disk, anything created is deleted after 3 days and other people can change or delete it)本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
opensolr-mcp
mcp-name: com.opensolr/opensolr-mcp
面向 Opensolr 的 MCP(Model Context Protocol)服务 — 让任何 AI Agent 都能将托管式 Apache Solr 搜索用作工具:混合检索 (BM25 + kNN)、服务端 GPU 嵌入、文档索引(也支持本地文件和文件夹、逐页处理 PDF、通过 OCR 处理扫描件),以及有依据的 RAG 回答。
在线体验(真实新闻索引、混合搜索 + AI 回答): https://search.opensolr.com/news__dense?q=how+am+I+supposed+to+save+money%3F
无需配置嵌入模型。无需运行向量数据库。只需一个 API 密钥。
工具
| 工具 | 功能 |
|---|---|
opensolr_search | 混合(关键词 + 语义)或纯语义搜索,支持 Solr 筛选条件和日期范围;PDF 会返回匹配度最高的页面,并附带可直接打开该页的链接 |
opensolr_search_by_image | 使用照片搜索 — Opensolr 会读取图片中的视觉标签、OCR 文本和任何条形码 / QR 码,然后用这些词进行搜索(不存储图片向量) |
opensolr_read_document | 完整读取一条搜索结果 — PDF 逐页读取,其他文档作为一段文本读取 |
opensolr_ai_answer | 有依据的 RAG 回答:排名靠前的混合搜索结果会成为大模型上下文 — 与托管搜索 UI 使用相同的处理流程 |
opensolr_index_files | 为本地文件或整个文件夹建立索引:PDF 每页作为一篇文档,支持 Word / RTF / OpenDocument / 文本 / HTML,以及通过 OCR 处理扫描件和图片 |
opensolr_extract_text | 读取本地文件而不为其建立索引:文本、图片中的 OCR 内容,以及逐页读取的 PDF |
opensolr_describe_image | 描述图片内容(一句话)、图片上印刷的文字、标签和条形码 |
opensolr_add_documents | 为纯文本 + 元数据建立索引(在服务端进行嵌入) |
opensolr_delete_documents | 按 ID 删除文档 |
opensolr_list_indexes / opensolr_index_info | 查看账户的索引 |
opensolr_create_index | 在 opensolr_vector_regions 中的某个区域创建向量索引(可使用环境 ID,或 us 这类短名称;短名称会与实时列表匹配) |
opensolr_vector_regions | 支持向量功能的区域实时列表 |
opensolr_check_schema | 检查索引是否支持各工具所需的功能(数据摄取、向量和混合搜索、PDF 页面、关键词搜索),并说明具体原因 |
opensolr_apply_schema | 在向量区域的索引上安装 Opensolr 向量架构(会替换索引配置;索引中已有文档时需使用 force) |
设置
在 opensolr.com/register 注册免费 Opensolr 账户(永久免费,无需银行卡),然后从账户中复制 API 密钥。
无需账户即可试用
我们提供了一个公开演示账户。将程序包指向该账户后,本 README 中的所有内容都能立即运行,无需注册:
export [email protected]
export OPENSOLR_API_KEY=420b8b23e7b12dc8ab838932145a5065
mcp_demo_d1__dense 已载入 300 篇新闻文章,因此连接后即可搜索、筛选并获取有依据的回答。你还可以使用写入功能:在该账户上创建自己的索引,向其中导入数据并进行查询。此共享密钥不支持删除:此处的任何索引都无法手动删除或重新配置。你创建的所有内容都会在 3 天后自动删除。
请了解你正在使用的资源:
- 你在此处创建的任何内容都会在 3 天后删除。 自动删除,不会提前通知,也无法导出。包括你创建的索引及其中的每份文档。
- 此账户由所有阅读本文的人共享。 其他人可以看到你的索引,也可以向其中添加文档;你也可以向他们的索引添加文档。任何人都无法在此处删除或重新配置索引(此密钥已关闭这些功能),但切勿在其中放入任何真实、私密或归客户所有的内容。
- 每个索引的限制都很低,这是有意设置的。 每个索引的带宽为 200 MB,磁盘空间为 50 MB。你最先会达到带宽限制:这些额度足以用于演示、教程和概念验证,但无法支撑应用程序。
如果你需要一个私有、专属且下周仍然存在的索引,请获取自己的密钥 — 永久免费,无需银行卡 — 然后更改上面的两个变量。代码的其他部分无需更改。
Claude Desktop / Claude Code
{
"mcpServers": {
"opensolr": {
"command": "uvx",
"args": ["opensolr-mcp"],
"env": {
"OPENSOLR_EMAIL": "[email protected]",
"OPENSOLR_API_KEY": "YOUR_OPENSOLR_API_KEY"
}
}
}
}
Cursor / Windsurf / 任意 MCP 客户端
配置方式相同 — 使用 stdio 传输,命令为 uvx opensolr-mcp(或
pipx run opensolr-mcp),并在环境变量中设置 OPENSOLR_EMAIL 和 OPENSOLR_API_KEY。
Agent 会话示例
你: 为我们的常见问题解答建立索引,然后找出所有与退款相关的内容。
Agent 会先调用
opensolr_add_documents(index="faq__dense", texts=[...]), 然后调用opensolr_search(index="faq__dense", query="refund policy", hybrid=True)— BM25 会捕捉确切词语“refund”,kNN 会捕捉“把钱退还给客户”,再将两者的分数按文档融合。
使用照片搜索
opensolr_search_by_image 让 Agent 可以使用图片而非文本查询进行搜索。Opensolr 会通过三种方式读取图片 — 视觉标签(描绘的内容)、OCR 文本(图片上印出的文字)以及任何条形码 / QR 码 — 将其转换为文字,然后执行常规搜索。不会存储图片向量。
opensolr_search_by_image(index="catalog__dense", image_path="/tmp/shelf.jpg",
using="auto", k=5)
# using: "auto" (engine's choice) | "meaning" (visual labels) |
# "text" (OCR only) | "code" (exact barcode/QR) | "all" (everything)
# -> { "read": {text, mode, labels, codes}, "results": [...] }
search_mode、mode、alpha、fresh_bias、filter_query、date_from、date_to
和 group_pages 的行为与 opensolr_search 完全相同。
本地文件和文件夹:逐页处理 PDF,通过 OCR 处理扫描件
opensolr_index_files 会为服务器运行所在机器上的单个文件或整个文件夹建立索引。Opensolr 的服务器会读取每个文件——文件中的文本、图片中的文字(支持 100 多种语言的 OCR),以及不含文字的图片的简短描述——并且 每个 PDF 都按每页一份文档建立索引,这样搜索结果会定位到能回答问题的页面,而不是提及相关内容的 200 页文件。Word、RTF、OpenDocument、文本、HTML 和图片文件(扫描件、文档照片)均各作为一份文档。
opensolr_index_files(index="contracts__dense", path="~/Documents/contracts",
pattern="*.pdf", metadata={"team": "legal"})
# -> {"documents": [{path, source, uri, id}], "pending": [], "failed": [], "jobs": [...]}
- 字节只传输一次:账户已发送过的文件(内容相同)不会再次上传,重新发送相同文件会替换其文档。
- 每份文档的
uri都是https://ingest.opensolr.com/<index>/<source>,其中source是所发送文件夹中的文件路径(也会记录在meta_source中);文档日期为文件的修改时间,因此本地文件也支持日期范围搜索。 - 大文件会在后台读取:超过
wait_seconds仍在读取的文件会列在pending中;再次使用相同路径调用工具即可为这些文件建立索引(不会重复发送任何内容)。 - 通过 OCR 读取的图片每张计为 0.5 次 AI 请求;之前读取过的文件免费。
opensolr_extract_text 会进行相同的读取,但不会建立索引——提取每个文件的文本;PDF 会按页面返回(page、text、is_ocr、lang)——供希望自行阅读合同、扫描版发票或报告文件夹的 Agent 使用。
opensolr_describe_image 会说明图片展示的内容和其中的文字:caption(一个句子)、text(OCR)、labels 以及条形码 / QR codes。
搜索结果中的 PDF 页面
对于按页存储 PDF 的索引(对上述文件建立的索引、通过 rtf 发送到 Data Ingestion 的 PDF、Web Crawler 找到的 PDF),opensolr_search 会将每个 PDF 作为最佳页面返回一次:
{"title": "Master services agreement", "page": 14,
"page_url": "https://example.com/msa.pdf#page=14", # opens the PDF at that page
"document_id": "9f2c...", # for opensolr_read_document
"more_pages": [{"page": 3, "page_url": "...#page=3"}, ...], # its other matching pages
"matching_pages": 4, "uri": "https://example.com/msa.pdf", ...}
group_pages=false 会将页面作为单独的结果返回。opensolr_read_document 会完整读取任意结果:PDF 按顺序读取其页面(page_from / page_to),其他文档则作为一段文本读取。
搜索指定时间段
date_from 和 date_to(格式为 YYYY-MM-DD,包含起止日期,任一项都可以留空)只保留日期在该时间段内的文档(creation_date)。它们可与其他所有选项(包括 fresh_bias)组合使用。
搜索运算符
查询字符串支持人们在搜索框中熟悉的运算符。它们适用于所有模式——关键词、混合和纯向量。
| 运算符 | 含义 | 示例 |
|---|---|---|
"word1 word2" | 短语——这些词按指定顺序相邻出现 | "machine learning" |
+word | 必含——每条结果都必须包含该词 | +laptop 15 inch gaming |
+"word1 word2" | 必含短语 | +"13 inch" |
-word | 排除——移除任何包含该词的文档 | laptop -refurbished |
-"word1 word2" | 排除短语 | -"open box" |
它们可以组合使用:+laptop +"13 inch" -refurbished 只会返回 13 英寸笔记本电脑,并且绝不会返回翻新机。
带前缀的词项(+ 或 -,可以是词或短语)会成为过滤条件,应用于整个结果集。一旦涉及向量,这一点就很重要:混合搜索的语义侧无法理解否定,因此如果 -refurbished 仅作为查询文本,翻新商品反而会被推到结果前列;作为过滤条件时,它会约束所有文档,无论文档是由搜索的哪一侧找到的,排除效果都是绝对的。
不带前缀的短语(例如前面没有 + 的 "machine learning")是关键词侧的相关性信号,而不是过滤条件——如果需要强制匹配,请使用 +"machine learning"。
+ 和 - 只有出现在词首时才会生效,因此 e-mail、covid-19 和 1+1 会按字面内容搜索。
备注
- 向量索引位于向量区域:运行网页爬虫的 Opensolr 服务器,无论其 Solr 版本是什么。区域列表是实时的,不会写入软件包:
opensolr_vector_regions会返回当前可创建新索引的区域(环境 ID、国家/地区、Solr 版本)。location=可接受列表中的环境 ID,也可使用us、de或fi等简写,系统会根据环境 ID 或国家/地区与实时列表匹配。可按需部署其他专用区域(付费附加项):[email protected]。 - 每个索引也都是普通的 Apache Solr,支持原生
/selectAPI——工具不会限制你的使用。 - LangChain 的 Python 配套项目:
langchain-opensolr· 产品页面:opensolr.com/langchain
写入方式(Data Ingestion API)
写入通过 Opensolr 的 Data Ingestion API进行——与 Drupal 和 WordPress 连接器使用的管道相同。该流程是异步的:文档会先进入队列,然后在服务端计算嵌入、情感、语言,以及所有与爬虫一致的衍生字段,文档约一分钟内即可搜索。可在控制面板 → Data Ingestion中查看进度——这里有每个作业的状态面板(排队中/处理中/已完成/失败,并显示每个作业已处理/成功/失败的文档数量),也可通过 ingest_status API 查看。每个文档的标识是其 uri(Solr ID 为 md5(uri)):在元数据中传入真实 URL({"uri": "https://..."}),也可以根据你的 ID 自动生成一个确定性的 URL。重新提交相同的 uri 会更新文档。传入 {"rtf": True, "uri": "https://.../file.pdf"},服务器会为你从 PDF/DOCX/XLSX 中提取文本。
纯词法模式
不需要向量?纯关键词搜索会完全跳过嵌入调用——不消耗任何 AI 配额。它适用于任何包含 title、description 和 text 字段的 Opensolr 索引,包括向量区域以外的索引和较旧的 Solr 版本(参见Index requirements)。
索引要求
此软件包执行的所有操作都依赖位于向量区域中的 Opensolr 索引,且该索引采用 Opensolr 向量架构——每个 Opensolr 向量索引都会运行的配置。通过此软件包创建的索引(create_index、create_if_missing)两者兼备。通过其他方式创建的索引则未必如此:服务器可能位于向量区域之外,也可能使用自己的架构。向量区域是运行网络爬虫的 Opensolr 服务器,不受 Solr 版本影响;可接收新索引的区域来自实时的 vector_regions 列表,而不是软件包中的列表。
检查会自动执行。 软件包首次访问某个索引时,会向平台查询该索引是否能执行所请求的操作:每个客户端的每个索引只请求一次,该结果在客户端的整个生命周期内保留,绝不会在每次搜索时都请求。如果检查本身无法执行(例如网络错误或平台繁忙),则不会阻止任何操作:操作照常运行,并会在 5 分钟后重试检查。如果索引与 Opensolr 向量架构不一致,则会在 opensolr 日志记录器上记录一次警告,说明原因和修复方法。
检查会限制以下功能——仅限无法以其他方式运行的功能:
| 功能 | 用途 | 缺少时的处理方式 |
|---|---|---|
ingestion | 数据摄取:添加文档和为文件编制索引 | 索引位于向量区域之外:发送任何文档或字节之前就会拒绝 |
vector_search | 向量搜索和混合搜索 | 索引没有大小正确的向量字段:在产生任何嵌入费用之前就会拒绝 |
pdf_pages | 在搜索结果中对 PDF 页面进行分组 | 结果会像以前一样返回,但不分组 |
keyword_search | 关键词(词法)搜索 | 不会被阻止 |
错误会准确说明问题所在。 被阻止的操作会引发 OpensolrSchemaError(OpensolrError 的子类),其中包含 .index、.capability 和 .report(完整检查报告),错误消息会列出所有原因和修复方法:
Index 'shop_it' cannot take documents or files through Data Ingestion. Index shop_it
is on IT-SOLR-9-6 (Milano, Italy), which is not a vector region: Data Ingestion,
server-side embeddings and hybrid search run only on the servers of a vector region
(DE-SOLR-9 (Germany, Solr 9.00), FINLAND9 (Finland, Solr 9.60), ...). This index
cannot be made ready: create a new index in one of the vector regions (...), for
example with create_index, and send your documents there.
当 Solr 本身拒绝请求时,OpensolrSolrError 会包含 Solr 给出的原因和索引名称;它仍然是 httpx.HTTPStatusError,因此之前捕获该异常的代码仍能正常工作。
from opensolr_mcp.client import OpensolrClient, OpensolrSchemaError
client = OpensolrClient(email, api_key)
try:
client.ingest_files("shop_it", "~/Documents/catalog")
except OpensolrSchemaError as e:
print(e.capability, e.report["fix"]["action"]) # ingestion new_index
查看详情,并修复可修复的问题:
client.check_schema("shop_it") # ready, capabilities, server, Solr version, missing / different fields, problems, fix
client.apply_schema("shop_it", force=False) # installs the Opensolr vector schema; force=True when the index holds documents
apply_schema 的作用是让配置已更改或尚未设置的向量区域索引,无需重新创建,就能支持此软件包的所有功能:它会安装每个 Opensolr 向量索引都会运行的相同配置,并替换索引配置。已有文档的索引需要设置 force=True;这些文档仍保留写入时使用的字段,必须重新发送。向量区域之外的索引无法使用此配置——请在 vector_regions 中的某个区域创建新索引,并将文档发送到该索引。软件包绝不会自行安装架构。
在 Agent 中,相同的两个调用对应工具 opensolr_check_schema 和 opensolr_apply_schema;其他所有工具都会自行执行检查,并在拒绝操作时返回上述消息。
您的索引架构
文档遵循 Opensolr 文档模型(title、description、text、meta_* 自定义字段)。完整架构及其所有字段和类型后缀,请参阅 索引架构参考。要查看您自己的副本:控制面板 → 点击您的
索引 → 配置 → 编辑文件 → schema.xml。想要轻松录入数据?请在控制面板中配置网络爬虫(索引工具 →
WebCrawler):添加网站 URL,验证后,Opensolr 就会为您抓取整个网站并编制索引。
搜索调优
检索(搜索和 RAG 基础内容)通过平台经过调优的
管道运行:全局默认值 → 索引已保存的 搜索调优(控制面板 → 索引设置 → 搜索调优:语义↔词法平衡、字段权重、最小匹配、搜索模式、向量候选池、内容质量加权)→ 通过 tuning 设置的可选单次调用覆盖项:
tuning={"search_mode": "keywords_required", "fw_title": 0.2,
"mm": "strict", "vector_topk": 500, "quality_boost": 0.3}
默认值与平台的 PHP 配置完全一致——只需在控制面板中自定义一次,或在代码中按调用自定义。
新鲜结果偏好
提高较新文档的排名,同时不隐藏任何较旧文档。每个分数都会乘以基于 creation_date 的时效曲线——今天发布的文档权重为满值,一年后约为一半:
store.similarity_search_with_score("solar inverter warranty", fresh_bias=True)
client.hybrid_search(index, query, fresh_bias=True)
client.ai_answer(index, question, tuning={"fresh_bias": 1})
它只会重新排序,绝不会过滤:命中数始终相同,较旧内容仍可访问;没有 creation_date 的文档则保持原有位置,不会被推到列表底部。它适用于三种检索形式——纯向量、纯关键词和融合后的混合排名——因为加权作用于最终分数,而非其中一部分。默认关闭。
这与访问者在托管的 Opensolr 搜索页面排序选项旁使用的 新鲜度 开关相同,因此同一查询在此处和页面上的行为完全一致。
fresh_bias和freshness_boost是两个不同的选项,名称容易造成混淆。freshness_boost是以天数为单位的硬性时间窗口——超出窗口的内容会被过滤,命中数也会减少。fresh_bias则不会过滤任何内容。
测试方式
每个版本都会针对实时 Opensolr 基础设施进行验证——不使用模拟:
- 单元测试(离线):根据实时区域列表进行位置匹配、filter→fq 映射、查询构建、转义。
- 端到端测试套件:完整写入路径,包括异步 Data Ingestion 队列(排队 → 服务端增强 → 可搜索)、语义 / 混合 / 词法检索、元数据往返、过滤器、id 往返(你的 id 和 Solr
md5(uri)id),按 id 和按查询删除。 - 真实语料验证:针对 opensolr.com 自有生产搜索索引的 340 篇文档副本运行搜索。已验证:关键词零重叠时的纯语义命中(“灾难发生后,如何找回我的数据”→ 备份与恢复文档)、跨语言查询(罗马尼亚语查询 → 英语内容)、混合模式下的精确术语呈现、全部四种混合模式,以及完整的 alpha 范围 0 → 1。
- PDF 摄取:通过
rtf:true摄取真实 PDF——服务端文本提取(超过 13k 个字符)、自动内容类型检测,然后根据 PDF 内容进行纯语义查询并检索。
每次发布前都会对这些工具进行实时测试(搜索模式、等待完成的摄取、状态、删除、RAG 答案)。RAG 基础内容会进行端到端验证:对于只能从已摄取 PDF 中回答的问题,返回的正确答案会注明来源为 PDF 提取文本。
MIT 许可证。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。