Agentes de IA (MCP)
Como integrar a Perpetuus API com agentes de inteligência artificial através do Model Context Protocol (MCP).
O Perpetuus CRM disponibiliza um servidor MCP (Model Context Protocol) autônomo. Ele permite que agentes (Cursor, Claude Desktop e SDKs) leiam e editem o CRM com as mesmas permissões do seu usuário.
Setup rápido no Cursor
Gere um token de API e anote o slug da organização.
No repositório, entre em perpetuus-crm-mcp, rode npm install.
Copie o JSON abaixo para .cursor/mcp.json (ajuste cwd, tenant e token).
Reinicie o Cursor e peça: “liste meus boards no Perpetuus”.
Configuração MCP para Cursor
.cursor/mcp.json
{
"mcpServers": {
"perpetuus-crm": {
"command": "npx",
"args": ["tsx", "src/stdio.ts"],
"cwd": "./perpetuus-crm-mcp",
"env": {
"STRAPI_URL": "https://api.perpetuus.com.br",
"MCP_CRM_TENANT_ID": "sua-organizacao",
"MCP_CRM_USER_TOKEN": "seu_token_de_api"
}
}
}
}Por que MCP?
- Interface unificada: o agente lista boards, busca contatos, move cards e cria tarefas sem decorar paths REST.
- Segurança: o MCP só fala com a API REST — tenant, RBAC e plano continuam no backend.
- Ciclo de vida separado: deploy e auditoria independentes do runtime de mensagens.
Rodando localmente
STDIO (Cursor / VS Code)
STRAPI_URL=https://api.perpetuus.com.br \
MCP_CRM_TENANT_ID=sua-organizacao \
MCP_CRM_USER_TOKEN=seu_token_de_api \
npx tsx src/stdio.tsHTTP (conexões remotas)
STRAPI_URL=https://api.perpetuus.com.br \
MCP_CRM_TENANT_ID=sua-organizacao \
MCP_CRM_USER_TOKEN=seu_token_de_api \
MCP_CRM_HTTP_PORT=3031 \
npx tsx src/http.tscurl -fsS http://127.0.0.1:3031/healthCatálogo de ferramentas
Contatos
crm.search_contacts,crm.get_contact,crm.create_contact,crm.update_contactcrm.add_contact_note
Boards e pipeline
crm.list_boards,crm.get_board_structurecrm.search_cards,crm.create_card,crm.update_card,crm.move_card_phase
Analytics
crm.get_board_report,crm.aggregate_card_field
Agenda e reuniões (BETA)
crm.list_agenda_eventsreúne calendário conectado, campanhas, tarefas e prazos de cards; confirameta.partialquando uma fonte estiver indisponível.crm.list_card_meetingslista a aba Meet, ecrm.find_meeting_slotsconsulta horários no calendário conectado.crm.schedule_card_meeting,crm.update_card_meetingecrm.cancel_card_meetingexigem confirmação humana: podem alterar o calendário conectado e notificar convidados.
boardId e cardId são documentId CRM. O id da reunião também é
documentId, mas identifica a reunião, não o card. Fluxo: consultar slots,
confirmar horário/timezone/convidados e agendar.
Segmentos
crm.list_segments,crm.get_segment,crm.create_segment,crm.update_segment,crm.delete_segment,crm.preview_segment,crm.resolve_segment,crm.count_segment,crm.get_segment_filter_options
Fluxo igual à UI de Disparos: descubra campos com get_segment_filter_options,
valide alcance com preview_segment, depois create_segment com
{ conditions: [...] } (e opcionalmente requiredSegments / excludedSegments).
Produtos e categorias
crm.list_products,crm.get_product,crm.create_product,crm.update_product,crm.delete_productcrm.list_product_categories,crm.get_product_category,crm.create_product_category,crm.update_product_category,crm.delete_product_category
Criação exige name, sku e price (SKU único por organização), como no formulário
do CRM. Upload de imagem do produto continua na UI; o MCP cobre o restante do catálogo.
Templates
- WhatsApp:
crm.list_whatsapp_templates,crm.create_whatsapp_template,crm.upload_whatsapp_template_media_handle,crm.sync_whatsapp_templates,crm.delete_whatsapp_template - E-mail:
crm.list_email_templates,crm.get_email_template,crm.create_email_template,crm.update_email_template,crm.delete_email_template,crm.preview_email_template,crm.send_test_email
Templates de board (crm.list_templates / crm.get_template) são somente
leitura — servem para criar funis, não para cadastrar novos templates de board.
Tasks
crm.list_tasks,crm.create_task,crm.update_task,crm.update_task_status
crm.create_task e crm.update_task aceitam prioridade (low, medium,
high, urgent), recorrência (none, daily, weekly, monthly) e
recurrenceInterval (1–365). taskStatus é configurado pelo board — não há
enum fixo; a interface usa pending, in-progress, completed e cancelled
como padrão.
Ao concluir uma task recorrente que tenha dueDate, o backend cria a próxima
ocorrência automaticamente. Tasks com vencimento recebem lembrete automático
via cron; o MCP não expõe campo de lembrete.
Chat, conversas e templates
O MCP opera o inbox via API Perpetuus, nunca diretamente no Chatwoot ou na Meta. Isso preserva isolamento de tenant, RBAC e auditoria do CRM.
IDs de Chatwoot (inboxId, conversationId e cursores de mensagem) são
numéricos. IDs de contato, card, board e chat-channel são documentId do
Strapi. Não são intercambiáveis.
Escopos e confirmação
- Leituras requerem
chat:read. - Escritas requerem
chat:writee devem ser confirmadas por uma pessoa no fluxo assistido, inclusive mudança de status, marcação de leitura e vínculo de card. - Mensagens, anexos e início de conversa podem alcançar uma pessoa real no WhatsApp; confirme destinatário, conteúdo e canal antes de executá-los.
- O backend ainda aplica a permissão granular do usuário, o escopo de equipe e o plano contratado. Um token com escopo não substitui RBAC.
Fluxos recomendados
Ler e responder uma conversa existente
crm.list_conversations(useenriched=truequando precisar do card vinculado).crm.get_conversationecrm.list_conversation_messages.- Confirme a resposta humana e execute
crm.send_conversation_message. - Opcionalmente use
crm.mark_conversation_seenoucrm.update_conversation_status.
Para navegar no histórico, passe o ID numérico da última mensagem em before
(mais antigas) ou after (mais novas). Não use documentId como cursor.
Primeiro contato (igual à UI)
- Localize/crie o contato CRM.
- Execute
crm.sync_contact_to_chat. - Descubra o
inboxIdcomcrm.list_chat_inboxese ochannelIdcomcrm.list_chat_channels. - Fora da janela de 24h, liste o HSM com
crm.list_whatsapp_templates(channelId). - Após confirmação humana, chame
crm.start_conversationcommessage: { content, template_params: { name, category, language, processed_params } }— o mesmo shape da UI de nova conversa. Texto livre só dentro da janela.
Antes de abrir, use crm.list_contact_conversations para evitar thread duplicado.
Criar / trocar card (igual à UI)
- Criar card:
crm.get_conversation→crm.list_inbox_board_links(inboxId)→crm.create_card_from_conversation(boardLinkId). - Trocar card:
crm.list_contact_conversation_cards(contactId, conversationId)→crm.switch_conversation_card(targetCardId).
WhatsApp e janela de 24 horas
Em conversa já existente, envie HSM com crm.send_conversation_message
(template_params + content_type/content_attributes). Para criar um
template com HEADER de mídia: crm.upload_whatsapp_template_media_handle →
crm.create_whatsapp_template → crm.sync_whatsapp_templates.
Catálogo de conversas
| Grupo | Tools |
|---|---|
| Inbox | crm.list_chat_inboxes, crm.get_chat_inbox, crm.list_inbox_board_links |
| Conversas | crm.list_conversations, crm.get_conversation, crm.get_conversations_meta, crm.list_contact_conversations, crm.get_conversation_unread_counts |
| Mensagens | crm.list_conversation_messages, crm.send_conversation_message, crm.send_conversation_attachment, crm.start_conversation |
| Estado compartilhado | crm.update_conversation_status, crm.mark_conversation_seen, crm.mark_conversation_unread |
| Relação com CRM | crm.get_conversation_card, crm.list_contact_conversation_cards, crm.create_card_from_conversation, crm.link_conversation_to_card, crm.switch_conversation_card, crm.list_chat_cards |
| Contatos Chatwoot | crm.search_chat_contacts, crm.sync_contact_to_chat |
crm.send_conversation_attachment usa o endpoint multipart do backend, mas a
tool recebe cada arquivo como base64, filename e mimeType. O backend valida
tipo suportado e limita cada arquivo a 50 MB.
Canais e templates WhatsApp
Use crm.list_chat_channels para descobrir o channelId (documentId) e
crm.get_chat_channel_health antes de operar um canal com problema.
crm.list_board_chat_channels retorna os vínculos canal-board; o boardLinkId
desse resultado é necessário em crm.create_card_from_conversation.
| Operação | Tool |
|---|---|
| Listar templates Meta do canal | crm.list_whatsapp_templates |
| Upload handle de mídia (HEADER) | crm.upload_whatsapp_template_media_handle |
| Criar template Meta | crm.create_whatsapp_template |
| Apagar template Meta | crm.delete_whatsapp_template |
| Sincronizar catálogo com Chatwoot | crm.sync_whatsapp_templates |
| Alias de campanha (aprovados p/ disparo) | crm.list_channel_templates |
crm.list_whatsapp_templates usa a rota canônica
GET /chat-channels/:channelId/templates; a antiga rota global sem canal não é
utilizada. Criar templates submete um ativo externo para a Meta; apagar pode
quebrar campanhas e sincronizar altera o catálogo do Chatwoot. Todas exigem
confirmação humana.
Templates de e-mail
crm.list_email_templates e crm.get_email_template usam documentId.
crm.preview_email_template renderiza conteúdo com um contato seguro de
exemplo e não envia e-mail. As escritas disponíveis são
crm.create_email_template, crm.update_email_template e
crm.delete_email_template; a última é destrutiva.
crm.send_test_email envia uma mensagem real para um único destinatário e
ignora a lista de supressão. Sempre pré-visualize e peça confirmação antes do
teste. Essas tools exigem que o tenant tenha a feature de campanhas e a
permissão apropriada.
Operações intencionalmente não expostas
Por segurança, o MCP não expõe configuração/disable global do Chatwoot, embedded signup, exclusão de contexto de conversa, escrita da configuração de e-mail com secrets, nem webhooks.
A especificação completa das tools está no README do pacote perpetuus-crm-mcp.
Para o contrato REST, use a API Reference ou baixe
/export/docs.json.