Skip to main content
Glama
shuji-bonji

pdf-verify-mcp

by shuji-bonji

Verify PDF Digital Signatures (cryptographic)

verify_signatures
Read-onlyIdempotent

Verifies digital signatures in a PDF: recomputes digests, checks CMS signature and timestamp, evaluates certificate chain, and checks revocation to detect tampering and confirm signer identity.

Instructions

Cryptographically verify the digital signatures in a PDF document.

For each signature this tool: recomputes the ByteRange digest and compares it with the CMS messageDigest attribute, verifies the CMS/PKCS#7 signature value against the signer certificate, verifies any RFC 3161 signature timestamp, evaluates the certificate chain against trust anchors, and checks revocation status.

Args:

  • file_path (string): Absolute path to a local PDF file

  • response_format ('markdown' | 'json'): Output format (default: 'markdown')

  • trust_anchors (string[], optional): Paths to trust anchor certificates (PEM/DER). Also reads the PDF_VERIFY_TRUST_ANCHORS env var (directory).

  • check_revocation ('none' | 'embedded' | 'online'): Revocation mode (default: 'embedded'; 'online' queries OCSP/CRL endpoints over HTTP)

  • revocation_freshness (integer seconds, default 86400): How long before the validation time a CRL / OCSP response may have been issued and still count as "good"

  • trusted_ocsp_responders (string[], optional): Certificates of locally trusted OCSP responders (RFC 6960 §4.2.2.2)

  • password (string, optional): Password for an encrypted PDF (permission-encrypted PDFs are decrypted automatically with the empty user password)

Returns: An object of the form { scope, signatures: [...] }. The top level changed from an array to an object in v0.21.0 - read .signatures for the list.

Size (v0.29.0): a JSON response is never cut by length. At most 32 signature fields are verified (file order); when the file has more, signaturesTruncated = { returned, total } is set and the remaining fields are NOT verified — evaluate_policy verifies every field. A markdown response is cut at 50,000 characters with a visible marker.

Every report begins with a "scope" object - how far the reading got, not a verdict: whether the cross-reference chain could be walked to the end (chainStop), whether this tool had to rebuild the cross-reference table itself (reconstructed - when true, the table is this tool's reconstruction and not the one the file carries), how many objects and sections were read, and whether an encrypted document could be opened. Read it before the verdict: "no violations" over a rebuilt table is not the same statement as "no violations" over the file's own table. For this tool it matters most: when scope.reconstructed is true, a signature the rebuild did not reach is absent from the list, so a short or empty list is not proof that the file carries no other signatures.

Per-signature verdict ('valid' / 'invalid' / 'indeterminate'), trust status ('trusted' / 'untrusted' / 'not_evaluated' with certificate path), revocation status ('good' / 'revoked' / 'revoked_after_validation_time' / 'unknown' / 'not_checked'; 'not_checked' when check_revocation is 'none') with source, origin ('dss' / 'cms_signed_data' / 'cms_revocation_info_archival'), revocationTime, thisUpdate and nextUpdate, per-intermediate-CA results in trust.chainRevocation, validationTime ({ time, source: 'signature_timestamp' | 'document_timestamp' | 'current_time' }), and signature timestamp verification.

Validation time: a verified timestamp (the signature's own, else the earliest document timestamp covering it) or, without one, the current time. The CMS signingTime attribute is written by the signer and is never used. A revoked signer certificate makes the verdict 'indeterminate' unless a timestamp proves the signature predates the revocation (then the status is 'revoked_after_validation_time' and the verdict is unchanged). CRLs and OCSP responses whose signatures cannot be verified, that expired before the validation time, or that were issued more than revocation_freshness seconds before it give 'unknown'.

Note: without trust_anchors (or the env var), trust is reported as not_evaluated — a 'valid' verdict then means cryptographic integrity, not signer identity assurance.

Complements pdf-reader-mcp's inspect_signatures, which inspects structure only.

Examples:

  • Verify a signed contract has not been altered since signing

  • Validate a signature against your organization's CA (trust_anchors)

  • Check whether the signer certificate has been revoked (check_revocation: "online")

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
passwordNoPassword for an encrypted PDF. Omit for permission-encrypted PDFs (an empty user password is tried automatically).
file_pathYesAbsolute path to a local PDF file (e.g., "/path/to/document.pdf")
trust_anchorsNoAbsolute paths to trust anchor certificates (PEM or DER). Merged with the PDF_VERIFY_TRUST_ANCHORS environment variable (a directory of *.pem/*.crt/*.cer/*.der files). When omitted and the env var is unset, trust is reported as not_evaluated.
response_formatNoOutput format: "markdown" for human-readable, "json" for structured datamarkdown
check_revocationNoRevocation checking: "none", "embedded" (OCSP/CRL data inside the PDF/CMS, default), or "online" (additionally query OCSP responders and CRL distribution points over HTTP).embedded
revocation_freshnessNoSeconds before the validation time that a CRL / OCSP response may have been issued (thisUpdate) and still support "good". Default 86400 (24 h); 0 accepts only data issued at or after the validation time. Older data gives "unknown".
trusted_ocsp_respondersNoAbsolute paths to certificates (PEM or DER) of locally trusted OCSP responders (RFC 6960 §4.2.2.2). A response signed by one of them is accepted even when the responder is not the issuing CA or its delegate.

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.29.1

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes far beyond the annotations by disclosing exact verification behavior: digest recomputation, CMS verification, timestamp validation, trust-chain evaluation, revocation modes, scope.reconstructed semantics, response truncation, and validation-time rules. It also clarifies that without trust_anchors, trust is not_evaluated. No annotation contradiction exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured: purpose, Args, Returns, behavioral caveats, alternatives, examples. The front-loaded core sentence and clear headings help an agent locate relevant sections quickly. Some redundancy exists between Args and the input schema descriptions, but the overall organization earns its length for a complex verification tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description explains the return shape in detail, including scope semantics, per-signature status fields, truncation behavior, validation-time selection, and trust-anchor implications. It also covers important edge cases like rebuilt cross-reference tables and revoked certificates. This is complete enough for an agent to call the tool correctly and interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description largely restates the schema's parameter descriptions rather than adding substantially new semantics. Some context is added (e.g., trust env var behavior, RFC 6960 reference), but most parameter-meaning is already present in the input schema, so the description does not meaningfully compensate beyond the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource: 'Cryptographically verify the digital signatures in a PDF document.' The title reinforces the scope, and the description distinguishes it from structural inspection by naming inspect_signatures, which 'inspects structure only.' The purpose is unambiguous and differentiates the tool's role from the listed siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear usage context through the cryptographic verification steps, the note that inspect_signatures is structural only, and three concrete example use cases (integrity check, trust anchor validation, revocation checking). It does not explicitly enumerate exclusions for every sibling tool, so it stops short of a 5, but the guidance is strong.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.