mcpField
O
opensolr-mcp

opensolr-mcp

本地服务
opensolr.com搜索与检索03 周前更新

关于 opensolr-mcp

opensolr-mcp 为 AI Agent 提供托管 Apache Solr 搜索和文档处理能力,结合 BM25 与向量检索、服务端嵌入、本地文件索引、图像和 OCR 处理,以及基于检索内容的 RAG 回答。

主要功能

  1. 01BM25 与向量混合搜索
  2. 02服务端嵌入与索引
  3. 03按 PDF 页面搜索和阅读
  4. 04本地文件提取与 OCR
  5. 05图像搜索及有依据的 RAG 回答

适用场景

  1. 01用关键词和语义匹配搜索文档
  2. 02索引 PDF 与扫描件文件夹
  3. 03通过照片查找目录商品
  4. 04生成基于已索引文档的回答

MCP 相关

该 MCP 服务向 MCP 客户端提供 Opensolr 搜索、索引、文档、图像及索引管理工具。连接 Opensolr 账户需使用邮箱和 API 密钥。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"com-opensolr-opensolr": {
"command": "uvx",
"args": [
"opensolr-mcp"
],
"env": {
"OPENSOLR_EMAIL": "<OPENSOLR_EMAIL>",
"OPENSOLR_API_KEY": "<OPENSOLR_API_KEY>"
}
}
}
}
启动命令uvx opensolr-mcp
需要配置的环境变量
OPENSOLR_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+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypiopensolr-mcp0.8.1

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

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,支持原生 /select API——工具不会限制你的使用。
  • 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 许可证。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。