Tutoriel

Comment les Agent Plugins donnent de nouvelles capacités à un agent de code : manifeste, Skills, MCP et le JSON après installation

Installer un plugin ne rend pas le modèle plus intelligent. Le client lit seulement quelques JSON à des chemins fixes.

Les deux textes précédents montraient à quoi ressemble la boîte et quand ne pas l’emballer. Aujourd’hui on suppose que vous livrez un Plugin. La vraie question : une fois Cursor, Claude Code ou Antigravity a installé ce répertoire, pourquoi le modèle interroge tout à coup les factures et rédige le résumé hebdo ? Ce n’est ni une mise à jour de poids, ni un prompt système réécrit. Agent Plugins 1.0.0 est net : lire d’abord le plugin.json racine, puis découvrir skills/ et mcp.json aux emplacements fixes. Le Google Cloud Developer Plugin suit le même chemin. On termine ici les hops JSON après install, puis on passe à MCP et JSON Schema.

Cinq sauts, pas « le modèle a appris »

« L’agent a gagné une capacité tout seul » sonne comme un apprentissage. En ingénierie, ce sont cinq sauts, aucun n’est facultatif. Premier : le client ancre le répertoire ; un chemin résolu hors de la racine est refusé, y compris un lien symbolique vers l’extérieur. Deuxième : lire plugin.json, valider le schéma fermé, prendre name et la version de spec. Échec ici : tout le paquet est rejeté, les sauts trois à cinq n’ont pas lieu. Troisième : si skills/ existe, ne regarder que les enfants directs qui contiennent un fichier régulier nommé exactement SKILL.md, puis injecter name et description. Quatrième : si mcp.json existe, connecter selon chaque type, puis tools/list après la poignée de main. Cinquième : le modèle recoupe une description ou un nom d’outil, puis lit le corps du Skill ou envoie tools/call.

La spec ignore volontairement l’apparence du bouton d’install. Le Google Developers Blog le dit : install, permissions, bac à sable et UX de confirmation sont l’affaire de chaque client. Agents CLI, Cursor et Claude Code peuvent afficher trois dialogues. Ce qui voyage, c’est le répertoire et deux JSON fermés. En revue, on ne demande pas « où clique l’utilisateur ? » mais « quels objets sont maintenant en mémoire ? » Pas de manifeste, pas de sauts suivants. Manifeste OK mais $schema de mcp.json en désaccord avec plugin.json : MCP coupé, skills conservés. Un SKILL.md hors Agent Skills : on saute ce skill seulement.

La délégation horizontale n’est pas ce pipeline. Découvrir l’agent factures d’une autre équipe, c’est une Agent Card — voir l’article A2A. Ici on demande seulement comment cet agent de code gagne un jeu de skills et d’outils. Appelez « nouvelle capacité » un résultat de découverte, puis regardez le JSON de chaque hop.

Ce hop JSON que le client tient maintenant Ce que le modèle peut faire
Lire plugin.jsonIdentité : name / version / $schemaRien encore — la boîte est seulement valide
Parcourir skills/Tableau de métadonnées skill (pas encore de corps)Peut choisir un brief ; le corps à la demande
Connecter MCP, puis tools/listNoms d’outils plus inputSchemaPeut remplir les arguments ; rien n’a tourné

D’abord le manifeste : plugin.json est le contrat d’identité

Le client DOIT lire le plugin.json racine avant de découvrir des composants. On ne renomme pas le fichier, on n’inline ni skills ni MCP dans le manifeste. Le schéma est fermé : seulement $schema, name, version, description, author, homepage, repository, license, keywords, extensions. Les clés de premier niveau en trop DOIVENT être signalées et ignorées — ce n’est pas un motif de rejet. Fatal : champ requis manquant, mauvais type, name illégal — on rejette le paquet et on ne découvre rien. Pour 1.0.0, $schema DOIT valoir https://agent-plugins.org/schemas/1.0.0/plugin.schema.json. Le client s’en sert pour choisir des règles locales et NE DOIT PAS aller chercher un schéma pendant le chargement.

name est un identifiant, pas un titre de boutique. Longueur 1–64 ; seulement a-z, chiffres, tiret, point ; premier et dernier caractères alphanumériques ; pas de -- ni de ... My-Plugin et -start rejettent tout le paquet. SemVer est recommandé pour version, mais « ça ne ressemble pas à SemVer » n’est pas un motif de rejet. L’objet author ne peut contenir que name / email / url. Le privé client va sous extensions.com.example.client ou dans un répertoire de domaine inversé à la racine. N’inventez pas une cinquième clé de premier niveau pour les hooks. Les mettre en tête de plugin.json, la spec dit de les ignorer — votre IDE les lira peut-être par hasard, le client suivant non.

Ci-dessous un manifeste complet à committer : plus que le minimum à deux champs, avec des métadonnées pour les humains. Faites-le parser et passer le schéma officiel avant de discuter du bouton d’install. keywords aident un catalogue. description aide une personne à décider d’installer. Elle n’aide pas le modèle à choisir un outil. Les skills se choisissent sur la description de SKILL.md ; les outils sur tools/list. Un brief d’outil dans le manifeste laisse la surface de découverte vide.

{
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
  "name": "invoice-ops",
  "version": "1.2.0",
  "description": "Invoice query MCP plus the weekly-summary skill, shipped as one directory",
  "author": {
    "name": "Finance Platform",
    "url": "https://docs.example.com/invoice-ops"
  },
  "homepage": "https://docs.example.com/invoice-ops",
  "repository": "https://github.com/example/invoice-ops",
  "license": "MIT",
  "keywords": ["invoices", "weekly-summary", "mcp"]
}

Après install : l’instantané de capacités dans le client

La spec n’exige pas d’exporter un fichier « capacités installées ». La revue doit quand même voir ce qui siège en mémoire. Pliez les cinq sauts en un JSON d’instantané : identité du plugin, skills découverts (métadonnées seulement), état MCP, contrats d’outils issus de tools/list. Cet instantané n’est pas une instance de plugin.schema.json — ne le validez pas avec le schéma d’emballage. C’est une fixture CI : nombre de skills, noms d’outils, champs requis de inputSchema. Install OK et instantané faux : la découverte ou la poignée de main a cassé. Le modèle n’a pas « échoué à apprendre ».

« Gagné automatiquement » se lit dans cet objet. skills[].loaded vaut metadata, pas body — une centaine de tokens au démarrage, le corps à la demande. tools[] vient de tools/list après la poignée de main, pas d’une liste écrite à la main dans plugin.json. mcpServers[].status est du runtime, pas le contrat d’emballage. tools vide avec connected : la poignée a marché, le serveur n’a rien exposé — déboguez le serveur, pas le manifeste. L’inverse, manifeste valide et zéro skill dans l’instantané, veut souvent dire que SKILL.md est un cran trop profond.

Après le Google Cloud Developer Plugin, le côté client a la même forme : identité de la boîte, métadonnées du skill garde-fou gcloud, liste d’outils du MCP Developer Knowledge. Les utilisateurs disent « l’agent sait chercher la doc Cloud ». En données, tools a gagné quelques entrées. Différenciez l’instantané et les plugin.json / mcp.json commités : vous attraperez qui réécrit le runtime dans les fichiers d’emballage. C’est du drift, pas un champ de spec.

{
  "plugin": {
    "name": "invoice-ops",
    "version": "1.2.0",
    "spec": "1.0.0"
  },
  "skills": [
    {
      "name": "write-weekly-summary",
      "description": "Turn invoice query results into the weekly summary finance reads. Use when the user asks for a week-end report.",
      "path": "skills/write-weekly-summary/SKILL.md",
      "loaded": "metadata"
    }
  ],
  "mcpServers": [
    {
      "id": "invoice-tools",
      "type": "streamable-http",
      "status": "connected"
    }
  ],
  "tools": [
    {
      "name": "query_invoices",
      "server": "invoice-tools",
      "inputSchema": {
        "type": "object",
        "required": ["week"],
        "properties": {
          "week": { "type": "string", "pattern": "^[0-9]{4}-W[0-9]{2}$" },
          "status": { "type": "string", "enum": ["open", "paid", "overdue"] }
        }
      }
    }
  ]
}

Saut Skill : le frontmatter devient la surface de découverte

Agent Plugins ne réécrit pas SKILL.md. Une seule règle de découverte : un enfant direct de skills/ qui contient un fichier régulier nommé exactement SKILL.md. Caché dans skills/deploy/extra/SKILL.md, il est invisible. Un skill hors Agent Skills DOIT être sauté ; les autres skills et le MCP continuent. Ce qui entre dans le contexte : name et description du frontmatter, plus un chemin pour relire plus tard le corps, scripts/ et references/.

La description doit dire quoi et quand. invoice-ops-skill-v2 ou un slogan à la première personne : surface de découverte nulle — la boîte est installée, le modèle ne la choisit jamais, les utilisateurs accusent le plugin. C’est le brief qui est cassé. scripts/ veut toujours dire « lance ça avec le shell que tu as déjà » ; les arguments sont argv, pas des outils de premier rang issus de tools/list. Pas de noms de scripts dans tools[] de l’instantané. S’ils y sont, quelqu’un a classé une pièce jointe de Skill comme MCP.

Charger le corps à la demande économise la fenêtre. Garder loaded: metadata dans l’instantané attrape la régression qui verse tout un runbook dans le prompt système. Une fenêtre saturée par un brief est un bug de politique de chargement client, pas un bug de format Plugin. La spec garantit seulement que le skill peut être trouvé. La façon de l’exposer au modèle et à l’utilisateur reste définie par le client.

Saut MCP : connecter, puis tools/list

