flint-slating
MCP server that reads PDFs and exposes them as structured Markdown, metadata, outlines, images, and tables to LLM consumers via tools like pdf_read_markdown and pdf_info.
README
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 |
|---|---|---|
| Docling | MIT | PDF → Markdown with heading hierarchy, multi-column reading order, and Markdown tables |
| pypdf | BSD-3 | metadata, TOC, page count, encryption checks, image enumeration |
| pdfplumber | 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) | uvx flint-slating or --transport http |
Long-lived local daemon, container, or shared service. |
| stdio | uvx flint-slating --transport stdio |
The standard MCP integration shape — drop into claude_desktop_config.json or any mcp.json. |
Run
As an HTTP daemon (default)
uvx flint-slating # listens on PORT (default 35833)
curl http://127.0.0.1:35833/health
Or pin it:
uv tool install flint-slating
flint-slating
As a stdio MCP server
uvx flint-slating --transport stdio
Wire 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:latest
Or 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 |
|---|---|
pdf_info |
{page_count, metadata, is_encrypted, sha256} |
pdf_toc |
flat outline [{level, title, page}] |
pdf_read_text |
plain text by page range (fast — pypdf, no ML) |
pdf_read_markdown |
high-quality Markdown via Docling (hybrid sync/async — see below) |
pdf_read_chunks |
per-page Markdown chunks with tables/images/toc_items (hybrid sync/async) |
pdf_list_images |
enumerate images: [{page, index, name, width, height, ext}] |
pdf_extract_image |
base64 bytes of one image |
pdf_find_tables |
per-page Markdown tables via pdfplumber |
get_job_status |
poll a background job |
get_job_result |
fetch a finished job's artifact |
cancel_job |
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 |
|---|---|---|---|
PORT |
35833 |
35833 |
HTTP bind port |
HOST |
0.0.0.0 |
0.0.0.0 |
HTTP bind address |
OUTPUT_ROOT |
./output |
/data/output |
Per-job output dirs |
CACHE_ROOT |
./cache |
/data/cache |
Materialized URL / base64 PDFs |
OUTPUT_EXPIRY_DAYS |
7 |
7 |
Sweep finished jobs older than N days |
MAX_INLINE_PDF_BYTES |
25 MB |
25 MB |
Cap on base64 upload size |
MAX_URL_PDF_BYTES |
200 MB |
200 MB |
Cap on URL download size |
SYNC_PAGE_THRESHOLD |
20 |
20 |
Inline-vs-job cutoff for Markdown conversion |
DOCLING_ARTIFACTS_PATH |
~/.cache/docling |
/opt/docling-models |
Docling layout-model cache |
ENABLE_OCR |
false |
false |
Enable Docling OCR (Tesseract required) |
PUBLIC_BASE_URL |
http://localhost:35833 |
http://localhost:35833 |
Used to build output_url |
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.0
The release workflow refuses tags that don't match pyproject.toml's
version, or that aren't on origin/main.
License
MIT. 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.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。