# PDF MCP Server

> A high-performance MCP (Model Context Protocol) server for PDF processing, built in Rust/C++.

- **Type:** MCP server
- **Install:** `agentstack add mcp-paradyno-pdf-mcp-server`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [paradyno](https://agentstack.voostack.com/s/paradyno)
- **Installs:** 0
- **Category:** [Content & Media](https://agentstack.voostack.com/c/content-and-media)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [paradyno](https://github.com/paradyno)
- **Source:** https://github.com/paradyno/PDF-MCP-Server

## Install

```sh
agentstack add mcp-paradyno-pdf-mcp-server
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# 📄 PDF MCP Server

A high-performance [MCP](https://modelcontextprotocol.io/) server for PDF processing, built in Rust.

[](https://opensource.org/licenses/Apache-2.0)
[](https://github.com/paradyno/pdf-mcp-server/actions/workflows/ci.yml)
[](https://codecov.io/gh/paradyno/pdf-mcp-server)

Give your AI agents powerful PDF capabilities — extract text, search, split, merge, encrypt, and more. All dependencies are Apache 2.0 licensed, keeping your project clean and permissive.

## ✨ Features

| Category | Tools |
|----------|-------|
| 📖 **Reading** | `extract_text` · `extract_metadata` · `extract_outline` · `extract_annotations` · `extract_links` · `extract_form_fields` |
| 🔍 **Search & Discovery** | `search` · `list_pdfs` · `get_page_info` · `summarize_structure` |
| 🖼️ **Media** | Image extraction (via `extract_text`) · `convert_page_to_image` |
| ✂️ **Manipulation** | `split_pdf` · `merge_pdfs` · `compress_pdf` · `fill_form` |
| 🔒 **Security** | `protect_pdf` · `unprotect_pdf` · Password-protected PDF support · Path sandboxing · SSRF protection |
| 📦 **Resources** | Expose PDFs as MCP Resources for direct client access |
| ⚡ **Performance** | Batch processing · LRU caching (with byte budget) · Operation chaining via cache keys |

## 🚀 Installation

### npm (Recommended)

```bash
npm install -g @paradyno/pdf-mcp-server
```

### Pre-built Binaries

Download from [GitHub Releases](https://github.com/paradyno/pdf-mcp-server/releases):

| Platform | x86_64 | ARM64 |
|----------|--------|-------|
| 🐧 Linux | `pdf-mcp-server-linux-x64` | `pdf-mcp-server-linux-arm64` |
| 🍎 macOS | `pdf-mcp-server-darwin-x64` | `pdf-mcp-server-darwin-arm64` |
| 🪟 Windows | `pdf-mcp-server-windows-x64.exe` | — |

### From Source

```bash
cargo install --git https://github.com/paradyno/pdf-mcp-server
```

## ⚙️ Configuration

### Claude Desktop

Add to your `claude_desktop_config.json`:
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "pdf": {
      "command": "npx",
      "args": ["@paradyno/pdf-mcp-server"]
    }
  }
}
```

### Claude Code

```bash
claude mcp add pdf -- npx @paradyno/pdf-mcp-server
```

### VS Code

```json
{
  "mcp.servers": {
    "pdf": {
      "command": "npx",
      "args": ["@paradyno/pdf-mcp-server"]
    }
  }
}
```

## 🛠️ Tools

### Source Types

All tools accept PDF sources in multiple formats:

```json
{ "path": "/documents/file.pdf" }
{ "base64": "JVBERi0xLjQK..." }
{ "url": "https://example.com/document.pdf" }
{ "cache_key": "abc123" }
```

---

### 📖 `extract_text`

Extract text content with LLM-optimized formatting (paragraph detection, multi-column reordering, watermark removal).

Example & Parameters

```json
{
  "sources": [{ "path": "/documents/report.pdf" }],
  "pages": "1-10",
  "include_metadata": true
}
```

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `sources` | array | Yes | — | PDF sources |
| `pages` | string | No | all | Page selection (e.g., `"1-5,10,15-20"`) |
| `include_metadata` | boolean | No | true | Include PDF metadata |
| `include_images` | boolean | No | false | Include extracted images (base64 PNG) |
| `password` | string | No | — | PDF password if encrypted |
| `cache` | boolean | No | false | Enable caching |

### 📖 `extract_outline`

Extract PDF bookmarks / table of contents.

Example, Parameters & Response

```json
{
  "sources": [{ "path": "/documents/book.pdf" }]
}
```

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `sources` | array | Yes | — | PDF sources |
| `password` | string | No | — | PDF password if encrypted |
| `cache` | boolean | No | false | Enable caching |

**Response:**

```json
{
  "results": [{
    "source": "/documents/book.pdf",
    "outline": [
      {
        "title": "Chapter 1: Introduction",
        "page": 1,
        "children": [
          { "title": "1.1 Background", "page": 3, "children": [] }
        ]
      }
    ]
  }]
}
```

### 📖 `extract_metadata`

Extract PDF metadata (author, title, dates, etc.) without loading full content.

Example & Parameters

```json
{
  "sources": [{ "path": "/documents/report.pdf" }]
}
```

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `sources` | array | Yes | — | PDF sources |
| `password` | string | No | — | PDF password if encrypted |
| `cache` | boolean | No | false | Enable caching |

### 📖 `extract_annotations`

Extract highlights, comments, underlines, and other annotations.

Example & Parameters

```json
{
  "sources": [{ "path": "/documents/report.pdf" }],
  "annotation_types": ["highlight", "text"],
  "pages": "1-5"
}
```

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `sources` | array | Yes | — | PDF sources |
| `annotation_types` | array | No | all | Filter by types (highlight, underline, text, etc.) |
| `pages` | string | No | all | Page selection |
| `password` | string | No | — | PDF password if encrypted |
| `cache` | boolean | No | false | Enable caching |

### 📖 `extract_links`

Extract hyperlinks and internal page navigation links.

Example, Parameters & Response

```json
{
  "sources": [{ "path": "/documents/paper.pdf" }],
  "pages": "1-10"
}
```

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `sources` | array | Yes | — | PDF sources |
| `pages` | string | No | all | Page selection |
| `password` | string | No | — | PDF password if encrypted |
| `cache` | boolean | No | false | Enable caching |

**Response:**

```json
{
  "results": [{
    "source": "/documents/paper.pdf",
    "links": [
      { "page": 1, "url": "https://example.com", "text": "Click here" },
      { "page": 3, "dest_page": 10, "text": "See Chapter 5" }
    ],
    "total_count": 2
  }]
}
```

### 📖 `extract_form_fields`

Read form field names, types, current values, and properties from PDF forms.

Example, Parameters & Response

```json
{
  "sources": [{ "path": "/documents/form.pdf" }],
  "pages": "1"
}
```

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `sources` | array | Yes | — | PDF sources |
| `pages` | string | No | all | Page selection |
| `password` | string | No | — | PDF password if encrypted |
| `cache` | boolean | No | false | Enable caching |

**Response:**

```json
{
  "results": [{
    "source": "/documents/form.pdf",
    "fields": [
      {
        "page": 1,
        "name": "full_name",
        "field_type": "text",
        "value": "John Doe",
        "is_read_only": false,
        "is_required": true,
        "properties": { "is_multiline": false, "is_password": false }
      },
      {
        "page": 1,
        "name": "agree_terms",
        "field_type": "checkbox",
        "is_checked": true,
        "is_read_only": false,
        "is_required": false,
        "properties": {}
      }
    ],
    "total_fields": 2
  }]
}
```

### 🖼️ `convert_page_to_image`

Render PDF pages as PNG images (base64). Enables Vision LLMs to understand visual layouts, charts, and diagrams.

Example, Parameters & Response

```json
{
  "sources": [{ "path": "/documents/chart.pdf" }],
  "pages": "1-3",
  "width": 1200
}
```

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `sources` | array | Yes | — | PDF sources |
| `pages` | string | No | all | Page selection |
| `width` | integer | No | 1200 | Target width in pixels |
| `height` | integer | No | — | Target height in pixels |
| `scale` | float | No | — | Scale factor (overrides width/height) |
| `password` | string | No | — | PDF password if encrypted |
| `cache` | boolean | No | false | Enable caching |

**Response:**

```json
{
  "results": [{
    "source": "/documents/chart.pdf",
    "pages": [
      {
        "page": 1,
        "width": 1200,
        "height": 1553,
        "data_base64": "iVBORw0KGgo...",
        "mime_type": "image/png"
      }
    ]
  }]
}
```

### 🔍 `search`

Full-text search within PDFs with surrounding context.

Example & Parameters

```json
{
  "sources": [{ "path": "/documents/manual.pdf" }],
  "query": "error handling",
  "context_chars": 100
}
```

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `sources` | array | Yes | — | PDF sources |
| `query` | string | Yes | — | Search query |
| `case_sensitive` | boolean | No | false | Case-sensitive search |
| `max_results` | integer | No | 100 | Maximum results to return |
| `context_chars` | integer | No | 50 | Characters of context around match |
| `password` | string | No | — | PDF password if encrypted |
| `cache` | boolean | No | false | Enable caching |

### 🔍 `get_page_info`

Get page dimensions, word/char counts, token estimates, and file sizes. Useful for planning LLM context usage.

Example, Parameters & Response

```json
{
  "sources": [{ "path": "/documents/report.pdf" }]
}
```

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `sources` | array | Yes | — | PDF sources |
| `password` | string | No | — | PDF password if encrypted |
| `cache` | boolean | No | false | Enable caching |
| `skip_file_sizes` | boolean | No | false | Skip file size calculation (faster) |

**Response:**

```json
{
  "results": [{
    "source": "/documents/report.pdf",
    "pages": [{
      "page": 1,
      "width": 612.0, "height": 792.0,
      "rotation": 0, "orientation": "portrait",
      "char_count": 2500, "word_count": 450,
      "estimated_token_count": 625,
      "file_size": 102400
    }],
    "total_pages": 10,
    "total_chars": 25000,
    "total_words": 4500,
    "total_estimated_token_count": 6250
  }]
}
```

> **Note:** Token counts are model-dependent approximations (~4 chars/token for Latin, ~2 tokens/char for CJK). Use as rough guidance only.

### 🔍 `summarize_structure`

One-call comprehensive overview of a PDF's structure. Helps LLMs decide how to process a document.

Example, Parameters & Response

```json
{
  "sources": [{ "path": "/documents/report.pdf" }]
}
```

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `sources` | array | Yes | — | PDF sources |
| `password` | string | No | — | PDF password if encrypted |
| `cache` | boolean | No | false | Enable caching |

**Response:**

```json
{
  "results": [{
    "source": "/documents/report.pdf",
    "page_count": 25,
    "file_size": 1048576,
    "metadata": { "title": "Annual Report", "author": "Acme Corp" },
    "has_outline": true,
    "outline_items": 12,
    "total_chars": 50000,
    "total_words": 9000,
    "total_estimated_tokens": 12500,
    "pages": [
      { "page": 1, "width": 612.0, "height": 792.0, "char_count": 2000, "word_count": 360, "has_images": true, "has_links": false, "has_annotations": false }
    ],
    "total_images": 5,
    "total_links": 3,
    "total_annotations": 2,
    "has_form": false,
    "form_field_count": 0,
    "form_field_types": {},
    "is_encrypted": false
  }]
}
```

### 🔍 `list_pdfs`

Discover PDF files in a directory with optional filtering.

Example & Parameters

```json
{
  "directory": "/documents",
  "recursive": true,
  "pattern": "invoice*.pdf"
}
```

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `directory` | string | Yes | — | Directory to search |
| `recursive` | boolean | No | false | Search subdirectories |
| `pattern` | string | No | — | Filename pattern (e.g., `"report*.pdf"`) |

### ✂️ `split_pdf`

Extract specific pages from a PDF to create a new PDF.

Example, Parameters & Page Range Syntax

```json
{
  "source": { "path": "/documents/book.pdf" },
  "pages": "1-10,15,20-z",
  "output_path": "/output/excerpt.pdf"
}
```

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `source` | object | Yes | — | PDF source |
| `pages` | string | Yes | — | Page range (see syntax below) |
| `output_path` | string | No | — | Save output to file |
| `password` | string | No | — | PDF password if encrypted |

**Page Range Syntax:**

| Syntax | Description |
|--------|-------------|
| `1-5` | Pages 1 through 5 |
| `1,3,5` | Specific pages |
| `z` | Last page |
| `r1` | Last page (reverse) |
| `5-z` | Page 5 to end |
| `z-1` | All pages reversed |
| `1-z:odd` | Odd pages only |
| `1-z:even` | Even pages only |
| `1-10,x5` | Pages 1–10 except page 5 |

### ✂️ `merge_pdfs`

Merge multiple PDFs into a single file.

Example & Parameters

```json
{
  "sources": [
    { "path": "/documents/chapter1.pdf" },
    { "path": "/documents/chapter2.pdf" }
  ],
  "output_path": "/output/complete-book.pdf"
}
```

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `sources` | array | Yes | — | PDF sources to merge (in order) |
| `output_path` | string | No | — | Save output to file |

### ✂️ `compress_pdf`

Reduce PDF file size using stream optimization, object deduplication, and compression.

Example, Parameters & Response

```json
{
  "source": { "path": "/documents/large-report.pdf" },
  "compression_level": 9,
  "output_path": "/output/compressed.pdf"
}
```

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `source` | object | Yes | — | PDF source |
| `object_streams` | string | No | `"generate"` | `"generate"` (best) · `"preserve"` · `"disable"` |
| `compression_level` | integer | No | 9 | 1–9 (higher = better compression) |
| `output_path` | string | No | — | Save output to file |
| `password` | string | No | — | PDF password if encrypted |

**Response:**

```json
{
  "results": [{
    "source": "/documents/large-report.pdf",
    "original_size": 5242880,
    "compressed_size": 2097152,
    "compression_ratio": 0.4,
    "bytes_saved": 3145728
  }]
}
```

### ✂️ `fill_form`

Write values into existing PDF form fields and produce a new PDF.

Example, Parameters & Limitations

```json
{
  "source": { "path": "/documents/form.pdf" },
  "field_values": [
    { "name": "full_name", "value": "Jane Smith" },
    { "name": "agree_terms", "checked": true }
  ],
  "output_path": "/output/filled-form.pdf"
}
```

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `source` | object | Yes | — | PDF source |
| `field_values` | array | Yes | — | Fields to fill (see below) |
| `output_path` | string | No | — | Save output to file |
| `password` | string | No | — | PDF password if encrypted |

**Field value format:**

| Field | Type | Description |
|-------|------|-------------|
| `name` | string | Field name (use `extract_form_fields` to discover names) |
| `value` | string | Text value (for text fields) |
| `checked` | boolean | Checked state (for checkbox/radio fields) |

**Supported field types:** Text fields, checkboxes, radio buttons. ComboBox/ListBox selection is read-only.

### 🔒 `protect_pdf`

Add password protection using 256-bit AES encryption.

Example & Parameters

```json
{
  "source": { "path": "/documents/confidential.pdf" },
  "user_password": "secret123",
  "allow_print": "none",
  "allow_copy": false
}
```

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `source` | object | Yes | — | PDF source |
| `user_password` | string | Yes | — | Password to open the PDF |
| `owner_password` | string | No | user_password | Password to change permissions |
| `allow_print` | string | No | `"full"` | `"full"` · `"low"` · `"none"` |
| `al

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [paradyno](https://github.com/paradyno)
- **Source:** [paradyno/PDF-MCP-Server](https://github.com/paradyno/PDF-MCP-Server)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-paradyno-pdf-mcp-server
- Seller: https://agentstack.voostack.com/s/paradyno
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
