Versionado, compatibilidad y conformidad
Versionado, compatibilidad y conformidad
En un plugin conviven dos relojes distintos que se parecen mucho y que no significan lo mismo:
- La versión de la especificación a la que apunta el paquete. Vive en el
campo
$schemadeplugin.jsony, si existe, también en el$schemademcp.json. - La versión de tu plugin. Vive en el campo opcional
versiondel manifiesto.
Cada uno tiene reglas y consecuencias propias cuando algo no calza. Este capítulo
separa los dos relojes, extrae la lista completa de requisitos de conformidad de
cada rol —paquete y cliente— y cierra con una estrategia de evolución para un
plugin propio. Lo que venga de FUTURE_CONSIDERATIONS.md, del apéndice A o de
Design Decisions se marca como no normativo.
flowchart TD
A["plugin.json"] --> B["$schema — versión de la ESPECIFICACIÓN"]
A --> C["version — versión de TU PLUGIN"]
B --> D["Selecciona reglas de validación e interpretación en el cliente"]
B --> E["Si mcp.json existe, DEBE declarar la misma versión"]
C --> F["El cliente PUEDE usarla para actualizaciones y frescura de caché"]
C --> G["El cliente NO DEBE rechazar el manifiesto por no ser SemVer"]
1. Cómo se versiona la especificación
1.1 Una versión cubre tres artefactos
La sección 10.1 es tajante: la versión declarada en la sección 1 identifica el
release completo de la especificación, y eso incluye tres cosas a la vez: el
texto normativo, el esquema del manifiesto (plugin.schema.json) y el esquema de
configuración MCP (mcp.schema.json). Y añade una regla que sorprende a quien
viene de otros ecosistemas:
“Every specification release MUST publish both schemas with the same version as the specification, even when a schema’s validation rules are unchanged from the previous release.”
Es decir: cada release DEBE (MUST) publicar los dos esquemas con la misma versión que la especificación, aunque las reglas de validación de uno de ellos no hayan cambiado. No existen tres líneas de versión independientes; hay una sola.
El apartado no normativo Why do schemas share the specification version?
explica el motivo: darle a autores y clientes una sola versión del formato
portable que entender, impedir paquetes de versiones mezcladas y permitir que
$schema seleccione el contrato completo de validación e interpretación,
incluidos los requisitos que JSON Schema no puede expresar.
1.2 $schema es un selector de versión, no una descarga
El $schema obligatorio de plugin.json identifica la versión de Agent Plugins
a la que apunta el paquete. Para 1.0.0 su valor DEBE ser exactamente el
identificador canónico:
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "minimal-plugin"
}
Y las reglas del cliente son estas, literales de la sección 5.2:
- El cliente DEBE (MUST) usar un valor de
$schemareconocido para seleccionar las reglas de validación e interpretación soportadas localmente. - El cliente PUEDE (MAY) mapear varios identificadores canónicos a la misma implementación, pero solo cuando reconoce explícitamente esas versiones de Agent Plugins como compatibles.
- El cliente NO DEBE (MUST NOT) recuperar un esquema mientras carga un plugin.
- Si el cliente no soporta la versión declarada ni una versión explícitamente reconocida como compatible, DEBE rechazar el plugin y DEBERÍA (SHOULD) reportar la versión no soportada.
Esa tercera regla define la naturaleza del campo: la URL nunca se descarga. Es un identificador opaco que actúa como llave de un diccionario local de implementaciones. Un cliente sin red carga un plugin igual de bien.
La sección 7.2.1 repite palabra por palabra el mismo trío de reglas para el
$schema de mcp.json, cuyo identificador canónico en 1.0.0 es
https://agent-plugins.org/schemas/1.0.0/mcp.schema.json.
1.3 Las dos versiones del paquete deben coincidir entre sí
Cuando un plugin trae mcp.json, la versión de su $schema DEBE coincidir
con la versión declarada por plugin.json. Un desajuste tiene una consecuencia
muy acotada:
“A mismatch makes the MCP configuration invalid under §7.2.2 but does not invalidate other component types.”
Traducido a comportamiento observable: si tu plugin apunta a 1.0.0 en
plugin.json y a otra versión en mcp.json, el cliente DEBE deshabilitar
MCP para ese plugin, DEBERÍA reportar el desajuste y seguirá cargando tus
skills. El plugin no muere; pierde una pata. Es el mismo principio de fronteras
de fallo estrechas del capítulo de
descubrimiento y carga.
1.4 Los identificadores canónicos son inmutables
Dos reglas cierran el modelo: un cambio en cualquiera de los dos esquemas
requiere un nuevo release de la especificación, y los identificadores
canónicos ya publicados NO DEBEN (MUST NOT) ser reasignados a contenidos de
esquema distintos. Una vez que
https://agent-plugins.org/schemas/1.0.0/plugin.schema.json describe un conjunto
de reglas, queda amarrado a ellas para siempre, y un cliente puede cachear esa
interpretación sin miedo a que el significado cambie bajo sus pies.
La contrapartida para los autores es generosa: los plugins existentes PUEDEN (MAY) seguir apuntando a una versión antigua. No hay caducidad forzada en el formato; los clientes deciden qué soportan con los identificadores canónicos declarados y sus mapeos explícitos de compatibilidad.
flowchart TD
A["El cliente lee $schema de plugin.json"] --> B{"¿Identificador reconocido localmente?"}
B -- No --> C["Rechaza el plugin y DEBERÍA reportar la versión no soportada"]
B -- Si --> D["Selecciona las reglas de validación de esa versión"]
D --> E{"¿Existe mcp.json?"}
E -- No --> F["Ausencia de ubicación fija: no es error"]
E -- Si --> G{"¿Su $schema declara la misma versión?"}
G -- No --> H["Deshabilita MCP para ese plugin y sigue cargando skills"]
G -- Si --> I["Valida mcp.json y cada entrada de servidor por separado"]
2. Qué significa exactamente 1.0.0
La cabecera declara **Spec Version: 1.0.0** y **Status: Published**. La
sección 1 fija el alcance del compromiso:
“Clients and plugin packages claiming conformance to Agent Plugins v1 MUST implement or follow the requirements in this document.”
Nótese la simetría: la obligación cae por igual sobre clientes y sobre paquetes de plugin. No es una especificación que solo regule runtimes; el paquete también tiene requisitos que cumplir, y la sección 3 los enumera todos.
2.1 Lo que 1.0.0 sí garantiza
Un plugin que declare 1.0.0 y respete el documento puede contar con que cualquier cliente conformante:
| Garantía | Sección |
|---|---|
Buscará el manifiesto en plugin.json en la raíz del plugin | §5.1 |
| Validará el manifiesto contra un esquema cerrado de 10 campos | §5.2 |
Descubrirá skills en skills/, solo en hijos inmediatos con SKILL.md | §6.1, §7.1 |
Descubrirá servidores MCP únicamente en mcp.json de la raíz | §6.1, §7.2 |
| No tratará como error la ausencia de una ubicación fija | §6.2 |
Ignorará los namespaces de extensions que no implemente, sin validarlos | §8.1 |
| Rechazará cualquier ruta de paquete que resuelva fuera de la raíz del plugin | §4.1 |
Si lanza subprocesos, proveerá PLUGIN_ROOT y PLUGIN_DATA | §9.1 |
Expandirá ${PLUGIN_ROOT} y ${PLUGIN_DATA} solo en args, env y cwd | §9.2 |
| No hará que el fallo de un componente tumbe a los demás | §11.3 |
2.2 Lo que 1.0.0 explícitamente no cubre
FUTURE_CONSIDERATIONS.md es no normativo y aclara que ninguno de sus puntos
es requisito de conformidad ni está comprometido para un release futuro. Con esa
advertencia, lo que allí se reconoce como ausente en 1.0.0 es:
- Permisos y UX de aprobación: no hay modelo de confianza, ni sistema de permisos, ni requisitos de sandboxing.
- Verificación de procedencia: no hay firmas criptográficas ni atestación.
- Manejo de secretos: no hay campo
secretsni inyección mediada por el cliente. Por eso la spec prohíbe embeber credenciales enenvyheadersen vez de ofrecer un mecanismo. - Controles empresariales: no hay allowlists, registros de organización ni overrides centralizados.
- Estandarización de auditoría: hay requisitos de reporte de fallos, pero no un esquema de eventos de ciclo de vida.
- Resolución de dependencias: no existe campo
dependencies. - Testing y validación: literalmente “No test harness or validation tool is specified.”
Ese último punto es el que más se malinterpreta: que no exista validador oficial no significa que no puedas validar, sino que la validación la construyes tú con validadores genéricos de JSON Schema, como veremos en el capítulo 8.
La sección no normativa Why only Agent Skills and MCP in v1? explica además por qué el catálogo de componentes es tan corto: skills y MCP tienen especificaciones establecidas fuera de este proyecto y adopción real entre clientes. Comandos, hooks, agentes, reglas y servidores LSP se consideraron demasiado específicos de cada cliente para un contrato portable estable.
3. Conformidad del paquete: la lista completa
Requisitos cuyo sujeto normativo es el plugin, su manifiesto, su configuración o su autor. Cada fila cita la sección de la spec.
3.1 Estructura y manifiesto
| Nivel | Requisito |
|---|---|
| DEBE | Un plugin incluye un manifiesto en plugin.json en la raíz del plugin (§4.1). |
| DEBE | El manifiesto es JSON y contiene un objeto de nivel superior (§5.2). |
| DEBE | Todo campo permitido cumple el tipo y las restricciones definidas (§5.2). |
| DEBE | Para 1.0.0, $schema vale exactamente el identificador canónico del esquema de manifiesto (§5.2). |
| DEBE | El name cumple las cuatro restricciones de §5.5: 1 a 64 caracteres, solo a-z, 0-9, - y ., primer y último carácter alfanuméricos, sin -- ni .. consecutivos. |
| PUEDE | El objeto author contiene únicamente name, email y url, cada uno string. Cualquier otro campo o tipo invalida el manifiesto (§5.4). |
| RECOMENDADO | version usa Versionado Semántico (§5.4). |
| RECOMENDADO | license usa un identificador SPDX (§5.4). |
| DEBE | Un campo de configuración definido como ruta relativa al plugin empieza con ./, se resuelve contra la raíz del plugin y permanece dentro de ella tras resolverse (§4.1). |
3.2 Componentes
| Nivel | Requisito |
|---|---|
| DEBE | Las Agent Skills conforman la Agent Skills specification, que la §7.1 declara fuente de verdad del formato de SKILL.md, sus campos de frontmatter y su layout de directorios (curso de Agent Skills). |
| NO DEBE | La configuración MCP se declara inline en plugin.json ni se carga desde ninguna ruta core alternativa (§7.2.1). |
| DEBE | mcp.json es un objeto JSON con los campos obligatorios $schema y mcpServers, y ningún otro campo de nivel superior (§7.2.1). |
| DEBE | mcpServers es un objeto cuyos nombres de miembro identifican servidores y cuyos valores son objetos de configuración (§7.2.1). |
| DEBE | Para 1.0.0, el $schema de mcp.json vale exactamente el identificador canónico del esquema MCP (§7.2.1). |
| DEBE | Cada configuración de servidor contiene type y casa exactamente con una de las variantes cerradas (§7.2.1). |
| DEBE | command es un único token ejecutable, no una cadena de shell; nombre desnudo o ruta relativa al plugin que empieza con ./ (§7.2.1). |
| NO DEBE | Un plugin que reclama conformidad depende de que un PATH configurado afecte la resolución de un command desnudo (§7.2.1). |
| DEBE | Un plugin que empaqueta un ejecutable usa un command relativo al plugin (§7.2.1). |
| DEBE | cwd, cuando está presente, tiene una de las tres formas admitidas y permanece contenido tras resolverse (§7.2.1). |
| DEBE | url es una URL absoluta HTTP o HTTPS, sin user-info ni fragmento; los endpoints no loopback usan HTTPS (§7.2.1). |
| DEBE | Los nombres y valores de header son campos HTTP válidos (§7.2.1). |
| NO DEBE | Los plugins embeben credenciales u otros secretos en headers (§7.2.1). |
| NO DEBE | Los plugins embeben credenciales u otros secretos en env (§9.2). |
| NO DEBE | El env de un servidor MCP contiene entradas llamadas PLUGIN_ROOT o PLUGIN_DATA (§9.2). |
| NO DEBE | Salvo la búsqueda de ejecutables de la plataforma para resolver un command desnudo, un plugin conformante depende de una variable del entorno base que la spec no exija ni la configuración de servidor suministre explícitamente (§9.1). |
3.3 Extensiones y versionado
| Nivel | Requisito |
|---|---|
| DEBE | Los datos de manifiesto específicos de cliente se representan bajo un namespace de dominio inverso en extensions (§8). |
| DEBE | Los archivos específicos de cliente se representan bajo un directorio de nivel superior con el nombre de ese namespace (§8). |
| DEBE | extensions es un objeto cuyos nombres de miembro son namespaces y cuyos valores son objetos (§8.1). |
| DEBE | Si mcp.json está presente, la versión de su $schema coincide con la declarada por plugin.json (§10.1). |
| PUEDE | Un plugin existente sigue apuntando a una versión anterior de Agent Plugins (§10.1). |
| DEBERÍA | El plugin usa Versionado Semántico para version (§10.2). |
4. Conformidad del cliente: la lista completa
La sección 11.1 abre con la regla general: “A conformant client MUST satisfy all applicable requirements in sections 1–10.” Todo lo anterior aplica. Sobre esa base, el documento enumera ocho capacidades mínimas:
- Puede cargar un plugin desde una ruta de directorio.
- Selecciona desde
$schemaun esquema de manifiesto soportado localmente, y luego parsea y valida el esquema cerrado deplugin.jsonusando las excepciones no fatales de §5.2 y §8.1. - Ignora los miembros no implementados de
extensionssin validar el contenido de sus valores. - Para cada tipo de componente que soporta, descubre los componentes en su ubicación fija.
- Si soporta servidores MCP, selecciona desde
$schemauna configuración MCP soportada localmente y soporta al menos una de las variantesstdioostreamable-httpdemcp.json. - Si lanza subprocesos de plugin —es decir, servidores MCP stdio— provee
PLUGIN_ROOTyPLUGIN_DATAy expande ambas variables en los valores de configuración de runtime:args,envycwd. - Para servidores MCP stdio, resuelve
commandcomo un único token ejecutable y usa la raíz del plugin como directorio de trabajo por defecto del subproceso. - Soporta al menos un tipo de componente: skills o servidores MCP.
4.1 Adopción incremental
La sección 11.2 desactiva la lectura maximalista de esa lista: “A client is not required to support every component type. For example, a skills-only client can conform without supporting MCP servers, provided it satisfies all applicable requirements.”
Un cliente que solo entiende skills es conformante. Y dentro de MCP, DEBE
soportar al menos uno de stdio o streamable-http, DEBERÍA soportar ambos,
y el soporte de sse es OPCIONAL. La palabra clave del punto 1 de 11.1 es
applicable: los requisitos de MCP no aplican a quien no implementa MCP.
4.2 Componentes no soportados y fallos
La sección 11.3 son cuatro reglas cortas que definen el carácter resiliente del formato:
- El cliente DEBE ignorar los tipos de componente que no soporta.
- Un campo de nivel superior desconocido o un
extensionsque no sea objeto son no fatales bajo §5.2 y §8.1. Cualquier otra violación del esquema deplugin.jsones fatal para el plugin: el cliente DEBE rechazarlo y NO DEBE descubrir ni ejecutar ninguno de sus componentes. - Un fallo aislado a un tipo de componente, a una entrada de componente o a un proceso de componente NO DEBE impedir que el cliente cargue los componentes que sean válidos de forma independiente.
- El cliente DEBERÍA reportar configuración inválida y fallos de componente. PUEDE reportar plugins parcialmente soportados, pero la falta de soporte para un tipo de componente, un transporte MCP o una extensión de cliente no es en sí misma un error.
Ese último matiz importa a quien escribe un cliente: no soportar algo no es un fallo que reportar como error, es una decisión de alcance legítima.
4.3 El apéndice A no es la especificación
El documento incluye un Conformance Checklist con 25 casillas repartidas en cinco bloques: plugin loader (7), component discovery (2), MCP configuration (4), environment and expansion (8) y resilience (4). Sirve para auditar una implementación de un vistazo, pero el propio apéndice avisa: “This checklist is for convenience only — when it conflicts with the spec text above, the spec governs.” El apéndice A y Design Decisions son no normativos; todas las demás secciones sí lo son.
5. Extensiones y campos propietarios sin romper la portabilidad
El manifiesto es un esquema cerrado: los únicos campos de nivel superior
permitidos son $schema, name, version, description, author, homepage,
repository, license, keywords y extensions. Cualquier otro campo raíz no
conforma al esquema.
Pero la consecuencia es deliberadamente suave: el cliente DEBE reportar e ignorar cada campo desconocido, DEBE seguir cargando el plugin si el resto del manifiesto cumple, y NO DEBE asignar semántica a campos desconocidos. Un campo inventado en la raíz no rompe el plugin, pero tampoco hace nada: ningún cliente puede interpretarlo sin violar la spec.
La vía correcta para datos propietarios es extensions, con clave de dominio
inverso:
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "example-plugin",
"extensions": {
"com.example.client": {
"setting": true
}
}
}
Y para archivos propietarios, un directorio de nivel superior con exactamente ese nombre de namespace:
my-plugin/
├── plugin.json
├── skills/
│ └── summarize/
│ └── SKILL.md
└── com.example.client/
└── hooks/
└── hooks.json
Reglas de portabilidad que hacen que esto funcione:
- Agent Plugins no asigna ninguna semántica portable de descubrimiento, validación, carga o fallo a los datos ni a los archivos de extensión. Cada cliente define el contenido y el comportamiento de su propio namespace.
- Un cliente DEBE ignorar las entradas de manifiesto de namespaces que no
implementa, sin validar el contenido de sus valores. Tu bloque
com.tuempresa.clientees invisible e inofensivo para el resto del ecosistema. - Un cliente DEBERÍA basar su namespace en un dominio que controle y DEBERÍA mantenerlo estable, y PUEDE usar una de las dos representaciones o ambas.
- Si
extensionsno es un objeto, el cliente DEBE reportar e ignorar el campo y continuar cargando componentes: es la segunda —y última— excepción no fatal del manifiesto.
El apartado no normativo Why reverse-domain client extensions? lo resume: los identificadores de dominio inverso dan una convención descentralizada para evitar colisiones sin necesitar un registro central de nombres de cliente.
flowchart TD
A["Necesitas declarar algo que la spec no define"] --> B{"¿Son datos o son archivos?"}
B -->|"Datos"| C["extensions con clave de dominio inverso en plugin.json"]
B -->|"Archivos"| D["Directorio de nivel superior con el nombre exacto del namespace"]
B -->|"Campo raíz inventado"| E["Violación del esquema cerrado: el cliente lo reporta e ignora"]
C --> F["Portable: los clientes ajenos lo ignoran sin validarlo"]
D --> F
E --> G["No aporta nada: ningún cliente puede asignarle semántica"]
5.1 La matriz de fatalidad, en una tabla
Situación en plugin.json | Consecuencia |
|---|---|
| Campo de nivel superior desconocido | No fatal: se reporta, se ignora y la carga continúa |
extensions presente pero no es un objeto | No fatal: se reporta, se ignora y la carga continúa |
Namespace de extensions que el cliente no implementa | Se ignora sin validar su contenido |
| Campo requerido ausente, de tipo incorrecto o vacío | Fatal: el plugin se rechaza; el cliente DEBERÍA decir cuál |
Campo desconocido dentro de author, o valor no string | Fatal: manifiesto inválido |
$schema de versión no soportada ni reconocida como compatible | Fatal: el plugin se rechaza; el cliente DEBERÍA reportar la versión |
| Cualquier otra violación del esquema | Fatal: ningún componente se descubre ni se ejecuta |
6. Versionado de tu plugin
6.1 Lo que dice la especificación
La sección 10.2 cabe en cuatro líneas. Los plugins DEBERÍAN (SHOULD) usar
Versionado Semántico para version, con esta tabla:
| Segmento | Significado | Descripción |
|---|---|---|
| Major | Cambio incompatible | Cambio de comportamiento o de esquema incompatible. |
| Minor | Funcionalidad retrocompatible | Comportamiento nuevo sin romper clientes ni usuarios existentes. |
| Patch | Corrección retrocompatible | Cambio correctivo sin ruptura de comportamiento intencionada. |
Y el cliente PUEDE (MAY) usar version para determinar si hay
actualizaciones disponibles y si las cachés están obsoletas.
Eso es todo lo normativo. Fíjate en lo que no dice:
- No obliga a incluir
version; es un campo opcional de metadatos (§5.4). - No define formato validado por esquema: en
plugin.schema.json,versiones simplemente"type": "string", sinpattern. - Y §5.4 lo blinda por el otro lado: el cliente NO DEBE rechazar un
manifiesto solo porque
versionno sea SemVer válido. La misma protección cubre ahomepage,repositoryyauthor.urlque no sean URLs reconocidas, aauthor.emailque no sea un email reconocido, y alicenseque no sea SPDX.
version es, por tanto, una señal cooperativa, no un contrato ejecutado por
el cliente: nadie te impedirá publicar version: "primavera-2", solo perderás la
capacidad de que las herramientas razonen sobre tus actualizaciones.
6.2 Qué cuenta como cambio mayor en un plugin
La spec da la definición abstracta —“cambio de comportamiento o de esquema incompatible”— pero no la traduce a los componentes concretos de un plugin. Lo que sigue es una guía práctica, no texto normativo: esa tabla aplicada a la superficie observable de un plugin, que son sus nombres y contratos visibles.
| Cambio | Segmento sugerido | Por qué |
|---|---|---|
Renombrar o eliminar un directorio bajo skills/ | Major | El skill deja de existir con ese nombre |
Renombrar o eliminar una clave de mcpServers | Major | El identificador del servidor cambia para el cliente |
Cambiar el type de un servidor de stdio a streamable-http | Major | Cambia el modelo de despliegue, de confianza y de red |
Cambiar el name del plugin | Major | Es la identidad del paquete |
Exigir una variable nueva en env que antes no hacía falta | Major | Rompe instalaciones existentes |
Subir la versión de Agent Plugins declarada en $schema | Major | Los clientes que solo soporten la anterior rechazarán el plugin |
Añadir un skill nuevo bajo skills/ | Minor | Superficie nueva sin quitar nada |
Añadir una entrada nueva a mcpServers | Minor | Los servidores existentes siguen igual |
Añadir un namespace nuevo en extensions | Minor | Quien no lo implementa lo ignora sin validarlo |
Corregir un bug en un script bajo skills/x/scripts/ | Patch | Comportamiento previsto sin cambio de contrato |
Cambiar description, homepage, keywords o author | Patch | Metadatos que no afectan el comportamiento |
El caso más subestimado es el sexto: subir la versión de spec declarada en
$schema es un cambio mayor de tu plugin, aunque tu código no cambie ni una
línea, porque un cliente que no reconoce el identificador nuevo DEBE rechazar
el plugin entero. Es la ruptura más total posible.
6.3 Estrategia de evolución en el tiempo
flowchart TD
A["Cambio propuesto en el plugin"] --> B{"¿Desaparece o se renombra algo que ya existía?"}
B -- Si --> C["Major"]
B -- No --> D{"¿Cambia el $schema de Agent Plugins?"}
D -- Si --> C
D -- No --> E{"¿Aparece superficie nueva?"}
E -- Si --> F["Minor"]
E -- No --> G["Patch"]
C --> H["Publicar CHANGELOG con la ruta de migración"]
F --> H
G --> H
Reglas de higiene que se derivan del formato:
- Mantén el
nameestable de por vida. Es la identidad del paquete y el esquema lo restringe con fuerza. Renombrar equivale a publicar un plugin distinto. - Usa
PLUGIN_DATApara todo lo que deba sobrevivir a una actualización. La spec obliga al cliente a preservar ese directorio entre actualizaciones, mientras quePLUGIN_ROOTse reemplaza al actualizar el paquete. Dependencias, código generado, cachés y estado van aPLUGIN_DATA; scripts, binarios y configuración empaquetada se referencian desdePLUGIN_ROOT. - Añade antes de quitar. Para renombrar un skill, publica primero una versión menor con el nombre nuevo junto al viejo, y elimina el viejo en la mayor siguiente. Los skills se descubren por nombre de directorio inmediato, así que dos directorios conviven sin conflicto.
- Cuando subas de versión de spec, sube ambos
$schemaa la vez. Si dejasmcp.jsonen la anterior, MCP se deshabilita entero mientras las skills siguen cargando: un fallo a medias que parece éxito. - Trata
CHANGELOG.mdcomo parte del paquete. El layout estándar de §4.2 lo muestra junto aLICENSEen la raíz. No es obligatorio, pero es el único lugar donde explicar una ruptura: la spec no define deprecación ni migración. - No dependas de nada que la spec no garantice. Un plugin conformante NO
DEBE depender de una variable del entorno base que la spec no exija o que la
configuración del servidor no suministre explícitamente, ni de que un
PATHconfigurado afecte la resolución de uncommanddesnudo.
6.4 La versión del plugin no es la versión del catálogo
Los catálogos reales suelen codificar la versión fuera del manifiesto: en el
repositorio google/skills, cada entrada fija la versión en un campo ref que
apunta a un tag de git y no publica version por plugin. Eso no es Agent
Plugins: la especificación no define el concepto de catálogo ni de marketplace,
y el término no aparece ni una vez en el documento. Es convención de producto,
que vemos en el capítulo 9
y en el curso hermano de Google Skills.
Consecuencia práctica: el version de tu plugin.json y el tag que publiques
son dos cosas que tú debes mantener sincronizadas.
7. Errores frecuentes
- Creer que
$schemase descarga. El cliente NO DEBE recuperar un esquema mientras carga un plugin. Es un selector de versión local. - Dejar
mcp.jsonen otra versión queplugin.json. No rompe el plugin, pero deshabilita MCP entero: parece cargar bien y le faltan las herramientas. - Meter campos propios en la raíz del manifiesto. El esquema es cerrado: van
bajo
extensions, con clave de dominio inverso. - Suponer que un cliente conformante soporta skills y MCP. Basta con uno
de los dos tipos de componente, y en MCP basta con
stdioostreamable-http. - Tomar el apéndice A o
FUTURE_CONSIDERATIONS.mdcomo norma. Ambos son no normativos; ante conflicto manda el texto de la especificación. - Guardar estado dentro de
PLUGIN_ROOT. Se pierde en la actualización siguiente. Ese es el problema quePLUGIN_DATAresuelve.
Resumen
- Agent Plugins versiona el release completo: el texto normativo y los dos esquemas comparten versión, y cada release DEBE publicar ambos aunque uno no haya cambiado.
$schemadeclara la versión de spec del paquete y el cliente lo usa como selector local: NO DEBE descargarlo, y si no la reconoce, rechaza el plugin.- Si existe
mcp.json, su$schemaDEBE declarar la misma versión queplugin.json. El desajuste deshabilita MCP, pero no invalida los demás tipos de componente. - Los identificadores canónicos publicados NO DEBEN reasignarse, y un plugin PUEDE seguir apuntando a una versión anterior.
- La conformidad obliga por igual a paquetes y a clientes: el cliente cumple ocho capacidades mínimas y puede soportar un solo tipo de componente.
- Solo dos situaciones del manifiesto son no fatales —campo raíz desconocido y
extensionsno objeto—; cualquier otra violación rechaza el plugin entero. - Lo propietario va en
extensionscon clave de dominio inverso o en un directorio de nivel superior con ese mismo nombre; los clientes ajenos lo ignoran sin validarlo. versiones una señal cooperativa: DEBERÍA ser SemVer, y subir el$schemade spec es, para tu plugin, un cambio mayor.- 1.0.0 no define permisos, firmas, secretos, dependencias ni validador oficial.