E-commerce MCP Server with Chatwoot Integration
Enables AI agents to manage e-commerce operations (products, carts, clients) through WhatsApp via Chatwoot, using MCP tools for inventory, cart, and customer management.
README
Servidor MCP de E-commerce con Integración Chatwoot
Un servidor Model Context Protocol (MCP) listo para producción, desplegado en Cloudflare Workers, diseñado para agentes de IA con capacidades de e-commerce y integración perfecta con WhatsApp a través de Chatwoot.
Tabla de Contenidos
- Resumen
- Arquitectura
- Características
- Esquema de Base de Datos
- Flujo del Sistema
- Endpoints de API
- Herramientas MCP
- Instalación y Despliegue
- Configuración
- Ejemplos de Uso
- Solución de Problemas
Resumen
Este servidor MCP permite a agentes de IA gestionar operaciones de e-commerce a través de WhatsApp, integrándose con Chatwoot para la comunicación con clientes y Supabase para la persistencia de datos. El sistema proporciona un conjunto completo de herramientas de e-commerce incluyendo navegación de productos, gestión de carritos y seguimiento de clientes.
Tecnologías Clave
- Cloudflare Workers: Plataforma de despliegue serverless
- MCP (Model Context Protocol): Interfaz de herramientas para agentes de IA
- Supabase: Base de datos PostgreSQL con API REST
- Chatwoot: Plataforma de engagement con clientes
- WhatsApp Business API: Canal de comunicación con clientes
Arquitectura
Arquitectura de Alto Nivel
┌─────────────┐
│ WhatsApp │
└──────┬──────┘
│
▼
┌─────────────────┐
│ Chatwoot │
│ (Inbox) │
└────────┬────────┘
│ Webhook de Automation Rule
▼
┌──────────────────────────────┐
│ Cloudflare Worker │
│ (Adaptador de Webhook) │
│ /api/chatwoot/webhook │
└────────┬─────────────────────┘
│
├─────────────────────────────┐
│ │
▼ ▼
┌─────────────────┐ ┌────────────────┐
│ Agente Laburen │ │ Supabase │
│ (dashboard) │ │ (Base Datos) │
└────────┬────────┘ └────────────────┘
│
│ Se conecta a
▼
┌──────────────────────────────┐
│ Servidor MCP │
│ /mcp │
│ │
│ Herramientas: │
│ - list_products │
│ - get_product_details │
│ - get_or_create_client │
│ - create_cart │
│ - add_to_cart │
│ - get_cart │
│ - update_cart_item │
│ - remove_from_cart │
│ - request_human_agent │
└──────────────────────────────┘
Responsabilidades de Componentes
| Componente | Responsabilidad |
|---|---|
| Canal de comunicación con clientes | |
| Chatwoot | CRM, enrutamiento de mensajes, gestión de conversaciones |
| Adaptador de Webhook | Recibe eventos de Chatwoot, llama al agente, envía respuestas a Chatwoot |
| Agente Laburen | Agente de IA que procesa mensajes y usa herramientas MCP |
| Servidor MCP | Proporciona herramientas de e-commerce al agente |
| Supabase | Persistencia de datos (productos, carritos, clientes) |
Características
Operaciones de E-commerce
- Gestión de Productos: Navegar productos con variantes (colores, talles, stock)
- Gestión de Carritos: Crear, actualizar y administrar carritos de compra
- Gestión de Clientes: Seguimiento de clientes por email y teléfono
- Control de Inventario: Disponibilidad de stock en tiempo real
- Etiquetado Automático: Agregar etiquetas en Chatwoot según tipo de prenda agregada al carrito
Capacidades de Integración
- WhatsApp Business: Comunicación nativa con clientes
- CRM Chatwoot: Historial de conversaciones y datos de clientes
- Soporte para Agentes IA: Interfaz completa de herramientas MCP
- API REST: Endpoints HTTP alternativos para documentación
- Transferencia a Humanos: Sistema de handoff de bot a agente humano con categorización de motivos
Características Técnicas
- Soporte UUID: Identificadores de carrito amigables con privacidad
- Formato Dual de ID: Maneja identificadores tanto numéricos como UUID
- Manejo de Errores: Respaldos elegantes para todas las operaciones
- Logging: Logs de depuración completos vía Cloudflare
Esquema de Base de Datos
Diagrama de Relaciones de Entidades
┌─────────────┐
│ products │
├─────────────┤
│ id (PK) │
│ name │
│ description │
│ price │
│ created_at │
└──────┬──────┘
│
│ 1:N
▼
┌──────────────────┐
│ product_variants │
├──────────────────┤
│ id (PK) │
│ product_id (FK) │◄───┐
│ color_id (FK) │ │
│ size_id (FK) │ │
│ stock │ │
└────────┬─────────┘ │
│ │
│ │
┌────┴────┐ ┌────┴────┐
│ colors │ │ sizes │
├─────────┤ ├─────────┤
│ id (PK) │ │ id (PK) │
│ name │ │ name │
└─────────┘ └─────────┘
┌─────────────┐
│ clients │
├─────────────┤
│ id (PK) │
│ email │
│ phone │
│ created_at │
└──────┬──────┘
│
│ 1:N
▼
┌─────────────┐
│ carts │
├─────────────┤
│ id (UUID PK)│
│ client_id │
│ created_at │
└──────┬──────┘
│
│ 1:N
▼
┌──────────────────┐
│ cart_items │
├──────────────────┤
│ id (PK) │
│ cart_id (FK) │
│ product_var... │
│ quantity │
│ price_at_add │
└──────────────────┘
Descripción de Tablas
products
Información central de productos.
| Columna | Tipo | Descripción |
|---|---|---|
| id | integer | Clave primaria |
| name | text | Nombre del producto |
| description | text | Descripción del producto |
| price | numeric | Precio base |
| garment_type_id | integer | FK a garment_types |
| created_at | timestamp | Fecha de creación |
garment_types
Tipos de prenda para categorización y etiquetado.
| Columna | Tipo | Descripción |
|---|---|---|
| id | integer | Clave primaria |
| name | text | Nombre del tipo de prenda (ej: "Camiseta", "Pantalón") |
product_variants
Variaciones de productos con color, talle y stock.
| Columna | Tipo | Descripción |
|---|---|---|
| id | integer | Clave primaria |
| product_id | integer | FK a products |
| color_id | integer | FK a colors |
| size_id | integer | FK a sizes |
| stock | integer | Cantidad disponible |
colors & sizes
Tablas de catálogo para atributos de productos.
| Columna | Tipo | Descripción |
|---|---|---|
| id | integer | Clave primaria |
| name | text | Nombre de color/talle |
clients
Información de clientes.
| Columna | Tipo | Descripción |
|---|---|---|
| id | integer | Clave primaria |
| name | text | Nombre del cliente |
| text | Email del cliente (único) | |
| phone | text | Teléfono del cliente (auto-capturado de WhatsApp) |
| created_at | timestamp | Fecha de registro |
carts
Encabezados de carritos de compra.
| Columna | Tipo | Descripción |
|---|---|---|
| id | uuid | Clave primaria (UUID para privacidad) |
| client_id | integer | FK a clients (opcional) |
| status | text | Estado del carrito: "active", "completed", "abandoned" |
| created_at | timestamp | Fecha de creación del carrito |
cart_items
Artículos en carritos de compra.
| Columna | Tipo | Descripción |
|---|---|---|
| id | integer | Clave primaria |
| cart_id | uuid | FK a carts |
| product_variant_id | integer | FK a product_variants |
| quantity | integer | Cantidad del artículo |
| price_at_add | numeric | Instantánea del precio al agregar |
Flujo del Sistema
Flujo de Mensajes (WhatsApp → Respuesta)
1. Cliente envía mensaje por WhatsApp
│
▼
2. Chatwoot recibe mensaje (incoming)
│
▼
3. Automation Rule dispara webhook
│
▼ POST a /api/chatwoot/webhook
4. Cloudflare Worker recibe webhook
│
├─ Extrae: conversationId, mensaje, remitente
│
▼
5. Worker llama a API del Agente Laburen
│ POST /api/agents/{agentId}/query
│ {
│ "query": "mensaje del cliente",
│ "channel": "chatwoot",
│ "conversationId": "123",
│ "visitorId": "+5491123365608"
│ }
│
▼
6. Agente procesa el mensaje
│
├─ Se conecta al Servidor MCP (/mcp)
│
├─ Usa herramientas MCP:
│ - list_products
│ - add_to_cart
│ - etc.
│
├─ Genera respuesta
│
▼
7. Agente devuelve respuesta al Worker
│ { "answer": "Respuesta del agente..." }
│
▼
8. Worker envía a API de Chatwoot
│ POST /api/v1/accounts/{accountId}/conversations/{convId}/messages
│ {
│ "content": "Respuesta del agente...",
│ "message_type": "outgoing"
│ }
│
▼
9. Chatwoot envía a WhatsApp
│
▼
10. Cliente recibe mensaje
Flujo de Ejecución de Herramientas
Consulta del Agente
│
▼
Llamada a Herramienta MCP (ej. list_products)
│
▼
Servidor MCP recibe solicitud de herramienta
│
▼
Llamada HTTP interna a endpoint REST
│ GET https://worker-url.workers.dev/api/products
│
▼
Consulta a Supabase
│ SELECT * FROM products
│ JOIN product_variants ...
│
▼
Devuelve datos formateados
│
▼
Agente procesa resultado
│
▼
Agente genera respuesta en lenguaje natural
Endpoints de API
Endpoints REST
Todos los endpoints tienen como prefijo la URL del worker:
https://mcp-server-laburenchallenge.facundodiaz2727.workers.dev
Productos
GET /api/products Lista todos los productos con variantes.
Parámetros de consulta:
color(opcional): Filtrar por nombre de colorsize(opcional): Filtrar por talleminStock(opcional): Nivel mínimo de stock
Respuesta:
[
{
"id": 1,
"name": "Camiseta Básica",
"description": "Camiseta de algodón",
"price": "1500.00",
"variants": [
{
"id": 1,
"color": "Rojo",
"size": "M",
"stock": 10
}
]
}
]
GET /api/products/:id Obtener detalles de producto por ID.
Respuesta: Objeto de producto único con variantes.
Clientes
POST /api/clients/get-or-create Obtener cliente existente o crear uno nuevo.
Solicitud:
{
"name": "Juan Pérez",
"email": "cliente@example.com",
"phone": "+5491123456789"
}
Respuesta:
{
"clientId": 1,
"cartId": "550e8400-e29b-41d4-a716-446655440000",
"cartStatus": "active"
}
Carritos
POST /api/carts Crear un nuevo carrito.
Solicitud:
{
"clientId": 1 // opcional
}
Respuesta:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"client_id": 1,
"created_at": "2026-02-08T12:00:00Z"
}
GET /api/carts/:cartId Obtener contenidos del carrito.
Respuesta:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"client_id": 1,
"items": [
{
"id": 1,
"product_variant_id": 1,
"quantity": 2,
"price_at_add": "1500.00",
"product_name": "Camiseta Básica",
"color": "Rojo",
"size": "M"
}
],
"total": 3000.00
}
POST /api/carts/:cartId/items Agregar artículo al carrito.
Solicitud:
{
"product_variant_id": 1,
"qty": 2,
"conversation_id": 123 // Opcional - para agregar etiquetas automáticamente
}
Respuesta:
{
"message": "Producto agregado al carrito exitosamente",
"data": {
"id": 1,
"cart_id": "550e8400-e29b-41d4-a716-446655440000",
"product_variant_id": 1,
"qty": 2
}
}
Nota: Si se proporciona conversation_id, el sistema agrega automáticamente una etiqueta en Chatwoot con el tipo de prenda (normalizado a minúsculas sin tildes).
PATCH /api/carts/:cartId/items/:itemId Actualizar cantidad de artículo en carrito.
Solicitud:
{
"quantity": 3
}
DELETE /api/carts/:cartId/items/:itemId Eliminar artículo del carrito.
Chatwoot
POST /api/chatwoot/webhook Recibe webhooks de automation rules de Chatwoot.
Solicitud (desde Chatwoot):
{
"event": "automation_event.message_created",
"id": 1,
"messages": [
{
"content": "hola",
"message_type": 0,
"sender": {
"name": "Cliente",
"type": "contact",
"phone_number": "+5491123456789"
}
}
]
}
Respuesta: 200 OK
Características del webhook:
- Filtra mensajes del bot y sistema (solo procesa mensajes de usuarios)
- Verifica custom attribute
bot(sifalse, no responde - conversación en manos de humano) - Auto-inicializa
bot=trueen conversaciones nuevas - Extrae teléfono automáticamente de WhatsApp
POST /api/chatwoot/request-human Transferir conversación a agente humano.
Solicitud:
{
"conversation_id": 123,
"reason": "reembolso" // "reembolso" | "producto_danado" | "otros"
}
Respuesta:
{
"message": "La conversación ha sido transferida a un agente humano. Un miembro de nuestro equipo te atenderá pronto."
}
Comportamiento:
- Actualiza custom attribute
bot=false - Agrega etiqueta "humano"
- Agrega etiqueta del motivo especificado
- El webhook deja de responder automáticamente a mensajes de esa conversación
Herramientas MCP
Interfaz de Herramientas
Conectarse al servidor MCP en: https://mcp-server-laburenchallenge.facundodiaz2727.workers.dev/mcp
Herramientas Disponibles
list_products
Listar todos los productos con opciones de filtrado.
Parámetros:
{
color?: string, // Filtrar por color
size?: string, // Filtrar por talle
minStock?: number // Nivel mínimo de stock
}
Retorna: Array de productos con variantes.
get_product_details
Obtener información detallada sobre un producto específico.
Parámetros:
{
productId: number
}
Retorna: Producto con todas sus variantes.
get_or_create_client
Obtener cliente existente o crear uno nuevo. Si el cliente existe, actualiza el teléfono. También crea o recupera un carrito activo para el cliente.
Parámetros:
{
name: string,
email: string,
phone?: string
}
Retorna: Objeto con clientId, cartId y cartStatus.
create_cart
Crear un nuevo carrito de compras.
Parámetros:
{
clientId?: number
}
Retorna: Objeto de carrito con UUID.
add_to_cart
Agregar variante de producto al carrito. Si se proporciona conversationId, agrega automáticamente una etiqueta en Chatwoot con el tipo de prenda.
Parámetros:
{
cartId: number | string, // Acepta UUID o número
productVariantId: number,
qty: number,
conversationId?: number // Opcional - para etiquetado automático
}
Retorna: Confirmación de éxito y datos del item agregado.
get_cart
Recuperar contenidos del carrito.
Parámetros:
{
cartId: number | string
}
Retorna: Carrito con artículos y total.
update_cart_item
Actualizar cantidad de artículo en carrito.
Parámetros:
{
cartId: number | string,
itemId: number,
qty: number
}
Retorna: Artículo actualizado.
remove_from_cart
Eliminar artículo del carrito.
Parámetros:
{
cartId: number | string,
itemId: number
}
Retorna: Confirmación de éxito.
request_human_agent
Transferir conversación a un agente humano. El agente debe preguntar primero al cliente el motivo y luego llamar a este tool con el motivo correspondiente.
Parámetros:
{
conversationId: number,
reason: "reembolso" | "producto_danado" | "otros"
}
Retorna: Mensaje de confirmación para el cliente.
Comportamiento:
- Actualiza el custom attribute
bot=falseen Chatwoot - Agrega etiqueta "humano" a la conversación
- Agrega etiqueta del motivo especificado
- El sistema deja de responder automáticamente a esa conversación
Instalación y Despliegue
Prerequisitos
- Node.js 18+
- Cuenta de Cloudflare
- Cuenta de Supabase
- Instancia de Chatwoot
- Agente Laburen (o plataforma de agente IA compatible)
Instalación
- Clonar repositorio
git clone <url-repositorio>
cd mcp-server-laburenchallenge
npm install
- Configurar Supabase
Crear tablas usando el esquema en Esquema de Base de Datos.
- Configurar variables de entorno
# Supabase
npx wrangler secret put NEXT_PUBLIC_SUPABASE_URL
npx wrangler secret put NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY
# Chatwoot (¡sin espacios al final!)
npx wrangler secret put CHATWOOT_URL
npx wrangler secret put CHATWOOT_ACCOUNT_ID
npx wrangler secret put CHATWOOT_API_TOKEN
# Agente Laburen
npx wrangler secret put LABUREN_API_KEY
npx wrangler secret put LABUREN_AGENT_ID
Importante: Al configurar variables de Chatwoot, asegurate de que NO haya espacios al final en los nombres de los secretos.
- Desplegar en Cloudflare
npm run deploy
Tu worker será desplegado en:
https://mcp-server-laburenchallenge.<tu-cuenta>.workers.dev
Configurar Chatwoot
-
Crear Custom Attribute
- Ir a Settings → Custom Attributes → Conversation
- Crear nuevo atributo:
- Display Name: "Bot"
- Key:
bot - Type: Checkbox
- Description: "Indica si el bot está habilitado para esta conversación"
-
Crear Labels (Etiquetas)
- Ir a Settings → Labels
- Crear las siguientes etiquetas manualmente (opcional, para personalizar colores):
humano- Para conversaciones transferidas a agentes humanosreembolso- Cliente solicita reembolsoproducto_danado- Producto llegó dañadootros- Otros motivos- Etiquetas de tipos de prendas (ej:
camiseta,pantalon,sudadera, etc.)
-
Deshabilitar Bot Nativo
- Ir a Settings → Inboxes → [Tu inbox de WhatsApp] → Configuration
- En "Agent Bot", seleccionar "Disable"
- Esto previene respuestas duplicadas
-
Crear Automation Rule
- Ir a Settings → Automations → Rules
- Crear nueva regla
-
Configurar Regla
- Evento: Message Created
- Condiciones:
- Inbox = Tu inbox de WhatsApp
- Message Type = Incoming
- Acciones:
- Action Type: Webhook
- Method: POST
- URL:
https://mcp-server-laburenchallenge.<tu-cuenta>.workers.dev/api/chatwoot/webhook - Headers:
{"Content-Type": "application/json"}
-
Guardar y Testear
Configurar Agente
Actualizar el system prompt del agente para incluir:
Eres un asistente de ventas IA con acceso a herramientas de e-commerce via MCP.
Herramientas disponibles:
- list_products: Explorar catálogo de productos
- get_product_details: Obtener información detallada de productos
- get_or_create_client: Registrar o recuperar cliente
- create_cart: Inicializar carrito de compras
- add_to_cart: Agregar artículos al carrito (usa conversationId para etiquetado automático)
- get_cart: Ver contenidos del carrito
- update_cart_item: Modificar cantidad de artículos
- remove_from_cart: Eliminar artículos
- request_human_agent: Transferir conversación a agente humano
Importante:
- NO uses send_chatwoot_message ni ninguna herramienta de Chatwoot
- Simplemente responde con texto - el sistema envía automáticamente tu respuesta al cliente
- Siempre sé amable y servicial
- Guía a los clientes en la selección de productos y proceso de compra
## ⚠️ REGLAS CRÍTICAS PARA GESTIÓN DE CLIENTES
### ❌ NUNCA hacer esto:
- NO llames a get_or_create_client hasta tener nombre y email REALES proporcionados por el cliente
- NO uses emails falsos como "example@email.com", "test@test.com" o similares
- NO uses el nombre del contacto de WhatsApp como nombre del cliente
- NO asumas datos del cliente
### ✅ FLUJO CORRECTO para clientes nuevos:
**PASO 1**: Saludar y ayudar con consultas de productos
**PASO 2**: Cuando el cliente quiera comprar, pedir nombre y email reales
**PASO 3**: Esperar respuesta con datos REALES del cliente
**PASO 4**: Recién ahora llamar a get_or_create_client con datos REALES
**PASO 5**: Continuar con la venta usando el cartId retornado
### ✅ FLUJO para add_to_cart:
- SIEMPRE pasar el conversationId cuando agregues productos al carrito
- Esto permite que el sistema agregue etiquetas automáticamente en Chatwoot
- Ejemplo: add_to_cart({ cartId: "uuid", productVariantId: 1, qty: 1, conversationId: 123 })
## 🤝 TRANSFERENCIA A AGENTE HUMANO
Cuando el cliente solicite hablar con un humano, seguir este flujo:
### PASO 1: Preguntar el motivo
Entiendo que prefieres hablar con un agente humano. Para poder ayudarte mejor, por favor indícame el motivo:
1️⃣ Reembolso - Quieres solicitar una devolución de dinero 2️⃣ Producto dañado - El producto llegó dañado o defectuoso 3️⃣ Otros - Otro motivo
Por favor responde con el número o el nombre de la opción.
### PASO 2: Clasificar la respuesta
- Si menciona "reembolso", "devolución", "devolver dinero", "cancelar" → usa reason: "reembolso"
- Si menciona "dañado", "roto", "defectuoso", "mal estado", "llegó mal" → usa reason: "producto_danado"
- Para cualquier otro motivo → usa reason: "otros"
### PASO 3: Llamar al tool
```typescript
request_human_agent({
conversationId: [conversation_id],
reason: [reason clasificado]
})
PASO 4: Confirmar al cliente
Después de llamar al tool, confirma:
✅ Perfecto, he transferido tu conversación a un agente humano que te ayudará con [el motivo]. Un miembro de nuestro equipo te atenderá en breve.
---
## Configuración
### Variables de Entorno
| Variable | Descripción | Ejemplo |
|----------|-------------|---------|
| `NEXT_PUBLIC_SUPABASE_URL` | URL del proyecto Supabase | `https://xxx.supabase.co` |
| `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY` | Clave anon de Supabase | `eyJhbGci...` |
| `CHATWOOT_URL` | URL de instancia Chatwoot | `https://app.chatwoot.com` |
| `CHATWOOT_ACCOUNT_ID` | ID de cuenta Chatwoot | `88` |
| `CHATWOOT_API_TOKEN` | Token de acceso API Chatwoot | `xxx` |
| `LABUREN_API_KEY` | Clave API plataforma Laburen | `xxx` |
| `LABUREN_AGENT_ID` | ID del agente en Laburen | `xxx` |
### Configuración de Chatwoot
**Formato URL de Webhook**:
https://<worker-url>/api/chatwoot/webhook
**Payload de Automation Rule** (enviado por Chatwoot):
```json
{
"event": "automation_event.message_created",
"id": 1,
"inbox_id": 92,
"messages": [{
"id": 2800,
"content": "texto del mensaje",
"message_type": 0,
"sender": {
"name": "Nombre del Cliente",
"phone_number": "+5491123456789"
}
}]
}
Ejemplos de Uso
Ejemplo 1: Cliente Navega Productos
Cliente: "Quiero ver camisetas rojas"
Flujo del Agente:
- Llama a
list_products({ color: "Rojo" }) - Recibe lista de productos
- Responde: "Tenemos estas camisetas rojas disponibles: [lista]"
Ejemplo 2: Agregar al Carrito
Cliente: "Quiero la camiseta M"
Flujo del Agente:
- Agente: "Para continuar, necesito tu nombre y email"
- Cliente: "Me llamo Juan Pérez, mi email es juan@email.com"
- Llama a
get_or_create_client({ name: "Juan Pérez", email: "juan@email.com", phone: "+5491123456789" }) - Recibe
{ clientId: 1, cartId: "uuid-abc", cartStatus: "active" } - Llama a
add_to_cart({ cartId: "uuid-abc", productVariantId: 1, qty: 1, conversationId: 123 }) - Sistema agrega automáticamente etiqueta "camiseta" en Chatwoot
- Responde: "Agregué la camiseta M a tu carrito, Juan"
Ejemplo 3: Ver Carrito
Cliente: "Que tengo en el carrito?"
Flujo del Agente:
- Llama a
get_cart({ cartId: "uuid-abc" }) - Responde: "Tienes: 1x Camiseta Roja M ($1500). Total: $1500"
Ejemplo 4: Solicitud de Agente Humano
Cliente: "Quiero hablar con un humano"
Flujo del Agente:
- Agente: "Entiendo que prefieres hablar con un agente humano. ¿Cuál es el motivo? 1️⃣ Reembolso 2️⃣ Producto dañado 3️⃣ Otros"
- Cliente: "El producto llegó roto"
- Agente identifica: reason = "producto_danado"
- Llama a
request_human_agent({ conversationId: 123, reason: "producto_danado" }) - Sistema actualiza
bot=falsey agrega etiquetas "humano" y "producto_danado" - Responde: "✅ He transferido tu conversación a un agente humano. Te atenderán pronto."
- Bot deja de responder a esta conversación automáticamente
Solución de Problemas
Problemas Comunes
1. Webhook no recibe eventos
Síntomas: No hay logs en Cloudflare al enviar mensaje por WhatsApp
Soluciones:
- Verificar que Automation Rule está activa en Chatwoot
- Verificar que la URL del webhook es correcta (sin errores de tipeo)
- Asegurar que las condiciones incluyen "Message Type = Incoming"
- Testear webhook con curl:
curl -X POST https://tu-worker.workers.dev/api/chatwoot/webhook \ -H "Content-Type: application/json" \ -d '{"event":"automation_event.message_created","id":1,"messages":[{"content":"test","message_type":0,"sender":{"name":"Test"}}]}'
2. Agente no responde
Síntomas: Webhook recibe mensaje pero no se envía respuesta
Verificar:
npx wrangler tailpara ver logs- Verificar que
LABUREN_API_KEYyLABUREN_AGENT_IDestán configuradas correctamente - Confirmar que el agente está conectado al servidor MCP
- Verificar que el system prompt del agente incluye instrucciones de uso de herramientas
- Verificar custom attribute
boten Chatwoot (debe sertrueo no existir)
2.1. Bot responde dos veces
Síntomas: El cliente recibe dos respuestas idénticas
Solución: Deshabilitar el bot nativo de Chatwoot:
- Settings → Inboxes → [WhatsApp Inbox] → Configuration → Agent Bot → Disable
3. Variables undefined
Síntomas: Los logs de error muestran undefined/api/v1/accounts/undefined
Solución:
- Eliminar y recrear secretos (verificar espacios al final):
npx wrangler secret delete "CHATWOOT_URL " npx wrangler secret put CHATWOOT_URL
4. Errores de formato de ID de carrito
Síntomas: Invalid input: expected number, received string
Solución: Esto ya está manejado - las herramientas aceptan tanto formatos UUID como numéricos.
5. Labels no se agregan automáticamente
Síntomas: No se agregan etiquetas al agregar productos al carrito
Verificar:
- Que el agente esté pasando
conversationIdal llamar aadd_to_cart - Que las etiquetas estén creadas en Chatwoot (o dejar que se creen automáticamente)
- Ver logs con
npx wrangler tailpara verificar el proceso de etiquetado - Verificar que los productos tienen
garment_typeasignado en la base de datos
6. Cliente creado con datos falsos
Síntomas: Clientes en la DB con emails como "example@email.com"
Solución: Actualizar el prompt del agente con las reglas de gestión de clientes (ver sección Configurar Agente)
Comandos de Debug
Ver logs en vivo:
npx wrangler tail --format pretty
Listar secretos:
npx wrangler secret list
Testear conexión MCP:
curl https://tu-worker.workers.dev/mcp
Testear endpoint de webhook:
curl -X POST https://tu-worker.workers.dev/api/chatwoot/webhook-debug \
-H "Content-Type: application/json" \
-d '{"event":"message_created","content":"test"}'
Consideraciones de Producción
Seguridad
- ✅ Secretos almacenados en Cloudflare (no en código)
- ✅ Políticas RLS de Supabase deben ser configuradas
- ⚠️ Sin autenticación en endpoint MCP (agregar si es necesario)
- ✅ Webhook valida tipos de eventos
- ✅ Webhook filtra mensajes del bot/sistema para prevenir loops
- ✅ Custom attribute
botpreviene respuestas automáticas cuando hay agente humano
Performance
- ✅ Cloudflare Workers: Despliegue global en edge
- ✅ Supabase: Postgres con connection pooling
- ⚠️ Tiempo de respuesta del agente: ~16 segundos (puede necesitar optimización)
- ✅ Respuestas de webhook: Siempre 200 OK (previene reintentos)
Monitoreo
- Cloudflare Workers Analytics
wrangler tailpara logs en tiempo real- Historial de conversaciones de Chatwoot
- Logs y métricas de Supabase
Escalabilidad
- Cloudflare Workers: Auto-escala globalmente
- Supabase: Escalar tier de base de datos según necesidad
- Considerar caché para catálogo de productos
- Implementar rate limiting si es necesario
Licencia
MIT
Soporte
Para problemas o preguntas, por favor abrir un issue en GitHub.
Construido con:
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.