Skip to main content
Glama

Uazapi WhatsApp MCP Server

by pabloweyne
workflow-chatbot-v5-pro.json21.4 kB
{ "name": "UAZAPI WhatsApp Chatbot v5 PRO", "nodes": [ { "parameters": { "httpMethod": "POST", "path": "uazapi-webhook", "responseMode": "responseNode" }, "id": "webhook", "name": "Webhook", "type": "n8n-nodes-base.webhook", "typeVersion": 2, "position": [240, 300] }, { "parameters": { "jsCode": "const body = $input.first().json.body || $input.first().json;\nconst remoteJid = body.key?.remoteJid || '';\nconst participant = body.key?.participant || '';\nconst isGroup = remoteJid.includes('@g.us');\nconst senderPhone = isGroup ? participant.split('@')[0] : remoteJid.split('@')[0];\nconst message = body.message?.conversation || body.message?.extendedTextMessage?.text || '';\nconst pushName = body.pushName || '';\nconst botNumber = $env.BOT_PHONE_NUMBER || '';\nconst isBotMentioned = message.toLowerCase().includes('@bot') || (body.message?.extendedTextMessage?.contextInfo?.mentionedJid || []).some(j => j.includes(botNumber));\n\nreturn { json: {\n chatId: remoteJid, senderPhone, senderName: pushName, message, messageId: body.key?.id || '',\n timestamp: Date.now(), isGroup, isBotMentioned,\n replyTo: isGroup ? remoteJid : senderPhone,\n keys: {\n user: `uazapi:user:${senderPhone}`,\n config: 'uazapi:config',\n templates: 'uazapi:templates',\n funil: 'uazapi:funil',\n blacklist: 'uazapi:blacklist',\n limits: `uazapi:limits:${new Date().toISOString().split('T')[0]}`,\n audit: 'uazapi:audit',\n lembretes: 'uazapi:lembretes'\n }\n}};" }, "id": "extract", "name": "Extrair", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [460, 300] }, { "parameters": { "operation": "get", "key": "={{ $json.keys.blacklist }}" }, "id": "redis-blacklist", "name": "Blacklist", "type": "n8n-nodes-base.redis", "typeVersion": 1, "position": [680, 300], "credentials": { "redis": { "id": "REDIS_CREDENTIAL_ID", "name": "Redis" } } }, { "parameters": { "jsCode": "const msg = $('Extrair').first().json;\nlet blacklist = [];\ntry { blacklist = JSON.parse($input.first().json?.value || '[]'); } catch(e) {}\nconst isBlocked = blacklist.includes(msg.senderPhone);\nconst isAuthorized = msg.senderPhone === ($env.ADMIN_PHONE || 'SEU_NUMERO');\nreturn { json: { ...msg, isBlocked, isAuthorized, blacklist } };" }, "id": "check-blacklist", "name": "Check Blacklist", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [900, 300] }, { "parameters": { "conditions": { "conditions": [{ "leftValue": "={{ $json.isBlocked }}", "rightValue": "={{false}}", "operator": { "type": "boolean", "operation": "equals" } }] } }, "id": "not-blocked", "name": "Não Bloqueado?", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [1120, 300] }, { "parameters": { "operation": "get", "key": "={{ $json.keys.limits }}" }, "id": "redis-limits", "name": "Limites", "type": "n8n-nodes-base.redis", "typeVersion": 1, "position": [1340, 240], "credentials": { "redis": { "id": "REDIS_CREDENTIAL_ID", "name": "Redis" } } }, { "parameters": { "jsCode": "const msg = $('Check Blacklist').first().json;\nlet limits = { enviadas: 0, max: 100 };\ntry { limits = { ...limits, ...JSON.parse($input.first().json?.value || '{}') }; } catch(e) {}\nconst limitReached = limits.enviadas >= limits.max;\nreturn { json: { ...msg, limits, limitReached } };" }, "id": "check-limits", "name": "Check Limites", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [1560, 240] }, { "parameters": { "operation": "get", "key": "={{ $json.keys.config }}" }, "id": "redis-config", "name": "Config", "type": "n8n-nodes-base.redis", "typeVersion": 1, "position": [1780, 240], "credentials": { "redis": { "id": "REDIS_CREDENTIAL_ID", "name": "Redis" } } }, { "parameters": { "operation": "get", "key": "={{ $json.keys.templates }}" }, "id": "redis-templates", "name": "Templates", "type": "n8n-nodes-base.redis", "typeVersion": 1, "position": [1780, 360], "credentials": { "redis": { "id": "REDIS_CREDENTIAL_ID", "name": "Redis" } } }, { "parameters": { "operation": "get", "key": "={{ $json.keys.funil }}" }, "id": "redis-funil", "name": "Funil", "type": "n8n-nodes-base.redis", "typeVersion": 1, "position": [1780, 480], "credentials": { "redis": { "id": "REDIS_CREDENTIAL_ID", "name": "Redis" } } }, { "parameters": { "operation": "get", "key": "={{ $json.keys.user }}" }, "id": "redis-user", "name": "User", "type": "n8n-nodes-base.redis", "typeVersion": 1, "position": [1780, 120], "credentials": { "redis": { "id": "REDIS_CREDENTIAL_ID", "name": "Redis" } } }, { "parameters": { "jsCode": "const msg = $('Check Limites').first().json;\nlet ctx = { historico: [], contatos: [], stats: { enviadas: 0 } };\nlet config = { grupos_habilitados: false, responder_apenas_mencao: true, limite_diario: 100, telegram_chat_id: '', email_notif: '' };\nlet templates = [];\nlet funil = { leads: [], estagios: ['Novo', 'Contato', 'Proposta', 'Negociação', 'Fechado', 'Perdido'] };\n\ntry { ctx = JSON.parse($('User').first().json?.value || '{}'); } catch(e) {}\ntry { config = { ...config, ...JSON.parse($('Config').first().json?.value || '{}') }; } catch(e) {}\ntry { templates = JSON.parse($('Templates').first().json?.value || '[]'); } catch(e) {}\ntry { funil = { ...funil, ...JSON.parse($('Funil').first().json?.value || '{}') }; } catch(e) {}\n\n// Preparar prompt\nlet prompt = '';\nif (ctx.historico?.length) {\n prompt += '\\n## HISTÓRICO (últimas mensagens)\\n';\n ctx.historico.slice(-5).forEach(m => prompt += `${m.role === 'user' ? 'Você' : 'Bot'}: ${m.content}\\n`);\n}\nif (templates.length) {\n prompt += '\\n## TEMPLATES SALVOS\\n';\n templates.forEach(t => prompt += `- ${t.nome}: \"${t.texto.substring(0,50)}...\"\\n`);\n}\nif (funil.leads?.length) {\n prompt += '\\n## FUNIL DE VENDAS\\n';\n funil.estagios.forEach(e => {\n const leads = funil.leads.filter(l => l.estagio === e);\n if (leads.length) prompt += `${e}: ${leads.map(l => l.nome).join(', ')}\\n`;\n });\n}\nprompt += `\\n## LIMITES\\n- Hoje: ${msg.limits.enviadas}/${config.limite_diario} mensagens`;\nprompt += `\\n## CONFIG\\n- Telegram: ${config.telegram_chat_id ? 'Configurado' : 'Não'}\\n- Email: ${config.email_notif ? 'Configurado' : 'Não'}`;\n\nreturn { json: { ...msg, ctx, config, templates, funil, prompt, keys: msg.keys } };" }, "id": "prepare", "name": "Preparar", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [2000, 240] }, { "parameters": { "model": "gpt-4o", "messages": { "values": [ { "role": "system", "content": "=Você é um assistente WhatsApp PRO com CRM, templates, análise e integrações.\n\n## AÇÕES DISPONÍVEIS\n\n### TEMPLATES\n- salvar_template: {nome, texto} - Salva template\n- usar_template: {nome, numero} - Envia template para alguém\n- listar_templates: {} - Lista todos\n- deletar_template: {nome}\n\n### FUNIL DE VENDAS\n- adicionar_lead: {nome, numero, estagio?} - Novo lead (default: 'Novo')\n- mover_lead: {nome_ou_numero, estagio} - Muda estágio\n- ver_funil: {} - Mostra funil completo\n- leads_estagio: {estagio} - Leads de um estágio\n- remover_lead: {nome_ou_numero}\nEstágios: Novo → Contato → Proposta → Negociação → Fechado/Perdido\n\n### ANÁLISE & RESUMO\n- analisar_sentimento: {mensagem} - Analisa tom (positivo/negativo/urgente)\n- resumir_conversa: {numero_ou_grupo} - Resume últimas mensagens\n- resumir_grupo: {grupo} - Resume discussão do grupo\n\n### LEMBRETES\n- criar_lembrete: {texto, data_hora, numero?} - Lembrete com notificação\n- listar_lembretes: {}\n- cancelar_lembrete: {id}\n\n### BACKUP\n- backup_conversas: {} - Exporta histórico\n- backup_contatos: {} - Exporta contatos\n- backup_funil: {} - Exporta CRM\n\n### NOTIFICAÇÕES\n- config_telegram: {chat_id} - Configura Telegram\n- config_email: {email} - Configura email\n- notificar_telegram: {mensagem} - Envia pro Telegram\n- notificar_email: {assunto, corpo} - Envia email\n- notificar_urgente: {mensagem} - Telegram + Email\n\n### BLACKLIST & LIMITES\n- bloquear: {numero} - Adiciona à blacklist\n- desbloquear: {numero} - Remove da blacklist\n- ver_blacklist: {}\n- config_limite: {limite_diario} - Define limite\n- ver_limites: {} - Mostra uso atual\n\n### AUDITORIA\n- ver_log: {limite?} - Últimas ações\n- log_hoje: {} - Ações de hoje\n\n### MENSAGENS\n- enviar_texto: {numero, mensagem}\n- preparar_massa: {numeros, mensagem} - SEMPRE pede confirmação\n- confirmar_massa: {} - Executa após \"sim\"\n\n{{ $json.prompt }}\n\n## RESPOSTA JSON\n```json\n{\n \"acao\": \"nome\",\n \"parametros\": {},\n \"mensagem_usuario\": \"resposta\",\n \"salvar\": {\n \"template\": {\"nome\": \"\", \"texto\": \"\"},\n \"lead\": {\"nome\": \"\", \"numero\": \"\", \"estagio\": \"\"},\n \"lembrete\": {\"texto\": \"\", \"data_hora\": \"\", \"numero\": \"\"},\n \"config\": {},\n \"blacklist_add\": \"\",\n \"blacklist_remove\": \"\"\n },\n \"notificar\": {\n \"telegram\": \"mensagem\",\n \"email\": {\"assunto\": \"\", \"corpo\": \"\"}\n },\n \"log\": \"descrição da ação\"\n}\n```\n\n## ANÁLISE DE SENTIMENTO\nQuando analisar, classifique como:\n- 😊 Positivo (satisfeito, agradecido)\n- 😐 Neutro (informativo, normal)\n- 😠 Negativo (reclamação, insatisfação)\n- 🚨 Urgente (problema crítico, precisa atenção)\n\nSe detectar URGENTE, sugira notificar via Telegram/Email.\n\n## REGRAS\n- NUNCA enviar em massa sem confirmação\n- Sempre logar ações importantes\n- Notificar urgências automaticamente se configurado" }, { "role": "user", "content": "={{ $json.message }}" } ] }, "options": { "temperature": 0.3, "maxTokens": 2500 } }, "id": "openai", "name": "OpenAI", "type": "@n8n/n8n-nodes-langchain.openAi", "typeVersion": 1.6, "position": [2220, 240], "credentials": { "openAiApi": { "id": "OPENAI_CREDENTIAL_ID", "name": "OpenAI API" } } }, { "parameters": { "jsCode": "const gpt = $input.first().json.message.content;\nconst prev = $('Preparar').first().json;\nlet parsed;\ntry {\n const m = gpt.match(/```json\\s*([\\s\\S]*?)```/) || gpt.match(/\\{[\\s\\S]*\\}/);\n parsed = JSON.parse(m[1] || m[0]);\n} catch (e) { parsed = { acao: 'responder', parametros: {}, mensagem_usuario: gpt }; }\n\nlet ctx = prev.ctx || { historico: [], contatos: [], stats: { enviadas: 0 } };\nlet config = prev.config;\nlet templates = prev.templates || [];\nlet funil = prev.funil || { leads: [], estagios: [] };\nlet limits = prev.limits;\n\n// Histórico\nctx.historico.push({ role: 'user', content: prev.message, ts: Date.now() });\nctx.historico.push({ role: 'assistant', content: parsed.mensagem_usuario, ts: Date.now() });\nif (ctx.historico.length > 30) ctx.historico = ctx.historico.slice(-30);\n\n// Salvar template\nif (parsed.salvar?.template?.nome) {\n const idx = templates.findIndex(t => t.nome === parsed.salvar.template.nome);\n if (idx >= 0) templates[idx] = parsed.salvar.template;\n else templates.push(parsed.salvar.template);\n}\n\n// Salvar lead\nif (parsed.salvar?.lead?.nome) {\n const lead = { ...parsed.salvar.lead, estagio: parsed.salvar.lead.estagio || 'Novo', criado: Date.now() };\n const idx = funil.leads.findIndex(l => l.numero === lead.numero);\n if (idx >= 0) funil.leads[idx] = { ...funil.leads[idx], ...lead };\n else funil.leads.push(lead);\n}\n\n// Config\nif (parsed.salvar?.config) config = { ...config, ...parsed.salvar.config };\n\n// Blacklist\nlet blacklist = prev.blacklist || [];\nif (parsed.salvar?.blacklist_add && !blacklist.includes(parsed.salvar.blacklist_add)) {\n blacklist.push(parsed.salvar.blacklist_add);\n}\nif (parsed.salvar?.blacklist_remove) {\n blacklist = blacklist.filter(b => b !== parsed.salvar.blacklist_remove);\n}\n\n// Incrementar limite\nif (parsed.acao === 'enviar_texto' || parsed.acao === 'usar_template') {\n limits.enviadas = (limits.enviadas || 0) + 1;\n ctx.stats.enviadas = (ctx.stats.enviadas || 0) + 1;\n}\n\n// Log de auditoria\nconst logEntry = {\n ts: Date.now(),\n acao: parsed.acao,\n descricao: parsed.log || parsed.acao,\n user: prev.senderPhone\n};\n\nreturn { json: {\n ...parsed,\n replyTo: prev.replyTo,\n keys: prev.keys,\n config,\n saves: {\n ctx: JSON.stringify(ctx),\n config: JSON.stringify(config),\n templates: JSON.stringify(templates),\n funil: JSON.stringify(funil),\n blacklist: JSON.stringify(blacklist),\n limits: JSON.stringify(limits)\n },\n logEntry: JSON.stringify(logEntry),\n notificar: parsed.notificar,\n telegram_chat_id: config.telegram_chat_id,\n email_notif: config.email_notif\n}};" }, "id": "parse", "name": "Parse", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [2440, 240] }, { "parameters": { "operation": "set", "key": "={{ $json.keys.user }}", "value": "={{ $json.saves.ctx }}", "expire": true, "ttl": 604800 }, "id": "save-user", "name": "Save User", "type": "n8n-nodes-base.redis", "typeVersion": 1, "position": [2660, 80], "credentials": { "redis": { "id": "REDIS_CREDENTIAL_ID", "name": "Redis" } } }, { "parameters": { "operation": "set", "key": "={{ $json.keys.config }}", "value": "={{ $json.saves.config }}" }, "id": "save-config", "name": "Save Config", "type": "n8n-nodes-base.redis", "typeVersion": 1, "position": [2660, 180], "credentials": { "redis": { "id": "REDIS_CREDENTIAL_ID", "name": "Redis" } } }, { "parameters": { "operation": "set", "key": "={{ $json.keys.templates }}", "value": "={{ $json.saves.templates }}" }, "id": "save-templates", "name": "Save Templates", "type": "n8n-nodes-base.redis", "typeVersion": 1, "position": [2660, 280], "credentials": { "redis": { "id": "REDIS_CREDENTIAL_ID", "name": "Redis" } } }, { "parameters": { "operation": "set", "key": "={{ $json.keys.funil }}", "value": "={{ $json.saves.funil }}" }, "id": "save-funil", "name": "Save Funil", "type": "n8n-nodes-base.redis", "typeVersion": 1, "position": [2660, 380], "credentials": { "redis": { "id": "REDIS_CREDENTIAL_ID", "name": "Redis" } } }, { "parameters": { "operation": "set", "key": "={{ $json.keys.blacklist }}", "value": "={{ $json.saves.blacklist }}" }, "id": "save-blacklist", "name": "Save Blacklist", "type": "n8n-nodes-base.redis", "typeVersion": 1, "position": [2660, 480], "credentials": { "redis": { "id": "REDIS_CREDENTIAL_ID", "name": "Redis" } } }, { "parameters": { "operation": "set", "key": "={{ $json.keys.limits }}", "value": "={{ $json.saves.limits }}", "expire": true, "ttl": 86400 }, "id": "save-limits", "name": "Save Limits", "type": "n8n-nodes-base.redis", "typeVersion": 1, "position": [2860, 80], "credentials": { "redis": { "id": "REDIS_CREDENTIAL_ID", "name": "Redis" } } }, { "parameters": { "operation": "push", "key": "={{ $json.keys.audit }}", "value": "={{ $json.logEntry }}" }, "id": "save-audit", "name": "Save Audit", "type": "n8n-nodes-base.redis", "typeVersion": 1, "position": [2860, 180], "credentials": { "redis": { "id": "REDIS_CREDENTIAL_ID", "name": "Redis" } } }, { "parameters": { "conditions": { "conditions": [{ "leftValue": "={{ $json.notificar?.telegram }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty" } }] } }, "id": "check-telegram", "name": "Notificar Telegram?", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [2860, 300] }, { "parameters": { "method": "POST", "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage", "sendBody": true, "specifyBody": "json", "jsonBody": "={ \"chat_id\": \"{{ $('Parse').first().json.telegram_chat_id }}\", \"text\": \"🔔 WhatsApp Bot:\\n\\n{{ $('Parse').first().json.notificar.telegram }}\" }" }, "id": "telegram", "name": "Telegram", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [3080, 240] }, { "parameters": { "conditions": { "conditions": [{ "leftValue": "={{ $json.notificar?.email?.assunto }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty" } }] } }, "id": "check-email", "name": "Notificar Email?", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [2860, 420] }, { "parameters": { "fromEmail": "={{ $env.SMTP_FROM }}", "toEmail": "={{ $('Parse').first().json.email_notif }}", "subject": "=🔔 WhatsApp: {{ $('Parse').first().json.notificar.email.assunto }}", "text": "={{ $('Parse').first().json.notificar.email.corpo }}" }, "id": "email", "name": "Email", "type": "n8n-nodes-base.emailSend", "typeVersion": 2.1, "position": [3080, 400], "credentials": { "smtp": { "id": "SMTP_CREDENTIAL_ID", "name": "SMTP" } } }, { "parameters": { "method": "POST", "url": "=https://api.uazapi.com/instances/{{ $env.UAZAPI_INSTANCE_ID }}/messages/send/text", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendBody": true, "specifyBody": "json", "jsonBody": "={ \"phone\": \"{{ $('Parse').first().json.replyTo }}\", \"message\": \"{{ $('Parse').first().json.mensagem_usuario }}\" }" }, "id": "reply", "name": "Responder", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [3300, 300], "credentials": { "httpHeaderAuth": { "id": "UAZAPI_CREDENTIAL_ID", "name": "UAZAPI Auth" } } }, { "parameters": { "respondWith": "json", "responseBody": "={\"status\": \"ok\"}" }, "id": "respond-ok", "name": "OK", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.1, "position": [3520, 300] }, { "parameters": { "respondWith": "json", "responseBody": "={\"status\": \"blocked\"}" }, "id": "respond-blocked", "name": "Blocked", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.1, "position": [1340, 400] } ], "connections": { "Webhook": { "main": [[{ "node": "Extrair", "type": "main", "index": 0 }]] }, "Extrair": { "main": [[{ "node": "Blacklist", "type": "main", "index": 0 }]] }, "Blacklist": { "main": [[{ "node": "Check Blacklist", "type": "main", "index": 0 }]] }, "Check Blacklist": { "main": [[{ "node": "Não Bloqueado?", "type": "main", "index": 0 }]] }, "Não Bloqueado?": { "main": [[{ "node": "Limites", "type": "main", "index": 0 }], [{ "node": "Blocked", "type": "main", "index": 0 }]] }, "Limites": { "main": [[{ "node": "Check Limites", "type": "main", "index": 0 }]] }, "Check Limites": { "main": [[{ "node": "Config", "type": "main", "index": 0 }, { "node": "Templates", "type": "main", "index": 0 }, { "node": "Funil", "type": "main", "index": 0 }, { "node": "User", "type": "main", "index": 0 }]] }, "Config": { "main": [[{ "node": "Preparar", "type": "main", "index": 0 }]] }, "Templates": { "main": [[]] }, "Funil": { "main": [[]] }, "User": { "main": [[]] }, "Preparar": { "main": [[{ "node": "OpenAI", "type": "main", "index": 0 }]] }, "OpenAI": { "main": [[{ "node": "Parse", "type": "main", "index": 0 }]] }, "Parse": { "main": [[{ "node": "Save User", "type": "main", "index": 0 }, { "node": "Save Config", "type": "main", "index": 0 }, { "node": "Save Templates", "type": "main", "index": 0 }, { "node": "Save Funil", "type": "main", "index": 0 }, { "node": "Save Blacklist", "type": "main", "index": 0 }]] }, "Save User": { "main": [[{ "node": "Save Limits", "type": "main", "index": 0 }]] }, "Save Limits": { "main": [[{ "node": "Save Audit", "type": "main", "index": 0 }]] }, "Save Audit": { "main": [[{ "node": "Notificar Telegram?", "type": "main", "index": 0 }, { "node": "Notificar Email?", "type": "main", "index": 0 }]] }, "Notificar Telegram?": { "main": [[{ "node": "Telegram", "type": "main", "index": 0 }], [{ "node": "Responder", "type": "main", "index": 0 }]] }, "Telegram": { "main": [[{ "node": "Responder", "type": "main", "index": 0 }]] }, "Notificar Email?": { "main": [[{ "node": "Email", "type": "main", "index": 0 }], []] }, "Email": { "main": [[]] }, "Responder": { "main": [[{ "node": "OK", "type": "main", "index": 0 }]] } }, "settings": { "executionOrder": "v1" } }

Latest Blog Posts

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/pabloweyne/uazapi-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server