paperless-mcp
An authenticated Model Context Protocol server that exposes a Paperless-ngx instance over streamable HTTP with static bearer-token authentication, built with FastMCP.
Use it to: search and read archived documents, inspect Paperless metadata, download files, update document properties, and upload new documents from any HTTP-capable MCP client.
Why Paperless MCP?
- Useful document access: eight focused tools cover retrieval, metadata, downloads, updates, and ingestion.
- Read-only mode: one environment variable disables every mutating tool.
- Authenticated transport: every MCP request requires a dedicated bearer token independent from the Paperless API token.
- Self-hosted deployment: runs beside Paperless-ngx or on another private Linux host with the included systemd unit.
- No live-instance tests: the test suite uses mocked HTTP requests and never needs access to real documents.
[!IMPORTANT] Start with
PAPERLESS_READ_ONLY=1unless clients need to update metadata or upload documents. This server is intended for trusted private networks. The built-in static token authentication is not sufficient public-internet hardening by itself.
Quick Start
Requirements: Python 3.11 or newer, a reachable Paperless-ngx instance, and uv.
The package is published on PyPI as trsdn-paperless-mcp; the command it
installs is paperless-mcp and the import name is paperless_mcp.
export PAPERLESS_URL=http://127.0.0.1:8000
export PAPERLESS_TOKEN=your-paperless-api-token
export PAPERLESS_MCP_TOKEN="$(openssl rand -hex 32)"
export PAPERLESS_READ_ONLY=1
uvx --from trsdn-paperless-mcp paperless-mcp
Alternatively install it permanently:
pip install trsdn-paperless-mcp
paperless-mcp # or: python -m paperless_mcp
To run from a checkout instead:
git clone https://github.com/trsdn/paperless-mcp.git
cd paperless-mcp
uv sync --locked --no-dev
uv run paperless-mcp
The server listens on http://0.0.0.0:8770/mcp by default. Keep the generated
MCP token secret and configure the same value in the client.
Available Tools
| Tool | Access | Purpose |
|---|---|---|
search_documents |
Read | Full-text and filtered document search |
get_document |
Read | Return metadata and optional OCR content |
download_document |
Read | Return an archived or original file as base64 |
list_tags |
Read | List Paperless tags |
list_correspondents |
Read | List Paperless correspondents |
list_document_types |
Read | List Paperless document types |
update_document |
Write | Update title, correspondent, type, or tags |
upload_document |
Write | Upload a file to the consume pipeline |
update_document and upload_document are disabled when
PAPERLESS_READ_ONLY=1. The compatibility default remains 0, so set the
variable explicitly for a read-only deployment.
Configuration
All configuration is via environment variables — see
deploy/paperless-mcp.env.example.
| Variable | Required | Default | Description |
|---|---|---|---|
PAPERLESS_URL |
yes | none | Base URL, e.g. http://127.0.0.1:8000 |
PAPERLESS_TOKEN |
yes | none | Paperless API token (Settings > API Tokens) |
PAPERLESS_MCP_TOKEN |
yes | none | Bearer token clients must send |
PAPERLESS_MCP_HOST |
no | 0.0.0.0 |
Bind host |
PAPERLESS_MCP_PORT |
no | 8770 |
Bind port |
PAPERLESS_MCP_PATH |
no | /mcp |
HTTP path |
PAPERLESS_READ_ONLY |
no | 0 |
Set 1 to disable writes |
Linux Service
curl -fsSLO https://raw.githubusercontent.com/trsdn/paperless-mcp/main/deploy/install.sh
less install.sh
sudo bash install.sh
sudoedit /etc/paperless-mcp/env
systemctl enable --now paperless-mcp
journalctl -u paperless-mcp -f
Generate a dedicated bearer token before editing the environment file:
openssl rand -hex 32
Development
uv sync --locked --all-groups
uv run ruff check .
uv run ruff format --check .
uv run pytest --cov=paperless_mcp --cov-fail-under=85
uv build
Tests use mocked HTTP requests and never require a live Paperless-ngx instance. CI runs on Python 3.11, 3.12, 3.13, and 3.14.
Client config
Local stdio-free launch (any client that spawns a command)
Clients that start the server themselves can invoke it via uvx:
{
"mcpServers": {
"paperless": {
"command": "uvx",
"args": ["--from", "trsdn-paperless-mcp", "paperless-mcp"],
"env": {
"PAPERLESS_URL": "http://127.0.0.1:8000",
"PAPERLESS_TOKEN": "your-paperless-api-token",
"PAPERLESS_MCP_TOKEN": "your-generated-mcp-token",
"PAPERLESS_READ_ONLY": "1"
}
}
}
}
The server then serves streamable HTTP on http://0.0.0.0:8770/mcp; point the
client at that URL as shown below.
Claude Desktop
Claude Desktop currently only speaks MCP over stdio, so use the
mcp-remote bridge:
// ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"paperless": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://paperless-mcp.example.com/mcp",
"--header",
"Authorization: Bearer YOUR_PAPERLESS_MCP_TOKEN"
]
}
}
}
VS Code (mcp.json)
{
"servers": {
"paperless": {
"type": "http",
"url": "https://paperless-mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_PAPERLESS_MCP_TOKEN"
}
}
}
}
Security Model
- Prefer
PAPERLESS_READ_ONLY=1. Enable writes only for clients that require them and that you trust with document access. - Do not expose port 8770 directly to the public internet. Restrict network access and place the service behind a maintained reverse proxy with TLS.
- Use long, independent values for the Paperless API token and MCP bearer token. Never commit either token.
- The bearer token only protects the MCP layer. The Paperless API token
stored in
/etc/paperless-mcp/envcarries full account permissions, so the file is0640, owned bypaperless-mcp. - To rotate the bearer token: edit
/etc/paperless-mcp/env, thensystemctl restart paperless-mcp. - See SECURITY.md for vulnerability reporting and the supported security boundary.
Project
Licensed under the MIT License.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file trsdn_paperless_mcp-0.1.2.tar.gz.
File metadata
- Download URL: trsdn_paperless_mcp-0.1.2.tar.gz
- Upload date:
- Size: 116.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f1e8edb02376b8118b8528a88baad8e2cb5b12a5a5e76066d99b0b74864b956
|
|
| MD5 |
1fc2776f9332512d7900a33e6091a5a9
|
|
| BLAKE2b-256 |
c8346fd424aef8d1d5d646eb4102b717648a58a333706edf205c936afb486fe7
|
Provenance
The following attestation bundles were made for trsdn_paperless_mcp-0.1.2.tar.gz:
Publisher:
release.yml on trsdn/paperless-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
trsdn_paperless_mcp-0.1.2.tar.gz -
Subject digest:
0f1e8edb02376b8118b8528a88baad8e2cb5b12a5a5e76066d99b0b74864b956 - Sigstore transparency entry: 2582023011
- Sigstore integration time:
-
Permalink:
trsdn/paperless-mcp@fbc34369d8375f2fbd04890fe1feae3fef2bacd1 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/trsdn
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@fbc34369d8375f2fbd04890fe1feae3fef2bacd1 -
Trigger Event:
push
-
Statement type:
File details
Details for the file trsdn_paperless_mcp-0.1.2-py3-none-any.whl.
File metadata
- Download URL: trsdn_paperless_mcp-0.1.2-py3-none-any.whl
- Upload date:
- Size: 9.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
45b281f1b9daeda02c3bf3348f0d08b15a17a545e33d4b9aa48ea2467f5a2f71
|
|
| MD5 |
6866993205de2e2f391a18801540be4e
|
|
| BLAKE2b-256 |
cdc17ecc1e8c97a8e1d980a35f45a1b7e53a212a4a1a1b3de6e81908951f2074
|
Provenance
The following attestation bundles were made for trsdn_paperless_mcp-0.1.2-py3-none-any.whl:
Publisher:
release.yml on trsdn/paperless-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
trsdn_paperless_mcp-0.1.2-py3-none-any.whl -
Subject digest:
45b281f1b9daeda02c3bf3348f0d08b15a17a545e33d4b9aa48ea2467f5a2f71 - Sigstore transparency entry: 2582023022
- Sigstore integration time:
-
Permalink:
trsdn/paperless-mcp@fbc34369d8375f2fbd04890fe1feae3fef2bacd1 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/trsdn
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@fbc34369d8375f2fbd04890fe1feae3fef2bacd1 -
Trigger Event:
push
-
Statement type: