Blog

Comment ajouter le jeton d’essai d’origine WebMCP à WordPress

Lighthouse marque ses audits WebMCP comme non applicables quand la page chargée n’a aucune API WebMCP à examiner. L’API n’est offerte que par l’entremise d’un essai d’origine (origin trial) pour l’instant. Pour les visiteurs, et pour toute exécution de Lighthouse hors de votre propre navigateur, votre site doit donc être inscrit à l’essai et envoyer le jeton sur chaque page. Sans jeton, pas d’API, et rien à auditer.

Sur WordPress, le jeton s’ajoute sous forme de balise meta dans le head ou d’en-tête de réponse Origin-Trial, quelques lignes dans les deux cas. Voici tout le parcours, avec la partie WordPress testée sur 7.1, et une façon d’écrire du code WebMCP qui survit à la fin de l’essai.

Key takeaways

  • Lighthouse marks its WebMCP audits as not applicable when the page has no WebMCP API to inspect. The API is only available through an origin trial, so your site must send a valid token on every page, and Lighthouse needs Chrome 150 or newer. arvindkumar.ca
  • Register your origin on Chrome’s origin trials site, and register again on Edge’s, because each browser issues its own tokens. Use the https address visitors land on, and tick the match all subdomains option if you want to cover the bare domain and subdomains. arvindkumar.ca
  • Watch the Edge domain field and the expiry dates. The Edge form accepts http:// without complaint, but that token never works on an https site, and my Edge token expired about six weeks after I registered. arvindkumar.ca
  • On WordPress, add the token with either a meta tag in the head or an Origin-Trial response header, not both. The meta tag must sit in the head, and the header can also be set outside WordPress in Apache, Nginx or a CDN. arvindkumar.ca
  • Purge your page cache after every change, then check with curl, the Origin Trials section in Chrome DevTools (Application panel) and typeof document.modelContext in the console. After that, run Lighthouse with Agentic Browsing ticked. arvindkumar.ca
  • Write your WebMCP code so the page works fine without the API. Check for document.modelContext, register tools only when it exists, and keep the AbortController so you can remove a tool. Ignore any guide that uses provideContext(), which is out of date. arvindkumar.ca
  • Three clocks run at once: each token’s expiry, Chrome’s trial and Edge’s trial, which end no later than March 29, 2027. Put the renewal dates in your calendar, since a feature-detected script simply does nothing once a trial ends. arvindkumar.ca

Summarised from this post, formatted for answer engines.

Pourquoi Lighthouse indique-t-il « non applicable »?

La réponse se trouve dans le code source de Lighthouse sur GitHub. Son collecteur WebMCP active le domaine WebMCP du protocole DevTools, puis fait une seule vérification dans la page : document.modelContext est-il défini, ou l’ancien navigator.modelContext? Si l’une ou l’autre étape échoue, les trois audits WebMCP renvoient « non applicable ».

Il y a donc deux causes possibles. Soit Lighthouse s’exécute dans une version de Chrome antérieure à la 150, que la documentation de Chrome indique comme nécessaire pour cette catégorie, soit la page n’expose pas l’API. Chrome ne l’expose que si la page porte un jeton d’essai d’origine valide, ou si vous avez activé chrome://flags/#enable-webmcp-testing pour des tests locaux. Ce drapeau ne change que votre propre navigateur; une exécution de Lighthouse ailleurs voit votre site comme le voient les visiteurs.

La catégorie Agentic Browsing est expérimentale, et dans le panneau Lighthouse de DevTools, c’est une case à cocher désactivée par défaut. Elle vérifie aussi la présence d’un fichier llms.txt, dont j’ai parlé dans ajouter llms.txt à WordPress.

Qu’est-ce qu’un essai d’origine, et comment s’inscrire?

Un essai d’origine donne à une origine inscrite l’accès à une fonctionnalité expérimentale pour une durée limitée, afin que l’équipe du navigateur recueille des commentaires avant de décider de l’avenir de la fonctionnalité. Chrome a déjà prolongé celui-ci : quand j’ai inscrit ce site en octobre 2026, la page d’inscription indiquait WebMCP comme disponible de Chrome 149 à Chrome 162, se terminant au plus tard le 29 mars 2027. Vérifiez les dates actuelles sur la page avant de planifier quoi que ce soit.

S’inscrire dans Chrome

  1. Inscrivez-vous dans Chrome. Ouvrez le site des essais d’origine de Chrome à developer.chrome.com/origintrials, trouvez WebMCP et cliquez sur Register.
  2. Entrez la bonne origine. Un jeton correspond exactement au schéma, à l’hôte et au port, donc https://www.example.com et https://example.com sont des origines différentes. Inscrivez l’adresse https où atterrissent les visiteurs (l’adresse du site sous Réglages, Général); l’API n’existe que dans les contextes sécurisés. Pour couvrir le domaine sans préfixe et tous les sous-domaines, www et staging compris, inscrivez https://example.com et cochez l’option de correspondance avec tous les sous-domaines. Laissez la correspondance tierce désactivée; elle sert aux scripts qui injectent le jeton dans les sites des autres. Pour l’utilisation prévue, la tranche la plus basse, de 0 à 10 000 pages vues par jour, convient à la plupart des sites.
Le formulaire d’inscription de Chrome. Les versions disponibles et la date de fin se trouvent en haut.
  1. Cochez les quatre confirmations et cliquez sur Register. Deux d’entre elles influencent votre code : l’essai peut être désactivé pour tout le monde si la fonctionnalité se retrouve sur plus de 1 % de tous les chargements de pages de Chrome, et on s’attend à ce que vous gériez le cas où la fonctionnalité n’est pas disponible. Le script plus loin dans cet article le fait par détection de fonctionnalité.
Quatre cases à cocher avant de pouvoir vous inscrire.
  1. Copiez le jeton, une longue chaîne en base64, depuis la page qui s’ouvre ensuite. Elle liste chaque jeton avec sa date d’expiration; le mien va jusqu’à la date de fin de l’essai, le 29 mars 2027. Mettez cette date à votre calendrier. Chrome dit qu’il enverra un courriel de rappel pour le renouvellement, et le bouton Renew sur la même page vous donne un nouveau jeton si l’essai se prolonge.
Mon inscription, jeton masqué.

S’inscrire dans Edge

Microsoft Edge mène son propre essai WebMCP avec ses propres jetons, alors inscrivez-vous là aussi. Le processus est semblable, avec un piège dans le champ du domaine.

  1. Trouvez l’essai. Sur le site des essais d’origine d’Edge à developer.microsoft.com/microsoft-edge/origin-trials, connectez-vous avec GitHub, cliquez sur See trials sous Select your origin trial, cherchez WebMCP et cliquez sur Details.
L’essai WebMCP d’Edge se termine le même jour que celui de Chrome.
  1. Acceptez les conditions. Faites défiler jusqu’à New Origin Trial Registration et cochez I Accept the Terms of Use. Entre autres choses, vous acceptez que Microsoft puisse vous contacter pour obtenir vos commentaires.
  2. Saisissez le domaine avec https devant. Le formulaire accepte http:// sans broncher. Mon premier jeton Edge a été émis pour http://arvindkumar.ca sur le port 80, ce qui ne correspond jamais à un site en https, et WebMCP exige https de toute façon. Tapez https://example.com, activez Enable token for subdomains, laissez la correspondance tierce désactivée et cliquez sur Submit.
Mon premier essai. Le formulaire a accepté http://, et le jeton émis ne fonctionne jamais sur un site en https.
  1. Copiez le jeton dans le tableau Registrations qui s’affiche. Regardez sa colonne Token Expiration : mon jeton Edge expire environ six semaines après l’inscription, bien avant la fin de l’essai, alors renouvelez-le à temps depuis la même page.
Le jeton de ce premier essai, flouté. Remarquez l’expiration : environ six semaines plus tard.

Comment ajouter le jeton dans WordPress?

Placez l’extension ci-dessous dans wp-content/plugins/mysite-origin-trial/ et activez-la, ou déposez ses deux fichiers dans wp-content/mu-plugins/, où ils se chargent sans activation; les deux approches ont été testées sur WordPress 7.1. D’abord les jetons, puis les deux méthodes. Utilisez-en une seule.

<?php
/**
 * Plugin Name: Origin Trial Tokens
 * Description: Sends WebMCP origin trial tokens for Chrome and Edge, as a meta tag or a response header.
 * Version:     1.0.0
 * Requires PHP: 7.4
 */

defined( 'ABSPATH' ) || exit;

/**
 * The tokens to send. Paste them here, or keep them out of version
 * control with a constant in wp-config.php:
 * define( 'MYSITE_OT_TOKENS', 'CHROME_TOKEN, EDGE_TOKEN' );
 *
 * @return string[]
 */
function mysite_origin_trial_tokens() {
	$tokens = array(
		'PASTE_YOUR_CHROME_TOKEN_HERE',
		'PASTE_YOUR_EDGE_TOKEN_HERE',
	);

	if ( defined( 'MYSITE_OT_TOKENS' ) ) {
		$tokens = explode( ',', MYSITE_OT_TOKENS );
	}

	// Tokens are base64 strings. Keep only those characters, so nothing
	// else can end up in a header or an attribute.
	$tokens = preg_replace( '/[^A-Za-z0-9+\/=]/', '', array_map( 'trim', $tokens ) );

	return array_filter( $tokens );
}

