All apps · 0 apps
Paperless-NGX-MCP
Docker app from pauly's Repository
Overview
Readme
View on GitHubpaperless-ngx-mcp-container
A minimal, multi-arch Docker image for paperless-ngx-mcp — a Model Context Protocol server that lets AI assistants (Claude, etc.) search and manage documents in your Paperless-NGX instance.
The image is automatically rebuilt and published to GitHub Container Registry on every new upstream release. The
image tag always equals the upstream version it bundles, so :0.1.6 contains paperless-ngx-mcp@0.1.6.
ghcr.io/paulmeier/paperless-ngx-mcp-container
| Tag | Contents |
|---|---|
latest |
The most recent upstream release |
0.1.6 |
Exactly paperless-ngx-mcp@0.1.6 (immutable) |
0.1 |
Latest patch of the 0.1 line |
0 |
Latest minor/patch of the 0 line |
Built for linux/amd64 and linux/arm64.
Quick start (Docker Compose)
git clone https://github.com/paulmeier/paperless-ngx-mcp-container.git
cd paperless-ngx-mcp-container
cp .env.example .env
# edit .env: set PAPERLESS_URL and PAPERLESS_API_KEY
docker compose up -d
The MCP server is now listening on http://localhost:3000/mcp.
You only need the
docker-compose.ymland.envfiles to run it — the compose file pulls the prebuilt image from GHCR, so cloning the whole repo is optional.
Quick start (docker run)
docker run -d --name paperless-mcp \
-p 3000:3000 \
-e PAPERLESS_URL=https://paperless.example.com \
-e PAPERLESS_API_KEY=your-api-token \
ghcr.io/paulmeier/paperless-ngx-mcp-container:latest
Configuration
Configuration is entirely through environment variables:
| Variable | Required | Default | Description |
|---|---|---|---|
PAPERLESS_URL |
✅ | — | Base URL of your Paperless-NGX instance. |
PAPERLESS_API_KEY |
✅ | — | Paperless-NGX API token (Settings → user menu → API Token). |
PAPERLESS_PUBLIC_URL |
— | — | Public URL used when building shareable document links. |
MCP_TRANSPORT |
— | http |
Transport to run: http or stdio. |
MCP_HTTP_PORT |
— | 3000 |
Port for the HTTP transport. |
Any extra arguments after the image name are forwarded to paperless-ngx-mcp unchanged.
Connecting an MCP client
HTTP transport (default)
The container exposes the streamable-HTTP endpoint at POST /mcp. Point any HTTP-capable MCP client at it.
Claude Code:
claude mcp add --transport http paperless http://localhost:3000/mcp
Generic mcpServers config:
{
"mcpServers": {
"paperless": {
"type": "http",
"url": "http://localhost:3000/mcp"
}
}
}
stdio transport
For clients that spawn the server per-session (e.g. Claude Desktop), run the container in stdio mode. Note the -i
(interactive) flag and MCP_TRANSPORT=stdio; no port is published.
Claude Code:
claude mcp add paperless -- \
docker run -i --rm \
-e PAPERLESS_URL=https://paperless.example.com \
-e PAPERLESS_API_KEY=your-api-token \
-e MCP_TRANSPORT=stdio \
ghcr.io/paulmeier/paperless-ngx-mcp-container:latest
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"paperless": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "PAPERLESS_URL",
"-e", "PAPERLESS_API_KEY",
"-e", "MCP_TRANSPORT=stdio",
"ghcr.io/paulmeier/paperless-ngx-mcp-container:latest"
],
"env": {
"PAPERLESS_URL": "https://paperless.example.com",
"PAPERLESS_API_KEY": "your-api-token"
}
}
}
}
How auto-publishing works
There is no source code for the MCP server in this repo — only the packaging. The upstream project is pulled from npm at image-build time.
.github/workflows/upstream-sync.ymlruns daily (and on demand). It reads the latestpaperless-ngx-mcpversion from the npm registry and compares it to the version recorded in.upstream-ref.- If a newer version exists, it calls
.github/workflows/docker-publish.yml, which builds the multi-arch image with--build-arg PAPERLESS_MCP_VERSION=<version>and pushes it to GHCR taggedX.Y.Z,X.Y,X, andlatest. - Only after a successful publish does it commit the bumped
.upstream-refand cut a matching GitHub Release. If a build fails, the version is not recorded, so the next run retries it.
Everything uses the built-in GITHUB_TOKEN — no personal access token or extra secrets are required. The publishing
workflow can also be triggered manually to rebuild any version (for example after a base-image or security bump):
gh workflow run docker-publish.yml --field version=0.1.6
First run & maintainer setup
The repo ships with .upstream-ref set to 0.0.0, so the first upstream-sync run (trigger it from the Actions
tab, or wait for the daily schedule) builds the current latest release and publishes it. After that it only builds when
upstream publishes something new. A few one-time repository settings:
- Actions must be enabled, with Settings → Actions → General → Workflow permissions → Read and write
permissions so
upstream-synccan push.upstream-refand cut releases. - The GHCR package is created private on first publish. To make it public and link it here, open the package page (repo → Packages → Package settings) and change its visibility.
Building locally
# Build the latest upstream release
docker build -t paperless-ngx-mcp .
# Pin a specific upstream version
docker build --build-arg PAPERLESS_MCP_VERSION=0.1.6 -t paperless-ngx-mcp:0.1.6 .
Continuous checks
- Lint (
lint.yml) — hadolint on the Dockerfile and ShellCheck on the shell scripts, on every push/PR. - Security scan (
security.yml) — Trivy scans the built image for CRITICAL/HIGH vulnerabilities on every push/PR and weekly, uploading results to the repo's Security tab.
Security
See SECURITY.md for the supported-versions policy and how to report a vulnerability. Treat
PAPERLESS_API_KEY as a secret — pass it via .env/Docker secrets, never bake it into an image.
License & credits
This packaging is released under the MIT License. The bundled MCP server, paperless-ngx-mcp, is the work of its respective authors and carries its own license. This project is not affiliated with the Paperless-NGX project.
Install Paperless-NGX-MCP on Unraid in a few clicks.
Find Paperless-NGX-MCP in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.
Requirements
Related apps
Explore more like this
Explore allDetails
ghcr.io/paulmeier/paperless-ngx-mcp-container:latestRuntime arguments
- Network
bridge- Shell
bash- Privileged
- false
- Extra Params
--restart=unless-stopped
Template configuration
Host port mapped to the paperless-ngx-mcp server. MCP clients connect to http://[UNRAID-IP]:[this port]/mcp for the streamable HTTP transport. Change only the host side if 3000 is already taken on your server.
- Target
- 3000
- Default
- 3000
- Value
- 3000
Full base URL of the Paperless-NGX instance the MCP server connects to, including scheme and port if non-standard. Example http://192.168.1.10:8000 or https://paperless.example.com . Do not use localhost or 127.0.0.1 here, because inside the container those refer to the MCP server itself, not your Paperless-NGX. If Paperless-NGX runs as another Docker container on this same Unraid host, use the Unraid host LAN IP with the published Paperless port, or put both containers on one custom Docker network and use the Paperless container name.
- Target
- PAPERLESS_URL
- Default
- https://paperless.example.com
- Value
- https://paperless.example.com
Paperless-NGX API token used to authenticate every request to Paperless. In Paperless-NGX open Settings, then the user menu, then API Token, create or copy a token, and paste it here. The token inherits the permissions of its owning Paperless user, so scope that user to least privilege. Treat it like a password.
- Target
- PAPERLESS_API_KEY
Optional public-facing base URL used when the server builds shareable document links. Set this only if your Paperless-NGX is reached through a different external address than the Paperless URL above, for example behind a reverse proxy. Leave blank to fall back to the Paperless URL.
- Target
- PAPERLESS_PUBLIC_URL
Container timezone, used for log timestamps. Example Europe/Madrid or America/New_York. Leave blank for UTC.
- Target
- TZ
Small writable folder used only to persist Tailscale state when you enable Unraid built-in Tailscale integration. The paperless-ngx-mcp server itself is stateless and stores nothing here. If you do not use Tailscale you can safely leave this at its default. Keeping it mapped lets the Use Tailscale toggle work without the Couldn't detect persistent Docker directory error.
- Target
- /appdata
- Default
- /mnt/user/appdata/paperless-ngx-mcp
- Value
- /mnt/user/appdata/paperless-ngx-mcp