Skip to main content
Glama
gzigurella

PDF MCP

by gzigurella
README.md
# PDF MCP
MCP server for PDF processing and analysis using PyPDFium2.

## Features

- **extract_text**: Extract text content from PDF files with page range support
- **extract_metadata**: Extract PDF metadata including title, author, and page count
- **search_text**: Search for specific text within PDF files with context
- **get_page_count**: Get the total number of pages in a PDF file
- **extract_pages**: Extract specific pages from a PDF and save as a new PDF
- **split_pdf**: Split a PDF into multiple page-based PDFs with base64 encoding
- **merge_pdfs**: Merge multiple PDF files into a single PDF
- **pdf_to_images**: Convert PDF pages to PNG images with configurable DPI
- **get_form_fields**: Extract all form fields from a PDF including names, types, and values
- **fill_form**: Fill form fields in a PDF with provided values and save to output path

## Installation

### From Git Repository

```bash
# Clone the repository
git clone https://github.com/gzigurella/pdf-mcp.git
cd pdf-mcp

# Create virtual environment
python3 -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install the package
pip install -e .
```

### With uv (recommended)

```bash
# Clone and enter directory
git clone https://github.com/gzigurella/pdf-mcp.git
cd pdf-mcp

# Install with uv
uv pip install -e .
```

## Integration

### OpenCode

Add to your `~/.config/opencode/opencode.json`:

```json
{
  "mcpServers": {
    "pdf-mcp": {
      "type": "local",
      "command": [
        "/path/to/pdf-mcp/venv/bin/python",
        "-m",
        "pdf_mcp"
      ],
      "enabled": true
    }
  }
}
```

### Claude Desktop

Add to your Claude Desktop config:

**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
**Linux**: `~/.config/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "pdf-mcp": {
      "command": "/path/to/pdf-mcp/venv/bin/python",
      "args": ["-m", "pdf_mcp"]
    }
  }
}
```

### Generic MCP Client

For any MCP-compatible client:

```bash
# Start the server directly
/path/to/venv/bin/python -m pdf_mcp
```

The server communicates via stdio using the MCP protocol.

## Tools

### extract_text

Extract text content from a PDF file. Supports PDFs with searchable text and can extract text from specific pages or ranges.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| file_path | string | Yes | - | Path to the PDF file to extract text from |
| pages | string | No | "all" | Page range to extract (e.g., '1-5', '3,7,9', 'all') |

```json
{
  "file_path": "/path/to/document.pdf",
  "pages": "1-5"
}
```

### extract_metadata

Extract metadata from a PDF file including title, author, subject, keywords, creator, producer, creation date, modification date, and page count.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| file_path | string | Yes | - | Path to the PDF file to extract metadata from |

```json
{
  "file_path": "/path/to/document.pdf"
}
```

### search_text

Search for specific text within a PDF file. Returns page numbers and context around the found text. Useful for finding specific content in large documents.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| file_path | string | Yes | - | Path to the PDF file to search within |
| query | string | Yes | - | Text to search for in the PDF |
| case_sensitive | boolean | No | false | Whether to perform case-sensitive search |
| context_words | integer | No | 10 | Number of words to include before and after each match |

```json
{
  "file_path": "/path/to/document.pdf",
  "query": "important term",
  "case_sensitive": false,
  "context_words": 5
}
```

### get_page_count

Get the total number of pages in a PDF file. Returns a simple integer count.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| file_path | string | Yes | - | Path to the PDF file to count pages for |

```json
{
  "file_path": "/path/to/document.pdf"
}
```

### extract_pages

Extract specific pages from a PDF file and save as a new PDF. Supports page ranges and individual page selection.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| file_path | string | Yes | - | Path to the source PDF file |
| pages | string | Yes | - | Pages to extract (e.g., '1-5', '3,7,9', '1,3-5') |
| output_path | string | Yes | - | Path where the extracted pages will be saved as a new PDF |

```json
{
  "file_path": "/path/to/source.pdf",
  "pages": "1,3,5-7",
  "output_path": "/path/to/output.pdf"
}
```

### split_pdf

Split a PDF file into multiple separate PDF files based on page ranges. Returns a JSON with base64-encoded PDFs for each selected page. Supports single pages, page ranges, and all pages.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| file_path | string | Yes | - | Path to the PDF file to split |
| page_range | string | Yes | - | Page range to split - 'all', single page (e.g., '1'), or range (e.g., '1-3', '2-5') |

```json
{
  "file_path": "/path/to/document.pdf",
  "page_range": "1-3"
}
```

### merge_pdfs

Merge multiple PDF files into a single PDF. Files are merged in the order provided.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| file_paths | array | Yes | - | List of PDF file paths to merge |
| output_path | string | Yes | - | Path where the merged PDF will be saved |

```json
{
  "file_paths": ["/path/to/doc1.pdf", "/path/to/doc2.pdf", "/path/to/doc3.pdf"],
  "output_path": "/path/to/merged.pdf"
}
```

### pdf_to_images

Convert PDF pages to PNG images. Returns a JSON with base64-encoded PNG images for each page. Supports custom DPI settings for resolution control.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| file_path | string | Yes | - | Path to the PDF file to convert to images |
| dpi | integer | No | 150 | Image resolution in dots per inch |
| format | string | No | "png" | Image format (PNG only) |

```json
{
  "file_path": "/path/to/document.pdf",
  "dpi": 300,
  "format": "png"
}
```

### get_form_fields

