{"id":47862501,"url":"https://github.com/bzsanti/oxidize-python","last_synced_at":"2026-04-03T23:49:07.169Z","repository":{"id":344173515,"uuid":"1176759916","full_name":"bzsanti/oxidize-python","owner":"bzsanti","description":"Python bindings for oxidize-pdf — generate, parse, split, merge \u0026 manipulate PDFs with native Rust performance. No C deps, no Java, no subprocesses.","archived":false,"fork":false,"pushed_at":"2026-04-03T08:13:29.000Z","size":358,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"develop","last_synced_at":"2026-04-03T23:49:05.284Z","etag":null,"topics":["maturin","pdf","pdf-extraction","pdf-generation","pdf-manipulation","pdf-merge","pdf-parser","pyo3","python","rust"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/oxidize-pdf/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bzsanti.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-09T10:51:51.000Z","updated_at":"2026-03-30T15:04:47.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bzsanti/oxidize-python","commit_stats":null,"previous_names":["bzsanti/oxidize-python"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/bzsanti/oxidize-python","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bzsanti%2Foxidize-python","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bzsanti%2Foxidize-python/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bzsanti%2Foxidize-python/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bzsanti%2Foxidize-python/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bzsanti","download_url":"https://codeload.github.com/bzsanti/oxidize-python/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bzsanti%2Foxidize-python/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31382355,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-03T23:20:52.058Z","status":"ssl_error","status_checked_at":"2026-04-03T23:20:51.675Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["maturin","pdf","pdf-extraction","pdf-generation","pdf-manipulation","pdf-merge","pdf-parser","pyo3","python","rust"],"created_at":"2026-04-03T23:49:04.012Z","updated_at":"2026-04-03T23:49:07.153Z","avatar_url":"https://github.com/bzsanti.png","language":"Python","readme":"# oxidize-pdf\n\n\u003c!-- mcp-name: io.github.bzsanti/oxidize-pdf-mcp --\u003e\n\n[![PyPI version](https://img.shields.io/pypi/v/oxidize-pdf)](https://pypi.org/project/oxidize-pdf/)\n[![CI](https://github.com/bzsanti/oxidize-python/actions/workflows/ci.yml/badge.svg)](https://github.com/bzsanti/oxidize-python/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n[![Python](https://img.shields.io/pypi/pyversions/oxidize-pdf)](https://pypi.org/project/oxidize-pdf/)\n[![Typed](https://img.shields.io/badge/typing-typed-green)](https://github.com/bzsanti/oxidize-python)\n[![MCP](https://img.shields.io/badge/MCP-compatible-purple)](https://modelcontextprotocol.io/)\n\n**Rust-powered PDF library for Python.** Generate, parse, split, merge, and manipulate PDFs with native performance. Ships with a built-in [MCP server](#mcp-server) so AI agents can work with PDFs out of the box.\n\nNo C dependencies. No Java. No subprocess calls.\n\n## Installation\n\n```bash\npip install oxidize-pdf            # Core library\npip install \"oxidize-pdf[mcp]\"     # + MCP server for AI agents\n```\n\n**Platforms:** Linux (x86_64, aarch64) | macOS (x86_64, Apple Silicon) | Windows (x86_64)\n**Requires:** Python 3.10+\n\n## Why oxidize-pdf?\n\n| | oxidize-pdf | Pure-Python libs | C/Java wrappers |\n|---|---|---|---|\n| **Performance** | Native (compiled Rust) | Interpreted | Native but heavy |\n| **Dependencies** | Zero | Varies | Poppler, Java, Ghostscript |\n| **Memory safety** | Rust ownership model | GC-dependent | Manual / GC |\n| **Type stubs** | Full (mypy/pyright) | Partial | Rare |\n| **AI-ready (MCP)** | Built-in | No | No |\n\n---\n\n## MCP Server\n\nGive your AI agent full PDF capabilities in one line:\n\n```bash\noxidize-mcp\n```\n\nThe built-in [Model Context Protocol](https://modelcontextprotocol.io/) server exposes **12 tools**, **6 resources**, and **5 prompts** — compatible with Claude, GPT, and any MCP client.\n\n### Claude Desktop integration\n\nAdd to your `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"oxidize-pdf\": {\n      \"command\": \"oxidize-mcp\",\n      \"env\": {\n        \"OXIDIZE_WORKSPACE\": \"/path/to/your/pdfs\"\n      }\n    }\n  }\n}\n```\n\n### Available tools\n\n| Tool | What it does |\n|------|-------------|\n| `read_pdf` | Read metadata — page count, version, encryption status, title, author |\n| `extract_text` | Extract text from all pages or a specific page |\n| `convert_pdf` | Convert to markdown, chunks, or RAG-optimized format |\n| `create_pdf` | Create a new PDF with optional metadata |\n| `save_pdf` | Save a session to disk, with optional encryption |\n| `add_content` | Add pages, text, and graphics to a session |\n| `annotate_pdf` | Add text annotations and highlights |\n| `manipulate_pdf` | Split, merge, rotate, extract pages, reverse, overlay |\n| `manage_forms` | Create, fill, read, and validate form fields |\n| `secure_pdf` | Encrypt, check permissions, verify signatures |\n| `extract_entities` | Extract structured entities from pages |\n| `analyze_pdf` | Validate structure, detect corruption, check PDF/A compliance |\n\nThe server also exposes **resources** (session data, capabilities, version info) and **prompts** (guided workflows for summarization, data extraction, form filling, and more).\n\n### Configuration\n\n```bash\nOXIDIZE_WORKSPACE=/path/to/pdfs oxidize-mcp\n```\n\nOr start programmatically:\n\n```python\nfrom oxidize_pdf.mcp.server import run\nrun()\n```\n\n---\n\n## Python API\n\n### Create a PDF\n\n```python\nfrom oxidize_pdf import Document, Page, Font, Color\n\ndoc = Document()\ndoc.set_title(\"My Document\")\ndoc.set_author(\"Jane Doe\")\n\npage = Page.a4()\npage.set_font(Font.HELVETICA, 24.0)\npage.set_text_color(Color.black())\npage.text_at(72.0, 750.0, \"Hello from oxidize-pdf!\")\n\npage.set_font(Font.TIMES_ROMAN, 12.0)\npage.text_at(72.0, 700.0, \"Generated with Python + Rust.\")\n\ndoc.add_page(page)\ndoc.save(\"output.pdf\")\n```\n\n### Parse an existing PDF\n\n```python\nfrom oxidize_pdf import PdfReader\n\nreader = PdfReader.open(\"document.pdf\")\nprint(f\"Pages: {reader.page_count}, Version: {reader.version}\")\n\nfor i, text in enumerate(reader.extract_text()):\n    print(f\"--- Page {i + 1} ---\")\n    print(text)\n```\n\n### Operations\n\n```python\nfrom oxidize_pdf import split_pdf, merge_pdfs, rotate_pdf, extract_pages\n\nsplit_pdf(\"input.pdf\", \"output_dir/\")                       # Split into individual pages\nmerge_pdfs([\"part1.pdf\", \"part2.pdf\"], \"merged.pdf\")         # Merge multiple PDFs\nrotate_pdf(\"input.pdf\", \"rotated.pdf\", 90)                   # Rotate all pages\nextract_pages(\"input.pdf\", \"subset.pdf\", [0, 2, 4])          # Extract specific pages\n```\n\n### Graphics\n\n```python\nfrom oxidize_pdf import Document, Page, Color\n\ndoc = Document()\npage = Page.a4()\n\npage.set_fill_color(Color.hex(\"#3498db\"))\npage.draw_rect(72.0, 700.0, 200.0, 100.0)\npage.fill()\n\npage.set_stroke_color(Color.red())\npage.set_line_width(2.0)\npage.draw_circle(300.0, 500.0, 50.0)\npage.stroke()\n\ndoc.add_page(page)\ndoc.save(\"graphics.pdf\")\n```\n\n### Types\n\n```python\nfrom oxidize_pdf import Color, Point, Rectangle, Margins, Font\n\n# Colors\nColor.rgb(1.0, 0.0, 0.0)          # RGB\nColor.hex(\"#ff6600\")               # Hex\nColor.cmyk(0.0, 1.0, 1.0, 0.0)   # CMYK\n\n# Geometry\nPoint(72.0, 720.0)\nRectangle.from_xywh(72.0, 72.0, 468.0, 648.0)\nMargins.uniform(72.0)\n\n# Fonts — all 14 standard PDF fonts\nFont.HELVETICA    # Font.HELVETICA_BOLD\nFont.TIMES_ROMAN  # Font.TIMES_BOLD\nFont.COURIER      # Font.COURIER_BOLD\n```\n\n### Error handling\n\n```python\nfrom oxidize_pdf import PdfReader, PdfError, PdfIoError, PdfParseError\n\ntry:\n    reader = PdfReader.open(\"missing.pdf\")\nexcept PdfIoError as e:\n    print(f\"I/O error: {e}\")\nexcept PdfParseError as e:\n    print(f\"Parse error: {e}\")\nexcept PdfError as e:\n    print(f\"PDF error: {e}\")\n```\n\nException hierarchy: `PdfError` \u003e `PdfIoError`, `PdfParseError`, `PdfEncryptionError`, `PdfPermissionError`\n\n## Known limitations\n\n- **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.\n- **CPython only**: PyPy and GraalPy are not supported.\n\n## License\n\nMIT — see [LICENSE](LICENSE) for details.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbzsanti%2Foxidize-python","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbzsanti%2Foxidize-python","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbzsanti%2Foxidize-python/lists"}