mcp-paperless-ngx
An MCP server that connects AI assistants such as Claude to Paperless-ngx. Search, file, tag and analyse documents without opening the web interface. I built it myself and released it as open source.
Why I built it
The main reason was saving tokens. A Paperless document carries its full OCR text. If a server passes that through untrimmed, a single search fills the model's memory, and every further question gets more expensive and less accurate. In the two active servers I looked at, I found no trimming of responses. Mine fetches only the fields it needs for lists. The full text sits behind its own tool, page by page.
The second reason: the server supports Paperless-ngx 3 and later completely, and nothing else. It speaks only API version 10 and nothing older. In return it uses everything version 3 brings, for example nested tags, document versions, share link bundles and the PDF tools. Of the 92 documented endpoints, each one is either available as a tool or left out with a written reason. A test checks this on every run. If you still run Paperless-ngx 2, use a different server.
Installation
You need Node 20 or newer, Paperless-ngx 3 and an API token.
1. Get an API token
In the Paperless web interface, click your user name at the top right, then “My Profile”. Next to the API token field there is a round arrow. It generates the token.
2. Check the connection
This command tests whether the server can reach your instance, then exits:
PAPERLESS_URL=https://paperless.example.com PAPERLESS_TOKEN=your-token npx -y mcp-paperless-ngx --check
3. Set up in Claude Code
claude mcp add paperless --scope user \
--env PAPERLESS_URL=https://paperless.example.com \
--env PAPERLESS_TOKEN=your-token \
-- npx -y mcp-paperless-ngx
4. In Claude Desktop, Cursor, Cline and other clients
Add the server to the client's MCP configuration:
{
"mcpServers": {
"paperless": {
"command": "npx",
"args": ["-y", "mcp-paperless-ngx"],
"env": {
"PAPERLESS_URL": "https://paperless.example.com",
"PAPERLESS_TOKEN": "your-token"
}
}
}
}
Restart the client afterwards.
Settings
All settings are environment variables. Only the first two are required.
| Variable | Default | Purpose |
|---|---|---|
PAPERLESS_URL | none | Address of your Paperless instance |
PAPERLESS_TOKEN | none | API token |
PAPERLESS_TOOLSETS | see below | Which tool groups are active, or all |
PAPERLESS_READ_ONLY | false | Only tools that cannot change anything |
PAPERLESS_PUBLIC_URL | same as PAPERLESS_URL | Address used in links, if Paperless has a different name from outside |
PAPERLESS_HEADERS | none | Extra request headers, needed behind forward-auth such as Authentik or Authelia |
PAPERLESS_DOWNLOAD_DIR | temp folder | Where downloaded files are written |
PAPERLESS_MAX_PAGE_SIZE | 100 | Upper limit for list sizes, whatever the model asks for |
With --list-tools the server shows which tools are currently active.
Tool groups and context cost
Seven groups are active by default: documents, metadata, customfields, views, sharing, workflows and system. The groups mail and admin are off, because most sessions never need them. Every additional tool costs context on every request:
| Groups | Tools | Cost per request |
|---|---|---|
all (all) | 99 | about 20,500 tokens |
| default | 85 | about 18,500 tokens |
documents,metadata | 49 | about 12,900 tokens |
If you only want to search and file documents, set PAPERLESS_TOOLSETS=documents,metadata. That saves more than any trimming of responses.
Behind a login proxy
If a forward-auth proxy sits in front of Paperless, the server needs extra headers. You pass them as JSON, for example {"X-Auth":"secret-value"}.
Using it
Once it is set up, you ask the assistant in plain language. Examples:
- “Find all documents tagged ‘Tax’ from last year.”
- “Which documents in the inbox still have no tag?”
- “Summarise the last three documents from ‘Example Ltd’.”
There are also three ready-made commands. In clients with MCP support they appear as slash commands:
triage_inboxgoes through the documents that are not filed yet and suggests tags, correspondents and types. Existing entries take priority. Nothing is applied until you confirm.find_documentfinds a document from a vague description. It searches cheaply first, then more broadly.audit_sharingreviews all public share links and flags the ones that never expire.
Safety
The server can delete things, otherwise it would be no use as a document manager. It protects you in several places. Tools that delete something are marked as destructive, so your client can ask first. With PAPERLESS_READ_ONLY=true all writing tools disappear from the list, so the model never sees them. Bulk actions take only explicit lists of document IDs, never “everything matching this filter”. There are deliberately no tools for credentials, such as new tokens or TOTP enrolment.
A note on sharing: create_share_link creates a publicly reachable address.
The current version
The current version is 0.1.1, under the MIT license. The source code is on GitHub, the package on npm. The server is also listed in the official MCP registry. The project is unofficial and not affiliated with Paperless-ngx.
