Reported issues for pdf-mcp
Pod holds 12 of 12 problems reported by people outside the maintainer team. Issues filed by the project's own owners, members and collaborators are excluded entirely — a maintainer's release checklist is not a warning to a prospective user.
Back to pdf-mcp.
Most discussed
add support for reading simple charts with PlotDigitizer
https://apps.automeris.io/wpd4/ something like this automatically?
if this is possible, I will package it into nixpkags (making it available for all NixOS).
Read the thread · 2026-07-13 · closed · external user · 10 comments
ocr_lang is not part of the page-text cache key: first OCR language wins permanently
Summary
ocr_lang is not part of the page-text cache key, so the first language used to OCR a page wins permanently. Any later pdf_read_pages(..., ocr=True, ocr_lang=<other>) on that page silently returns the previous language's text — instantly, labeled source: "ocr", with no error or warning.
This is easy to misdiagnose as "the Tesseract language pack isn't installed" or "language X doesn't work", because the failure is indistinguishable from a bad OCR result.
Reproduction
Read the thread · 2026-08-03 · closed · external user · 6 comments
ocr_lang cache key is not normalized: case and spelling variants create distinct rows
Follow-up to #25, from @deepdmk's verification of the 2.1.0 fix (comment).
ocr_lang goes verbatim from the tool argument into both the page_text.ocr_lang column and Tesseract's -l flag. Nothing lowercases, strips, or otherwise normalizes it in server.py or extractor.py, and _is_ocr_cache_hit compares it with exact string equality. Different spellings of one language set are therefore different cache keys.
Measure
Read the thread · 2026-08-10 · closed · 3 comments
Keyword search ranking depends on unrelated cached PDFs (FTS5 bm25 uses table-wide IDF)
Summary
Keyword-mode pdf_search ranks the pages of a single PDF, but the BM25 score
is computed over the entire shared FTS table. So a PDF's page ranking
depends on every other document the user happens to have cached — the same
query on the same PDF can return a different page order depending on unrelated
cached PDFs. Intra-document ranking should arguably be stable regardless of
what else is cached.
Where
PDFCache.search_fts (src/pdf_mcp/cache.py):
SELECT ..., -bm2
[Read the thread](https://github.com/jztan/pdf-mcp/issues/17) · 2026-06-24 · closed · 2 comments
### URL download fails TLS verification on relative HTTP redirects (IP-pinning drops hostname)
## Summary
`URLFetcher.fetch()` fails with a TLS certificate error when a download
follows a **relative** HTTP redirect. The IP-pinning hardening rewrites each
request to the resolved IP literal, but on a relative `Location` redirect the
hostname is lost, so the next hop verifies the server certificate against the
IP address instead of the hostname.
This breaks cold-cache downloads of any URL that issues a relative redirect
(arXiv does this today). It is masked everywhere by the download cache
[Read the thread](https://github.com/jztan/pdf-mcp/issues/16) · 2026-06-24 · closed · 1 comment
### Use per-user cache directory for URL downloads
## Summary
`URLFetcher` defaults downloaded PDF cache files to `tempfile.gettempdir() / "pdf-mcp" / "downloads"`, which is usually `/tmp/pdf-mcp/downloads` on Linux/macOS. Because the directory is created with private permissions (`chmod 0o700`), the first local user to start pdf-mcp can make the shared `/tmp/pdf-mcp` path inaccessible to other local users.
This can cause startup or runtime failures on shared machines, CI runners, or multi-user development boxes.
## Current Behavior
In `src/
[Read the thread](https://github.com/jztan/pdf-mcp/issues/15) · 2026-06-24 · closed · external user · 1 comment
### Suppress PyMuPDF swigvarlink DeprecationWarning
## Problem
PyMuPDF's SWIG bindings emit a `DeprecationWarning` on import and cleanup:
This is a known upstream PyMuPDF/SWIG issue. The warning leaks through to any tool that uses `pdf-mcp` as an MCP server, creating noisy output for end users.
## Suggested Fix
Add a targeted warning filter before `pymupdf` is imported:
```python
import warnings
warnings.filterwarnings("ignore", category=DeprecationWar
[Read the thread](https://github.com/jztan/pdf-mcp/issues/6) · 2026-03-14 · closed · 1 comment
### PDF validation can be bypassed when URL ends with .pdf
## Description
In `src/pdf_mcp/url_fetcher.py`, the PDF validation logic skips the magic-bytes (`%PDF`) check if the original URL ends with `.pdf`, even if the response `Content-Type` is non-PDF (e.g. `text/html`). This means a `.pdf` URL returning HTML content would be cached and processed as if it were a valid PDF.
## Suggested Fix
- Base the extension check on the final URL after redirects (`current_url`/`response.url`) rather than the original URL
- Always enforce the `%PDF` magic-bytes c
[Read the thread](https://github.com/jztan/pdf-mcp/issues/3) · 2026-02-24 · closed · 1 comment
## Most recent
### pdf_extract_chart splits dashed curves when dash lengths are below 1
## Summary
`pdf_extract_chart` can split a single dashed curve into several phantom
series when the chart uses dash lengths below 1.
## Cause
`_dash_key()` in `src/pdf_mcp/chart_extractor.py` parses the dash pattern with:
```python
re.findall(r"-?\d+(?:\.\d+)?", str(raw))
That requires a digit before the decimal point. PyMuPDF writes dash lengths below 1 without a leading zero, so real output looks like:
[ 1.0834783 .4685312 ] 0
The pattern cannot match .4685312 as a whole,
Read the thread · 2026-08-22 · closed · 0 comments
Hung OCR worker still hangs: in-parent timeout fallback has no timeout
Summary
run_pages() in parallel.py (reworked in #18) adds as_completed(timeout=)
to stop a hung worker from blocking forever. But the timeout only bounds the
wait on the pool — the fallback then re-runs each incomplete page in the
parent process with no timeout, so a page that genuinely hangs inside
Tesseract's native binding still produces an unbounded hang.
This is not a regression — pre-#18 pool.map() also hung forever on a stuck
worker. It's that the #18 fix doesn't fu
Read the thread · 2026-07-06 · closed · 0 comments
URL fetcher rejects valid password-protected PDFs as "truncated"
Summary
URLFetcher._validate_pdf_content() (added in #18) false-rejects valid
password-protected PDFs, failing with a misleading "zero pages — likely a
truncated file" error. Pre-#18 these PDFs were accepted (magic-byte check
only), so this is a regression introduced by the PDF-validation change.
Impact is narrow — only URL-fetched, encrypted PDFs — which is why it was split out of #18 rather than blocking it.
Root cause
_validate_pdf_content() checks page count before the encrypti
Read the thread · 2026-07-06 · closed · 0 comments
Your MCP server is graded 🟢 SAFE on Agent Skills Hub
Hi! I run Agent Skills Hub, an open directory that security-grades & quality-scores MCP servers and agent skills. {repo} came through 🟢 SAFE — nice work. If useful, you can show the grade in your README:
It renders a 🟢 SAFE badge linking to your skill's page (grade + quality breakdown). No strings — just a trust signal fo
Read the thread · 2026-06-23 · closed · external user · 0 comments
The remaining reports are on the project's issue tracker.