Tutoriales

Crear widgets de MCP Apps con un agente de IA

Casi todas las formas de crear una MCP App con Claude Code generan código en tu repo. Aquí tienes la otra: darle a tu agente tools para crear, diseñar y publicar widgets, con lo mismo que puedes hacer tú en la web.

8 min de lectura

¿Qué tal le fue a la tienda online en septiembre comparado con agosto?

Ha usado show_metrics

Un widget de MCP Apps de verdad, pintado como lo pinta un host. Hecho con Widgetry.

La respuesta corta

Para crear widgets con un agente de IA, conéctalo a un servidor MCP cuyas tools crean y editan widgets. El endpoint de Widgetry, https://widgets.gonzaloverdugo.com/mcp, es uno de ellos: conectas Claude, Claude Code o cualquier cliente MCP con permiso de edición, y el agente puede listar plantillas, crear un widget a partir de una, cambiar su esquema de datos, sus datos de ejemplo, el markup y los estilos, hacer un diseño, publicar el widget y darte el código para enlazarlo desde tu propio servidor. Hace lo mismo que una persona en la web, con 15 tools widgetry_*.

No es lo mismo que pedirle a un agente que escriba una MCP App desde cero en tu código. Las dos cosas sirven; la última sección las compara.

Por qué darle a un agente un servidor MCP para crear interfaces

Un widget de MCP Apps es una vista HTML que un host como ChatGPT o Claude pinta dentro de la conversación cuando se ejecuta una tool (lo tienes en qué son las MCP Apps). Escribirlo a mano supone empaquetar la vista, hablar el puente de postMessage, fijar una Content Security Policy y montar un servidor que registre el recurso y la tool.

Si el agente trabaja con tools, no toca nada de eso. Edita un widget que ya funciona: una plantilla Liquid, CSS que lee los tokens del diseño, un JSON Schema para los datos y unos datos de ejemplo que lo cumplen. El servidor comprueba cada cambio, y uno inválido vuelve con lo que hay que arreglar. El agente itera sobre lo que importa (qué enseña el widget y cómo se ve) y tú abres el resultado en el editor mientras trabaja.

Cómo conectar tu agente

La URL del MCP es la misma para todos los clientes: https://widgets.gonzaloverdugo.com/mcp. Lo que cambia es cómo se identifica cada uno. En los dos casos la credencial apunta a una organización, y el agente solo ve y cambia los widgets y los diseños de esa organización.

Claude y Claude Desktop: OAuth

Añade la URL como conector personalizado en claude.ai o en Claude Desktop. El cliente te lleva a Widgetry, entras con Google y eliges la organización en la pantalla de consentimiento. Esa pantalla también dice si el cliente pide solo leer o también escribir:

  • widgets:read: el agente ve la organización y puede enseñar sus widgets publicados.
  • widgets:write: además puede crear, editar, publicar y borrar widgets y diseños, si tu papel en esa organización lo permite.

El mismo flujo vale para otros clientes que conectan servidores MCP remotos con OAuth.

Claude Code, Codex y otros agentes: una clave de API

Los agentes de código y los scripts usan una clave de API que empieza por wgt_, enviada como token Bearer. La crea un propietario de la organización en Ajustes, con permiso de lectura o de lectura y escritura. Solo se enseña una vez, así que guárdala en cuanto aparezca.

En Claude Code, el comando es este:

bash
claude mcp add --transport http widgetry https://widgets.gonzaloverdugo.com/mcp \
  --header "Authorization: Bearer $WIDGETRY_API_KEY"

Cualquier otro cliente que admita servidores MCP por HTTP con cabeceras propias funciona igual: la URL más Authorization: Bearer wgt_.... Una clave de lectura le da al agente las tools de lectura; una de lectura y escritura, todas.

Las tools que recibe tu agente

Toda credencial recibe ocho tools de lectura. Solo una credencial que puede escribir recibe las otras siete. El servidor manda además al agente una guía corta en sus instrucciones (el contexto de Liquid, los tokens --wg-*, los scripts, las librerías y los dominios de imágenes), así que un modelo capaz puede empezar sin leer documentación.

Lectura (cualquier credencial)

