MCP Apps: Interfaces de Usuario Interactivas para Servidores MCP
Introducción
Una de las solicitudes más frecuentes de la comunidad MCP finalmente se hace realidad: interfaces de usuario interactivas directamente integradas en el protocolo. El 21 de noviembre de 2025, Anthropic anunció la extensión MCP Apps (SEP-1865), desarrollada en colaboración con OpenAI y el proyecto comunitario MCP-UI.
Esta iniciativa permite que los servidores MCP entreguen experiencias visuales ricas más allá del texto plano y los datos estructurados.
El problema actual
Hasta ahora, los servidores MCP se limitaban a intercambiar texto y datos estructurados con los hosts. Por ejemplo, un servidor de visualización de datos debía devolver los datos del gráfico en JSON, dejando que la aplicación cliente interpretara y renderizara la información.
// Antes: El servidor solo podía devolver datos
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const chartData = await getChartData();
// Solo JSON, sin visualización
return {
content: [{
type: "text",
text: JSON.stringify(chartData)
}]
};
});
Limitaciones:
- Cada cliente debía implementar su propia lógica de renderizado
- Experiencias inconsistentes entre aplicaciones
- Imposibilidad de crear interfaces interactivas personalizadas
La solución: MCP Apps
MCP Apps introduce un mecanismo estandarizado para que los servidores entreguen interfaces de usuario interactivas directamente a los clientes.
Características principales
1. Recursos predeclarados con URI ui://
Las plantillas de UI se registran utilizando el esquema ui:// y se referencian en los metadatos de las herramientas:
// Declarar recurso UI
const uiResource = {
uri: "ui://visualization/chart",
mimeType: "text/html",
content: `
<html>
<body>
<canvas id="chart"></canvas>
<script>
// Lógica de renderizado del gráfico
</script>
</body>
</html>
`
};
// Referenciar en herramienta
server.registerTool({
name: "create_chart",
description: "Crea un gráfico interactivo",
ui: {
resourceUri: "ui://visualization/chart"
}
});
Esto permite que los hosts revisen el contenido antes de ejecutar las herramientas.
2. Transporte sobre protocolo MCP existente
La extensión utiliza el protocolo JSON-RPC existente sobre postMessage, lo que permite a los desarrolladores usar el SDK estándar:
import { App } from "@modelcontextprotocol/ext-apps";
// La App se comunica con el host usando el SDK existente
const app = new App();
app.onMessage((message) => {
// Manejar mensajes del host
console.log("Mensaje recibido:", message);
});
// Llamar herramientas del servidor
await app.callTool("get_data", { query: "ventas" });
3. Soporte HTML en iframes sandboxed
La especificación inicial soporta contenido text/html renderizado en iframes con sandbox:
<iframe
sandbox="allow-scripts"
src="ui://my-component"
style="width: 100%; height: 400px;">
</iframe>
Ventajas:
- Compatibilidad universal con navegadores
- Modelo de seguridad bien establecido
- Aislamiento completo del contenido
4. Seguridad multicapa
El diseño prioriza la seguridad en múltiples niveles:
┌─────────────────────────────────────────────┐
│ Capa 1: Sandboxing de iframes │
│ - Permisos restringidos │
│ - Aislamiento de origen │
├─────────────────────────────────────────────┤
│ Capa 2: Plantillas predeclaradas │
│ - Revisables antes de ejecución │
│ - Sin código dinámico inesperado │
├─────────────────────────────────────────────┤
│ Capa 3: Mensajes auditables │
│ - Comunicación vía JSON-RPC │
│ - Trazabilidad completa │
├─────────────────────────────────────────────┤
│ Capa 4: Consentimiento del usuario │
│ - Aprobación para llamadas a herramientas │
│ - Control explícito de acciones │
└─────────────────────────────────────────────┘
Arquitectura técnica
Componentes del SDK
El repositorio ext-apps contiene:
| Módulo | Descripción |
|---|---|
types.ts | Tipos JSON-RPC para comunicación App-Host |
app.ts | Clase App para que las Apps se comuniquen con su host |
app-bridge.ts | Clase AppBridge para interacciones host-App |
message-transport.ts | Clase PostMessageTransport para mensajes en iframes |
Ejemplo de servidor con UI
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
const server = new Server({
name: "visualization-server",
version: "1.0.0"
});
// Registrar recurso UI
server.registerResource({
uri: "ui://dashboard/sales",
mimeType: "text/html",
content: await readFile("./dashboard.html", "utf-8")
});
// Herramienta que utiliza el recurso UI
server.registerTool({
name: "show_sales_dashboard",
description: "Muestra un dashboard interactivo de ventas",
inputSchema: {
type: "object",
properties: {
period: { type: "string", enum: ["week", "month", "year"] }
}
},
ui: {
resourceUri: "ui://dashboard/sales"
}
});
Ejemplo de App con React
import { useApp } from "@modelcontextprotocol/ext-apps/react";
function SalesDashboard() {
const { callTool, onDataUpdate } = useApp();
const [data, setData] = useState(null);
useEffect(() => {
// Escuchar actualizaciones de datos
onDataUpdate((newData) => {
setData(newData);
});
}, []);
const handleRefresh = async () => {
const result = await callTool("fetch_sales_data", {
period: "month"
});
setData(result);
};
return (
<div className="dashboard">
<button onClick={handleRefresh}>Actualizar</button>
{data && <Chart data={data} />}
</div>
);
}
Compatibilidad hacia atrás
La extensión MCP Apps es completamente opcional. Los servidores deben proporcionar alternativas de solo texto para todas las herramientas habilitadas con UI:
server.registerTool({
name: "visualize_data",
description: "Visualiza datos como gráfico o tabla de texto",
ui: {
resourceUri: "ui://chart",
// Fallback para clientes sin soporte UI
fallbackEnabled: true
},
handler: async (args) => {
const data = await fetchData(args);
// Si el cliente no soporta UI, devolver texto
return {
content: [{
type: "text",
text: formatAsTable(data)
}]
};
}
});
Colaboradores y adopción
Colaboración histórica
Esta extensión representa una colaboración sin precedentes entre:
- Anthropic: Creadores del protocolo MCP
- OpenAI: Con su Apps SDK
- MCP-UI: Proyecto comunitario pionero
Empresas adoptando patrones UI
Varias empresas ya utilizan patrones similares basados en MCP-UI:
- Postman: Interfaces de prueba de APIs
- Shopify: Dashboards de e-commerce
- Hugging Face: Visualización de modelos
- Goose: Componentes interactivos
- ElevenLabs: Interfaces de audio
MCP-UI: El proyecto comunitario
MCP-UI fue el proyecto que demostró la viabilidad de interfaces en MCP. Sus conceptos clave ahora forman parte de la especificación oficial:
UIResource
interface UIResource {
uri: string; // Identificador único
mimeType: string; // Tipo de contenido
text?: string; // Contenido textual
blob?: Uint8Array; // Contenido binario
}
Tipos de contenido soportados
| Tipo MIME | Descripción |
|---|---|
text/html | HTML renderizado en iframe |
text/uri-list | Lista de URIs |
application/vnd.mcp-ui.remote-dom | Remote DOM de Shopify |
SDKs disponibles
# TypeScript (servidor)
npm install @mcp-ui/server
# TypeScript (cliente)
npm install @mcp-ui/client
# Python
pip install mcp-ui-server
# Ruby
gem install mcp_ui_server
Instalación y uso
Instalar el SDK
# Actualmente disponible vía Git
npm install git+https://github.com/modelcontextprotocol/ext-apps.git
Estructura de proyecto
mi-servidor-mcp/
├── src/
│ ├── server.ts # Servidor MCP
│ └── ui/
│ ├── dashboard.html
│ └── components/
│ └── chart.tsx
├── package.json
└── mcp.json
Próximos pasos
El equipo de MCP invita a la comunidad a:
1. Revisar la especificación
# Clonar el repositorio
git clone https://github.com/modelcontextprotocol/modelcontextprotocol
# Ver el PR SEP-1865
gh pr view 1865
2. Participar en discusiones
- GitHub Issues: Reportar problemas y sugerencias
- Discord: Canal
#ui-wgen MCP Contributors
3. Probar implementaciones
# Clonar ext-apps
git clone https://github.com/modelcontextprotocol/ext-apps
# Instalar dependencias
npm install
# Ejecutar ejemplos
npm run example:react
npm run example:vanilla
Casos de uso
Visualización de datos
// Gráficos interactivos en lugar de tablas de texto
const chartUI = createBarChart({
data: salesData,
interactive: true,
onBarClick: (item) => callTool("get_details", { id: item.id })
});
Formularios complejos
// Formularios con validación en tiempo real
const formUI = createForm({
fields: schema,
onSubmit: (data) => callTool("process_form", data),
validation: "realtime"
});
Dashboards en tiempo real
// Métricas actualizándose automáticamente
const dashboardUI = createDashboard({
widgets: ["sales", "users", "performance"],
refreshInterval: 5000,
onWidgetClick: (widget) => callTool("drill_down", { widget })
});
Conclusión
MCP Apps marca un hito importante en la evolución del protocolo MCP:
- Experiencias visuales ricas directamente desde servidores MCP
- Colaboración industria-comunidad entre Anthropic, OpenAI y MCP-UI
- Seguridad primero con múltiples capas de protección
- Compatibilidad manteniendo soporte para clientes existentes
Esta extensión posiciona a MCP como un protocolo verdaderamente completo para la integración de IA con datos y servicios externos.
Post anterior: Automatización con MCP Prompts
Recursos: