paperless-mcp

baruchiro/paperless-mcp

3.7
Certified
file_systems

An MCP server for interacting with a Paperless-NGX API server, providing tools for managing documents, tags, correspondents, and document types.

Paperless-NGX MCP Server

smithery badge

An MCP (Model Context Protocol) server for interacting with a Paperless-NGX API server. This server provides tools for managing documents, tags, correspondents, and document types in your Paperless-NGX instance.

Quick Start

Install MCP Server

Installing via Smithery

To install Paperless NGX MCP Server for Claude Desktop automatically via Smithery:

npx -y @smithery/cli install @baruchiro/paperless-mcp --client claude

Manual Installation

Add these to your MCP config file:

// STDIO mode (recommended for local or CLI use)

"paperless": {
  "command": "npx",
  "args": [
    "-y",
    "@baruchiro/paperless-mcp@latest",
  ],
  "env": {
    "PAPERLESS_URL": "http://your-paperless-instance:8000",
    "PAPERLESS_API_KEY": "your-api-token",
    "PAPERLESS_PUBLIC_URL": "https://your-public-domain.com"
  }
}

// HTTP mode (recommended for Docker or remote use)

"paperless": {
  "command": "docker",
  "args": [
    "run",
    "-i",
    "--rm",
    "ghcr.io/baruchiro/paperless-mcp:latest",
  ],
  "env": {
    "PAPERLESS_URL": "http://your-paperless-instance:8000",
    "PAPERLESS_API_KEY": "your-api-token",
    "PAPERLESS_PUBLIC_URL": "https://your-public-domain.com"
  }
}
  1. Get your API token:

    1. Log into your Paperless-NGX instance
    2. Click your username in the top right
    3. Select "My Profile"
    4. Click the circular arrow button to generate a new token
  2. Replace the placeholders in your MCP config:

    • http://your-paperless-instance:8000 with your Paperless-NGX URL
    • your-api-token with the token you just generated
    • https://your-public-domain.com with your public Paperless-NGX URL (optional, falls back to PAPERLESS_URL)

That's it! Now you can ask Claude to help you manage your Paperless-NGX documents.

Example Usage

Here are some things you can ask Claude to do:

  • "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'"

Available Tools

Document Operations

list_documents

Get a paginated list of all documents.

Parameters:

  • page (optional): Page number
  • page_size (optional): Number of documents per page
list_documents({
  page: 1,
  page_size: 25
})
get_document

Get a specific document by ID.

Parameters:

  • id: Document ID
get_document({
  id: 123
})
search_documents

Full-text search across documents.

Parameters:

  • query: Search query string
search_documents({
  query: "invoice 2024"
})
download_document

Download a document file by ID.

Parameters:

  • id: Document ID
  • original (optional): If true, downloads original file instead of archived version
download_document({
  id: 123,
  original: false
})
bulk_edit_documents

Perform bulk operations on multiple documents.

Parameters:

  • documents: Array of document IDs
  • method: One of:
    • set_correspondent: Set correspondent for documents
    • set_document_type: Set document type for documents
    • set_storage_path: Set storage path for documents
    • add_tag: Add a tag to documents
    • remove_tag: Remove a tag from documents
    • modify_tags: Add and/or remove multiple tags
    • delete: Delete documents
    • reprocess: Reprocess documents
    • set_permissions: Set document permissions
    • merge: Merge multiple documents
    • split: Split a document into multiple documents
    • rotate: Rotate document pages
    • delete_pages: Delete specific pages from a document
  • Additional parameters based on method:
    • correspondent: ID for set_correspondent
    • document_type: ID for set_document_type
    • storage_path: ID for set_storage_path
    • tag: ID for add_tag/remove_tag
    • add_tags: Array of tag IDs for modify_tags
    • remove_tags: Array of tag IDs for modify_tags
    • permissions: Object for set_permissions with owner, permissions, merge flag
    • metadata_document_id: ID for merge to specify metadata source
    • delete_originals: Boolean for merge/split
    • pages: String for split "[1,2-3,4,5-7]" or delete_pages "[2,3,4]"
    • degrees: Number for rotate (90, 180, or 270)

Examples:

// Add a tag to multiple documents
bulk_edit_documents({
  documents: [1, 2, 3],
  method: "add_tag",
  tag: 5
})

// Set correspondent and document type
bulk_edit_documents({
  documents: [4, 5],
  method: "set_correspondent",
  correspondent: 2
})

// Merge documents
bulk_edit_documents({
  documents: [6, 7, 8],
  method: "merge",
  metadata_document_id: 6,
  delete_originals: true
})

// Split document into parts
bulk_edit_documents({
  documents: [9],
  method: "split",
  pages: "[1-2,3-4,5]"
})

// Modify multiple tags at once
bulk_edit_documents({
  documents: [10, 11],
  method: "modify_tags",
  add_tags: [1, 2],
  remove_tags: [3, 4]
})

// Modify custom fields
bulk_edit_documents({
  documents: [12, 13],
  method: "modify_custom_fields",
  add_custom_fields: {
    "2": "שנה"
  }
})
post_document

Upload a new document to Paperless-NGX.

Parameters:

  • file: Base64 encoded file content
  • filename: Name of the file
  • title (optional): Title for the document
  • created (optional): DateTime when the document was created (e.g. "2024-01-19" or "2024-01-19 06:15:00+02:00")
  • correspondent (optional): ID of a correspondent
  • document_type (optional): ID of a document type
  • storage_path (optional): ID of a storage path
  • tags (optional): Array of tag IDs
  • archive_serial_number (optional): Archive serial number
  • custom_fields (optional): Array of custom field IDs
