- On affirme que la connexion d’outils via MCP est « l’avenir », mais en pratique, ses limites — manque de composabilité et consommation excessive de contexte — font que l’écriture directe de code reste plus efficace
- Même à l’ère des LLM, pour les tâches automatisées et répétitives, générer/exploiter du code reste supérieur en matière de fiabilité et de vérification
- Les LLM excellent davantage dans la génération de code et son exécution répétée que dans l’automatisation fondée sur l’inférence ; les processus basés sur le code sont meilleurs pour identifier les problèmes, vérifier les résultats et passer à l’échelle
- Avec certains outils comme Playwright (approche MCP), l’incertitude et la difficulté de débogage augmentent à chaque étape « fondée sur l’inférence », tandis que générer/modifier directement des scripts en code améliore à la fois la répétabilité, la vitesse et la fiabilité
- En pratique, la boucle « code → revue → itération », où un LLM génère le code puis un autre LLM l’examine et l’explique, constitue le flux d’automatisation le plus puissant
Le code suffit
- Si vous me suivez sur Twitter, vous savez sans doute que je ne suis pas très positif ces derniers temps à propos du Model Context Protocol (MCP)
- Ce n’est pas que je rejette l’idée en elle-même, mais plutôt que MCP n’est pas aussi efficace que ce que sa promotion laisse entendre
- MCP présente deux défauts majeurs
- il n’offre pas une vraie composabilité (composable)
- sa demande excessive de contexte entraîne une consommation de contexte supérieure à celle d’une simple écriture puis exécution de code
- On peut le vérifier avec une expérience simple
- par exemple, si l’on exécute une tâche avec le GitHub MCP puis la même avec l’outil en ligne de commande
gh, la seconde approche utilise bien mieux le contexte et atteint le résultat voulu plus rapidement
But MCP is the Future! : mais MCP, c’est l’avenir, non ?
- J’aimerais revenir sur les retours que j’ai reçus à propos de cette position (l’idée que le code est meilleur)
- J’ai expérimenté MCP en profondeur dans le contexte du codage agentique (agentic coding), et je l’ai évalué précisément là où ses limites apparaissent le plus clairement
- Un retour fréquent est que « MCP n’est pas vraiment nécessaire pour la génération de code généraliste, puisque les modèles sont déjà assez bons pour ça ». À l’inverse, on m’a aussi dit que MCP pouvait avoir du sens pour des applications orientées utilisateur final dans des domaines spécifiques (par exemple l’automatisation dans une entreprise financière)
- Un autre argument consiste à dire que, dans le futur, les modèles auront accès à davantage d’outils et pourront traiter des tâches plus complexes ; c’est cette possibilité qu’il faut regarder
- Mais voici mon jugement actuel : d’après mes données expérimentales et mon expérience concrète, le MCP actuel est toujours plus difficile à utiliser que l’écriture directe de code
- la raison principale est que MCP dépend de l’inférence
- quand on observe aujourd’hui « toutes les tentatives de connecter plus d’outils aux LLM », on finit toujours par ajouter une couche où le LLM reçoit tous les outils et les filtre selon la tâche
- jusqu’ici, personne n’a proposé d’architecture ou d’approche meilleure que celle-là
- J’en conclus donc ceci : même dans des cas particuliers comme l’automatisation de domaine spécifique pour non-développeurs, la génération de code reste au final un meilleur choix en matière de composabilité et de réutilisabilité
Replace Yourself With A Shellscript
- Une façon de voir le problème : sans IA, l’outil qu’un développeur utilise pour résoudre un problème, c’est le code
- Pour un non-développeur, le code est difficile, et beaucoup de tâches encore faites à la main peuvent en réalité être automatisées par logiciel
- Le vrai problème, c’est qui va écrire ce code. Si vous êtes dans un environnement particulier et ne savez pas programmer, il est difficile d’apprendre à coder de zéro, comme d’attendre que quelqu’un écrive du code sur mesure pour vous
- Bien sûr, certaines tâches peuvent vraiment exiger de l’inférence (jugement humain / flexibilité), mais dans les faits, la plupart des tâches répétitives et bien définies peuvent être automatisées par du code
- Il existe un vieux dicton de développeur : « se remplacer soi-même par un shell script », et ce type d’automatisation existe depuis longtemps
- À l’époque des LLM et de la programmation, on cherche à se remplacer non plus par un shell script, mais par un LLM, mais cela fait apparaître trois problèmes (coût, vitesse, fiabilité)
- Tant que ces trois problèmes ne sont pas résolus, il n’est même pas encore temps de se demander s’il faut utiliser des outils (MCP, etc.)
- Autrement dit, l’essentiel est d’abord de garantir que l’automatisation fonctionne réellement d’une manière correctement scalable
Automation at Scale : l’essence de l’automatisation à grande échelle
- Le cœur de l’automatisation, c’est de confier au code les tâches répétitives et réutilisables
- Une tâche qu’on ne fera qu’une seule fois n’a pas besoin d’être automatisée. L’automatisation commence avec les tâches répétées, celles où la machine apporte un vrai gain de productivité
- En pratique, on le fait une ou deux fois à la main, on formalise le fonctionnement, puis on fait exécuter la tâche des milliers de fois par la machine : c’est cela, l’automatisation
- Pour ce type d’automatisation répétitive, le mieux est toujours d’écrire du “code”
- si l’on demande au LLM de le faire à chaque fois par « inférence », cela fonctionne plus ou moins pour de petites tâches, mais le temps et l’effort nécessaires à la vérification finissent par annuler le bénéfice de l’automatisation
- exemple : au lieu de demander directement un calcul au LLM, il vaut mieux lui faire écrire du code Python, puis exécuter le calcul via ce code ; on y gagne à la fois en fiabilité et en capacité de passage à l’échelle
- avec du code, on peut examiner la formule ou la logique elle-même, la modifier si besoin, ou même demander à un LLM de vérifier si « cette approche est correcte »
- comme il n’y a pas lieu de craindre que Python se trompe dans le calcul, il devient clair que l’approche par génération de code est meilleure du point de vue de la vérification et de la confiance
- Cette logique va bien au-delà du simple calcul et s’applique aussi au travail réel de développement
- exemple : j’ai récemment converti tout le format de ce blog de reStructuredText vers Markdown
- je repoussais cela depuis assez longtemps ; ce n’était pas seulement pénible, c’est aussi que je ne faisais pas confiance à un LLM pour faire directement la conversion, de peur d’avoir des omissions subtiles, des erreurs ou des déformations de contexte
- j’ai donc fini par ne pas utiliser le LLM pour exécuter directement la conversion, mais pour générer le code de conversion, puis traiter le tout par code
LLM → code → LLM : la réalité de l’automatisation par validation itérative
- Première étape : j’ai demandé au LLM de générer la logique centrale de conversion de reStructuredText vers Markdown
- et pas une simple conversion : il devait utiliser directement un AST (arbre syntaxique abstrait) afin de
- parser le reStructuredText en AST → le convertir en AST Markdown → le rendre en HTML
- cela permet d’obtenir une étape intermédiaire de conversion, et donc de comparer et vérifier plus facilement le résultat
- Deuxièmement, j’ai aussi demandé au LLM d’écrire un script comparant l’ancien HTML et le nouveau HTML
- le script analyse la diff du HTML après conversion, tout en corrigeant automatiquement avant comparaison les différences mineures (par exemple les espaces ou la manière de gérer les notes de bas de page)
- je lui ai fait prendre lui-même en compte les types d’erreurs acceptables pendant la conversion
- par exemple, même si la représentation HTML diffère légèrement entre les bibliothèques Markdown et reStructuredText, le script est conçu pour ne remonter que les pertes ou erreurs essentielles
- Troisièmement, j’ai aussi demandé au LLM un script batch pour analyser en masse les résultats sur des centaines de fichiers
- avec ce script, j’ai fait tourner l’ensemble des fichiers et poursuivi les améliorations itératives (boucle agentique) jusqu’à réduction des écarts
- Le processus complet ressemblait à ceci :
- au départ, je n’ai lancé qu’une dizaine d’exemples, en itérant jusqu’à ce que les différences diminuent fortement
- une fois le résultat satisfaisant, je l’ai appliqué à l’ensemble des billets, pour un traitement automatisé d’environ 30 minutes
- le point clé, ce n’est pas que le LLM ait “réussi” la conversion en tant que telle, mais que je pouvais vérifier et relire l’ensemble du processus sous forme de “code”, ce qui le rendait digne de confiance
- Et en plus, j’ai demandé à un autre LLM d’examiner et d’expliquer le code généré ainsi que les modifications, ce qui a encore renforcé ma confiance
- j’avais l’assurance que la conversion se faisait correctement, mécaniquement, sans perte de données, et il était toujours facile d’échantillonner et corriger
- même dans le pire des cas, cela ne produisait que de petites erreurs de syntaxe Markdown, sans jamais abîmer le contenu réel du texte
- Un autre point important est que le coût d’inférence de cette approche reste constant, si bien que la différence de charge entre 15 et 150 fichiers reste faible
- lors de l’analyse finale, les écarts mineurs étant déjà ignorés automatiquement, la charge de validation itérative reste limitée même pour des conversions en volume
MCP Cannot Do That
- L’idée centrale de cette longue explication est que tout le pipeline de conversion et d’automatisation fonctionne en “code”
- entrée humaine → génération de code → revue par LLM → amélioration itérative : cette structure peut être appliquée telle quelle à des tâches générales
- Prenons par exemple Playwright, cas représentatif de l’approche MCP
- c’est un outil d’automatisation qui contrôle le navigateur à distance, lit la page, l’interprète, clique sur les boutons, etc. ; l’inférence se répète à chaque étape
- il est vrai que ce type de tâche n’est pas toujours entièrement remplaçable par une simple « approche code »
- Mais si l’on connaît déjà la structure de la page (par exemple pour tester sa propre application en cours de développement)
- il est bien plus rapide et plus fiable de demander au LLM de générer un script Python Playwright, puis de l’exécuter
- une fois le script créé, on peut le rejouer des dizaines ou des centaines de fois sans nouvelle inférence
- il n’est plus nécessaire d’interpréter l’écran en temps réel ni de retrouver la position des boutons à chaque fois, et l’ensemble du flux d’automatisation peut être exécuté d’un seul tenant
- L’approche MCP exige des appels d’outils abstraits et de l’inférence à chaque étape, ce qui rend très difficile le fait de faire en sorte que le LLM se comporte toujours correctement, et complique aussi énormément le débogage
- par exemple, même en voulant intégrer un client MCP dans un shell script pour appeler efficacement des services distants, je me suis rendu compte à quel point cette méthode était inefficace et difficile à mettre en œuvre
- Au final, je suis un humain, pas un client MCP
- le code est facile à exécuter et à déboguer, alors que les appels MCP restent incertains à chaque fois et ne sont pas fiables
- en pratique, j’utilise plutôt comme outils durables dans mon propre processus de développement les petits outils que le LLM produit pendant la génération de code (par exemple les snippets de Claude Code)
Où cette conclusion nous mène-t-elle ?
- Honnêtement, je ne sais pas moi-même où cette dynamique va nous conduire. Mais c’est précisément le bon moment pour réfléchir à la manière d’améliorer encore l’approche fondée sur la génération de code pour le “codage agentique intentionnel” (agentic coding)
- Cela peut sembler étrange, mais MCP fonctionne parfois vraiment très bien. Malgré tout, dans sa forme actuelle, il dépend trop de « l’inférence » et donne l’impression d’une impasse peu adaptée à l’automatisation à grande échelle et scalable
- Il faudra donc sans doute mieux séparer et abstraire les domaines où MCP a de vrais atouts et le rôle de l’approche par génération de code
- pour cela, il faudra aussi construire de meilleurs sandboxes (environnements d’exécution sûrs) et tenter de repenser les API pour permettre aux agents un raisonnement plus libre de type « fan out / fan in »
- je pense qu’il faut traiter autant que possible par du code tout ce qui peut l’être, puis laisser le LLM juger et relire le résultat global après l’exécution en masse
- Et si, pendant le processus de génération de code, on ajoute suffisamment de contexte pour que le LLM puisse expliquer en langage naturel à des non-développeurs ce que fait le script généré, alors ce flux d’automatisation pourra à l’avenir être utilisé facilement aussi par des non-développeurs
- En conclusion, je recommande d’exploiter plus franchement les capacités de génération de code des LLM à la place de MCP, et d’expérimenter de nouvelles possibilités
- Si l’on laisse les LLM écrire directement du code, on peut automatiser bien plus de choses qu’on ne l’imagine
Références
2 commentaires
Je suis d’accord, mais je pense que le problème tient moins à MCP lui-même qu’au lieu où il est conçu, ou plutôt à l’optimisation de la direction de conception. Même pour une même fonctionnalité, selon le type de MCP, il génère en interne du code et des commandes, ce qui réduit les opérations inutiles. Si l’on utilise non pas le GitHub MCP mais le
gh cli mcpou le terminal MCP, on consomme certes des tokens, mais bien moins, tout en obtenant le même effet. J’ai l’impression que cet aspect a été négligé.Avis Hacker News
Globalement, je suis d’accord avec l’idée que c’est la bonne direction. L’usage de grands LLM sert souvent à combler l’écart entre deux interfaces robustes. Le cœur de la fiabilité ne vient pas du résultat du LLM, mais du fait que les interfaces elles-mêmes n’autorisent que certains réglages précis.
La sortie du LLM est souvent forcée vers des valeurs plus déterministes, comme des types ou des primary keys de base de données. La valeur d’un LLM dépend énormément de la qualité avec laquelle le code et les outils existants modélisent les données, la logique et les comportements de mon domaine.
Personnellement, les LLM me font de plus en plus penser aux imprimantes 3D. Dans les deux cas, ils permettent de relier rapidement des pièces pour du prototypage rapide, mais si on veut de l’échelle et de la robustesse, il faut au final que des ingénieurs ou les LLM eux-mêmes remplacent ces raccords temporaires par des supports déterministes comme du métal ou du code.
Comme pour les attentes exagérées qu’on a eues autrefois sur les imprimantes 3D, les LLM donnent l’impression qu’ils pourraient remplacer toutes les réalités opérationnelles, alors qu’en pratique ils ne deviennent vraiment utiles que lorsque la modélisation numérique existante constitue une base solide
J’ai réalisé quelque chose en utilisant des outils LLM. Si on réduit le problème à une forme que le LLM peut résoudre dans un sandbox, en utilisant des outils de façon itérative, alors on peut le résoudre par brute force. La clé, c’est d’identifier ce type de problème et de définir le bon sandbox, les bons outils à utiliser, ainsi que les critères de réussite.
Ce processus demande lui aussi beaucoup de compétence et d’expérience, mais c’est d’un niveau bien supérieur au simple fait de tâtonner manuellement.
C’est ce que j’ai compris en faisant mon « expérience Mandelbrot en assembleur ».
(Lien de l’expérience : https://simonwillison.net/2025/Jul/…)
Idéalement, il faut une métrique d’évaluation sous forme de fonction continue, ou au minimum divers jeux d’entrée avec leurs sorties attendues quantifiées, pour que cela devienne réellement automatisable
Par exemple, les LLM sont faibles avec les génériques TypeScript, mais si on fait réellement tourner TSC, on peut continuer à tester jusqu’à ce qu’ils trouvent la bonne solution. La maintenabilité du code risque d’en souffrir, mais en théorie c’est une structure très intrigante.
Et comme Cursor peut voir les erreurs TypeScript, il suffit de créer des tests de types utilitaires pour que Cursor écrive lui-même les tests et résolve le problème par simple brute force répétée
Rapport intéressant à consulter : https://github.com/davidkimai/Context-Engineering/…
Je ne l’ai pas encore lu en entier, mais c’est assez impressionnant
Je me demande si c’est aussi faisable avec des modèles locaux, ou via un abonnement comme Claude Code Pro.
L’expérience Mandelbrot était amusante, mais la difficulté n’est pas vraiment la même qu’avec une base de code commerciale complexe
Je ne pense pas que ce soit un problème propre à MCP. Au niveau actuel de l’IA, une structure avec intervention humaine est bien meilleure.
Les LLM sont très bons pour certaines tâches, mais restent souvent coincés dans des minima locaux. Donc quand on fait des allers-retours dans une interface web avec une boucle du type « écris-moi un programme → vérification et indices → test », la qualité s’améliore clairement.
On peut transformer 10 000 lignes de code désordonné en 400 lignes de code clair. Pour l’instant, c’est ça la réalité.
Bien sûr, beaucoup d’entreprises ou de développeurs veulent « remplacer complètement les programmeurs par des LLM », mais ce n’est pas encore possible dans le monde réel.
Le vrai effet, c’est de multiplier la vitesse de travail des programmeurs, ou de permettre à des débutants de devenir rapidement productifs grâce aux LLM. Mais le « agentic coding » ne fonctionne pas encore bien.
Aujourd’hui, la bonne façon d’utiliser les LLM, c’est comme collègues ou assistants. En pratique, ce ne sont pas encore des « agents IA » autonomes sans boucle de feedback
Je travaille dans un langage compilé, type-safe et fonctionnel, donc je dois de toute façon toujours relire le résultat, et je pense que ce serait encore plus inquiétant dans un langage moins strict.
Malgré cela, le gain de temps est important. J’apprécie surtout le fait de pouvoir découper le travail et rendre des objectifs ambitieux plus faciles à traiter
En pratique, quand j’essaie d’effectuer une tâche avec GitHub MCP et que je fais la même chose avec gh CLI, gh CLI utilise bien plus efficacement le contexte, donc c’est beaucoup plus rapide.
J’ai un fichier CLAUDE.md dans un dossier « devops » qui contient un recueil de commandes bash communes.
Quand une nouvelle tâche est terminée, je demande à Claude d’y ajouter un exemple, puis pour des requêtes similaires ensuite, Claude les résout d’un seul coup.
Contenu initial partagé de CLAUDE.md :
(Les commandes concrètes sont résumées)
Au final, c’est devenu une forme de logiciel auto-réparant, où en cas de problème j’ajoute à la commande des instructions pour tester et corriger l’application
Parmi tous les usages de MCP que j’ai vus jusqu’ici, le plus impressionnant est clojure-mcp de Bruce Hauman.
Il fournit au LLM (a) bash, (b) un REPL Clojure persistant, et (c) des outils d’édition structurelle.
Grâce à cela, l’édition de code Clojure fonctionne bien plus efficacement qu’avec une approche purement basée sur des diff textuels.
Avec une bonne suite de tests, voir le LLM éditer des fichiers, recharger, puis relancer les tests en boucle d’une manière proche du travail humain m’a vraiment surpris
Il prend en charge des fonctions essentielles comme le debug du code, l’évaluation d’expressions individuelles ou la documentation des types de retour de fonctions.
J’ai eu l’impression que les langages dotés d’un REPL puissant étaient bien supérieurs sur ce plan, et voir ce qu’on peut faire avec clojure-mcp a profondément changé mon regard sur l’IA
L’exemple de GitHub CLI ne montre pas pleinement les points forts de MCP.
Avec des outils comme gh CLI, dont la documentation est facilement accessible, il est logique qu’un LLM les exploite mieux puisqu’il peut facilement générer le code correspondant.
Mais le véritable avantage de MCP apparaît avec des outils internes ou des API de niche pour lesquelles il existe peu ou pas de documentation en ligne.
On peut toujours injecter toute la documentation dans le contexte, mais dans ce genre de situation MCP est au contraire plus efficace.
Si l’on utilise un outil MCP bien conçu avec les bonnes entrées, cela réduit fortement la charge liée à la compréhension de l’API par le LLM, à l’authentification ou à la gestion des edge cases.
GitHub n’a sans doute pas vraiment besoin de MCP, mais dans des environnements comme des API internes ou incomplètes, des outils MCP préparés à l’avance sont bien plus puissants
Par exemple, avec sonnet4, on atteint déjà une limite au-delà d’une quinzaine d’outils. Rien qu’utiliser le MCP Playwright officiel consomme déjà de la capacité côté outils
Au final, l’unique avantage de MCP pourrait être de reconfirmer qu’une API qui semblait difficile était en réalité simplement trop complexe
À propos de l’exemple Playwright,
moi aussi j’ai créé cette semaine un agent basé sur le serveur MCP Playwright, puis je suis revenu à des appels directs à Playwright parce que c’était lent, inefficace en tokens et peu fiable.
Le serveur MCP est utile pour tester ce qui est possible, mais en pratique les appels d’API sont plus efficaces et plus stables.
Je partage un exemple et une démo de l’agent LinkedIn personnel que j’ai créé :
LinkedIn est réputé pour être une plateforme extrêmement difficile à automatiser ; je serais curieux de savoir si vous avez rencontré des difficultés ou des limitations en créant votre agent LinkedIn personnel
En réalité, j’ai l’impression qu’un simple terminal suffit.
J’ai utilisé MCP tous les jours pendant plusieurs mois, mais maintenant je n’utilise plus qu’un seul serveur MCP basé sur iTerm2, autrement dit le terminal.
Au besoin, on peut avoir une spec OpenAPI, mais en pratique presque tout se fait avec des commandes shell et
curlLa critique « il faut trop de contexte » se règle en réalité surtout par un bon paramétrage des prompts initiaux.
Tous les grands outils, y compris Claude Code et Gemini CLI, le prennent en charge
Transmettre au LLM toute la liste des outils pour le laisser faire le tri lui-même n’est peut-être pas l’approche idéale, mais
les LLM récents continuent de progresser, et en pratique je n’ai jamais eu de grosse difficulté à choisir la bonne fonction MCP.
Quant aux problèmes de coût, de vitesse et de fiabilité :
Il n’est pas nécessaire d’y consacrer soi-même du temps de conversation
Comme exemple récent, le LLM a géré automatiquement un grand nombre d’outils externes comme Notion, Linear, git, les PR GitHub et les logs CI,
et je n’ai eu à faire qu’une seule revue de PR.
Le coût est resté inférieur à 1 dollar
Ajouter des outils peut au contraire accroître les informations nécessaires au départ, ce qui peut devenir une contrainte sérieuse
c’est surtout encore masqué, et cette structure de promotions gratuites ou bon marché ne durera pas.
Par exemple, Cursor a déjà introduit une offre à 200 $ par mois, et la qualité de service des offres bon marché se dégrade.
Une fois les promotions terminées, on reviendra au niveau normal
Je travaille avec Julia, et j’ai bénéficié d’un environnement à sessions longue durée.
Comme les fonctions sont compilées à leur première exécution, j’ai créé un MCP pour que Claude Code envoie le code vers un kernel Julia persistant (Jupyter).
L’exécution des tests est bien plus rapide, et CC utilise mieux les fonctions existantes de la base de code au lieu d’écrire du bash sur mesure.
D’après CCUsage, l’usage de tokens a aussi baissé de près de 50 %.
Il n’était pas absolument nécessaire de passer par MCP, mais l’idée principale est qu’il est plus facile de rattacher une « capacité donnée » à la base de code que d’écrire à la main du code personnalisé pour Claude à chaque fois