paperless-mcp

by baruchiro (community) · Claude Desktop, Paperless-NGX

MCP MCP Servers Open Source v0.1.0

MCP-сервер для управления документами в Paperless-NGX — self-hosted системе управления документами. Позволяет искать, читать и организовывать скан-архив через LLM. Возможности: - Поиск документов по содержимому, тегам, корреспонденту - Просмотр метаданных документа - Получение OCR-текста документа - Управление тегами и корреспондентами - Список документов с фильтрацией - Идеально для "спроси у своего архива" сценариев

v0.1.0
current
Добавлен 18.06.2026 · Обновлён 07.07.2026 · MCP Servers
Установка
# Claude Desktop — claude_desktop_config.json:
{
  "mcpServers": {
    "paperless": {
      "command": "npx",
      "args": ["-y", "@baruchiro/paperless-mcp@latest"],
      "env": {
        "PAPERLESS_URL": "http://your-paperless-instance:8000",
        "PAPERLESS_API_KEY": "your_api_token"
      }
    }
  }
}

# Claude Code (CLI):
claude mcp add paperless --env PAPERLESS_URL=http://localhost:8000 --env PAPERLESS_API_KEY=your_token -- npx -y @baruchiro/paperless-mcp@latest

# OpenCode — ~/.config/opencode/opencode.json:
{
  "mcp": {
    "paperless": {
      "type": "local",
      "command": ["npx", "-y", "@baruchiro/paperless-mcp@latest"],
      "environment": {
        "PAPERLESS_URL": "http://your-paperless-instance:8000",
        "PAPERLESS_API_KEY": "your_api_token"
      }
    }
  }
}
переведено ИИ

Paperless-NGX MCP Сервер

CodeRabbit Pull Request Reviews

MCP (Model Context Protocol) сервер для взаимодействия с API сервером Paperless-NGX. Этот сервер предоставляет инструменты для управления документами, тегами, корреспондентами и типами документов в вашем экземпляре Paperless-NGX.

Быстрый старт

Install MCP Server

Установка

Добавьте следующее в ваш конфигурационный файл MCP:

// Режим STDIO (рекомендуется для локального использования или через CLI)

"paperless": {
  "command": "npx",
  "args": [
    "-y",
    "@baruchiro/paperless-mcp@latest",
  ],
  "env": {
    "PAPERLESS_URL": "http://your-paperless-instance:8000",
    "PAPERLESS_API_KEY": "your-api-token",
    "PAPERLESS_PUBLIC_URL": "https://your-public-domain.com"
  }
}

// Режим HTTP (рекомендуется для Docker или удалённого использования)

"paperless": {
  "command": "docker",
  "args": [
    "run",
    "-i",
    "--rm",
    "ghcr.io/baruchiro/paperless-mcp:latest",
  ],
  "env": {
    "PAPERLESS_URL": "http://your-paperless-instance:8000",
    "PAPERLESS_API_KEY": "your-api-token",
    "PAPERLESS_PUBLIC_URL": "https://your-public-domain.com"
  }
}
  1. Получите ваш API токен:
  2. Войдите в ваш экземпляр Paperless-NGX
  3. Нажмите на ваше имя пользователя в правом верхнем углу
  4. Выберите «Мой профиль»
  5. Нажмите кнопку с круговой стрелкой для генерации нового токена

  6. Замените плейсхолдеры в вашем конфиге MCP:

  7. http://your-paperless-instance:8000 на URL вашего Paperless-NGX
  8. your-api-token на токен, который вы только что сгенерировали
  9. https://your-public-domain.com на публичный URL вашего Paperless-NGX (необязательно, по умолчанию используется PAPERLESS_URL)

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

Переменная Обязательна Значение по умолчанию Описание
PAPERLESS_URL Да Базовый URL вашего экземпляра Paperless-NGX
PAPERLESS_API_KEY Да API токен из вашего профиля Paperless-NGX
PAPERLESS_PUBLIC_URL Нет PAPERLESS_URL Публичный URL для ссылок на документы
PAPERLESS_API_VERSION Нет 5 Версия REST API Paperless-ngx. Используйте 10 для Paperless-ngx v3+. Если вы видите ошибки HTTP 406, установите значение 10.
PAPERLESS_MCP_UPLOAD_PATHS Нет Список разрешённых директорий для загрузок через file_path, разделённых двоеточием. Рекомендуется для безопасности. Пример: /var/uploads:/tmp/scans

