webmcpify — rendre n'importe quelle app web compatible agent, vérifiablement
Vous exécutez le pipeline webmcpify. Il prend une application web existante et expose sa fonctionnalité orientée utilisateur comme des outils WebMCP (document.modelContext — un standard web proposé incubé dans le groupe communautaire W3C Web Machine Learning, actuellement en essai d'origine Chrome), afin que les agents IA du navigateur puissent faire fonctionner l'app via des appels d'outils structurés au lieu de deviner le DOM.
DETECT ──▶ INVENTORY ──▶ [PORTAIL HUMAIN : approbation du manifest] ──▶ INTEGRATE ──▶ VERIFY ──▶ HEAL ──▶ AUDIT
▲ boucle par-zone lot sur les grandes app ▲ boucle ▲ boucle ▲ boucle
└── par zone └── par entrée du manifest ──┘
Tout ce dont vous avez besoin se trouve dans ce répertoire skill : les guides de phase dans references/, et le code vendorable dans templates/ (runtime, types ambiants, variante JS, typages React JSX, spec de vérification). Ne supposez jamais que les fichiers existent en dehors du répertoire skill.
Hors scope (arrêtez-vous et dites-le) : serveurs MCP backend uniquement (c'est du MCP classique, pas WebMCP), automatiser des sites tiers que vous ne contrôlez pas, et du travail SEO générique.
Modes d'invocation
L'utilisateur peut passer un argument (/webmcpify <mode> ou du texte simple) :
| Argument | Exécuter | Arrêter à |
|---|---|---|
(aucun) ou full |
toutes les phases, reprendre depuis l'état du manifest actuel | terminé |
inventory / map |
boucles DETECT + INVENTORY uniquement — zéro changement de code | présenter le tableau du manifest pour révision |
integrate |
boucle INTEGRATE uniquement (requiert des outils approuvés dans le manifest) | intégrés + compilés |
verify |
boucles VERIFY + HEAL sur les outils intégrés/vérifiés | rapport vert/ignoré |
status |
lire .webmcpify/manifest.json — lecture seule |
rapporter la phase, les comptes d'outils par statut, et la commande suivante recommandée |
Tout autre texte est un guide de scope (ex. « uniquement la zone de paiement », « outils lecture seule uniquement »).
Règles fondamentales (non négociables, appliquez-les à chaque phase)
- Zéro changement non lié. Chaque hunk diff que vous produisez doit être traçable à une entrée du manifest ou à la configuration unique enregistrée. Ne refactorisez jamais, ne reformatez jamais, ne renommez jamais, ni « n'améliorez » rien d'autre — notez les problèmes dans le rapport à la place. Les fichiers déjà sales au baseline (enregistrés dans le manifest) sont intouchables : ne les modifiez ni ne les ramenez jamais.
- Outils lecture seule en premier. Les mutations sont à trois états :
mutating: false,"client"(navigateur local uniquement : prefs, localStorage), ou"server"(données quittent le navigateur). Les outils mutants serveur requièrent une approbation humaine explicite par-outil enregistrée dans le manifest ; les outils mutants client peuvent être approuvés en lot à la portail. N'exposez jamais les actions destructrices, irréversibles, ou de paiement dans une première intégration. - Le serveur est la seule limite de confiance. La fonction
execute()d'un outil ne peut appeler que les chemins de code que l'UI utilise déjà (mêmes endpoints, mêmes validations, mêmes auth). Ne créez jamais de nouveaux endpoints, ne contournez jamais les contrôles existants, ne mettez jamais de secrets dans les outils. - Spec-shaped et sans dépendances. Enregistrez via
document.modelContext.registerTool()avec le cycle de vie AbortSignal (détection de la rétrocompatibilité fallbacknavigator.modelContextdéprécié). Aucune dépendance de runtime WebMCP tierce. Tout est détecté de manière dynamique : l'app se comporte de manière identique dans les navigateurs sans WebMCP. - Ne jamais
toolautosubmitsur les formulaires qui changent d'état — nimutating: "client"ni"server". Uniquement sur les formulaires de lecture pure (recherche, filtre, disponibilité). - L'état vit dans les fichiers, pas dans votre contexte. Lisez/écrivez
.webmcpify/constamment ; supposez que votre contexte peut être effacé entre n'importe quelles deux étapes. Écrivez le manifest de manière atomique (écrivezmanifest.json.tmp, puis renommez surmanifest.json). - Les commits sont opt-in. Ne commitez jamais à moins que l'humain n'ait choisi une politique de commit à la portail (voir ci-dessous). Sans git ou sans permission, laissez les changements dans l'arborescence de travail et enregistrez la progression dans le manifest uniquement.
Orientation fraîche et autorisée
WebMCP est une API en essai d'origine en évolution — la surface a déjà changé pendant l'essai (testing API supprimée 2026-07 ; navigator → document). Avant la Phase 2, si le réseau est disponible, tirez les guides officiels actuels de Google plutôt que de compter sur la mémoire :
npx -y modern-web-guidance@latest retrieve "webmcp,agentic-forms,agentic-javascript-tools"
Si hors ligne, utilisez references/integrate.md — mais préférez les guides en direct quand ils entrent en conflit.
Le protocole d'état — .webmcpify/ dans le repo cible
| Fichier | Objectif |
|---|---|
manifest.json |
Source unique de vérité (schema ci-dessous ; écritures atomiques) |
areas/<id>.tools.json |
Sortie de shard du sous-agent pendant la fan-out d'inventory (fusionné, puis supprimé) |
report.md |
Rapport en cours orienté humain ; finalisé à la fin |
Règle de reprise : si manifest.json existe, reprenez — ne recalculez rien de déjà enregistré. Fusionnez d'abord les shards restants : tout fichier areas/<id>.tools.json existant est fusionné dans le manifest (marquez ces zones inventoried, supprimez les shards) avant de redistribuer les sous-agents. Puis continuez à pipeline.phase, la première zone pending, ou le premier outil dont le statut n'est pas terminal. Statuts terminaux : verified, skipped, rejected.
Transitions de phase (faites l'écriture atomique du manifest au moment où la condition se tient) :
detect → inventory:appenregistré,baselineSha/baselineDirtycapturés.inventory → gate: aucune zonepending, la passe de complétude a tourné.gate → integrate: chaque outildiscoveredestapproved/rejected, etcommitPolicy+commitWebmcpifyDirsont définis.integrate → verify: aucun outilapprovedne reste (chacunintegratedou terminal), build vert.verify → heal: la boucle verify a visité chaque outilintegratedet ≥1 estfailed(aucun failed → directement àaudit).heal → audit: aucun outilfailedet re-vérification complète post-healing passée.audit → done: chaque hunk mappé-ou-flaggé,report.mdfinalisé.
Manifest schema (Webmcpify Manifest v3) :
{
"webmcpify": 3,
"app": { "stack": "react-vite", "typescript": true, "entry": "src/main.tsx",
"baseUrl": "http://localhost:5173", "startCommand": "npm run dev",
"authFixtures": { // comment verify OBTIENT chaque session
"member": { "obtain": "npm run seed:test-user, puis connectez-vous à /login",
"account": "member@example.test",
"env": ["TEST_MEMBER_PASSWORD"] } // noms de variables d'env uniquement — jamais de valeurs secrètes
} },
"pipeline": {
"phase": "inventory", // detect|inventory|gate|integrate|verify|heal|audit|done — règles de transition ci-dessus
"setup": { // CHEMINS créés/modifiés par étape de configuration unique ([] = pas encore fait)
"runtimeVendored": ["src/webmcp/webmcpify.ts", "src/webmcp/webmcp.d.ts"],
"harnessInstalled": [".webmcpify/webmcp.spec.ts"],
"originTrialNoted": ["README.md"]
},
"baselineSha": "abc1234", // HEAD au démarrage du pipeline ; null sans git
"baselineDirty": ["src/wip.ts"], // chemins sales au démarrage — intouchables (règle fondamentale 1)
"commitPolicy": null, // défini à la portail : "commit-per-batch" | "no-commit"
"commitWebmcpifyDir": null, // défini à la portail : committer .webmcpify/ lui-même ? true | false
"blockers": [] // ex. « app ne démarre pas localement : a besoin de $API_KEY » — surfacé à la portail
},
"areas": [
{ "id": "checkout", "paths": ["src/features/checkout/"], "status": "pending" } // pending|inventoried
],
"tools": [
{
"id": "create_ticket",
"area": "tickets",
"kind": "imperative", // imperative | declarative
"mutating": "server", // false | "client" (navigateur local uniquement : prefs, localStorage) | "server" (données quittent le navigateur)
"priority": 1, // 1 = exposer en premier ; 2/3 = vagues ultérieures
"description": "Crée un nouveau ticket dans le projet actuellement ouvert.",
"inputSchema": { /* JSON Schema */ },
"annotations": { "readOnlyHint": false, "untrustedContentHint": false }, // verify affirme ces propriétés sur l'outil énuméré
"source": ["src/features/tickets/NewTicket.tsx:42"], // le chemin de code UI qu'il enveloppe
"route": "/projects/demo/tickets", // où verify navigue
"auth": ["role:member"], // "none" | "session" | ["role:<name>", ...] — clés dans app.authFixtures ; verify tourne une fois par rôle listé
"examples": { "valid": { "title": "Test ticket" }, "invalid": {} },
// invalid: null UNIQUEMENT pour les outils readOnlyHint sans/vides params —
// verify affirme alors dual-outcome : rejette OU résout sans effet secondaire
"expect": { "result": "created", "navigation": null, "ui": "new row appears in the ticket list" },
// exactement un de result|navigation : result = substring de la chaîne résolue ;
// navigation = destination URL/pattern quand executeTool résout null (navigué)
"cleanup": "supprimez le ticket créé via le chemin delete de l'UI (données de test uniquement)", // requis pour mutating:"server", recommandé pour "client"
"status": "discovered", // discovered|approved|rejected*|integrated|verified*|failed|skipped* (* = terminal)
"approval": null, // outils mutant serveur, une fois approuvés : { "note": "...", "at": "2026-07-12",
// "productionSideEffect": null } — défini uniquement quand la vérification inévitablement
// cause un vrai effet en production (voir VERIFY : politique d'effet côté production)
"attempts": 0, // cycles heal-fix ; l'échec verify déclencheur est attempt 0
"batchCommit": null, // sha sous commit-per-batch — arrive dans le manifest un commit PLUS TARD
"notes": ""
}
],
"log": [ "2026-07-12 inventory: area checkout done, 4 candidates" ]
}
Migration v2→v3 : la reprise d'un manifest "webmcpify": 2 migre sur place à la première écriture — auth string → array ; setup booléens → tableaux de chemins (false → [] ; true → récupérer les chemins de git/log, sinon null = fait-mais-non-enregistré, audit traite ces fichiers flag-only) ; mutating: true → "server" ; ajouter annotations (par défaut du tableau d'inventory), blockers: [], commitWebmcpifyDir: null, expect.navigation: null ; puis augmenter à 3.
Phase 0 — DETECT
Identifiez la pile, les commandes build + dev-server, TypeScript ou non, le modèle d'auth (incluant comment verify obtient chaque session de test → app.authFixtures), la configuration de test, et comment l'app démarre localement ; enregistrez sous app. Enregistrez le baseline git : pipeline.baselineSha = HEAD actuel et pipeline.baselineDirty = chemins git status --porcelain (tous deux null/[] sans git). Si l'app ne peut pas être démarrée localement, ajoutez le blocker à pipeline.blockers — l'intégration peut procéder, mais la vérification sera bloquée et cela doit être surfacé à la portail. Détails : references/inventory.md.
Phase 1 — INVENTORY (boucle ; s'adapte à n'importe quelle taille)
Ne mappez jamais une grande codebase en une seule passe.
- Cartographie de zone en premier (bon marché, structurel) : énumérez les routes/vues/modules de fonctionnalités depuis la config du routeur, le répertoire pages, ou la navigation — sans lire les fichiers d'implémentation. Écrivez chaque zone dans
areasavec"pending". - Boucle d'inventory — une zone par itération : lisez en profondeur uniquement les fichiers de cette zone ; rédigez un outil candidat par action utilisateur (conventions, budget de compte d'outils, et règles de chevauchement :
references/inventory.md) avec TOUS les champs du manifest remplis, incluantroute,auth,annotations,examples,expect, etcleanup(requis pourmutating: "server", recommandé pour"client") — la phase verify s'exécute uniquement depuis ces champs. Ajoutez comme"discovered", marquez la zone"inventoried", écrivez le manifest, répétez.- Fan-out du sous-agent : les sous-agents n'écrivent jamais
manifest.json. Chacun écrit uniquement son propre shardareas/<id>.tools.json— schema{ "webmcpifyShard": 3, "area": "<id>", "tools": [ /* full v3 tool entries */ ] }, écrit de manière atomique (tmp + rename). Vous (le coordinateur) fusionnez les shards dans le manifest séquentiellement, puis les supprimez ; en reprise, fusionnez les shards existants EN PREMIER avant de redistribuer (Règle de reprise).
- Fan-out du sous-agent : les sous-agents n'écrivent jamais
- Sortie : aucune zone
pendingne reste, plus une passe de complétude — parcourez la navigation de l'app et demandez-vous « y a-t-il une action utilisateur visible manquante ? »
PORTAIL — approbation du manifest (le seul vrai checkpoint)
Présentez le manifest de manière compacte (id, zone, kind, mutating, priority, description d'une ligne) — par-zone lot sur les grandes app. Demandez à l'humain de décider, en un seul échange si possible :
- Quels outils sont
approvedvsrejected(rejectedest terminal — les outils rejetés sont exclus de chaque phase ultérieure et des conditions de sortie). Les outilsmutating: "server"requièrent l'approbation individuelle → enregistrer dansapproval; les outilsmutating: "client"peuvent être approuvés en lot. - Politique de commit :
commit-per-batch(chaque lot d'intégration commité, réversible — recommandé sur un baseline propre) ouno-commit(laisser les changements uncommités pour que l'humain révise/committe) →pipeline.commitPolicy. Aussi si.webmcpify/lui-même doit être commité (recommandé : oui — cela documente l'intégration) →pipeline.commitWebmcpifyDir. - Chaque entrée dans
pipeline.blockers(ex. app ne démarre pas). Si la vérification d'un outil causera inévitablement un vrai effet côté production (ex. un mailer avec un endpoint origin-allow-listed), récupérez l'approbation ICI et enregistrez-la dansapproval.productionSideEffectde l'outil — voir VERIFY.
Appliquez references/security.md à chaque outil mutant avant de présenter.
Phase 2 — INTEGRATE (boucle)
Configuration unique en premier — enregistrez les chemins des fichiers créés/modifiés dans pipeline.setup (ex. runtimeVendored: ["src/webmcp/webmcpify.ts", ...]) : vendorisez le runtime depuis les templates/ de cette skill (webmcpify.ts, ou webmcpify.js pour les projets non-TS, plus webmcp.d.ts pour TS et webmcp-jsx.d.ts pour React TSX — conservez le header MIT complet ; voir references/runtime.md) et notez la condition de l'essai d'origine/flag dans le README cible (originTrialNoted). Puis boucle :
- Choisissez le lot suivant d'outils
approved— une zone ou ≤5 outils. - Implémentez par
references/integrate.md: attributs déclaratifs pour les formulaires HTML standards (incluant les formulaires rendus par framework et les fetch-interceptés) ; enregistrement impératif via le runtime vendorisé pour les actions non-formulaire ou à état contrôlé. - Build + typecheck ; corrigez uniquement ce que le lot a cassé.
- Marquez les outils
"integrated", écrivez le manifest. Souscommit-per-batch: exigez un index propre avant staging (changements staged non liés → arrêtez et surfacez) ; stagez uniquement les fichiers du lot par chemin — jamaisgit add -A,-u,., oucommit -a; commitezfeat(webmcp): expose <ids> (webmcpify). Le sha du commit arrive dansbatchCommitsur l'écriture suivante du manifest — un commit plus tard (le manifest ne peut pas contenir le sha de son propre commit). Ne jamais amender un commit de lot précédent. - Répétez jusqu'à ce qu'aucun outil
approvedne reste.
Phase 3 — VERIFY (boucle)
Configurez une fois depuis templates/webmcp.spec.ts par references/verify.md (vrai Chrome headed ; surface de production getTools()/executeTool() avec sonde de fallback legacy). Puis bouclez sur chaque outil integrated, en utilisant ses champs du manifest route, auth, examples, expect, et annotations :
- affirmer que l'outil est enregistré avec le schema attendu (le
inputSchemaénuméré est un JSON Schema stringifié — parsez avant de comparer) et lesannotationsdu manifest ; - exécuter l'exemple valide (outils mutants : données dev/test uniquement, puis exécutez
cleanup) et un exemple invalide (invalid: nulloutils lecture seule zéro-param : affirmation dual-outcome — voirreferences/verify.md) ; - affirmer sur le résultat retourné et l'état UI résultant par
expect(un delta UI, ouexpect.navigationquand l'exécution résoutnull).
Passage → "verified". Échec → "failed" + note d'échec. Outils scope-rôle : exécutez la boucle une fois par rôle listé dans auth, en vous connectant via l'entrée app.authFixtures correspondante.
Politique d'effet côté production — quand la vérification d'un outil inévitablement cause un effet réel en production (ex. un email réellement envoyé), LES TROIS sont requis : (1) l'humain l'a approuvé à la portail, enregistré dans approval.productionSideEffect ; (2) chaque payload de test est marqué [webmcpify verification] ; (3) l'effet est listé dans report.md. Sans l'approbation enregistrée, n'exécutez pas le chemin live — marquez l'outil skipped avec une note de blocker.
Phase 4 — HEAL (boucle)
Tant qu'un outil est "failed" : diagnostiquez par references/heal.md, corrigez uniquement l'intégration de cet outil — corrections implémentation-uniquement ; si la correction changerait le contrat approuvé (schema, description, classe mutating, annotations, expect), retournez à la portail pour re-approbation au lieu de changer silencieusement le manifest. L'échec verify déclencheur est attempt 0 ; incrémentez attempts par cycle de correction et re-vérifiez. À attempts = 3 → "skipped" avec une note de blocker claire (une escalade explicite à l'humain, pas un abandon silencieux). Ne jamais élargissez le diff ou simulez une réussite. Après healing, re-lancez la vérification une fois pour tous les outils avec le statut integrated ou verified (guérir un outil peut en casser un autre — collisions de scope).
Sortie : chaque outil est verified, skipped, ou rejected ; build vert.
Final — AUDIT + rapport
- Audit diff (flag-only, jamais auto-revert) : collectez les changements du pipeline —
git diff <baselineSha>..HEADplus l'index et les fichiers non suivis souscommit-per-batch, ou l'arborescence de travail + index + non-suivis sousno-commit. Chaque hunk doit être mappé à une entrée du manifest ou un cheminpipeline.setupenregistré. Un hunk non mappé → flaggez-le dans le rapport avec fichier/ligne et une disposition suggérée ; ne revertez jamais rien vous-même. Un hunk dans un fichierbaselineDirty→ intouchable, flaggez uniquement. SansbaselineSha, auditez les fichiers nommés dans les champssourcedu manifest et les cheminspipeline.setup(entrées de setup enregistrées commenullpar la migration v2→v3 : revenez à flag-only pour ces fichiers). - Finalisez
.webmcpify/report.md: couverture d'outil par zone, outils skipped/rejected avec raisons, notes de sécurité (quels outils mutants existent, qu'est-ce qui les protège, les effets côté production enregistrés), comment tester manuellement (flag, DevTools WebMCP pane, extension inspector), et chaque blocker qui requiert un humain. - Dites à l'humain : ce qui est exposé, ce qui est skipped et pourquoi, et comment l'essayer.
Références (lire à la demande, pas en avant)
references/inventory.md— cartographie de zone, conventions de naming/schema, budgets/chevauchementreferences/integrate.md— patterns déclaratifs + impératifs par stackreferences/runtime.md— vendorisation + câblage du runtimetemplates/references/verify.md— installation du harnais : flags, surfaces, Playwright/Puppeteer, evalsreferences/heal.md— taxonomie des échecs → correctionsreferences/security.md— la checklist de sécurité (appliquez avant la portail et à l'audit)