SPONSORED / REPO SPOTLIGHT

Por dentro de finestructure-ai/claude-plugin: un plugin de Claude Code en siete archivos

finestructure-ai/claude-plugin empaqueta la plataforma de aplicaciones Fine Structure como plugin de Claude Code y ofrece /deploy, /fs-status y /fs-domain junto con un conector MCP alojado que hace el trabajo real. Merece la pena leerlo menos por lo que despliega y más por lo que enseña sobre el formato de plugin: todo es markdown y JSON, menos de catorce kilobytes, sin paso de compilación y sin salida compilada.

THE REPOSITORY

finestructure-ai/claude-pluginSponsored

Open finestructure-ai/claude-plugin

El repositorio entero son siete archivos

Clónalo y el árbol de archivos cabe en una sola pantalla:

.claude-plugin/
  plugin.json        686 B
  marketplace.json   507 B
commands/
  deploy.md          3.3 KB
  fs-domain.md       905 B
  fs-status.md       741 B
skills/
  fine-structure/
    SKILL.md         4.0 KB
LICENSE              MIT
README.md            2.3 KB

No hay package.json, ni lockfile, ni CI, ni dist. Nada se compila ni se empaqueta, y no existe versión de este repositorio cuya construcción pueda fallar. Si has ido posponiendo escribir un plugin porque dabas por hecho que hacía falta una cadena de herramientas, esta es la corrección: el formato es una convención de directorios más dos archivos JSON, y el resto es prosa.

plugin.json es un puntero, no un programa

El manifiesto lleva los campos de identidad habituales (name, versión 0.1.0, description, author, homepage, repository, license, keywords) y después un único bloque que hace todo el trabajo interesante:

"mcpServers": {
  "finestructure": {
    "type": "http",
    "url": "https://finestructure.ai/api/mcp"
  }
}

Dos claves. Sin command, sin args, sin env. Compáralo con la forma que adopta la mayoría de las configuraciones MCP: un proceso local (npx, uvx, una ruta a un binario), una lista de argumentos y un mapa env con una clave de API. Declarar en su lugar un endpoint streamable HTTP saca el servidor de la máquina del usuario, y por eso 105 herramientas (la cifra que da el archivo de skill) caben detrás de un manifiesto de 686 bytes. Nada en la versión de Node o de Python del usuario puede romper la instalación, y los cambios del lado del servidor llegan sin publicar una versión del plugin. El precio es la reproducibilidad: no puedes fijar la superficie de herramientas desde el cliente.

marketplace.json convierte el repositorio en su propio canal de distribución

Claude Code instala plugins desde marketplaces, no desde un registro de paquetes, y un marketplace es un archivo JSON que lista plugins con una ruta de origen. El segundo archivo de .claude-plugin hace justo eso, y su única entrada de plugin tiene "source": "./". El repositorio es a la vez el plugin y el marketplace que lo sirve, así que publicar es un git push público:

/plugin marketplace add finestructure-ai/claude-plugin
/plugin install finestructure@finestructure

Los dos tokens idénticos de la segunda línea son el nombre del plugin en el nombre del marketplace, y coinciden porque los dos se llaman finestructure. Si copias esta disposición, ponles nombres distintos. Las instrucciones de instalación quedan más claras y te dejas sitio para añadir un segundo plugin más adelante.

Los comandos son plantillas de prompt con frontmatter

Cada archivo de commands/ es frontmatter YAML más prosa. deploy.md declara un description y un argument-hint, las dos cadenas que el usuario ve en el selector, y luego despliega un árbol de decisión numerado: mirar en la raíz del proyecto si hay un .finestructure.json con un app_id, si no llamar a list_apps y buscar una coincidencia de nombre, y si tampoco, tratarlo como primer despliegue y usar $ARGUMENTS como nombre de la aplicación. fs-status.md ocupa 741 bytes y hace el trabajo de un subcomando de CLI: resolver la aplicación, llamar a get_app_status, get_app_links y get_errors, y resumir. fs-domain.md recorre en orden add_custom_domain, get_domain_verification, check_domain_verification, get_domain_ssl_status y set_primary_domain.