Вот и всё! Теперь вы можете попросить Claude помочь вам управлять документами Paperless-NGX.

Примеры использования

Вот что вы можете попросить Claude сделать:

  • «Покажи мне все документы с тегом «Счёт-фактура»»
  • «Поиск документов, содержащих «налоговая декларация»»
  • «Создай новый тег «Квитанции» с цветом #FF0000»
  • «Скачать документ №123»
  • «Показать список всех корреспондентов»
  • «Создать новый тип документа «Банковская выписка»»

Доступные инструменты

Операции с документами

list_documents

Получить постраничный список всех документов.

Параметры: - page (необязательно): Номер страницы - page_size (необязательно): Количество документов на странице

list_documents({
  page: 1,
  page_size: 25
})

get_document

Получить конкретный документ по ID.

Параметры: - id: ID документа

get_document({
  id: 123
})

search_documents

Полнотекстовый поиск по документам.

Параметры: - query: Строка поискового запроса

search_documents({
  query: "invoice 2024"
})

download_document

Скачать файл документа по ID.

Параметры: - id: ID документа - original (необязательно): Если true, скачивает оригинальный файл вместо архивированной версии

download_document({
  id: 123,
  original: false
})

get_document_thumbnail

Получить миниатюру документа (изображение-превью) по ID. Возвращает миниатюру как ресурс изображения WebP, закодированный в base64.

Параметры: - id: ID документа

get_document_thumbnail({
  id: 123
})

bulk_edit_documents

Выполнить массовые операции над несколькими документами.

Параметры: - documents: Массив ID документов - method: Одно из значений: - set_correspondent: Установить корреспондента для документов - set_document_type: Установить тип документа для документов - set_storage_path: Установить путь хранения для документов - add_tag: Добавить тег к документам - remove_tag: Удалить тег у документов - modify_tags: Добавить и/или удалить несколько тегов - delete: Удалить документы - reprocess: Переобработать документы - set_permissions: Установить права доступа к документам - merge: Объединить несколько документов - split: Разделить документ на несколько документов - rotate: Повернуть страницы документа - delete_pages: Удалить определённые страницы из документа - Дополнительные параметры в зависимости от метода: - correspondent: ID для set_correspondent - document_type: ID для set_document_type - storage_path: ID для set_storage_path - tag: ID для add_tag/remove_tag - add_tags: Массив ID тегов для modify_tags - remove_tags: Массив ID тегов для modify_tags - permissions: Объект для set_permissions с полями owner, permissions, флагом merge - metadata_document_id: ID для merge для указания источника метаданных - delete_originals: Булево значение для merge/split - pages: Строка для split "[1,2-3,4,5-7]" или delete_pages "[2,3,4]" - degrees: Число для rotate (90, 180 или 270)

Примеры:

// Добавить тег к нескольким документам
bulk_edit_documents({
  documents: [1, 2, 3],
  method: "add_tag",
  tag: 5
})

// Установить корреспондента и тип документа
bulk_edit_documents({
  documents: [4, 5],
  method: "set_correspondent",
  correspondent: 2
})

// Объединить документы
bulk_edit_documents({
  documents: [6, 7, 8],
  method: "merge",
  metadata_document_id: 6,
  delete_originals: true
})

// Разделить документ на части
bulk_edit_documents({
  documents: [9],
  method: "split",
  pages: "[1-2,3-4,5]"
})

// Изменить несколько тегов одновременно
bulk_edit_documents({
  documents: [10, 11],
  method: "modify_tags",
  add_tags: [1, 2],
  remove_tags: [3, 4]
})

// Изменить пользовательские поля
bulk_edit_documents({
  documents: [12, 13],
  method: "modify_custom_fields",
  add_custom_fields: [
    { field: 2, value: "year" }
  ],
  remove_custom_fields: []
})