ToolQué hace
widgetry_get_organizationDónde trabaja la credencial, si puede escribir, cuántos widgets y diseños hay, y las URLs
widgetry_list_startersLos tipos de widget de partida y las librerías de script disponibles (three, gsap, d3, chartjs)
widgetry_get_starterUna plantilla completa: markup, estilos, script, esquema de datos y datos de ejemplo
widgetry_list_widgetsLos widgets de la organización, borradores incluidos
widgetry_get_widgetUn widget completo, con sus dominios de imágenes y sus librerías
widgetry_export_widgetEl manifiesto (tool y recurso con su CSP), la URL viva para enlazar y el TypeScript para registrarlo
widgetry_list_designsLos diseños de serie y los de la organización
widgetry_get_designLos tokens claros y oscuros de un diseño, su CSS extra y todos los tokens que un diseño puede fijar

Escritura (clave de escritura, u OAuth con widgets:write de un editor o propietario)

ToolQué hace
widgetry_create_widgetCrea un borrador copiando una plantilla, con slug fijo, diseño e idioma de los datos de ejemplo opcionales
widgetry_update_widgetCambia solo los campos que mandas: nombre, descripción, diseño, markup, estilos, script, librerías, dominios de imágenes, esquema de datos, datos de ejemplo
widgetry_set_publishedPublica o despublica un widget
widgetry_delete_widgetBorra un widget para siempre
widgetry_create_designCrea un diseño a partir de cualquier otro, con tokens, tokens oscuros y CSS
widgetry_update_designEdita un diseño de la organización
widgetry_delete_designBorra un diseño que no lleve ningún widget

Cada widget que devuelven las tools trae un editorUrl y un previewUrl, que abres en el navegador con tu sesión. Y cada widget publicado se convierte en su propia tool en el mismo endpoint, show_<slug>, así que el agente lo puede pintar en la conversación en el momento.

Un ejemplo completo

Una sesión con datos inventados. Le pides a Claude Code: "Hazme un widget con las cifras semanales del equipo de soporte, con un diseño verde azulado, y dame el código para mi servidor MCP".

1. Ver dónde está. El agente llama a widgetry_get_organization y ve canWrite: true.

2. Elegir plantilla. widgetry_list_starters devuelve los 13 tipos. Una fila de cifras con su variación encaja con la plantilla de indicadores, así que el agente la lee con widgetry_get_starter para conocer su esquema.

3. Crear el widget. Un slug fijo mantiene estable el nombre de la tool, y locale: "es" arranca con los datos de ejemplo en castellano:

json
{
  "starterId": "metrics",
  "name": "Soporte semanal",
  "slug": "soporte-semanal",
  "locale": "es"
}

La respuesta trae "toolName": "show_soporte_semanal", el editorUrl y el previewUrl.

4. Dar forma a los datos. El agente llama a widgetry_update_widget con una descripción que leerá el modelo, un esquema que ahora exige el periodo y datos de ejemplo:

json
{
  "slug": "soporte-semanal",
  "description": "Muestra las cifras semanales del equipo de soporte: tickets, tiempo de respuesta y satisfacción, cada una con su variación frente a la semana anterior.",
  "dataSchema": {
    "type": "object",
    "required": ["title", "period", "metrics"],
    "properties": {
      "title": { "type": "string" },
      "period": { "type": "string" },
      "metrics": {
        "type": "array",
        "items": {
          "type": "object",
          "required": ["label", "value"],
          "properties": {
            "label": { "type": "string" },
            "value": { "type": "number" },
            "unit": { "type": "string" },
            "change": { "type": "number" },
            "lower_is_better": { "type": "boolean" }
          }
        }
      }
    }
  },
  "sampleData": {
    "title": "Soporte esta semana",
    "period": "Semana 40",
    "metrics": [
      { "label": "Tickets resueltos", "value": 1284, "change": 6.2 },
      { "label": "Primera respuesta", "value": 38, "unit": "min", "change": -12.5, "lower_is_better": true },
      { "label": "Satisfacción", "value": 94.1, "unit": "%", "change": 1.3 }
    ]
  }
}

Si los datos no cumplieran el esquema, la tool respondería con el error y lo que hay que arreglar, y el agente volvería a intentarlo.

5. Hacer un diseño. Ningún diseño de serie es verde azulado, así que el agente crea uno a partir de nordic:

json
{
  "name": "Puerto",
  "from": "nordic",
  "tokens": { "--wg-accent": "#0f766e" },
  "darkTokens": { "--wg-accent": "#2dd4bf" }
}

El diseño recibe la clave puerto, y otra llamada a widgetry_update_widget le pone "design": "puerto" al widget.

6. Publicar. widgetry_set_published con "published": true. Para publicar hacen falta una descripción y unos datos de ejemplo que cumplan el esquema, y los dos ya están. El widget es ahora la tool show_soporte_semanal del endpoint.

7. Entregar el código. widgetry_export_widget devuelve el manifiesto, la URL viva y dos snippets de TypeScript: uno que enlaza el widget publicado con una clave de solo lectura (lo que publiques después llega a tu servidor en menos de un minuto, sin desplegar) y otro que registra los ficheros descargados. El agente pega el enlazado en tu servidor. Añadir una interfaz a tu servidor MCP explica los dos.

Un aviso si el agente es Claude Code: la terminal no pinta MCP Apps, llama a la tool como texto. Abre el previewUrl o el editor para ver el widget o, con Widgetry conectado en Claude en la web o en el escritorio, pídele que llame a show_soporte_semanal.

Límites: lo que el agente no puede hacer

Dar permiso de escritura a un agente es más seguro cuando los límites están en el servidor y no en el prompt:

  • Una credencial de lectura se queda en lectura. Una clave de lectura, o un token OAuth sin widgets:write, solo recibe las tools de lectura. Un token sin ese scope actúa como lector aunque la persona sea propietaria.
  • Los papeles siguen contando. Un lector de la organización tampoco escribe a través de un agente. Para escribir hace falta un editor o un propietario detrás del token, o una clave de escritura.
  • Ni miembros, ni invitaciones, ni claves. Se quedan en la web a propósito: una clave creada por un agente acabaría escrita en un chat.
  • Una organización por credencial. Cada widget y cada diseño pertenecen a una organización, y la credencial decide cuál. Pedir algo de otra organización devuelve "not found".
  • Las tools vivas están protegidas. Un widget publicado rechaza un cambio que rompería su tool; el agente tiene que despublicarlo antes o mantener el esquema compatible.
  • Borrar está marcado como destructivo, y la tool le dice al agente que te lo confirme antes. No se puede deshacer.

Frente a las skills que generan código

Hay buenas skills que enseñan a un agente de código a escribir MCP Apps. Resuelven otro problema.

OpciónQué haceMejor para
Agent Skills oficiales de ext-apps (create-mcp-app, add-app-to-server, convert-web-app, migrate-oai-app) y el plugin mcp-apps de Claude CodeGeneran y migran código de MCP Apps en tu repo (ext-apps)Interfaces a medida con tu framework, control de cada línea, migrar una app de OpenAI
La skill build-mcp-app de Anthropic, en el plugin mcp-server-devAñade interfaz (formularios, selectores, diálogos de confirmación) mientras construyes un servidor MCP (plugin)Pasos interactivos dentro de un servidor que estás escribiendo
La skill generate-mcp-app-ui de Microsoft Power Apps (en preview)Genera widgets HTML autocontenidos con Fluent UI a partir del JSON de una tool (docs)Equipos que ya están en Power Apps y quieren widgets con Fluent UI
Las tools MCP de WidgetryCrean, diseñan y publican widgets como datos en un servicio alojadoMostrar datos (tableros, indicadores, gráficos, tablas) sin código de interfaz en tu repo, diseños compartidos y cambios que llegan a tu servidor sin desplegar

Generar código gana cuando la interfaz es poco común, cuando tiene que pedir sus propios datos o cuando no quieres depender de un servicio. Un widget de Widgetry es una plantilla Liquid con un script opcional limitado a un catálogo cerrado de librerías, y enseña los datos que le pasa el modelo: no pide datos por su cuenta. Si eso te encaja, el agente tiene un widget que funciona en cada paso en lugar de código que depurar. Para ver más opciones, lee herramientas para crear MCP Apps comparadas.

Pruébalo

Entra en widgets.gonzaloverdugo.com, crea una clave de escritura en Ajustes (o conecta Claude con OAuth) y pídele un widget a tu agente. Verás cada cambio llegar al editor, podrás pulirlo tú y dejar que el agente lo publique cuando te guste.

Tu primer widget, en el chat en unos minutos

Elige una plantilla, pon tus datos y míralo como lo enseñarán ChatGPT o Claude. Después enlázalo desde tu servidor MCP, o deja que tu agente haga el siguiente.