Guide développeur NextPDF Connect
NextPDF Connect (nextpdf/server) encapsule le moteur PDF 2.0 NextPDF, indépendant de tout framework, dans un service. Il ne réimplémente pas la génération de PDF. Il expose chaque capacité du moteur sous forme d’outil nommé et décrit par un schéma, puis met ce catalogue à disposition via trois transports : le Model Context Protocol (MCP) sur l’entrée et la sortie standard, une interface de programmation (API) Representational State Transfer (REST), et gRPC. Utilise ce guide lorsque tu développes avec le serveur, que tu étends son jeu d’outils ou que tu l’exploites en production.
Trois concepts structurent toute la conception : le registre d’outils, les trois transports indépendants et la barrière de confirmation human-in-the-loop (HITL). Cette page explique comment ils s’articulent et comment les utiliser sans affaiblir le modèle de sécurité. Pour les symboles exacts des outils, des RPC et des messages, consulte la référence de l’API.
Prérequis : PHP 8.4, Composer 2 et, pour les transports réseau, le binaire RoadRunner ainsi qu’au moins une clé d’API. Installe le package avec composer require nextpdf/server.
Frontières d’architecture
Section intitulée « Frontières d’architecture »Garde chaque responsabilité du bon côté des frontières. Un outil est une fine enveloppe autour d’un appel au moteur ; il ne doit porter ni l’interprétation de la mise en page, ni la sémantique du document, ni l’intelligence de transformation.
| Couche | Propriétaire | Responsabilité | À ne pas mettre ici |
|---|---|---|---|
| Client ou agent | Ton intégration | Décider quel outil appeler ; relayer les défis de confirmation à un humain. | La logique du moteur ou la détection de niveau. |
| Transport | nextpdf/server | Encadrer les requêtes (JSON-RPC, HTTP ou Protocol Buffers), authentifier et router vers l’exécuteur d’outils. | La sémantique du document. |
| Registre d’outils | nextpdf/server | Découvrir les niveaux, enregistrer les outils sous réserve de la liste d’autorisation de sécurité et retrouver un outil par son nom. | La génération de PDF. |
| Outil | nextpdf/server | Valider les arguments contre le schéma d’entrée et appeler le moteur. | L’interprétation de la mise en page ou l’orchestration multi-étapes. |
| Barrière de confirmation | nextpdf/server | Retenir une opération ApprovalRequired jusqu’à son autorisation par un humain. | L’authentification de l’appelant. |
| Moteur | nextpdf/core (et nextpdf/premium) | Générer, inspecter et transformer le contenu PDF. | Les préoccupations de transport ou d’authentification. |
Cycle de vie à l’exécution
Section intitulée « Cycle de vie à l’exécution »Chaque transport a son propre point d’entrée et sa propre fabrique de démarrage, et chacun construit explicitement son graphe d’objets. Il n’y a aucun conteneur d’injection de dépendances dans lequel enregistrer ces objets.
- Charge la configuration. Le serveur MCP résout la configuration en donnant la priorité aux variables d’environnement (
NEXTPDF_MCP_*) sur la sectionnextpdf_mcpdu fichier YAML, qui prime elle-même sur les valeurs par défaut intégrées, et produit unreadonlyMcpConfig. Les serveurs REST et gRPC lisentHttpConfigdepuis les variables d’environnementNEXTPDF_*. Voir Configuration. - Construis la politique de sécurité. La liste d’autorisation
enabled_toolsest construite avant le registre, afin qu’elle contraigne la découverte dès le premier enregistrement. - Construis le registre et découvre les outils.
ToolRegistry::registerDefaults()enregistre le niveau Core, puis les fournisseurs Pro et Enterprise lorsque leurs classes sont résolues, puis les fournisseurs AST et de mutation embarqués sous réserve de leurs barrières d’environnement. - Construis les magasins partagés et la barrière. Le magasin de documents en mémoire est construit à partir du TTL et de la capacité configurés ; la
ConfirmationGateest assemblée avec son magasin de jetons à usage unique. - Lie le transport. Le transport MCP entre dans une boucle lecture-traitement-écriture sur stdio jusqu’à la fin de fichier. REST et gRPC construisent leur table de routes ou de services à partir des niveaux détectés et confient la boucle de requêtes à RoadRunner.
Une requête suit ensuite ce flux : authentifier (REST et gRPC), résoudre l’outil ou l’opération, exécuter la barrière de confirmation pour le travail ApprovalRequired, exécuter l’appel sur le moteur et renvoyer le résultat. Voir Démarrage et découverte.
Modèle de transports
Section intitulée « Modèle de transports »Les trois transports partagent le registre, la configuration et la barrière comme concepts, mais ce sont des processus indépendants. Démarrer l’un ne lance pas les autres.
| Transport | Point d’entrée | Quand le choisir |
|---|---|---|
| MCP | bin/nextpdf-mcp | Un client IA local qui lance le serveur comme sous-processus de confiance. |
| REST | bin/nextpdf-server | Des clients HTTP en réseau ; décrit par un document OpenAPI 3.1. |
| gRPC | bin/nextpdf-grpc | Des clients typés et en streaming ; le service nextpdf.connect.v1.NextPDFConnect. |
Choisis les transports en fonction du profil RoadRunner que tu exécutes : .rr.yaml (REST uniquement), .rr.grpc.yaml (gRPC uniquement), ou .rr.full.yaml (les deux). Le transport MCP est un simple sous-processus et n’a besoin d’aucun superviseur. Les détails de protocole par transport se trouvent dans Transport MCP, Transport REST, et Transport gRPC.
Structure de déploiement recommandée
Section intitulée « Structure de déploiement recommandée »Exécute les transports réseau sous RoadRunner avec des magasins partagés et des clés montées depuis un secret. Le profil combiné permet à REST et gRPC de partager le même superviseur.
| Chemin ou réglage | Rôle |
|---|---|
.rr.full.yaml | Profil REST et gRPC combiné sous un seul superviseur. |
NEXTPDF_API_KEYS_FILE | Chemin vers un fichier de clés d’API monté depuis un secret et rechargé à chaud. |
NEXTPDF_REDIS_HOST | Active les magasins de limitation de débit, d’idempotence et de documents adossés à Redis pour les pools multi-workers. |
NEXTPDF_WORKER_COUNT / NEXTPDF_GRPC_WORKER_COUNT | Dimensionnement du pool de workers pour les pools HTTP et gRPC. |
| Répertoire de sortie de base | Volume dédié avec des permissions de système de fichiers respectant le moindre privilège pour les outils de sortie vers fichier. |
L’exemple de shell suivant démarre le profil combiné avec des clés montées depuis un secret et un magasin Redis partagé. Aucun secret n’est écrit dans le fichier lui-même ; les clés sont montées sur /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.yamlPour un pool multi-workers, configure Redis et vérifie que ext-redis est présent dans l’image exécutée ; sans lui, les magasins de limitation de débit, d’idempotence et de documents restent propres à chaque worker. Voir Déploiement.
Registre d’outils et résolution des niveaux
Section intitulée « Registre d’outils et résolution des niveaux »NextPDF\Server\ToolRegistry (src/ToolRegistry.php) construit le catalogue au démarrage. Le niveau est un invariant déclaré : chaque outil renvoie ses propres tier() et riskLevel() ; le registre n’infère jamais le niveau depuis l’espace de noms ni l’empaquetage.
- Le niveau Core s’enregistre sans condition : les outils de document et de diagnostic, plus
generate_barcodequand le registre d’encodeurs de codes-barres du core est présent, plusparse_pdfseulement quandNEXTPDF_MCP_TOOL_PARSE_PDF_ENABLEDvauttrueou1. - Les fournisseurs Pro et Enterprise s’enregistrent lorsque leurs classes de fournisseur sont résolues, après sondage avec
class_exists(). Un niveau absent est ignoré silencieusement. - Les fournisseurs AST et de mutation embarqués s’enregistrent sous le niveau Pro, contrôlés par
NEXTPDF_AST_TOOLS_ENABLEDetNEXTPDF_MUTATION_TOOLS_ENABLED(les deux activés par défaut). - Le filtre de politique de sécurité croise chaque enregistrement avec la liste d’autorisation
enabled_tools. La liste d’autorisation ne fait que soustraire ; elle n’ajoute jamais. Le compteur par niveau ne comptabilise que les outils admis par la politique.
Les décomptes par niveau qui en résultent, ainsi que le total, sont rapportés dans la réponse initialize du MCP et l’endpoint REST GET /api/v1/capabilities. Considère comme obsolète tout total figé dans le texte ; interroge le serveur en cours d’exécution. Voir Catalogue d’outils.
Niveaux de risque et barrière de confirmation
Section intitulée « Niveaux de risque et barrière de confirmation »Chaque outil déclare l’un des quatre niveaux de risque de l’énumération RiskLevel (src/Config/RiskLevel.php) : Safe (0), Caution (1), Review (2), et ApprovalRequired (3). La journalisation d’audit s’applique à partir de Caution inclus. Un remplacement de configuration peut élever le risque d’un outil ; il ne peut jamais abaisser un outil qui est ApprovalRequired par conception. Le chargeur de configuration lève une exception au chargement, et le serveur refuse de démarrer plutôt que de tourner avec une barrière affaiblie.
Quand un outil ApprovalRequired est invoqué sans jeton valide, la ConfirmationGate (src/Mcp/ConfirmationGate.php) renvoie un jeton de défi à usage unique. Le jeton lie le nom de l’outil, un nonce aléatoire et une durée de vie (TTL) de 300 secondes, mais pas les arguments, car les clients peuvent re-sérialiser les arguments avec un ordre de clés différent lors d’une nouvelle tentative. L’agent relaie le défi à un humain et réinvoque le même outil avec le jeton dans l’argument _confirmation_token. Le jeton est consommé à l’usage, ce qui autorise exactement un appel contrôlé.
L’exemple PHP suivant est un assistant indépendant du transport qui pilote un appel d’outil MCP et, lors d’un défi de confirmation, transmet le défi à un approbateur humain avant de réessayer avec le jeton émis. Il déclare des types stricts, est entièrement typé et intercepte l’exception la plus spécifique plutôt que d’avaler toutes les erreurs.
<?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); }}Raccorde McpClientInterface, HumanApproverInterface et ApprovalDeniedException à ton propre transport et à ton propre canal d’approbation. La nouvelle tentative réutilise les arguments d’origine plus le jeton émis ; n’approuve jamais automatiquement un défi sans une décision humaine. Voir Niveaux de risque HITL.
Points d’extension
Section intitulée « Points d’extension »Le serveur s’étend en ajoutant des outils et des fournisseurs, pas en modifiant le registre.
| Point d’extension | À utiliser pour | Contrainte |
|---|---|---|
Une classe implémentant ToolInterface | Une nouvelle capacité du moteur exposée sous forme d’outil. | Déclare tier(), riskLevel(), category() et un inputSchema() JSON Schema ; garde-le comme une fine enveloppe autour du moteur. |
Un fournisseur ToolProviderInterface | Enregistrer un jeu d’outils pour un niveau. | Les fournisseurs Pro et Enterprise sont découverts par class_exists() ; ne rends pas le package propriétaire obligatoire dans le serveur. |
enabled_tools, liste d’autorisation | Restreindre le catalogue exposé au moindre privilège. | La liste d’autorisation ne fait que soustraire ; elle ne peut pas enregistrer un outil absent. |
risk_level_overrides | Durcir un déploiement en élevant le risque d’un outil. | En montée uniquement ; un abaissement d’un outil ApprovalRequired fait échouer le démarrage. |
| Points d’injection de transport et de worker injectables | Tester le serveur de façon isolée. | Ces points existent pour les tests, pas pour le câblage applicatif. |
Flux de travail d’exploitation
Section intitulée « Flux de travail d’exploitation »- Choisis un profil. Exécute
.rr.yaml,.rr.grpc.yaml, ou.rr.full.yamlpour les transports que tu exposes. - Monte les clés depuis un secret. Pointe
NEXTPDF_API_KEYS_FILEvers un fichier de secret ; préfère le magasin de clés basé sur un fichier rechargé à chaud pour que la rotation n’exige aucun redémarrage. - Configure les magasins partagés. Définis
NEXTPDF_REDIS_HOSTet vérifie la présence deext-redispour tout pool de plus d’un worker ; place le magasin de jobs SQLite sur un volume accessible en écriture par tous les workers. - Termine le TLS. Exécute REST derrière un terminateur Transport Layer Security (TLS) ; exécute gRPC avec TLS mutuel sur tout réseau non fiable, avec la clé du serveur, le certificat du serveur et l’autorité de certification client fournis comme secrets de déploiement.
- Sonde la santé. Utilise les endpoints anonymes
/healthzet/readyz(REST) ou les RPCHealthChecketReadinessCheck(gRPC) pour les sondes de l’orchestrateur. - Restreins le catalogue. Restreins
enabled_toolsau jeu minimal dont une intégration a besoin.
Vérifie la santé de Redis plutôt que de la présumer : le serveur REST se rabat sur les magasins en mémoire quand une connexion Redis configurée échoue. Voir Déploiement et Sécurité et exploitation.
Gestion des défaillances
Section intitulée « Gestion des défaillances »| Défaillance | Où elle apparaît | Réponse recommandée |
|---|---|---|
Identifiant inconnu document_id | Exécution d’outil | Retourner une erreur définie à l’appelant ; lui demander d’appeler d’abord create_pdf. |
| ETag obsolète sur une mutation | Outil de mutation AST | Relire le document avec get_document_ast et réessayer avec le nouvel ETag. |
| Clé d’API manquante ou invalide (REST) | Middleware d’authentification | Retourner 401 avec un défi WWW-Authenticate: Bearer ; ne pas divulguer quelle partie était erronée. |
| Niveau non habilité (REST) | Autorisation | Retourner 403 ; le niveau de la clé est inférieur à celui de l’opération. |
| Route de niveau absente (REST) | Routeur | Retourner 404 ; le package n’est pas installé. C’est un cas attendu, pas une défaillance. |
| Jeton incorrect (gRPC) | Authentificateur gRPC | Faire échouer l’appel avec UNAUTHENTICATED. |
| Redis injoignable | Démarrage ou exécution | Dégrader vers les magasins en mémoire ; alerter les opérateurs et vérifier la santé de Redis. |
| Chemin de sortie hors du répertoire de base | Outil de sortie vers fichier | Échouer en mode sûr ; le chemin est canonicalisé et la traversée est rejetée. |
Faire remonter les défaillances du moteur sous forme d’objets d’erreur définis, jamais comme des succès silencieux. Le modèle d’erreur de chaque transport est détaillé dans la référence de l’API.
Valeurs par défaut sûres
Section intitulée « Valeurs par défaut sûres »| Préoccupation | Par défaut | Quand le remplacer |
|---|---|---|
parse_pdf | Désactivé (activation explicite via NEXTPDF_MCP_TOOL_PARSE_PDF_ENABLED). | À activer seulement quand une intégration a besoin d’une inspection structurelle. |
enabled_tools | Vide (tous les outils découverts sont autorisés). | Définis une liste d’autorisation explicite pour les déploiements au moindre privilège. |
| Remplacements de risque | Aucun. | Élève le risque pour un déploiement durci ; ne tente jamais un abaissement. |
document_ttl / max_documents | 1800 secondes / 50 documents. | Abaisse-les pour les déploiements sensibles à la résidence des données ou à mémoire contrainte. |
allow_file_output | Activé. | Définis-le à false pour les déploiements sans état, sensibles à la résidence des données. |
| Nombre de workers | Quatre (HTTP), deux (gRPC). | Dimensionne-le selon la latence observée et les cœurs disponibles. |
| Écouteur REST | HTTP en clair derrière un terminateur TLS. | Termine toujours le TLS en amont ; n’expose jamais de trafic en clair sur un réseau non fiable. |
| gRPC sur des réseaux non fiables | TLS mutuel. | Requis ; n’exécute jamais d’écouteur gRPC en clair sur un réseau non fiable. |
Liste de vérification des tests
Section intitulée « Liste de vérification des tests »- Les tests du registre vérifient qu’un niveau Pro ou Enterprise absent est ignoré silencieusement et que le catalogue Core s’enregistre quand même.
- Les tests de la liste d’autorisation vérifient que
enabled_toolssoustrait et n’ajoute jamais un outil que le registre n’a pas découvert. - Les tests de la barrière de confirmation vérifient qu’un outil
ApprovalRequiredrenvoie un défi au premier appel, ne s’exécute qu’une seule fois avec un jeton valide à usage unique, et que le jeton expire après son TTL. - Les tests d’abaissement vérifient qu’une entrée
risk_level_overridesaffaiblissant un outilApprovalRequiredfait échouer le démarrage. - Les tests d’authentification couvrent les clés manquantes, malformées, désactivées et expirées sur REST (
401avecWWW-Authenticate) et gRPC (UNAUTHENTICATED), ainsi que le rejet pour niveau insuffisant (403). - Les tests de concurrence vérifient qu’un ETag obsolète fait échouer une mutation et qu’une
idempotency_keyrépétée rejoue le résultat mis en cache. - Les tests de confinement de chemin vérifient qu’un chemin de sortie vers fichier dont la résolution sort du répertoire de base est rejeté.
- Garde des fixtures petites et non sensibles ; ne commite jamais une vraie clé d’API ni du contenu de document.
Voir aussi
Section intitulée « Voir aussi »- Référence de l’API — symboles exacts des outils, des RPC et des messages
- Catalogue d’outils — le jeu Core vérifié et le comptage à l’exécution
- Niveaux de risque HITL — le modèle de risque et l’enveloppe de confirmation
- Configuration — l’ordre de résolution et le remplacement en montée uniquement
- Déploiement — profils RoadRunner, Redis et TLS mutuel
- Sécurité et exploitation — authentification, sécurité du transport et modèle de menace