Enterprise edition
MCP tools
At a glance
Section titled “At a glance”NextPDF Enterprise adds eleven MCP tools to the NextPDF Connect server. They give AI assistants and agent frameworks direct, typed access to the Enterprise engine: compliance policy checks, PDF forensics, LTV health checks, AI-readiness stamping, AST-aware chunking, and RAG ingestion and search. Every tool declares its own risk level and read-only posture, so your MCP host can gate, log, and audit agent activity with confidence. Failures never surface as exceptions; agents always receive a structured, parseable result.
Availability & licensing
Section titled “Availability & licensing”This capability ships in NextPDF Enterprise (nextpdf/enterprise) and activates with an Enterprise-tier license envelope. A deployment without that entitlement does not load the capability’s classes. Compare editions and get a license.
Install
Section titled “Install”composer require nextpdf/enterprise:^3The MCP host itself is NextPDF Connect, shipped in the nextpdf/server package; see Connect install. When both packages are present, the server’s tool registry discovers NextPDF\Enterprise\McpToolProvider automatically and registers the eleven Enterprise tools. No wiring code is required. If nextpdf/server is absent, the provider file returns early and nothing loads.
The batch and RAG tools additionally require the Spectrum sidecar. Configure it through environment variables read by NextPDF\Enterprise\Mcp\SpectrumClientFactory: SPECTRUM_URL (default http://127.0.0.1:7800), SPECTRUM_TIMEOUT (default 30.0 seconds), SPECTRUM_AUTH_TOKEN, and SPECTRUM_APP_SECRET.
Conceptual overview
Section titled “Conceptual overview”The Model Context Protocol (MCP) is an open protocol that lets AI assistants and agent frameworks call typed tools exposed by a server. Instead of pasting PDF bytes into a prompt and hoping, an agent calls a named tool with a JSON-schema-validated payload and receives a deterministic, structured result. NextPDF Connect is that server for PDFs; the Enterprise package extends its catalog with the tools below. Each tool is a thin wrapper over the same Enterprise APIs your PHP code calls directly, so an agent-run check and a code-run check produce the same verdict.
Tool catalog
Section titled “Tool catalog”| MCP tool | Class | What it does | Risk | Read-only |
|---|---|---|---|---|
compliance_check | ComplianceCheckTool | Validates one PDF against a named policy: pdfa4, pdfa4e, pdfa4f, pades-baseline, ltv-health, eidas-qualified, zugferd, fda-part11, and four sec-17a4 variants. | Review | yes |
batch_compliance_check | BatchComplianceCheckTool | Checks many PDFs against pdfa, pades, or zugferd policies in one Spectrum sidecar batch. | Safe | yes |
forensic_analyze | ForensicAnalyzeTool | Reports revision history, incremental updates, and modification events for tamper detection. | Safe | yes |
batch_forensic_analyze | BatchForensicAnalyzeTool | Runs forensic analysis over many PDFs in one sidecar batch. | Safe | yes |
ltv_health_check | LtvHealthCheckTool | Checks a signed PDF for long-term validation material: DSS dictionary, OCSP responses, CRL entries, VRI entries, and certificate stores. | Safe | yes |
ai_ready_certify | AiReadyCertifyTool | Read-only product-defined AI-readiness verdict over four criteria: forensic integrity, signature presence, LTV validity, no encryption. | Review | yes |
certify_ai_ready | CertifyAiReadyTool | Product-defined readiness verdict over three criteria (the read-only tool’s four minus forensic integrity - by design, since this tool rewrites the file it stamps) and appends an XMP provenance stamp; returns the stamped PDF as base64. | Review | no |
ast_aware_chunk | AstAwareChunkTool | Splits a PDF into citation-anchored chunks along heading boundaries, with node ID, page index, and bounding box per chunk. | Review | yes |
audit_ast_mutations | AuditAstMutationsTool | Retrieves the AST mutation audit trail for a document by SHA-256 source hash. | Review | yes |
embed_documents | EmbedDocumentsTool | Ingests PDFs into a RAG collection: parse, chunk, embed, index. Modifies collection state. | Caution | no |
search_documents | SearchDocumentsTool | Hybrid retrieval (BM25 keyword plus semantic) over an ingested collection, with ranked, scored chunks. | Safe | yes |
The “certify” tools issue a product-defined readiness verdict (certified, partial, or not_certified). That verdict is a technical check result, not a certification by any accreditation body.
Approval gating and audit posture
Section titled “Approval gating and audit posture”Every tool declares a risk level from the four-tier Connect model. Safe tools auto-execute. Caution tools auto-execute with an audit-log entry. Review tools carry a warning for the calling agent’s instructions. ApprovalRequired tools demand human confirmation; no Enterprise MCP tool currently declares this level, because none is destructive. Runtime configuration can only raise a tool’s risk level, never lower it. Tools also publish MCP behavior annotations (readOnlyHint, idempotentHint), so a conforming client can apply its own gating on top. See HITL risk tiers for the full model.
Why it works this way
Section titled “Why it works this way”The load-bearing decision is that tools are thin, deterministic wrappers with self-declared governance: each tool states its own risk level and tier as a domain invariant, never inferred from namespace or packaging. This keeps the gating decision auditable at the host without trusting the transport. Tools contain no document intelligence of their own; they delegate to the same Enterprise APIs your code calls, so there is exactly one behavior to test and one verdict to trust. Errors return on the MCP error channel instead of escaping as exceptions, because an agent cannot catch a PHP exception but can always branch on isError. Input that could touch the filesystem is fail-closed by default, since MCP arguments are attacker-reachable by definition.
Design background: An API that refuses to guess.
API surface
Section titled “API surface”All eleven tools implement the NextPDF\Server\Tools\ToolInterface contract from nextpdf/server and share the same public surface. Signatures below are shown once on NextPDF\Enterprise\Mcp\ComplianceCheckTool as the representative:
public function name(): stringpublic function description(): stringpublic function inputSchema(): arraypublic function annotations(): arraypublic function riskLevel(): RiskLevelpublic function tier(): ToolTierpublic function category(): stringpublic function execute(array $arguments, InMemoryDocumentStore $store): ToolResultThrows or fails with: execute() never throws. It catches Throwable internally and returns ToolResult::error() with isError = true. Invalid arguments (missing workspace_token, malformed documents entries, unknown document_id, unsafe source) surface as InvalidArgumentException messages on that error channel.
The audit-trail tool takes its storage backend by constructor injection:
public function __construct(private readonly AstAuditTrailInterface $auditTrail)The provider that registers the catalog:
public function getTier(): stringpublic function getTools(): arraygetTier() returns 'enterprise'. getTools() returns the eleven tool instances; audit_ast_mutations is wired with NextPDF\Enterprise\Ast\InMemoryAstAuditTrail by default.
The Spectrum sidecar client factory, which is also a PSR-17 request and stream factory:
public static function create(): SpectrumClientpublic static function reset(): voidpublic function createRequest(string $method, $uri): RequestInterfacepublic function createStream(string $content = ''): StreamInterfacepublic function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterfacepublic function createStreamFromResource($resource): StreamInterfaceThrows or fails with: create() throws InvalidArgumentException when SPECTRUM_URL is malformed or when the configured endpoint targets a known private or reserved address (except localhost). This is a configuration-time gate, not a network-layer control: still enforce egress policy, redirect handling, and DNS pinning in the host environment. createStreamFromFile() throws NextPDF\Enterprise\Mcp\McpStreamException (a RuntimeException subclass, per the PSR-17 contract) when the file cannot be opened.
Code sample — Quick start
Section titled “Code sample — Quick start”Run a PDF/A-4 compliance check exactly as an agent would, using the in-memory data: URI channel:
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Mcp\ComplianceCheckTool;use NextPDF\Enterprise\Mcp\McpStreamException;use NextPDF\Enterprise\Mcp\SpectrumClientFactory;use NextPDF\Server\Document\InMemoryDocumentStore;
$streams = new SpectrumClientFactory(); // PSR-17 stream factory from this module
try { $pdfBytes = (string) $streams->createStreamFromFile(__DIR__ . '/invoice.pdf');} catch (McpStreamException $e) { fwrite(STDERR, 'Cannot read PDF: ' . $e->getMessage() . PHP_EOL); exit(1);}
$tool = new ComplianceCheckTool();$result = $tool->execute( [ 'source' => 'data:application/pdf;base64,' . base64_encode($pdfBytes), 'policy' => 'pdfa4', ], new InMemoryDocumentStore(),);
// Tool failures arrive on the MCP error channel, never as exceptions.if ($result->isError) { fwrite(STDERR, $result->content[0]['text'] . PHP_EOL); exit(1);}
echo $result->content[0]['text'] . PHP_EOL;Expected output for a conformant file (finding counts vary per document):
Compliance check (PDF/A-4): PASS — 0 finding(s)The full machine-readable report, including per-finding severity, rule ID, clause, and suggestion, is available on $result->structured.
Code sample — Production
Section titled “Code sample — Production”Preflight the sidecar, enforce the declared risk posture, then run a batch compliance check:
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Mcp\BatchComplianceCheckTool;use NextPDF\Enterprise\Mcp\SpectrumClientFactory;use NextPDF\Server\Document\InMemoryDocumentStore;
// 1. Fail fast on sidecar misconfiguration before accepting agent traffic.// The factory validates SPECTRUM_URL and rejects private/reserved targets.try { SpectrumClientFactory::create();} catch (InvalidArgumentException $e) { fwrite(STDERR, 'Spectrum sidecar rejected: ' . $e->getMessage() . PHP_EOL); exit(1);}
$tool = new BatchComplianceCheckTool();$risk = $tool->riskLevel();
// 2. Enforce the declared risk posture before execution.if ($risk->requiresHumanConfirmation()) { // Route to your approval queue instead of executing. exit(0);}
if ($risk->requiresAuditLog()) { error_log(sprintf('[mcp-audit] tool=%s risk=%s', $tool->name(), $risk->label()));}
// 3. Execute the batch.$result = $tool->execute( [ 'workspace_token' => (string) getenv('SPECTRUM_WORKSPACE_TOKEN'), 'documents' => [ ['id' => 'contract-001', 'path' => '/var/pdf-inbox/contract-001.pdf'], ['id' => 'contract-002', 'path' => '/var/pdf-inbox/contract-002.pdf'], ], 'policies' => ['pdfa', 'pades'], ], new InMemoryDocumentStore(),);
echo $result->content[0]['text'] . PHP_EOL;Expected output (counts reflect your documents):
Batch compliance check complete: 1 compliant, 1 non-compliantEdge cases & gotchas
Section titled “Edge cases & gotchas”- Filesystem
sourcepaths are disabled by default. Without theNEXTPDF_MCP_INPUT_DIRenvironment variable, a path-shapedsourceis rejected with an error result. Usedocument_id, adata:URI, or raw base64 instead. - Raw base64 is recognized only above 256 characters. A shorter base64 blob is treated as a file path and rejected. Wrap small payloads in a
data:application/pdf;base64,URI. - Unknown
document_idvalues fail with guidance. The error text isUnknown document_id: ... Call create_pdf first.Documents in the in-memory store also expire on the store’s TTL, so a stale ID fails the same way. compliance_checkrejects unknown policy keys and lists the supported set in the error message.- Batch and RAG tools need the sidecar.
batch_compliance_check,batch_forensic_analyze,embed_documents, andsearch_documentsrequire a reachable Spectrum endpoint and aworkspace_token. The factory caches one client per process; callSpectrumClientFactory::reset()in tests. search_documentsclampstop_kto 1–100; non-integer values fall back to the server default of 10.ast_aware_chunkdefaults are 1500 characters per chunk with 150 characters of overlap.certify_ai_readyomits the stamped bytes whenreturn_stamped_pdfisfalseor the verdict isnot_certified. When present, the base64 payload is about one third larger than the PDF itself.- The default AST audit trail is in-memory. Entries recorded through the stock provider wiring do not persist across processes; inject a persistent
AstAuditTrailInterfaceimplementation for durable audit trails.
Security notes
Section titled “Security notes”- Fail-closed source resolution. MCP callers fully control tool arguments, so the resolver treats them as hostile. Stream wrappers (
phar://,php://,file://, and any scheme) and null bytes are rejected before any filesystem call. Path traversal is rejected. Raw file paths work only whenNEXTPDF_MCP_INPUT_DIRis set, and therealpath-canonicalized target must resolve strictly inside that directory, compared on a separator boundary to block prefix-confusion escapes. - SSRF guard on the sidecar endpoint.
SpectrumClientFactoryallows localhost for the local-sidecar mode and validates every otherSPECTRUM_URLagainst private, reserved, link-local, and cloud-metadata ranges, throwingInvalidArgumentExceptionon a blocked address. This is a configuration-time gate on the configured endpoint, not a network-layer control - keep egress policy, redirect handling, and DNS pinning in the host environment. - Secrets stay in the environment. The sidecar bearer token (
SPECTRUM_AUTH_TOKEN) and HMAC signing secret (SPECTRUM_APP_SECRET) are read from environment variables and never appear in tool payloads or results. - Non-reflective errors. Path-rejection messages are generic by design (
Source path is not permitted.), so a probing caller learns nothing about the host filesystem. - Risk overrides only go up. Operator configuration can raise a tool’s declared risk level but can never lower it below the tool’s own declaration.
Conformance
Section titled “Conformance”The compliance tools check document structure against the named policy profiles and report findings with clause references; the compliance_check report additionally carries the engine’s own disclaimer that it is a technical structure check for reference, not legal advice or a compliance endorsement. The ai_ready_certify and certify_ai_ready verdicts are product-defined readiness levels. MCP is an open protocol published by its vendor steward.
Behavior contract
Section titled “Behavior contract”- Tool failures are returned as error results (
isError = truewith a message); exceptions never cross the MCP boundary. - Successful results carry a one-line human-readable summary plus a structured JSON payload with a stable, documented field set per tool.
- Every tool reports
tier() = ToolTier::Enterpriseand a declaredRiskLevel; risk cannot be lowered at runtime. - Read-only tools declare
readOnlyHint: trueand do not modify the document store, the source PDF, or any collection. certify_ai_readynever alters the input document in place; the stamp is applied to a returned copy.- Compliance and LTV reports include a validation timestamp and finding counts by severity; the
compliance_checkpayload additionally includes the engine’s legal disclaimer string.
Core fallback
Section titled “Core fallback”The MCP host itself does not require Enterprise. NextPDF Connect (nextpdf/server, Apache-2.0) runs with the open Core engine and serves its core-tier tool catalog: document creation, text and content operations, and extraction. See the tool catalog. Core alone does not provide compliance policy checks, forensic analysis, LTV health checks, AI-readiness stamping, AST-aware chunking, mutation audit trails, or the batch and RAG tools; those eleven tools register only with nextpdf/enterprise installed and licensed.
Publication boundary
Section titled “Publication boundary”This page documents externally observable behavior and the supported public API surface only. Internal namespace paths, helper classes, mechanism tables, runbook filenames, and ticket prefixes are out of scope.