/**
* 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
};
}
}
}
};
}