Skip to main content

Hirarapdf

Self-hosted PDF tools for AI agents — read, parse, and create. No API keys.

Part of the Hirara tool hub. Pure-Python: pypdf reads, reportlab writes. URL fetches route through the hub's shared SSRF guard, hirara-core.

License Python MCP


Three tools

Tool Role What it does
pdf_read reader Full text + per-page text + metadata out of a PDF
pdf_info parser Structure only — page count, metadata, outline, form fields, page sizes
pdf_create maker A real, paginating PDF from Markdown, plain text, or HTML

pdf_info is the cheap "what is this file" call — use it to decide whether or how to read a large or unfamiliar PDF before paying to extract every page.


Quick start

pip install -e ../hirara-core        # shared SSRF guard (repo-local)
pip install -e ".[service,mcp]"

As an HTTP service:

uvicorn hirarapdf.service:app --host 127.0.0.1 --port 8200

Read a PDF's text (base64, path, or URL):

curl -X POST localhost:8200/pdf_read -H 'content-type: application/json' \
  -d '{"pdf_path":"/path/to/report.pdf"}'

Or upload it directly:

curl -X POST localhost:8200/pdf_read/upload -F file=@report.pdf

Inspect structure without extracting all the text:

curl -X POST localhost:8200/pdf_info -H 'content-type: application/json' \
  -d '{"pdf_path":"/path/to/report.pdf"}'

Create a PDF from Markdown — returns pdf_base64, or writes to output_path:

curl -X POST localhost:8200/pdf_create -H 'content-type: application/json' \
  -d '{"content":"# Hello\n\n- one\n- two","title":"Demo","output_path":"out.pdf"}'

As an MCP server over stdio (Claude Desktop / Cursor / agent runtimes):

python -m hirarapdf.mcp_server

With Docker (loopback-bound, nothing to download at boot):

docker compose up -d --build

The maker's input formats

pdf_create accepts three formats, all rendered pure-Python on top of reportlab — no browser engine, no cairo/pango system libraries, the usual way "HTML to PDF" balloons a container.

markdown — a lightweight subset, deliberately not full CommonMark: #/##/### headings, -/* bullet lists, 1. numbered lists, ``` fenced code blocks, and inline **bold**, *italic*, `code`. Not supported: tables, images, nested blockquotes. User content is XML-escaped before the inline markup is applied, so a document that literally contains <script> or & renders as text, not broken markup.

text — plain text; blank lines separate paragraphs. No markup at all.

html — a practical subset of HTML + CSS, rendered by xhtml2pdf: headings, paragraphs, lists, tables, images, and simple inline/@page CSS. It is not a modern layout engine — JavaScript, flexbox and grid do not apply, so feed it document-style HTML. A bare fragment is wrapped in a minimal document (so title/author/subject reach the PDF metadata); a full <html> document is passed through and controls its own <head>.

curl -X POST localhost:8200/pdf_create -H 'content-type: application/json' \
  -d '{"format":"html","content":"<h1>Invoice</h1><table><tr><td>A</td><td>1</td></tr></table>","title":"Invoice"}'

Security

This tool turns attacker-influenceable bytes into and out of PDFs, so three levers matter:

pdf_url is off by default. When you enable it (CPDF_ALLOW_URL_FETCH=true), the fetch goes through hirara-core's safe_download — resolve-then-pin, every redirect hop re-validated, streamed under a hard byte cap — so a public URL that 302s to 169.254.169.254 is rejected at the hop. It is never a bare httpx.get.

Local filesystem access is gated. pdf_path (read) and output_path (write) let a caller name any path on the host. Fine for a local MCP server or a loopback service you trust; off in the Docker image because a network-exposed service should not read or write arbitrary files. Set CPDF_ALLOW_LOCAL_PATH=true only for a trusted, local deployment.

Everything is size-capped. Input PDFs are bounded by CPDF_MAX_BYTES, extracted text by CPDF_MAX_CHARS (the result flags truncated=true), and pdf_create input by CPDF_MAX_CREATE_CHARS.

Errors come back in the response body, not as HTTP status codes — the caller is an agent loop, and "PDF too large" is a result to reason about, not a transport failure. Every response carries the same keys whether it succeeded or failed.

Note — no OCR. pdf_read extracts a PDF's embedded text layer. A scanned PDF that is just images with no text layer comes back with little or no text. OCR is a separate concern (and a candidate for a future hub tool).


API

Endpoint Purpose
POST /pdf_read Extract text. pdf_path / pdf_url / pdf_base64, password, include_pages
POST /pdf_read/upload Same, multipart file upload
POST /pdf_info Structure only. Same sources
POST /pdf_info/upload Same, multipart file upload
POST /pdf_create Build a PDF. content, format, title, author, subject, page_size, output_path
GET /schemas Tool definitions, ready for an LLM tools array
GET /health Liveness + effective config

Configuration

All via environment variable.

Variable Default Notes
CPDF_MAX_BYTES 26214400 Cap on an input PDF (25 MB)
CPDF_MAX_CHARS 200000 Cap on extracted text; result flags truncated
CPDF_ALLOW_URL_FETCH false Enable pdf_url (through the SSRF guard)
CPDF_URL_TIMEOUT 30 Seconds for a URL fetch
CPDF_ALLOW_LOCAL_PATH true (lib) / false (image) pdf_path read + output_path write
CPDF_PAGE_SIZE A4 Default page size for pdf_create
CPDF_MAX_CREATE_CHARS 500000 Cap on pdf_create input length

Testing

pip install -e ".[dev]"
pytest -q

The suite roundtrips through both engines — the maker builds a PDF, the reader reads it back — so no binary fixtures are checked in. It also proves pdf_url routes through the shared SSRF guard and surfaces a block as an error envelope rather than an exception.


License

Apache License 2.0 — see LICENSE and NOTICE.

Copyright 2026 Lucas D Marshall (Kaung Myat San).

Release files for hirarapdf 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hirarapdf 0.1.0
File Size Uploaded
hirarapdf-0.1.0.tar.gz 28.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hirarapdf 0.1.0
File Interpreter ABI Platform
hirarapdf-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 55.3 kB

Release files / hirarapdf-0.1.0.tar.gz

Download URL hirarapdf-0.1.0.tar.gz
Size 28.5 kB
Tags Source
SHA-256 checksum
How to use checksums
78135eca2807b38001a9fb80dcbf3cb40d32ddef81950d7f39b92a3d63ec667c
BLAKE2b-256 checksum
How to use checksums
60878a5c86961f0c29dc5a7c7ee6bc23a43f402c05d8e4f75c15b64760527e20
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 6, 2026.

Transparency log

Release files / hirarapdf-0.1.0-py3-none-any.whl

Download URL hirarapdf-0.1.0-py3-none-any.whl
Size 26.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ada0109efab22c5de2337066a4ba4d3fff9e41dfb527ef532832b02248eaee0e
BLAKE2b-256 checksum
How to use checksums
d55ac9749f608f38d6fc557a9951c4087ff830c2edac640362b96a1013c69a6f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page