github Python analyzed 01f72c4

jztan/pdf-mcp

v3.3.0
github

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.

maintainer
jztan
licence
MIT
first seen
2026-06-01
last seen
2026-09-19
releases · 30d
9
short id

Drift inferred · capture-to-capture

tool count over time

06-01 18:08 now
8t
9t
capabilities 1 tools
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
skills & danger signals github-tarball
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

code evidence v3.3.0 · github-tarball
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