MCP server exposing the PDF Extractor API as tools.
Project description
PDF Extractor MCP Server
A Model Context Protocol server that exposes the PDF Extractor API as tools so that LLM agents (Claude Desktop, Claude Code, Cursor, etc.) can extract images, tables, text blocks, formulas, and other elements from PDF documents.
Tools
| Tool | Description |
|---|---|
extract_elements |
Extract elements from a single PDF (path, URL, or base64). |
extract_elements_batch |
Extract elements from multiple PDFs (Business tier). |
list_extractions |
Paginate the authenticated user's past extraction jobs. |
get_extraction |
Fetch details and files for a specific extraction. |
delete_extraction |
Delete an extraction job. |
download_file |
Fetch (and optionally save) a presigned Files[].Url from an extraction. |
Install
Requires Python 3.10+. Pick whichever fits your workflow:
# Zero local setup — recommended for end users
uvx pdf-extractor-mcp
# Or a persistent install
pipx install pdf-extractor-mcp
# Or from source (for development)
cd mcp_server
python -m pip install -e ".[dev]"
Configure
Generate an API token at https://www.pdf-xtract.com/tokens and export it before running the server:
export PDF_EXTRACTOR_API_KEY=pxt_...
# Optional: point at a self-hosted deployment
# export PDF_EXTRACTOR_API_URL=https://pdf.example.com
Run
pdf-extractor-mcp
# or
python -m pdf_extractor_mcp
The server speaks MCP over stdio.
Claude Desktop / Claude Code config
Add this to claude_desktop_config.json (or your IDE's MCP settings). With
uvx the package is fetched and cached on first run, so users don't need a
prior pip install:
{
"mcpServers": {
"pdf-extractor": {
"command": "uvx",
"args": ["pdf-extractor-mcp"],
"env": {
"PDF_EXTRACTOR_API_KEY": "pxt_..."
}
}
}
}
If you installed via pipx, replace "command": "uvx", "args": [...] with
"command": "pdf-extractor-mcp".
Element categories
Caption, Footnote, Expression, Entry, Footer, Header, Image,
SectionTitle, Table, Text, Title. Defaults to ["Image"].
Example prompts
- "Extract all tables from
~/Downloads/report.pdfas PNG and summarize the first one." - "Pull every figure caption from pages 5-12 of
https://arxiv.org/pdf/2401.12345.pdf." - "List my extractions from the last week."
Testing the server
Three ways to exercise the server without a full IDE round-trip:
-
MCP Inspector (interactive UI):
npx @modelcontextprotocol/inspector pdf-extractor-mcp
Lists every tool, lets you fill in arguments, and shows the live response.
-
stdio smoke test — confirms the binary starts and registers tools:
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \ | pdf-extractor-mcp
-
Unit tests (no network, no API key required):
cd mcp_server pip install -e ".[dev]" pytest -m "not integration"
An opt-in integration test exercises the live API; set a real key and run:
PDF_EXTRACTOR_API_KEY=pxt_... pytest -m integration
Releasing
The MCP server is published to PyPI as pdf-extractor-mcp from the
.github/workflows/mcp-server-release.yml workflow. To cut a release:
- Bump
versioninmcp_server/pyproject.toml. - Tag the commit:
git tag mcp-v0.1.0 && git push origin mcp-v0.1.0. - The workflow builds the sdist + wheel and publishes via PyPI Trusted Publishing (OIDC — no API token stored).
One-time PyPI setup (Trusted Publishing)
Before the first release, register a pending publisher on PyPI so it
will accept the OIDC token. Without this the publish step fails with
invalid-publisher: valid token, but no corresponding publisher.
-
Under "Add a new pending publisher", enter these values exactly (they must match the token claims the workflow produces):
Field Value PyPI Project Name pdf-extractor-mcpOwner BorisBeskyRepository name pdf-extractorWorkflow name mcp-server-release.ymlEnvironment name pypi -
Make sure a GitHub environment named
pypiexists (repo Settings → Environments). The release job declaresenvironment: pypi; the name is case-sensitive and must match the PyPI entry above. -
Re-run the release (re-push the tag, or trigger the workflow manually via "Run workflow").
Once the first publish succeeds, PyPI converts the pending publisher into a
normal trusted publisher automatically — no further setup for later mcp-v*
tags.
Notes
- Pass
store_file=true(the default) for large PDFs - the API returns presigned URLs instead of base64 blobs. Usedownload_fileto fetch them. - When
store_file=false, the server truncatesFileDatain its response summary and addsFileDataLength; the raw base64 stays available by calling the API directly if needed. - OCR (
ocr_mode=element|page) requires Starter or Business tier. - Batch extraction requires Business tier.
Project details
Release history Release notifications | RSS feed
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 pdf_extractor_mcp-0.1.1.tar.gz.
File metadata
- Download URL: pdf_extractor_mcp-0.1.1.tar.gz
- Upload date:
- Size: 19.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cb9813a37c5ec1264556a3338b6fd8f982aebf361efd2f364fa25de6cf47cfe9
|
|
| MD5 |
dc8b3fdb6fec43dae07d3263b0d3027e
|
|
| BLAKE2b-256 |
843adb731b7a7fdd372db0efa355813426b66603977e03a9df758b6307b7b37c
|
Provenance
The following attestation bundles were made for pdf_extractor_mcp-0.1.1.tar.gz:
Publisher:
mcp-server-release.yml on BorisBesky/pdf-extractor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pdf_extractor_mcp-0.1.1.tar.gz -
Subject digest:
cb9813a37c5ec1264556a3338b6fd8f982aebf361efd2f364fa25de6cf47cfe9 - Sigstore transparency entry: 1631024570
- Sigstore integration time:
-
Permalink:
BorisBesky/pdf-extractor@7271bf02a7f42ad266523fe1d1de1bbd772d0da1 -
Branch / Tag:
refs/tags/mcp-v0.1.1 - Owner: https://github.com/BorisBesky
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
mcp-server-release.yml@7271bf02a7f42ad266523fe1d1de1bbd772d0da1 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pdf_extractor_mcp-0.1.1-py3-none-any.whl.
File metadata
- Download URL: pdf_extractor_mcp-0.1.1-py3-none-any.whl
- Upload date:
- Size: 13.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9df5e51b50fea8e1d7d89ee97e038b779b940c5c4f8f73086c0432ea0d23fce3
|
|
| MD5 |
9970ee249ac9032a2714a3fb2a7b84c1
|
|
| BLAKE2b-256 |
181d58c9833e594c06f53cae7d065609ced2c5cc03ecf13b9fcaeece2eaa2ff7
|
Provenance
The following attestation bundles were made for pdf_extractor_mcp-0.1.1-py3-none-any.whl:
Publisher:
mcp-server-release.yml on BorisBesky/pdf-extractor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pdf_extractor_mcp-0.1.1-py3-none-any.whl -
Subject digest:
9df5e51b50fea8e1d7d89ee97e038b779b940c5c4f8f73086c0432ea0d23fce3 - Sigstore transparency entry: 1631024624
- Sigstore integration time:
-
Permalink:
BorisBesky/pdf-extractor@7271bf02a7f42ad266523fe1d1de1bbd772d0da1 -
Branch / Tag:
refs/tags/mcp-v0.1.1 - Owner: https://github.com/BorisBesky
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
mcp-server-release.yml@7271bf02a7f42ad266523fe1d1de1bbd772d0da1 -
Trigger Event:
push
-
Statement type: