Les outils MCP ont désormais une étiquette de prix : déclarez le coût de chaque appel, plafonnez ce qu'une conversation peut dépenser


Vous le découvrez en fin de mois : un outil MCP a tourné une quarantaine de fois et chaque appel a facturé de vrais crédits. En relisant la transcription, il se comportait exactement comme un lecteur de fichiers gratuit — même JSON en entrée, même « terminé » d’une ligne en sortie. Rien dans la conversation ne vous disait quels appels coûtaient de l’argent.

C’est la position inconfortable dans laquelle se trouve aujourd’hui l’écosystème MCP. La génération d’images, de vidéos et de 3D ainsi que les API payantes arrivent toutes sous forme de serveurs MCP, et un agent les voit exactement comme il voit read_file. La PR #142470, fusionnée le 21 octobre 2026, ajoute les deux pièces manquantes : un coût déclaré par outil et un budget par conversation.

Trois nouvelles clés

À l’intérieur d’une entrée mcp_servers dans config.yaml :

mcp_servers:
  renders:
    command: "render-mcp"
    trust: untrusted
    tool_costs:
      create_image: 20                                    # environ 20 crédits par appel
      animate: {credits: [5, 20], note: "per animation"}   # une fourchette, avec une courte note
      get_status: 0                                        # gratuit ; identique à l'absence de clé
    spend_limit: 100     # par conversation ; 0 ou absent = pas de limite
    cost_unit: credits   # libellé dans les invites (par défaut : credits)

tool_costs accepte trois formes :

  • un nombre positif ou nul pour un coût fixe ;
  • une fourchette [min, max], adaptée aux outils facturés à la résolution ou à la durée ;
  • un objet avec credits contenant un nombre ou une fourchette, plus une note pour une ligne en langage clair.

spend_limit est un plafond par conversation ; 0 ou absent signifie pas de limite. cost_unit ne change que le libellé dans les invites et les totaux (par défaut credits), ce qui permet à un service facturé en « runs » ou en « points » de le dire.

L’invite d’approbation devient une facture

Avant les déclarations, un serveur en trust: untrusted demandait « autoriser create_image ? » avant un appel capable d’écrire. Avec un coût déclaré, la même invite affiche :

Costs about 20 credits.

Une fourchette s’affiche sous la forme Costs 5-20 credits (per animation). Une fois que la conversation a dépensé quelque chose sur ce serveur, une seconde ligne apparaît :

This chat has used about 40 credits on 'renders' (limit 100).

L’intérêt, c’est que l’approbation cesse d’être uniquement une question de sécurité pour devenir une question de budget. Vous n’approuvez plus une action ; vous approuvez 20 crédits de plus.

Où le total courant est conservé

Ces règles comptent plus que la configuration, parce qu’elles décident si vous pouvez faire confiance au chiffre :

  • Les totaux sont tenus par conversation et par serveur ; rien ne se reporte d’une conversation à l’autre.
  • Seuls les appels réellement transmis comptent. Les appels refusés ou bloqués n’ajoutent rien.
  • La facturation utilise l’estimation déclarée, et le haut de la fourchette — le design penche vers la demande d’approbation plus tôt.
  • Un appel dont le serveur meurt avant de le recevoir compte quand même, pour la même raison.
  • Le décompte vit en mémoire : c’est un budget pour une conversation, pas la facture du fournisseur. Redémarrer Hermes remet tous les totaux à zéro.
  • Le total suit la conversation à travers la compression de contexte et /branch. Dans le CLI, /new ouvre un nouveau total (idem pour une nouvelle conversation Desktop) ; sur les plateformes de messagerie, le total appartient à la conversation, il survit donc à /new. Chaque exécution cron a son propre total.

Ce qui se passe quand le budget est dépassé

