An MCP server that gives your AI agent agentic RAG over your PDFs, one file or a whole folder: hybrid semantic + keyword search, selective page reads, tables, images, OCR, chart data, and multi-column/CJK layouts. The agent decides when to search; pdf-mcp does the retrieval.
Drift inferred · capture-to-capture
tool count over time
06-01 18:08 now
8t
9t
transport stdio · streamable-http · http
verified
reported
listed in the official MCP registry counts 1 tools · 0 res
· 0 prompts
permission surface via code analysis
tools
-
pdf_cache_clear
prompt-surface
shipped agent-instruction files + hidden-content / dangerous-code findings —
quoted from the analyzed source
analyzed commit 01f72c4 · analyzer v33 · 25m ago
danger signals2
- dynamic code execution pickle.loads() jztan-pdf-mcp-01f72c4/tests/test_corpus.py :1590
clone = pickle.loads(pickle.dumps(_warm_extract_worker)) - suspicious endpoint 169.254.169.254 (cloud metadata) jztan-pdf-mcp-01f72c4/tests/test_url_fetcher.py :634
redirect_url = "https://169.254.169.254/latest/meta-data/"
evidence-backed
findings quoted directly from the published source artifact — not inferred
code files: 234
filesystem 168
- fs jztan-pdf-mcp-01f72c4/benchmark_data/chart_extraction/bench_discovery.py :70
doc = fitz.open(p) - fs jztan-pdf-mcp-01f72c4/benchmark_data/chart_extraction/bench_real.py :42
with open(pdf, "wb") as f: - fs jztan-pdf-mcp-01f72c4/benchmark_data/chart_extraction/bench_synthetic.py :29
GT = json.load(open(os.path.join(CORPUS, "ground_truth.json"))) - fs jztan-pdf-mcp-01f72c4/benchmark_data/chart_extraction/gen_synthetic.py :339
doc = pymupdf.open(os.path.join(OUT, "line_neg_linear.pdf")) - fs jztan-pdf-mcp-01f72c4/benchmark_data/content_trust_corpus/generate.py :47
d = pymupdf.open() - fs (weak) jztan-pdf-mcp-01f72c4/benchmark_data/cuda_embedding/scripts/libs.py :18
for line in open("/proc/self/maps"): - fs (weak) jztan-pdf-mcp-01f72c4/benchmark_data/cuda_embedding/scripts/measure.py :46
open(out, "w").write(json.dumps(res)) - fs jztan-pdf-mcp-01f72c4/infra/bedrock_kb/app.py :6
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/_bedrock_kb.py :15
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/archive/benchmark_boilerplate.py :50
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/archive/benchmark_coreml_provider.py :30
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/archive/benchmark_drilldown.py :23
from pathlib import Path
show 28 more
- fs (weak) jztan-pdf-mcp-01f72c4/scripts/archive/benchmark_e5_prefix.py :33
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/archive/benchmark_hybrid_sections.py :28
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/archive/benchmark_large_models.py :31
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/archive/benchmark_minilm_mlx.py :28
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/archive/benchmark_mlx_backend.py :37
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/archive/benchmark_pooling_attribution.py :26
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/archive/benchmark_search_impact.py :43
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/archive/spike_rerank.py :34
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/archive/test_benchmark_drilldown.py :4
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/archive/test_benchmark_hybrid_sections.py :2
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/archive/test_benchmark_large_models.py :4
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/archive/test_benchmark_mlx_backend.py :5
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/author_corpus_queries.py :59
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/author_trap_passages.py :29
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/bedrock_kb_stack.py :29
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_bedrock_kb.py :40
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_bge_small_cosine_parity.py :45
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_bge_small_throughput.py :53
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_cache_write.py :31
import shutil - fs (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_cjk_keyword.py :31
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_content_trust.py :39
doc = pymupdf.open(os.path.join(d, name)) - fs (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_corpus_modes.py :33
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_corpus_search.py :30
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_embedding_models.py :29
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_excerpt_quality.py :33
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_excerpt_style_arm.py :11
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_german_fts.py :53
from pathlib import Path - fs (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_multicol_parity.py :38
from pathlib import Path
128 more not shown — this panel samples each group; the count above is the real total.
shell / exec 22
- shell (weak) jztan-pdf-mcp-01f72c4/scripts/_mcp_client.py :13
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/scripts/author_corpus_queries.py :56
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/scripts/bedrock_kb_stack.py :26
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_semantic_excerpts.py :52
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/scripts/build_mcpb.py :20
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/scripts/eval_c2_query_teaching.py :31
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/scripts/eval_coherence.py :16
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/scripts/eval_financial_answerability.py :42
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/scripts/eval_multiturn_fanout.py :32
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/scripts/eval_render_legibility.py :23
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/scripts/eval_spread_fanout_behavior.py :34
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/scripts/probe_ocr_lang_variance.py :43
import subprocess
show 10 more
- shell (weak) jztan-pdf-mcp-01f72c4/scripts/release.py :40
import subprocess - shell jztan-pdf-mcp-01f72c4/src/pdf_mcp/extractor.py :168
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/tests/test_build_mcpb.py :6
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/tests/test_demo_fusion_parity.py :8
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/tests/test_launcher_node.py :4
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/tests/test_parallel.py :3
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/tests/test_pdf_reader.py :1620
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/tests/test_release.py :8
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/tests/test_tesseract_resolver.py :3
import subprocess - shell (weak) jztan-pdf-mcp-01f72c4/tests/test_warm_batching.py :8
import subprocess
network 26
- net jztan-pdf-mcp-01f72c4/benchmark_data/chart_extraction/bench_real.py :17
import os, time, sys, urllib.request - net (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_bedrock_kb.py :41
from urllib.parse import urlparse - net (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_bge_small_cosine_parity.py :75
import httpx - net (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_bge_small_throughput.py :85
import httpx - net (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_ocr_corpus.py :36
import urllib.request - net (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_parallel_pages.py :55
import urllib.request - net (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_reading_order.py :40
import urllib.request - net (weak) jztan-pdf-mcp-01f72c4/scripts/fetch_corpus_distractors.py :27
import httpx - net (weak) jztan-pdf-mcp-01f72c4/scripts/fetch_financial_corpus.py :26
from urllib.parse import urlparse - net (weak) jztan-pdf-mcp-01f72c4/scripts/release.py :1388
import urllib.request - net (weak) jztan-pdf-mcp-01f72c4/scripts/update_tesseract_pins.py :13
import urllib.request - net (weak) jztan-pdf-mcp-01f72c4/scripts/update_uv_pins.py :12
import urllib.request
show 14 more
- net jztan-pdf-mcp-01f72c4/src/pdf_mcp/config.py :15
from urllib.parse import urlsplit - net jztan-pdf-mcp-01f72c4/src/pdf_mcp/portable_tesseract.py :23
import urllib.request - net jztan-pdf-mcp-01f72c4/src/pdf_mcp/remote_embedder.py :25
pool (``httpx.Client`` is thread-safe; `_get_model` in embedder.py is - net jztan-pdf-mcp-01f72c4/src/pdf_mcp/remote_embedding_check.py :74
# httpx. - net jztan-pdf-mcp-01f72c4/src/pdf_mcp/server.py :24
import httpx - net jztan-pdf-mcp-01f72c4/src/pdf_mcp/updates.py :87
import httpx - net jztan-pdf-mcp-01f72c4/src/pdf_mcp/url_fetcher.py :10
import socket - net (weak) jztan-pdf-mcp-01f72c4/tests/test_benchmark_bge_small_cosine_parity.py :17
import httpx - net (weak) jztan-pdf-mcp-01f72c4/tests/test_benchmark_bge_small_throughput.py :17
import httpx - net (weak) jztan-pdf-mcp-01f72c4/tests/test_remote_embedder.py :3
All tests mock httpx.Client -- no network call, no live server. This repo - net (weak) jztan-pdf-mcp-01f72c4/tests/test_server.py :16
import httpx - net (weak) jztan-pdf-mcp-01f72c4/tests/test_url_fetcher.py :4
import socket - net (weak) jztan-pdf-mcp-01f72c4/tests/test_url_fetcher_security.py :3
import socket - net (weak) jztan-pdf-mcp-01f72c4/tests/test_uv_pins.py :6
import urllib.error
secrets 1
- secrets jztan-pdf-mcp-01f72c4/src/pdf_mcp/server.py :6342
token = os.environ.get("PDF_MCP_AUTH_TOKEN", "").strip()
database 22
- db (weak) jztan-pdf-mcp-01f72c4/scripts/archive/benchmark_hybrid_sections.py :34
import sqlite3 # noqa: E402 - db (weak) jztan-pdf-mcp-01f72c4/scripts/bench_env.py :19
import sqlite3 - db (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_cache_write.py :32
import sqlite3 - db (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_corpus_search.py :27
import sqlite3 - db (weak) jztan-pdf-mcp-01f72c4/scripts/benchmark_platform_smoke.py :296
import sqlite3 as _sq - db (weak) jztan-pdf-mcp-01f72c4/scripts/measure_page_text_migration.py :22
import sqlite3 - db (weak) jztan-pdf-mcp-01f72c4/scripts/recheck_tiebreak_permutation.py :41
import sqlite3 - db jztan-pdf-mcp-01f72c4/src/pdf_mcp/cache.py :11
import sqlite3 - db jztan-pdf-mcp-01f72c4/src/pdf_mcp/server.py :19
import sqlite3 - db (weak) jztan-pdf-mcp-01f72c4/tests/conftest.py :48
import sqlite3 as _sqlite3 - db (weak) jztan-pdf-mcp-01f72c4/tests/test_bench_env.py :11
import sqlite3 - db (weak) jztan-pdf-mcp-01f72c4/tests/test_benchmark_bedrock_kb.py :289
import sqlite3
show 10 more
- db (weak) jztan-pdf-mcp-01f72c4/tests/test_benchmark_corpus_search.py :4
import sqlite3 - db (weak) jztan-pdf-mcp-01f72c4/tests/test_cache.py :5
import sqlite3 - db (weak) jztan-pdf-mcp-01f72c4/tests/test_cache_pragmas.py :16
import sqlite3 - db (weak) jztan-pdf-mcp-01f72c4/tests/test_corpus.py :5
import sqlite3 - db (weak) jztan-pdf-mcp-01f72c4/tests/test_doc_profiles.py :77
import sqlite3 - db (weak) jztan-pdf-mcp-01f72c4/tests/test_password_locked.py :4
import sqlite3 - db (weak) jztan-pdf-mcp-01f72c4/tests/test_pdf_reader.py :6
import sqlite3 - db (weak) jztan-pdf-mcp-01f72c4/tests/test_server.py :4791
import sqlite3 - db (weak) jztan-pdf-mcp-01f72c4/tests/test_server_info.py :324
import sqlite3 - db (weak) jztan-pdf-mcp-01f72c4/tests/test_table_cache_version.py :23
import sqlite3
tool registrations 1
- pdf_cache_clear jztan-pdf-mcp-01f72c4/src/pdf_mcp/server.py :5245
declared dependencies 26
- fastmcp@>=3.0.0
- mcp@>=1.28.1,<2.0
- pydantic@>=2.0
- packaging@>=23.0
- tomli@>=2.0; python_version <
- pytesseract@>=0.3.10
- pillow@>=12.3.0
- de@*
- snowballstemmer@>=2.2.0
- pymupdf@>=1.24.0
- pytest@>=8.0
- pytest-xdist@>=3.5
show 14 more
- pytest-asyncio@>=0.23.0
- pytest-cov@>=4.0
- mypy@>=1.8.0
- flake8@>=7.0
- black@>=26.3.1
- pip-audit@>=2.7.0
- pip@>=26.1.2
- msgpack@>=1.2.1
- pre-commit@>=3.5
- pyyaml@>=6.0
- boto3@>=1.40
- aws-cdk-lib@>=2.267,<3
- constructs@>=10.0,<11
- tesserocr@>=2.6