Extract all form fields from a PDF document including field names, types, current values, and available choices for dropdown fields.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| file_path | string | Yes | - | Path to the PDF file to extract form fields from |

```json
{
  "file_path": "/path/to/form.pdf"
}
```

Returns a JSON with field information:
```json
{
  "fields": [
    {
      "name": "first_name",
      "type": "text",
      "value": "",
      "page": 1,
      "rect": {"x0": 50, "y0": 72, "x1": 150, "y1": 92}
    },
    {
      "name": "country",
      "type": "combobox",
      "value": "",
      "page": 1,
      "rect": {...},
      "choices": ["USA", "Canada", "UK"]
    },
    {
      "name": "accept_terms",
      "type": "checkbox",
      "value": "",
      "page": 1,
      "rect": {...},
      "on_state": "Yes"
    }
  ],
  "total_fields": 3
}
```

### fill_form

Fill form fields in a PDF document with provided values and save to output path. Supports text fields, checkboxes, radio buttons, and dropdowns.

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| file_path | string | Yes | - | Path to the source PDF file |
| fields | object | Yes | - | Dictionary of field names and their values to fill |
| output_path | string | Yes | - | Path where the filled PDF will be saved |

```json
{
  "file_path": "/path/to/form.pdf",
  "fields": {
    "first_name": "John",
    "last_name": "Doe",
    "country": "USA",
    "accept_terms": true
  },
  "output_path": "/path/to/filled_form.pdf"
}
```

Checkbox values accept: `true`/`false`, `"yes"`/`"no"`, `"1"`/`"0"`.
Radio buttons: use the value from `on_state` field (get with `get_form_fields` first).

## Configuration

### Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| PDF_MCP_DEBUG | false | Enable debug logging |

```bash
# Example
export PDF_MCP_DEBUG=true
python -m pdf_mcp
```

## Development

### Running Tests

```bash
source venv/bin/activate
pytest

# With coverage
pytest --cov=src --cov-report=html
```

### Project Structure

```
pdf-mcp/
├── src/pdf_mcp/
│   ├── __init__.py
│   ├── __main__.py
│   ├── server.py
│   ├── config.py
│   └── tools/
│       ├── __init__.py
│       ├── extract_text.py
│       ├── extract_metadata.py
│       ├── search_text.py
│       ├── get_page_count.py
│       ├── extract_pages.py
│       ├── split_pdf.py
│       ├── merge_pdfs.py
│       ├── pdf_to_images.py
│       ├── get_form_fields.py
│       └── fill_form.py
├── tests/
├── pyproject.toml
└── README.md
```

## Troubleshooting

### Installation Issues

If you encounter installation errors, ensure you have Python 3.10 or later:

```bash
python --version
```

### File Not Found Errors

Make sure the PDF file paths are correct and the files exist:

```bash
ls -l /path/to/your/document.pdf
```

### Encrypted PDFs

The tools will raise a RuntimeError if attempting to process encrypted PDFs. Ensure your PDFs are not password-protected.

### Memory Issues with Large PDFs

For very large PDF files, consider processing them in smaller chunks using the `extract_pages` or `split_pdf` tools.

### Permission Errors (Linux)

If you encounter permission errors, ensure the PDF files are readable:

```bash
chmod +r /path/to/your/document.pdf
```

## Security Considerations

- **File Access**: The server only processes files that exist and are readable by the running process
- **Path Validation**: All file paths are validated before processing
- **No Network Access**: The server does not make any network requests
- **Temporary Files**: Temporary files are properly cleaned up after processing
- **Error Handling**: Sensitive information is not exposed in error messages
- **Encrypted PDFs**: Password-protected PDFs are rejected with appropriate error messages

## Example Usage Scenarios

### Scenario 1: Extract Text from Specific Pages

```json
{
  "name": "extract_text",
  "arguments": {
    "file_path": "/documents/report.pdf",
    "pages": "1-3,7,9"
  }
}
```

### Scenario 2: Search and Extract Context

```json
{
  "name": "search_text",
  "arguments": {
    "file_path": "/documents/contract.pdf",
    "query": "liability clause",
    "case_sensitive": true,
    "context_words": 15
  }
}
```

### Scenario 3: Merge Multiple Reports

```json
{
  "name": "merge_pdfs",
  "arguments": {
    "file_paths": [
      "/reports/q1.pdf",
      "/reports/q2.pdf", 
      "/reports/q3.pdf",
      "/reports/q4.pdf"
    ],
    "output_path": "/reports/annual.pdf"
  }
}
```

### Scenario 4: Convert PDF to Images

```json
{
  "name": "pdf_to_images",
  "arguments": {
    "file_path": "/documents/presentation.pdf",
    "dpi": 300
  }
}
```

## License

MIT

TDQS

A4.2/5.0

Scored across 10 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: metadata extraction, text extraction, page extraction, form handling, merging, splitting, conversion to images, text search, and page count. No overlapping functionality.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case (e.g., extract_metadata, merge_pdfs, get_page_count). The naming is predictable and clear.

Tool Count5/5

10 tools cover a well-scoped set of PDF operations without redundancy. The count is appropriate for a utility server handling common PDF tasks.

Completeness4/5

The tool set covers core PDF workflows: metadata, text extraction, page manipulation, form handling, merging, splitting, search, and conversion. Minor gaps like PDF creation or OCR are absent but not critical for typical use.

Maintenance

ActivityInactive
ResponsivenessNo issues