Aller au contenu

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.

Fenêtre de terminal
composer require nextpdf/server

Le modèle de risque comporte exactement quatre niveaux ordonnés :

NiveauValeurSensEffet
safe0Lecture seule, aucun effet de bordExécution automatique
caution1Crée ou modifie un état en mémoireExécution automatique, consignée dans le journal d’audit
review2Produit une sortie qui pourrait être détournéeExécution automatique, consignée dans le journal d’audit
approval_required3Destructrice, juridique ou critique pour la vie privéeConfirmation 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).

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.

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/call avec arguments._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.

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.

Déclenche un défi en écrivant un fichier avec output_pdf :

Fenêtre de terminal
./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"}}}
EOF

La 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>"}}}

Élève un outil normalement classé caution vers approbation requise pour un déploiement durci :

/etc/nextpdf/nextpdf-mcp.yaml
nextpdf_mcp:
risk_level_overrides:
add_image: 3 # require human confirmation for image insertion

Un 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.

  • output_pdf en mode base64 n’applique pas le contrôle. L’écriture sur disque est classée à approbation requise ; renvoyer le PDF en base64 (sans file_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.

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.

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/.

AffirmationSourcereference_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/.

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.

  • /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