Skip to main content

Python bindings for oxidize-pdf — generate, parse, split, merge, and manipulate PDF files

Project description

oxidize-pdf

PyPI version CI License: MIT Python Typed MCP

oxidize-python MCP server

Rust-powered PDF library for Python. Generate, parse, split, merge, and manipulate PDFs with native performance. Ships with a built-in MCP server so AI agents can work with PDFs out of the box.

No C dependencies. No Java. No subprocess calls.

Installation

pip install oxidize-pdf            # Core library
pip install "oxidize-pdf[mcp]"     # + MCP server for AI agents

Platforms: Linux (x86_64, aarch64) | macOS (x86_64, Apple Silicon) | Windows (x86_64) Requires: Python 3.10+

Why oxidize-pdf?

oxidize-pdf Pure-Python libs C/Java wrappers
Performance Native (compiled Rust) Interpreted Native but heavy
Dependencies Zero Varies Poppler, Java, Ghostscript
Memory safety Rust ownership model GC-dependent Manual / GC
Type stubs Full (mypy/pyright) Partial Rare
AI-ready (MCP) Built-in No No

MCP Server

Give your AI agent full PDF capabilities in one line:

oxidize-mcp

The built-in Model Context Protocol server exposes 12 tools, 6 resources, and 5 prompts — compatible with Claude, GPT, and any MCP client.

Claude Desktop integration

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "oxidize-pdf": {
      "command": "oxidize-mcp",
      "env": {
        "OXIDIZE_WORKSPACE": "/path/to/your/pdfs"
      }
    }
  }
}

GitHub Copilot (VS Code) integration

Copilot's agent mode speaks MCP. Add .vscode/mcp.json to your workspace:

{
  "servers": {
    "oxidize-pdf": {
      "command": "oxidize-mcp",
      "env": {
        "OXIDIZE_WORKSPACE": "/path/to/your/pdfs"
      }
    }
  }
}

Open the Chat view, switch to Agent mode, and the 12 PDF tools appear in the tool picker. (The same block also works under the mcp.servers key in your user settings.json if you prefer a global install.)

OpenAI Agents SDK integration

The OpenAI Agents SDK spawns the server over stdio and exposes its tools to an agent:

from agents import Agent, Runner
from agents.mcp import MCPServerStdio

async with MCPServerStdio(
    params={"command": "oxidize-mcp", "env": {"OXIDIZE_WORKSPACE": "/path/to/your/pdfs"}},
    cache_tools_list=True,
) as server:
    agent = Agent(
        name="PDF assistant",
        instructions="Use the oxidize-pdf tools to inspect and manipulate PDFs.",
        mcp_servers=[server],
    )
    result = await Runner.run(agent, "How many pages does report.pdf have?")
    print(result.final_output)

A runnable version is in examples/openai_agents_quickstart.py.

Both integrations run the server locally over stdio, so its tools operate on PDFs in the configured workspace directory. Remote/hosted use (e.g. the OpenAI Responses API hosted MCP tool) needs an HTTP transport and is not yet exposed.

Available tools

Tool What it does
read_pdf Read metadata — page count, version, encryption status, title, author
extract_text Extract text from all pages or a specific page
convert_pdf Convert to markdown, chunks, or RAG-optimized format
create_pdf Create a new PDF with optional metadata
save_pdf Save a session to disk, with optional encryption
add_content Add pages, text, and graphics to a session
annotate_pdf Add text annotations and highlights
manipulate_pdf Split, merge, rotate, extract pages, reverse, overlay
manage_forms Create, fill, read, and validate form fields
secure_pdf Encrypt, check permissions, verify signatures
extract_entities Extract structured entities from pages
analyze_pdf Validate structure, detect corruption, check PDF/A compliance

The server also exposes resources (session data, capabilities, version info) and prompts (guided workflows for summarization, data extraction, form filling, and more).

Configuration

OXIDIZE_WORKSPACE=/path/to/pdfs oxidize-mcp

The server is configured entirely through environment variables:

Variable Default Purpose
OXIDIZE_WORKSPACE ~/Documents/oxidize-mcp Sandbox root; all paths must resolve inside it.
OXIDIZE_ALLOWED_PATHS (none) Comma-separated extra directories allowed outside the workspace.
OXIDIZE_MAX_FILE_SIZE_MB 100 Reject input PDFs larger than this on disk.
OXIDIZE_MAX_PAGES 10000 Reject documents with more pages than this before any extraction work.
OXIDIZE_MAX_OUTPUT_BYTES 10485760 Cap the serialized size of a tool's JSON response (10 MB).
OXIDIZE_MAX_SESSIONS 10 Maximum concurrent stateful PDF-creation sessions.
OXIDIZE_MAX_SESSION_BYTES 10485760 Cap the content a single session may accumulate (10 MB).
OXIDIZE_SESSION_TIMEOUT 3600 Session expiry, in seconds.

