UNPKG

coreto-mcp-glpi

Version:

MCP Server para integração CORETO AI com GLPI via tools de tickets

153 lines (135 loc) 4.49 kB
import { mcpLogger } from '../logger.js' import { TICKET_STATUS, TICKET_PRIORITY } from '../constants.js' /** * Get user tickets from GLPI * @param {Object} args - Tool arguments * @param {Object} tenantContext - Tenant context with GLPI connector * @returns {Object} Tool execution result */ async function getUserTickets(args, tenantContext) { const logger = mcpLogger.child({ tool: 'get_user_tickets' }) try { const { status = 'open', limit = 10 } = args const { glpiConnector, tenant_id } = tenantContext // Validate parameters const validStatuses = ['open', 'closed', 'all'] if (!validStatuses.includes(status)) { throw new Error(`Status deve ser: ${validStatuses.join(', ')}`) } const limitNumber = parseInt(limit) if (isNaN(limitNumber) || limitNumber < 1 || limitNumber > 50) { throw new Error('Limite deve ser um número entre 1 e 50') } logger.info('Getting user tickets', { tenantId: tenant_id, status, limit: limitNumber }) // Build search criteria based on status let criteria = {} if (status === 'open') { // Open tickets: status 1-4 (Novo, Em atendimento, Pendente) criteria.status = '1,2,3,4' } else if (status === 'closed') { // Closed tickets: status 5-6 (Solucionado, Fechado) criteria.status = '5,6' } // 'all' = no status filter // Search tickets const tickets = await glpiConnector.searchTickets(criteria) // Process and format tickets const processedTickets = tickets .slice(0, limitNumber) .map(ticket => { const formatDate = (dateStr) => { if (!dateStr || dateStr === '0000-00-00 00:00:00') return null try { return new Date(dateStr).toLocaleString('pt-BR') } catch { return dateStr } } return { id: ticket.id, title: ticket.name || 'Sem título', status: TICKET_STATUS[ticket.status] || `Status ${ticket.status}`, status_code: ticket.status, priority: TICKET_PRIORITY[ticket.priority] || `Prioridade ${ticket.priority}`, priority_code: ticket.priority, created_date: formatDate(ticket.date), last_update: formatDate(ticket.date_mod), type: ticket.type === 1 ? 'Incidente' : ticket.type === 2 ? 'Solicitação' : 'Outro', category_id: ticket.itilcategories_id || 0 } }) // Build summary const statusCounts = {} tickets.forEach(ticket => { const statusName = TICKET_STATUS[ticket.status] || `Status ${ticket.status}` statusCounts[statusName] = (statusCounts[statusName] || 0) + 1 }) logger.info('User tickets retrieved successfully', { tenantId: tenant_id, totalFound: tickets.length, returned: processedTickets.length, status }) return { success: true, message: `Encontrados ${tickets.length} chamados (exibindo ${processedTickets.length})`, data: { tickets: processedTickets, summary: { total_found: tickets.length, displayed: processedTickets.length, filter_status: status, status_counts: statusCounts } } } } catch (error) { logger.error('Error getting user tickets', { tenantId: tenantContext.tenant_id, error: error.message, args }) // Handle specific error cases if (error.message.includes('GLPI')) { return { success: false, error: `Erro de conexão com GLPI: ${error.message}`, code: 'GLPI_CONNECTION_ERROR' } } return { success: false, error: error.message, code: 'TICKET_SEARCH_ERROR' } } } // Tool configuration const getUserTicketsTool = { name: 'get_user_tickets', description: 'Listar chamados do usuário com filtros de status e limite', inputSchema: { type: 'object', properties: { status: { type: 'string', enum: ['open', 'closed', 'all'], description: 'Filtrar por status: open=em aberto, closed=fechados, all=todos', default: 'open' }, limit: { type: 'number', description: 'Número máximo de chamados a retornar (1-50)', default: 10, minimum: 1, maximum: 50 } } }, handler: getUserTickets } export default getUserTicketsTool