paperless-ngx-mcp
v0.1.5
Published
Model Context Protocol (MCP) server for Paperless-NGX. Lets AI assistants manage documents, tags, correspondents, document types, custom fields, saved views, storage paths, workflows, share links, notes, trash, and tasks via the Paperless-NGX REST API.
Maintainers
Readme
paperless-ngx-mcp
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, workflows, notes, trash, and tasks.
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
claude mcp add paperless --scope user \
--env PAPERLESS_URL=https://your-paperless-instance \
--env PAPERLESS_API_KEY=your-api-token \
-- npx -y paperless-ngx-mcpDrop --scope user to install for the current project only. See claude mcp add --help for more options.
Codex CLI
codex mcp add paperless \
--env PAPERLESS_URL=https://your-paperless-instance \
--env PAPERLESS_API_KEY=your-api-token \
-- npx -y paperless-ngx-mcpThis writes the entry to ~/.codex/config.toml.
Claude Desktop, Cursor, Cline, and other MCP clients
Add this to your client's MCP config file (e.g. claude_desktop_config.json, ~/.cursor/mcp.json, ~/.config/cline/mcp.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"
}
}
}
}Get your Paperless-NGX API token
- Log into your Paperless-NGX instance.
- Click your username (top right) → My Profile.
- Click the circular arrow button to generate a new token.
Configuration
| Variable | Required | Purpose |
|---|---|---|
| PAPERLESS_URL | yes | Base URL the MCP server uses to talk to Paperless-NGX. |
| PAPERLESS_API_KEY | yes | API token (see above). |
| PAPERLESS_PUBLIC_URL | no | Public URL the assistant uses when constructing browser links to documents. Falls back to PAPERLESS_URL. |
CLI flags (--baseUrl, --token, --publicUrl, --http, --port) 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"
Available Tools
The server registers tools across ten 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_next_asn
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, update_share_link, delete_share_link
Workflows
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
System / Notes / Trash / Tasks
get_statistics, list_document_notes, create_document_note, delete_document_note, list_trash, restore_from_trash, empty_trash, list_tasks, acknowledge_tasks
Tool naming convention (for permission allowlists)
Tool names are verb-first, so wildcard-based permission rules group cleanly by operation:
| Wildcard | Covers |
|---|---|
| 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_*_bulk | All bulk-edit operations across entity types |
| mcp__paperless__delete_* | ⚠️ Destructive — system-wide deletes |
A read-only allowlist is therefore: list_*, get_*, search_*, download_*. Write access without destructive operations: add create_*, update_*, edit_*_bulk, post_document, email_document. delete_* 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, default25): maximum number of inbox documents to triage in one pass.
Notable tool details
edit_documents_bulk
Perform bulk operations on multiple documents.
Parameters:
documents: array of document IDsmethod: one ofset_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- 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
// Add a tag to multiple documents
edit_documents_bulk({ documents: [1, 2, 3], method: "add_tag", tag: 5 })
// Merge documents
edit_documents_bulk({
documents: [6, 7, 8],
method: "merge",
metadata_document_id: 6,
delete_originals: true,
})
// Split a document into parts
edit_documents_bulk({ documents: [9], method: "split", pages: "[1-2,3-4,5]" })
// Modify multiple tags at once
edit_documents_bulk({
documents: [10, 11],
method: "modify_tags",
add_tags: [1, 2],
remove_tags: [3, 4],
})post_document
Upload a new document.
Parameters: file (base64-encoded contents), filename, plus optional title, created, correspondent, document_type, storage_path, tags, archive_serial_number, custom_fields.
Matching algorithms
create_tag, create_correspondent, create_document_type, and create_storage_path accept a matching_algorithm (0–6):
| Value | Meaning | |---|---| | 0 | None | | 1 | Any word | | 2 | All words | | 3 | Exact match | | 4 | Regular expression | | 5 | Fuzzy word | | 6 | Automatic |
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):
# via env vars (recommended)
PAPERLESS_URL=http://localhost:8000 PAPERLESS_API_KEY=xxx npx -y paperless-ngx-mcp
# or via CLI flags
npx -y paperless-ngx-mcp --baseUrl http://localhost:8000 --token xxxHTTP (Streamable HTTP transport)
Use the --http flag to expose the server over HTTP. --port defaults to 3000.
npx -y paperless-ngx-mcp --baseUrl http://localhost:8000 --token xxx --http --port 3000- The MCP API is available at
POST /mcpon the chosen port. - Each request is handled statelessly via
StreamableHTTPServerTransport. - A legacy
GET /sse+POST /messagesSSE transport is also exposed for clients that don't yet support the streamable transport.
Error Handling
Tool calls return clear errors when:
PAPERLESS_URLorPAPERLESS_API_KEYis missing or wrong- The Paperless-NGX server is unreachable
- The underlying API rejects the operation
- 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.
git clone https://github.com/cubinet-code/paperless-ngx-mcp.git
cd paperless-ngx-mcp
npm install # install dependencies
npm 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/inspectornpm 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:
npm run test:e2e:up # start the test stack (paperless + redis)
npm run test:e2e # run the e2e suite against it
npm run test:e2e:down # tear down and remove volumesBuilt with:
- @modelcontextprotocol/sdk — MCP server SDK
- zod — schema validation
- axios — HTTP client (with keep-alive agents and a 60s timeout)
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.
