add-webmcp

Par browserbase · skills

Analysez une application web existante, identifiez les capacités sûres visibles par l'utilisateur à travers les routes, formulaires, server actions, handlers et schémas, puis implémentez des outils WebMCP first-party et validez la découverte et l'invocation avec Stagehand. À utiliser lorsque l'utilisateur demande à rendre une codebase agent-ready, exposer les fonctionnalités d'un site web en tant qu'outils WebMCP, ou ajouter WebMCP directement à une application plutôt que de générer un script d'injection autonome à partir d'une URL.

npx skills add https://github.com/browserbase/skills --skill add-webmcp

Ajouter WebMCP

Transformez les capacités déjà implémentées par une application web en outils WebMCP maintenus et de première partie. Modifiez le codebase cible et ses tests ; n'introduisez pas de proxy hébergé ni de runtime tiers.

Compatibilité : le validateur Stagehand fourni nécessite Node.js 22.18 ou plus récent. La validation nécessite Chrome/Chromium localement ou une BROWSERBASE_API_KEY pour une prévisualisation accessible publiquement.

Soyez verbeux pendant votre travail : signalez ce que chaque étape découvre au fur et à mesure, pas seulement dans le rapport final.

Utilisez webmcp-gen quand la sortie demandée est un script d'initialisation autonome dérivé d'une URL en direct. Cette compétence part du code source et intègre les outils dans l'application.

1. Établir les limites de l'application

Lisez les instructions du référentiel cible, les manifestes de packages, la configuration du framework et l'état git actuel. Préservez les modifications non liées.

Définissez ADD_WEBMCP_SKILL_DIR sur le répertoire contenant ce fichier et exécutez le scanner délimité :

node "$ADD_WEBMCP_SKILL_DIR/scripts/scan-codebase.mjs" "$TARGET_REPO"

Traitez les résultats du scanner comme des pistes, pas comme des conclusions. Dans un monorepo, identifiez l'application browser réelle et les packages serveur qu'elle appelle avant de modifier.

2. Construire un inventaire des capacités

Tracez chaque candidat de son point d'entrée visible par l'utilisateur jusqu'au gestionnaire client, au schéma de validation, à la limite du serveur, aux vérifications d'autorisation, à l'effet et à l'état renvoyé. Examinez :

  • les routes et les écrans ;
  • les formulaires et leurs gestionnaires de soumission ;
  • les actions serveur, les gestionnaires API, les procédures RPC et les clients de service ;
  • les validateurs Zod, Valibot, Yup, Joi, JSON Schema ou équivalents ;
  • l'authentification, l'autorisation, le CSRF, l'idempotence, les limites de débit et les hooks d'audit.

Privilégiez les tâches utilisateur complètes comme search_catalog ou save_draft, pas un outil mécanique par endpoint. Excluez les opérations internes/réservées aux administrateurs, les contournements d'authentification, l'accès brut aux bases de données, les opérations portant des secrets et les capacités que l'interface utilisateur n'accorde pas à l'utilisateur actuel.

Pour chaque outil sélectionné, enregistrez ses fichiers source, sa validation existante et la limite d'autorisation, les effets secondaires, la classe de risque, le comportement de confirmation et une entrée fixture sûre. Consultez references/implementation-and-validation.md pour l'inventaire détaillé et les modèles de framework.

3. Concevoir le contrat d'outil

  • Utilisez un nom verbe-nom stable et décrivez l'effet visible par l'utilisateur, les conditions préalables et les exclusions importantes.
  • Dérivez le JSON Schema du validateur existant de l'application ou du type de domaine. Ne pas inventer un second contrat plus permissif. Fermez les schémas d'objet avec additionalProperties: false et faites le parser d'exécution rejeter également les champs inconnus ; un schéma de découverte fermé soutenu par un parser de runtime permissif n'est pas un contrat fermé.
  • Renvoyez des résultats compacts sérialisables en JSON. Ne pas retourner de nœuds DOM, identifiants, cookies, tokens ou documents HTML entiers.
  • Appelez la même limite client/service que l'interface utilisateur afin que la validation existante, l'autorisation, l'observabilité et les règles métier restent autoritaires.
  • Validez à nouveau à l'intérieur du gestionnaire. L'entrée fournie par l'agent n'est pas de confiance.
  • Ne jamais renvoyez la requête comme résultat. Lisez le résultat à partir de l'état propre de l'application, et quand cet état est mis à jour de manière asynchrone (React et la plupart des stores réactifs ne reflètent pas un changement à la ligne suivante), interrogez jusqu'à ce qu'il se stabilise avant de le lire, puis signalez ce qui est réellement vrai. L'écho transforme une non-opération silencieuse en test réussi.

Attribuez les annotations délibérément :

Risque Conception d'outil Annotation et comportement de confirmation
Lecture seule Pas de mutation d'état Enregistrez readOnlyHint: true ; ajoutez untrustedContentHint: true quand la sortie inclut du texte contrôlé par la page ou l'utilisateur
Mutation réversible Brouillons, préférences, modifications de panier Enregistrez readOnlyHint: false ; préservez l'auth/idempotence ; testez uniquement avec un état jetable
Conséquent ou irréversible Achat, envoi, publication, suppression, modifications de permissions Scindez aperçu/préparation de validation ; n'ajoutez pas de toolautosubmit déclaratif ; gardez l'action finale derrière le contrôle de confirmation réel de l'app

L'enregistrement utilise les noms de hints WebMCP actuels readOnlyHint et untrustedContentHint. Stagehand v4 normalise les annotations découvertes en readOnly, untrustedContent et, pour les formulaires déclaratifs, autosubmit. Ce sont des hints pour le navigateur ou l'agent, pas de l'application des règles de sécurité. L'application doit appliquer les permissions, la validation, la confirmation, l'idempotence et la protection contre la relecture.

4. Intégrer avec l'application

Utilisez le contexte du modèle runtime exposé par le navigateur :

const modelContext = navigator.modelContext || document.modelContext;

Gardez les deux accesseurs : Chrome actuel expose document.modelContext comme un ModelContext natif tandis que navigator.modelContext est undefined, donc le fallback est porteur plutôt que défensif. La surface est fournie par le navigateur et présente sur n'importe quelle page, donc l'application n'expédie aucun polyfill.

Enregistrez les outils impératifs à partir d'une racine/provider client-only après que l'application soit prête. registerTool retourne une promesse et est idempotent par nom — réenregistrer remplace la définition précédente plutôt que la dupliquer, et il n'y a pas de handle de désenregistrement — donc le remontage et le rechargement à chaud sont sûrs sans démontage. Utilisez les attributs de formulaire déclaratifs quand un formulaire existant représente déjà la tâche exacte et préserver une étape de révision visible est précieux.

Ne dupliquez pas la logique métier du serveur dans l'exécuteur d'outil. N'affaiblissez pas le CSRF, same-origin, l'auth ou les vérifications de confirmation pour faire passer un test de fumée. N'embarquez jamais de secrets dans le code navigateur.

5. Vérifier l'implémentation

Exécutez les tests ciblés du cible, vérifiez les types et construisez en production. Ensuite, créez un petit webmcp.e2e.json avec chaque outil attendu. La découverte est obligatoire ; l'invocation est opt-in par cas de test et doit utiliser des données synthétiques ou jetables.

Installez les dépendances du validateur une fois :

pnpm --dir "$ADD_WEBMCP_SKILL_DIR" install --frozen-lockfile

Validez localhost avec un navigateur lancé par Stagehand :

node "$ADD_WEBMCP_SKILL_DIR/scripts/validate-stagehand.mjs" \
  --url http://localhost:3000 \
  --config "$TARGET_REPO/webmcp.e2e.json" \
  --local

Les exécutions locales sont headed par défaut afin que le navigateur soit visible pendant la validation ; passez --headless pour les exécutions CI ou sans supervision.

Si la découverte rapporte zéro outil, vérifiez l'hôte avant de soupçonner le code : les serveurs de développement se lient couramment à localhost uniquement, donc --url http://127.0.0.1:PORT ne trouve rien tandis que http://localhost:PORT fonctionne. L'échec ressemble identiquement à des outils ne s'enregistrant jamais.

Utilisez --browserbase uniquement pour une prévisualisation déployée accessible publiquement. Le validateur utilise le vrai chemin page.tools(), tool.invoke() et invocation.result() de Stagehand v4. Il refuse les invocations conséquentes sauf si --allow-consequential est explicitement fourni.

Un script d'initialisation injecté est utile pour tester le validateur lui-même, mais ce n'est pas la preuve que l'app cible expédie ses propres outils. La preuve d'application finale doit s'exécuter sans --init-script.

6. Vérifier contradictoirement que les outils ont réellement fonctionné

L'étape 5 prouve que chaque outil est découvrable et que son exécuteur s'est exécuté. Elle ne prouve pas que l'outil a fait ce qu'il prétendait, et une configuration réussie n'est pas la preuve d'un contrat sain. Exécutez cette étape en dernier, après que l'étape 5 soit verte, et conduisez-la vous-même contre la page en direct plutôt que de l'encoder dans webmcp.e2e.json — le point est de sonder les entrées que l'auteur n'a pas anticipées.