// Установить пустое значение пользовательского поля, например, поле даты, используемое как маркер ожидания
bulk_edit_documents({
  documents: [14],
  method: "modify_custom_fields",
  add_custom_fields: [
    { field: 9, value: "" }
  ],
  remove_custom_fields: []
})

post_document

Загрузить новый документ в Paperless-NGX.

Два режима загрузки:

  1. Режим Base64 (традиционный): Укажите file (контент в кодировке base64) + filename
  2. Режим файловой системы (эффективный): Укажите file_path (абсолютный путь на сервере)

Примечание по безопасности: При использовании file_path установите переменную окружения PAPERLESS_MCP_UPLOAD_PATHS (список разрешённых директорий, разделённых двоеточием) для ограничения загрузок определёнными расположениями. Без этого любой файл в файловой системе сервера может быть загружен.

Параметры: - file (необязательно): Содержимое файла в кодировке base64. Требуется либо file, либо file_path. - file_path (необязательно): Абсолютный путь к файлу в файловой системе сервера. Требуется либо file, либо file_path. - filename (необязательно): Имя файла. Обязательно при использовании file, необязательно при использовании file_path (определяется из пути). - title (необязательно): Заголовок документа - created (необязательно): Дата и время создания документа (например, "2024-01-19" или "2024-01-19 06:15:00+02:00") - correspondent (необязательно): ID корреспондента - document_type (необязательно): ID типа документа - storage_path (необязательно): ID пути хранения - tags (необязательно): Массив ID тегов - archive_serial_number (необязательно): Архивный серийный номер - custom_fields (необязательно): Массив ID пользовательских полей

Ограничение размера файла: 100 МБ для обоих режимов

// Режим Base64 (традиционный)
post_document({
  file: "base64_encoded_content",
  filename: "invoice.pdf",
  title: "January Invoice",
  created: "2024-01-19",
  correspondent: 1,
  document_type: 2,
  tags: [1, 3],
  archive_serial_number: "2024-001",
  custom_fields: [1, 2]
})

// Режим файловой системы (более эффективен для больших файлов)
post_document({
  file_path: "/var/uploads/invoice.pdf",
  title: "January Invoice",
  correspondent: 1,
  document_type: 2,
  tags: [1, 3]
})

Операции с тегами

list_tags

Получить все теги.

list_tags()

create_tag

Создать новый тег.

Параметры: - name: Имя тега - color (необязательно): Цвет в формате HEX (например, "#ff0000") - match (необязательно): Текстовый шаблон для сопоставления - matching_algorithm (необязательно): Число от 0 до 6: 0 - Нет 1 - Любое слово 2 - Все слова 3 - Точное совпадение 4 - Регулярное выражение 5 - Нечёткое слово 6 - Автоматически

create_tag({
  name: "Invoice",
  color: "#ff0000",
  match: "invoice",
  matching_algorithm: 5
})

Операции с корреспондентами

list_correspondents

Получить всех корреспондентов.

list_correspondents()

create_correspondent

Создать нового корреспондента.

Параметры: - name: Имя корреспондента - match (необязательно): Текстовый шаблон для сопоставления - matching_algorithm (необязательно): Число от 0 до 6: 0 - Нет 1 - Любое слово 2 - Все слова 3 - Точное совпадение 4 - Регулярное выражение 5 - Нечёткое слово 6 - Автоматически

create_correspondent({
  name: "ACME Corp",
  match: "ACME",
  matching_algorithm: 5
})

Операции с типами документов

list_document_types

Получить все типы документов.

list_document_types()

create_document_type

Создать новый тип документа.

Параметры: - name: Имя типа документа - match (необязательно): Текстовый шаблон для сопоставления - matching_algorithm (необязательно): Число от 0 до 6: 0 - Нет 1 - Любое слово 2 - Все слова 3 - Точное совпадение 4 - Регулярное выражение 5 - Нечёткое слово 6 - Автоматически

create_document_type({
  name: "Invoice",
  match: "invoice total amount due",
  matching_algorithm: 1
})

Операции с пользовательскими полями

list_custom_fields

Получить все пользовательские поля.

list_custom_fields()

get_custom_field

Получить конкретное пользовательское поле по ID.

Параметры: - id: ID пользовательского поля

get_custom_field({
  id: 1
})

create_custom_field

Создать новое пользовательское поле.

