@auth0/agent-components
@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 |
| |
| |
POC de servidor MCP ejecutable; pruébalo desde el MCP Inspector. Incluye | |
CopilotKit como cliente MCP — login real de Auth0 ( |
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.resourceUriapunta 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 queforms.js, estilos, fuentes e imágenes se carguen, ycsp.connectDomains— para que elfetchdel 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):
Declara un campo oculto en el formulario (por ejemplo,
session_token).El flujo del formulario lo lee — por ejemplo, una acción
Update Userconuser_id: {{fields.session_token}}.El servidor MCP, actuando como servidor de recursos OAuth, verifica el token de Auth0 del llamante, resuelve el
subdel 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 aregisterAuth0Formsdesdeserver.server.oninitializedpara 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
This server cannot be installed
Maintenance
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.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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