Resource caps (OXIDIZE_MAX_*) protect the server from a large or malicious PDF: oversized documents are rejected up front and tool responses are bounded rather than serialized unbounded. Exceeding a cap returns an error with code RESOURCE_LIMIT.

Or start programmatically:

from oxidize_pdf.mcp.server import run
run()

Python API

Create a PDF

from oxidize_pdf import Document, Page, Font, Color

doc = Document()
doc.set_title("My Document")
doc.set_author("Jane Doe")

page = Page.a4()
page.set_font(Font.HELVETICA, 24.0)
page.set_text_color(Color.black())
page.text_at(72.0, 750.0, "Hello from oxidize-pdf!")

page.set_font(Font.TIMES_ROMAN, 12.0)
page.text_at(72.0, 700.0, "Generated with Python + Rust.")

doc.add_page(page)
doc.save("output.pdf")

Parse an existing PDF

from oxidize_pdf import PdfReader

reader = PdfReader.open("document.pdf")
print(f"Pages: {reader.page_count}, Version: {reader.version}")

for i, text in enumerate(reader.extract_text()):
    print(f"--- Page {i + 1} ---")
    print(text)

Operations

from oxidize_pdf import split_pdf, merge_pdfs, rotate_pdf, extract_pages

split_pdf("input.pdf", "output_dir/")                       # Split into individual pages
merge_pdfs(["part1.pdf", "part2.pdf"], "merged.pdf")         # Merge multiple PDFs
rotate_pdf("input.pdf", "rotated.pdf", 90)                   # Rotate all pages
extract_pages("input.pdf", "subset.pdf", [0, 2, 4])          # Extract specific pages

Graphics

from oxidize_pdf import Document, Page, Color

doc = Document()
page = Page.a4()

page.set_fill_color(Color.hex("#3498db"))
page.draw_rect(72.0, 700.0, 200.0, 100.0)
page.fill()

page.set_stroke_color(Color.red())
page.set_line_width(2.0)
page.draw_circle(300.0, 500.0, 50.0)
page.stroke()

doc.add_page(page)
doc.save("graphics.pdf")

Types

from oxidize_pdf import Color, Point, Rectangle, Margins, Font

# Colors
Color.rgb(1.0, 0.0, 0.0)          # RGB
Color.hex("#ff6600")               # Hex
Color.cmyk(0.0, 1.0, 1.0, 0.0)   # CMYK

# Geometry
Point(72.0, 720.0)
Rectangle.from_xywh(72.0, 72.0, 468.0, 648.0)
Margins.uniform(72.0)

# Fonts — all 14 standard PDF fonts
Font.HELVETICA    # Font.HELVETICA_BOLD
Font.TIMES_ROMAN  # Font.TIMES_BOLD
Font.COURIER      # Font.COURIER_BOLD

Error handling

from oxidize_pdf import PdfReader, PdfError, PdfIoError, PdfParseError

try:
    reader = PdfReader.open("missing.pdf")
except PdfIoError as e:
    print(f"I/O error: {e}")
except PdfParseError as e:
    print(f"Parse error: {e}")
except PdfError as e:
    print(f"PDF error: {e}")

Exception hierarchy: PdfError > PdfIoError, PdfParseError, PdfEncryptionError, PdfPermissionError

MCP Server

oxidize-pdf includes an MCP server that exposes PDF capabilities to AI assistants like Claude. Install with the mcp extra:

pip install oxidize-pdf[mcp]

Claude Desktop

Add this to your claude_desktop_config.json:

{
  "mcpServers": {
    "oxidize-pdf": {
      "command": "uvx",
      "args": ["--from", "oxidize-pdf[mcp]", "oxidize-mcp"]
    }
  }
}

Claude Code

claude mcp add oxidize-pdf -- uvx --from "oxidize-pdf[mcp]" oxidize-mcp

Available tools

Tool Description
read_pdf Open a PDF and get metadata (pages, version, encryption)
extract_text Extract text content from PDF pages
convert_pdf Convert between PDF versions
analyze_pdf Analyze structure, fonts, images, and compliance
extract_entities Extract images and digital signatures
manipulate_pdf Split, merge, rotate, extract, and reorder pages
annotate_pdf Add text annotations, highlights, and stamps
manage_forms Create, fill, and read PDF form fields
secure_pdf Encrypt, decrypt, and set document permissions
create_pdf Create a new PDF document with pages
add_pdf_content Add text, shapes, and images to pages
save_pdf Save the document to file or bytes

Resources

  • oxidize://fonts — Available built-in PDF fonts
  • oxidize://page-sizes — Standard page sizes with dimensions
  • oxidize://capabilities — Server capabilities and tool listing
  • oxidize://version — Version information
  • oxidize://workspace — PDF files in the workspace directory
  • oxidize://session/{id} — Session data by ID

