Barry Walker 63f355d404 Add comprehensive README with full API documentation
- Professional header with badges
- Complete feature overview
- Multiple installation methods (dotnet, Docker, Claude Desktop)
- Configuration reference
- Full API documentation for all 43+ MCP tools
- Project structure and tech stack
- Contributing guidelines
- Troubleshooting section

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 14:05:30 -05:00

📄 PaperlessMCP

Model Context Protocol Server for Paperless-ngx

.NET 10 License: MIT MCP Build Status

Seamlessly integrate your Paperless-ngx document management system with Claude via the Model Context Protocol

FeaturesInstallationConfigurationUsageAPI ReferenceContributing


🎯 Overview

PaperlessMCP is a powerful Model Context Protocol (MCP) server that bridges Paperless-ngx with AI assistants like Claude. It provides comprehensive document management capabilities through a modern, type-safe .NET implementation with built-in retry logic and error handling.

What is MCP?

The Model Context Protocol enables AI models to securely interact with external data sources and tools. PaperlessMCP implements this protocol to give Claude direct access to your document management system.


Features

📚 Document Operations

  • Search & Discovery - Full-text search with advanced filtering (tags, dates, correspondents, types)
  • Document Management - Create, read, update, delete documents with metadata
  • Bulk Operations - Process multiple documents at once (add/remove tags, set properties, reprocess)
  • File Uploads - Support for base64 content or local file paths with automatic retries
  • Download URLs - Get preview, thumbnail, and original file URLs

🏷️ Metadata Management

  • Tags - Create, organize, and manage document tags with auto-tagging rules
  • Correspondents - Track document sources and senders
  • Document Types - Classify documents with custom types
  • Storage Paths - Organize files with template-based storage paths
  • Custom Fields - Define and assign custom metadata fields (string, date, boolean, monetary, etc.)

🔧 Developer Features

  • Dual Transport - Supports both stdio (Claude Desktop) and HTTP transports
  • Pagination - Efficient handling of large datasets with configurable page sizes
  • Dry Run Mode - Preview destructive operations before execution
  • Retry Logic - Built-in exponential backoff for transient failures
  • Health Checks - Verify connectivity and discover API capabilities
  • Comprehensive Tests - Full test suite with 100% coverage

🚀 Installation

Prerequisites

Method 1: Clone and Build

# Clone the repository
git clone https://github.com/barryw/PaperlessMCP.git
cd PaperlessMCP

# Build the project
dotnet build

# Run tests (optional)
dotnet test

Method 2: Docker

# Build the Docker image
docker build -t paperless-mcp ./PaperlessMCP

# Run with environment variables
docker run -d \
  -e PAPERLESS_BASE_URL=https://your-paperless-instance.com \
  -e PAPERLESS_API_TOKEN=your-token-here \
  -p 5000:5000 \
  paperless-mcp

Method 3: Claude Desktop Integration

  1. Build the project:

    cd PaperlessMCP
    dotnet build -c Release
    
  2. Add to your Claude Desktop configuration (claude_desktop_config.json):

    macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

    Windows: %APPDATA%\Claude\claude_desktop_config.json

    {
      "mcpServers": {
        "paperless": {
          "command": "dotnet",
          "args": [
            "run",
            "--project",
            "/absolute/path/to/PaperlessMCP/PaperlessMCP",
            "--",
            "--stdio"
          ],
          "env": {
            "PAPERLESS_BASE_URL": "https://your-paperless-instance.com",
            "PAPERLESS_API_TOKEN": "your-token-here"
          }
        }
      }
    }
    
  3. Restart Claude Desktop


⚙️ Configuration

Environment Variables

PaperlessMCP supports multiple configuration methods. Environment variables take precedence over appsettings.json.

Variable Aliases Required Default Description
PAPERLESS_BASE_URL PAPERLESS_URL Yes - Base URL of your Paperless-ngx instance
PAPERLESS_API_TOKEN PAPERLESS_TOKEN Yes - API authentication token
MAX_PAGE_SIZE - No 100 Maximum items per page for paginated requests
MCP_PORT - No 5000 HTTP server port (HTTP mode only)

