Integrações
Visão geral das integrações nativas do Hub: WhatsApp via Evolution API, email via SMTP, workflows n8n e ferramentas MCP, com instruções para adicionar novas integrações.
Integrações
O Hub é uma plataforma no-code para construir agentes que conversam com canais externos e executam ações em sistemas de terceiros. Cada integração é exposta como ferramenta MCP que o agente pode invocar durante uma conversa.
As integrações nativas vivem em apps/mcp-server/src/tools/ e são descobertas automaticamente pelo MCP server na inicialização via ensureIntegrationsLoaded().
Credenciais nunca são passadas como parâmetro de ferramenta. O MCP server resolve credenciais por organização a partir do X-Org-Id no contexto da request, usando CredentialSet (org-level) ou AgentCredentialOverride (agente-level). Consulte Autenticação para detalhes.
WhatsApp (Evolution API)
A integração de WhatsApp usa Evolution API — uma camada open-source sobre o Baileys que expõe uma API REST por instância.
Slug da integração: evolution_api
Ferramentas MCP expostas:
| Tool | Descrição |
|---|---|
whatsapp_send_text | Envia mensagem de texto para um número (com country code) |
whatsapp_send_media | Envia imagem, vídeo, áudio ou documento por URL pública |
whatsapp_send_template | Envia template aprovado (WABA / HSM) |
Credenciais obrigatórias (auto-injetadas a partir do Channel da organização):
EVOLUTION_API_URL # base URL da Evolution API
EVOLUTION_API_KEY # apikey do header
EVOLUTION_INSTANCE_NAME # nome da instância WhatsAppComo o agente envia uma mensagem
O agente LangGraph chama a tool MCP whatsapp_send_text com os argumentos number e text. O MCP server resolve o Channel ativo da org, monta o request e chama:
POST {EVOLUTION_API_URL}/message/sendText/{EVOLUTION_INSTANCE_NAME}
apikey: {EVOLUTION_API_KEY}
Content-Type: application/json
{
"number": "5511999998888",
"text": "Olá!"
}O number deve incluir country code, apenas dígitos (ex.: 5511999998888).
Ingestão de mensagens recebidas
Mensagens entrantes do WhatsApp são processadas pelo consumer (apps/langgraph-server/oap_agent/consumer.py), que consome a fila RabbitMQ alimentada pelo webhook da Evolution API. O consumer normaliza o payload pelo adapter evolution.ts e dispara o grafo do agente. Detalhes do contrato canônico em Channel adapters.
Email (SMTP)
A integração de email usa SMTP via nodemailer — qualquer provedor compatível (Resend, SendGrid, Amazon SES, Postmark, SMTP custom) pode ser plugado configurando as credenciais.
Nodemailer tem timeout padrão de socket de 10 minutos. Em workers e tools MCP, defina explicitamente socketTimeout e connectionTimeout para evitar travamento silencioso.
Slug da integração: email_smtp
Ferramenta MCP exposta:
| Tool | Descrição |
|---|---|
send_email | Envia um email transacional via SMTP |
Campos de credencial:
| Chave | Obrigatório | Descrição |
|---|---|---|
SMTP_HOST | sim | Host do servidor SMTP |
SMTP_PORT | sim | Porta (tipicamente 587 para STARTTLS, 465 para SSL) |
SMTP_USER | sim | Usuário de autenticação |
SMTP_PASS | sim | Senha ou API key |
FROM_EMAIL | sim | Endereço remetente |
FROM_NAME | não | Nome de exibição do remetente |
Exemplo de configuração com Resend
Resend expõe um relay SMTP. Configure o Channel de email da org com:
SMTP_HOST=smtp.resend.com
SMTP_PORT=587
SMTP_USER=resend
SMTP_PASS=re_xxxxxxxxxxxxx
[email protected]
FROM_NAME=Sua EmpresaO domínio FROM_EMAIL precisa estar verificado no provedor (SPF + DKIM).
n8n workflows
O Hub usa n8n para orquestrar workflows de eventos operacionais — alertas do GlitchTip, automações administrativas, ingestões batch — que não fazem parte do fluxo conversacional do agente.
Instância: https://n8n-hub.simplafy.com.br
MCP n8n no agente: o .mcp.json do repo declara o servidor n8n-mcp (npx n8n-mcp) com N8N_API_URL + N8N_API_KEY, expondo tools de listagem, criação, validação e execução de workflows direto do agente Claude Code durante o desenvolvimento.
Padrões de workflow
Ao construir tool nodes para um nó AI Agent dentro do n8n:
Use n8n-nodes-base.httpRequestTool v4.4, não @n8n/n8n-nodes-langchain.toolHttpRequest. A API REST do n8n só aceita conexões ai_tool se o nó for do tipo base.
Cada $fromAI() key deve ser única entre todas as tool nodes do mesmo agente. Chaves duplicadas com descrições diferentes derrubam o workflow.
sendQuery: false em POST tool nodes — evita conflito de key entre query string e body.
Conexões ai_tool apenas pela UI. A API REST converte ai_tool em main silenciosamente; criar via API quebra o agent.
Exemplo: GlitchTip para GitHub Issue
O workflow bzp5JdOOLXhqF4xI recebe webhook do GlitchTip, faz análise por LLM e abre issue no GitHub. Ele expõe 5 tools ao AI Agent:
Read File
Search Issues
Create Issue
Add Comment
Get GlitchTip IssueWebhook endpoint: https://n8n-hub.simplafy.com.br/webhook/glitchtip-events.
MCP tools
Toda integração nativa do Hub é distribuída como ferramenta MCP no servidor apps/mcp-server. Isso garante que o mesmo conjunto de tools fica disponível para:
- Agentes LangGraph em produção (transport HTTP/Streamable)
- Tools Playground na admin web
- Claude Code via tunnel local (
./scripts/mcp-tunnel.sh start)
Tools nativas registradas
| Slug | Tools | Função |
|---|---|---|
evolution_api | whatsapp_send_text, whatsapp_send_media, whatsapp_send_template | WhatsApp via Evolution |
email_smtp | send_email | Email transacional via SMTP |
postgres | postgres_query, postgres_execute | Query SQL parametrizada |
google_sheets | sheets_read, sheets_append, sheets_update | Leitura/escrita em planilhas |
followize | followize_* | CRM Followize (OAuth2) |
crm | crm_lead_* | CRM interno (leads, históricos) |
org_files | org_files_* | Storage de arquivos por org |
uniflex_caderno | uniflex_* | Integração Uniflex (seguros) |
pipefy (GraphQL discovery) | dinâmicas | Pipefy por pipe descoberto |
admin | admin_* | Operações internas (apenas service-account) |
Tools dinâmicas
Além das tools estáticas, o MCP server expõe DynamicIntegration e DynamicTool — ferramentas geradas em runtime a partir de specs OpenAPI registradas por org. Isso permite plugar qualquer API REST sem código novo, mapeando endpoints para tools MCP via configuração.
Contexto de execução
Toda tool MCP recebe contexto via headers HTTP propagados pelo SDK:
X-Org-Id # organização ativa (obrigatório)
X-Agent-Id # agente que está chamando (opcional)
X-Deployment-Id # deployment LangGraph (opcional)Dentro do handler, o padrão é:
async (rawArgs, extra) => {
const { args, credentials, context } = await resolveAndApplyMappings(
"tool_name",
rawArgs,
extra,
);
const missing = validateCredentials("tool_name", credentials);
if (missing.length > 0) {
return { content: [{ type: "text", text: `Missing: ${missing.join(", ")}` }] };
}
// ... lógica da tool
}resolveAndApplyMappings faz três coisas: resolve credenciais da org (com cache de 1 minuto), aplica ParamMapping configurado por agente, e retorna o contexto pronto para uso.
Adicionar nova integração
Para adicionar uma integração nativa nova ao Hub, siga o padrão estabelecido em apps/mcp-server/src/tools/.
Crie o arquivo da tool em apps/mcp-server/src/tools/<slug>.ts. Use postgres.ts, followize.ts ou google-sheets.ts como referência.
Declare a integração com declareIntegration({ slug, name, description, tools, credentialFields }). Os credentialFields aparecem na UI da admin quando o usuário configura a credencial da org.
Declare as credenciais por tool com declareToolCredentials(toolName, requirements). Marque required: true apenas para chaves sem as quais a tool não pode rodar.
Registre a tool no MCP server com server.tool(name, description, zodSchema, handler). Use Zod para o schema — JSON Schema bruto quebra o SDK.
Resolva credenciais e contexto dentro do handler via resolveAndApplyMappings(toolName, args, extra). Sempre valide com validateCredentials() antes de fazer requests externos.
Importe a tool em index.ts dentro de ensureIntegrationsLoaded() e registerAllTools(). Use await import() — imports estáticos podem causar ciclos.
Esqueleto de uma tool nova
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import {
declareToolCredentials,
validateCredentials,
resolveAndApplyMappings,
} from "./index.js";
import { declareIntegration } from "../lib/integrations.js";
declareIntegration({
slug: "minha_api",
name: "Minha API",
description: "Integração com sistema externo X.",
tools: ["minha_api_listar"],
credentialFields: [
{
key: "MINHA_API_TOKEN",
label: "API Token",
description: "Token de acesso",
required: true,
type: "password",
},
],
});
declareToolCredentials("minha_api_listar", [
{ key: "MINHA_API_TOKEN", description: "API token", required: true },
]);
export function registerMinhaApiTools(server: McpServer): void {
server.tool(
"minha_api_listar",
"Lista recursos no sistema X.",
{
limit: z.number().int().positive().max(100).default(20),
},
async (rawArgs, extra) => {
const { args, credentials } = await resolveAndApplyMappings(
"minha_api_listar",
rawArgs as Record<string, any>,
extra,
);
const missing = validateCredentials("minha_api_listar", credentials);
if (missing.length > 0) {
return {
content: [
{ type: "text" as const, text: `Missing: ${missing.join(", ")}` },
],
};
}
const res = await fetch("https://api.exemplo.com/v1/recursos", {
headers: { Authorization: `Bearer ${credentials.MINHA_API_TOKEN}` },
});
const data = await res.json();
return {
content: [{ type: "text" as const, text: JSON.stringify(data, null, 2) }],
};
},
);
}Após criar a tool, configure o CredentialSet da org de testes (via admin web em /credentials) antes de invocá-la pelo Tools Playground. Sem credencial, validateCredentials() retorna Missing: <keys> em vez de chamar a API externa.
Boas práticas
- Idempotência: quando a tool faz POST/mutação, exponha um campo
externalId/idempotencyKeypara o agente passar, ou derive um hash determinístico dos argumentos. - Erros graciosos: retorne
content: [{ type: "text", text: "..." }]com mensagem clara em vez de lançar — o agente consegue se recuperar e tentar outra abordagem. - Trim de credenciais: valores em
CredentialSet.encryptedValuespodem vir com whitespace ou aspas residuais.resolveCredentials()faz trim defensivo, mas valide na criação também. - Sem segredos em logs: nunca logue
credentials.*noconsole. Os logs vão para Loki e podem ser indexados.
Referências
Conversas
Threads cross-channel no Hub: como conversas são formadas a partir de adapters de canal, identidade do contato, inbox operacional e auditoria.
Equipe
Modelo de equipe do Hub: organizações como tenant, papéis OWNER/ADMIN/MEMBER/CLIENT, fluxo de convites, bypass interno via MCP_INTERNAL_SECRET e troca de organização.