Les jetons sont de toute façon publics dans votre HTML; la constante permet simplement à l’environnement de préproduction et à la production d’avoir chacun le leur sans modifier le fichier de l’extension. Elle va dans wp-config.php, au-dessus de la ligne qui dit d’arrêter les modifications :

define( 'MYSITE_OT_TOKENS', 'CHROME_TOKEN, EDGE_TOKEN' );

Méthode A : une balise meta dans le head

/**
 * Method A: a meta tag, printed first in wp_head.
 */
add_action( 'wp_head', 'mysite_origin_trial_meta', 0 );
function mysite_origin_trial_meta() {
	foreach ( mysite_origin_trial_tokens() as $token ) {
		echo '<meta http-equiv="origin-trial" content="' . esc_attr( $token ) . '">' . "\n";
	}
}

Chromium ne tient compte d’une balise meta d’origin trial que si elle se trouve dans le head, et il ignore celle du body; l’emplacement compte donc. En accrochant wp_head à la priorité 0, la balise passe avant tout ce que WordPress ajoute au head, y compris tout script susceptible d’utiliser l’API. Comme la balise fait partie du HTML, un cache de pages la sert avec la page mise en cache.

Méthode B : un en-tête de réponse Origin-Trial

/**
 * Method B: an Origin-Trial response header. Chromium reads several
 * tokens from one header when they are separated by commas.
 */
add_action( 'send_headers', 'mysite_origin_trial_header' );
function mysite_origin_trial_header() {
	$tokens = mysite_origin_trial_tokens();

	if ( $tokens && ! headers_sent() ) {
		header( 'Origin-Trial: ' . implode( ', ', $tokens ) );
	}
}

L’action send_headers se déclenche sur les requêtes côté public, après la requête principale et avant le chargement du gabarit; l’en-tête part donc avant toute sortie. Vous pouvez aussi le définir hors de WordPress, avec mod_headers d’Apache (Header set), add_header de Nginx ou une règle d’en-tête de réponse sur un CDN, et ne rien mettre dans le PHP.

Le cache pose problème aux deux méthodes. Un cache de pages complètes sert l’ancien HTML, avec ou sans la balise meta, jusqu’à ce que vous le vidiez, et un cache qui sert les pages comme fichiers statiques peut perdre un en-tête ajouté par PHP. Videz le cache après chaque changement, puis vérifiez avec curl.

Comment vérifier que ça fonctionne?

  1. Vérifiez la réponse. curl -sI https://www.example.com/ | grep -i origin-trial affiche l’en-tête; curl -s https://www.example.com/ | grep -i origin-trial affiche la balise meta. Exécutez les deux sur l’origine en production après avoir vidé le cache.
  2. Vérifiez l’état du jeton. Dans Chrome DevTools, ouvrez le panneau Application, déroulez Frames et sélectionnez top. La section Origin Trials liste WebMCP avec un état par jeton : Success est ce que vous voulez, WrongOrigin signifie que le jeton a été créé pour une autre origine (un jeton http sur une page https se retrouve ici), Expired signifie qu’il faut le renouveler. Chrome ignore les jetons qu’il ne peut pas valider, donc le jeton Edge ne cause aucun problème ici.
  3. Vérifiez l’API. Dans la console, typeof document.modelContext affiche « object » quand l’API est active, et await document.modelContext.getTools() liste les outils enregistrés par votre page.
  4. Relancez Lighthouse. Cochez Agentic Browsing et lancez l’analyse. Avec l’API exposée, l’audit des outils enregistrés liste vos outils, l’audit des formulaires liste les formulaires sans les attributs toolname et tooldescription (il reste sans objet sur une page sans formulaire), et l’audit du schéma réussit ou échoue.

Comment écrire du code WebMCP qui survit à l’essai?

Écrivez-le de sorte que la page fonctionne très bien sans l’API : vérifiez la présence de document.modelContext, n’enregistrez que s’il existe, et gardez l’AbortController pour pouvoir retirer l’outil par la suite. Voici le fichier que l’extension charge, un seul outil en lecture seule qui cherche dans le site par l’API REST.