mcp.json DOIT être à la racine. Pas d’inline dans plugin.json, pas d’autre chemin cœur. Premier niveau : seulement $schema et mcpServers. Fixez $schema à https://agent-plugins.org/schemas/1.0.0/mcp.schema.json, et il DOIT coller à la version de spec du manifeste. Écart : MCP de ce plugin seulement coupé. Chaque serveur DOIT poser type explicitement : stdio, streamable-http, ou sse héritage optionnel. Ne pas déduire le transport de la forme de l’objet. Une url streamable-http DOIT être http/https absolue ; hors loopback, https. headers sont des données d’emballage visibles, pas un tiroir à secrets.

La surface de découverte après connexion, c’est tools/list. Le fichier d’emballage dit où se connecter. Le contrat d’outil dit si les arguments de ce hop sont légaux. Ne copiez pas inputSchema dans plugin.json, ni name / version dans inputSchema. Un échec d’auth est un échec de connexion de ce serveur, pas une config plugin illégale — la spec ne définit pas de champs OAuth portables ; les secrets restent dans le runtime client. Détail filaire : Qu’est-ce que MCP.

Ci-dessous un fragment MCP distant portable. Pas de clé API dans les fixtures du dépôt. Après connexion, versez tools/list dans tools[] de l’instantané. Un échec de poignée saute ce serveur-là ; les autres serveurs et les skills continuent. Cette frontière d’échec est dans la spec, pas un slogan produit.

{
  "$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
  "mcpServers": {
    "invoice-tools": {
      "type": "streamable-http",
      "url": "https://billing.example.com/mcp"
    }
  }
}
Échec Ce qui meurt Ce qui reste
Majuscule dans name de plugin.jsonTout le paquet ; aucun composantRien
$schema de mcp.json en désaccord avec le manifesteTout le MCP de ce pluginLes skills continuent
Un SKILL.md au frontmatter casséCe skill-làAutres skills + MCP

Échecs indépendants, fixtures dans JSONVue

Au moins quatre fixtures de revue : le plugin.json légal ci-dessus, l’instantané, un mcp.json portable, un objet arguments query_invoices. Le premier DOIT passer plugin.schema.json officiel. Le deuxième : votre schéma d’instantané, ou des asserts de structure — ne forcez pas le schéma d’emballage. Le troisième passe mcp.schema.json. Le quatrième passe l’inputSchema de l’outil. Quatre JSON, quatre métiers : identité, inventaire, connexion, appel.

Deux négatifs : name = Invoice-Ops ; retirer type d’une entrée mcp.json. Le premier DOIT rejeter le paquet. Le second saute seulement ce serveur. Si la CI traite un champ de premier niveau inconnu comme fatal, vous êtes plus stricts que le client — la spec dit signaler, ignorer, continuer. Aucun secret dans une fixture commitée.

Ça se fait dans le navigateur :Formateur JSONpour voir si manifeste, instantané et mcp.json parsent ;Validateur JSON Schemapour $schema, name, mcpServers et inputSchema ;JSON Diffpour attraper le runtime réécrit dans les fichiers d’emballage. Rien ne quitte la machine. Pour aller plus loin :MCP et JSON Schema, l’aperçu Plugins, et quand emballer.

Liens : Google Agent Plugins 2026, Skills vs MCP vs Plugins, MCP et JSON Schema, Qu’est-ce que MCP.

FAQ

Installer un Plugin, c’est fine-tuner le modèle ?

Non. Les poids ne bougent pas. Le client a gagné un objet d’identité, des métadonnées de skills, et des contrats d’outils issus de tools/list. Il « sait » parce que la surface de découverte a changé, pas parce que le modèle a appris la facturation.

Puis-je mettre la liste d’outils dans plugin.json et sauter mcp.json ?

Non. Le manifeste n’inline pas les composants et ne change pas les chemins de découverte. La liste arrive de tools/list après la poignée. En tête de plugin.json, elle est ignorée. Sous extensions, elle ne vaut que pour un client et disparaît au suivant.

Puis-je valider l’instantané avec plugin.schema.json officiel ?

Non. Le schéma officiel décrit l’identité de la boîte. L’instantané est un inventaire assemblé par le client : status runtime et inputSchema d’outil. Écrivez un schéma d’instantané, ou assertez en CI les champs qui comptent.

L’UX d’install change selon le client. Le Plugin reste-t-il portable ?

L’emballage est portable. L’install n’a pas à l’être. La spec exclut install, permissions et bac à sable exprès. Changez de client : le répertoire et les deux JSON fermés restent. Les dialogues de confirmation et la politique entreprise peuvent diverger.

À retenir et suite

En 2026, « un Plugin donne automatiquement des capacités à un agent de code » tient en une ligne : une nouvelle capacité est un résultat de découverte, pas un poids. Cinq sauts plus tard, la mémoire tient identité, métadonnées de skills et contrats d’outils. Un saut manqué, et les utilisateurs disent « installé, toujours incapable ».

Livrer dans cet ordre : faire passer plugin.json au schéma officiel ; parcourir skills/ et mcp.json ; figer une fixture d’instantané ; valider le premier tools/call contre inputSchema. Garder les quatre contrats dans JSONVue. La boîte : article Plugins. Emballer ou non : article de décision. Le fil : articles MCP.