Параметры: - name: Имя пользовательского поля - data_type: Одно из значений "string", "url", "date", "boolean", "integer", "float", "monetary", "documentlink", "select" - extra_data (необязательно): Дополнительные данные для пользовательского поля, такие как варианты для select

create_custom_field({
  name: "Invoice Number",
  data_type: "string"
})

update_custom_field

Обновить существующее пользовательское поле.

Параметры: - id: ID пользовательского поля - name (необязательно): Новое имя пользовательского поля - data_type (необязательно): Новый тип данных - extra_data (необязательно): Дополнительные данные для пользовательского поля

update_custom_field({
  id: 1,
  name: "Updated Invoice Number",
  data_type: "string"
})

delete_custom_field

Удалить пользовательское поле.

Параметры: - id: ID пользовательского поля

delete_custom_field({
  id: 1
})

bulk_edit_custom_fields

Выполнить массовые операции над несколькими пользовательскими полями.

Параметры: - custom_fields: Массив ID пользовательских полей - operation: Одно из значений "delete"

bulk_edit_custom_fields({
  custom_fields: [1, 2, 3],
  operation: "delete"
})

Операции с почтой

Инструменты для управления почтовыми учётными записями Paperless и почтовыми правилами, обеспечивающими автоматическую загрузку писем. Пароли/токены учётных записей никогда не отображаются: они заменяются на *** во всех ответах инструментов.

list_mail_accounts

Получить список почтовых учётных записей, чтобы выбрать ID учётной записи при создании почтового правила. Пароли заменены на ***.

Параметры: - page (необязательно): Номер страницы - page_size (необязательно): Количество результатов на странице

list_mail_accounts()

get_mail_account

Получить одну почтовую учётную запись по ID. Поля пароля/токена заменены на ***.

Параметры: - id: ID почтовой учётной записи

get_mail_account({
  id: 1
})

process_mail_account

Вручную запустить обработку почты Paperless для одной учётной записи. Это может обработать письма, соответствующие активным почтовым правилам учётной записи.

Параметры: - id: ID почтовой учётной записи

process_mail_account({
  id: 1
})

list_mail_rules

Получить список почтовых правил с опциональной пагинацией.

Параметры: - page (необязательно): Номер страницы - page_size (необязательно): Количество результатов на странице

list_mail_rules()

get_mail_rule

Получить одно почтовое правило по ID.

Параметры: - id: ID почтового правила

get_mail_rule({
  id: 1
})

create_mail_rule

Создать почтовое правило. Сначала используйте list_mail_accounts для выбора учётной записи.

Обязательные параметры: - name: Имя правила - account: ID почтовой учётной записи - folder: Папка IMAP для сканирования (например, "INBOX")

Основные необязательные параметры: - enabled (по умолчанию true): Активно ли правило - filter_from / filter_to / filter_subject / filter_body: Сопоставление входящих писем - maximum_age: Обрабатывать только письма новее указанного количества дней - action: 1=Удалить, 2=Переместить в папку, 3=Отметить как прочитанное, 4=Пометить флагом, 5=Добавить тег - action_parameter: Целевая папка/тег для выбранного действия - assign_title_from: 1=Тема, 2=Имя вложения, 3=Не назначать - assign_tags / assign_correspondent / assign_document_type: Метаданные для применения - assign_correspondent_from: 1=Нет, 2=Адрес электронной почты, 3=Имя отправителя, 4=Использовать assign_correspondent - attachment_type: 1=Только вложения, 2=Все файлы, включая встроенные - consumption_scope: 1=Только вложения, 2=Полное письмо как .eml, 3=Оба варианта - pdf_layout: 0=Системная настройка по умолчанию, 1=Текст+HTML, 2=HTML+текст, 3=Только HTML, 4=Только текст

create_mail_rule({
  name: "Invoices",
  account: 1,
  folder: "INBOX",
  filter_subject: "invoice",
  action: 3,
  attachment_type: 1
})

update_mail_rule

Обновить существующее почтовое правило. Изменяются только те поля, которые вы указали.

Параметры: - id: ID почтового правила - ...любое из полей create_mail_rule для обновления

update_mail_rule({
  id: 1,
  enabled: false
})

