librechat-search-mcp
librechat-search-mcp
이 프로젝트는 LibreChat의 Search messages 기능을 MCP 도구로 확장하여 선제적 또는 필요 시(on-demand) 사용할 수 있는 "전체 메시지 기억(all-message memory)"을 가능하게 합니다.
Related MCP server: Claw Recall
요약
LibreChat이 인덱스한 메시지 기록을 검색하기 위해 범용 meilisearch-mcp를 기반으로 한 제한된 LibreChat 전용 MCP 서버입니다. 기본 memory 기능/능력을 보강하면서, 선택적 LibreChat memory.agent를 비활성화할 때 비용과 컨텍스트 손실을 줄이기 위한 것입니다. 전용 컨테이너에서 LibreChat Docker Compose 네트워크에 호스팅되는 Streamable HTTP를 사용하며(즉, Docker가 아닌 호스팅/배포 구성에서는 구현되지 않습니다!), LibreChat의 요청별 User-Id 헤더에서 사용자를 파악하여 서버 측에서 사용자 필터를 적용합니다. 또한 검색 후(post-search) 필터를 적용하여 에이전트에 반환하기 전에 결과를 제한합니다. 의도적으로 이러한 기능은 이미 해당 권한이 있는 사용자와 관리자의 범위로 제한되도록 설계되었으며, 개인정보 보호가 문제가 될 수 있는 잠재적 위험을 인지하고 명시적으로 적시하면서, 주로 "프라이버시를 기대할 수 없다(no expectation of privacy)"는 점이 사용자에게 명확히 전달되는 시나리오를 염두에 두고 설계되었습니다.
동기
LibreChat의 내장 메모리 기능은 메모장 스타일의 컨텍스트 기억에는 나쁘지 않지만, 몇 가지 비용과 부작용이 있습니다:
작은 모델(예:
Gemma-4-12B)은 새 채팅에서 해당 메모리를 중요한 프롬프트 컨텍스트로 해석하여 다른 대화의 내용이 이상하게 끌려오는 결과를 낳습니다.기본 LibreChat 자동 메모리 에이전트는 메모리를 이어붙이거나 병합하지 않고 완전히 덮어써서, 의도적으로 기록한 메모리가 유실됩니다.
자동 메모리 에이전트는 모든 사용자 메시지 턴마다 실행되어 입력 토큰 비용이 두 배가 됩니다 (물론 메모리 에이전트에는 더 값싼 모델을 쓰고 계시겠지만요...).
캐시 쓰기 비용 - 제가 결국 이 프로젝트를 만들게 된 트리거 : 메모리 에이전트가 메모리를 수정할 때마다 전체 대화 캐시가 (OpenAI 캐싱 사용 시) 다시 쓰이는데, 이유는 메모리가 스토리(thread) 기록에서 앞부분 오브젝트 사이에 삽입되기 때문입니다.
GPT-5.6-Terra 대화 몇 개는 각각 $3 이상이 들었고, 사용량을 되새겨보니 가장 큰 원인은 불필요하게 반복된 **캐시 쓰기(cache writes)**였습니다.
한편, 저는 에이전트가 ChatGPT처럼 전체 이력을 더 잘 인지하길 원했습니다. LibreChat의 Search messages 입력 창에 그냥 입력할 수 있는 기능을 놓고 보면, "(에이전트에게도 이 능력을 부여하면 안될까?)"라는 생각이 떠오지 않을 수 없습니다 — 이 기능이 에이전트에도 부여되지 못하는 것일까? 예. 메시지 전체에서 얻을 수 있는 정보는, 값싼 에이전트로 요약된 메모리보다 훨씬 풍부하며 약간의 재귀 탐색을 통해 많은 대화들에서 많은 실마리를 연결할 수 있습니다. 제 개인 구현은 이미 이를 증명하고 있고, 저희 그룹의 직장 내 배포는 아직 지켜봐야 합니다...
MCP 도구
이 서버는 기본 프로젝트인 meilisearch-mcp의 상류(upstream) 프로젝트가 가진 도구 중에서 읽기 전용 도구를 LibreChat 특화 항목으로 노출하고 쓰기 도구는 배제합니다.
search_messages: 대화의 연속성을 위해 호출자의 색인된 메시지를 선제적으로 검색합니다; 선택적으로 알려진 대화 ID, 보낸 사람, 결과 수로 범위를 좁힐 수 있습니다. 메시지 ID, 대화 ID, 보낸 사람, 텍스트를 반환합니다.search_conversations: 호출자의 색인된 대화를 제목을 기준으로 선제적으로 검색합니다. 후속 메시지 검색을 위해 대화 ID, 제목, 태그를 반환합니다.admin_search_messages: 명시적으로 요청되고 권한이 부여된 대상 사용자의 메시지 검색입니다. 대상 사용자와 문서화된 메시지 필드를 반환합니다.admin_search_conversations: 명시적으로 요청되고 권한이 부여된 대상 사용자의 대화를 제목으로 검색합니다. 대상 사용자와 대화 ID, 제목, 태그를 반환합니다.health-check: 구성된 Meilisearch 가용성 상태를 읽습니다.get-version: Meilisearch 버전 정보를 읽습니다.get-stats: Meilisearch 데이터베이스 전체 통계를 읽습니다.get-health-status: 구조화된 상태 및 인덱스 상태 정보를 읽습니다.get-system-info: Meilisearch 시스템 정보를 읽습니다.get-index-metrics: 하나의 알려진 인덱스에 대한 메트릭을 읽습니다(indexUid필수).NOT YET IMPLEMENTED — 기본 LibreChat 구성에서는 오류를 반환합니다. 반환되는
fieldDistribution는 향후 네트워크화된 메시지 검색을 위한 토Poical 그래프 구성에 유용할 수 있지만, LibreChat 최신 버전의 Meili에서 이 기능은 실험 단계이며 활성화/생성해야 합니다.
사용자 범위
일반 검색은 서비스에 의해 요청 및 요청자에 귀속되며(모델이 tip) 대상을 지정하는 user 또는 원시 필터를 허용하지 않습니다. 관리자 검색은 정의된 범위와 서비스 인가를 요구하며 일반적으로 대상 사용자가 필요합니다. 인가가 실패하면 재시도나 탐색을 하지 마세요. 현재 구현은 일반적인 검색 실패 메시지를 반환합니다. 모든 도구는 읽기 전용이며 위에 문서화된 필드만 반환합니다.
요청 범위(요청 헤더)와 IT 도구 동작의 문제
처음부터 분명하지 않았던 것은, 요청을 헤더에 포함하는 (즉, MCP 헤더에 메시지나 대화 ID를 포함하는) 방식이 사용자 경험을 어떻게 바꾸는가 하는 점입니다. MCP 서버는 전반적으로 선택할 때 표시되지만, 제공되는 도구 자체는 표시되지 않습니다. 즉 사용자 지향 에이전트에서 관리자(admin) 도구를 해제할 수는 없지만, 이 서버가 사용자 범위에 따라 도구를 표시하는 방식에는 일부 동적 기능이 있습니다. 이상적으로는 서버 연결 헤더와 도구 사용 헤더를 별도로 설정할 수 있어야 합니다. LibreChat에서 진행되는 MCP 버그/PR들을 따라가며 커스터마이징을 더 개선하기 위해 어떤 조정을 할 수 있는지 파악하고 있습니다.
알려진 문제
현재 프로젝트 안에서:
디버깅에는 로그가 너무 기본입니다 (요청 매개변수와 응답 메트릭스를 추가하고 선택적으로 오류를 JSON으로 저장).
도구 실패 오류가 무언의 측면이 없습니다(설치 상황에서는 당분간 개인 정보 보호를 위해 의도적으로 차별화를 저장; 진단을 위해 더 많은 내용이 필요).
conversationId필터를 사용한search_messages가 때때로 실패할 수 있나요? (연결/스레드/비동기 관련일 수 있습니다; TODO: 대화(conversation)를 필터 필드로 추가)get-index-metrics는 experimental 기능 활성화가 필요합니다 (TODO: 테스트 및 탐구)문서와 코드에 레거시/개발 유물이 남아 있고 불일치도 있습니다
관리자 대상 검색을 위한 사용자 ID의 획득가 번거로움 (TODO: PeoplePicker API를 통해 핸들이나 이름+이니셜 매핑 탐색)
통합/활성화 효과:
도구 선택이 불가능("요청 범위 헤더"때문에)
하위 에이전트가 사용하는 빠르게 연속적인 도구 호출은 실패 응답이 발생 (스레딩 및 비동기 함수를 더 검토 필요)
과거 주제에 대한 반복 검색/논의는 미래 검색에서 해당 주제의 명확성을 희석시킴
대화 그룹핑이 번거를로고 토큰 비용이 커질 수 있습니다 (TODO: 메시지 검색 위에 대화 그룹별 통계를 반환하는 기능이나 도구 추가)
복잡한 검색 시나리오의 비용이 큽니다 (TODO: 서버 측 그룹핑, 키워드/토픽 그래프, 다중 검색 union/intersect/exclude 연산, 중복 제거, 정렬)
보안 모델
이 도구는 반드시 LibreChat 배포가 single-tenant(single tenancy)로 운영되고 단일 정책을 가지며 보안 특화 모델이나 연동 공급자를 도입하지 않았을 것이라는 기본 가정으로 짜여 있습니다!
도구에는 기본적인 사용자 게이트가 있으며 잠재적으로 매우 넓은 관리자 범위가 있습니다:
일반 도구:
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 키를 받습니다. Meilisearch 마스터 키는 절대로 사용하거나 전달하면 안 됩니다.결과는 스키마로 제한됩니다. 일반 결과에는
messageId,conversationId,sender,text만 포함됩니다. 대화 검색 결과에는conversationId,title,tags만 포함됩니다. 관리 결과에는 선택한user가 추가로 포함됩니다.식별자가 누락되었거나 또는 형식이 잘못된 식별자는 가용저장(fail closed) 방식으로 처리됩니다. 인가 실패는 의도적으로 일반적이며 비밀 번호는 절대 반환하지 않습니다.
검색된 텍스트는 LibreChat이 인덱스화한 그것 그대로입니다. 인덱셔와 배포에 따라 인덱서가 설정된 분야에 따라 결과에는 어시스턴트 출력, 추론 류 텍스트 또는 도구 호출 흔적이 포함될 수 있습니다. 이 MCP 서버는 LibreChat헷dexing하지 못한 내용은 복구할 수 없습니다. 검색 결과는 잠재적으로 민감한 감사 데이터로 취급하세요.
추가 주의사항 및 제한사항은 SECURITY.md를 참조하세요!!!
데이터 관리 책임
제 IT 보안 운영팀과 저는 모든 데이터/기록을 볼 수 있다는 점을( "프라이버시에 대한 기대 없음") 이미 기업 사용자에게 공지합니다. 또는 배포에 해당한다면 같은 주의를 할 것이라고 가정합니다. 적용 정책을 위반할 수 있는 상황에서는 구현하지 않을 것입니다. 이 도구는 MongoDB 툴이나 Meili CLI를 쓰는 대신, 이미 자금 할 수 있는 일을 더 간단히 수행하게 해줄뿐 아니라 이 단말에서 다른 공급자/모델/에이전트의 기록을 노출합니다(내 배포에서는 필요에 따라 개인 모델을 도입하지 않아 문제는 아직 없음을 감을 참고).
LibreChat 구성
다음 example 파일들을 LibreChat Compose 프로젝트에 복사 또는 병합하고 고유 키/ID/설정을 입력하세요:
librechat-search-mcp/librechat.yaml.example:mcpSettings와mcpServers를 기존librechat.yaml에 병합하세요.{{LIBRECHAT_USER_ID}}같은 MCP 헤더 매개변수는 주어진 규칙대로 정확하게(혹은 그대로) 구성해야 하며 LibreChat이 요청별로 치환합니다. 이 헤더는 보안 모델과 필터링 기능의 일부입니다.권장사항 (배포 환경의 saya 동기에 동의한다면):
librechat.yaml에서 메모리 에이전트를 비활성화하기를 권장합니다. 향후 LibreChat 버전에서 메모리 에이전트의 동작이 변경되지 않는 한, 토큰 비용 및 대화 상호 주제 오염을 방지할 수 있습니다.참고: 최신 LibreChat부터 메모리 도구의 동작은
endpoints.agents.capabilities문맥으로 옵트인 방식이 변경되었습니다. 원하는 에이전트가 필요시 메모리를 쓸 수 있도록 하려면memory을 추가하세요.
librechat-search-mcp/docker-compose.override.yml.example:librechat-search-mcp서비스를 기존 Compose 프로젝트에 병합하세요. 서비스는 내부 전용이며expose: 8000,ports없음, 기본 Compose 네트워크에 참여합니다.librechat-search-mcp/.env.example: 이 키들을 메인 LibreChat.env의 해당 부분에 추가하세요. 그리고 표시된 자리표시자(placeholder)만 교체하세요. 기존의Search섹션 바로 아래에 넣는 것을 추천합니다.
MCP URL은 http://librechat-search-mcp:8000/mcp입니다. MCP에 표시되는 서버 이름은 사용자 이해를 위해 chat-search입니다. LibreChat에서 비공개(private) MCP 대상 주소를 차단한다면 librechat.yaml.example에 정의된 allowedAddresses/allowedDomains 항목을 그대로 유지하세요. 주의: 도메인 화이트리스트가 비워 있지 않으면 다른 MCP 서버로도 영향을 줄 수 있으므로 의도적으로 잘 구현하세요.
MEILI_HOST_PORT=7700은 기존 LibreChat 배포에 사용하는 호스트/Compose 브리지 변수입니다. MCP 컨테이너 자체는 반드시 http://meilisearch:${MEILI_HOST_PORT}라는 Compose 서비스 URL을 사용해야 하며(유도된 overrider 값이 해당 URL를 구성합니다) LibreChat에 이미 있는 MEILI_HOST=http://0.0.0.0:7700은 호스트를 바라보는 별개의 설정이므로 무분별하게 바꾸지 않아야 합니다.
관리자(admin)의 사용자 ID를 확인하여 명시적으로 활성화
MEILI_MCP_ADMINS의 사용자 ID 애는 다음 중 손쉬운 방법으로 얻을 수 있습니다 (당연히 밝히는 순서대로 나열):
인터넷 브라우저의 UI에서 정보 쿼리/확인:
브라우저 개발자 도구(ctrl+shift+i)를 열고
Network탭을 선택합니다.Chat History 대화 목록에서 이전 대화를 선택합니다(현재 브라우저 캐시에 없는 더 오래된 대화를 선택해야 할 수도 있습니다).
Network 탭에 기록된 첫 번째 API 호출은
Response하위 탭에 대화 헤더 데이터를 로드합니다. 여기에는 다음이 포함됩니다.user- 이 값은 당신의 ID입니다 (이 필드는 서버 내에서 검색을 필터링하거나admin_도구의target-user매개변수로 사용됩니다) - 당신이 선택한 다른 관리자/권한 수혜자에게도 동일한 값을 제공하도록 요청한 뒤, 이 값을 복사하고.env파일의MEILI_MCP_ADMINS에 넣으세요 [목록 구분은 쉼표만 사용];conversationId- 이것은search_MCP 도구 매개변수에서 사용되는 것과 동일한 ID이며, 대화의 URL인http://localhost:3080/c/{conversationId}와도 일치한다는 점을 참고하세요;
이 프로젝트의 동작 방식에서 중요한 점 - 세 번째 API 호출에는 이 대화의 메시지 목록이 포함되어 있으며, 그 구조는 Meilisearch가 이를 인덱싱하는 방식과 유사합니다. 이 프로젝트는 다음 키를 사용합니다:
conversationId- 이 프로젝트는 기본적으로 검색 결과에서 현재 대화를 제외하거나 메시지를 목표로 필터링할 때 사용합니다.sender: "User" 또는 에이전트 표시 이름text: 메시지 내용향후 구현을 위해 검토할 사항:
endpoint(또는 더 정확하게는model)을 활성화 시,MEILI_MCP_CONSTRAIN_ENDPOINT=true설정과 결합하고 있으면 비밀 모델/에이전트를 공개 제공자 모델과 분리하여 엔드포인트를 넘나드는 메시지 검색을 방지하기 위한 필터로 호출할 수 있습니다.parentMessageId는 이미 MCP 전송 헤더에서 LibreChat 의{{LIBRECHAT_BODY_PARENTMESSAGEID}}동적 변수를 통해 도구 호출 결과 필터로 통합되어 있습니다. 이 필드를 활용해 특정 검색 결과의 앞/뒤 버퍼를 목표적으로 설정하고, 결과를 결정적으로 정렬하고, 메시지 체인 구조를 그래프로 나타내기 위한 방법으로 검색 인덱스를 다시 검토할 예정입니다.content에는 도구 호출의 생각/추론이 담겨 있습니다 (이것이 인덱싱된 메시지에 나타나는 것은 보지 못했는데, 아마 이유가 있을 것입니다. 메시지 기록을 검색하는 사용자는 제목이나 메시지 텍스트와 일치를 기대하지, 파일이나 에이전트 내부의 내용을 기대하지 않습니다).attachments에는 도구 호출 결과(및 RAG 및/또는 업로드된 파일 내용)이 포함됩니다.content와 비슷하게 이 항목 역시 인덱싱되지는 않을 것입니다.createdAt은 결정적 시간 순서의 정렬 기준이나 필터 키로 사용될 수 있습니다 (Meili는 이미 결과를 겉보기 시간 순으로 반환하지만, 연관성 점수에 의해서도 영향을 받을 수 있습니다). 이 값은 인덱스 문서 문서의 세부 데이터(인덱스가 생성/갱신된 시간)로도 접근할 수 있을 수 있지만(다소 다른 값일 수 있음), 그러한 경우 인덱스를 생성할 때마다 그 가치를 모두 잃을 수 있습니다.
LibreChat 컨테이너 로그를 확인합니다(
docker compose logs api) - 관리자 권한으로 LibreChat UI에서 동작을 수행한 직후 / (주의: 동시 사용자가 많으면 이 로그에는 사용자 이름이 표시되지 않으므로 다른 결과와 대조/매칭하는 것은 권장하지 않습니다)Mongo Express 에서
users테이블을 확인하는 방법 (별도로 구성했다면 웹 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
exitMCP 서버용 읽기 전용 권한 키 생성
LibreChat의 MEILI_MASTER_KEY를 MEILI_MCP_KEY로 사용하지 마세요!
저장소에는 API 키를 한 번의 명령으로 생성하고 검증하는 크로스 플랫폼 헬퍼가 포함되어 있습니다.
이 헬퍼는 meilisearch 컨테이너에 접속하여(따라서 실행되고 있어야 함) 권한 있는 키를 생성하고,
기본적으로 키를 출력하거나, 선택적으로 로컬 파일에 기록합니다. 그리고 LibreChat의 기본 .env 파일은 절대 편집하지 않습니다.
출력 파일 방식은 선택사항이며, 파일에서 이미 존재하지 않으면 --force/-Force를 제공하지 않는 한 생성되지 않습니다. (만약 존재하면) 생성되는 *.local.env 파일은 요구되지 않으며 권한이 제한됩니다.
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.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 스크립트 내부에서 수행하는 작업을 수동으로 하는 방법입니다. 차후 사용자를 위해 또는(이미 특별히) 커스터마이즈를 했다면(아래 스크립트를 참조) 수동으로 진행해 되지 실수:
이 서비스에 사용자가 하나의 전용 읽기전용 키를 만듭니다. 정확한 액션 계약은 다음과 같습니다.
searchstats.getmetrics.getindexes.getsettings.getversion
키를 설정한 두 인덱스(messages와 convos, 또는 설정값)로 범위를 한정하세요. 전역 health endpoint는 별도로 확인하며 쓰기가 가능한 역할을 필요로 하지 않습니다. 의도가 있는 경우가 아니고 non-expiring 운영 키만, expiresAt을 null로 설정하고, 반환된 키는 `MEILI_MCP_KEY에만 저장하세요.
chat-meilisearch(docker exec)/meilisearch(docker compose exec) 컨테이너에서 키를 생성하세요가 아닌, MCP container가 아닙니다. 아래 마스터 키는 명령 히스토리상의 플레이스토루블러이며 프롬프트/로그/또는 이 저장소에 절대로 붙여넣어서는 안 됩니다:
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그런 다음 무해한 삭제 프로브가 거부되는지 확인합니다. 없어서 없는 센티넬 문서 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;; 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를 확인하세요각 키를 제거하려면 다음 실행:
curl -sS -X DELETE -H "Authorization: Bearer $MEILI_MASTER_KEY" "http://127.0.0.1:7700/keys/KEY_UID"(KEY_UID를 실제 값으로 대체)
완전한 설정 명령 시퀀스
다음 명령을 하나씩 인터랙션 하며 실행하세요 (윈도우 사용자들이나 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의 .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이 만든 메시지 인덱스에는 필터 가능한 conversationId가 없습니다; 이는 MCP 검색 도구를 위한 다른 매개변수와마찬가지로 호출자에게 반환하기 전에 서버 쪽에서 처리됩니다.
로그 마운트 유지
컨테이너는 구조화된 JSON-lines 로그를 /var/log/librechat-search-mcp로 작성합니다. Compose 예제는 /var/log/librechat-search-mcp를 ${MEILI_MCP_LOG_HOST_DIR}에 바인드 마운트합니다. 기본값은 상위 Compose 프로젝트의 ./librechat-search-mcp/logs입니다. 로그 파일의 이름은 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 이미지에 포함되어 되어 있습니다.
헬스, 인덱스 이름, 기본 키, 필터 가능성, 정렬 가능 속성을 검사하며 설정을 변경하거나 키를 출력하지 않습니다. 종료 코드 0 및 JSON "status": "pass"는 계약이 통과되었음을 의미하고, 0이 아닌 종료 코드는 보고된 헬스/인덱스/설정 또는 필수 필터 검사 실패를 의미합니다. 이는 진단용이며, MCP 준비상태 프로브는 아닙니다. /health는 MCP 프로세스가 살아 있음을 확인해줍니다.
호출자 프롬프트와 예상 동작
구성 완료 후 컨테이너가 실행되고 있는 상태에서 새 LibreChat 대화를 시작하세요(예: MCP 사이드바, Agent Builder, 또는 상자 MCP Servers 드롭다운)를 통해 모델이 도구 목록을 발견합니다.
도구에 대한 설명은 일반적인 검색 도구에 대한 사전적(proactive) 사용을 권장하는 것으로 작성되어 있으며, 반면 admin_ 변형은 "사용자가 댜하지 않은 첫 사용" 지침을 가집니다. 앞으로 경험에 따라 이 설명를 조정할 가능성이 있고, 불필요하다거나이나 지나치게 광범위한 재미있는 사전 사용을 이미 발견되었습니다.
NOTE: 소형 로컬 모델은 프롬트에서 이용하는 도구 이름을 명시적으로 필요로 하는 경우가 있습니다.
일반 검색 - 명시적 지시:
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...사용자가 "grackle ornithopter" 같은 쿼리로 검색을 적극적으로 수행해야 하며,문자 그대로 대화에서 일치하는 메시지를 확인할 수 있어야 합니다.
의도된 검색 에이전트 설계:
이 도구에는 일반적인 구성 및 도구 설명만 존재하지만, 실제 정묘는 전용 에이전트 및/또는 유익한 SKILL.md를 정의하여 메모리처럼 동작하는 걸 만드는 것입니다. 이 도구의 결과가 전체 메시지이므로 토큰 비용이 상당할 수 있으므로, 저렴한 모델을 기반으로 한 하위 에이전트를 만들어 상호 연결된 대화 주제를 재귀적으로 추적한 다음 상세한 요약/요약을 반환하게 하는 것이 그 팀의 기본 에이전트로 배포하는 방법일 것입니다.
허용된 관리자만 가능한 대상 관리자 감사를 위해(목록을 갖춘 계정만 사용):
제 할 일 목록에는 LibreChat `PeoplePicker` API를 조사하고, 그것이 Compose 네트워크 안에서 어떻게/얼마나 노출되는지 확인하는 것이 있습니다. 이상적으로는 관리자가 handle 또는 이름(first name)으로 사용자를 지정할 수 있고, PeoplePicker가 활성화되어 있다면 에이전트가 내부 ID를 조회할 수 있을 것입니다(또는 에이전트를 거치지 않고 서버 자체에서 조회 대상 필터링/오류 처리를 수행할 수도 있습니다. 예: "2명의 'Sally'를 찾았습니다: Sally X. 또는 Sally Y.를 의미하시나요?", *에이전트에게 이메일이나 전체 이름을 노출하지 않은 채로*)...
GXP15
### 의도된 관리자 범위(디버깅, 프롬프트/대화 최적화, 집단적 집중)
GXP16
GXP17
### 경계 검사:
GXP18
GXP19
후자는 **지원되지 않습니다**: 이 프로젝트는 타임스탬프 정렬, 이전/이후 검색 조회, MongoDB/API 조회, 주변 메시지 재구성 또는 임의의 정렬을 추가하지 않습니다. 발신자 및 대화 필터는 제한된 사후 필터이므로 요청된 한도보다 적은 결과도 유효하며, 원래 Meilisearch 히트 순서는 유지됩니다.
</details>
## 검증
<details>
<summary>테스트</summary>
로컬 검사(LibreChat 안의 이 프로젝트 폴더에서):
GXP20
배포 검사에는 여전히 실행 중인 LibreChat/Meilisearch 스택이 필요합니다: 새 세션 도구 검색, `User-Id` 헤더, 제한된 키 권한, 인덱스 계약, 호스트 포트 비공개, 그리고 두 사용자의 동시 요청을 검증하세요. 로컬 단위 테스트를 실제 호출자 동작의 증거로 취급하지 마십시오.
</details>
## 배포 및 문제 해결
* 지원되는 Docker Compose 경계, 안전한 구성 순서, 서비스 식별자 및 `container_name` 트레이드오프에 대한 내용은 [`docs/deployment.md`](docs/deployment.md)를 참고하세요.
* 일반적인 Compose, 키 생성, 네트워킹, MCP 검색, 인덱스, 로깅 오류에 대한 내용은 [`docs/troubleshooting.md`](docs/troubleshooting.md)를 참고하세요.
* 서비스를 활성화하기 전에 [`SECURITY.md`](SECURITY.md)를 참고하세요. 이 문서는 인덱싱된 콘텐츠, AI 제공자 노출, 신원 및 관리자 범위, 로그/보존 기간, 제한된 키, 신뢰 경계, 그리고 이 프로젝트가 보장하지 않는 사항을 다룹니다.
## 개발
* 에이전트가 바라보는 도구 계약은 [`docs/tool-descriptions.md`](docs/tool-descriptions.md)를 참고하세요.
* 업스트림 출처 및 라이선스 정보는 [`ATTRIBUTION.md`](ATTRIBUTION.md)를 참고하세요.
* 개발, 계획, 감사 및 내부 결정 기록은 의도적으로 프로덕션 저장소 밖인 `workspace/project-context/librechat-search-mcp/development-records/`에 유지됩니다.
말하자면, 누군가 *기여*하고 싶다면 discussion이나 이슈든 그냥 열어주세요. 저도 **Contributing** 섹션을 추가하고 PR이 어떻게 돌아가는지 알아볼 수 있을지도 모르고요... 하지만 사실 이것은 제 개인 취미 프로젝트일 뿐이며, 저는 그것이 업무에서도 저에게 큰 가치가 될 것이라는 것을 알고 있습니다. 그리고 여기서 저기로 가는 가장 쉬운 연결 라인은 GitHub에 공개하는 것입니다. 즉, 저는 무언가를 만들고 문제를 해결하는 것을 좋아하지만, 다른 사람의 이슈에 주의를 기울일 결과는 없으며, 아마도 "대박 기능 활성화"가 "격차 메우기" 중 하나를 우선하게 될 것입니다.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