Skip to main content
Glama
martinriesel

librechat-personal-files-mcp

by martinriesel

librechat-personal-files-mcp

MCP-сервер, предоставляющий агентам LibreChat личное файловое хранилище для каждого пользователя, постоянную документацию, индексацию/поиск RAG и публикацию непрозрачных публичных ссылок.

Возможности

  • Хранилище для каждого пользователя: Личные файлы в /data/private/<userId>/ с полным набором операций CRUD, вывода списка и перемещения.

  • Каталог документации: save_documentation / update_documentation записывают в docs/ и обновляют memory-index.json (схема v2).

  • Интеграция с RAG: index_document отправляет содержимое в rag_api через POST /embed с canary-проверкой (issue #305); search_knowledge — для семантического поиска; remove_from_knowledge — для удаления.

  • Публикация в общий доступ: publish_file создает криптографически случайные токены (≥128 бит); файлы отдаются через Nginx X-Accel-Redirect с Content-Disposition: attachment, nosniff, no-store.

  • Строгая безопасность: Отказ по умолчанию (fail-closed) при отсутствии или недействительном X-User-Id; блокировка path traversal; запрет абсолютных путей; запрет сегментов ..; обнаружение выхода через симлинки; защита зарезервированных сегментов; атомарная запись индекса с межпроцессной блокировкой.

Related MCP server: knowledge_mgmt

Архитектура

┌──────────────┐     ┌────────────────────────┐     ┌─────────────┐
│ LibreChat    │────▶│ librechat-personal-files-mcp │──▶│ rag_api     │
│ (Agent)      │ MCP │ (stateless HTTP /mcp)  │     │ (vector DB) │
└──────────────┘     └────────────────────────┘     └─────────────┘
                            │
                            │ GET /files/{token}
                            ▼
                     ┌──────────────┐
                     │ Nginx        │
                     │ (X-Accel)    │
                     └──────────────┘
                            │
                            ▼
                     ┌──────────────┐
                     │ /data/private│  (read-only bind)
                     └──────────────┘

Быстрый старт (разработка)

cd /opt/LibreChat/mcp-personal-files
python -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest
.venv/bin/python -m ruff check .
# Run server
STORAGE_ROOT=/tmp/pf-private JWT_SECRET=$(openssl rand -hex 32) .venv/bin/personal-files-mcp

Развертывание в продакшене

1. Подготовка хоста (выполняется один раз от имени root)

cd /opt/LibreChat
groupadd -g 2500 lcfiles 2>/dev/null || true
mkdir -p ./data/private/_system
chown -R 2000:2500 ./data/private
chmod 2770 ./data/private
setfacl -R -m g:2500:rX,d:g:2500:rX ./data/private 2>/dev/null || \
  echo "ACL tools absent; using 644/755 fallback"
grep -q '^JWT_SECRET=' .env || echo "JWT_SECRET=$(openssl rand -hex 32)" >> .env

2. Добавьте в docker-compose.override.yml

Скопируйте блоки из docker-compose.snippet.yml в ваш существующий override-файл.

3. Настройте панель администратора LibreChat

Добавьте в разделе Настройки MCP:

mcpSettings:
  allowedAddresses:
    - 'librechat-personal-files:8080'

mcpServers:
  personal-files:
    type: streamable-http
    url: http://librechat-personal-files:8080/mcp
    timeout: 120000
    chatMenu: false
    headers:
      X-User-ID: '{{LIBRECHAT_USER_ID}}'
      X-User-Email: '{{LIBRECHAT_USER_EMAIL}}'

Перезапустите LibreChat.

4. Конфигурация Nginx (добавьте в существующий блок server)

limit_req_zone $binary_remote_addr zone=pubfiles:10m rate=5r/s;

location ^~ /files/ {
    limit_req zone=pubfiles burst=10 nodelay;
    limit_req_status 429;
    proxy_pass http://librechat-personal-files:8080/files/;
    proxy_set_header X-Original-URI $request_uri;
    proxy_set_header X-Real-IP $remote_addr;
}

location ^~ /_protected/ {
    internal;
    alias /data/private/;
}

Перезагрузите Nginx.

Переменные окружения

Переменная

По умолчанию

Описание

USER_HEADER

X-User-Id

Заголовок, передающий идентификатор пользователя

STORAGE_ROOT

/data/private

Корневой каталог для данных пользователя

SHARE_ROOT

/data/share

Унаследованная общая область (чтение/запись во время миграции)

RAG_API_URL

http://rag_api:8000

Конечная точка rag_api

JWT_SECRET

обязательно

Секрет HS256, общий с LibreChat/rag_api (≥32 символов)

PUBLIC_BASE_URL

https://gpt.riesel.com.br/files

Базовый URL для публичных ссылок

MAX_FILE_SIZE_MB

20

Максимальный размер отправляемого файла

REGISTRY_DB

/data/private/_system/links.db

Реестр SQLite для публичных ссылок

Инструменты MCP

Хранилище

  • list_files(path="", recursive=false, pattern=null) — список файлов и каталогов

  • read_file(path) — читает текст UTF-8; ошибка для бинарных файлов или файлов размером более 2 МБ

  • write_file(path, content) — записывает текст (UTF-8), создает родительские каталоги

  • update_file(path, content) — обновляет существующий файл

  • delete_file(path) — удаляет файл или каталог

  • move_file(src, dst) — перемещает в пределах корневого каталога пользователя

  • get_file_info(path) — метаданные + docindex + статус публикации

Документация

  • save_documentation(filename, content, title?, description?, tags?, topics?) — сохраняет в docs/, обновляет индекс, не публикует и не индексирует

  • update_documentation(filename, content, ...) — обновляет существующий документ

  • get_document_metadata(filename) — полная запись индекса

RAG

  • search_knowledge(query, limit=8) — семантический поиск (в пределах владельца через JWT)

  • index_document(path) — выполняет эмбеддинг + canary-проверку, обновляет статус индекса

  • remove_from_knowledge(path) — удаляет из rag_api, очищает индекс

  • get_index_status() — счетчики + состояние rag_api

Публикация

  • publish_file(path, expires_in_days?) — создает/повторно использует публичную ссылку, возвращает токен и URL

  • unpublish_file(path_or_token) — отзывает ссылку (файл остается приватным)

  • get_public_link(path) — активная ссылка для пути

  • list_public_links() — все ссылки пользователя

Модель безопасности

  • Идентификация: Заголовок X-User-Id вставляется LibreChat ({{LIBRECHAT_USER_ID}}). Если плейсхолдер не заменен → пустая строка → fail-closed.

  • Fail-closed: Отсутствующий/пустой/недействительный заголовок → HTTP 403 {"error":"missing_user_identity"} или {"error":"invalid_user_identity"}.

  • Безопасность путей: Все пути относительные; абсолютные пути и .. отклоняются; выход через симлинк обнаруживается с помощью Path.resolve() + проверки префикса.

  • Изоляция: область владельца rag_api обеспечивается JWT sub/id = userId (PR #319 влит 2026-08-15).

  • Публичные ссылки: Непрозрачные токены secrets.token_urlsafe(16); в URL нет пользователя/пути; отзыв через 410 Gone; ленивая очистка истекших записей.

Разработка

# Run tests
.venv/bin/pytest -q

# Lint
.venv/bin/ruff check .

# Type check (optional)
.venv/bin/mypy src/personal_files_mcp  # if mypy added to deps

Лицензия

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables uploading, organizing, and semantically searching documents with support for various file types and embedding providers.
    25 npm
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Provides AI agents with local file-processing capabilities for token counting, RAG chunking, CSV/JSON conversion, QR generation, and more, while keeping documents private on the user's machine.
    7
    1
    MIT
  • A
    license
    B
    quality
    A
    maintenance
    Enables file-based knowledge management with ranked keyword and semantic hybrid search, allowing AI agents to learn from documents and recall relevant knowledge as a persistent memory tool.
    30
    31 npm
    AGPL 3.0