delete_mail_rule

Удалить почтовое правило. Требуется явный флаг подтверждения. Это изменяет поведение будущей загрузки почты, но не удаляет существующие документы.

Параметры: - id: ID почтового правила - confirm: Должно быть true для подтверждения удаления

delete_mail_rule({
  id: 1,
  confirm: true
})

Обработка ошибок

Сервер будет отображать понятные сообщения об ошибках, если: - URL Paperless-NGX или API токен указаны неверно - Сервер Paperless-NGX недоступен - Запрошенная операция не удалась - Предоставленные параметры недействительны

Тестирование

Юнит-тесты

Запуск набора юнит-тестов (внешние зависимости не требуются):

npm test

E2E тесты

Набор E2E тестов запускает пустой экземпляр Paperless-ngx, компилированный MCP сервер и выполняет детерминированный последовательный сценарий через запросы tools/call — создаёт тег, корреспондента и тип документа, загружает PDF, затем выполняет list / get / search / download / thumbnail / bulk-edit для одного и того же документа. Без LLM и без клиента Paperless REST за пределами MCP.

Необходимые условия: Docker, Docker Compose и jq.

# 1. Собрать MCP сервер
npm run build

# 2. Запустить Paperless-ngx
docker compose -f docker-compose.e2e.yml up -d

# 3. Дождаться готовности Paperless и получить токен
TOKEN=$(curl -s -X POST http://localhost:8000/api/token/ \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"admin123"}' | jq -r '.token')

# 4. Запустить MCP сервер
node build/index.js --http --port 3001 \
  --baseUrl http://localhost:8000 --token "$TOKEN" &
MCP_PID=$!

# 5. Запустить E2E тесты
MCP_URL=http://localhost:3001/mcp \
PAPERLESS_URL=http://localhost:8000 \
PAPERLESS_TOKEN="$TOKEN" \
npm run test:e2e

# 6. Очистка
kill "$MCP_PID"
docker compose -f docker-compose.e2e.yml down -v

E2E тесты также автоматически запускаются в CI при каждом pull request и push в main, охватывая как CLI build/index.js, так и опубликованный Docker образ.

Разработка

Хотите внести вклад или изменить сервер? Вот что вам нужно знать:

  1. Клонируйте репозиторий
  2. Установите зависимости:
npm install
  1. Внесите изменения в server.js
  2. Тестируйте локально:
node server.js http://localhost:8000 your-test-token

Сервер построен с использованием: - litemcp: Фреймворк на TypeScript для создания MCP серверов - zod: Валидация схем с приоритетом TypeScript

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

Этот MCP сервер реализует эндпоинты из REST API Paperless-NGX. Для получения дополнительной информации об основном API см. официальную документацию.

Запуск MCP сервера

MCP сервер может работать в двух режимах:

1. stdio (по умолчанию)

Это режим по умолчанию. Сервер взаимодействует через stdio, что подходит для CLI и прямых интеграций.

npm run start -- <baseUrl> <token>

2. HTTP (Streamable HTTP Transport)

Для запуска сервера как HTTP сервиса используйте флаг --http. Вы также можете указать порт с помощью --port (по умолчанию: 3000). Этот режим требует установки Express (он включён как зависимость).

npm run start -- <baseUrl> <token> --http --port 3000
  • MCP API будет доступен по адресу POST /mcp на указанном порту.
  • Каждый запрос обрабатывается без сохранения состояния, в соответствии с паттерном StreamableHTTPServerTransport.
  • GET и DELETE запросы к /mcp вернут 405 Method Not Allowed.

API токен для каждого запроса (режим HTTP/Docker)

В HTTP режиме клиенты аутентифицируются, предоставляя API токен Paperless-NGX через стандартный заголовок Authorization:

Authorization: Bearer <paperless-ngx-api-token>

Токен передаётся напрямую в Paperless-NGX, поэтому права доступа Paperless каждого клиента обеспечиваются на протяжении всего процесса. Это позволяет одному экземпляру сервера обслуживать нескольких пользователей, каждый со своим токеном. Такое поведение применимо к обоим эндпоинтам /mcp и /sse.

⚠️ Изменение, не совместимое с предыдущими версиями, в v2.0.0 — HTTP режим теперь по умолчанию требует аутентификации.

Ранее запрос без заголовка Authorization молча использовал токен сервера PAPERLESS_API_KEY, что делало HTTP эндпоинт доступным для любого, кто мог подключиться к порту. Начиная с v2.0.0, запросы без Bearer токена отклоняются с ошибкой 401 Unauthorized. Серверный токен никогда не используется для неаутентифицированных запросов, если вы явно не включите его с помощью --no-auth.

Сценарий --no-auth выключен (по умолчанию) --no-auth включён
Клиент отправляет Authorization: Bearer <tok> <tok> (от клиента) <tok> (от клиента)
Нет заголовка, PAPERLESS_API_KEY / --token задан 401 Unauthorized серверный токен
Нет заголовка, нет серверного токена 401 Unauthorized 401 Unauthorized

Миграция с v1.x: если вы использовали старый механизм отката (общий PAPERLESS_API_KEY для клиентов, которые не отправляют токен), у вас есть два варианта:

  1. Рекомендуется: чтобы каждый клиент отправлял Authorization: Bearer <paperless-token>.
  2. Восстановить старое поведение (только для доверенных/локальных сетей): запустите сервер с флагом --no-auth, например, добавьте его к command/args Docker или к вашей команде в CLI. Для этого необходим серверный токен (PAPERLESS_API_KEY или --token).

Развёртывание с помощью Docker

MCP сервер может быть развёрнут с помощью Docker и Docker Compose. Docker образ автоматически запускается в HTTP режиме с поддержкой SSE (Server-Sent Events) на порту 3000.

Конфигурация Docker Compose

Создайте файл docker-compose.yml:

services:
paperless-mcp:
  container_name: paperless-mcp
  image: ghcr.io/baruchiro/paperless-mcp:latest
  environment:
    - PAPERLESS_URL=http://your-paperless-ngx-server:8000
    - PAPERLESS_API_KEY=your-paperless-api-key
    - PAPERLESS_PUBLIC_URL=https://paperless-ngx.yourpublicurl.com
  ports:
    - "3000:3000"
  restart: unless-stopped

Затем выполните:

docker-compose up -d

Использование с расширением Continue для VS Code

Если вы используете расширение Continue для VS Code, вы можете настроить его для работы с Dockerизированным MCP сервером через SSE.

Создайте или отредактируйте файл .continue/mcpServers/paperless-mcp.yaml в корне вашего рабочего пространства:

name: Paperless
version: 0.0.1
schema: v1
mcpServers:
- name: Paperless
  type: sse
  url: http://localhost:3000/sse

Примечания: - Замените localhost на IP-адрес или имя хоста Docker, если сервер запущен на удалённой машине - Docker контейнер обрабатывает аутентификацию через переменные окружения, поэтому указывать учётные данные в конфиге Continue не нужно - SSE эндпоинт доступен по адресу /sse на настроенном порту (по умолчанию: 3000)

Благодарности

Этот проект является форком nloui/paperless-mcp. Большое спасибо автору оригинала за его работу. Вклады и улучшения могут быть возвращены в основной репозиторий.

Отладка

Для отладки MCP сервера в VS Code используйте следующую конфигурацию запуска:

{
    "type": "node",
    "request": "launch",
    "name": "Debug Paperless MCP (HTTP, ts-node ESM)",
    "program": "${workspaceFolder}/node_modules/ts-node/dist/bin.js",
    "args": [
        "--esm",
        "src/index.ts",
        "--http",
        "--baseUrl",
        "http://your-paperless-instance:8000",
        "--token",
        "your-api-token",
        "--port",
        "3002"
    ],
    "env": {
        "NODE_OPTIONS": "--loader ts-node/esm",
    },
    "console": "integratedTerminal",
    "skipFiles": [
        "<node_internals>/**"
    ]
}

Важно: Перед отладкой раскомментируйте следующую строку в src/index.ts (примерно на строке 175):

// await new Promise((resolve) => setTimeout(resolve, 1000000));

Это предотвратит немедленное завершение работы сервера и позволит вам устанавливать точки останова и отлаживать код.

Комментарии
Войдите, чтобы оставить комментарий