Known limitations

  • Encryption write support: Document.encrypt() configures encryption parameters but the underlying Rust library does not yet serialize the encryption dictionary to the PDF output. Reading encrypted PDFs works correctly.
  • Image extraction returns raw embedded streams: extract_images_from_pdf extracts each embedded image as-is (e.g. a DCTDecode JPEG is written byte-for-byte). Image preprocessing — auto rotation-correction, contrast enhancement, denoise, upscaling, force-grayscale — is not available, because the build excludes the upstream external-images feature (and its image-crate dependency). This keeps extraction faithful and lossless; it does not silently return empty or stub results.
  • CPython only: PyPy and GraalPy are not supported.

License

MIT — see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

oxidize_pdf-0.16.0.tar.gz (671.7 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

oxidize_pdf-0.16.0-cp310-abi3-win_amd64.whl (5.1 MB view details)

Uploaded CPython 3.10+Windows x86-64

oxidize_pdf-0.16.0-cp310-abi3-manylinux_2_28_x86_64.whl (5.7 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ x86-64

oxidize_pdf-0.16.0-cp310-abi3-manylinux_2_28_aarch64.whl (5.8 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ ARM64

oxidize_pdf-0.16.0-cp310-abi3-macosx_11_0_arm64.whl (5.3 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

oxidize_pdf-0.16.0-cp310-abi3-macosx_10_12_x86_64.whl (5.5 MB view details)

Uploaded CPython 3.10+macOS 10.12+ x86-64

File details

Details for the file oxidize_pdf-0.16.0.tar.gz.

File metadata

  • Download URL: oxidize_pdf-0.16.0.tar.gz
  • Upload date:
  • Size: 671.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for oxidize_pdf-0.16.0.tar.gz
Algorithm Hash digest
SHA256 e726bd2039b736678cda00b55e1bdbbae9a64e531e649bb47958f2334bb54ed8
MD5 8d5e27b23c14b77d24c2f81607eae051
BLAKE2b-256 29cce5662255bac9b280b758de633e68e0e200145f7c146e7580dd3301f4e665

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxidize_pdf-0.16.0.tar.gz:

Publisher: release.yml on bzsanti/oxidize-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oxidize_pdf-0.16.0-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: oxidize_pdf-0.16.0-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 5.1 MB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for oxidize_pdf-0.16.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 5cede554482f8079ff784a5781db9ef55ca9147d1bea653298d31a940c59f8c3
MD5 2749900bc8d30131793dc3d97a983b15
BLAKE2b-256 25933a121d7f3f549af597642195b5262d594b967ff7df8d724f51e4c185b227

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxidize_pdf-0.16.0-cp310-abi3-win_amd64.whl:

Publisher: release.yml on bzsanti/oxidize-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oxidize_pdf-0.16.0-cp310-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for oxidize_pdf-0.16.0-cp310-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c4d2e82057700c1b3897498effbb8f88ff69d506a93a02802ae5dbfba5f6cd83
MD5 705e8687d748e452d255fb84d70d7638
BLAKE2b-256 5cd420c95104e4d32079bd3c0b2b67d80447dcaf3a09095ea5a9830153b29952

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxidize_pdf-0.16.0-cp310-abi3-manylinux_2_28_x86_64.whl:

Publisher: release.yml on bzsanti/oxidize-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oxidize_pdf-0.16.0-cp310-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for oxidize_pdf-0.16.0-cp310-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 7ac0ffc221556b91c65cb8e5408017de158c5164f3bbdc39440d313d157b13d0
MD5 ad16387b0366464066f07d4760c9b06d
BLAKE2b-256 090f3c0123fe7284d60b538003b9a36d3c6fde9667eb3ce6dd25e638704eb8d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxidize_pdf-0.16.0-cp310-abi3-manylinux_2_28_aarch64.whl:

Publisher: release.yml on bzsanti/oxidize-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oxidize_pdf-0.16.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for oxidize_pdf-0.16.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1b7b07adef2c2b888db203a5389d9356ea1ee02390b5d8e7fe855d43b1040842
MD5 63b376b3768f158e652d56305f507c07
BLAKE2b-256 6015ddab9500e64a921b32137503fef06bde67e2dcb98a712624064691a036b6

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxidize_pdf-0.16.0-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on bzsanti/oxidize-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oxidize_pdf-0.16.0-cp310-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for oxidize_pdf-0.16.0-cp310-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 af22db599353e7f64da04fd6f375a6a3d22aa5123df6b718f99ce05bb1276e85
MD5 82c9c6cc785c136340fbe0d6bae3225c
BLAKE2b-256 5702218318de57e629d7f91f516b6c5c9818d96052d1dbcf201ecf6fa71803c5

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxidize_pdf-0.16.0-cp310-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on bzsanti/oxidize-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page