appsettings.json

Alternatively, configure via appsettings.json:

{
  "Paperless": {
    "BaseUrl": "https://your-paperless-instance.com",
    "ApiToken": "your-token-here",
    "MaxPageSize": 100
  },
  "Mcp": {
    "Port": 5000
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "ModelContextProtocol": "Debug"
    }
  }
}

Transport Modes

  • stdio mode (for Claude Desktop): dotnet run -- --stdio
  • HTTP mode (for remote access): dotnet run (default)

💻 Usage

With Claude Desktop

Once configured, simply ask Claude to interact with your documents:

"Search for all invoices from 2024"
"Upload this PDF to Paperless and tag it as 'Receipt'"
"Show me documents with the tag 'Important' that have no correspondent"
"Create a new tag called 'Urgent' with a red color"

HTTP Endpoint

When running in HTTP mode, the MCP endpoint is available at:

http://localhost:5000/mcp

Running the Server

# Stdio mode (Claude Desktop)
dotnet run --project PaperlessMCP/PaperlessMCP -- --stdio

# HTTP mode (remote access)
dotnet run --project PaperlessMCP/PaperlessMCP

# Docker
docker run -e PAPERLESS_BASE_URL=... -e PAPERLESS_API_TOKEN=... -p 5000:5000 paperless-mcp

📖 API Reference

Health & Capabilities

paperless.ping

Verify connectivity and authentication with Paperless-ngx.

Returns: Connection status and server version

paperless.capabilities

Return supported API endpoints and detected Paperless-ngx version information.

Returns: Available endpoints, bulk operations, and server capabilities


Document Operations

paperless.documents.search

Search for documents with full-text search and filters.

Parameters:

  • query (string, optional) - Full-text search query
  • tags (string, optional) - Filter by tag IDs (comma-separated)
  • tagsExclude (string, optional) - Exclude tag IDs (comma-separated)
  • correspondent (int, optional) - Filter by correspondent ID
  • documentType (int, optional) - Filter by document type ID
  • storagePath (int, optional) - Filter by storage path ID
  • createdAfter (string, optional) - Filter by creation date (YYYY-MM-DD)
  • createdBefore (string, optional) - Filter by creation date (YYYY-MM-DD)
  • addedAfter (string, optional) - Filter by added date (YYYY-MM-DD)
  • addedBefore (string, optional) - Filter by added date (YYYY-MM-DD)
  • archiveSerialNumber (int, optional) - Filter by archive serial number
  • page (int, default: 1) - Page number
  • pageSize (int, default: 25, max: 100) - Results per page
  • ordering (string, optional) - Sort field (e.g., 'created', '-created', 'title')
  • includeContent (bool, default: false) - Include document content in results
  • contentMaxLength (int, default: 500) - Max content length when includeContent=true

Returns: Paginated list of document summaries

paperless.documents.get

Get a document by its ID.

Parameters:

  • id (int, required) - Document ID

Returns: Complete document details including content

paperless.documents.download

Get download URLs for a document's original file, preview, and thumbnail.

Parameters:

  • id (int, required) - Document ID

Returns: Object with download URLs (original_url, preview_url, thumbnail_url)

paperless.documents.preview

Get the preview URL for a document.

Parameters:

  • id (int, required) - Document ID

Returns: Preview URL

paperless.documents.thumbnail

Get the thumbnail URL for a document.

Parameters:

  • id (int, required) - Document ID

Returns: Thumbnail URL

paperless.documents.upload

Upload a new document to Paperless-ngx via base64-encoded content.

