UNPKG

@ria-sys/mcp

Version:

MCP Server para integração com WhatsApp

235 lines (207 loc) 7.12 kB
#!/usr/bin/env node import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { z } from 'zod'; import { MessageService } from './services/MessageService.js'; // Tipos inferidos dos schemas const SendMessageSchema = z.object({ phones: z.array(z.string()).describe("Lista de números de telefone com DDI e DDD (ex: ['5547999999999'])"), message: z.string().describe("Texto da mensagem a ser enviada"), sessionName: z.string().describe("Nome da sessão do WhatsApp onde a mensagem será enviada") }); const FormatPhoneSchema = z.object({ phones: z.array(z.string()).describe("Lista de números de telefone para formatar no padrão E.164 (ex: ['5547999999999'])"), removeNinthDigit: z.boolean().optional().default(false).describe("Se verdadeiro, remove o nono dígito do número de telefone brasileiro") }); type SendMessageInput = z.infer<typeof SendMessageSchema>; type FormatPhoneInput = z.infer<typeof FormatPhoneSchema>; // Serviço de mensagens const messageService = new MessageService(); // Configuração do servidor MCP const server = new McpServer( { name: "ria-sys", version: "3.0.3", description: "Sistema de envio e formatação de mensagens via WhatsApp" } ); // Adicionar um recurso de documentação server.resource( "Documentação de Formato de Telefone", "docs://formato-telefone", { mimeType: "text/plain" }, async (uri) => { return { contents: [{ uri: uri.href, text: ` Formatos de Telefone Suportados: 1. Formato Internacional E.164: - Formato: +[código do país][código de área][número do telefone] - Exemplo: +5547999999999 2. Formato Nacional: - Formato: [código de área][número do telefone] - Exemplo: 47999999999 3. Formato com separadores (será normalizado automaticamente): - Exemplos: (47) 99999-9999, 47-99999-9999 Observações: - O nono dígito para celulares brasileiros (9) pode ser removido se necessário - O sistema faz a normalização automática dos números antes do envio ` }] }; } ); // Função para formatar erros de maneira padronizada function formatError(error: unknown): string { if (error instanceof Error) { return `Erro: ${error.message}`; } return `Erro desconhecido: ${String(error)}`; } // Handler para envio de mensagens server.tool( "sendMessage", "Envia uma mensagem via WhatsApp para uma lista de destinatários", { phones: z.array(z.string()).describe("Lista de números de telefone com DDI e DDD (ex: ['5547999999999'])"), message: z.string().describe("Texto da mensagem a ser enviada"), sessionName: z.string().describe("Nome da sessão do WhatsApp onde a mensagem será enviada") }, async (args: SendMessageInput) => { try { console.error(`[DEBUG] Tentando enviar mensagem para ${args.phones.length} destinatários`); const result = await messageService.sendMessage(args.phones, args.message, args.sessionName); console.error(`[DEBUG] Resultado do envio: ${result.success ? 'Sucesso' : 'Falha'}`); return { content: [ { type: "text", text: result.message } ], isError: !result.success, metadata: { recipients: args.phones.length, sessionName: args.sessionName, timestamp: new Date().toISOString() } }; } catch (error) { console.error(`[ERROR] Falha ao enviar mensagem:`, error); return { content: [ { type: "text", text: formatError(error) } ], isError: true, metadata: { errorType: error instanceof Error ? error.name : 'UnknownError', timestamp: new Date().toISOString() } }; } } ); // Handler para formatação de números server.tool( "formatPhone", "Formata números de telefone para o padrão E.164 internacional", { phones: z.array(z.string()).describe("Lista de números de telefone para formatar no padrão E.164 (ex: ['5547999999999'])"), removeNinthDigit: z.boolean().optional().default(false).describe("Se verdadeiro, remove o nono dígito do número de telefone brasileiro") }, async (args: FormatPhoneInput) => { try { console.error(`[DEBUG] Formatando ${args.phones.length} números de telefone`); console.error(`[DEBUG] Remover nono dígito: ${args.removeNinthDigit}`); const formattedPhones = args.phones.map((phone: string) => { const result = messageService.formatPhone(phone, args.removeNinthDigit || false); return result.success ? result.phone : `Erro: ${result.message}`; }); console.error(`[DEBUG] Formatação concluída com sucesso`); return { content: [ { type: "text", text: JSON.stringify(formattedPhones, null, 2) } ], metadata: { totalProcessed: args.phones.length, removeNinthDigit: args.removeNinthDigit, timestamp: new Date().toISOString() } }; } catch (error) { console.error(`[ERROR] Falha ao formatar números:`, error); return { content: [ { type: "text", text: formatError(error) } ], isError: true, metadata: { errorType: error instanceof Error ? error.name : 'UnknownError', timestamp: new Date().toISOString() } }; } } ); // Adicionar um prompt de modelo para envio de mensagens server.prompt( "enviar-mensagem", "Modelo para criar uma mensagem WhatsApp para envio", { destinatarios: z.string().describe("Lista de números separados por vírgula"), mensagem: z.string().describe("Texto da mensagem a ser enviada"), sessao: z.string().describe("Nome da sessão do WhatsApp a ser usada") }, ({ destinatarios, mensagem, sessao }) => { const phoneList = destinatarios.split(',').map(phone => phone.trim()); return { description: "Modelo para envio de mensagem via WhatsApp", messages: [ { role: "assistant", content: { type: "text", text: `Preparando para enviar uma mensagem pelo WhatsApp. Destinatários: ${phoneList.join(', ')} Sessão: ${sessao} Total de destinatários: ${phoneList.length} Você pode usar a ferramenta 'mcp_ria_sys_sendMessage' para enviar esta mensagem diretamente. ` } }, { role: "user", content: { type: "text", text: `Mensagem a ser enviada: "${mensagem}"` } } ] }; } ); // Inicia o servidor async function runServer() { try { const transport = new StdioServerTransport(); await server.connect(transport); console.error("RIA System MCP Server rodando via stdio"); } catch (error) { console.error("Erro fatal ao iniciar servidor:", error); process.exit(1); } } // Executa o servidor runServer();