Skip to main content
Glama
ticket.tools.ts9.81 kB
/** * Ticket Management Tools for MCP Server */ import { z } from 'zod'; import { FitSlotAPIService } from '../services/fitslot-api.service.js'; import { TicketStatus, TicketPriority } from '../types/index.js'; import { logger } from '../utils/logger.js'; import { validateNotEmpty, validateEnum } from '../utils/validation.js'; export function createTicketTools(apiService: FitSlotAPIService) { return { create_ticket: { description: 'Create a new support ticket in the FitSlot system', parameters: z.object({ title: z.string().describe('Title of the ticket'), description: z.string().describe('Detailed description of the issue or request'), priority: z.enum(['low', 'medium', 'high', 'urgent']).describe('Priority level of the ticket'), userId: z.string().describe('ID of the user creating the ticket') }), execute: async (args: { title: string; description: string; priority: string; userId: string; }) => { try { logger.info('Creating new ticket', args); // Validate inputs validateNotEmpty(args.title, 'Title'); validateNotEmpty(args.description, 'Description'); validateNotEmpty(args.userId, 'User ID'); validateEnum(args.priority, TicketPriority, 'Priority'); const ticket = await apiService.createTicket({ title: args.title, description: args.description, priority: args.priority as TicketPriority, userId: args.userId }); return { content: [ { type: 'text', text: JSON.stringify( { success: true, message: 'Ticket created successfully', ticket: { id: ticket.id, title: ticket.title, status: ticket.status, priority: ticket.priority, createdAt: ticket.createdAt } }, null, 2 ) } ] }; } catch (error) { logger.error('Failed to create ticket', error); return { content: [ { type: 'text', text: JSON.stringify( { success: false, error: error instanceof Error ? error.message : 'Unknown error' }, null, 2 ) } ], isError: true }; } } }, list_tickets: { description: 'List all tickets for a user, optionally filtered by status', parameters: z.object({ userId: z.string().describe('ID of the user'), status: z.enum(['open', 'in_progress', 'resolved', 'closed']).optional().describe('Filter by ticket status') }), execute: async (args: { userId: string; status?: string; }) => { try { logger.info('Listing tickets', args); validateNotEmpty(args.userId, 'User ID'); if (args.status) { validateEnum(args.status, TicketStatus, 'Status'); } const tickets = await apiService.getTickets( args.userId, args.status as TicketStatus | undefined ); return { content: [ { type: 'text', text: JSON.stringify( { success: true, count: tickets.length, tickets: tickets.map(t => ({ id: t.id, title: t.title, status: t.status, priority: t.priority, createdAt: t.createdAt, updatedAt: t.updatedAt })) }, null, 2 ) } ] }; } catch (error) { logger.error('Failed to list tickets', error); return { content: [ { type: 'text', text: JSON.stringify( { success: false, error: error instanceof Error ? error.message : 'Unknown error' }, null, 2 ) } ], isError: true }; } } }, get_ticket: { description: 'Get detailed information about a specific ticket', parameters: z.object({ ticketId: z.string().describe('ID of the ticket to retrieve') }), execute: async (args: { ticketId: string }) => { try { logger.info('Getting ticket details', args); validateNotEmpty(args.ticketId, 'Ticket ID'); const ticket = await apiService.getTicket(args.ticketId); return { content: [ { type: 'text', text: JSON.stringify( { success: true, ticket }, null, 2 ) } ] }; } catch (error) { logger.error('Failed to get ticket', error); return { content: [ { type: 'text', text: JSON.stringify( { success: false, error: error instanceof Error ? error.message : 'Unknown error' }, null, 2 ) } ], isError: true }; } } }, update_ticket: { description: 'Update an existing ticket (status, description, or priority)', parameters: z.object({ ticketId: z.string().describe('ID of the ticket to update'), status: z.enum(['open', 'in_progress', 'resolved', 'closed']).optional().describe('New status'), description: z.string().optional().describe('Updated description'), priority: z.enum(['low', 'medium', 'high', 'urgent']).optional().describe('Updated priority') }), execute: async (args: { ticketId: string; status?: string; description?: string; priority?: string; }) => { try { logger.info('Updating ticket', args); validateNotEmpty(args.ticketId, 'Ticket ID'); if (args.status) { validateEnum(args.status, TicketStatus, 'Status'); } if (args.priority) { validateEnum(args.priority, TicketPriority, 'Priority'); } const ticket = await apiService.updateTicket({ id: args.ticketId, status: args.status as TicketStatus | undefined, description: args.description, priority: args.priority as TicketPriority | undefined }); return { content: [ { type: 'text', text: JSON.stringify( { success: true, message: 'Ticket updated successfully', ticket }, null, 2 ) } ] }; } catch (error) { logger.error('Failed to update ticket', error); return { content: [ { type: 'text', text: JSON.stringify( { success: false, error: error instanceof Error ? error.message : 'Unknown error' }, null, 2 ) } ], isError: true }; } } }, close_ticket: { description: 'Close a ticket by setting its status to closed', parameters: z.object({ ticketId: z.string().describe('ID of the ticket to close') }), execute: async (args: { ticketId: string }) => { try { logger.info('Closing ticket', args); validateNotEmpty(args.ticketId, 'Ticket ID'); const ticket = await apiService.updateTicket({ id: args.ticketId, status: TicketStatus.CLOSED }); return { content: [ { type: 'text', text: JSON.stringify( { success: true, message: 'Ticket closed successfully', ticket: { id: ticket.id, status: ticket.status, updatedAt: ticket.updatedAt } }, null, 2 ) } ] }; } catch (error) { logger.error('Failed to close ticket', error); return { content: [ { type: 'text', text: JSON.stringify( { success: false, error: error instanceof Error ? error.message : 'Unknown error' }, null, 2 ) } ], isError: true }; } } } }; }

Implementation Reference

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/osmarsant/fitslot-mcp'

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