Parameters:

  • fileContent (string, required) - Base64-encoded file content
  • fileName (string, required) - Original filename with extension
  • title (string, optional) - Document title
  • correspondent (int, optional) - Correspondent ID
  • documentType (int, optional) - Document type ID
  • storagePath (int, optional) - Storage path ID
  • tags (string, optional) - Tag IDs (comma-separated)
  • archiveSerialNumber (int, optional) - Archive serial number
  • created (string, optional) - Created date (YYYY-MM-DD)

Returns: Task ID and upload status

Note: For large files, use paperless.documents.upload_from_path instead.

paperless.documents.upload_from_path

Upload a document from a local file path. More reliable for large files.

Parameters:

  • filePath (string, required) - Absolute path to the file
  • title (string, optional) - Document title (defaults to filename)
  • correspondent (int, optional) - Correspondent ID
  • documentType (int, optional) - Document type ID
  • storagePath (int, optional) - Storage path ID
  • tags (string, optional) - Tag IDs (comma-separated)
  • archiveSerialNumber (int, optional) - Archive serial number
  • created (string, optional) - Created date (YYYY-MM-DD)

Returns: Task ID, upload status, and file information

Features: Supports ~/ expansion, automatic retries, file validation

paperless.documents.update

Update document metadata.

Parameters:

  • id (int, required) - Document ID
  • title (string, optional) - New title
  • correspondent (int, optional) - Correspondent ID (use -1 to clear)
  • documentType (int, optional) - Document type ID (use -1 to clear)
  • storagePath (int, optional) - Storage path ID (use -1 to clear)
  • tags (string, optional) - Tag IDs to set (comma-separated)
  • archiveSerialNumber (int, optional) - Archive serial number
  • created (string, optional) - Created date (YYYY-MM-DD)

Returns: Updated document

paperless.documents.delete

Delete a document. Requires explicit confirmation.

Parameters:

  • id (int, required) - Document ID
  • confirm (bool, default: false) - Must be true to confirm deletion

Returns: Deletion status or dry-run preview

Safety: Without confirm=true, returns a dry-run preview showing what would be deleted.

paperless.documents.bulk_update

Perform bulk operations on multiple documents.

Parameters:

  • documentIds (string, required) - Document IDs (comma-separated)
  • operation (string, required) - Operation: add_tag, remove_tag, set_correspondent, set_document_type, set_storage_path, delete, reprocess
  • value (int, optional) - Parameter value (e.g., tag ID, correspondent ID)
  • dryRun (bool, default: true) - Preview changes without applying
  • confirm (bool, default: false) - Must be true to execute

Returns: Affected document IDs and operation status

Safety: Defaults to dry-run mode to prevent accidental changes.

paperless.documents.reprocess

Reprocess a document's OCR and content extraction.

Parameters:

  • id (int, required) - Document ID
  • confirm (bool, default: false) - Must be true to confirm reprocessing

Returns: Processing status


Tag Operations

paperless.tags.list

List all tags with pagination.

Parameters:

  • page (int, default: 1) - Page number
  • pageSize (int, default: 25, max: 100) - Results per page
  • ordering (string, optional) - Sort field (e.g., 'name', '-document_count')

Returns: Paginated list of tags

paperless.tags.get

Get a tag by its ID.

Parameters:

  • id (int, required) - Tag ID

Returns: Tag details

paperless.tags.create

Create a new tag.

Parameters:

  • name (string, required) - Tag name
  • color (string, optional) - Hex color (e.g., '#ff0000')
  • match (string, optional) - Match pattern for auto-tagging
  • matchingAlgorithm (int, optional) - Matching algorithm (0=None, 1=Any, 2=All, 3=Literal, 4=Regex, 5=Fuzzy, 6=Auto)
  • isInboxTag (bool, optional) - Mark as inbox tag

Returns: Created tag

paperless.tags.update

Update an existing tag.

Parameters:

  • id (int, required) - Tag ID
  • name (string, optional) - New name
  • color (string, optional) - Hex color
  • match (string, optional) - Match pattern
  • matchingAlgorithm (int, optional) - Matching algorithm
  • isInboxTag (bool, optional) - Inbox tag status

Returns: Updated tag