El punto de diseño: ninguno de estos archivos llama a nada. Nombran herramientas, fijan un orden y describen qué hacer cuando un paso falla. La ejecución ocurre cuando el modelo invoca herramientas MCP. Un comando de barra es un prompt versionado, así que revisarlo no es preguntar si la lógica es correcta, sino si la instrucción es ambigua.

Las mejores líneas son las negativas. deploy.md prohíbe las herramientas de borrado salvo que el usuario lo pida de forma explícita. fs-domain.md advierte de que la propagación de DNS tarda de minutos a horas e indica que se sugiera reintentar más tarde en lugar de entrar en un bucle de verificación. Eso es política de reintentos y barreras de seguridad escritas como frases, y es justo lo que omiten los plugins ingenuos.

Skill frente a command: tirar frente a empujar

skills/fine-structure/SKILL.md tiene dos campos de frontmatter, name y description, y la description se lee como una condición de activación y no como un resumen: usar siempre que el usuario quiera desplegar, crear o actualizar una aplicación, conectar un dominio o gestionar datos o secretos. Esa formulación es deliberada. Un comando se dispara porque una persona lo ha escrito. Un skill se dispara porque el modelo ha emparejado la descripción con lo que está pasando.

El reparto de contenido se deduce de ahí. SKILL.md es un modelo mental, no una lista de tareas: qué es aquí una aplicación (páginas JSX, componentes compartidos, esquemas de entidades, ningún código de servidor arbitrario), qué son las entidades y qué operaciones gastan créditos. Después los flujos de trabajo como cadenas de herramientas, de get_app_files a read_app_file, a write_app_file, a validate_app y a publish_app, con conjuntos de cambios para las ediciones de varios archivos. Y después la semántica de errores, que es lo que más pesa por byte: los errores de autenticación significan volver a conectar, los de crédito significan recargar, y ninguno de los dos admite reintento. Un agente sin ese conocimiento reintenta en bucle un fallo que no se puede reintentar, y en una plataforma con contador ese bucle tiene precio.

La regla para tu propio plugin sale sola. Si un archivo de comando está explicando qué es tu producto, ese párrafo pertenece al skill. Los comandos se quedan en procedimientos.

OAuth es la razón de que el manifiesto no guarde secretos

El endpoint se autentica con OAuth 2.1 y registro dinámico de cliente, así que la primera llamada a una herramienta abre una página de consentimiento en el navegador y el token acaba en el almacén de credenciales de Claude Code, no en el repositorio. Un fork es seguro por construcción, la revocación es del lado del servidor y no una edición de configuración que tenga que llegar a cada máquina, y a nadie se le pide pegar una clave de larga duración en un archivo que está a un commit descuidado de un diff público.

Qué copiar para tu propio plugin

Indicaciones concretas, más o menos en orden de construcción:

  • Empieza con .claude-plugin/plugin.json con name, version y description. Todo lo demás es opcional.
  • Si tienes un endpoint MCP alojado, declara "type": "http" con una url en lugar de un comando local. Eso borra el entorno de ejecución del usuario de tu superficie de soporte.
  • Publica marketplace.json en el mismo repositorio con "source": "./" mientras solo tengas un plugin, y ponle un nombre distinto del plugin.
  • Da a cada comando un description y un argument-hint en el frontmatter, escritos como respuestas a qué hace esto y qué escribo después.
  • Usa $ARGUMENTS en vez de inventarte una sintaxis posicional. No hay analizador, solo sustitución.
  • Escribe los cuerpos de los comandos como árboles de decisión con las herramientas nombradas de forma explícita. "Si existe el archivo de configuración lee app_id, si no llama a list_apps" aguanta mejor que un párrafo de intenciones.
  • Pon por escrito la semántica de los fallos: qué errores son terminales, cuáles admiten reintento y qué decir en lugar de reintentar.
  • Nombra tus herramientas destructivas en la prosa y prohíbelas salvo petición expresa.
  • Mantén el modelo de dominio en SKILL.md y el procedimiento en el comando. La duplicación entre ambos es mala señal.
  • Prueba con /plugin marketplace add contra una ruta local o contra tu fork antes de mandar a nadie a main.

