NextPDF Connect: guida per sviluppatori
In breve
Sezione intitolata “In breve”NextPDF Connect (nextpdf/server) incapsula in un servizio indipendente dal framework il motore PDF 2.0 di NextPDF. Non reimplementa la generazione di PDF. Espone ogni funzionalità del motore come strumento con nome e schema descrittivo e pubblica il catalogo su tre trasporti: Model Context Protocol (MCP) su standard input e output, un’API (Application Programming Interface) REST (Representational State Transfer) e gRPC. Usare questa guida quando si lavora sul server, se ne estende l’insieme di strumenti o lo si gestisce in produzione.
L’intero progetto si fonda su tre concetti: il registro degli strumenti, i tre trasporti indipendenti e il gate di conferma con intervento umano (human-in-the-loop, HITL). Questa pagina spiega come questi elementi si integrano tra loro e come utilizzarli senza indebolire il modello di sicurezza. Per i simboli esatti di strumenti, RPC e messaggi, consultare la documentazione di riferimento dell’API.
Prerequisiti: PHP 8.4, Composer 2 e, per i trasporti di rete, il binario RoadRunner e almeno una chiave API. Installare con composer require nextpdf/server.
Confine architetturale
Sezione intitolata “Confine architetturale”Mantenere ogni responsabilità dal lato corretto del rispettivo confine. Uno strumento è un wrapper sottile attorno a una chiamata al motore; non deve contenere interpretazione dell’impaginazione, semantica del documento o logica di trasformazione.
| Livello | Di competenza di | Responsabilità | Non collocare qui |
|---|---|---|---|
| Client o agente | La propria integrazione | Decidere quale strumento chiamare; inoltrare a una persona le richieste di conferma. | Logica del motore o rilevamento dei livelli. |
| Trasporto | nextpdf/server | Gestire il framing delle richieste (JSON-RPC, HTTP o Protocol Buffers), autenticare e instradare verso l’esecutore degli strumenti. | Semantica del documento. |
| Registro degli strumenti | nextpdf/server | Rilevare i livelli, registrare gli strumenti nel rispetto dell’allowlist di sicurezza, risolvere uno strumento per nome. | Generazione di PDF. |
| Strumento | nextpdf/server | Convalidare gli argomenti rispetto allo schema di input e chiamare il motore. | Interpretazione dell’impaginazione o orchestrazione in più fasi. |
| Gate di conferma | nextpdf/server | Mantenere in sospeso un’operazione ApprovalRequired finché una persona non la autorizza. | Autenticazione del chiamante. |
| Motore | nextpdf/core (e nextpdf/premium) | Generare, ispezionare e trasformare il contenuto dei PDF. | Aspetti di trasporto o autenticazione. |
Ciclo di vita di runtime
Sezione intitolata “Ciclo di vita di runtime”Ogni trasporto ha un punto di ingresso e una factory di avvio propri, e ciascuno costruisce esplicitamente il proprio grafo di oggetti. Non esiste alcun container di dependency injection da configurare.
- Caricare la configurazione. Il server MCP risolve la configurazione dando precedenza alle variabili d’ambiente (
NEXTPDF_MCP_*) sulla sezionenextpdf_mcpdel file YAML, e a quest’ultima sui valori predefiniti incorporati; il risultato è unreadonlyMcpConfig. I server REST e gRPC leggonoHttpConfigdalle variabili d’ambienteNEXTPDF_*. Vedere Configurazione. - Costruire i criteri di sicurezza. L’allowlist
enabled_toolsviene costruita prima del registro, così da vincolare l’individuazione già dalla prima registrazione. - Costruire il registro e individuare gli strumenti.
ToolRegistry::registerDefaults()registra il livello core, poi i provider Pro ed Enterprise quando le loro classi vengono risolte e infine i provider AST e di mutation in bundle, in base ai rispettivi gate d’ambiente. - Costruire gli store condivisi e il gate. Lo store dei documenti in memoria viene costruito a partire da TTL e capacità configurati; il
ConfirmationGateviene assemblato con il proprio store di token monouso. - Collegare il trasporto. MCP entra in un ciclo leggi-gestisci-scrivi su stdio fino alla fine del file. REST e gRPC costruiscono la propria tabella di route o di servizi a partire dai livelli rilevati e affidano il ciclo delle richieste a RoadRunner.
A quel punto, una richiesta segue questo flusso: autenticazione (REST e gRPC), risoluzione dello strumento o dell’operazione, esecuzione del gate di conferma per le operazioni ApprovalRequired, esecuzione sul motore e restituzione del risultato. Vedere Avvio e individuazione.
Modello di trasporto
Sezione intitolata “Modello di trasporto”A livello concettuale, i tre trasporti condividono il registro, la configurazione e il gate, ma sono processi indipendenti. Avviarne uno non avvia gli altri.
| Trasporto | Punto di ingresso | Quando sceglierlo |
|---|---|---|
| MCP | bin/nextpdf-mcp | Un client IA locale che avvia il server come sottoprocesso attendibile. |
| REST | bin/nextpdf-server | Client HTTP in rete, con interfaccia descritta da un documento OpenAPI 3.1. |
| gRPC | bin/nextpdf-grpc | Client tipizzati e in streaming, tramite il servizio nextpdf.connect.v1.NextPDFConnect. |
Scegliere i trasporti in base al profilo RoadRunner che si esegue: .rr.yaml (solo REST), .rr.grpc.yaml (solo gRPC) o .rr.full.yaml (entrambi). Il trasporto MCP è un semplice sottoprocesso e non richiede alcun supervisore. I dettagli di protocollo per ciascun trasporto sono riportati in Trasporto MCP, Trasporto REST e Trasporto gRPC.
Struttura di distribuzione consigliata
Sezione intitolata “Struttura di distribuzione consigliata”Eseguire i trasporti di rete sotto RoadRunner con store condivisi e chiavi montate come segreti. Il profilo combinato consente a REST e gRPC di condividere un unico supervisore.
| Percorso o impostazione | Scopo |
|---|---|
.rr.full.yaml | Profilo REST e gRPC combinato sotto un unico supervisore. |
NEXTPDF_API_KEYS_FILE | Percorso di un file di chiavi API montato come segreto e ricaricato a caldo. |
NEXTPDF_REDIS_HOST | Abilita gli store di rate limiting, idempotenza e documenti con backend Redis per i pool con più worker. |
NEXTPDF_WORKER_COUNT / NEXTPDF_GRPC_WORKER_COUNT | Dimensionamento del pool di worker per i pool HTTP e gRPC. |
| Directory di base per l’output | Volume dedicato con permessi del filesystem a privilegio minimo per gli strumenti che producono file. |
L’esempio shell seguente avvia il profilo combinato con chiavi montate come segreti e uno store Redis condiviso. Non contiene segreti nel file in sé; le chiavi sono montate in /run/secrets/api-keys.
export NEXTPDF_API_KEYS_FILE=/run/secrets/api-keysexport NEXTPDF_WORKER_COUNT=8export NEXTPDF_GRPC_WORKER_COUNT=4export NEXTPDF_REDIS_HOST=redis./vendor/bin/rr serve -c .rr.full.yamlPer un pool con più worker, configurare Redis e verificare che ext-redis sia presente nell’immagine in esecuzione; senza l’estensione, gli store di rate limiting, idempotenza e documenti restano per singolo worker. Vedere Distribuzione.
Registro degli strumenti e risoluzione dei livelli
Sezione intitolata “Registro degli strumenti e risoluzione dei livelli”NextPDF\Server\ToolRegistry (src/ToolRegistry.php) costruisce il catalogo all’avvio. Il livello è dichiarato come invariante: ogni strumento restituisce il proprio tier() e riskLevel(); il registro non deduce mai il livello dal namespace o dal packaging.
- Il livello core si registra incondizionatamente: gli strumenti di documento e di diagnostica, più
generate_barcodequando il registro core degli encoder di codici a barre è presente, piùparse_pdfsoltanto quandoNEXTPDF_MCP_TOOL_PARSE_PDF_ENABLEDètrueo1. - I provider Pro ed Enterprise si registrano quando le rispettive classi provider, verificate con
class_exists(), vengono risolte. Un livello assente viene ignorato silenziosamente. - I provider AST e di mutation in bundle vengono registrati nel livello Pro e sono controllati da
NEXTPDF_AST_TOOLS_ENABLEDeNEXTPDF_MUTATION_TOOLS_ENABLED(entrambi abilitati per impostazione predefinita). - Il filtro dei criteri di sicurezza interseca ogni registrazione con l’allowlist
enabled_tools. L’allowlist sottrae; non aggiunge mai. Il conteggio per livello include solo gli strumenti ammessi dai criteri.
I conteggi per livello risultanti e il totale sono riportati nella risposta initialize di MCP e nell’endpoint REST GET /api/v1/capabilities. Qualsiasi totale fisso indicato nel testo va considerato obsoleto; interrogare il server in esecuzione. Vedere Catalogo degli strumenti.
Livelli di rischio e gate di conferma
Sezione intitolata “Livelli di rischio e gate di conferma”Ogni strumento dichiara uno dei quattro livelli di rischio dell’enum RiskLevel (src/Config/RiskLevel.php): Safe (0), Caution (1), Review (2) e ApprovalRequired (3). La registrazione di audit si applica da Caution in poi. Un override di configurazione può innalzare il rischio di uno strumento; non può mai abbassare il rischio di uno strumento che è ApprovalRequired per progettazione. Il loader della configurazione genera un’eccezione al momento del caricamento e il server rifiuta di avviarsi anziché funzionare con un gate indebolito.
Quando uno strumento ApprovalRequired viene invocato senza un token valido, il ConfirmationGate (src/Mcp/ConfirmationGate.php) restituisce un token di challenge monouso. Il token vincola il nome dello strumento, un nonce casuale e un time-to-live (TTL) di 300 secondi, non gli argomenti, perché, in caso di nuovo tentativo, i client potrebbero riserializzare gli argomenti con un diverso ordinamento delle chiavi. L’agente inoltra la challenge a una persona e reinvoca lo stesso strumento con il token nell’argomento _confirmation_token. Il token viene consumato al momento dell’uso, sbloccando esattamente una chiamata sottoposta al gate.
L’esempio PHP seguente mostra un helper indipendente dal trasporto che esegue una chiamata a uno strumento MCP e, in caso di challenge di conferma, presenta la challenge a un approvatore umano prima di riprovare con il token emesso. Dichiara i tipi stretti, è completamente tipizzato e intercetta l’eccezione più specifica anziché ignorare ogni errore.
<?php
declare(strict_types=1);
namespace App\Connect;
use JsonException;
/** * Drives one tool call and resolves an ApprovalRequired confirmation * challenge through a human approver before retrying. */final readonly class ConfirmingToolCaller{ public function __construct( private McpClientInterface $client, private HumanApproverInterface $approver, ) {}
/** * @param non-empty-string $toolName * @param array<string, mixed> $arguments * * @return array<string, mixed> The tool result content * * @throws JsonException When a response cannot be decoded * @throws ApprovalDeniedException When the human declines the challenge */ public function call(string $toolName, array $arguments): array { $response = $this->client->callTool($toolName, $arguments);
if (!isset($response['challenge'], $response['token'])) { return $response; }
$challenge = (string) $response['challenge']; $token = (string) $response['token'];
if (!$this->approver->approve($toolName, $challenge)) { throw new ApprovalDeniedException($toolName); }
$arguments['_confirmation_token'] = $token;
return $this->client->callTool($toolName, $arguments); }}Collegare McpClientInterface, HumanApproverInterface e ApprovalDeniedException al proprio trasporto e canale di approvazione. Il nuovo tentativo riutilizza gli argomenti originali più il token emesso; non approvare mai automaticamente una challenge senza una decisione umana. Vedere Livelli di rischio HITL.
Punti di estensione
Sezione intitolata “Punti di estensione”Estendere il server aggiungendo strumenti e fornendo provider, non modificando il registro.
| Punto di estensione | Da usare per | Vincolo |
|---|---|---|
Una classe che implementa ToolInterface | Una nuova funzionalità del motore esposta come strumento. | Dichiarare tier(), riskLevel(), category() e un inputSchema() come schema JSON; mantenerla come wrapper sottile del motore. |
Un provider ToolProviderInterface | Registrare un insieme di strumenti per un livello. | I provider Pro ed Enterprise vengono individuati tramite class_exists(); non imporre al server il pacchetto proprietario. |
Allowlist enabled_tools | Definire l’ambito del catalogo esposto a privilegio minimo. | L’allowlist sottrae soltanto; non può registrare uno strumento assente. |
risk_level_overrides | Rafforzare una distribuzione innalzando il rischio di uno strumento. | Solo innalzamento; un abbassamento di uno strumento ApprovalRequired fa fallire l’avvio. |
| Punti di iniezione per trasporto e worker | Testare il server in isolamento. | Questi punti di estensione esistono per i test, non per il wiring dell’applicazione. |
Flusso di lavoro operativo
Sezione intitolata “Flusso di lavoro operativo”- Scegliere un profilo. Eseguire
.rr.yaml,.rr.grpc.yamlo.rr.full.yamlin base ai trasporti da esporre. - Montare le chiavi da un segreto. Puntare
NEXTPDF_API_KEYS_FILEa un file segreto; preferire lo store di chiavi su file con ricarica a caldo, così la rotazione non richiede alcun riavvio. - Configurare gli store condivisi. Impostare
NEXTPDF_REDIS_HOSTe verificareext-redisper qualsiasi pool con più di un worker; collocare lo store dei job SQLite su un volume su cui tutti i worker possano scrivere. - Terminare il TLS. Eseguire REST dietro un terminatore TLS (Transport Layer Security); eseguire gRPC con TLS reciproco su qualsiasi rete non attendibile, fornendo la chiave del server, il certificato del server e l’autorità di certificazione del client come segreti di distribuzione.
- Sondare lo stato di salute. Usare gli endpoint anonimi
/healthze/readyz(REST) oppure le RPCHealthCheckeReadinessCheck(gRPC) per i probe dell’orchestratore. - Definire l’ambito del catalogo. Limitare
enabled_toolsall’insieme minimo di cui un’integrazione ha bisogno.
Verificare lo stato di salute di Redis anziché darlo per scontato: il server REST ripiega sugli store in memoria se la connessione Redis configurata fallisce. Vedere Distribuzione e Sicurezza e operazioni.
Gestione degli errori
Sezione intitolata “Gestione degli errori”| Errore | Dove si manifesta | Risposta consigliata |
|---|---|---|
document_id sconosciuto | Esecuzione dello strumento | Restituire un errore definito al chiamante; istruirlo a chiamare prima create_pdf. |
| ETag obsoleto su una mutation | Strumento di mutation AST | Rileggere il documento con get_document_ast e riprovare con l’ETag aggiornato. |
| Chiave API mancante o non valida (REST) | Middleware di autenticazione | Restituire 401 con una challenge WWW-Authenticate: Bearer; non rivelare quale parte era errata. |
| Livello non abilitato (REST) | Autorizzazione | Restituire 403; il livello della chiave è inferiore al livello dell’operazione. |
| Route del livello assente (REST) | Router | Restituire 404; il pacchetto non è installato. È un comportamento previsto, non un guasto. |
| Token non valido (gRPC) | Autenticatore gRPC | Far fallire la chiamata con UNAUTHENTICATED. |
| Redis irraggiungibile | Avvio o runtime | Ripiegare sugli store in memoria; avvisare gli operatori e verificare lo stato di salute di Redis. |
| Percorso di output esterno alla directory di base | Strumento che produce file | Rifiutare l’operazione in modalità fail-closed; il percorso viene canonicalizzato e il traversal viene rifiutato. |
Esporre gli errori del motore come oggetti di errore definiti, mai come successi silenziosi. Il modello degli errori per ciascun trasporto è descritto nella documentazione di riferimento dell’API.
Valori predefiniti sicuri
Sezione intitolata “Valori predefiniti sicuri”| Aspetto | Predefinito | Quando eseguire l’override |
|---|---|---|
parse_pdf | Disabilitato (attivabile tramite NEXTPDF_MCP_TOOL_PARSE_PDF_ENABLED). | Abilitare solo quando un’integrazione richiede l’ispezione strutturale. |
enabled_tools | Vuota (tutti gli strumenti individuati sono consentiti). | Impostare un’allowlist esplicita per le distribuzioni a privilegio minimo. |
| Override del rischio | Nessuno. | Innalzare il rischio per una distribuzione irrobustita; non tentare mai un abbassamento. |
document_ttl / max_documents | 1800 secondi / 50 documenti. | Abbassare per le distribuzioni sensibili alla residenza dei dati o con vincoli di memoria. |
allow_file_output | Abilitato. | Impostare su false per le distribuzioni stateless e sensibili alla residenza dei dati. |
| Numero di worker | Quattro (HTTP), due (gRPC). | Dimensionare in base alla latenza osservata e ai core disponibili. |
| Listener REST | HTTP in chiaro dietro un terminatore TLS. | Terminare sempre il TLS a monte; non esporre mai testo in chiaro su una rete non attendibile. |
| gRPC su reti non attendibili | TLS reciproco. | Obbligatorio; non eseguire mai un listener gRPC in chiaro su una rete non attendibile. |
Checklist di test
Sezione intitolata “Checklist di test”- I test del registro verificano che un livello Pro o Enterprise assente venga ignorato silenziosamente e che il catalogo core si registri comunque.
- I test dell’allowlist verificano che
enabled_toolssottragga e non aggiunga mai uno strumento che il registro non ha individuato. - I test del gate di conferma verificano che uno strumento
ApprovalRequiredrestituisca una challenge alla prima chiamata e venga eseguito una sola volta con un token monouso valido, nonché che il token scada dopo il suo TTL. - I test di abbassamento verificano che una voce
risk_level_overridesche indebolisce uno strumentoApprovalRequiredfaccia fallire l’avvio. - I test di autenticazione coprono chiavi mancanti, malformate, disabilitate e scadute su REST (
401conWWW-Authenticate) e gRPC (UNAUTHENTICATED), e il rifiuto quando il livello non è abilitato (403). - I test di concorrenza verificano che un ETag obsoleto faccia fallire una mutation e che una
idempotency_keyripetuta riproduca il risultato memorizzato nella cache. - I test di contenimento dei percorsi verificano che un percorso di output che si risolve all’esterno della directory di base venga rifiutato.
- Mantenere le fixture piccole e non sensibili; non eseguire mai il commit di una chiave API reale o del contenuto di un documento.
Vedere anche
Sezione intitolata “Vedere anche”- Documentazione di riferimento dell’API: simboli esatti di strumenti, RPC e messaggi
- Catalogo degli strumenti: l’insieme core verificato e il conteggio a runtime
- Livelli di rischio HITL: il modello di rischio e l’envelope di conferma
- Configurazione: l’ordine di risoluzione e l’override solo in innalzamento
- Distribuzione: profili RoadRunner, Redis e TLS reciproco
- Sicurezza e operazioni: autenticazione, sicurezza del trasporto e modello delle minacce