paperless.tags.delete

Delete a tag. Requires explicit confirmation.

Parameters:

  • id (int, required) - Tag ID
  • confirm (bool, default: false) - Must be true to confirm deletion

Returns: Deletion status or dry-run preview

paperless.tags.bulk_delete

Delete multiple tags.

Parameters:

  • tagIds (string, required) - Tag IDs (comma-separated)
  • dryRun (bool, default: true) - Preview changes without applying
  • confirm (bool, default: false) - Must be true to execute

Returns: Affected tag IDs and operation status


Correspondent Operations

paperless.correspondents.list

List all correspondents with pagination.

Parameters:

  • page (int, default: 1) - Page number
  • pageSize (int, default: 25, max: 100) - Results per page
  • ordering (string, optional) - Sort field (e.g., 'name', '-document_count', 'last_correspondence')

Returns: Paginated list of correspondents

paperless.correspondents.get

Get a correspondent by its ID.

Parameters:

  • id (int, required) - Correspondent ID

Returns: Correspondent details

paperless.correspondents.create

Create a new correspondent.

Parameters:

  • name (string, required) - Correspondent name
  • match (string, optional) - Match pattern for auto-assignment
  • matchingAlgorithm (int, optional) - Matching algorithm (0=None, 1=Any, 2=All, 3=Literal, 4=Regex, 5=Fuzzy, 6=Auto)

Returns: Created correspondent

paperless.correspondents.update

Update an existing correspondent.

Parameters:

  • id (int, required) - Correspondent ID
  • name (string, optional) - New name
  • match (string, optional) - Match pattern
  • matchingAlgorithm (int, optional) - Matching algorithm

Returns: Updated correspondent

paperless.correspondents.delete

Delete a correspondent. Requires explicit confirmation.

Parameters:

  • id (int, required) - Correspondent ID
  • confirm (bool, default: false) - Must be true to confirm deletion

Returns: Deletion status or dry-run preview

paperless.correspondents.bulk_delete

Delete multiple correspondents.

Parameters:

  • correspondentIds (string, required) - Correspondent IDs (comma-separated)
  • dryRun (bool, default: true) - Preview changes without applying
  • confirm (bool, default: false) - Must be true to execute

Returns: Affected correspondent IDs and operation status


Document Type Operations

paperless.document_types.list

List all document types with pagination.

Parameters:

  • page (int, default: 1) - Page number
  • pageSize (int, default: 25, max: 100) - Results per page
  • ordering (string, optional) - Sort field (e.g., 'name', '-document_count')

Returns: Paginated list of document types

paperless.document_types.get

Get a document type by its ID.

Parameters:

  • id (int, required) - Document type ID

Returns: Document type details

paperless.document_types.create

Create a new document type.

Parameters:

  • name (string, required) - Document type name
  • match (string, optional) - Match pattern for auto-assignment
  • matchingAlgorithm (int, optional) - Matching algorithm (0=None, 1=Any, 2=All, 3=Literal, 4=Regex, 5=Fuzzy, 6=Auto)

Returns: Created document type

paperless.document_types.update

Update an existing document type.

Parameters:

  • id (int, required) - Document type ID
  • name (string, optional) - New name
  • match (string, optional) - Match pattern
  • matchingAlgorithm (int, optional) - Matching algorithm

Returns: Updated document type

paperless.document_types.delete

Delete a document type. Requires explicit confirmation.

Parameters:

  • id (int, required) - Document type ID
  • confirm (bool, default: false) - Must be true to confirm deletion

Returns: Deletion status or dry-run preview

paperless.document_types.bulk_delete

Delete multiple document types.

Parameters:

  • documentTypeIds (string, required) - Document type IDs (comma-separated)
  • dryRun (bool, default: true) - Preview changes without applying
  • confirm (bool, default: false) - Must be true to execute

Returns: Affected document type IDs and operation status


Storage Path Operations

paperless.storage_paths.list

List all storage paths with pagination.