Aristas

Tres, con honestidad, y ninguna es fatal. Todo está en inglés, y el formato no ofrece ningún gancho para arreglarlo: no hay clave locale en el frontmatter, así que localizar significa duplicar archivos de comando o aceptar el desajuste.

La historia de que no hay claves de API tiene un asterisco. SKILL.md admite que las herramientas de generación de medios quedan fuera de la conexión OAuth y necesitan un token MCP estático con permisos de medios, creado en el Studio de la plataforma y enviado en una cabecera bearer. El plugin lo gestiona bien, porque le dice al modelo que explique la ausencia en lugar de reintentar contra un muro, pero es una segunda vía de autenticación atornillada a un diseño cuyo argumento de venta es tener una sola.

Y es la versión 0.1.0, sin changelog, sin pruebas y sin CI. Para markdown eso es defendible, aunque una comprobación de esquema JSON en un hook de pre-commit atraparía la única clase de error que de verdad rompe instalaciones, un manifiesto mal formado. El envío al directorio está en revisión en el momento de escribir esto, así que por ahora se instala por referencia al repositorio.

Lee primero los tres archivos de comandos, después SKILL.md y al final los dos archivos JSON. En ese orden el formato se explica solo: el markdown decide qué debe pasar y en qué orden, el servidor MCP decide qué se ejecuta de verdad, y el manifiesto es la costura fina entre ambos.

QUESTIONS

Asked about this repository

¿cuál es la estructura mínima de archivos para un plugin de claude code?
Un archivo: .claude-plugin/plugin.json con un name, una version y una description. Comandos, skills, agentes y hooks son capas opcionales encima. finestructure-ai/claude-plugin sirve de referencia de tamaño porque usa varias de esas capas y aun así suma siete archivos y menos de catorce kilobytes, sin paso de compilación.
¿cómo funcionan los comandos de barra en un plugin de claude code?
Un comando de barra es un archivo markdown en commands/ cuyo nombre de archivo pasa a ser el nombre del comando. El frontmatter aporta un description y un argument-hint para el selector, y el cuerpo es un prompt que el modelo recibe cuando el comando se ejecuta, con $ARGUMENTS sustituido por lo que venga detrás. El archivo no ejecuta nada por sí mismo, así que el trabajo real tiene que venir de herramientas que el modelo pueda llamar, y por eso este plugin empareja comandos con un servidor MCP.
¿necesito una clave de API para usar un servidor MCP en un plugin de claude code?
No, si el servidor habla OAuth. Este manifiesto declara solo "type": "http" y una url, y el endpoint usa OAuth 2.1 con registro dinámico de cliente, así que la autorización ocurre en el navegador y el token se queda en el almacén de credenciales de Claude Code. La alternativa, un bloque env con una clave, funciona pero pone un secreto de larga duración en un archivo que los usuarios copian de un sitio a otro. Una salvedad visible aquí: las herramientas de medios quedan fuera de ese flujo y siguen necesitando un token estático.
¿cómo convierto un repositorio de github en un marketplace de plugins de claude code?
Añade .claude-plugin/marketplace.json con un name, un owner y un array plugins. Si sirve un plugin del mismo repositorio, pon el source de ese plugin en "./", que es lo que hace este repositorio. Los usuarios ejecutan entonces /plugin marketplace add owner/repo seguido de /plugin install plugin-name@marketplace-name. No hay registro ni paso de publicación entre un git push y un plugin instalable.

THE SPONSOR

The platform behind the endpoint

Fine Structure runs the hosted MCP server this plugin points at, and sponsors this publication.

finestructure.ai