Conduisez la page avec une session de navigateur persistante afin que les sondes s'accumulent contre un état réel. La CLI browse est l'option la plus légère — une installation globale, et la session survit entre les commandes :

browse open http://localhost:3000 --session probe --local --headed
browse eval --session probe '(async()=>{const mc=document.modelContext;const t=(await mc.getTools()).find(x=>x.name==="my_tool");try{return "ACCEPTED "+JSON.stringify(await mc.executeTool(t,JSON.stringify({/* probe input */})));}catch(e){return "REJECTED";}})()'
browse screenshot --session probe --path /tmp/effect.png

Trois choses coûteront du temps sinon : browse open utilise par défaut un navigateur cloud qui ne peut atteindre localhost, donc --local est requis ; browse eval accepte de manière fiable uniquement les scripts sur une seule ligne, donc exécutez une sonde par commande ; et executeTool prend l'objet d'outil plus les arguments comme une chaîne JSON — un objet simple échoue avec "Failed to parse input arguments".

Affirmez sur rejeté-versus-accepté, pas sur le texte d'erreur. La couche WebMCP remplace le message d'un gestionnaire par une chaîne d'invocation échouée générique, donc une raison précise ne parvient jamais à l'appelant.

Utilisez le tool.inputSchema découvert comme la chose testée, pas comme la source de vérité. Pour chaque outil, sondez :

  • Fermeture du schéma. Invoquez avec un champ supplémentaire que le schéma ne déclare pas. Un outil honorant §3 le rejette. L'acceptation signifie que le contrat fermé est décoratif.
  • Champs obligatoires. Omettez une propriété required. L'invocation doit échouer ; un statut Completed portant un résultat null ou partiel est pire qu'une erreur, car l'agent croit qu'il a réussi.
  • Types et contraintes. Envoyez une chaîne où le schéma dit number, une valeur hors limites contre minimum/maximum et une valeur en dehors d'un enum. La coercition silencieuse ou l'écho-retour signifie que le gestionnaire n'a jamais validé.
  • Honnêteté d'erreur. Confirmez qu'un outil qui devrait échouer rapporte un statut non-Completed plutôt que de retourner un corps en forme de succès.
  • Honnêteté des annotations. Comparez les annotations réelles de chaque outil par rapport au risque que vous avez attribué à l'étape 3. Une pure recherche annonçant readOnly: false, ou un outil mutant annonçant readOnly: true, est un défaut même si la découverte réussit.
  • Rejet propre. Après les sondes malformées ci-dessus, relisez l'état de l'application. Un appel rejeté ne doit rien laisser derrière ; un état partiel provenant d'une invocation demi-appliquée est un défaut que le résultat accept/reject seul ne surfacera pas.
  • Gating conséquent. N'invoquez jamais ceux-ci. Vérifiez que l'outil déclare son risque, qu'aucun toolautosubmit déclaratif n'est présent et que le contrôle de confirmation propre de l'app reste entre l'agent et l'effet.

Vérifiez ensuite l'effet, pas la valeur de retour. Invoquez l'outil, puis inspectez l'application indépendamment — des assertions DOM pour l'état rendu, une capture d'écran quand la surface est un canevas ou un graphique. Un gestionnaire qui retourne {saved: true} sans rien changer réussit l'étape 5 et échoue ici. Quand la surface n'a pas de DOM lisible, faites lire l'outil à partir du véritable store de l'application afin que la valeur retournée soit ancrée dans un état réel plutôt que composée par l'exécuteur.

Traitez chaque discordance comme un défaut dans l'application ou le contrat d'outil, et corrigez-le là. Ne relâchez pas un schéma, ne réduisez pas une annotation ou ne supprimez une sonde pour que cette étape réussisse.

7. Rapporter le résultat

Listez les capacités considérées et expliquez les exclusions. Pour chaque outil implémenté, rapportez son contrat, son chemin de code de soutien, son traitement des risques/confirmations, son résultat réel de découverte/invocation Stagehand et les sondes adversariales de l'étape 6 qu'il a surmontées. Indiquez tout support d'environnement ou de navigateur non testé.

Pour un benchmark comparatif, un audit de qualité ou une évaluation notée, consultez references/quality-rubric.md. Appliquez ses portes de qualification avant de rapporter des scores numériques ; ne laissez pas un score de diagnostic élevé dissimuler un comportement fabriqué, une limite de conséquence dangereuse ou une découverte de production manquante.

Skills similaires