Paperless-NGX-MCP

Paperless-NGX-MCP

Docker app from pauly's Repository

Overview

Paperless-NGX MCP is a Model Context Protocol server that connects AI assistants and other MCP clients to your Paperless-NGX document archive. A client such as Claude can search your documents, read their content and metadata, and manage tags, correspondents, and document types through scoped tools instead of raw API calls. This container runs the server in streamable HTTP transport mode on port 3000 and serves the MCP endpoint at POST /mcp. It needs a reachable Paperless-NGX instance and a Paperless-NGX API token to authenticate. This is a headless server with no browsable web interface: point your MCP client at http://[Unraid-IP]:3000/mcp . The image is maintained at paulmeier/paperless-ngx-mcp-container and wraps the upstream paperless-ngx-mcp project by cubinet-code.

paperless-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.yml and .env files 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.

  1. .github/workflows/upstream-sync.yml runs daily (and on demand). It reads the latest paperless-ngx-mcp version from the npm registry and compares it to the version recorded in .upstream-ref.
  2. 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 tagged X.Y.Z, X.Y, X, and latest.
  3. Only after a successful publish does it commit the bumped .upstream-ref and 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-sync can push .upstream-ref and 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.

Open the Apps tab on your Unraid server Search Community Apps for Paperless-NGX-MCP Review the template variables and paths Click Install

Requirements

A running Paperless-NGX instance that this container can reach over the network, plus a Paperless-NGX API token. Create the token in Paperless-NGX under Settings, then the user menu, then API Token. The token inherits the permissions of the Paperless user that owns it, so use an account scoped to only what you want the MCP server to be able to do. In the Paperless URL field use the Paperless host LAN IP or container name, not localhost, which inside the container points back at the MCP server itself.

Details

Repository
ghcr.io/paulmeier/paperless-ngx-mcp-container:latest
Last Updated2026-07-09
First Seen2026-07-09

Runtime arguments

Network
bridge
Shell
bash
Privileged
false
Extra Params
--restart=unless-stopped

Template configuration

MCP Server PortPorttcp

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
Paperless URLVariable

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 API TokenVariable

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
Paperless Public URLVariable

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
TimezoneVariable

Container timezone, used for log timestamps. Example Europe/Madrid or America/New_York. Leave blank for UTC.

Target
TZ
Appdata (Tailscale state)Pathrw

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