HiraraReader
Self-hosted Office-document reader for AI agents — docx, pptx, xlsx → text. No API keys.
Part of the Hirara tool hub.
Pure-Python — python-docx,
python-pptx, and
openpyxl. URL fetches route
through the hub's shared SSRF guard, hirara-core.
One tool, three formats
office_read takes a Word, PowerPoint, or Excel file and returns clean
markdown (plus the plain text). The format is auto-detected from the file
contents — they are all ZIP containers, told apart by what's inside — so the
agent never has to pick; it just says "read this file."
| Format | What comes out |
|---|---|
.docx |
Headings (#), bullet lists (-), and tables preserved as markdown |
.pptx |
Per-slide text under ## Slide N, plus speaker notes |
.xlsx |
One markdown table per sheet, under ## Sheet: <name> |
It pairs with the hub's other readers: hirarapdf for PDFs
and hiraraocr for images and scans. This one owns the Office
formats.
Legacy binary formats (
.doc/.xls/.ppt) are recognized and rejected with a clear message — save as the modern OOXML format instead.
Quick start
pip install -e ../hirara-core # shared SSRF guard (repo-local)
pip install -e ".[service,mcp]"
As an HTTP service:
uvicorn hirarareader.service:app --host 127.0.0.1 --port 8500
Read a document (base64, path, or URL) → markdown + text:
curl -X POST localhost:8500/office_read -H 'content-type: application/json' \
-d '{"file_path":"/path/to/report.docx"}'
Or upload it directly:
curl -X POST localhost:8500/office_read/upload -F file=@deck.pptx
As an MCP server over stdio (Claude Desktop / Cursor / agent runtimes):
python -m hirarareader.mcp_server
With Docker (loopback-bound, nothing to download at boot):
docker compose up -d --build
API
| Endpoint | Purpose |
|---|---|
POST /office_read |
Read one document. file_path / file_url / file_base64, filename |
POST /office_read/upload |
Same, multipart file upload |
GET /schemas |
Tool definition, ready for an LLM tools array |
GET /health |
Liveness + supported formats |
Response carries kind (docx/pptx/xlsx), markdown, text, meta
(paragraph/slide/sheet counts), truncated, source, and error. Errors come
back in the body, not as HTTP status codes: the caller is an agent loop, and
"unrecognized document" is a result to reason about.
Security
file_urlis off by default. When enabled (CRDR_ALLOW_URL_FETCH=true), the fetch goes throughhirara-core'ssafe_download— resolve-then-pin, every redirect hop re-validated, streamed under a byte cap — never a barehttpx.get.- Local file access is gated.
file_pathlets a caller name any file on the host; fine for a local/MCP server, off in the Docker image. SetCRDR_ALLOW_LOCAL_PATH=trueonly for a trusted, local deployment. - Everything is size-capped — input by
CRDR_MAX_BYTES, output byCRDR_MAX_CHARS(flagstruncated), spreadsheet rows byCRDR_MAX_ROWS.
Configuration
All via environment variable.
| Variable | Default | Notes |
|---|---|---|
CRDR_MAX_BYTES |
26214400 |
Cap on an input file (25 MB) |
CRDR_MAX_CHARS |
500000 |
Cap on output text/markdown; flags truncated |
CRDR_MAX_ROWS |
2000 |
Per-sheet row cap for spreadsheets |
CRDR_ALLOW_URL_FETCH |
false |
Enable file_url (through the SSRF guard) |
CRDR_ALLOW_LOCAL_PATH |
true (lib) / false (image) |
file_path reads |
Testing
pip install -e ".[dev]"
pytest -q
The suite builds tiny real .docx/.pptx/.xlsx files in memory and reads
them back — so it exercises the actual libraries end-to-end, no fixtures checked
in. Verified on a live server: all three formats read to the expected markdown.
License
Apache License 2.0 — see LICENSE and NOTICE.
Copyright 2026 Lucas D Marshall (Kaung Myat San).
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hirarareader-0.1.0.tar.gz.
File metadata
- Download URL: hirarareader-0.1.0.tar.gz
- Upload date:
- Size: 19.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
afa4e7d58bfba1ceaf530f572150fb9bad77e0eaca90d10f1feead93f978cfbe
|
|
| MD5 |
1957f565c2502b92c513d9ad435b076f
|
|
| BLAKE2b-256 |
10c8bcadcad82f58532344c5fee47531aec52bac8a5236e80806f90c4aff0259
|
Provenance
The following attestation bundles were made for hirarareader-0.1.0.tar.gz:
Publisher:
pypi-publish.yml on lucasdmarshall/Hirara
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hirarareader-0.1.0.tar.gz -
Subject digest:
afa4e7d58bfba1ceaf530f572150fb9bad77e0eaca90d10f1feead93f978cfbe - Sigstore transparency entry: 2370829263
- Sigstore integration time:
-
Permalink:
lucasdmarshall/Hirara@0ee6a761a9c854e848407f3a2c9ad6bb57e24960 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/lucasdmarshall
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@0ee6a761a9c854e848407f3a2c9ad6bb57e24960 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file hirarareader-0.1.0-py3-none-any.whl.
File metadata
- Download URL: hirarareader-0.1.0-py3-none-any.whl
- Upload date:
- Size: 18.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e20c6a9effebc385472ef12ad65cf23f800670821655f9f16a25b1c1ac276dcf
|
|
| MD5 |
1c1f1180cafaaf1bcaddc1e878846a90
|
|
| BLAKE2b-256 |
9d012cb6d707d99034378db3e45a948b229d5dbe90c47694078e86bc479b9782
|
Provenance
The following attestation bundles were made for hirarareader-0.1.0-py3-none-any.whl:
Publisher:
pypi-publish.yml on lucasdmarshall/Hirara
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hirarareader-0.1.0-py3-none-any.whl -
Subject digest:
e20c6a9effebc385472ef12ad65cf23f800670821655f9f16a25b1c1ac276dcf - Sigstore transparency entry: 2370829294
- Sigstore integration time:
-
Permalink:
lucasdmarshall/Hirara@0ee6a761a9c854e848407f3a2c9ad6bb57e24960 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/lucasdmarshall
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@0ee6a761a9c854e848407f3a2c9ad6bb57e24960 -
Trigger Event:
workflow_dispatch
-
Statement type: