Sneaker Carousel MCP App
README.md
# Sneaker Carousel MCP App
Demo portable de **MCP Apps** para mostrar en Claude: carrusel de zapatillas, selección de talle/cantidad y botón de pago simulado.
## Qué demuestra
- Un tool visible para el modelo: `show-sneaker-carousel`.
- Un recurso `ui://sneaker-drop/carousel.html` renderizado por el host.
- HTML, CSS y JavaScript empaquetados en un único archivo.
- Una llamada UI → host → servidor mediante `app.callServerTool()`.
- Un tool privado para la UI: `prepare-demo-checkout`.
- Validación autoritativa de producto, talle y total en el servidor.
- Adaptación al tema y tipografías del host.
> El pago es una simulación. No solicita tarjeta ni procesa dinero.
## Ejecutar localmente
Requisitos: Node.js 20 o superior.
```bash
npm install
npm run build
npm start
```
Endpoint MCP:
```text
http://localhost:3001/mcp
```
Health check:
```text
http://localhost:3001/
```
Vista previa del carrusel sin un host MCP:
```text
http://localhost:3001/preview
```
## Probar con el basic-host oficial
En otra carpeta:
```bash
git clone https://github.com/modelcontextprotocol/ext-apps.git
cd ext-apps
npm install
SERVERS='["http://localhost:3001/mcp"]' npm start
```
Abrí `http://localhost:8080`, elegí `show-sneaker-carousel` y ejecutá el tool.
## Deploy con Docker
```bash
docker build -t sneaker-mcp-app .
docker run --rm -p 3001:3001 sneaker-mcp-app
```
Podés desplegar el Dockerfile en Railway, Render, Fly.io, Cloud Run o ECS. El servicio debe quedar públicamente accesible por HTTPS.
Ejemplo final:
```text
https://tu-dominio.example/mcp
```
## Conectarlo a Claude
1. Desplegá el proyecto con HTTPS.
2. En Claude abrí **Customize / Connectors**.
3. Elegí **Add custom connector**.
4. Pegá `https://tu-dominio.example/mcp`.
5. Para esta demo, seleccioná conexión sin autenticación si Claude ofrece esa opción.
6. En un chat, activá el conector y escribí:
```text
Mostrame el carrusel de zapatillas y ayudame a elegir una.
```
Claude debería llamar `show-sneaker-carousel` y renderizar la MCP App dentro de la conversación.
## Checkout externo opcional
Si definís:
```bash
DEMO_CHECKOUT_URL=https://example.com/checkout
```
el servidor devolverá esa URL y la MCP App pedirá al host abrirla. Para una integración real, generá una URL única de checkout en el backend y confirmá el pago por webhook. No confíes en el monto enviado por la interfaz.
## Estructura
```text
.
├── main.ts # servidor HTTP/stdio
├── server.ts # tools y recurso MCP App
├── mcp-app.html # entrada de la UI
├── src/
│ ├── mcp-app.ts # comportamiento del carrusel y checkout
│ └── styles.css # estilos responsivos
├── Dockerfile
└── render.yaml
```
## Solución de problemas
### `outputSchema` no acepta `z.object(...)`
Esta versión usa `@modelcontextprotocol/ext-apps` 1.7.4 junto con el SDK MCP 1.29.0. Los helpers del servidor terminan delegando en la API Zod del SDK 1.x, por lo que los schemas de salida se pasan como shapes:
```ts
outputSchema: StoreOutputSchema.shape
```
### `root is possibly null`
El elemento raíz se valida una vez y luego se guarda con tipo `HTMLElement`, de modo que TypeScript conserva el tipo dentro de callbacks.
### `Cannot find module dist/main.js`
`dist/main.js` se genera recién cuando `npm run build` termina correctamente. Ejecutá:
```bash
rm -rf dist
npm run build
npm start
```
### Avisos de `npm audit`
Los avisos de auditoría no causan los errores de compilación. Revisalos con:
```bash
npm audit
npm audit fix
npm run build
```
No ejecutes `npm audit fix --force` sin revisar los cambios, porque puede instalar actualizaciones mayores incompatibles.
## Compatibilidad con Claude
La UI primero lee `structuredContent`. Como fallback de compatibilidad, también puede recuperar el catálogo y la orden desde un payload JSON marcado dentro de `content`. Esto permite que la demo siga renderizando en hosts que no reenvían `structuredContent` al iframe.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues