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 分