post_document({
  file: "base64_encoded_content",
  filename: "invoice.pdf",
  title: "January Invoice",
  created: "2024-01-19",
  correspondent: 1,
  document_type: 2,
  tags: [1, 3],
  archive_serial_number: "2024-001",
  custom_fields: [1, 2]
})

Tag Operations

list_tags

Get all tags.

list_tags()
create_tag

Create a new tag.

Parameters:

  • name: Tag name
  • color (optional): Hex color code (e.g. "#ff0000")
  • match (optional): Text pattern to match
  • matching_algorithm (optional): Number between 0 and 6: 0 - None 1 - Any word 2 - All words 3 - Exact match 4 - Regular expression 5 - Fuzzy word 6 - Automatic
create_tag({
  name: "Invoice",
  color: "#ff0000",
  match: "invoice",
  matching_algorithm: 5
})

Correspondent Operations

list_correspondents

Get all correspondents.

list_correspondents()
create_correspondent

Create a new correspondent.

Parameters:

  • name: Correspondent name
  • match (optional): Text pattern to match
  • matching_algorithm (optional): Number between 0 and 6: 0 - None 1 - Any word 2 - All words 3 - Exact match 4 - Regular expression 5 - Fuzzy word 6 - Automatic
create_correspondent({
  name: "ACME Corp",
  match: "ACME",
  matching_algorithm: 5
})

Document Type Operations

list_document_types

Get all document types.

list_document_types()
create_document_type

Create a new document type.

Parameters:

  • name: Document type name
  • match (optional): Text pattern to match
  • matching_algorithm (optional): Number between 0 and 6: 0 - None 1 - Any word 2 - All words 3 - Exact match 4 - Regular expression 5 - Fuzzy word 6 - Automatic
create_document_type({
  name: "Invoice",
  match: "invoice total amount due",
  matching_algorithm: 1
})

Custom Field Operations

list_custom_fields

Get all custom fields.

list_custom_fields()
get_custom_field

Get a specific custom field by ID.

Parameters:

  • id: Custom field ID
get_custom_field({
  id: 1
})
create_custom_field

Create a new custom field.

Parameters:

  • name: Custom field name
  • data_type: One of "string", "url", "date", "boolean", "integer", "float", "monetary", "documentlink", "select"
  • extra_data (optional): Extra data for the custom field, such as select options
create_custom_field({
  name: "Invoice Number",
  data_type: "string"
})
update_custom_field

Update an existing custom field.

Parameters:

  • id: Custom field ID
  • name (optional): New custom field name
  • data_type (optional): New data type
  • extra_data (optional): Extra data for the custom field
update_custom_field({
  id: 1,
  name: "Updated Invoice Number",
  data_type: "string"
})
delete_custom_field

Delete a custom field.

Parameters:

  • id: Custom field ID
delete_custom_field({
  id: 1
})
bulk_edit_custom_fields

Perform bulk operations on multiple custom fields.

Parameters:

  • custom_fields: Array of custom field IDs
  • operation: One of "delete"
bulk_edit_custom_fields({
  custom_fields: [1, 2, 3],
  operation: "delete"
})

Error Handling

The server will show clear error messages if:

  • The Paperless-NGX URL or API token is incorrect
  • The Paperless-NGX server is unreachable
  • The requested operation fails
  • The provided parameters are invalid

Development

Want to contribute or modify the server? Here's what you need to know:

  1. Clone the repository
  2. Install dependencies:
npm install
  1. Make your changes to server.js
  2. Test locally:
node server.js http://localhost:8000 your-test-token

The server is built with:

  • litemcp: A TypeScript framework for building MCP servers
  • zod: TypeScript-first schema validation

API Documentation

This MCP server implements endpoints from the Paperless-NGX REST API. For more details about the underlying API, see the official documentation.

Running the MCP Server

The MCP server can be run in two modes:

1. stdio (default)

This is the default mode. The server communicates over stdio, suitable for CLI and direct integrations.

npm run start -- <baseUrl> <token>

2. HTTP (Streamable HTTP Transport)

To run the server as an HTTP service, use the --http flag. You can also specify the port with --port (default: 3000). This mode requires Express to be installed (it is included as a dependency).

npm run start -- <baseUrl> <token> --http --port 3000
  • The MCP API will be available at POST /mcp on the specified port.
  • Each request is handled statelessly, following the StreamableHTTPServerTransport pattern.
  • GET and DELETE requests to /mcp will return 405 Method Not Allowed.

Credits

This project is a fork of nloui/paperless-mcp. Many thanks to the original author for their work. Contributions and improvements may be returned upstream.

Debugging

To debug the MCP server in VS Code, use the following launch configuration:

{
    "type": "node",
    "request": "launch",
    "name": "Debug Paperless MCP (HTTP, ts-node ESM)",
    "program": "${workspaceFolder}/node_modules/ts-node/dist/bin.js",
    "args": [
        "--esm",
        "src/index.ts",
        "--http",
        "--baseUrl",
        "http://your-paperless-instance:8000",
        "--token",
        "your-api-token",
        "--port",
        "3002"
    ],
    "env": {
        "NODE_OPTIONS": "--loader ts-node/esm",
    },
    "console": "integratedTerminal",
    "skipFiles": [
        "<node_internals>/**"
    ]
}

Important: Before debugging, uncomment the following line in src/index.ts (around line 175):

// await new Promise((resolve) => setTimeout(resolve, 1000000));

This prevents the server from exiting immediately and allows you to set breakpoints and debug the code.