E-commerce MCP Server with Chatwoot Integration

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.

Category
Visit Server

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

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
WhatsApp 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
email 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 color
  • size (opcional): Filtrar por talle
  • minStock (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 (si false, no responde - conversación en manos de humano)
  • Auto-inicializa bot=true en 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=false en 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

  1. Clonar repositorio
git clone <url-repositorio>
cd mcp-server-laburenchallenge
npm install
  1. Configurar Supabase

Crear tablas usando el esquema en Esquema de Base de Datos.

  1. 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.

  1. Desplegar en Cloudflare
npm run deploy

Tu worker será desplegado en: https://mcp-server-laburenchallenge.<tu-cuenta>.workers.dev

Configurar Chatwoot

  1. 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"
  2. Crear Labels (Etiquetas)

    • Ir a Settings → Labels
    • Crear las siguientes etiquetas manualmente (opcional, para personalizar colores):
      • humano - Para conversaciones transferidas a agentes humanos
      • reembolso - Cliente solicita reembolso
      • producto_danado - Producto llegó dañado
      • otros - Otros motivos
      • Etiquetas de tipos de prendas (ej: camiseta, pantalon, sudadera, etc.)
  3. Deshabilitar Bot Nativo

    • Ir a Settings → Inboxes → [Tu inbox de WhatsApp] → Configuration
    • En "Agent Bot", seleccionar "Disable"
    • Esto previene respuestas duplicadas
  4. Crear Automation Rule

    • Ir a Settings → Automations → Rules
    • Crear nueva regla
  5. 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"}
  6. 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:

  1. Llama a list_products({ color: "Rojo" })
  2. Recibe lista de productos
  3. Responde: "Tenemos estas camisetas rojas disponibles: [lista]"

Ejemplo 2: Agregar al Carrito

Cliente: "Quiero la camiseta M"

Flujo del Agente:

  1. Agente: "Para continuar, necesito tu nombre y email"
  2. Cliente: "Me llamo Juan Pérez, mi email es juan@email.com"
  3. Llama a get_or_create_client({ name: "Juan Pérez", email: "juan@email.com", phone: "+5491123456789" })
  4. Recibe { clientId: 1, cartId: "uuid-abc", cartStatus: "active" }
  5. Llama a add_to_cart({ cartId: "uuid-abc", productVariantId: 1, qty: 1, conversationId: 123 })
  6. Sistema agrega automáticamente etiqueta "camiseta" en Chatwoot
  7. Responde: "Agregué la camiseta M a tu carrito, Juan"

Ejemplo 3: Ver Carrito

Cliente: "Que tengo en el carrito?"

Flujo del Agente:

  1. Llama a get_cart({ cartId: "uuid-abc" })
  2. Responde: "Tienes: 1x Camiseta Roja M ($1500). Total: $1500"

Ejemplo 4: Solicitud de Agente Humano

Cliente: "Quiero hablar con un humano"

Flujo del Agente:

  1. Agente: "Entiendo que prefieres hablar con un agente humano. ¿Cuál es el motivo? 1️⃣ Reembolso 2️⃣ Producto dañado 3️⃣ Otros"
  2. Cliente: "El producto llegó roto"
  3. Agente identifica: reason = "producto_danado"
  4. Llama a request_human_agent({ conversationId: 123, reason: "producto_danado" })
  5. Sistema actualiza bot=false y agrega etiquetas "humano" y "producto_danado"
  6. Responde: "✅ He transferido tu conversación a un agente humano. Te atenderán pronto."
  7. 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 tail para ver logs
  • Verificar que LABUREN_API_KEY y LABUREN_AGENT_ID está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 bot en Chatwoot (debe ser true o 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 conversationId al llamar a add_to_cart
  • Que las etiquetas estén creadas en Chatwoot (o dejar que se creen automáticamente)
  • Ver logs con npx wrangler tail para verificar el proceso de etiquetado
  • Verificar que los productos tienen garment_type asignado 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 bot previene 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 tail para 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

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured