Paperless-ngx

io.github.cubinet-code由 GitHub 账号 cubinet-code 发布v3.2.1更新于 Oct 24, 2026

Full Paperless-ngx API for AI assistants: search, tag, edit and upload documents, workflows and more

已验证STDIO仅桌面效率与工作流文件与存储

概览

AI 生成的概览

该 MCP 服务器封装完整的 Paperless-ngx REST API,让助手能搜索、打标签、编辑、上传和管理文档、工作流与邮件规则。

可以做什么
搜索、读取、下载和上传文档,包括批量下载、版本、缩略图、预览和元数据,还可发送文档邮件,以及批量打标签、合并、拆分、旋转和移除密码。创建、更新和删除标签、通信方、文档类型、自定义字段、存储路径和已保存视图。管理分享链接与打包、工作流及其触发器和动作,以及邮件账户和规则,包括立即处理邮件。查看系统状态、统计和归档选项,处理文档备注、回收站和任务,并运行收件箱分拣提示,先提出元数据建议再等待确认。
适用场景
适合自建 Paperless-ngx 实例的用户,希望助手帮忙查找、归档、打标签或清理文档,或配置工作流和邮件规则,而不必在网页界面中逐项操作。
运行要求
通过 stdio 在本地运行,通常由 MCP 客户端用 npx 或 Docker 启动。需要一个可访问的 Paperless-ngx 实例(面向 3.2 版,不支持更旧版本),以及环境变量 PAPERLESS_URL 和 PAPERLESS_API_KEY,后者在“我的资料”中生成。PAPERLESS_PUBLIC_URL 为可选项。另有 HTTP 模式,但仅支持单实例且无身份验证。
安装前请注意
PAPERLESS_API_KEY 中的 API 令牌对 Paperless 实例拥有广泛权限。许多工具会写入、修改或删除数据:删除类工具、empty_trash、合并和批量删除需要 confirm,但创建、更新、批量编辑、上传、恢复和确认任务不需要。process_mail_account 会抓取邮件并执行规则,可能在服务器上移动或删除邮件。HTTP 模式没有身份验证且绑定所有网络接口,请勿暴露在不可信网络。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Paperless-ngx,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

paperless-ngx-mcp

[CI] [License: ISC] [npm] [npm downloads]

A Model Context Protocol server for Paperless-NGX. Exposes the full Paperless-NGX REST API to AI assistants — documents, tags, correspondents, document types, custom fields, storage paths, saved views, share links and bundles, workflows, mail accounts and rules, document versions, notes, trash, and tasks.

[Claude Code triaging a Paperless-ngx inbox with paperless-ngx-mcp]

Why this one?

  • Complete, and it stays that way. A CI test checks every endpoint in Paperless's /api/schema/ against the tools here and fails when upstream adds one that is neither wrapped nor deliberately skipped.
  • Tested against real Paperless. The end-to-end suite runs the tools against a live Paperless-ngx 3.2.1 container, not mocks.
  • Asks before it breaks things. Every delete_* tool, empty_trash, merge_documents_as_versions and bulk delete require confirm: true; bulk edits across "all matching documents" refuse filters Paperless would silently ignore; and the triage_inbox prompt proposes changes and waits for your go-ahead before writing anything.
  • Easy to allowlist. Verb-first tool names (list_*, get_*, delete_*, …) group into one permission wildcard each.
  • Install it your way: npx, a Docker image, a one-click Claude Desktop extension, or the official MCP Registry.

Compatibility

Targets Paperless-ngx 3.2 (tested against 3.2.1). Older Paperless versions are not supported — use [email protected] for Paperless 2.x. The package major version tracks the Paperless-ngx major it targets; there are no 1.x or 2.x releases.

Quick Start

The server is published to npm as paperless-ngx-mcp. You can run it with npx — no clone or build required.

Claude Code

bash
claude mcp add paperless --scope user \  --env PAPERLESS_URL=https://your-paperless-instance \  --env PAPERLESS_API_KEY=your-api-token \  -- npx -y paperless-ngx-mcp

Drop --scope user to install for the current project only. See claude mcp add --help for more options.

Codex CLI

bash
codex mcp add paperless \  --env PAPERLESS_URL=https://your-paperless-instance \  --env PAPERLESS_API_KEY=your-api-token \  -- npx -y paperless-ngx-mcp

This writes the entry to ~/.codex/config.toml.

Claude Desktop (extension)

Download paperless-ngx-mcp.mcpb from the latest release and double-click it, or install it from Settings → Extensions. Claude Desktop asks for your Paperless URL and API token.

Claude Desktop, Cursor, Cline, and other MCP clients

[Add to Cursor] [Install in VS Code]

The buttons install placeholder values; replace PAPERLESS_URL and PAPERLESS_API_KEY afterwards. Or add this to your client's MCP config file (e.g. claude_desktop_config.json, ~/.cursor/mcp.json, ~/.config/cline/mcp.json):

json
{  "mcpServers": {    "paperless": {      "command": "npx",      "args": ["-y", "paperless-ngx-mcp"],      "env": {        "PAPERLESS_URL": "https://your-paperless-instance",        "PAPERLESS_API_KEY": "your-api-token",        "PAPERLESS_PUBLIC_URL": "https://your-public-domain"      }    }  }}

Docker

A multi-arch image (amd64, arm64) is published to ghcr.io/cubinet-code/paperless-ngx-mcp. As a stdio server in any MCP client config:

json
{  "mcpServers": {    "paperless": {      "command": "docker",      "args": ["run", "-i", "--rm", "-e", "PAPERLESS_URL", "-e", "PAPERLESS_API_KEY", "ghcr.io/cubinet-code/paperless-ngx-mcp"],      "env": {        "PAPERLESS_URL": "https://your-paperless-instance",        "PAPERLESS_API_KEY": "your-api-token"      }    }  }}

Or as a long-running Streamable HTTP server. It has no authentication, so keep it off untrusted networks:

bash
docker run -d -p 127.0.0.1:3000:3000 \  -e PAPERLESS_URL=https://your-paperless-instance \  -e PAPERLESS_API_KEY=your-api-token \  ghcr.io/cubinet-code/paperless-ngx-mcp --http --port 3000

Get your Paperless-NGX API token

  1. Log into your Paperless-NGX instance.
  2. Click your username (top right) → My Profile.
  3. Click the circular arrow button to generate a new token.

Configuration

VariableRequiredPurpose
PAPERLESS_URLyesBase URL the MCP server uses to talk to Paperless-NGX.
PAPERLESS_API_KEYyesAPI token (see above).
PAPERLESS_PUBLIC_URLnoPublic URL the assistant uses when constructing browser links to documents. Falls back to PAPERLESS_URL.

CLI flags (--baseUrl, --token, --publicUrl, --http, --port, plus the HTTP session limits) take precedence over environment variables.

Example Usage

Things you can ask Claude (or any MCP-aware assistant):

  • "Show me all documents tagged as 'Invoice'"
  • "Search for documents containing 'tax return'"
  • "Create a new tag called 'Receipts' with color #FF0000"
  • "Download document #123"
  • "List all correspondents"
  • "Create a new document type called 'Bank Statement'"
  • "Empty the trash"
  • "Show me pending consumption tasks"
  • "Move every document from correspondent 'ACME GmbH (mail)' to 'ACME GmbH'"
  • "Remove the password from document #55 and keep the unlocked file as a new version"
  • "Create a workflow that strips PDF passwords from uploaded bank statements"
  • "Which mail rule is creating a new correspondent for every sender?"

Available Tools

The server registers tools across twelve domains.

Documents

list_documents, get_document, get_document_content, search_documents, download_document, download_documents_bulk, get_document_thumbnail, get_document_preview, get_document_history, get_document_metadata, update_document, post_document, email_document, edit_documents_bulk, delete_document, search_autocomplete, get_document_suggestions, get_document_ai_suggestions, get_next_asn, upload_document_version, update_document_version, delete_document_version, merge_documents_as_versions

Tags

list_tags, get_tag, create_tag, update_tag, delete_tag, edit_tags_bulk

Correspondents

list_correspondents, get_correspondent, create_correspondent, update_correspondent, delete_correspondent, edit_correspondents_bulk

Document Types

list_document_types, get_document_type, create_document_type, update_document_type, delete_document_type, edit_document_types_bulk

Custom Fields

list_custom_fields, get_custom_field, create_custom_field, update_custom_field, delete_custom_field, edit_custom_fields_bulk

Storage Paths

list_storage_paths, get_storage_path, create_storage_path, update_storage_path, delete_storage_path, test_storage_path

Saved Views

list_saved_views, get_saved_view, create_saved_view, update_saved_view, delete_saved_view

Share Links

list_share_links, list_document_share_links, get_share_link, create_share_link, delete_share_link, list_share_link_bundles, get_share_link_bundle, create_share_link_bundle, rebuild_share_link_bundle, delete_share_link_bundle

Workflows

list_workflows, get_workflow, create_workflow, update_workflow, delete_workflow, list_workflow_actions, get_workflow_action, create_workflow_action, update_workflow_action, delete_workflow_action, list_workflow_triggers, get_workflow_trigger, create_workflow_trigger, update_workflow_trigger, delete_workflow_trigger

Mail

list_mail_accounts, get_mail_account, create_mail_account, update_mail_account, delete_mail_account, test_mail_account, process_mail_account, list_mail_rules, get_mail_rule, create_mail_rule, update_mail_rule, delete_mail_rule

System / Notes / Trash / Tasks

get_statistics, get_system_status, get_filing_options, list_document_notes, create_document_note, delete_document_note, list_trash, restore_from_trash, empty_trash, list_tasks, list_active_tasks, get_task_status_counts, get_task_summary, acknowledge_tasks

Tool naming convention (for permission allowlists)

Tool names are verb-first, so wildcard-based permission rules group cleanly by operation:

WildcardCovers
mcp__paperless__list_*All list/index reads
mcp__paperless__get_*All single-item reads
mcp__paperless__search_*Full-text search and autocomplete
mcp__paperless__download_*download_document and download_documents_bulk
mcp__paperless__create_*All create endpoints
mcp__paperless__update_*Per-item PATCH updates
mcp__paperless__edit_*_bulkAll bulk-edit operations across entity types
mcp__paperless__delete_*⚠️ Destructive — system-wide deletes
mcp__paperless__test_*Dry-run checks: test_storage_path, test_mail_account
mcp__paperless__upload_*upload_document_version
mcp__paperless__rebuild_*rebuild_share_link_bundle
mcp__paperless__merge_*⚠️ merge_documents_as_versions — merged documents stop existing on their own
mcp__paperless__process_*process_mail_account — fetches mail now and runs its rules (which may delete or move mail on the server)

A read-only allowlist is therefore: list_*, get_*, search_*, download_*, test_*. Write access without destructive operations: add create_*, update_*, edit_*_bulk, upload_*, rebuild_*, post_document, email_document, restore_from_trash, acknowledge_tasks. delete_*, merge_*, process_* and empty_trash should require explicit user approval.

Prompts

The server also registers MCP prompts — reusable, parameterized instructions that surface as slash commands in clients like Claude Code (e.g. /mcp__paperless__triage_inbox).

triage_inbox

Walks the assistant through inbox triage: gather existing tags / correspondents / document types, propose metadata for each inbox document preferring existing items, present a confirmation table, and only apply changes after the user replies apply. New correspondents / types / tags are flagged (NEW) so you can veto creations before they happen.

Argument:

  • limit (optional, default 25): maximum number of inbox documents to triage in one pass.

Notable tool details

edit_documents_bulk

Perform bulk operations on multiple documents.

Parameters:

  • Selection: documents (array of IDs), or all: true + filters with optional excluded_documents. filters takes Paperless document filter names such as correspondent__id, tags__id__all, document_type__id, title_content or query — not list_documents' tool arguments. Keys Paperless doesn't know are refused (it would otherwise ignore them and select every document), a preview query catches invalid values, and the result reports matched_documents. all: true isn't supported for merge, split, delete_pages, edit_pdf or remove_password.
  • method: one of set_correspondent, set_document_type, set_storage_path, add_tag, remove_tag, modify_tags, modify_custom_fields, delete, reprocess, set_permissions, merge, split, rotate, delete_pages, edit_pdf, remove_password
  • Method-specific parameters: correspondent, document_type, storage_path, tag, add_tags, remove_tags, add_custom_fields, remove_custom_fields, set_permissions, owner, merge, metadata_document_id, delete_originals, pages, degrees, operations, update_document, include_metadata, password, delete_original, remote_ocr
typescript
// Add a tag to multiple documentsedit_documents_bulk({ documents: [1, 2, 3], method: "add_tag", tag: 5 })
// Merge documentsedit_documents_bulk({  documents: [6, 7, 8],  method: "merge",  metadata_document_id: 6,  delete_originals: true,})
// Split a document into partsedit_documents_bulk({ documents: [9], method: "split", pages: "[1-2,3-4,5]" })
// Modify multiple tags at onceedit_documents_bulk({  documents: [10, 11],  method: "modify_tags",  add_tags: [1, 2],  remove_tags: [3, 4],})
// Move every document from a duplicate correspondent (12) to the canonical one (34)edit_documents_bulk({ all: true, filters: { correspondent__id: 12 }, method: "set_correspondent", correspondent: 34 })
// Unlock a password-protected PDF, keeping the result as a new versionedit_documents_bulk({ documents: [55], method: "remove_password", password: "…", update_document: true })

Paperless answers remove_password with OK even when it skips a document (its latest version isn't encrypted) or the password is wrong, so check the document's versions afterwards.

Workflows

A workflow — its triggers plus the actions they run — is what Paperless executes; create_workflow builds one in a single call. Standalone triggers and actions (create_workflow_trigger / create_workflow_action) do nothing on their own, and Paperless deletes unattached ones whenever any workflow is updated.

  • Action types: 1 assignment, 2 removal, 3 email, 4 webhook, 5 password removal, 6 move to trash, 7 remote OCR, 8 apply AI suggestions. Remote OCR needs a consumption-started trigger; AI suggestions need a trigger other than consumption-started.
  • update_workflow changes only what you pass — but a triggers or actions list replaces the whole list: entries with an id are updated, entries without one are created, and omitted ones are deleted. get_workflow output can be edited and sent straight back.
  • PDF passwords of password-removal actions are always returned masked (**********). Sending the masked list back keeps the stored passwords; a new action needs the real ones.
  • Which filters a trigger checks depends on its type: sources, filter_path and filter_mailrule only work on consumption-started triggers (type 1); tag/correspondent/type/storage-path filters, filter_custom_field_query and content matching only on added/updated/scheduled (types 2–4); filter_filename on every type.
Document versions

upload_document_version adds a new file to an existing document (a signed copy, a corrected scan), and merge_documents_as_versions folds duplicate documents into one. Content, search, downloads and get_document_metadata follow the latest version, but page_count and the file names on get_document describe the original (root) version — check get_document_content to see whether the current version is readable.

Reading and editing single documents
  • get_filing_options returns every tag, correspondent, document type, storage path and custom field (id + name) in one call — fetch it once before filing instead of guessing IDs.
  • update_document takes add_tags / remove_tags to change single tags without touching the rest. tags replaces the whole list. Every tag change returns tag_changes: { added, removed }.
  • list_documents takes ids to read several known documents in one call, and fields (on get_document too) to return only what you need, e.g. ["title", "tags"].
  • get_document_content takes max_chars and offset for long documents; the result then reports total_chars and truncated. Paperless stores the text without page boundaries, so slices are by characters.
  • search_documents searches the full-text index (mode: query for advanced syntax — the default, text for plain words, title for titles only). The index can lag behind; list_documents with search matches substrings straight from the database.
post_document

Upload a new document.

Parameters: file, filename, plus optional title, created, correspondent, document_type, storage_path, tags, archive_serial_number, custom_fields, poll, poll_timeout_seconds.

file accepts base64-encoded contents (the universal method — works for any deployment, since the bytes travel over the wire) or an absolute file path that the server reads from its own filesystem. The path option only works when the MCP server runs on the same machine as the file (local/stdio deployments); for a remote server, use base64.

Upload is asynchronous. By default the tool returns a task UUID (track it with list_tasks). Set poll: true to wait for the consumer to finish and get the result in one call — the new document_id on success, or the consumer error on failure. poll_timeout_seconds (default 30, max 300) caps the wait; raise it for large scans where OCR is slow.

Matching algorithms

create_tag, create_correspondent, create_document_type, and create_storage_path accept a matching_algorithm (0–6). Workflow triggers accept 0–5 (no Automatic):

ValueMeaning
0None
1Any word
2All words
3Exact match
4Regular expression
5Fuzzy word
6Automatic

Since Paperless-ngx 3.2, Automatic matching only assigns when the classifier is confident enough (PAPERLESS_CLASSIFIER_MATCH_THRESHOLD, default 0.6), and regular-expression matching gives up after PAPERLESS_MATCH_REGEX_TIMEOUT_SECONDS (default 0.1 s) — raise it if regex rules miss on long documents.

Running the MCP Server

stdio (default)

The default mode. The server communicates over stdio — that's what every MCP client config in the Quick Start uses. You usually never run this manually; the MCP client launches it for you.

If you do want to run it directly (e.g. for debugging):

bash
# via env vars (recommended)PAPERLESS_URL=http://localhost:8000 PAPERLESS_API_KEY=xxx npx -y paperless-ngx-mcp
# or via CLI flagsnpx -y paperless-ngx-mcp --baseUrl http://localhost:8000 --token xxx

HTTP (Streamable HTTP transport)

Use the --http flag to expose the server over HTTP. --port defaults to 3000.

bash
npx -y paperless-ngx-mcp --baseUrl http://localhost:8000 --token xxx --http --port 3000
  • The MCP API is available at POST /mcp on the chosen port, backed by StreamableHTTPServerTransport in stateful mode.
  • The first request (an initialize call) creates a session and returns an Mcp-Session-Id header; subsequent requests must send that header back to reuse the same session. Transports are kept in an in-memory Map, so this only works for single-instance deployments.
  • GET /mcp streams server-initiated messages for a session; DELETE /mcp terminates it and evicts it from the map. Both require a valid Mcp-Session-Id header.
  • A legacy GET /sse + POST /messages SSE transport is also exposed for clients that don't yet support the streamable transport.
Session limits

Every session holds its own MCP server instance (~3.5 MB), and the HTTP port has no authentication — so sessions are bounded:

FlagEnvironment variableDefaultPurpose
--maxSessionsPAPERLESS_MAX_SESSIONS50Concurrent sessions allowed. Past this, initialize is refused with HTTP 503.
--sessionIdleMinutesPAPERLESS_SESSION_IDLE_MINUTES30Evict a session after this long with no activity.

A client that is actively connected — including one holding a GET /mcp stream open — is never evicted, no matter how long it stays idle. Only genuinely abandoned sessions are reclaimed.

Because sessions live in memory, --http only works for single-instance deployments. Do not expose the port to an untrusted network: there is no auth, and it binds all interfaces.

Error Handling

Tool calls return clear errors when:

  • PAPERLESS_URL or PAPERLESS_API_KEY is missing or wrong
  • The Paperless-NGX server is unreachable
  • The underlying API rejects the operation — Paperless's own message is passed through (e.g. {"non_field_errors":["password not specified"]} (HTTP 400)), while HTML error pages are reduced to the status line
  • A Paperless call doesn't finish within 90 seconds (downloads are exempt); for a timed-out write the error warns that the change may already have been applied
  • Tool parameters fail validation

Development

You only need this section if you're modifying the server itself. End users should follow the Quick Start instead — there's no need to clone or build.

bash
git clone https://github.com/cubinet-code/paperless-ngx-mcp.gitcd paperless-ngx-mcpnpm install        # install dependenciesnpm run start      # run the server with tsx (no build step)npm run build      # compile TypeScript to build/npm test           # unit tests (node:test + tsx)npm run inspect    # build, then launch @modelcontextprotocol/inspector

npm run start accepts the same flags / env vars as the built binary.

End-to-end tests

E2E tests spin up a real Paperless-NGX container via Docker Compose:

bash
npm run test:e2e:up    # start the test stack (paperless + redis)npm run test:e2e       # run the e2e suite against itnpm run test:e2e:down  # tear down and remove volumes

Runs against ghcr.io/paperless-ngx/paperless-ngx:3.2.1.

Built with:

  • @modelcontextprotocol/sdk — MCP server SDK
  • zod — schema validation
  • axios — HTTP client (with keep-alive agents, a 60s idle timeout and a 90s per-request deadline)

API Documentation

This MCP server wraps endpoints from the Paperless-NGX REST API. See the official API documentation for details on the underlying behaviour and field semantics.

License

ISC. See LICENSE.

来源:README.md,提交 7bd4e08

工具

0
SourceWeft 尚未在沙箱中启动过该软件包,因此其工具未知。

版本历史

2
  1. v3.2.1最新Oct 1, 2026
  2. v3.2.0Sep 23, 2026

评分

已满足适用检查项的 50%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分

    请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。

  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具15 分

    请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。

  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分