oxidize-pdf

Kit de herramientas PDF impulsado por Rust sobre MCP: crear, leer y analizar PDFs; extraer texto y entidades para RAG; convertir a Markdown; dividir/combinar/rotar/reordenar páginas; gestionar campos de formulario y anotaciones; cifrar documentos. Se ejecuta localmente mediante uvx oxidize-mcp.

Documentación

oxidize-pdf

PyPI version CI License: MIT Python Typed MCP

oxidize-python MCP server

Biblioteca PDF impulsada por Rust para Python. Genera, analiza, divide, combina y manipula PDFs con rendimiento nativo. Incluye un servidor MCP integrado para que los agentes de IA puedan trabajar con PDFs sin configuración adicional.

Sin dependencias de C. Sin Java. Sin llamadas a subprocesos.

Instalación

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

Plataformas: Linux (x86_64, aarch64) | macOS (x86_64, Apple Silicon) | Windows (x86_64) Requiere: Python 3.10+

¿Por qué oxidize-pdf?

oxidize-pdfPure-Python libsC/Java wrappers
RendimientoNativo (Rust compilado)InterpretadoNativo pero pesado
DependenciasCeroVaríaPoppler, Java, Ghostscript
Seguridad de memoriaModelo de propiedad de RustDependiente del GCManual / GC
Stubs de tiposCompleto (mypy/pyright)ParcialRaro
Listo para IA (MCP)IntegradoNoNo

Servidor MCP

Dale a tu agente de IA capacidades PDF completas en una línea:

oxidize-mcp

El servidor Model Context Protocol integrado expone 12 herramientas, 6 recursos y 5 indicaciones — compatible con Claude, GPT y cualquier cliente MCP.

Integración con Claude Desktop

Añade a tu claude_desktop_config.json:

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

Integración con GitHub Copilot (VS Code)

El modo agente de Copilot habla MCP. Añade .vscode/mcp.json a tu espacio de trabajo:

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

Abre la vista de Chat, cambia al modo Agente y las 12 herramientas PDF aparecerán en el selector de herramientas. (El mismo bloque también funciona bajo la clave mcp.servers en tu settings.json de usuario si prefieres una instalación global.)

Integración con OpenAI Agents SDK

El OpenAI Agents SDK inicia el servidor sobre stdio y expone sus herramientas a un agente:

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)

Una versión ejecutable está en examples/openai_agents_quickstart.py.

Ambas integraciones ejecutan el servidor localmente sobre stdio, por lo que sus herramientas operan sobre PDFs en el directorio de espacio de trabajo configurado. El uso remoto/alojado (por ejemplo, la herramienta MCP alojada de OpenAI Responses API) necesita un transporte HTTP y aún no está expuesto.

Herramientas disponibles

HerramientaQué hace
read_pdfLee metadatos — número de páginas, versión, estado de cifrado, título, autor
extract_textExtrae texto de todas las páginas o de una página específica
convert_pdfConvierte a markdown, fragmentos o formato optimizado para RAG
create_pdfCrea un nuevo PDF con metadatos opcionales
save_pdfGuarda una sesión en disco, con cifrado opcional
add_contentAñade páginas, texto y gráficos a una sesión
annotate_pdfAñade anotaciones de texto y resaltados
manipulate_pdfDivide, combina, rota, extrae páginas, invierte, superpone
manage_formsCrea, rellena, lee y valida campos de formulario
secure_pdfCifra, comprueba permisos, verifica firmas
extract_entitiesExtrae entidades estructuradas de las páginas
analyze_pdfValida la estructura, detecta corrupción, comprueba el cumplimiento PDF/A

El servidor también expone recursos (datos de sesión, capacidades, información de versión) e indicaciones (flujos de trabajo guiados para resumen, extracción de datos, relleno de formularios y más).

Configuración

OXIDIZE_WORKSPACE=/path/to/pdfs oxidize-mcp

El servidor se configura completamente mediante variables de entorno:

VariablePredeterminadoPropósito
OXIDIZE_WORKSPACE~/Documents/oxidize-mcpRaíz del sandbox; todas las rutas deben resolverse dentro de ella.
OXIDIZE_ALLOWED_PATHS(ninguno)Directorios adicionales separados por comas permitidos fuera del espacio de trabajo.
OXIDIZE_MAX_FILE_SIZE_MB100Rechaza PDFs de entrada más grandes que esto en disco.
OXIDIZE_MAX_PAGES10000Rechaza documentos con más páginas que esto antes de cualquier trabajo de extracción.
OXIDIZE_MAX_OUTPUT_BYTES10485760Limita el tamaño serializado de la respuesta JSON de una herramienta (10 MB).
OXIDIZE_MAX_SESSIONS10Máximo de sesiones concurrentes de creación de PDF con estado.
OXIDIZE_MAX_SESSION_BYTES10485760Limita el contenido que una sola sesión puede acumular (10 MB).
OXIDIZE_SESSION_TIMEOUT3600Caducidad de la sesión, en segundos.

Los límites de recursos (OXIDIZE_MAX_*) protegen al servidor de un PDF grande o malicioso: los documentos sobredimensionados se rechazan de antemano y las respuestas de las herramientas están limitadas en lugar de serializarse sin límite. Superar un límite devuelve un error con código RESOURCE_LIMIT.

O iniciar programáticamente:

from oxidize_pdf.mcp.server import run
run()

API de Python

Crear un 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")

Analizar un PDF existente

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)

Operaciones

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

Gráficos

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")

Tipos

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

Manejo de errores

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}")

Jerarquía de excepciones: PdfError > PdfIoError, PdfParseError, PdfEncryptionError, PdfPermissionError

Servidor MCP

oxidize-pdf incluye un servidor MCP que expone capacidades PDF a asistentes de IA como Claude. Instala con el extra mcp:

pip install oxidize-pdf[mcp]

Claude Desktop

Añade esto a tu 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

Herramientas disponibles

HerramientaDescripción
read_pdfAbre un PDF y obtén metadatos (páginas, versión, cifrado)
extract_textExtrae contenido de texto de las páginas del PDF
convert_pdfConvierte entre versiones de PDF
analyze_pdfAnaliza estructura, fuentes, imágenes y cumplimiento
extract_entitiesExtrae imágenes y firmas digitales
manipulate_pdfDivide, combina, rota, extrae y reordena páginas
annotate_pdfAñade anotaciones de texto, resaltados y sellos
manage_formsCrea, rellena y lee campos de formulario PDF
secure_pdfCifra, descifra y establece permisos de documento
create_pdfCrea un nuevo documento PDF con páginas
add_pdf_contentAñade texto, formas e imágenes a las páginas
save_pdfGuarda el documento en archivo o bytes

Recursos

  • oxidize://fonts — Fuentes PDF integradas disponibles
  • oxidize://page-sizes — Tamaños de página estándar con dimensiones
  • oxidize://capabilities — Capacidades del servidor y listado de herramientas
  • oxidize://version — Información de versión
  • oxidize://workspace — Archivos PDF en el directorio del espacio de trabajo
  • oxidize://session/{id} — Datos de sesión por ID

Limitaciones conocidas

  • Soporte de escritura de cifrado: Document.encrypt() configura los parámetros de cifrado, pero la biblioteca Rust subyacente aún no serializa el diccionario de cifrado en la salida del PDF. La lectura de PDFs cifrados funciona correctamente.
  • La extracción de imágenes devuelve flujos incrustados sin procesar: extract_images_from_pdf extrae cada imagen incrustada tal cual (por ejemplo, un JPEG DCTDecode se escribe byte a byte). El preprocesamiento de imágenes — corrección automática de rotación, mejora de contraste, reducción de ruido, ampliación, forzar escala de grises — no está disponible, porque la compilación excluye la característica external-images upstream (y su dependencia de crate image). Esto mantiene la extracción fiel y sin pérdidas; no devuelve silenciosamente resultados vacíos o simulados.
  • Solo CPython: PyPy y GraalPy no son compatibles.

Licencia

MIT — consulta LICENSE para más detalles.