Skip to main content
Glama
krahnikblis

librechat-search-mcp

by krahnikblis

Объедините секции mcpSettings и mcpServers внутри существующего файла librechat.yaml. Обратите внимание, что сопоставления параметров заголовков MCP, такие как {{LIBRECHAT_USER_ID}}, должны быть настроены точно в виде, кокой предстакт.Posposy. LibreChat подставляет эти параметры в каждом запросе, и они являются частью модели безопасности и фильтрации.

Рекомендуется для до настройки LibreChat: в разделе memory agent можно отключить до появления будущих версий, где официальному исправлению или выгоде по токенам удалённого поведения. Это лучше в соответствии с мотивацией выше.

Примечание. Последние изменения LibreChat изменяют поведение memory инструмента, требующие отдельно указать memory в endpoints.agents.capabilities. Чтобы агент мог сохранять память по запросу, добавьте там "memory".

  1. Откройте инспектор (инструменты разработчика) (ctrl+shift+i) и выберите вкладку Network;

  2. из списка бесед «Chat History» выберите предыдущую беседу (возможно, понадобится выбрать более старую, которой ещё нет в кэше браузера);

  3. первый вызов API, записанный на вкладке Network, загружает данные заголовка беседы в свою подвкладку Response, которые включают:

    • user — это значение — ваш ID (и это поле используется для фильтрации поиска на сервере, а также как параметр target-user для инструментов admin_) — скопируйте его (и попросите других выбранных вами администраторов/правополучателей предоставить вам то же самое) в файл .env как MEILI_MCP_ADMINS [разделяйте элементы списка только запятыми];

    • conversationId — это тот же идентификатор, который используется в параметрах MCP-инструментов search_, и примечательно, что он совпадает с тем, что находится в URL беседы: http://localhost:3080/c/{conversationId};

  4. примечательно относительно функциональности этого проекта: третий API-вызов содержит список сообщений этой беседы, по структуре похожий на то, как Meilisearch его индексирует; этот проект использует следующие ключи:

    • conversationId — используется этим проектом для исключения результатов поиска из текущего чата по умолчанию или для адресной фильтрации сообщений;

    • sender — «User» или отображаемое имя агента;

    • text — содержимое сообщения;

    • будущие направления для исследовательской работы, касающихся желаемого функционала:

      • endpoint (или, в более точечном смысле, model) может использоваться как фильтр в сочетании с настройкой MEILI_MCP_CONSTRAIN_ENDPOINT=true (если приватные модели/агенты отделены от публичных моделей) для запрета доступа к поиску сообщений между разными эндпоинтами;

      • parentMessageId уже интегрирован как фильтр результатов при использовании инструментов с помощью динамической переменной {{LIBRECHAT_BODY_PARENTMESSAGEID}} LibreChat в заголовке MCP-транспорта; я планирую пересмотреть индексы поиска по этому ключу как потенциальный метод для целевых буферов «до/после» вокруг найденных сообщений, детерминированного упорядочивания результатов и построения графов цепочек сообщений;

      • content содержит мысли/рассуждения вызовов инструментов (не припомню, чтобы видел это в индексируемом содержимом, вероятно, по вполне оправданной причине — пользователь, ищущий по истории переписки, ожидает совпадений по заголовку или тексту сообщения, а не по внутренностям файлов/действий агента);

      • attachments содержит результаты вызовов инструментов (и, возможно, содержимое RAG и/или загруженных файлов) — как и content, не ожидаю, что это индексируется;

      • createdAt можно было бы использовать для детерминированной временной сортировки или даже в качестве ключа фильтрации (Meili уже возвращает результаты в видимом временном порядке, но на него может влиять также релевантность) — возможно, к этому же можно обращаться (хотя и с несколько иным значением) через метаданные индекса Meilisearch (время создания/обновления индекса), но при любой переиндексации эта информация может полностью потерять ценность.

  • Логи контейнера LibreChat (docker compose logs api) сразу после того, как вы (как администратор) выполните действие в интерфейсе LibreChat (ОСТОРОЖНО: не советую, если у вас много параллельных пользователей — логи не содержат имён, ваши действия легко перепутать);

  • просмотр таблицы users в Mongo Express (если вы настроили егоuresOaturally, в его веб-интерфейсе немного проще);

  • просмотр таблицы users в MongoDB (команды одни и те же при работе в 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 (поэтому он должен быть запущен), формируют ключ с правами, по умолчанию печатают ключ либо, по желанию, записывают его в локальный файл и никогда не изменяют основной .env LibreChat. Способ с выводом в файл — необязательный; он отклоняется, если файл уже существует и не указан --force/-Force; сгенерированные файлы *.local.env игнорируются в git и получают ограничительные права доступа везде, где платформа это поддерживает.

Запустите из каталога LibreChat после того, как вы git clone сделали клонирование этого репозитория в его:

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.env

PowerShell:

# 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

Вывод скрипта содержит проверки валидности разрешений эндпоинтов и фиктивную delete-пробу, чтобы убедиться в правах только на чтение; ключ с правами только на чтение печатается в конце либо записывается в выбранный вами файл.

В скрипте остались проверки и сообщения, которые я использовал при отладке; я оставил их для будущего душевного спокойствия, и вам она может пригодиться точно так же:

[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 — это ключ, который следует указать как MEILI_MCP_KEY в файле .env LibreChat.

Ожидаемое сообщение FAIL

В настоящее время эндпоинт /metrics, как ожидается, будет возвращать ошибку, потому что это экспериментальная функция в версии Meilisearch, которую использует LibreChat; я изучаю её потенциальную пользу и, если будут результаты, дополню репозиторий инструкциями/скриптами по включению. Это значит, что инструмент get_index_metrics будет возврат ошибку, показанную в примере вывода скрипта выше, до тех пор, пока/если вы сами не включите эту функцию.

Ниже — ручной способ выполнения того, что описан в скриптах generate-restricted-key, на случай кастомизированной реализации или возникновения ошибок (либо просмотрите сами скрипты во всей их тщательной красе):

Создайте один отдельный ключ только для чтения для этого сервиса. Его точный контракт действий:

  • search

  • stats.get

  • metrics.get

  • indexes.get

  • settings.get

  • version

Ограничьте ключ двумя настроенными индексами (messages и convos или вашими собственными именами). Общий эндпоинт health проверяется отдельно и не требует роли с правами на запись. Устанавливайте expiresAt в null только если намеренно нужен ключ без срока действия и храните вернувшийся ключ в MEILI_MCP_KEY.

Создайте ключ из терминала контейнере chat-meilisearch (docker exec)/meilisearch (docker compose exec), а НЕ из MCP-контейнера. Приведённый ниже мастер-ключ — это заполнитель в истории команд и его нельзя вставлять в промпты, логи или в этот репозиторий:

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

Затем проверьте, что безобидная delete-проба отвергается. Используйте sentinel-идентификатор документа, которого точно нет; не подставляйте вместо него настоящий идентификатор документа:

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;; esac

Это же ключ используется и в поисковых, и диагностических путях MCP. При появлении ошибки 401/403 у любой проверки только на чтение исправьте контракт действий ключа или область индексов; не подменяйте ключа мастер-ключом и не расширяйте права, пока записи не ста отвергаться.

Переизбыток ключей и их удаление

ОСТОРОЖНО: многократный запуск указанных выше скриптов/команд создаёт в MeiliSearch несколько осиротевших ключей. Не делать этого и не рекомендую. Но если вы всё же наделали, то

  • Либо установите переменную окружения с мастером-ключом в контейнере, либо замените в приведённых ниже командах $MEILI_MASTER_KEY своим реальным ключом

  • Из терминала в основном контейнере Meilisearch сначала выведите список всех ключей: curl -sS -H "Authorization: Bearer $MEILI_MASTER_KEY" "http://127.0.0.1:7700/keys"

  • Найдите ключи, которым создающиеся скриптом этого проекта, у них есть description «LibreChat MCP search and read-only diagnostics»

  • Выберите те, что не являются ключом, который вы хотели оставить, и заведите их uid

  • Для каждого удаляемого ключа выполните (замените 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!

Окружение и контракт индексов

Обязательные:

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>

Оба индEKS'а должны содержать фильтруемый атрибут user (в LibreChat уже так есть). Созданный LibreChat индекс messages не имеет фильтруемой conversationId; это и другие параметров для MCP-инструментов поиска обрабатываются на стороне сервера перед возвратом вызывающему.

Монтирование логов и постоянство

Контейнер записывает структурированные журналы (JSON-lines) в /var/log/librechat-search-mcp. В примере Compose это каталог привязывается к ${MEILI_MCP_LOG_HOST_DIR}; по умолчанию это ./librechat-search-mcp/logs относительно родительского Compose-проекта LibreChat. Файлы логов называются librechat-search-mcp-YYYY-MM-DD.log, поэтому при перезапуске контейнера существующие логи на хост-стороне не удаляются. Держите этот каталог на хосте закрытым и делавбэкап либо ротируйте по правилам вашего развёртывания. Чтобы вместо этого использовать обычный каталог логов исходного проекта, задайте MEILI_MCP_LOG_HOST_DIR=./logs в локальной .env; не коммитьте заполненный файл или сгенерированные логи.

Запустите проверку контракта только на чтение в контейнере 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. Он проверяет health, имена индексов, первичные ключи, фильтруемость и сортируемые атрибуты, не изменяя настройки и не печатая ключ. Статус выхода 0 и JSON "status": "pass" говорят о том, что контракт соблюдён; ненулевой статус выхода означает: здоровье, индексы, настройки или проверка требуемого фильтра не пройдены. Это диагностика, а не индикатор готовности MCP. /health подтверждает только, что процесс MCP жив.

Related MCP server: knowledge-base

Промпты вызывающего и ожидаемое поведение

Начните новую беседу в LibreChat после настройки и запуска контейнеров (например, в боковой панели MCP в интерфейсе, в Agent Builder и/или в выпадающем списке MCP Servers в поле чата), чтобы модель обнаружила нктуальный список инструментов.

Описание инструментов написаны так, чтобы поощрять проактивное агентное использование для стандартных поисковых инструментов, а варианты 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...

Агент должен проактивно выполнить поиск с запросом, похожим на «nn"», и вы должны увидеть подходящие сообщения сразу из нескольких бесед.

Целевой дизайн агента для поиска:

Этот инструмент поставляется с обычной настройкой и описаниями, но настоящее веселье начинается при создании профильного агента и/или информативного SKILL.md для формировании поведения, похожего на память. Поскольку результаты этих инструментов — полные сообщения, затраты токенов могут оставаться существенными, поэтому субагент на более дешёвой модели, которому задаётся инструкция рекурсивно трассировать темы по смежным беседам и возвращать детализированную сводку/синтез — это, скорее всего, и есть способ, как я буду разворачивать это для своей команды в их агенте по умолчанию.

Целевой администативный аудит (только с аккаунта из разрешённого списка):

В моем списке дел — изучить API PeoplePicker из LibreChat и выяснить, как/доступен ли он в сети Compose. В идеале администратор мог бы указать пользователя по хэндлу или имени, и если PeoplePicker включен, агент мог бы выполнить поиск внутреннего идентификатора (или, возможно, в обход агента выполнять на сервере целевую фильтрацию/выдачу ошибок, например: «Найдено двое „Sally“: вы имели в виду Sally X. или Sally Y.?», не раскрывая агенту адрес электронной почты или полное имя)...

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 перед включением сервиса. В нем описываются индексируемый контент, раскрытие данных ИИ-провайдерам, идентичность и область администратора, логи/хранение, ограниченные ключи, границы доверия и то, что этот проект не гарантирует.

Разработка

  • См. docs/tool-descriptions.md — контракт инструментов, видимый агенту.

  • См. ATTRIBUTION.md — происхождение вышестоящих проектов и лицензирование.

  • Записи о разработке, планировании, аудите и внутренних решениях намеренно хранятся вне производственного репозитория в workspace/project-context/librechat-search-mcp/development-records/.

Если кто-то хочет что-то добавить — открывайте обсуждение или issue или что угодно; я бы мог подумать о добавлении раздела Contributing и разобраться, как работают PR... но на самом деле это просто мой хобби-проект, который, я знаю, пригодится мне и на работе, а самый простой путь отсюда туда — публикация на GitHub. То есть мне нравится создавать вещи и решать задачи, но я не обещаю уделять внимание чужим issue и, скорее всего, буду в первую очередь делать то, что либо добавляет отличные возможности, либо закрывает пробелы.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    F
    maintenance
    Persistent, searchable memory for AI agents. Enables agents to recover context after compaction by searching indexed conversations, emails, and files via MCP tools.
    1
    MIT
  • F
    license
    Not graded
    quality
    F
    maintenance
    Enables AI coding agents to persistently store and retrieve conversation history with hybrid semantic and keyword search, cross-encoder reranking, session filtering, and archiving through MCP tools.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to search and read archived Telegram and WhatsApp messages and attachments through a Streamable HTTP MCP endpoint, with scoped credentials, per-account/chat permissions, full-text search, and extracted file text.
    MIT