Skip to main content
Glama
mustafadeel

@auth0/agent-components

by mustafadeel

@auth0/agent-components — Auth0 Universal Components for Agents

Convierte un Auth0 Form en una MCP App — una interfaz de usuario interactiva que un servidor de Model Context Protocol sirve a un cliente MCP, renderizada en un iframe aislado. Esto es Auth0 Universal Components for Agents: cualquier Auth0 Form se convierte en una interfaz de usuario invocable por agentes, sin necesidad de una Auth0 Action.

Estado: prueba de concepto. Funciona de extremo a extremo con la capacidad oficial de MCP Apps (SEP-1865), el MCP Inspector y CopilotKit (ver examples/copilotkit-poc).

Por qué

Los Auth0 Forms normalmente se renderizan solo dentro de una Auth0 Action durante el Universal Login. El dx-flows-sdk desacopló eso: un formulario se puede incrustar mediante el bundle del navegador fuera de una redirección de login. Las MCP Apps permiten que un servidor entregue HTML interactivo a un cliente para renderizarlo en un iframe aislado. Juntándolos, un agente puede mostrar un Auth0 Form real y completamente funcional — registro, consentimiento, perfil, pago — como una de sus herramientas.

Cómo funciona

MCP host (e.g. MCP Inspector, CopilotKit)
 └─ sandboxed iframe  ← our ui:// HTML resource (text/html;profile=mcp-app)
      ├─ <script src="https://<tenant>/forms/sdk/forms.js">
      ├─ Auth0Forms.embed(formId, "#root", { fields: { session_token } })
      │    └─ form submits to its OWN Auth0 backend (/forms/api/...)  ← we never see the data
      └─ bridge: on af-submitForm-success → app.updateModelContext({ status: "completed" })
                                          → app.requestTeardown()   (close the app view)
                  on af-redirect          → app.openLink(url)       (never navigates the iframe)

El formulario es dueño de sus datos. El Auth0 Form se envía de forma nativa a su backend de Auth0. La capa MCP nunca lee ni transmite los valores de los campos — solo informa un estado de finalización (completed / cancelled / errored, más un destino de redirección opcional) para que el agente sepa que el usuario terminó.

Paquetes

Package

What it is

packages/agent-components

@auth0/agent-components — registra Auth0 Forms como MCP Apps en cualquier McpServer.

packages/mcp-apps-middleware-auth

@auth0/mcp-apps-middleware-auth — añade autenticación al @ag-ui/mcp-apps-middleware de CopilotKit, que no puede adjuntar una credencial a sus conexiones MCP.

examples/poc-server

POC de servidor MCP ejecutable; pruébalo desde el MCP Inspector. Incluye scripts/discover-forms.mjs (descubrimiento de formularios del tenant mediante la CLI de Auth0).

examples/copilotkit-poc

CopilotKit como cliente MCP — login real de Auth0 (@auth0/auth0-server-js) → el formulario se renderiza y se envía en línea. De extremo a extremo.

Uso

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { registerAuth0Forms } from "@auth0/agent-components";

const server = new McpServer({ name: "my-server", version: "1.0.0" });

await registerAuth0Forms(
  server,
  [
    {
      formId: "your-form-id",
      tenantOrigin: "https://your-tenant.us.auth0.com",
      // inputMode: "prefill",         // expose form fields as optional agent inputs
      // ui: { csp: { frameDomains: ["https://js.stripe.com"] } }, // for payment/social steps
      onComplete: (r) => console.log(r.formId, r.status),         // status only — no field data
    },
  ],
  { assumeUiSupport: true }, // register before connect; see "Registration timing"
);

// ...connect your transport (StreamableHTTP / stdio / SSE)

Cada formulario registra:

  • una herramienta open_form_<slug> cuyo _meta.ui.resourceUri apunta a …

  • un recurso ui://agent-components/<formId> que devuelve el HTML de la aplicación de formulario + un bloque CSP.

CSP

El host renderiza el recurso bajo una política predeterminada estricta (default-src 'none'). @auth0/agent-components automáticamente incluye en la lista blanca tu tenantOrigin en ambos:

  • csp.resourceDomains — para que forms.js, estilos, fuentes e imágenes se carguen, y

  • csp.connectDomains — para que el fetch del bundle a /forms/api/... funcione.

