librechat-search-mcp
librechat-search-mcp
本项目通过将 LibreChat 的 Search messages 能力扩展到 MCP 工具,使其可被主动或按需使用,从而实现「全消息记忆」。
Related MCP server: Claw Recall
摘要
这是一个受限的、LibreChat 专用的 MCP 服务器,基于通用的 meilisearch-mcp 构建,用于搜索 LibreChat 已索引的消息历史,目的是在禁用可选的 LibreChat memory.agent 时,增强原生的 memory 功能/能力,同时节省成本与上下文丢失带来的开销。它运行在 LibreChat Docker Compose 网络中的专用容器内,使用 Streamable HTTP(即并未面向非 Docker 托管/部署方案实现!),它从 LibreChat 每次请求的 User-Id 请求头中解析出实际用户,并在服务端应用用户过滤。在把结果返回给代理之前,还会使用额外的搜索后过滤来帮助约束结果。它的设计初衷就是把这些能力限制在已经拥有相应权限的用户和管理员范围内,并在可能涉及隐私的地方明确注意潜在风险;同时,它的主要适用场景是那些已向用户明确传达「不期待隐私」的环境。
动机
LibreChat 内置的 memory 功能 对于便签式的上下文记忆来说够用,但它的确存在一些成本和副作用:
较小的模型(例如
Gemma-4-12B)会把记忆当作新的对话中重要的提示上下文,导致其他对话的内容奇怪地串扰进来默认的 LibreChat 自动记忆代理会完全覆写而非追加/合并记忆,导致用户特意创建的记忆丢失
自动记忆代理会在每一轮用户消息上都运行,导致输入 token 成本翻倍(是的,你可能也确实会用更便宜的模型来跑你的记忆代理……)
缓存写入成本——这是最终促使我构建这个项目的导火索:每次记忆代理调整记忆内容时,整个会话缓存都会被重写(在使用 OpenAI 缓存系统时),因为记忆被插入在会话历史中前几个对象的中间。
我有一些 GPT-5.6-Terra 对话,每个对话最多花了 3 美元,后来检查自己的用量,发现最大、最不必要的来源就是那些反复的缓存写入。
与此同时,我也希望我的 agent 能像 ChatGPT 那样,对整个历史有更强的感知。既然我可以直接在 LibreChat 的 Search messages 输入框里开始输入,我不禁想:“为什么不把这个能力交给 agent 呢?”相比“便宜代理所总结的记忆”,完整消息里包含的信息要丰富得多,再加上一些递归式搜索,就能把很多对话之间的大量线索联系起来。我个人的实现已经证明了这一点;至于我在公司小组中的工作部署效果如何,还有待观察……
MCP 工具
该服务器提供其所基于的上游 meilisearch-mcp 项目中只读工具的 LibreChat 专用版本(并丢弃了写工具的资源)。
search_messages:主动搜索调用者的已索引消息,以保持连续性;可以按已知的会话 ID、消息发送者和结果条数可选地缩小范围。返回消息 ID、会话 ID、发送者和文本。search_conversations:主动按标题查找调用者已索引的会话;返回会话 ID、标题和标签,供后续的消息搜索使用。admin_search_messages:显式请求、经授权的指定用户消息搜索;返回目标用户以及上面文档描述的消息字段。admin_search_conversations:显式请求、授权后在指定的用户会话中搜索标题;返回目标用户以及会话 ID、标题和标签。health-check:读取配置好的 Meilisearch 可用性状态。版本信息。get-stats:读取数据库范围内 Meilisearch 统计信息。get-health-status:读取完整的健康和索引状态。get-system-info:读取 Meilisearch 系统信息。get-index-metrics:读取某个已知索引(需要indexUid)的指标。尚未实现——在默认的 LibreChat 环境下会返回错误。返回的
fieldDistribution将会有用于将来的(跨集合消息搜索的)拓扑图谱构建,但在 LibreChat 最新版本的 Meilisearch 中,这个功能是实验性的,必须先启用/创建。
用户范围作用域
普通搜索由服务端按「请求 + 调用者」执行作用域限制,不接受任何目标用户或原始过滤器。管理搜索则需要服务授权,通常还指定目标用户;如果授权失败,也不要随后重试或进一步探测。当前实现会返回一个通用搜索错误。所有工具都是只读的,并且只返回上面说明的那些字段。
按请求作用域的工具行为
我开始时并没意识到的一个点是:如果按请求维度来作用域这些工具(即在 MCP 头中使用消息或会话 ID)会如何改变用户体验。MCP 服务器整体是可以被选择出来的、但这些工具本身却不可见——因此你在面向用户的 agent 中无法取消对这些 admin 工具的暴露(但该服务器在根据用户作用域动态展示工具方面还是可以有一些灵活性的)。理想情况下,我们可以在工具使用之外,单独配置连接服务器的头。我一直在跟进 LibreChat 里相关 MCP bug/PR 中,想了解还能做哪部分调整来提升可定制性。
已知问题
当前项目内的部分:
日志对于项目排查失去友好(建议在请求参数和时间(metrics)上加上;或者也将错误按 json 转储)
工具错误缺乏描述性(一开始为隐私而有意如此;但 agent 需要更多环境信息来做 self-correction)
conversationId过滤后的search_messages使用偶发问题?(可能是连接/线程/异步有关;TODO:把 conversationId 加为 filter 字段)get-index-metrics需要启用实验 feature(TODO:测试并探索此功能)文档和代码中还残留着一些 legacy/开发中间产物和不一致
针管理员的目标用户 ID 获取很繁琐(TODO:探索 PeoplePicker API 来映射 handle 或名称+首字母)
集成/启用方面的影响:
不支持未使用应用(因为在了请求级 header,无法决定工具放行)——实际没能实现工具选择
子代理中快速连续调用会产生 failure responses(线程和异步函数需要仔细观察)
对历史主题反复搜索/讨论会让这些主题在后面的搜索中被稀释
会话分组较为笨重而且 token 成本高昂(TODO:添加一种按消息搜索给出分组统计的函数/功能)
复杂搜索的成本也很高(TODO:服务端分组、关键词/主题图、多搜索联合/交集/排除操作、去重、排序)
安全模型
本工具搭建在一个基准假设之上:LibreChat 部署是单租户、单策略的,且没有特定于安全性的模型或安全容器环境。
工具具备基本用户门控,以及可能非常大的管理范围:
普通工具:
search_messages和search_conversations始终只搜索调用者自己的内容。模型既不能给出user,也不能给出Meilisearch原始过滤条件。管理工具:
admin_search_messages和admin_search_conversations要求调用的User-Id与MEILI_MCP_ADMINS中的某个值完全一致。除非MEILI_MCP_ADMIN_SCOPE_ALL_USERS=true,基本上是需要user目标的,否则不符合要求。MCP 服务使用限制了个
MEILI_MCP_KEY;绝不使用 Meilisearch 主密钥。结果被很注意地 schema 化了:普通结果只包含
messageId、conversationId、sender和text;会话结果只包含conversationId、title和tags;管理结果额外包含所取的user。缺失、为空、或格式错误的身份都会 fail closed。授权失败有意输出通用结果,绝不会返回密钥等机密信息。
得到的文本就是 LibreChat 索引到的东西。根据具体索引器或部署,它可能包含助手响应、类似推理文本,或者工具调用记录。这个 MCP 服务器不能恢复 LibreChat 并未索引的内容;所以请将搜索结果视为潜在的敏感数据。
再重要提醒一遍:详见 SECURITY.md 中的其他警示!!!
管理责任
我已即使将其告知企业用户下一代:IT 安全运维人员和我会查看他们所有数据/历史(“无隐私预期”)。我推测,如果你的部署情况与之相同,你也会这样做;否则,你就干脆不要在任何涉及违背合规的环境中使用。这个工具只是让我“能做來这”更加便利(相对于 MongoDB 工具或 Meili CLI),同时也能把历史从某个 provider/model/agent 给另一个 device(在我的部署里,这不是问题——目前是——因为我尚未实施也未实现更严谨的私有模型)。
LibreChat 设置
复制或合并这些 example 文件并输入你的业务 key/ID/配置:
librechat-search-mcp/librechat.yaml.example:把mcpSettings和mcpServers合并到现有的librechat.yaml中。注意:{{LIBRECHAT_USER_ID}}之类 MCP header 参数映射得严格按照说明配置;LibreChat 会在每个请求时替换它,这也正是安全模型和过滤逻辑的其中一部分。建议:如果你认同我给上面说过的动机这么部署,可以在
librechat.yaml中禁用 memory agent(除非未来 LibreChat 的实现会改动这个行为——即这个改进只会把你的 token 成本跨对话污染降到最低)。注意 最近 LibreChat 的改动把记忆工具的可用行为改为了 gating ——
endpoints.agents.capabilities中若工程师需要,就加入memory.agent。假如你需要:“agent 能够按需写入记忆”,你在那放"memory"即可。
librechat-search-mcp/docker-compose.override.yml.example:把librechat-search-mcp服务合成现有的 Compose 项目里。它是纯内部服务:expose: 8000,无ports,加入 Compose 默认网络。librechat-search-mcp/.env.example:将环境变量添加到你主.env的 key 中,替换给你的自占位符。我会把它们直接补在现有Search小节的下面方便一点。
MCP URL 是 http://librechat-search-mcp:8000/mcp。暴露给 MCP 的 server 名字仍然是 chat-search 有助于客户端去查看它是谁。如果 LibreChat 本身阻止私有 MCP 目标,请保留 librechat.yaml.example 里的 allowedAddresses。注意:非空域白名单会影响随身携带其他 MCP servers,所以把这行添加到意图中。
MEILI_HOST_PORT=7700 是周围 LibreChat 部署支持的主机/Compose 桥接口变量。要记住 MCP 容器自身必须用 Compose 服务地址 http://meilisearch:${MEILI_HOST_PORT}(示例 override 中会构造该值);LibreChat 自带的 MEILI_HOST=http://0.0.0.0:7700 是另一个面向主机的设置,别随手用它来替换。
请找到你的(管理员)User ID 以及显式管理
MEILI_MCP_ADMINS 的值可以从下面几种方法中的任意一种取到(按执行方便程度)顺列:
在你的浏览器 UI 中:
打开检查器/开发者工具(Ctrl+Shift+I),选择 Network 标签页;
在 Chat History 对话列表中,选择一个之前的历史对话(你可能需要选择一个当前登录在浏览器缓存中的较旧对话);
Network 标签页中记录的第一个 API 调用会在其
Response子标签页中包含 conversations 元数据,其中包括:user—— 这个值就是 *你的 (并且这个字段用于在服务器中过滤搜索,或作为admin_工具的target-user参数)—— 复制此值(并让你选定的其他管理员以相同方式加减)到.env文件的MEILI_MCP_ADMINS[仅用逗号分隔列表];conversationId—— 这与search_MCP 工具参数中使用的 ID 是同一个,注意 DES 与对话 URL 中的 ID 一致,例如https://localhost:3080/c/{conversationId};
与这一项目功能相关的值得注意之处:第 3 个 API 调用包含此对话的消息列表,其结构与 Meilisearch 用来索引它们的结构类似;本项目使用了下列 key:
conversationId—— 本项目默认将其用于排除当前聊天的搜索结果,或用于定向消息过滤sender—— “User” 或智能体的显示名称text—— 消息的类型对未来功能的研究方向:
endpoint(或范围更窄的model)可以用作过滤条件,配合MEILI_MCP_CONSTRAIN_ENDPOINT=true设置(如果私有模型/智能体与公共 provider 模型/智能体分离)去禁止跨端点的消息搜索访问parentMessageId已经通过 LibreChat 的{{LIBRECHAT_BODY_PARENTMESSAGEID}}动态变量集成在 MCP transport 的 header 中,作为工具使用期间的一种结果过滤方式;我计划重新检查 search indexes,将其作为一种可能的、能在搜索命中消息前后优先返回排序 buffer、以确定性顺序输出结果、并对消息链绘图的方式content包含工具调用时依赖的思维/推理过程(我不记得在索引内容中见过它,也许是出于合理考虑:搜索消息历史的用户很可能希望看到标题或消息文本的命中,而不是文件/agent 内部细节)attachments包含工具调用结果(可能也包含 RAG / 上传文件的 content)—— 与content类似,我觉得它未被索引createdAt可以用作确定的时序或时间过滤键(Meilisearch 已经按时间顺序返回命中,但相关性评分也可能影响最终顺序)—— 这也许还可以通过 Mein索引文档元数据(索引创建/更新的时间戳)访问(虽然值略有不同),但任何一次 reindex 都会使其失去所有价值。
LibreChat 容器日志(
docker compose logs api)——立即在你(作为管理员)从 LibreChat UI 操作之后查看(警惕:如果你有很多并发用户把日志混在一起看,可能会导致误判, 因为这并不显示用户名)在 Mongo Express 中查看
users表(如果你已单独配置 Mongo Express;如果是这样,操作其 Web UI 在查看时会更方便)在 MongoDB 中查看
users表(以下命令对 bash 或 PowerShell 一致;请从 LibreChat 目录或docker-compose.yml所在的位置运行):
# open a shell terminal within the MongoDB container - this assumes the default LibreChat service name `mongodb`:
docker compose exec mongodb sh
# open a database shell terminal within the container's shell:
mongosh
# switch to the database used by LibreChat (see all with `show databases`):
use LibreChat
# display target user by `role` attribute == "ADMIN" (LibreChat also stores `email` and `username` which may be present/null depending on registration method):
db.users.find({role: "ADMIN"}).forEach(printjson)
# Alternatively, display the entire users collection (be careful with this if you have many users):
db.users.find().forEach(printjson)
# the hash string in the first key of returned JSONs is the `user` ID - assuming you've found yourself/chosen admins, grab just this hash value from the `ObjectId` construct:
# {
# _id: ObjectId('derp7bfe19e9268da678derp'), #### <- in this dummy example, derp7bfe19e9268da678derp is my user ID to add to MEILI_MCP_ADMINS ####
# name: 'krahnik blis',
# username: 'krahnik',
# email: 'krahnik@emailmenot.derp',
# ...
# quit the mongosh terminal
quit
# exit the mongodb container shell terminal
exit为 MCP 服务器创建只读许可密钥
不要使用 LibreChat 的 MEILI_MASTER_KEY 作为你的 MEILI_MCP_KEY!
该仓库包含跨平台的的帮助脚本,用于以一条命令生成和验证 API 密钥。
它会通过访问 meilisearch 容器(所以它必须处于运行状态)来生成一个带权限的密钥,
默认打印该密钥,也可以设置写入本地文件,并且绝不修改主 LibreChat .env。
保存文件是可选的,如果文件已存在,除非提供了 --force/-Force,否则会拒绝覆盖;生成的 *.local.env 文件已被 git 忽略,并在受支持的平台上获得限制性权限。
在你将本仓库 git clone 到 LibreChat 目录后,从 LibreChat 目录中运行:
bash:
# ensure the script is executable:
chmod +x librechat-search-mcp/scripts/generate-restricted-key.sh
# run the script in terminal mode:
./librechat-search-mcp/scripts/generate-restricted-key.sh
# OR, run it in file-output mode:
./librechat-search-mcp/scripts/generate-restricted-key.sh --output .librechat-search-mcp.local.envPowerShell:
# run the script in terminal mode:
powershell.exe -ExecutionPolicy Bypass -File .\librechat-search-mcp\scripts\generate-restricted-key.ps1
# OR, run it in file-output mode:
powershell.exe -ExecutionPolicy Bypass -File .\librechat-search-mcp\scripts\generate-restricted-key.ps1 -Output .librechat-search-mcp.local.env脚本运行输出会包含对端点权限的验证测试,以及一个虚拟的删除操作探测,用来确认数据库的只读权限; 最后输出只读许可密钥,或者写到你指定的文件。
脚本中包含了我在调试时使用的检查和信息,留给以后重新陷入困惑时查阅用,你也可以类似于这样:
[info] Working directory: /path/to/LibreChat
[info] Environment file: .env
[info] Meilisearch container: meilisearch
[info] Messages index: messages
[info] Conversations index: convos
[warning] MEILI_HOST used 0.0.0.0; using loopback for in-container requests.
[info] MEILI_HOST from .env: http://0.0.0.0:7700
[info] API URL used inside chat-meilisearch: http://127.0.0.1:7700
[info] MEILI_MASTER_KEY length: 32
[info] MEILI_MASTER_KEY SHA-256: d3907119a65e489d0202derp0ac65216a44derpb43bd8be71b7dderpb158ac67
[info] Testing Meilisearch connectivity from inside the container.
PASS /health -> HTTP 200
[info] Testing the MEILI_MASTER_KEY read from .env.
PASS .env master key accepted by /version
[info] Key contract payload: {"description":"LibreChat MCP search and read-only diagnostics","actions":["search","stats.get","metrics.get","indexes.get","settings.get","version"],"indexes":["messages","convos"],"expiresAt":null}
[info] Creating restricted key in chat-meilisearch.
[info] Restricted key created successfully.
[info] Generated key length: 64
[info] Validating read-only key contract.
PASS /health -> HTTP 200
PASS /version -> HTTP 200
PASS /stats -> HTTP 200
FAIL /metrics -> HTTP 400
{"message":"Getting metrics requires enabling the `metrics` experimental feature. See https://github.com/meilisearch/product/discussions/625","code":"feature_not_enabled","type":"invalid_request","link":"https://docs.meilisearch.com/errors#feature_not_enabled"}
PASS /indexes -> HTTP 200
PASS /indexes/messages/settings -> HTTP 200
PASS /indexes/convos/settings -> HTTP 200
[info] Testing that document deletion is rejected.
PASS DELETE /indexes/messages/documents/__mcp_read_only_probe__ -> HTTP 403
Restricted key was created, but one or more validation checks failed:
- /metrics returned HTTP 400
The key will still be returned below. Do not deploy it until the failures are understood.
394ederp18e6299f7fddderpbb485b77be7bb1d0906b29ade8derpebaf65de43^ 在这个虚构示例中,394ederp18e6299f7fddderpbb485b77be7bb1d0906b29ade8derpebaf65de43 是应该作为 LibreChat .env 文件中的 MEILI_MCP_KEY 来使用的密钥。
预期 FAIL 消息
目前,/metrics 端点预期会失败,因为它是 LibreChat 所用的 Meilisearch 版本中的一个试验性功能;我正在研究其潜在用途,如果有任何有价值的成果,我会更新此仓库,提供启用说明/操作脚本。这意味着 get_index_metrics 工具会返回上述示例输出中的错误,除非你自己启用该功能。
以下是 generate-restricted-key 中脚本流程对应的手动方法,以备你在自定义实现中遇到错误,或想更全面地了解这些脚本时使用:
为这个服务创建一个专用的只读 key,其 action 契约必须包含:
searchstats.getmetrics.getindexes.getsettings.getversion
将 key 的范围限定到已配置的那两个索引(messages 和 convos,或你配置的名字)。全局健康端点是单独检查的,不需要可写角色。只有当你需要一个永不盼期的运维 key 时,才设置 expiresAt 为 null。同时,只把返回的 key 存放到 MEILI_MCP_KEY 中。
在 chat-meilisearch(docker exec) / meilisearch(docker compose exec) 容器的终端中创建密钥,而不能在 MCP 容器中。下面的 master key 只是命令历史的占位符,绝不补漏到提示、日志,或本仓库中:
curl -fsS -X POST "http://127.0.0.1:7700/keys" \
-H "Authorization: Bearer $MEILI_MASTER_KEY" \
-H "Content-Type: application/json" \
--data '{"description":"LibreChat MCP search and read-only diagnostics","actions":["search","stats.get","metrics.get","indexes.get","settings.get","version"],"indexes":["messages","convos"],"expiresAt":null}'不要添加 documents.*、indexes.create、indexes.delete 写入权限、settings.* 写入权限、keys.*、tasks.cancel,或 *。永远不要让 MEILI_MCP_KEY 等于 MEILI_MASTER_KEY。
在部署密钥之前,用下面的只读探针验证契约。它们都必须返回 HTTP 200(JSON 内容被逐条丢弃仅保留响应状态):
auth=(-H "Authorization: Bearer $MEILI_MCP_KEY" -H "Accept: application/json")
for path in /health /version /stats /metrics /indexes /indexes/messages/settings /indexes/convos/settings; do
code=$(curl -sS -o /dev/null -w '%{http_code}' "${auth[@]}" "http://127.0.0.1:7700/$path")
test "$code" = 200 || { printf 'unexpected %s: HTTP %s\n' "$path" "$code" >&2; exit 1; }
done然后再验证一个无害的删除探测会被拒绝。使用一个不存在而来的 sentinel 文档 ID;用真实文档 ID 来替换它:
code=$(curl -sS -o /dev/null -w '%{http_code}' -X DELETE \
"${auth[@]}" "http://127.0.0.1:7700/indexes/messages/documents/__mcp_read_only_probe__")
case "$code" in 401|403) ;; *) printf 'write permission was not rejected: HTTP %s\n' "$code" >&2; exit 1;; esacMCP 搜索和诊断路径会使用同一个语义。如果任一只读探测返回 401/403,请修正密钥的 action 契约或索引范围;请不要用 master key,否则会更棘手,直到写操作被拒绝。
密钥过多及删除
注意:多次运行上述脚本/命令会在 Meilisearch 多处创建多个孤儿密钥。所以,我的建议是不要这样做。但如果你真执行到了那一步,
要么在容器内设置一个包含 master key 的环境变量,要么把下面这些
$MEILI_MASTER_KEY替换成你的真实 key在主要的 Meilisearch 容器的终端里,先列出所有密钥:
curl -sS -H "Authorization: Bearer $MEILI_MASTER_KEY" "http://127.0.0.1:7700/keys"找到本项目创建脚本生成的 key,它们的
description会标注为 “LibreChat MCP search and read-only diagnostics”选出那些不是你要保留的 key,记录它们各自的
uid对于每一个要删除的 key,执行(将
KEY_UID替换为你真实的值):curl -sS -X DELETE -H "Authorization: Bearer $MEILI_MASTER_KEY" "http://127.0.0.1:7700/keys/KEY_UID"
完整配置命令序列
请以下这些命令按交互方式递进逐步执行(我们所说 Windows 用户可以跳过 cat/nano 那类麻烦,直接用记事本/IDE):
cd LibreChat
# this creates the folder librechat-search-mcp WITHIN the LibreChat Compose scope:
git clone https://github.com/krahnikblis/librechat-search-mcp.git
# assuming the baseline LibreChat Compose services are already running, this creates & tests the restricted API key to set manually into the LibreChat .env MEILI_MCP_KEY:
# see above/README page for details and/or PowerShell equivalent commands
# either write to a local file:
./librechat-search-mcp/scripts/generate-restricted-key.sh --output .librechat-search-mcp.local.env
# OR print to the terminal:
./librechat-search-mcp/scripts/generate-restricted-key.sh
# print the example to copy as template:
cat librechat-search-mcp/.env.example
# copy or merge the example MEILI_MCP_ variables, including the key generated in the prior step into .env:
nano .env
# print the example to copy as template:
cat librechat-search-mcp/docker-compose.override.yml.example
# copy or merge the example configurations from the example into docker-compose.override.yml
nano docker-compose.override.yml
# print the example to copy as template:
cat librechat-search-mcp/librechat.yaml.example
# copy or merge the MCP [and optional agent capabilities and memory agent changes] configurations into librechat.yaml:
nano librechat.yaml
# validate config:
docker compose config
# stop existing services to recreate the LibreChat container with the MCP settings:
docker compose down
# build the image:
docker compose build librechat-search-mcp
# start all Compose services together:
docker compose up -d
# check logs for the new service:
docker compose logs --tail=100 librechat-search-mcp如果一切就绪,那么此 MCP 就会出现在你的 LibreChat UI 中!
环境变量和索引契约
必需项:
MEILI_MCP_KEY=<restricted-search-key>
MEILI_MCP_ADMINS=<admin,list>.env 中的重要值:
MEILI_HOST_PORT=7700
MEILI_MCP_PORT=8000
MEILI_MCP_MESSAGES_INDEX=messages
MEILI_MCP_CONVOS_INDEX=convos
MEILI_MCP_DEFAULT_LIMIT=5
MEILI_MCP_MAX_LIMIT=25
MEILI_MCP_ADMIN_SCOPE_ALL_USERS=false
MEILI_MCP_LOG_HOST_DIR=<local/log/path>两个索引都必须包含一个 user 可过滤属性(举例,这是 LibreChat 设计所提供)。
LibreChat 创建的 messages 索引不带有可过滤的 conversationId 属性;
在返回调用方之前,此属性和 MCP 搜索工具的其他参数在服务端负责处理。
日志挂载与持久化
容器会以结构化 JSON 行日志写入 /var/log/librechat-search-mcp。
Compose 示例将该目录绑定到 ${MEILI_MCP_LOG_HOST_DIR};
默认值是相对于项目 Compose 项目目录下 libreqemplate – ./librechat-search-mcp/logs。日志文件命名为 librechat-search-mcp-YYYY-MM-DD.log,因此重建容器不会删除已有的主机端日志。将这个日志目录保密,并按部署策略进行备份或轮转。如果想改用父级项目的常用日志目录,请在本地 .env 中设置 MEILI_MCP_LOG_HOST_DIR=./logs;`并将已写入日志或生成的文件加入 gitignore。
在 librechat-search-mcp 容器中运行只读契约检查:
bash/PowerShell:
# The image's WORKDIR is /app and Compose injects MEILI_HOST plus the
# restricted MEILI_MCP_KEY into the service.
# the script was copied into the container as part of image build
docker compose exec -T -w /app librechat-search-mcp python scripts/check_index_contract.py该脚本会被复制到镜像内的 /app/scripts/check_index_contract.py。
它会检查健康检查、索引名称、主键、过滤器印发能力和可排序字段,而不会修改设置或打印密钥。退出状态 0 且 JSON "status": "pass" 表示契约通过;非零退出状态表示报告的一个或多个健康/索引/设置/必需过滤器检查失败。这是一个诊断脚本,而不是 MCP 就绪探测。/health 仅仅确认 MCP 进程是否存活。
调用方提示和预期行为
完成配置并且容器正在运行后,请(例如,在 UI 的 MCP 侧边、Agent Builder 和/或对话框的 MCP Servers 下拉列表)新开一个 LibreChat 对话,以便模型发现最新的工具列表。
工具描述作为它们的引导,鼓励标准搜索工具主动使用 agentic 调用,而 admin_ 变体则给出 “用户先调用才使用” 的指令。我未来更新时可能根据体验调整这些提示语——我已经看到了一些有意思的主动用法,但有时候是不必要 / 请求过度的……
注意:较小的本地区模型可能需要在提示中显式提到工具名。
普通搜索 —— 显式指令:
Use search_conversations with query "deployment" and limit 3. Return only conversationId, title, and tags.Use search_messages with query "deployment" and limit 3. Return only messageId, conversationId, sender, and text.主动使用标准搜索的预期:
Hey remember that time we went wild designing a giant robotic grackle? I have some ideas about how to combine it with the ornithopter we discussed last week...该 agent 应该主动执行一个类似搜索“grackle 蝙蝠”效果的搜索词,并能观察到来自多个会话的消息,命中对应的消息。
预期搜索 agent 架构:
这个工具本身附带基本的工具说明,但真正重点在于构建专门的 agent 和/或一个有参考价值的 SKILL.md ,以形成一种 能记忆的 memory-like 行为。不仅仅因为它返回的是完整消息,查询结果仍可能造成不小 token 开销,因此,一个基于更便宜模型、并被指示在相互关联的会话间递归追踪同一主题、最后返回详细摘要/综合结论的子 agent,很可能就是我会在自己团队的默认工作 agent 中使用的方式。
目标性 admin 审计(仅从 “允许列表” 账户使用):
(End)
我的待办清单上有一件事是研究 LibreChat 的 PeoplePicker API,看看它在 Compose 网络中如何暴露、是否已经暴露 —— 理想情况下,管理员可以用句柄或名字来指代某个用户;如果启用了 PeoplePicker,agent 就可以查出内部 ID(或者干脆绕过 agent,在服务器内部完成带定向过滤/报错的查找,比如给出 "2 'Sally's found: did you mean Sally X. or Sally Y.?" 这样的提示),并且不向 agent 暴露邮箱或全名。
Use admin_search_messages for target user "<target-user-id>" with query "deployment" and limit 3.预期的管理员范围(调试、提示词/对话优化、集体关注)
What are our team members saying overall about our company's brand presense in the FIFA World Cup?Let's review <target-user-id>'s conversation <conversationId> - what initial prompt and context would have elicited the final answer more directly?边界检查:
Try to search another user's messages by supplying a user argument and a raw filter. Do not bypass the tool schema; report whether the request was rejected and do not return cross-user results.Find messages before and after this hit using createdAt, reconstruct surrounding messages through MongoDB, and sort by timestamp.后者不支持:本项目不进行排序、不提供按时间先后检索、MongoDB/API 查找、上下文消息重建或任意排序。发送者和对话过滤属于受限的后置过滤,因此返回结果少于请求数量是合法的,并保留 Meilisearch 原始的匹配顺序。
验证
本地检查(在此项目位于 LibreChat 中的文件夹内运行):
python -m pytest tests/test_monitoring.py tests/test_m2_contract.py tests/test_m2_authorization.py tests/test_m1_search.py tests/test_server.py -q
python -m compileall -q src scripts tests
git diff --check部署检查仍需要一套运行中的 LibreChat/Meilisearch 环境:请验证新会话中的工具发现、User-Id 请求头、受限密钥权限、索引契约、不向宿主机公布端口,以及对两个用户并发请求。不要将本地单元测试作为实际调用行为的证据。
部署与故障排查
参阅
docs/deployment.md了解支持的 Docker Compose 边界、安全配置顺序、服务身份,以及container_name的取舍。参阅
docs/troubleshooting.md了解 Compose、密钥生成、网络、MCP 发现、索引与日志等常见失败。启用本服务前请先参阅
SECURITY.md。其中涵盖索引内容、AI 提供方暴露面、身份与管理范围、日志/留存、受限密钥、信任边界,以及本服务不做哪些保证。
开发
参阅
docs/tool-descriptions.md了解面向 agent 的工具契约。参阅 [
ATTRIBUTION.md] 文件了解上游来源与许可信息。开发、计划、审计和内部决策记录有意保留在
workspace/project-context/librechat-search-mcp/development-records/,与
我的意思是,如果谁想参与贡献,随手开个 discussion 或 issue、或者随便什么都行;我可以考虑加一个 Contributing 部分,不过得等我真的弄清 PR 是怎么运作的再说……但说实话,这本来就只是我的一个业余爱好项目,我也知道它对我的工作也同样有价值,而把我居家和办公连接起来的最便捷通道,就是通过 GitHub 将它发布出去。也就是说,我喜欢做东西、也不怕出问题,只是我没有承诺要去关心其他人的 issue,而且我很可能优先去搞那些别的选项没有的功能,或者是补上某个空白处的功能。
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables semantic search across conversation archives via MCP, allowing AI clients to retrieve relevant past conversations using vector embeddings and text fallback.04ISC
- AlicenseNot gradedqualityFmaintenancePersistent, searchable memory for AI agents. Enables agents to recover context after compaction by searching indexed conversations, emails, and files via MCP tools.1MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to perform web searches with full content retrieval and multi-engine provenance, including trust scoring and local corpus persistence, via MCP integration.42Apache 2.0
- AlicenseNot gradedqualityCmaintenanceLocal context management, search engine, and memory for agentic AI via MCP, enabling efficient context retrieval and storage.541MIT
Related MCP Connectors
Search your AI chat history (ChatGPT, Claude, Codex) from any MCP client. Remote, private, read-only
Multi-engine search for AI agents. Trust scoring, local corpus, MCP-native. Self-hostable, BYOK.
Persistent memory and knowledge management for AI agents with semantic search and 50+ tools.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/krahnikblis/librechat-search-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server