Parameters:

  • page (int, default: 1) - Page number
  • pageSize (int, default: 25, max: 100) - Results per page
  • ordering (string, optional) - Sort field (e.g., 'name', '-document_count')

Returns: Paginated list of storage paths

paperless.storage_paths.get

Get a storage path by its ID.

Parameters:

  • id (int, required) - Storage path ID

Returns: Storage path details

paperless.storage_paths.create

Create a new storage path.

Parameters:

  • name (string, required) - Storage path name
  • path (string, required) - Path template (e.g., {correspondent}/{document_type})
  • match (string, optional) - Match pattern for auto-assignment
  • matchingAlgorithm (int, optional) - Matching algorithm (0=None, 1=Any, 2=All, 3=Literal, 4=Regex, 5=Fuzzy, 6=Auto)

Returns: Created storage path

paperless.storage_paths.update

Update an existing storage path.

Parameters:

  • id (int, required) - Storage path ID
  • name (string, optional) - New name
  • path (string, optional) - Path template
  • match (string, optional) - Match pattern
  • matchingAlgorithm (int, optional) - Matching algorithm

Returns: Updated storage path

paperless.storage_paths.delete

Delete a storage path. Requires explicit confirmation.

Parameters:

  • id (int, required) - Storage path ID
  • confirm (bool, default: false) - Must be true to confirm deletion

Returns: Deletion status or dry-run preview

paperless.storage_paths.bulk_delete

Delete multiple storage paths.

Parameters:

  • storagePathIds (string, required) - Storage path IDs (comma-separated)
  • dryRun (bool, default: true) - Preview changes without applying
  • confirm (bool, default: false) - Must be true to execute

Returns: Affected storage path IDs and operation status


Custom Field Operations

paperless.custom_fields.list

List all custom field definitions with pagination.

Parameters:

  • page (int, default: 1) - Page number
  • pageSize (int, default: 25, max: 100) - Results per page

Returns: Paginated list of custom field definitions

paperless.custom_fields.get

Get a custom field definition by its ID.

Parameters:

  • id (int, required) - Custom field ID

Returns: Custom field details

paperless.custom_fields.create

Create a new custom field definition.

Parameters:

  • name (string, required) - Custom field name
  • dataType (string, required) - Data type: string, url, date, boolean, integer, float, monetary, documentlink, select
  • selectOptions (string, optional) - Select options (comma-separated, for 'select' type only)
  • defaultCurrency (string, optional) - Default currency (for 'monetary' type only)

Returns: Created custom field

paperless.custom_fields.update

Update an existing custom field definition.

Parameters:

  • id (int, required) - Custom field ID
  • name (string, optional) - New name
  • selectOptions (string, optional) - Select options (comma-separated)
  • defaultCurrency (string, optional) - Default currency

Returns: Updated custom field

paperless.custom_fields.delete

Delete a custom field definition. Requires explicit confirmation.

Parameters:

  • id (int, required) - Custom field ID
  • confirm (bool, default: false) - Must be true to confirm deletion

Returns: Deletion status or dry-run preview

paperless.custom_fields.assign

Assign a custom field value to a document.

Parameters:

  • documentId (int, required) - Document ID
  • fieldId (int, required) - Custom field ID
  • value (string, required) - Value to assign (string, number, boolean, or date depending on field type)

Returns: Assignment status and assigned value


🛠️ Development

Building from Source

# Clone the repository
git clone https://github.com/barryw/PaperlessMCP.git
cd PaperlessMCP

# Restore dependencies
dotnet restore

# Build
dotnet build

# Run tests
dotnet test

# Build for release
dotnet build -c Release

Running Tests

# Run all tests
dotnet test

# Run tests with coverage
dotnet test /p:CollectCoverage=true

# Run specific test file
dotnet test --filter "FullyQualifiedName~DocumentToolsTests"

Project Structure

