Playwright MCP : lancer un build Chromium personnalisé
Configurez un serveur Playwright MCP pour lancer un build Chromium précis avec son profil, puis prouvez depuis la session quel exécutable a réellement démarré.
BotBrowser Team
Vous voulez la documentation structurée pour Déploiement ?
Cet article fait partie de la bibliothèque éditoriale. Pour les étapes de configuration, la référence et les mises à jour continues, passez directement à la section docs.
Un serveur Playwright MCP se place entre un client d’agent et un navigateur, et le navigateur qu’il démarre dépend d’une configuration qu’il est facile de laisser sans inspection. Quand la configuration est correcte, l’agent pilote le build et le profil choisis par l’opérateur. Quand elle est fausse, le serveur démarre son propre Chromium embarqué et signale un succès, si bien qu’un agent peut mener une tâche entière contre un navigateur que personne n’avait l’intention d’utiliser. Les clés de configuration qui portent un exécutable personnalisé, la relecture qui prouve quel binaire a démarré et le mode de défaillance où l’argument de profil est silencieusement perdu forment le cœur opérationnel de la mise en route. Playwright MCP est un projet Microsoft avec son propre cycle de publication, et la configuration ci-dessous est documentée d’après son schéma publié. BotBrowser prend en charge executablePath et un argument de profil depuis tout lanceur compatible Playwright, et il ne fournit aucun serveur MCP, donc il ne peut pas corriger un serveur qui ne transmet jamais l’option.
TL;DR
- Placez l’exécutable dans
browser.launchOptions.executablePath, pas dans une clé de premier niveau. Le schéma de configuration MCP imbrique leLaunchOptionsde Playwright sousbrowser, et une clé de premier niveau inconnue est ignorée plutôt que rejetée. - Deux autres voies existent et sont plus faciles à confondre : l’option
--executable-pathet la variable d’environnementPLAYWRIGHT_MCP_EXECUTABLE_PATH. Choisissez une seule voie par déploiement, sinon une valeur obsolète l’emporte. - L’argument de profil va dans
launchOptions.argscomme élément de tableau distinct, parce que Playwright transmet chaque élément comme un argument propre. - Prouvez le binaire depuis la session : lisez
navigator.userAgent, le chemin du processus rapporté par le serveur et un marqueur exposé par le build personnalisé. Un serveur retombé sur son Chromium embarqué répond différemment sur les trois. - Gardez une instance de serveur MCP par profil. Un profil persistant est verrouillé sur une seule instance de navigateur, donc deux clients partageant un espace de travail entrent en conflit au lieu de s’isoler.
Sommaire
- Où se place le chemin de l’exécutable
- Transmettre le profil sans le perdre
- Prouver quel binaire a démarré
- Modes de défaillance et branche de repli
- Conclusion pratique
Où se place le chemin de l’exécutable
Le fichier de configuration MCP est un document JSON contenant un objet browser. Dans cet objet, launchOptions est typé comme le LaunchOptions de Playwright, le même type qu’un script Playwright direct passe à browserType.launch. C’est là que vit executablePath, et c’est la seule imbrication que le serveur lit.
{
"browser": {
"browserName": "chromium",
"launchOptions": {
"executablePath": "/opt/botbrowser/chrome",
"headless": true,
"args": ["--bot-profile=/etc/botbrowser/profile.enc"]
},
"contextOptions": {
"viewport": { "width": 1280, "height": 800 }
}
}
}
Trois propriétés de ce bloc comptent plus que les autres. browserName reste chromium, parce qu’un build Chromium personnalisé parle toujours le protocole Chromium et que les autres valeurs (firefox, webkit) orienteraient vers un autre pilote. headless appartient à launchOptions et non à côté de browserName, puisque le serveur transmet l’objet entier à l’appel de lancement. args est un tableau de chaînes séparées, et chaque élément devient un argument ; une chaîne unique contenant un espace n’est pas découpée.
| Voie | Où va la valeur | L’emporte sur | Erreur typique |
|---|---|---|---|
| Fichier de configuration | browser.launchOptions.executablePath | Rien d’autre, sauf si une option ou une variable est aussi définie | Écrire executablePath au premier niveau du fichier |
| Option de ligne de commande | --executable-path /path/to/chrome | Le fichier de configuration | Croire que l’option définit aussi browserName |
| Variable d’environnement | PLAYWRIGHT_MCP_EXECUTABLE_PATH=/path/to/chrome | Le fichier de configuration | Une valeur obsolète héritée d’un profil de shell |
Les trois voies sont des alternatives, pas des couches. Un déploiement qui définit le fichier de configuration et exporte aussi la variable d’environnement possède deux sources de vérité, et celle que le serveur lit en dernier détermine le navigateur. Choisissez-en une et vérifiez que les autres sont absentes de l’environnement de lancement.
Pourquoi une clé inconnue échoue en silence
Le serveur valide la forme qu’il connaît et ignore ce qu’il ne reconnaît pas. Une configuration qui place executablePath au premier niveau, l’écrit executable_path, ou l’imbrique sous contextOptions au lieu de launchOptions, produit un serveur qui démarre normalement et un navigateur qui n’est pas celui visé. Rien dans le journal de démarrage ne le dit nécessairement, parce que du point de vue du serveur la configuration était valide et le lancement a réussi.
Ce comportement explique pourquoi la relecture de la section suivante n’est pas facultative. Traiter un démarrage réussi comme preuve du binaire visé est l’échec le plus facile à manquer, et elle échoue dans la direction qui compte : l’agent travaille, la tâche se termine, et le navigateur était le mauvais.
Les options de contexte sont distinctes
contextOptions est un autre objet et porte BrowserContextOptions, pas LaunchOptions. La taille de la fenêtre, la langue, le fuseau horaire, le schéma de couleurs et les permissions y appartiennent. Déplacer executablePath dans contextOptions produit une option de contexte invalide qui est ignorée, et le navigateur retombe sur le build embarqué.
La séparation mérite d’être retenue parce que les deux objets semblent interchangeables dans un fichier JSON plat. Une habitude utile consiste à relire le fichier avant le lancement et à vérifier que browser.launchOptions.executablePath est une chaîne qui existe sur le disque et est exécutable, et que browser.contextOptions ne contient aucune valeur de forme chemin.
Priorité entre les trois voies
Quand plusieurs voies définissent un chemin, le résultat dépend de celle que le serveur lit en dernier, et cet ordre ne se devine pas. Le schéma sûr consiste à rendre les deux autres impossibles : ne pas définir PLAYWRIGHT_MCP_EXECUTABLE_PATH dans l’environnement qui démarre le serveur, et ne jamais passer --executable-path sur la ligne de commande quand le fichier de configuration porte déjà la valeur.
Une vérification concrète coûte une commande dans l’environnement de lancement : afficher la variable et confirmer qu’elle est vide, puis démarrer le serveur. Un profil de shell qui exporte la variable pour un projet sans rapport est une cause fréquente d’un serveur qui démarre le navigateur embarqué malgré un fichier de configuration correct, parce que les surcharges d’environnement sont fusionnées après la lecture du fichier de configuration, donc la valeur héritée l’emporte.
Le même raisonnement vaut pour un script d’enveloppe qui assemble la ligne de commande. Si l’enveloppe ajoute --executable-path depuis une variable vide dans un environnement donné, l’option peut disparaître entièrement, laissant le fichier de configuration comme seule source. C’est le résultat souhaitable, et il vaut la peine d’écrire l’enveloppe pour omettre l’option plutôt que la passer vide.
Transmettre le profil sans le perdre
Un profil n’est pas une option de lancement que Playwright connaît. C’est un argument du navigateur, donc il voyage dans launchOptions.args comme élément de tableau propre. Un script Playwright direct l’écrit de la même façon, ce qui explique que le profil soit la pièce la plus souvent perdue quand un script qui fonctionne est converti en configuration MCP.
{
"browser": {
"browserName": "chromium",
"launchOptions": {
"executablePath": "/opt/botbrowser/chrome",
"args": ["--bot-profile=/etc/botbrowser/profile.enc", "--bot-locale=en-US"]
}
}
}
Chaque argument est un élément de tableau, sans guillemets de shell autour. "--bot-profile=/etc/botbrowser/profile.enc" et "--bot-profile=/etc/botbrowser/profile.enc --bot-locale=en-US" ne sont pas équivalents : le second est un argument unique contenant un espace, et le navigateur le reçoit comme une option malformée au lieu de deux.
D’où le profil est lu
Le fichier de profil doit être lisible par le processus que le serveur engendre, qui n’est pas toujours celui que l’opérateur a démarré. Un serveur lancé par un client de bureau hérite de l’environnement de ce client, et un serveur lancé dans un conteneur ne voit que ce qui a été monté. Un chemin qui fonctionne dans un shell interactif peut donc échouer au lancement MCP, et l’échec peut se manifester comme un navigateur démarré avec les valeurs par défaut plutôt que comme une erreur.
Résolvez le chemin absolu une fois, dans le même environnement qui démarre le serveur, et enregistrez-le à côté de la configuration. Les chemins relatifs sont résolus par rapport au répertoire de travail du serveur, que le client choisit et que l’opérateur définit rarement volontairement.
Une instance de serveur, un profil
Un profil persistant ne peut être utilisé que par une instance de navigateur à la fois. Deux clients MCP pointés sur le même profil, ou un client et une session de navigateur manuelle partageant le même répertoire de données utilisateur, entrent en conflit : l’un des deux échoue au démarrage ou s’attache à l’état de l’autre. Le commutateur d’isolation change cela en gardant le profil en mémoire, mais il jette aussi le profil à la fermeture, donc c’est un mode différent plutôt qu’une correction.
| Intention | Réglage | Conséquence |
|---|---|---|
| Un client, un profil fixe | Profil persistant plus une instance de serveur | Le profil est verrouillé sur cette instance |
| Plusieurs clients en parallèle | Mode isolé ou répertoire de données utilisateur distinct par client | Aucun état partagé ; le profil ne survit pas à un redémarrage |
| Réutiliser un navigateur déjà lancé | Se connecter à un point d’accès existant | Le serveur ne lance pas du tout l’exécutable configuré |
La troisième ligne est le piège d’un déploiement sur build personnalisé. Se connecter à un point d’accès existant contourne entièrement le chemin de lancement, donc l’executablePath de la configuration n’est jamais consulté. Une équipe qui ajoute un point d’accès CDP pour accélérer le démarrage peut perdre silencieusement le build personnalisé sans changer aucune option de lancement.
État du profil et ce qu’un redémarrage perd
La différence entre un profil persistant et un profil isolé ne tient pas qu’au stockage. Un profil persistant porte les cookies, le stockage local et l’état mis en cache qu’un site utilise pour reconnaître un visiteur qui revient. Un profil isolé démarre propre à chaque fermeture du navigateur, donc une tâche qui dépend d’une session authentifiée doit injecter cet état explicitement au lieu de supposer qu’il survit.
Pour une charge de surveillance ou de test, c’est le bon compromis, parce qu’un démarrage propre rend deux exécutions comparables. Pour une charge qui doit rester connectée, le profil persistant est nécessaire, et la restriction d’instance unique devient une contrainte d’exploitation plutôt qu’une gêne. Enregistrer le mode utilisé à côté du chemin de profil évite qu’une comparaison ultérieure entre une exécution isolée et une exécution persistante soit traitée comme une différence de comportement.
Prouver quel binaire a démarré
La seule vérification fiable s’exécute dans la session que l’agent pilote. Trois lectures ensemble distinguent le build visé du repli embarqué, et chacune est peu coûteuse.
La première est la chaîne d’agent utilisateur. Un build personnalisé peut rapporter une version de Chromium différente de celle du build embarqué, ou rapporter un agent utilisateur configuré qui ne correspond à aucun build, donc cette lecture corrobore au lieu de décider. Un Chromium embarqué par Playwright rapporte la version livrée avec le paquet installé. Les deux diffèrent, et la différence est visible depuis une seule lecture de navigator.userAgent.
La deuxième est le chemin d’exécutable rapporté par le processus. Là où le build l’expose, lisez-le depuis la page ; là où il ne l’expose pas, lisez-le dans la liste des processus du serveur sur l’hôte qui l’a engendré. Dans les deux cas la valeur doit égaler le chemin de la configuration, caractère pour caractère.
La troisième est un marqueur que le build personnalisé définit et qu’un build standard ne définit pas. Cela peut être une propriété supplémentaire sur un objet d’API du navigateur, une chaîne de version dans un espace de noms propre au produit, ou un indicateur de capacité documenté. Le marqueur est le plus fort des trois parce qu’il ne peut pas être produit par un numéro de version fortuitement proche.
| Lecture | Réponse du build visé | Réponse du repli embarqué | Où la lire |
|---|---|---|---|
navigator.userAgent | La version de Chromium du build personnalisé | La version embarquée par Playwright | N’importe quelle page de la session |
| Chemin d’exécutable du processus | Le chemin configuré | Un chemin sous le cache Playwright | Liste des processus du serveur, ou une lecture de page là où il est exposé |
| Marqueur du build personnalisé | Présent | Absent ou valeur par défaut | Un script de page qui lit la propriété précise |
Une relecture qui ne vérifie que la première lecture est faible, parce qu’un build personnalisé peut partager une chaîne de version avec le build embarqué. Une relecture qui ne vérifie que la troisième est faible aussi, parce qu’elle prouve une capacité plutôt que l’identité du processus qui sert la page. Vérifiez le chemin et le marqueur, et utilisez l’agent utilisateur comme corroboration.
Une relecture que l’agent peut exécuter lui-même
La vérification n’a pas besoin d’un harnais séparé. Demandez au client d’évaluer une courte expression dans la session et de renvoyer le résultat ; l’agent peut le comparer au chemin configuré sans quitter la conversation. Ce qui compte est que la comparaison soit explicite et enregistrée, pas qu’elle soit automatisée.
Enregistrez trois valeurs par session : le chemin configuré, le chemin observé et le résultat du marqueur. Une session dont le chemin correspond et dont le marqueur est présent correspond au build visé. Une session dont le chemin diffère est le repli, quoi que dise l’agent utilisateur.
Lire le chemin quand le build ne l’expose pas
Tous les builds n’exposent pas leur propre chemin d’exécutable au script de page, et un build qui ne l’expose pas n’est pas défectueux. Là où la page ne peut pas répondre, lisez la liste des processus sur l’hôte qui a engendré le serveur et identifiez le processus enfant du serveur. La relation parent-enfant est la partie à vérifier : une machine peut exécuter plusieurs processus Chromium, et celui qui compte est le descendant du serveur MCP, pas un navigateur que l’opérateur a ouvert à la main.
Un marqueur au niveau de la page reste le signal positif le moins coûteux, donc il vaut la peine de demander au fournisseur du build quelle propriété est stable plutôt que d’en extraire une accessoire. Un marqueur qui change entre versions mineures est pire que pas de marqueur, parce qu’il produit un faux négatif qui ressemble à un repli.
Modes de défaillance et branche de repli
Les défaillances se regroupent en un petit ensemble, et chacune a une signature distincte. Les nommer transforme le diagnostic en consultation plutôt qu’en expérience.
| Symptôme | Cause | Confirmation | Correction |
|---|---|---|---|
| Le navigateur démarre, mauvaise version dans l’agent utilisateur | executablePath non lu | Le fichier porte la clé au premier niveau ou sous contextOptions | La déplacer dans browser.launchOptions |
| Le navigateur démarre, réglages de profil absents | Argument de profil perdu ou malformé | args contient une chaîne avec un espace au lieu d’éléments séparés | Découper en un élément de tableau par option |
| Le serveur sort avec une erreur de lancement | Chemin configuré absent ou non exécutable | Le chemin ne se résout pas dans l’environnement du serveur | Utiliser un chemin absolu lisible par le processus qui engendre |
| Le second client ne peut pas démarrer un navigateur | Profil persistant déjà verrouillé | Les deux clients pointent sur le même répertoire de données utilisateur | Isoler, ou donner à chaque client son propre répertoire |
| Build personnalisé ignoré après une accélération du démarrage | Un point d’accès existant a été configuré | La configuration liste encore un point d’accès | Retirer le point d’accès pour que le chemin de lancement s’exécute |
Les deux premières lignes sont celles qui produisent un agent fonctionnel contre le mauvais navigateur, et ce sont aussi celles qu’un journal de démarrage ne signalera pas. Les trois autres échouent assez fort pour être remarquées, ce qui en fait la moitié la moins coûteuse du problème.
Ce que le client voit et ne voit pas
Un client MCP voit les outils que le serveur expose : navigation, instantané, clic, saisie, et tout ce que le serveur publie. Il ne voit pas la configuration de lancement, le processus engendré ni les arguments transmis. Cette asymétrie est la raison pour laquelle la relecture doit être demandée à travers la session plutôt que supposée du côté client.
Elle explique aussi pourquoi un client ne peut pas détecter le repli tout seul. Le partage des responsabilités entre une boucle d’agent et le processus du navigateur est traité dans navigateur headless pour agents IA, le script direct que cette configuration doit reproduire, avec executablePath et --bot-profile dans launchOptions.args, se trouve dans le guide de démarrage Playwright, et la forme plate de l’objet de lancement attendue par un serveur Puppeteer est traitée dans configuration du serveur MCP Puppeteer. Du point de vue du client, le serveur fonctionne correctement, parce que c’est le cas : le serveur a démarré un navigateur et sert des outils dessus. La seule partie qui sait quel navigateur était visé est l’opérateur qui a écrit la configuration.
Enregistrer le résultat d’une vérification
Une vérification qui n’est pas écrite est une vérification qui sera répétée. Stockez le chemin configuré, le chemin observé, le résultat du marqueur et l’horodatage ensemble, pour qu’une session ultérieure puisse comparer sans redéduire ce que « correct » signifiait à ce moment. Quand la configuration change, l’enregistrement rend le changement visible au lieu de le laisser silencieux.
C’est la même discipline qu’un lancement Playwright direct, et la raison pour laquelle elle compte davantage sous un serveur MCP est que le lancement se situe une couche plus loin de la personne qui a écrit les options. Le client ne voit pas cette couche, donc l’enregistrement est la seule preuve durable que la couche était configurée comme prévu.
FAQ
Playwright MCP lit-il executablePath au premier niveau du fichier de configuration ?
Non. Le schéma imbrique le LaunchOptions de Playwright sous browser.launchOptions, et une clé de premier niveau ne fait pas partie de cette forme. Le serveur ignore ce qu’il ne reconnaît pas, donc une clé mal placée produit un démarrage normal avec le navigateur embarqué plutôt qu’une erreur de validation.
Un serveur MCP peut-il servir plusieurs profils à la fois ?
Pas à travers un seul profil persistant. Un profil persistant est verrouillé sur une instance de navigateur, donc des clients parallèles ont besoin du mode isolé ou de répertoires de données utilisateur séparés. Le mode isolé garde le profil en mémoire et le jette à la fermeture, ce qui est un compromis différent plutôt qu’un moyen de partager un profil.
Un agent utilisateur identique suffit-il à prouver que le bon build a démarré ?
Non. Un build personnalisé peut rapporter la même version de Chromium que le build embarqué, donc une correspondance de version est une corroboration et non une preuve. Comparez le chemin d’exécutable du processus avec le chemin configuré, et lisez un marqueur que seul le build personnalisé expose.
Conclusion pratique
Écrivez l’exécutable dans browser.launchOptions.executablePath, placez chaque option de profil et de langue dans son propre élément args, et choisissez exactement une des trois voies capables de définir le chemin. Demandez ensuite à l’agent de relire le chemin du processus et un marqueur propre au build avant tout travail réel.
L’action suivante tient en une session : démarrer le serveur avec la configuration, demander au client de renvoyer navigator.userAgent et le chemin d’exécutable observé, puis comparer les deux avec le fichier. Si le chemin correspond, l’installation est prouvée. Sinon, le serveur exécute son Chromium embarqué et chaque résultat de cette session décrit un navigateur que vous n’avez pas choisi. Deux surfaces voisines portent le même problème de vérification : la configuration d’un navigateur headless pour agents IA traite le passage de l’agent au navigateur, et le guide de démarrage Playwright traite le script direct que la configuration MCP doit reproduire.
Sources
Cet article fait partie du guide : Déploiement et livraison du navigateur : carte opérationnelle
Articles Connexes
Puppeteer MCP : configurer un build Chromium propre
DémarrageNavigateur headless pour agents IA : lancement et limites des outils
DéploiementAutomatiser le navigateur avec Stagehand
DémarrageConfigurer browser-use avec un navigateur contrôlé
DémarragePlaywright avec des profils d'identité cohérents
DémarrageDébuter avec l'automatisation du navigateur : carte initiale
Exécutez la même vérification dans BotBrowser
Chargez un profil, gardez dans le navigateur les signaux que vous venez de lire, puis confirmez le résultat sur votre propre machine avant le déploiement.