Laisser un agent déployer : le MCP de Zerolith dans Claude Code
Un assistant écrit le handler, puis c'est vous qui copiez, collez et relancez. Le MCP supprime cet aller-retour : une commande pour connecter Claude Code, un OAuth sans clé d'API, et un agent qui referme la boucle déployer–appeler–lire les logs–corriger. Avec ce qu'il ne verra jamais, et ce que ça coûte.
Un assistant écrit très bien un handler Python. Il sait aussi vous dire quelle commande curl
lancer pour le déployer. Entre les deux, il y a vous : vous copiez le code dans un fichier, vous
collez la commande, vous récupérez l'URL, vous la lui rendez, il lit l'erreur, il corrige, et vous
recommencez. Le modèle réfléchit, et vous faites les mains.
Le Model Context Protocol supprime cet aller-retour. C'est un standard par lequel un assistant découvre des outils et les appelle lui-même. Zerolith en expose un : quarante et un outils, tous bornés à votre compte, et le déploiement devient une phrase dans la conversation plutôt qu'une suite de commandes recopiées.
Voici comment on le branche à Claude Code, ce que ça donne vraiment une fois en place, et les quelques choses qui valent d'être sues avant de laisser un agent appuyer sur les boutons.
Une commande pour se connecter
Le serveur est distant : il tourne chez nous, en HTTP. Il n'y a donc rien à installer, aucun processus local, aucun binaire à maintenir à jour.
claude mcp add --transport http zerolith https://zerolith.io/mcp
Ouvrez ensuite Claude Code et tapez /mcp : le serveur apparaît, vous choisissez de vous
authentifier, votre navigateur s'ouvre sur la page d'autorisation Zerolith. Vous vous connectez,
vous validez, et les outils sont là.
Ce qui n'apparaît nulle part dans cette procédure : une clé d'API. Le flux est un OAuth 2.1 complet, et il vaut la peine de dire pourquoi, parce que c'est exactement ce qui manque à la plupart des intégrations « collez votre clé ici » :
- L'agent s'enregistre lui-même (RFC 7591). Vous n'avez aucun identifiant applicatif à créer, à copier ni à ranger quelque part.
- PKCE en S256, obligatoire. Un code d'autorisation intercepté ne sert à rien sans le vérificateur, qui ne quitte jamais votre poste.
- Le jeton est lié à sa ressource (RFC 8707). Un jeton émis pour Zerolith ne vaut rien ailleurs, et un jeton émis pour un autre service ne vaut rien ici.
- Le jeton d'accès vit une heure, le jeton de rafraîchissement quatorze jours, et chaque renouvellement invalide le précédent. Un jeton dérobé puis rejoué se signale de lui-même.
Aucun secret longue durée ne traîne dans un fichier de configuration. Sur un poste de travail, ce n'est pas un détail : un fichier de config finit toujours par être sauvegardé, synchronisé ou partagé par accident.
La première question à poser à l'agent
Avant de lui demander de déployer quoi que ce soit, demandez-lui ce qu'il voit. Deux outils en lecture répondent, et ce sont ceux qui cadrent toute la suite.
whoami renvoie le compte et le solde. get_catalog renvoie les langages disponibles, les gabarits
et les tarifs — voici la réponse réelle du serveur de production, abrégée :
{"languages": [{"name": "python", "code_filename": "main.py", "default_handler": "main.handler"},
{"name": "python313", "code_filename": "main.py", "default_handler": "main.handler"},
{"name": "python314", "code_filename": "main.py", "default_handler": "main.handler"},
{"name": "nodejs20", "code_filename": "main.js", "default_handler": "main.handler"},
{"name": "nodejs22", "code_filename": "main.js", "default_handler": "main.handler"},
{"name": "nodejs24", "code_filename": "main.js", "default_handler": "main.handler"}],
"sizes": [{"name": "small", "memory": "128Mi", "cpu": "100m"},
{"name": "medium", "memory": "256Mi", "cpu": "250m"}, "…"],
"defaults": {"language": "python", "size": "small", "min_scale": 0, "max_scale": 2,
"stable_window": "60s", "timeout_seconds": 120},
"pricing": {"price_per_gb_second": 0.000004, "price_per_vcpu_second": 0.0000125,
"price_per_invocation": 0.0000004}}Ce n'est pas une politesse d'introduction, c'est la parade au défaut le plus fréquent d'un agent :
il déduit de sa mémoire ce que la plateforme accepte. Un modèle a lu des milliers de fichiers
serverless.yml et vous proposera volontiers un runtime python3.11, un gabarit xlarge ou une
option qui n'existe pas ici.
Le catalogue est la source de vérité, et il bouge. Notez les identifiants : python est 3.12 et le
reste, parce qu'une révision Knative est immuable et que repointer python déplacerait du code
tiers sur un interpréteur qu'il n'a jamais choisi — 3.13 a supprimé une douzaine de modules de la
bibliothèque standard, c'est une rupture réelle. Les versions récentes sont donc des identifiants à
part, python313 et python314, qu'on choisit. Et un langage dont l'image n'est pas déployée en
production n'est pas annoncé du tout, plutôt que d'être offert puis refusé au déploiement : la
liste ci-dessus est celle de ce qui tourne aujourd'hui, pas celle de ce que le code sait faire.
La boucle qui change vraiment quelque chose
Le déploiement n'est pas le sujet. Ce qui compte, c'est que l'agent puisse refermer la boucle tout seul : déployer, appeler, lire ce qui s'est passé, corriger, redéployer.
Une demande en langage naturel suffit :
> Déploie une fonction Python "taux" qui renvoie le taux EUR/USD du jour depuis l'API de la BCE, en JSON. Rends-la publique, appelle-la, et montre-moi la réponse.
Ce que l'agent enchaîne derrière, outil par outil :
get_catalog— quel langage, quel gabarit, quels défauts.deploy_function— le code, le nom,public: true. Réponse : l'identifiant et l'URL.invoke_function— un appel réel, qui réveille un pod et renvoie le statut HTTP et le corps.get_function_logs— si le statut est 500, la trace Python est là.update_function— le correctif, qui produit une nouvelle révision.invoke_function— de nouveau, pour vérifier.
Les étapes 3 à 6 sont l'intérêt de la manœuvre. Un assistant sans MCP s'arrête à l'étape 2 et vous
rend un bloc de code en espérant qu'il marche ; ici il constate l'échec, lit la trace et corrige,
sans que vous ayez ouvert un terminal. Sur une erreur bête — un champ JSON mal nommé, un décodage
de date, un timeout trop court — la boucle se referme en une minute.
Et le reste du périmètre suit le même chemin. Les variables d'environnement, les URL signées, les domaines sur mesure, les bases privées : dix-neuf des quarante et un outils concernent la base de données privée, assez pour qu'un agent la crée, y pose un schéma par une fonction migratrice, l'attache à votre API et déclenche un export — la marche complète, décrite à la main, est dans l'article précédent.
Ce que l'agent ne voit jamais
C'est la question qu'il faut se poser avant de brancher quoi que ce soit sur un compte : jusqu'où va la délégation. Ici, elle porte sur les actions, pas sur les secrets.
- Vos clés d'API restent invisibles. Elles sont stockées hachées et ne s'affichent qu'une fois, à leur création, dans l'interface. Aucun outil MCP ne les renvoie, et l'agent n'en a pas besoin : il s'authentifie avec son propre jeton.
- Une variable d'environnement de type
secretne se relit pas. L'agent peut la créer, la remplacer, la supprimer — pas en lire la valeur. Vous non plus, d'ailleurs : la valeur n'existe que dans l'objet du cluster, et le backend n'a pas le droit de lecture dessus. - Le jeton de votre base de données ne sort pas. L'agent peut créer la base, l'attacher à une fonction et lancer une migration sans jamais recevoir l'identifiant qui l'ouvre. La fonction, elle, le trouve dans son environnement.
- Une ressource qui ne vous appartient pas répond « introuvable », jamais « interdit ». L'agent n'apprend même pas qu'elle existe.
Il y a deux portées, et pas davantage : mcp:read pour consulter, mcp:write pour agir. Chaque
outil déclare aussi s'il modifie l'état et s'il est destructeur, ce qui permet à Claude Code de vous
demander confirmation avant un delete_function tout en laissant passer un list_functions. Le
serveur tourne d'ailleurs sur exactement le même code que l'API REST et l'interface web : il n'existe
pas de chemin privilégié réservé aux agents, donc un outil MCP ne peut jamais faire ce que votre
compte ne peut pas faire lui-même.
Ce que ça coûte
Le MCP n'est pas facturé. Lister vos fonctions, lire vos métriques, créer une variable, déclencher un export : ce sont des appels d'administration, ils passent par la même API que l'interface web et ne coûtent rien.
Ce qui est facturé, c'est l'exécution — à l'identique, qu'elle vienne d'un agent, d'un curl ou
d'un navigateur. Aux tarifs publics, un pod small coûte 0,00000175 €/s (0,125 Gio à
0,000004 €/Gio-seconde, plus 0,1 vCPU à 0,0000125 €/vCPU-seconde) et chaque invocation
0,0000004 €.
Une séance de mise au point typique — un déploiement, une vingtaine d'appels étalés sur un quart d'heure, le pod restant éveillé quelques minutes en tout — se chiffre donc en fractions de centime. Le facteur qui compte n'est pas le nombre d'appels de l'agent, c'est le temps pendant lequel un pod reste debout : après le dernier appel, l'autoscaler observe sa fenêtre de stabilité (60 s par défaut) puis laisse un délai de grâce. Vingt appels dans la même minute coûtent moins qu'un appel toutes les cinq minutes.
Et si le crédit s'épuise, un agent qui boucle ne creuse pas un trou : l'appel est refusé en bordure, avant même que le pod ne démarre. C'est la même garantie que pour le reste de la plateforme, elle ne s'assouplit pas parce qu'un agent est au clavier. Le détail est sur la page tarifs.
Trois choses apprises en s'en servant
Faites-lui lire avant d'écrire. update_function remplace le code, il ne le fusionne pas. Un
agent qui n'a pas rappelé get_function récrit le handler de mémoire, et efface au passage la
correction que vous aviez faite à la main dans l'interface il y a deux jours. La description de
l'outil le dit d'ailleurs explicitement — encore faut-il que la demande ne l'invite pas à aller
plus vite.
La plateforme ne garde pas d'historique de votre code. Elle garde le code courant, lisible par
get_function, et son empreinte. Pas la version d'avant. Une conversation n'est pas un dépôt :
ce que l'agent déploie doit finir dans votre git, sinon la seule copie de votre handler est celle
qui tourne.
Un compte non vérifié ne peut rien écrire. L'agent reçoit un refus propre et poli, qu'il vous rapportera comme une erreur mystérieuse ; il s'agit simplement de l'email d'inscription à valider. Même chose pour une invocation refusée en 402 : ce n'est pas une panne, c'est le solde.
Couper l'accès
La révocation se fait depuis la page MCP de votre tableau de bord, et elle invalide immédiatement le jeton d'accès déjà émis, pas seulement son renouvellement. La nuance a l'air théorique et ne l'est pas : sans elle, un agent garderait la main jusqu'à l'expiration de son jeton — jusqu'à une heure — pendant que l'interface afficherait « déconnecté ». Réinitialiser votre mot de passe coupe lui aussi tout accès MCP en cours, en plus de vos sessions web.
Ce que ça ne remplace pas
Trois limites, honnêtement :
- Ce n'est pas un accès administrateur. L'agent a exactement votre périmètre, ni plus, ni moins. Si vous attendiez qu'il règle un problème que vous ne pouvez pas régler vous-même, non.
- Ce n'est pas une revue de code. Un handler déployé par un agent est du code en production. Il mérite le même œil que le vôtre, surtout s'il est public et qu'il manipule ce qui arrive dans la requête.
- Quarante et un outils, c'est du contexte. Sur une conversation déjà longue, mieux vaut un client qui ne charge le détail d'un outil qu'au moment de s'en servir. Claude Code le fait.
Le reste tient en une phrase : la partie fastidieuse du déploiement — copier, coller, relancer, relire les logs — n'a jamais eu besoin d'un humain. Elle avait besoin d'une interface qu'une machine puisse appeler.
La référence complète du serveur, avec le tableau des outils et leurs portées, est sur la page MCP ; le tutoriel pas à pas, en quatre étapes, sur la page Claude Code. Et si vous préférez tout faire à la main, la documentation décrit la même chose côté API.
Essayez sur votre propre compte
L'inscription vient avec du crédit, de quoi déployer, planifier et mesurer tout ce qui précède sans sortir de carte bancaire.
Commencer »