PaperlessMCP/
├── PaperlessMCP/                 # Main application
│   ├── Client/                   # Paperless API client
│   │   ├── PaperlessClient.cs    # Main API client implementation
│   │   └── PaperlessAuthHandler.cs # Authentication handler
│   ├── Configuration/            # Configuration options
│   │   └── PaperlessOptions.cs   # Connection configuration
│   ├── Models/                   # Data models
│   │   ├── Common/               # Shared models
│   │   ├── Documents/            # Document models
│   │   ├── Tags/                 # Tag models
│   │   ├── Correspondents/       # Correspondent models
│   │   ├── DocumentTypes/        # Document type models
│   │   ├── StoragePaths/         # Storage path models
│   │   └── CustomFields/         # Custom field models
│   ├── Tools/                    # MCP tool implementations
│   │   ├── HealthTools.cs        # Health checks
│   │   ├── DocumentTools.cs      # Document operations
│   │   ├── TagTools.cs           # Tag operations
│   │   ├── CorrespondentTools.cs # Correspondent operations
│   │   ├── DocumentTypeTools.cs  # Document type operations
│   │   ├── StoragePathTools.cs   # Storage path operations
│   │   └── CustomFieldTools.cs   # Custom field operations
│   ├── Program.cs                # Application entry point
│   ├── Dockerfile                # Docker configuration
│   └── appsettings.json          # Default configuration
├── PaperlessMCP.Tests/           # Test project
│   ├── Client/                   # Client tests
│   ├── Tools/                    # Tool tests
│   └── Fixtures/                 # Test fixtures
└── PaperlessMCP.sln              # Solution file

Technology Stack

  • .NET 10 - Modern, cross-platform framework
  • ModelContextProtocol 0.2.0-preview.1 - MCP server implementation
  • Polly 8.5.2 - Resilience and transient fault handling
  • xUnit - Testing framework

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Guidelines

  1. Fork the repository and create your branch from main
  2. Write tests for any new functionality
  3. Ensure all tests pass with dotnet test
  4. Follow the existing code style and conventions
  5. Update documentation for any API changes
  6. Submit a pull request with a clear description of changes

Development Setup

# Fork and clone your fork
git clone https://github.com/YOUR-USERNAME/PaperlessMCP.git
cd PaperlessMCP

# Create a feature branch
git checkout -b feature/your-feature-name

# Make changes and test
dotnet test

# Commit and push
git add .
git commit -m "Add your feature"
git push origin feature/your-feature-name

🐛 Troubleshooting

Common Issues

Connection Errors

Problem: "Failed to connect to Paperless instance"

Solution:

  • Verify PAPERLESS_BASE_URL is correct and accessible
  • Ensure your Paperless-ngx instance is running
  • Check network connectivity and firewall rules
  • Verify API endpoint: curl https://your-instance/api/

Authentication Errors

Problem: "401 Unauthorized"

Solution:

  • Verify your PAPERLESS_API_TOKEN is correct
  • Generate a new token in Paperless-ngx: Settings → API → Tokens
  • Ensure the token has necessary permissions

Upload Failures

Problem: Document uploads timeout or fail

Solution:

  • For large files, use paperless.documents.upload_from_path instead of base64 upload
  • Check file size limits in Paperless-ngx configuration
  • Verify disk space on Paperless-ngx server
  • Check Paperless-ngx logs for processing errors

Claude Desktop Integration

Problem: Server doesn't appear in Claude Desktop

Solution:

  • Verify JSON syntax in claude_desktop_config.json
  • Use absolute paths (no relative paths or ~)
  • Restart Claude Desktop completely
  • Check Claude Desktop logs for errors

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.


🙏 Acknowledgments


📞 Support


⬆ back to top

Made with ❤️ for the Paperless-ngx and MCP communities

S
Description
Fork von github.com/barryw/PaperlessMCP — Tool-Namen mit Underscores statt Punkten (claude.ai-kompatibel).
Readme 177 KiB
Languages
C# 99.2%
Dockerfile 0.4%
Shell 0.4%