C’est la partie à retenir :

  1. Il demande même sur un serveur en trust: full. Un tel serveur exécute normalement les outils facturés sans invite ; dès qu’un appel franchirait spend_limit, il s’arrête et demande.
  2. Il demande à chaque fois. Choisir « autoriser pour cette session » ne fait pas taire les appels facturés suivants dans cette conversation.
  3. Là où personne ne peut répondre, il refuse sans transmettre. Les jobs cron, hermes chat -q et un gateway sans approbateur tombent tous dans ce cas. Le modèle reçoit une erreur d’outil nommant la dépense et la limite, avec instruction de ne pas réessayer — pas un échec silencieux.
  4. Sous la limite, rien ne change. trust: full reste sans invite, et les outils annotés readOnlyHint: true ne sont pas réveillés à moins que le budget l’exige.

Autrement dit, spend_limit n’est pas un régulateur de débit. C’est une barrière qui dit « au-delà de cette ligne, un humain doit hocher la tête ».

Les paquets portables peuvent aussi le déclarer

Un paquet de plugin portable embarque le même tableau pour son serveur dans plugin.json :

"extensions": {
  "com.nousresearch.hermes": {
    "servers": {
      "meshy": {
        "trust": "untrusted",
        "costs": { "meshy_remesh": 5, "meshy_animate": { "credits": [5, 20], "note": "per animation" } },
        "spend_limit": 100,
        "cost_unit": "credits"
      }
    }
  }
}

Ça résout une asymétrie bien réelle : l’auteur du plugin sait exactement ce que coûte un outil, et l’utilisateur, en général, non. Les clés costs / spend_limit / cost_unit du paquet se traduisent en clés natives.

Cinq pièges

  1. Un tableau de coûts mal formé fait sauter tout le serveur, au lieu d’être ignoré. Si l’une des trois clés a la mauvaise forme, ce serveur ne se charge pas et l’erreur nomme la clé. C’est délibéré : une faute de frappe ne doit pas faire disparaître votre budget en silence.
  2. Les clés de tool_costs doivent être les noms d’outils du serveur lui-même, pas le préfixe d’affichage mcp_<server>_ de Hermes. Une mauvaise clé n’échoue pas — elle affiche un avertissement à la connexion, facile à manquer.
  3. Héritage en cas de surcharge de même nom : si vous ajoutez votre propre entrée mcp_servers pour le même serveur (par exemple pour le passer en trust: full), les clés de coût du paquet s’appliquent toujours, sauf si votre entrée les définit. spend_limit: 0 désactive la limite du paquet ; tool_costs: {} supprime ses coûts.
  4. C’est un budget, pas une facture. La facturation du fournisseur peut contredire la déclaration, et les totaux sont remis à zéro au redémarrage. Ne le traitez pas comme de la comptabilité.
  5. hermes plugins validate liste server costs: <name>. Vérifiez cette ligne avant d’installer, plutôt que de reconstituer la dépense depuis une transcription après coup.

Peut-on l’utiliser dès maintenant ?

La fonctionnalité est sur main et pas dans la v0.22.4 livrée — la plage de comparaison v0.22.3 vers v0.22.4 contient 14 commits et celle-ci n’en fait pas partie. Les installations de production attendent la prochaine release ; les checkouts source qui suivent main peuvent l’essayer tout de suite.

Le crédit de conception revient à un projet communautaire, Adolanium/hermes-tripo, qui avait implémenté « chaque crédit, demandé » et « une limite par conversation » avec un hook natif pre_tool_call. Les paquets portables ne peuvent pas embarquer de hooks, donc la fonctionnalité est arrivée dans le cœur, pilotée par des données déclarées — ce qui permet aussi aux plugins officiels, comme celui de Meshy, de s’en servir.

Si vous hésitez encore sur les serveurs qui méritent trust: full, notre guide de sécurité du catalogue MCP détaille les niveaux de trust. Les déclarations de coût et les niveaux de trust répondent à des questions différentes ; ils fonctionnent mieux ensemble.