MCP server for PDF authenticity verification — cryptographic digital signature verification, tamper detection, PAdES baseline level detection, and PDF/A / PDF/UA declaration identification.
- ✓Open-source license (MIT)
- ✓Actively maintained (<30d)
- ✓Clear description
- ✓Topics declared
- ✓Documented (README)
git clone https://github.com/shuji-bonji/pdf-verify-mcp{
"mcpServers": {
"pdf-verify-mcp": {
"command": "node",
"args": ["/path/to/pdf-verify-mcp/dist/index.js"]
}
}
}Resumen de MCP Servers
# pdf-verify-mcp
[](https://github.com/shuji-bonji/pdf-verify-mcp/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/@shuji-bonji/pdf-verify-mcp)
[](./LICENSE)
[日本語](./README.ja.md)
MCP server for PDF **authenticity and conformance verification** — cryptographic digital signature verification, tamper detection, PAdES baseline level detection, and PDF/A (ISO 19005) / PDF/UA (ISO 14289) validation.
Part of the PDF family alongside [pdf-reader-mcp](https://github.com/shuji-bonji/pdf-reader-mcp) (structure analysis) and [pdf-spec-mcp](https://github.com/shuji-bonji/pdf-spec-mcp) (specification reference). Where `pdf-reader-mcp` tells you *what is in* a PDF, `pdf-verify-mcp` tells you *whether it is genuine*.
## Tools
| Tool | Purpose |
|------|---------|
| `verify_signatures` | Cryptographic verification, trust chain evaluation against trust anchors, revocation checking (embedded OCSP/CRL or online), RFC 3161 timestamp verification |
| `verify_integrity` | Tamper detection: incremental updates, changes after signing, **DocMDP certification violations assessed per P value** (below), and an object-level diff of the revision chain (which objects each update added, rewrote or freed). Incremental updates are legal, so the diff says what to review — no verdict rests on it. Where those objects sit on the page is [pdf-reader-mcp](https://github.com/shuji-bonji/pdf-reader-mcp) `locate_objects` |
| `detect_pades_level` | PAdES baseline level (B-B / B-T / B-LT / B-LTA) with content-validated LTV data |
| `identify_conformance` | Declared PDF/A / PDF/UA conformance from XMP metadata |
| `validate_conformance` | PDF/A (ISO 19005) and PDF/UA (ISO 14289) validation: veraPDF when installed, built-in rule subset otherwise |
| `validate_clauses` | Constraints mapped from ISO 32000-1/-2 clauses — the specification body itself, which the PDF/A and PDF/UA profiles do not cover |
| `evaluate_policy` | Deterministic 4-value trust verdict (trust_and_use / use_with_caution / human_review_required / reject) from a fixed rule table over the verification facts, with domain profiles (contract, financial, legal, medical, government). The judge is code; the narrative is the LLM |
## Verdicts
| Verdict | Meaning |
|---------|---------|
| `valid` | ByteRange digest matches and the CMS signature is cryptographically valid |
| `invalid` | Digest mismatch or signature verification failure — possible tampering |
| `indeterminate` | Unsupported format or verification could not complete |
## DocMDP certification permissions (v0.14)
A certification signature's `P` value states **which kinds of change are allowed**
(ISO 32000-2 **Table 257**). `verify_integrity` classifies the changes made after signing at the
object level and compares them against what that `P` permits.
| P | Permitted changes | Is adding an annotation a violation? |
|---|---|---|
| 1 | none (DSS / document-timestamp incremental updates are the §12.8.2.2 exception) | **yes** |
| 2 | filling in forms, instantiating page templates, signing | **yes** — annotations start at 3 |
| 3 | as for 2, plus annotation creation, deletion and modification | no |
Objects that a permitted change **necessarily drags along** — the page whose `/Annots` grew, the
catalog, `/Info`, the XMP stream — are classified as `housekeeping` and are not counted as
violations. Counting them would make *every* certified document violate, since a lawful P=3
annotation addition moves all four.
### `violationAssessment` is three-valued
| Value | Meaning |
|---|---|
| `permitted` | every change after signing is of a kind `P` allows |
| `violated` | at least one change is outside it |
| `indeterminate` | **it could not be determined** (the xref chain could not be walked, or a changed object's kind could not be read) |
> ⚠️ **`indeterminate` is not a pass.** This server disproves, and "could not be disproved" is a
> different statement from "is fine" — the same discipline as `validate_clauses` returning
> `needs_external_fact` rather than defaulting a check into a pass.
>
> `violatedByLaterChanges` (boolean) is kept for compatibility and **collapses `indeterminate` to
> `false`**. Read `violationAssessment` wherever "could not tell" must not be mistaken for
> "fine". `evaluate_policy` raises `indeterminate` to `human_review_required` as well.
A bare stream with no `/Type` is treated as *not determined* rather than as `content`: the same
bytes could be a form field's appearance stream (which P=2 permits) or a page's content stream
(which no P permits).
## Response size (v0.29.0)
A JSON response is never cut by length. Lists are capped instead, and every cut is reported next to the list as `{ returned, total }`: `signatures` / `levels` at 32 (`verify_signatures` does not verify the fields beyond the cap; `evaluate_policy` verifies all and caps only `facts.signatures`), `revisions` at 32, `violations` / `results` at 200 (counts such as `compliant`, `failedRules`, `violations`, `notDecided` cover all entries). A markdown response is cut at 50,000 characters with a visible marker.
## Trust & revocation (v0.2)
Pass `trust_anchors` (PEM/DER file paths) or set the `PDF_VERIFY_TRUST_ANCHORS` env var (a directory of certificates) to evaluate the signer's chain: results are `trusted` / `untrusted` / `not_evaluated` with the certificate path. The validation time is a verified signature timestamp, else the earliest document timestamp covering the signature, else the current time (v0.27.0); the CMS `signingTime` attribute is written by the signer and is not used. The chosen time is reported as `validationTime`.
`check_revocation` controls revocation checking: `embedded` (default — OCSP/CRL data in the DSS, CMS `SignedData.crls`, or the CMS signed attribute `adbe-revocationInfoArchival`; reported as `revocation.origin`), `online` (additionally query OCSP responders and CRL distribution points over HTTP), or `none` (`revocation.status: not_checked`). CRLs and OCSP responses whose signatures cannot be verified, whose `nextUpdate` is before the validation time, or whose `thisUpdate` is more than `revocation_freshness` seconds (default 86400) before it give `unknown` (v0.28.0). Pass `trusted_ocsp_responders` to trust an OCSP responder issued by another CA. Each intermediate CA's result is reported in `trust.chainRevocation`. A revoked signer certificate gives `revoked_after_validation_time` (verdict unchanged) when a timestamp proves the signature predates the revocation; otherwise `revoked` with verdict `indeterminate`. In online mode, missing issuer certificates are fetched via AIA caIssuers to complete the chain (v0.4). When anchors are provided, TSA certificate chains of RFC 3161 timestamps are evaluated too (`tsaTrust`).
| Step | What is checked | Network |
| --- | --- | --- |
| Integrity | `/ByteRange` hash matches the CMS `messageDigest` | none |
| Signature value | Signature value verifies with the signer certificate's public key | none |
| Certificate chain | Chains up to a trust anchor | `online` only: issuer certificates fetched via AIA caIssuers |
| Revocation | OCSP / CRL for the signer certificate | none under `embedded`; under `online`, HTTP queries when embedded data gives no answer |
| Timestamp | RFC 3161 token and TSA signature | none |
`verdict: valid` means integrity and signature value passed (`revoked` turns it into `indeterminate`). `online` results reflect the CA's state at query time and can change later. See the [site guide](https://shuji-bonji.github.io/pdf-agent-stack/mcp/pdf-verify#what-signature-verification-checks) for each step and how to choose a mode.
> Without trust anchors, `trust` stays `not_evaluated` and a `valid` verdict asserts cryptographic integrity, not signer identity.
Encrypted PDFs are decrypted automatically when permission-encrypted (empty user password); pass `password` for reader-password PDFs. Supported: RC4 (R2–R4), AES-128, AES-256 (R6). Decryption recovers string metadata (field name, /M, /Reason, /Location) and XMP — a signature's `/Contents` is exempt from encryption, so verification never depends on it.
Supported SubFilters: `ETSI.CAdES.detached` (PAdES), `adbe.pkcs7.detached`, `ETSI.RFC3161` (document timestamps). RFC 3161 signature timestamps are fully verified (imprint + TSA signature). Legacy MD5/SHA-1 signatures are verified via node:crypto and flagged as weak.
## PDF/A validation (v0.3)
`validate_conformance` uses a hybrid engine. With veraPDF installed (`PDF_VERIFY_VERAPDF` env var or on PATH) validation is delegated for authoritative results. Otherwise a built-in subset of ~15 high-value ISO 19005 rules runs natively (encryption, trailer /ID, LZW, font embedding, JavaScript/prohibited actions, OutputIntent, transparency for A-1, XFA, and more), each reported with its clause reference.
Native results are honest about their limits: violations mean definitively non-compliant; all-passed means "no violations in the checked subset" — never certification.
PDF/A-4 (`pdfa-4`, `pdfa-4e`, `pdfa-4f`) is accepted. Note that **PDF/A-4 has no conformance level** — there is no `pdfa-4b`; `e` and `f` are variants. The native rules were written from ISO 19005-1/-2 and have not been checked against ISO 19005-4, so a PDF/A-4 report says outright that the native verdict ranks below veraPDF. Validate part 4 with veraPDF.
## ISO 32000 clause constraints (v0.9)
`validate_clauses` covers different ground: the **body of the PDF specification**, not the PDF/A or PDF/UA profiles. A file can be judged COMPLIANT by veraPDF and still violate ISO 32000 — embedding a CFF font program under `/FontFile2` (Table 124) is a real example that surfaced only as a viewer warning.
The mapping from clauses to structural conditions, and its evaluation, liLo que la gente pregunta sobre pdf-verify-mcp
¿Qué es shuji-bonji/pdf-verify-mcp?
+
shuji-bonji/pdf-verify-mcp es mcp servers para el ecosistema de Claude AI. MCP server for PDF authenticity verification — cryptographic digital signature verification, tamper detection, PAdES baseline level detection, and PDF/A / PDF/UA declaration identification. Tiene 0 estrellas en GitHub y su última actualización registrada es del 2026-09-19.
¿Cómo se instala pdf-verify-mcp?
+
Puedes instalar pdf-verify-mcp clonando el repositorio (https://github.com/shuji-bonji/pdf-verify-mcp) o siguiendo las instrucciones del README en GitHub. ClaudeWave también te ofrece bloques de instalación rápida en esta misma página.
¿Es seguro usar shuji-bonji/pdf-verify-mcp?
+
Nuestro agente de seguridad ha analizado shuji-bonji/pdf-verify-mcp y le ha asignado un Trust Score de 95/100 (tier: Verified). Revisa el desglose completo de comprobaciones superadas y flags en esta página.
¿Quién mantiene shuji-bonji/pdf-verify-mcp?
+
shuji-bonji/pdf-verify-mcp es mantenido por shuji-bonji. La última actividad registrada en GitHub es del 2026-09-19, con 0 issues abiertos.
¿Hay alternativas a pdf-verify-mcp?
+
Sí. En ClaudeWave puedes explorar mcp servers similares en /categories/mcp, ordenados por popularidad o actividad reciente.
Despliega pdf-verify-mcp en tu cloud
Lleva este repo a producción en minutos. Cada plataforma genera su propio entorno con variables de entorno editables.
¿Mantienes este repo? Añade un badge a tu README
Pega el badge en tu README de GitHub para mostrar que está auditado por ClaudeWave. Cada badge enlaza de vuelta a esta página y muestra el Trust Score actual.
[](https://claudewave.com/repo/shuji-bonji-pdf-verify-mcp)<a href="https://claudewave.com/repo/shuji-bonji-pdf-verify-mcp"><img src="https://claudewave.com/api/badge/shuji-bonji-pdf-verify-mcp" alt="Featured on ClaudeWave: shuji-bonji/pdf-verify-mcp" width="320" height="64" /></a>Más MCP Servers
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.
User-friendly AI Interface (Supports Ollama, OpenAI API, ...)
An open-source AI agent that brings the power of Gemini directly into your terminal.
Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface
🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl! Don't be shy, join here: https://discord.gg/EMgGbDceNQ
The fastest path to AI-powered full stack observability, even for lean teams.