flint-slating
flint-slating
MCP server that reads PDFs and exposes them to LLM consumers as structured Markdown, plus the usual ancillaries: metadata, outline, images, tables.
Designed to pair with a separate "wiki" MCP server that handles the
writing side — an agent calls flint-slating to read PDFs and another
MCP to persist notes about them into a frontmattered-markdown knowledge
base.
What it does
Built on a permissive-license PDF stack:
Library | License | Role |
MIT | PDF → Markdown with heading hierarchy, multi-column reading order, and Markdown tables | |
BSD-3 | metadata, TOC, page count, encryption checks, image enumeration | |
MIT | per-page table extraction |
There is no PyMuPDF, no MuPDF, no AGPL or GPL anywhere in the dependency tree. A CI license-check job rejects PRs that pull in copyleft transitive deps.
Transports
Two transports off the same MCP server, selected via --transport:
Transport | Run via | Use case |
Streamable-HTTP (default) |
| Long-lived local daemon, container, or shared service. |
stdio |
| The standard MCP integration shape — drop into |
Run
As an HTTP daemon (default)
uvx flint-slating # listens on PORT (default 35833)
curl http://127.0.0.1:35833/healthOr pin it:
uv tool install flint-slating
flint-slatingAs a stdio MCP server
uvx flint-slating --transport stdioWire into Claude Code's MCP config:
{
"mcpServers": {
"flint-slating": {
"command": "uvx",
"args": ["flint-slating", "--transport", "stdio"]
}
}
}Docker
docker run --rm \
-p 35833:35833 \
-v $(pwd)/pdfs:/pdfs:ro \
-v flint-slating-data:/data \
ghcr.io/parkviewlab/flint-slating:latestOr use docker-compose.yml for a persistent stack.
MCP tools
All PDF tools take a source argument with one of:
{"path": "/abs/path/to/file.pdf"}— local file{"url": "https://..."}— streamed to a content-addressed cache{"bytes_b64": "...", "filename": "x.pdf"}— base64 upload (size-capped)
Tool | What it does |
|
|
| flat outline |
| plain text by page range (fast — pypdf, no ML) |
| high-quality Markdown via Docling (hybrid sync/async — see below) |
| per-page Markdown chunks with tables/images/toc_items (hybrid sync/async) |
| enumerate images: |
| base64 bytes of one image |
| per-page Markdown tables via pdfplumber |
| poll a background job |
| fetch a finished job's artifact |
| cancel a running job |
Hybrid sync/async
pdf_read_markdown and pdf_read_chunks run inline when
page_count <= SYNC_PAGE_THRESHOLD (default 20). For larger PDFs they
queue a background job and return a job_id — poll get_job_status
until state=="done", then call get_job_result (or, in HTTP mode,
fetch output_url directly).
stdio mode transparently waits for the job inline — there's no HTTP server to download from, so the originating tool call blocks until the result is ready and returns it directly.
HTTP endpoints (HTTP mode only)
GET /health—{ok, version, uptime_seconds}GET /admin/version— package and dependency versions, Docling model statusGET /admin/jobs— recent job listGET /outputs/{job_id}/result.md— finished MarkdownGET /outputs/{job_id}/result.json— finished chunked outputGET /outputs/{job_id}/log.jsonl— append-only job logPOST /sse— MCP Streamable-HTTP transport
Configuration
Env var | Default (daemon) | Default (container) | Purpose |
|
|
| HTTP bind port |
|
|
| HTTP bind address |
|
|
| Per-job output dirs |
|
|
| Materialized URL / base64 PDFs |
|
|
| Sweep finished jobs older than N days |
|
|
| Cap on base64 upload size |
|
|
| Cap on URL download size |
|
|
| Inline-vs-job cutoff for Markdown conversion |
|
|
| Docling layout-model cache |
|
|
| Enable Docling OCR (Tesseract required) |
|
|
| Used to build |
Resource notes
Docling downloads a ~200–500 MB layout model on first use. The container image does not pre-fetch it (pre-fetching dominated multi-arch build time under QEMU); the daemon warms it on startup, and the first user-facing call pays the download. Operators can populate
DOCLING_ARTIFACTS_PATH(default/opt/docling-modelsin the container) via volume mount for a hot start.pypdf, pdfplumber, and the URL / base64 paths are fast and have no ML overhead — use
pdf_info,pdf_toc,pdf_read_text, andpdf_find_tableswhenever Markdown isn't strictly needed.
Releasing
Tag-driven CI publishes to both PyPI (flint-slating) and GHCR
(ghcr.io/parkviewlab/flint-slating):
# Bump version in pyproject.toml first, then:
git tag v0.1.0
git push origin v0.1.0The release workflow refuses tags that don't match pyproject.toml's
version, or that aren't on origin/main.
Commit message convention
After the publish jobs, a changelog job generates the new CHANGELOG.md section — an LLM-written "Highlights" paragraph plus a git-cliff categorized commit list — commits it back to main, and creates the GitHub Release with the same content as its body. Categorization uses Conventional Commits prefixes (see cliff.toml):
Prefix | Section | Notes |
| Features | user-visible |
| Bug fixes | user-visible |
| Performance | user-visible |
| Refactor | |
| Docs | |
| Tests | |
| (dropped) | not surfaced in CHANGELOG |
Squash-merge PRs use the PR title as the commit subject — so the PR title is what needs the prefix. Commits without a recognised prefix are silently dropped from the CHANGELOG (still in git history). The "Highlights" paragraph requires the ANTHROPIC_API_KEY org-level secret; if the LLM call fails, a placeholder lands and the release still ships.
License
Licensed under either of
Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0), or
MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option. In SPDX terms: MIT OR Apache-2.0.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this work by you shall be dual-licensed as above, without any additional terms or conditions. See LICENSING.md.
flint-slating only depends on permissive-licensed libraries; the CI
license-check job enforces this on every PR. torch and torchvision are pinned
to the CPU-only PyTorch wheel index so
the distribution does not bundle NVIDIA's proprietary CUDA libraries. Inference
runs on CPU on Linux/Windows and on MPS (Metal) on Apple Silicon. See
THIRD_PARTY_LICENSES.md for the per-dependency
license breakdown.
© 2026 Gary Frattarola · Licensed under MIT OR Apache-2.0 · part of ParkviewLab