Si un paso del formulario anida un iframe de otro origen (Stripe, un proveedor social, un captcha), decláralo:

ui: { csp: { frameDomains: ["https://js.stripe.com", "https://hooks.stripe.com"] } }

Observa la consola del navegador la primera vez que renderices un formulario nuevo: cualquier violación de CSP te indica exactamente qué origen añadir.

Formularios respaldados por sesión (formularios de flujo/router)

Los formularios con un nodo FLOW/ROUTER necesitan una sesión autenticada — de lo contrario, el paso posterior al router falla con ERR_INVALID_FORM_SESSION. El mecanismo (confirmado con el equipo de Forms, verificado de extremo a extremo):

  1. Declara un campo oculto en el formulario (por ejemplo, session_token).

  2. El flujo del formulario lo lee — por ejemplo, una acción Update User con user_id: {{fields.session_token}}.

  3. El servidor MCP, actuando como servidor de recursos OAuth, verifica el token de Auth0 del llamante, resuelve el sub del usuario, emite un JWT de confianza de corta duración para él (firmado con un secreto compartido que el backend de Forms confía) y lo inyecta en el campo oculto por solicitud.

Marca el formulario como consciente de sesión:

{
  formId: "ap_...",
  session: { field: "session_token" },   // must match the form's hidden field
}

…e inicializa el cliente con la configuración de confianza del servidor + un resolvedor que lee la identidad verificada (verifier + subFromExtra provienen del subpath /auth, respaldado por @auth0/auth0-api-js):

import { createAgentComponents } from "@auth0/agent-components";
import { subFromExtra } from "@auth0/agent-components/auth";

const agentComponents = createAgentComponents({
  tenantOrigin: "https://your-tenant.auth0.com",
  assumeUiSupport: true,
  sessionTrust: { secret: process.env.FORMS_TRUST_SECRET! }, // shared with the Forms backend
  resolveUserSub: subFromExtra,                    // returns the caller's `sub`, or undefined
});
await agentComponents.register(server, forms);

El servidor POC (examples/poc-server) conecta el flujo completo: createAuth0Verifier (→ @auth0/auth0-api-js), un endpoint de metadatos ProtectedResourceMetadataBuilder y requireBearerAuth — de modo que un desafío 401 + WWW-Authenticate permite al cliente ejecutar el flujo OAuth de Auth0. El token/sub/JWT emitido nunca entra en el contexto del modelo MCP — el token emitido viaja en embed().fields solo al backend de Auth0 Forms.

Nota: un viaje de Auth0 Forms completado es de un solo uso hoy (re-enviar un viaje gastado devuelve ERR_INVALID_FORM_SESSION). Universal Portals EPIC 7 añade viajes re-completables. La MCP App se completa una vez e informa el estado, por lo que una nueva invocación de herramienta obtiene un viaje nuevo — el re-envío no es parte del flujo.

Momento de registro

El SDK de MCP prohíbe añadir una capacidad después de server.connect(transport). Dos patrones admitidos:

  • Registrar antes de conectar (lo más simple) con assumeUiSupport: true. Correcto para clientes con capacidad de UI (MCP Inspector, Claude). Esto es lo que hace el POC.

  • Control dinámico por cliente (assumeUiSupport: "auto", el predeterminado): llama a registerAuth0Forms desde server.server.oninitialized para que se conozcan las capacidades del cliente — y construye el servidor con { capabilities: { tools: {}, resources: {} } }, o registra una herramienta + un recurso antes de conectar, para que el registro posterior a la conexión no intente añadir una nueva capacidad.

Desarrollo

npm install
npm run build      # builds all packages (agent-components builds its bridge first)
npm test           # unit tests (form→tool, ui-template CSP, bridge status-only contract)

Licencia

MIT

-
license - not tested
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • An AI concierge that turns static forms into adaptive AI conversations. From any MCP client.

  • Create and wire up contact forms from your coding agent. Forms, snippets, and submissions.

  • Phone, SMS & email for AI agents — one remote MCP endpoint, OAuth login, zero install.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mustafadeel/universal-components-agents'

If you have feedback or need assistance with the MCP directory API, please join our Discord server