NextPDF Connect — niveaux de risque HITL
Chaque outil déclare l’un des quatre niveaux de risque. Au niveau le plus élevé, approbation requise, l’outil ne s’exécute pas au premier appel. À la place, ConfirmationGate renvoie un jeton de défi à usage unique, qu’un agent doit transmettre à un humain pour autoriser la réinvocation.
Installation
Section intitulée « Installation »composer require nextpdf/serverVue d’ensemble conceptuelle
Section intitulée « Vue d’ensemble conceptuelle »Le modèle de risque comporte exactement quatre niveaux ordonnés :
| Niveau | Valeur | Sens | Effet |
|---|---|---|---|
| safe | 0 | Lecture seule, aucun effet de bord | Exécution automatique |
| caution | 1 | Crée ou modifie un état en mémoire | Exécution automatique, consignée dans le journal d’audit |
| review | 2 | Produit une sortie qui pourrait être détournée | Exécution automatique, consignée dans le journal d’audit |
| approval_required | 3 | Destructrice, juridique ou critique pour la vie privée | Confirmation humaine requise |
Le risque d’un outil provient exactement de deux sources : la déclaration propre à l’outil et un remplacement de configuration optionnel défini par l’opérateur. Il n’existe pas de troisième source. Le modèle est versionné, et la réponse MCP initialize expose ce numéro afin qu’un client puisse détecter tout changement incompatible. La journalisation d’audit s’applique dès le niveau caution.
Suspendre une action automatisée jusqu’à ce qu’un humain l’autorise place le contrôle précisément là où l’automatisation introduit le risque. C’est l’emplacement qu’identifie l’IEC 31010 pour maîtriser le risque introduit par l’action humaine, au point d’introduction ou à proximité (IEC 31010:2019).
Surface d’API
Section intitulée « Surface d’API »La ConfirmationGate
Section intitulée « La ConfirmationGate »Lorsqu’un outil approval_required est invoqué sans jeton valide, le contrôle émet un défi. La vérification renvoie l’une des deux formes suivantes.
{ "allowed": true }ou
{ "allowed": false, "challenge": "<human-readable text>", "token": "confirm_<nonce>" }Le texte du défi indique l’opération et sa description, et avertit lorsqu’un fichier cible serait écrasé. Il demande à l’appelant de réinvoquer le même outil avec un paramètre _confirmation_token défini sur le jeton émis. Le jeton expire au bout de 300 secondes.
La liaison du jeton est délibérée : le jeton associe le nom de l’outil, un nonce aléatoire et le TTL — pas les arguments. Lors d’une nouvelle tentative, les clients MCP peuvent re-sérialiser les arguments avec un ordre des clés ou une normalisation différents ; hacher les arguments romprait donc des confirmations légitimes. Le jeton est à usage unique ; le consommer lors de la réinvocation autorise l’appel exactement une fois.
Exposition par transport
Section intitulée « Exposition par transport »Le contrôle s’applique à chaque transport qui pilote des outils :
- MCP : le défi est renvoyé en bande sous forme de réponse JSON-RPC réussie dont le contenu est le texte du défi. L’appelant réinvoque
tools/callavecarguments._confirmation_token. - REST et gRPC : le même contrôle s’exécute dans l’exécuteur d’outils partagé avant une opération
approval_required. Le défi apparaît dans la réponse de l’opération ; l’appelant répète l’opération avec le jeton.
Protection intégrée contre le déclassement
Section intitulée « Protection intégrée contre le déclassement »Un remplacement de configuration peut élever le niveau de risque d’un outil, mais il ne peut jamais abaisser le niveau d’un outil qui est approval_required par conception. Le chargeur de configuration impose un ensemble critique fixe et lève une erreur au chargement si un remplacement tente un déclassement. Le serveur refuse de démarrer plutôt que de fonctionner avec un contrôle affaibli.
Exemple de code — Démarrage rapide
Section intitulée « Exemple de code — Démarrage rapide »Déclenche un défi en écrivant un fichier avec output_pdf :
./vendor/bin/nextpdf-mcp <<'EOF'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"c","version":"1.0.0"}}}{"jsonrpc":"2.0","method":"notifications/initialized"}{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"output_pdf","arguments":{"document_id":"<id>","file_path":"/var/lib/nextpdf/tmp/out.pdf"}}}EOFLa réponse contient le défi, pas le fichier. Réinvoque avec le jeton émis :
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"output_pdf","arguments":{"document_id":"<id>","file_path":"/var/lib/nextpdf/tmp/out.pdf","_confirmation_token":"confirm_<nonce>"}}}Exemple de code — Production
Section intitulée « Exemple de code — Production »Élève un outil normalement classé caution vers approbation requise pour un déploiement durci :
nextpdf_mcp: risk_level_overrides: add_image: 3 # require human confirmation for image insertionUn déclassement est rejeté au chargement et le serveur ne démarre pas. Par exemple, définir output_pdf en dessous de 3 est un déclassement.
Cas limites et pièges
Section intitulée « Cas limites et pièges »-
output_pdfen mode base64 n’applique pas le contrôle. L’écriture sur disque est classée à approbation requise ; renvoyer le PDF en base64 (sansfile_path) est traité comme un risque moindre et s’exécute sans confirmation. -
Le jeton n’est pas une donnée d’authentification. Il n’authentifie pas l’appelant et ne remplace pas une clé d’API sur les transports réseau. Il ne déverrouille qu’un appel contrôlé spécifique, une seule fois, dans un délai de 300 secondes.
-
Un nouveau défi à chaque fois. Si le jeton n’est pas relayé, ou s’il expire, l’outil n’est pas bloqué de façon permanente ; l’appel suivant émet un nouveau défi. Les jetons sont stockés dans un magasin de jetons à usage unique avec un ramasse-miettes périodique.
-
L’audit a lieu quel que soit le résultat. L’émission d’un défi, une exécution réussie et une exécution échouée à partir du niveau caution sont toutes consignées dans le journal d’audit avec le nom de l’outil et le niveau de risque.
Performances
Section intitulée « Performances »Le contrôle ajoute une consultation du magasin de jetons et, en cas de défi, la génération d’un jeton aléatoire. Ce coût est négligeable face à celui de l’opération contrôlée, et ce chemin ne s’exécute que pour les outils approval_required.
Notes de sécurité
Section intitulée « Notes de sécurité »Le contrôle est un mécanisme de confinement, pas un mécanisme d’authentification. Il garantit qu’un humain autorise les actions destructrices, juridiques ou critiques pour la vie privée, même lorsqu’un agent autonome pilote l’outil. Pour ces opérations, le serveur ne prétend pas pouvoir fonctionner sans supervision humaine, et la configuration ne peut pas affaiblir le contrôle. Combine-le avec le modèle de clé d’API sur les transports réseau et avec le cantonnement au moindre privilège enabled_tools. Voir /connect/security-and-operations/.
Conformité
Section intitulée « Conformité »| Affirmation | Source | reference_id |
|---|---|---|
| Maîtriser le risque au point d’introduction (humaine) | IEC 31010:2019 |
La version du modèle de risque est portée dans la réponse MCP initialize afin que les clients puissent détecter un changement incompatible. Le format filaire est documenté sur /transports/mcp/.
Contexte commercial
Section intitulée « Contexte commercial »Les outils Premium déclarent leur propre niveau de risque en utilisant le même modèle à quatre niveaux. Les opérations Premium destructrices (par exemple la rédaction) sont contrôlées par le même mécanisme. Le contrôle fait partie du serveur, pas du package Premium.
Voir aussi
Section intitulée « Voir aussi »- /connect/tool-catalog/ — le niveau de risque de chaque outil de base vérifié
- /connect/configuration/ — le remplacement de risque en élévation uniquement
- /connect/security-and-operations/ — comment le contrôle s’inscrit dans le modèle de menace
- /transports/mcp/ — le format filaire du défi en bande
- /connect/overview/ — où se situe le contrôle dans l’architecture