/* Register one read-only WebMCP tool, only where the API exists. */
( () => {
	// The API lives on document.modelContext. Early trial builds exposed it as
	// navigator.modelContext; that half of the line is only there for them.
	const modelContext = document.modelContext || navigator.modelContext;

	if ( ! modelContext || typeof modelContext.registerTool !== 'function' ) {
		return; // No token, the trial has ended, or another browser. The page works as before.
	}

	const restLink = document.querySelector( 'link[rel="https://api.w.org/"]' );
	const restRoot = restLink ? restLink.href : location.origin + '/wp-json/';
	const controller = new AbortController();

	modelContext.registerTool(
		{
			name: 'search_posts',
			description: 'Search the posts and pages on this site. Returns up to five titles with their URLs.',
			inputSchema: {
				type: 'object',
				properties: {
					query: { type: 'string', description: 'Words to search for' },
				},
				required: [ 'query' ],
			},
			annotations: { readOnlyHint: true },
			async execute( { query }, { signal } ) {
				const url = new URL( 'wp/v2/search', restRoot );
				url.searchParams.set( 'search', query );
				url.searchParams.set( 'per_page', '5' );

				// The agent's signal cancels the request if the agent stops.
				const response = await fetch( url, { signal } );
				if ( ! response.ok ) {
					throw new Error( 'Search failed with status ' + response.status );
				}

				const results = await response.json();
				return results.map( ( r ) => r.title + ': ' + r.url ).join( '\n' ) || 'No results.';
			},
		},
		{ signal: controller.signal }
	).catch( ( error ) => console.warn( 'WebMCP tool not registered:', error ) );

	// To take the tool away later, abort the signal: controller.abort();
} )();

Trois choses à retenir. La première ligne garde une solution de repli pour navigator.modelContext, là où les premières versions d’essai plaçaient l’API; la spécification et la documentation de Chrome utilisent maintenant document.modelContext, et Chromium a depuis retiré l’ancien nom. Vous pourrez donc supprimer cette moitié de la ligne quand les anciennes versions n’auront plus d’importance. Deuxièmement, l’enregistrement passe un AbortSignal, et l’interrompre désenregistre l’outil; c’est la façon prévue par la spécification d’en retirer un. Troisièmement, execute() reçoit son propre signal, qui annule le fetch si l’agent s’arrête. Gardez le catch : registerTool() rejette les noms en double, les descriptions vides et les schémas qui ne se sérialisent pas.

Si un guide que vous lisez appelle navigator.modelContext.provideContext(), il est périmé. Les méthodes de document.modelContext dans la spécification actuelle sont registerTool(), getTools() et executeTool(); il n’y a pas de provideContext(). Le plugin charge le fichier avec la stratégie defer :

/**
 * The WebMCP tool script, loaded on every front-end page.
 */
add_action( 'wp_enqueue_scripts', 'mysite_webmcp_script' );
function mysite_webmcp_script() {
	wp_enqueue_script(
		'mysite-webmcp',
		plugins_url( 'webmcp-tools.js', __FILE__ ),
		array(),
		'1.0.0',
		array( 'strategy' => 'defer' )
	);
}

Quand ça se termine-t-il?

Trois horloges tournent en même temps : la date d’expiration propre à chaque jeton, qui correspondait pour moi à la date de fin de l’essai dans Chrome et à environ six semaines dans Edge; l’essai de Chrome, qui va jusqu’à Chrome 162 et se termine au déploiement de la version suivante, au plus tard le 29 mars 2027; et celui d’Edge, qui indique la même date de fin. Mettez les dates de renouvellement dans votre calendrier et revérifiez de temps en temps les deux pages d’inscription, car les essais sont parfois prolongés ou arrêtés plus tôt. Quand un essai prend fin, le navigateur ignore le jeton, document.modelContext disparaît, à moins que WebMCP n’ait été livré d’ici là, et le script avec détection de fonctionnalité ci-dessus ne fait rien.

Enregistrez l’origine, ajoutez le jeton d’une des façons, videz le cache et relancez Lighthouse. Les audits passent de « sans objet » à un vrai résultat, et vous pouvez observer comment les agents traitent votre site avant que les fabricants de navigateurs décident de ce que WebMCP deviendra.

5 questions about the WebMCP origin trial token, answered

Why does Lighthouse say WebMCP audits are not applicable?

Lighthouse returns not applicable when the page does not expose document.modelContext (or the older navigator.modelContext), or when it runs in a Chrome older than 150. Chrome only exposes the API when the page carries a valid origin trial token.

Do I need a separate WebMCP origin trial token for Edge?

Yes. Microsoft Edge runs its own WebMCP trial with its own tokens, so you register there as well. Chrome ignores tokens it cannot validate, so the Edge token does no harm in Chrome.

Should I add the WebMCP token as a meta tag or a response header in WordPress?

Either works, but use only one. A meta tag must sit in the head, and the header can be sent with the send_headers action or set in Apache, Nginx or a CDN.

How can I check that my WebMCP origin trial token is working?

Use curl to look for the header or meta tag, then open the Origin Trials section in the Chrome DevTools Application panel and look for a Success status. You can also run typeof document.modelContext in the console, which prints "object" when the API is on.

What happens to my WebMCP code when the origin trial ends?

The browser ignores the token and document.modelContext disappears, unless WebMCP has shipped by then. If your script uses feature detection, it simply does nothing.

Read next