Skip to main content
Glama
calendar-tools.ts70.6 kB
/** * MCP Calendar Tools for GoHighLevel Integration * Exposes calendar and appointment management capabilities to Claude Desktop */ import { Tool } from '@modelcontextprotocol/sdk/types.js'; import { GHLApiClient } from '../clients/ghl-api-client.js'; import { MCPGetCalendarsParams, MCPCreateCalendarParams, MCPUpdateCalendarParams, MCPGetCalendarEventsParams, MCPGetFreeSlotsParams, MCPCreateAppointmentParams, MCPUpdateAppointmentParams, MCPCreateBlockSlotParams, MCPUpdateBlockSlotParams, GHLCalendar, GHLGetCalendarsResponse, GHLGetCalendarGroupsResponse, GHLGetCalendarEventsResponse, GHLGetFreeSlotsResponse, GHLCalendarEvent, GHLBlockSlotResponse, MCPCreateCalendarGroupParams, MCPValidateGroupSlugParams, MCPUpdateCalendarGroupParams, MCPDeleteCalendarGroupParams, MCPDisableCalendarGroupParams, MCPGetAppointmentNotesParams, MCPCreateAppointmentNoteParams, MCPUpdateAppointmentNoteParams, MCPDeleteAppointmentNoteParams, MCPGetCalendarResourcesParams, MCPCreateCalendarResourceParams, MCPGetCalendarResourceParams, MCPUpdateCalendarResourceParams, MCPDeleteCalendarResourceParams, MCPGetCalendarNotificationsParams, MCPCreateCalendarNotificationParams, MCPGetCalendarNotificationParams, MCPUpdateCalendarNotificationParams, MCPDeleteCalendarNotificationParams, MCPGetBlockedSlotsParams } from '../types/ghl-types.js'; /** * Calendar Tools Class * Implements MCP tools for calendar and appointment management */ export class CalendarTools { constructor(private ghlClient: GHLApiClient) {} /** * Get all calendar tool definitions for MCP server */ getToolDefinitions(): Tool[] { return [ { name: 'get_calendar_groups', description: 'Get all calendar groups in the GoHighLevel location', inputSchema: { type: 'object', properties: {} } }, { name: 'get_calendars', description: 'Get all calendars in the GoHighLevel location with optional filtering', inputSchema: { type: 'object', properties: { groupId: { type: 'string', description: 'Filter calendars by group ID' }, showDrafted: { type: 'boolean', description: 'Include draft calendars (default: true)', default: true } } } }, { name: 'create_calendar', description: 'Create a new calendar in GoHighLevel', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Name of the calendar' }, description: { type: 'string', description: 'Description of the calendar' }, calendarType: { type: 'string', description: 'Type of calendar to create', enum: ['round_robin', 'event', 'class_booking', 'collective', 'service_booking', 'personal'], default: 'event' }, groupId: { type: 'string', description: 'Calendar group ID to organize the calendar' }, slotDuration: { type: 'number', description: 'Duration of appointment slots in minutes (default: 30)', default: 30 }, slotDurationUnit: { type: 'string', description: 'Unit for slot duration', enum: ['mins', 'hours'], default: 'mins' }, autoConfirm: { type: 'boolean', description: 'Automatically confirm appointments (default: true)', default: true }, allowReschedule: { type: 'boolean', description: 'Allow clients to reschedule appointments (default: true)', default: true }, allowCancellation: { type: 'boolean', description: 'Allow clients to cancel appointments (default: true)', default: true }, isActive: { type: 'boolean', description: 'Make calendar active immediately (default: true)', default: true } }, required: ['name', 'calendarType'] } }, { name: 'get_calendar', description: 'Get detailed information about a specific calendar by ID', inputSchema: { type: 'object', properties: { calendarId: { type: 'string', description: 'The unique ID of the calendar to retrieve' } }, required: ['calendarId'] } }, { name: 'update_calendar', description: 'Update an existing calendar in GoHighLevel', inputSchema: { type: 'object', properties: { calendarId: { type: 'string', description: 'The unique ID of the calendar to update' }, name: { type: 'string', description: 'Updated name of the calendar' }, description: { type: 'string', description: 'Updated description of the calendar' }, slotDuration: { type: 'number', description: 'Updated duration of appointment slots in minutes' }, autoConfirm: { type: 'boolean', description: 'Updated auto-confirm setting' }, allowReschedule: { type: 'boolean', description: 'Updated reschedule permission setting' }, allowCancellation: { type: 'boolean', description: 'Updated cancellation permission setting' }, isActive: { type: 'boolean', description: 'Updated active status' } }, required: ['calendarId'] } }, { name: 'delete_calendar', description: 'Delete a calendar from GoHighLevel', inputSchema: { type: 'object', properties: { calendarId: { type: 'string', description: 'The unique ID of the calendar to delete' } }, required: ['calendarId'] } }, { name: 'get_calendar_events', description: 'Get appointments/events from calendars within a date range', inputSchema: { type: 'object', properties: { startTime: { type: 'string', description: 'Start time in milliseconds or ISO date (e.g., "2024-01-01" or "1704067200000")' }, endTime: { type: 'string', description: 'End time in milliseconds or ISO date (e.g., "2024-01-31" or "1706745599999")' }, calendarId: { type: 'string', description: 'Filter events by specific calendar ID' }, userId: { type: 'string', description: 'Filter events by assigned user ID' }, groupId: { type: 'string', description: 'Filter events by calendar group ID' } }, required: ['startTime', 'endTime'] } }, { name: 'get_free_slots', description: 'Get available time slots for booking appointments on a specific calendar', inputSchema: { type: 'object', properties: { calendarId: { type: 'string', description: 'The calendar ID to check availability for' }, startDate: { type: 'string', description: 'Start date for availability check (YYYY-MM-DD format or milliseconds)' }, endDate: { type: 'string', description: 'End date for availability check (YYYY-MM-DD format or milliseconds)' }, timezone: { type: 'string', description: 'Timezone for the results (e.g., "America/New_York")' }, userId: { type: 'string', description: 'Specific user ID to check availability for' } }, required: ['calendarId', 'startDate', 'endDate'] } }, { name: 'create_appointment', description: 'Create a new appointment/booking in GoHighLevel', inputSchema: { type: 'object', properties: { calendarId: { type: 'string', description: 'The calendar ID to book the appointment in' }, contactId: { type: 'string', description: 'The contact ID for whom to book the appointment' }, startTime: { type: 'string', description: 'Start time in ISO format (e.g., "2024-01-15T10:00:00-05:00")' }, endTime: { type: 'string', description: 'End time in ISO format (optional, will be calculated from slot duration if not provided)' }, title: { type: 'string', description: 'Title/subject of the appointment' }, appointmentStatus: { type: 'string', description: 'Initial status of the appointment', enum: ['new', 'confirmed'], default: 'confirmed' }, assignedUserId: { type: 'string', description: 'User ID to assign this appointment to' }, address: { type: 'string', description: 'Meeting location or address' }, meetingLocationType: { type: 'string', description: 'Type of meeting location', enum: ['custom', 'zoom', 'gmeet', 'phone', 'address'], default: 'custom' }, ignoreDateRange: { type: 'boolean', description: 'Ignore minimum scheduling notice and date range restrictions', default: false }, toNotify: { type: 'boolean', description: 'Send notifications for this appointment', default: true } }, required: ['calendarId', 'contactId', 'startTime'] } }, { name: 'get_appointment', description: 'Get detailed information about a specific appointment by ID', inputSchema: { type: 'object', properties: { appointmentId: { type: 'string', description: 'The unique ID of the appointment to retrieve' } }, required: ['appointmentId'] } }, { name: 'update_appointment', description: 'Update an existing appointment in GoHighLevel', inputSchema: { type: 'object', properties: { appointmentId: { type: 'string', description: 'The unique ID of the appointment to update' }, title: { type: 'string', description: 'Updated title/subject of the appointment' }, appointmentStatus: { type: 'string', description: 'Updated status of the appointment', enum: ['new', 'confirmed', 'cancelled', 'showed', 'noshow'] }, assignedUserId: { type: 'string', description: 'Updated assigned user ID' }, address: { type: 'string', description: 'Updated meeting location or address' }, startTime: { type: 'string', description: 'Updated start time in ISO format' }, endTime: { type: 'string', description: 'Updated end time in ISO format' }, toNotify: { type: 'boolean', description: 'Send notifications for this update', default: true } }, required: ['appointmentId'] } }, { name: 'delete_appointment', description: 'Cancel/delete an appointment from GoHighLevel', inputSchema: { type: 'object', properties: { appointmentId: { type: 'string', description: 'The unique ID of the appointment to delete' } }, required: ['appointmentId'] } }, { name: 'create_block_slot', description: 'Create a blocked time slot to prevent bookings during specific times', inputSchema: { type: 'object', properties: { startTime: { type: 'string', description: 'Start time of the block in ISO format (e.g., "2024-01-15T10:00:00-05:00")' }, endTime: { type: 'string', description: 'End time of the block in ISO format (e.g., "2024-01-15T12:00:00-05:00")' }, title: { type: 'string', description: 'Title/reason for the block (e.g., "Lunch Break", "Meeting")' }, calendarId: { type: 'string', description: 'Specific calendar to block (optional, blocks all if not specified)' }, assignedUserId: { type: 'string', description: 'User ID to apply the block for' } }, required: ['startTime', 'endTime'] } }, { name: 'update_block_slot', description: 'Update an existing blocked time slot', inputSchema: { type: 'object', properties: { blockSlotId: { type: 'string', description: 'The unique ID of the block slot to update' }, startTime: { type: 'string', description: 'Updated start time in ISO format' }, endTime: { type: 'string', description: 'Updated end time in ISO format' }, title: { type: 'string', description: 'Updated title/reason for the block' }, calendarId: { type: 'string', description: 'Updated calendar ID for the block' }, assignedUserId: { type: 'string', description: 'Updated assigned user ID' } }, required: ['blockSlotId'] } }, { name: 'create_calendar_group', description: 'Create a new calendar group', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Group name' }, description: { type: 'string', description: 'Group description' }, slug: { type: 'string', description: 'URL slug for the group' }, isActive: { type: 'boolean', description: 'Whether group is active', default: true } }, required: ['name', 'description', 'slug'] } }, { name: 'validate_group_slug', description: 'Validate if a calendar group slug is available', inputSchema: { type: 'object', properties: { slug: { type: 'string', description: 'Slug to validate' }, locationId: { type: 'string', description: 'Location ID' } }, required: ['slug'] } }, { name: 'update_calendar_group', description: 'Update calendar group details', inputSchema: { type: 'object', properties: { groupId: { type: 'string', description: 'Calendar group ID' }, name: { type: 'string', description: 'Group name' }, description: { type: 'string', description: 'Group description' }, slug: { type: 'string', description: 'URL slug for the group' } }, required: ['groupId', 'name', 'description', 'slug'] } }, { name: 'delete_calendar_group', description: 'Delete a calendar group', inputSchema: { type: 'object', properties: { groupId: { type: 'string', description: 'Calendar group ID' } }, required: ['groupId'] } }, { name: 'disable_calendar_group', description: 'Enable or disable a calendar group', inputSchema: { type: 'object', properties: { groupId: { type: 'string', description: 'Calendar group ID' }, isActive: { type: 'boolean', description: 'Whether to enable (true) or disable (false) the group' } }, required: ['groupId', 'isActive'] } }, { name: 'get_appointment_notes', description: 'Get notes for an appointment', inputSchema: { type: 'object', properties: { appointmentId: { type: 'string', description: 'Appointment ID' }, limit: { type: 'number', description: 'Maximum number of notes to return', default: 10 }, offset: { type: 'number', description: 'Number of notes to skip', default: 0 } }, required: ['appointmentId'] } }, { name: 'create_appointment_note', description: 'Create a note for an appointment', inputSchema: { type: 'object', properties: { appointmentId: { type: 'string', description: 'Appointment ID' }, body: { type: 'string', description: 'Note content' }, userId: { type: 'string', description: 'User ID creating the note' } }, required: ['appointmentId', 'body'] } }, { name: 'update_appointment_note', description: 'Update an appointment note', inputSchema: { type: 'object', properties: { appointmentId: { type: 'string', description: 'Appointment ID' }, noteId: { type: 'string', description: 'Note ID' }, body: { type: 'string', description: 'Updated note content' }, userId: { type: 'string', description: 'User ID updating the note' } }, required: ['appointmentId', 'noteId', 'body'] } }, { name: 'delete_appointment_note', description: 'Delete an appointment note', inputSchema: { type: 'object', properties: { appointmentId: { type: 'string', description: 'Appointment ID' }, noteId: { type: 'string', description: 'Note ID' } }, required: ['appointmentId', 'noteId'] } }, { name: 'get_calendar_resources_equipments', description: 'Get calendar equipment resources', inputSchema: { type: 'object', properties: { limit: { type: 'number', description: 'Maximum number to return', default: 20 }, skip: { type: 'number', description: 'Number to skip', default: 0 } } } }, { name: 'create_calendar_resource_equipment', description: 'Create a calendar equipment resource', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Equipment name' }, description: { type: 'string', description: 'Equipment description' }, quantity: { type: 'number', description: 'Total quantity available' }, outOfService: { type: 'number', description: 'Number currently out of service' }, capacity: { type: 'number', description: 'Capacity per unit' }, calendarIds: { type: 'array', items: { type: 'string' }, description: 'Associated calendar IDs' } }, required: ['name', 'description', 'quantity', 'outOfService', 'capacity', 'calendarIds'] } }, { name: 'get_calendar_resource_equipment', description: 'Get specific equipment resource details', inputSchema: { type: 'object', properties: { resourceId: { type: 'string', description: 'Equipment resource ID' } }, required: ['resourceId'] } }, { name: 'update_calendar_resource_equipment', description: 'Update equipment resource details', inputSchema: { type: 'object', properties: { resourceId: { type: 'string', description: 'Equipment resource ID' }, name: { type: 'string', description: 'Equipment name' }, description: { type: 'string', description: 'Equipment description' }, quantity: { type: 'number', description: 'Total quantity available' }, outOfService: { type: 'number', description: 'Number currently out of service' }, capacity: { type: 'number', description: 'Capacity per unit' }, calendarIds: { type: 'array', items: { type: 'string' }, description: 'Associated calendar IDs' }, isActive: { type: 'boolean', description: 'Whether resource is active' } }, required: ['resourceId'] } }, { name: 'delete_calendar_resource_equipment', description: 'Delete an equipment resource', inputSchema: { type: 'object', properties: { resourceId: { type: 'string', description: 'Equipment resource ID' } }, required: ['resourceId'] } }, { name: 'get_calendar_resources_rooms', description: 'Get calendar room resources', inputSchema: { type: 'object', properties: { limit: { type: 'number', description: 'Maximum number to return', default: 20 }, skip: { type: 'number', description: 'Number to skip', default: 0 } } } }, { name: 'create_calendar_resource_room', description: 'Create a calendar room resource', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Room name' }, description: { type: 'string', description: 'Room description' }, quantity: { type: 'number', description: 'Total quantity available' }, outOfService: { type: 'number', description: 'Number currently out of service' }, capacity: { type: 'number', description: 'Room capacity' }, calendarIds: { type: 'array', items: { type: 'string' }, description: 'Associated calendar IDs' } }, required: ['name', 'description', 'quantity', 'outOfService', 'capacity', 'calendarIds'] } }, { name: 'get_calendar_resource_room', description: 'Get specific room resource details', inputSchema: { type: 'object', properties: { resourceId: { type: 'string', description: 'Room resource ID' } }, required: ['resourceId'] } }, { name: 'update_calendar_resource_room', description: 'Update room resource details', inputSchema: { type: 'object', properties: { resourceId: { type: 'string', description: 'Room resource ID' }, name: { type: 'string', description: 'Room name' }, description: { type: 'string', description: 'Room description' }, quantity: { type: 'number', description: 'Total quantity available' }, outOfService: { type: 'number', description: 'Number currently out of service' }, capacity: { type: 'number', description: 'Room capacity' }, calendarIds: { type: 'array', items: { type: 'string' }, description: 'Associated calendar IDs' }, isActive: { type: 'boolean', description: 'Whether resource is active' } }, required: ['resourceId'] } }, { name: 'delete_calendar_resource_room', description: 'Delete a room resource', inputSchema: { type: 'object', properties: { resourceId: { type: 'string', description: 'Room resource ID' } }, required: ['resourceId'] } }, { name: 'get_calendar_notifications', description: 'Get calendar notifications', inputSchema: { type: 'object', properties: { calendarId: { type: 'string', description: 'Calendar ID' }, isActive: { type: 'boolean', description: 'Filter by active status' }, deleted: { type: 'boolean', description: 'Include deleted notifications' }, limit: { type: 'number', description: 'Maximum number to return' }, skip: { type: 'number', description: 'Number to skip' } }, required: ['calendarId'] } }, { name: 'create_calendar_notifications', description: 'Create calendar notifications', inputSchema: { type: 'object', properties: { calendarId: { type: 'string', description: 'Calendar ID' }, notifications: { type: 'array', items: { type: 'object', properties: { receiverType: { type: 'string', enum: ['contact', 'guest', 'assignedUser', 'emails'], description: 'Who receives the notification' }, channel: { type: 'string', enum: ['email', 'inApp'], description: 'Notification channel' }, notificationType: { type: 'string', enum: ['booked', 'confirmation', 'cancellation', 'reminder', 'followup', 'reschedule'], description: 'Type of notification' }, isActive: { type: 'boolean', description: 'Whether notification is active' }, templateId: { type: 'string', description: 'Template ID' }, body: { type: 'string', description: 'Notification body' }, subject: { type: 'string', description: 'Notification subject' } }, required: ['receiverType', 'channel', 'notificationType'] }, description: 'Array of notification configurations' } }, required: ['calendarId', 'notifications'] } }, { name: 'get_calendar_notification', description: 'Get specific calendar notification', inputSchema: { type: 'object', properties: { calendarId: { type: 'string', description: 'Calendar ID' }, notificationId: { type: 'string', description: 'Notification ID' } }, required: ['calendarId', 'notificationId'] } }, { name: 'update_calendar_notification', description: 'Update calendar notification', inputSchema: { type: 'object', properties: { calendarId: { type: 'string', description: 'Calendar ID' }, notificationId: { type: 'string', description: 'Notification ID' }, receiverType: { type: 'string', enum: ['contact', 'guest', 'assignedUser', 'emails'], description: 'Who receives the notification' }, channel: { type: 'string', enum: ['email', 'inApp'], description: 'Notification channel' }, notificationType: { type: 'string', enum: ['booked', 'confirmation', 'cancellation', 'reminder', 'followup', 'reschedule'], description: 'Type of notification' }, isActive: { type: 'boolean', description: 'Whether notification is active' }, deleted: { type: 'boolean', description: 'Whether notification is deleted' }, templateId: { type: 'string', description: 'Template ID' }, body: { type: 'string', description: 'Notification body' }, subject: { type: 'string', description: 'Notification subject' } }, required: ['calendarId', 'notificationId'] } }, { name: 'delete_calendar_notification', description: 'Delete calendar notification', inputSchema: { type: 'object', properties: { calendarId: { type: 'string', description: 'Calendar ID' }, notificationId: { type: 'string', description: 'Notification ID' } }, required: ['calendarId', 'notificationId'] } }, { name: 'get_blocked_slots', description: 'Get blocked time slots for a location', inputSchema: { type: 'object', properties: { userId: { type: 'string', description: 'Filter by user ID' }, calendarId: { type: 'string', description: 'Filter by calendar ID' }, groupId: { type: 'string', description: 'Filter by group ID' }, startTime: { type: 'string', description: 'Start time for the query range' }, endTime: { type: 'string', description: 'End time for the query range' } }, required: ['startTime', 'endTime'] } } ]; } /** * Execute calendar tool based on tool name and arguments */ async executeTool(name: string, args: any): Promise<any> { switch (name) { case 'get_calendar_groups': return this.getCalendarGroups(); case 'get_calendars': return this.getCalendars(args as MCPGetCalendarsParams); case 'create_calendar': return this.createCalendar(args as MCPCreateCalendarParams); case 'get_calendar': return this.getCalendar(args.calendarId); case 'update_calendar': return this.updateCalendar(args as MCPUpdateCalendarParams); case 'delete_calendar': return this.deleteCalendar(args.calendarId); case 'get_calendar_events': return this.getCalendarEvents(args as MCPGetCalendarEventsParams); case 'get_free_slots': return this.getFreeSlots(args as MCPGetFreeSlotsParams); case 'create_appointment': return this.createAppointment(args as MCPCreateAppointmentParams); case 'get_appointment': return this.getAppointment(args.appointmentId); case 'update_appointment': return this.updateAppointment(args as MCPUpdateAppointmentParams); case 'delete_appointment': return this.deleteAppointment(args.appointmentId); case 'create_block_slot': return this.createBlockSlot(args as MCPCreateBlockSlotParams); case 'update_block_slot': return this.updateBlockSlot(args as MCPUpdateBlockSlotParams); case 'create_calendar_group': return this.createCalendarGroup(args as MCPCreateCalendarGroupParams); case 'validate_group_slug': return this.validateGroupSlug(args as MCPValidateGroupSlugParams); case 'update_calendar_group': return this.updateCalendarGroup(args as MCPUpdateCalendarGroupParams); case 'delete_calendar_group': return this.deleteCalendarGroup(args as MCPDeleteCalendarGroupParams); case 'disable_calendar_group': return this.disableCalendarGroup(args as MCPDisableCalendarGroupParams); case 'get_appointment_notes': return this.getAppointmentNotes(args as MCPGetAppointmentNotesParams); case 'create_appointment_note': return this.createAppointmentNote(args as MCPCreateAppointmentNoteParams); case 'update_appointment_note': return this.updateAppointmentNote(args as MCPUpdateAppointmentNoteParams); case 'delete_appointment_note': return this.deleteAppointmentNote(args as MCPDeleteAppointmentNoteParams); case 'get_calendar_resources_equipments': return this.getCalendarResourcesEquipments(args as MCPGetCalendarResourcesParams); case 'create_calendar_resource_equipment': return this.createCalendarResourceEquipment(args as MCPCreateCalendarResourceParams); case 'get_calendar_resource_equipment': return this.getCalendarResourceEquipment(args as MCPGetCalendarResourceParams); case 'update_calendar_resource_equipment': return this.updateCalendarResourceEquipment(args as MCPUpdateCalendarResourceParams); case 'delete_calendar_resource_equipment': return this.deleteCalendarResourceEquipment(args as MCPDeleteCalendarResourceParams); case 'get_calendar_resources_rooms': return this.getCalendarResourcesRooms(args as MCPGetCalendarResourcesParams); case 'create_calendar_resource_room': return this.createCalendarResourceRoom(args as MCPCreateCalendarResourceParams); case 'get_calendar_resource_room': return this.getCalendarResourceRoom(args as MCPGetCalendarResourceParams); case 'update_calendar_resource_room': return this.updateCalendarResourceRoom(args as MCPUpdateCalendarResourceParams); case 'delete_calendar_resource_room': return this.deleteCalendarResourceRoom(args as MCPDeleteCalendarResourceParams); case 'get_calendar_notifications': return this.getCalendarNotifications(args as MCPGetCalendarNotificationsParams); case 'create_calendar_notifications': return this.createCalendarNotifications(args as MCPCreateCalendarNotificationParams); case 'get_calendar_notification': return this.getCalendarNotification(args as MCPGetCalendarNotificationParams); case 'update_calendar_notification': return this.updateCalendarNotification(args as MCPUpdateCalendarNotificationParams); case 'delete_calendar_notification': return this.deleteCalendarNotification(args as MCPDeleteCalendarNotificationParams); case 'get_blocked_slots': return this.getBlockedSlots(args as MCPGetBlockedSlotsParams); default: throw new Error(`Unknown calendar tool: ${name}`); } } /** * GET CALENDAR GROUPS */ private async getCalendarGroups(): Promise<{ success: boolean; groups: any[]; message: string }> { try { const response = await this.ghlClient.getCalendarGroups(); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } const data = response.data as GHLGetCalendarGroupsResponse; const groups = Array.isArray(data.groups) ? data.groups : []; return { success: true, groups, message: `Retrieved ${groups.length} calendar groups` }; } catch (error) { process.stderr.write(`[GHL MCP] Get calendar groups error: ${JSON.stringify(error, null, 2)}\n`); throw new Error(`Failed to get calendar groups: ${error instanceof Error ? error.message : String(error)}`); } } /** * GET CALENDARS */ private async getCalendars(params: MCPGetCalendarsParams = {}): Promise<{ success: boolean; calendars: GHLCalendar[]; message: string }> { try { const response = await this.ghlClient.getCalendars(params); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } const data = response.data as GHLGetCalendarsResponse; const calendars = Array.isArray(data.calendars) ? data.calendars : []; return { success: true, calendars, message: `Retrieved ${calendars.length} calendars` }; } catch (error) { throw new Error(`Failed to get calendars: ${error instanceof Error ? error.message : String(error)}`); } } /** * CREATE CALENDAR */ private async createCalendar(params: MCPCreateCalendarParams): Promise<{ success: boolean; calendar: GHLCalendar; message: string }> { try { const calendarData = { locationId: this.ghlClient.getConfig().locationId, name: params.name, description: params.description, calendarType: params.calendarType, groupId: params.groupId, teamMembers: params.teamMembers, slotDuration: params.slotDuration || 30, slotDurationUnit: params.slotDurationUnit || 'mins', autoConfirm: params.autoConfirm !== undefined ? params.autoConfirm : true, allowReschedule: params.allowReschedule !== undefined ? params.allowReschedule : true, allowCancellation: params.allowCancellation !== undefined ? params.allowCancellation : true, isActive: params.isActive !== undefined ? params.isActive : true }; const response = await this.ghlClient.createCalendar(calendarData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, calendar: response.data.calendar, message: `Calendar created successfully with ID: ${response.data.calendar.id}` }; } catch (error) { throw new Error(`Failed to create calendar: ${error instanceof Error ? error.message : String(error)}`); } } /** * GET CALENDAR BY ID */ private async getCalendar(calendarId: string): Promise<{ success: boolean; calendar: GHLCalendar; message: string }> { try { const response = await this.ghlClient.getCalendar(calendarId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, calendar: response.data.calendar, message: 'Calendar retrieved successfully' }; } catch (error) { throw new Error(`Failed to get calendar: ${error instanceof Error ? error.message : String(error)}`); } } /** * UPDATE CALENDAR */ private async updateCalendar(params: MCPUpdateCalendarParams): Promise<{ success: boolean; calendar: GHLCalendar; message: string }> { try { const { calendarId, ...updateData } = params; const response = await this.ghlClient.updateCalendar(calendarId, updateData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, calendar: response.data.calendar, message: 'Calendar updated successfully' }; } catch (error) { throw new Error(`Failed to update calendar: ${error instanceof Error ? error.message : String(error)}`); } } /** * DELETE CALENDAR */ private async deleteCalendar(calendarId: string): Promise<{ success: boolean; message: string }> { try { const response = await this.ghlClient.deleteCalendar(calendarId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, message: 'Calendar deleted successfully' }; } catch (error) { throw new Error(`Failed to delete calendar: ${error instanceof Error ? error.message : String(error)}`); } } /** * GET CALENDAR EVENTS */ private async getCalendarEvents(params: MCPGetCalendarEventsParams): Promise<{ success: boolean; events: GHLCalendarEvent[]; message: string }> { try { // Convert date strings to milliseconds if needed const startTime = this.convertToMilliseconds(params.startTime); const endTime = this.convertToMilliseconds(params.endTime); const eventParams = { locationId: this.ghlClient.getConfig().locationId, startTime, endTime, userId: params.userId, calendarId: params.calendarId, groupId: params.groupId }; const response = await this.ghlClient.getCalendarEvents(eventParams); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } const data = response.data as GHLGetCalendarEventsResponse; const events = Array.isArray(data.events) ? data.events : []; return { success: true, events, message: `Retrieved ${events.length} calendar events` }; } catch (error) { throw new Error(`Failed to get calendar events: ${error instanceof Error ? error.message : String(error)}`); } } /** * GET FREE SLOTS */ private async getFreeSlots(params: MCPGetFreeSlotsParams): Promise<{ success: boolean; freeSlots: any; message: string }> { try { // Convert dates to milliseconds if needed const startDate = this.convertDateToMilliseconds(params.startDate); const endDate = this.convertDateToMilliseconds(params.endDate); const slotParams = { calendarId: params.calendarId, startDate, endDate, timezone: params.timezone, userId: params.userId }; const response = await this.ghlClient.getFreeSlots(slotParams); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, freeSlots: response.data, message: 'Free slots retrieved successfully' }; } catch (error) { throw new Error(`Failed to get free slots: ${error instanceof Error ? error.message : String(error)}`); } } /** * CREATE APPOINTMENT */ private async createAppointment(params: MCPCreateAppointmentParams): Promise<{ success: boolean; appointment: GHLCalendarEvent; message: string }> { try { const appointmentData = { calendarId: params.calendarId, locationId: this.ghlClient.getConfig().locationId, contactId: params.contactId, startTime: params.startTime, endTime: params.endTime, title: params.title, appointmentStatus: params.appointmentStatus || 'confirmed', assignedUserId: params.assignedUserId, address: params.address, meetingLocationType: params.meetingLocationType, ignoreDateRange: params.ignoreDateRange, toNotify: params.toNotify !== undefined ? params.toNotify : true }; const response = await this.ghlClient.createAppointment(appointmentData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, appointment: response.data, message: `Appointment created successfully with ID: ${response.data.id}` }; } catch (error) { throw new Error(`Failed to create appointment: ${error instanceof Error ? error.message : String(error)}`); } } /** * GET APPOINTMENT BY ID */ private async getAppointment(appointmentId: string): Promise<{ success: boolean; appointment: GHLCalendarEvent; message: string }> { try { const response = await this.ghlClient.getAppointment(appointmentId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, appointment: response.data.event, message: 'Appointment retrieved successfully' }; } catch (error) { throw new Error(`Failed to get appointment: ${error instanceof Error ? error.message : String(error)}`); } } /** * UPDATE APPOINTMENT */ private async updateAppointment(params: MCPUpdateAppointmentParams): Promise<{ success: boolean; appointment: GHLCalendarEvent; message: string }> { try { const { appointmentId, ...updateData } = params; const response = await this.ghlClient.updateAppointment(appointmentId, updateData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, appointment: response.data, message: 'Appointment updated successfully' }; } catch (error) { throw new Error(`Failed to update appointment: ${error instanceof Error ? error.message : String(error)}`); } } /** * DELETE APPOINTMENT */ private async deleteAppointment(appointmentId: string): Promise<{ success: boolean; message: string }> { try { const response = await this.ghlClient.deleteAppointment(appointmentId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, message: 'Appointment deleted successfully' }; } catch (error) { throw new Error(`Failed to delete appointment: ${error instanceof Error ? error.message : String(error)}`); } } /** * CREATE BLOCK SLOT */ private async createBlockSlot(params: MCPCreateBlockSlotParams): Promise<{ success: boolean; blockSlot: GHLBlockSlotResponse; message: string }> { try { const blockSlotData = { locationId: this.ghlClient.getConfig().locationId, startTime: params.startTime, endTime: params.endTime, title: params.title, calendarId: params.calendarId, assignedUserId: params.assignedUserId }; const response = await this.ghlClient.createBlockSlot(blockSlotData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, blockSlot: response.data, message: `Block slot created successfully with ID: ${response.data.id}` }; } catch (error) { throw new Error(`Failed to create block slot: ${error instanceof Error ? error.message : String(error)}`); } } /** * UPDATE BLOCK SLOT */ private async updateBlockSlot(params: MCPUpdateBlockSlotParams): Promise<{ success: boolean; blockSlot: GHLBlockSlotResponse; message: string }> { try { const { blockSlotId, ...updateData } = params; const response = await this.ghlClient.updateBlockSlot(blockSlotId, updateData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, blockSlot: response.data, message: 'Block slot updated successfully' }; } catch (error) { throw new Error(`Failed to update block slot: ${error instanceof Error ? error.message : String(error)}`); } } /** * Helper method to convert date string to milliseconds */ private convertToMilliseconds(dateString: string): string { // If already in milliseconds, return as is if (/^\d+$/.test(dateString)) { return dateString; } // Try to parse as ISO date const date = new Date(dateString); if (!isNaN(date.getTime())) { return date.getTime().toString(); } // Return as is if can't parse return dateString; } /** * Helper method to convert date string to milliseconds for date-only values */ private convertDateToMilliseconds(dateString: string): number { // If already in milliseconds, parse and return if (/^\d+$/.test(dateString)) { return parseInt(dateString, 10); } // Try to parse as date string (YYYY-MM-DD format) const date = new Date(dateString); if (!isNaN(date.getTime())) { return date.getTime(); } // Fallback to current time return Date.now(); } /** * CREATE CALENDAR GROUP */ private async createCalendarGroup(params: MCPCreateCalendarGroupParams): Promise<{ success: boolean; group: any; message: string }> { try { const groupData = { locationId: this.ghlClient.getConfig().locationId, name: params.name, description: params.description, slug: params.slug }; const response = await this.ghlClient.createCalendarGroup(groupData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, group: response.data, message: `Calendar group created successfully with slug: ${params.slug}` }; } catch (error) { throw new Error(`Failed to create calendar group: ${error instanceof Error ? error.message : String(error)}`); } } /** * VALIDATE GROUP SLUG */ private async validateGroupSlug(params: MCPValidateGroupSlugParams): Promise<{ success: boolean; available?: boolean; message: string }> { try { const locationId = params.locationId || this.ghlClient.getConfig().locationId; const response = await this.ghlClient.validateCalendarGroupSlug(params.slug, locationId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, available: response.data.available, message: response.data.available ? 'Slug is available' : 'Slug is not available' }; } catch (error) { throw new Error(`Failed to validate group slug: ${error instanceof Error ? error.message : String(error)}`); } } /** * UPDATE CALENDAR GROUP */ private async updateCalendarGroup(params: MCPUpdateCalendarGroupParams): Promise<{ success: boolean; group: any; message: string }> { try { const { groupId, ...updateData } = params; const response = await this.ghlClient.updateCalendarGroup(groupId, updateData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, group: response.data, message: 'Calendar group updated successfully' }; } catch (error) { throw new Error(`Failed to update calendar group: ${error instanceof Error ? error.message : String(error)}`); } } /** * DELETE CALENDAR GROUP */ private async deleteCalendarGroup(params: MCPDeleteCalendarGroupParams): Promise<{ success: boolean; message: string }> { try { const response = await this.ghlClient.deleteCalendarGroup(params.groupId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, message: 'Calendar group deleted successfully' }; } catch (error) { throw new Error(`Failed to delete calendar group: ${error instanceof Error ? error.message : String(error)}`); } } /** * DISABLE CALENDAR GROUP */ private async disableCalendarGroup(params: MCPDisableCalendarGroupParams): Promise<{ success: boolean; message: string }> { try { const response = await this.ghlClient.disableCalendarGroup(params.groupId, params.isActive); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, message: `Calendar group ${params.isActive ? 'enabled' : 'disabled'} successfully` }; } catch (error) { throw new Error(`Failed to disable calendar group: ${error instanceof Error ? error.message : String(error)}`); } } /** * GET APPOINTMENT NOTES */ private async getAppointmentNotes(params: MCPGetAppointmentNotesParams): Promise<{ success: boolean; notes: any[]; message: string }> { try { const response = await this.ghlClient.getAppointmentNotes(params.appointmentId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } const notes = Array.isArray(response.data.notes) ? response.data.notes : []; return { success: true, notes, message: `Retrieved ${notes.length} appointment notes` }; } catch (error) { throw new Error(`Failed to get appointment notes: ${error instanceof Error ? error.message : String(error)}`); } } /** * CREATE APPOINTMENT NOTE */ private async createAppointmentNote(params: MCPCreateAppointmentNoteParams): Promise<{ success: boolean; note: any; message: string }> { try { const { appointmentId, ...noteData } = params; const response = await this.ghlClient.createAppointmentNote(appointmentId, noteData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, note: response.data, message: 'Appointment note created successfully' }; } catch (error) { throw new Error(`Failed to create appointment note: ${error instanceof Error ? error.message : String(error)}`); } } /** * UPDATE APPOINTMENT NOTE */ private async updateAppointmentNote(params: MCPUpdateAppointmentNoteParams): Promise<{ success: boolean; note: any; message: string }> { try { const { appointmentId, noteId, ...updateData } = params; const response = await this.ghlClient.updateAppointmentNote(appointmentId, noteId, updateData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, note: response.data, message: 'Appointment note updated successfully' }; } catch (error) { throw new Error(`Failed to update appointment note: ${error instanceof Error ? error.message : String(error)}`); } } /** * DELETE APPOINTMENT NOTE */ private async deleteAppointmentNote(params: MCPDeleteAppointmentNoteParams): Promise<{ success: boolean; message: string }> { try { const response = await this.ghlClient.deleteAppointmentNote(params.appointmentId, params.noteId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, message: 'Appointment note deleted successfully' }; } catch (error) { throw new Error(`Failed to delete appointment note: ${error instanceof Error ? error.message : String(error)}`); } } /** * GET CALENDAR RESOURCES - EQUIPMENTS */ private async getCalendarResourcesEquipments(params: MCPGetCalendarResourcesParams): Promise<{ success: boolean; resources: any[]; message: string }> { try { const locationId = params.locationId || this.ghlClient.getConfig().locationId; const response = await this.ghlClient.getCalendarResources('equipments', params.limit, params.skip, locationId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } const resources = Array.isArray(response.data) ? response.data : []; return { success: true, resources, message: `Retrieved ${resources.length} equipment resources` }; } catch (error) { throw new Error(`Failed to get equipment resources: ${error instanceof Error ? error.message : String(error)}`); } } /** * CREATE CALENDAR RESOURCE - EQUIPMENT */ private async createCalendarResourceEquipment(params: MCPCreateCalendarResourceParams): Promise<{ success: boolean; resource: any; message: string }> { try { const resourceData = { ...params, locationId: params.locationId || this.ghlClient.getConfig().locationId }; const response = await this.ghlClient.createCalendarResource('equipments', resourceData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, resource: response.data, message: 'Equipment resource created successfully' }; } catch (error) { throw new Error(`Failed to create equipment resource: ${error instanceof Error ? error.message : String(error)}`); } } /** * GET CALENDAR RESOURCE - EQUIPMENT */ private async getCalendarResourceEquipment(params: MCPGetCalendarResourceParams): Promise<{ success: boolean; resource: any; message: string }> { try { const response = await this.ghlClient.getCalendarResource('equipments', params.resourceId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, resource: response.data, message: 'Equipment resource retrieved successfully' }; } catch (error) { throw new Error(`Failed to get equipment resource: ${error instanceof Error ? error.message : String(error)}`); } } /** * UPDATE CALENDAR RESOURCE - EQUIPMENT */ private async updateCalendarResourceEquipment(params: MCPUpdateCalendarResourceParams): Promise<{ success: boolean; resource: any; message: string }> { try { const { resourceId, ...updateData } = params; const response = await this.ghlClient.updateCalendarResource('equipments', resourceId, updateData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, resource: response.data, message: 'Equipment resource updated successfully' }; } catch (error) { throw new Error(`Failed to update equipment resource: ${error instanceof Error ? error.message : String(error)}`); } } /** * DELETE CALENDAR RESOURCE - EQUIPMENT */ private async deleteCalendarResourceEquipment(params: MCPDeleteCalendarResourceParams): Promise<{ success: boolean; message: string }> { try { const response = await this.ghlClient.deleteCalendarResource('equipments', params.resourceId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, message: 'Equipment resource deleted successfully' }; } catch (error) { throw new Error(`Failed to delete equipment resource: ${error instanceof Error ? error.message : String(error)}`); } } /** * GET CALENDAR RESOURCES - ROOMS */ private async getCalendarResourcesRooms(params: MCPGetCalendarResourcesParams): Promise<{ success: boolean; resources: any[]; message: string }> { try { const locationId = params.locationId || this.ghlClient.getConfig().locationId; const response = await this.ghlClient.getCalendarResources('rooms', params.limit, params.skip, locationId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } const resources = Array.isArray(response.data) ? response.data : []; return { success: true, resources, message: `Retrieved ${resources.length} room resources` }; } catch (error) { throw new Error(`Failed to get room resources: ${error instanceof Error ? error.message : String(error)}`); } } /** * CREATE CALENDAR RESOURCE - ROOM */ private async createCalendarResourceRoom(params: MCPCreateCalendarResourceParams): Promise<{ success: boolean; resource: any; message: string }> { try { const resourceData = { ...params, locationId: params.locationId || this.ghlClient.getConfig().locationId }; const response = await this.ghlClient.createCalendarResource('rooms', resourceData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, resource: response.data, message: 'Room resource created successfully' }; } catch (error) { throw new Error(`Failed to create room resource: ${error instanceof Error ? error.message : String(error)}`); } } /** * GET CALENDAR RESOURCE - ROOM */ private async getCalendarResourceRoom(params: MCPGetCalendarResourceParams): Promise<{ success: boolean; resource: any; message: string }> { try { const response = await this.ghlClient.getCalendarResource('rooms', params.resourceId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, resource: response.data, message: 'Room resource retrieved successfully' }; } catch (error) { throw new Error(`Failed to get room resource: ${error instanceof Error ? error.message : String(error)}`); } } /** * UPDATE CALENDAR RESOURCE - ROOM */ private async updateCalendarResourceRoom(params: MCPUpdateCalendarResourceParams): Promise<{ success: boolean; resource: any; message: string }> { try { const { resourceId, ...updateData } = params; const response = await this.ghlClient.updateCalendarResource('rooms', resourceId, updateData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, resource: response.data, message: 'Room resource updated successfully' }; } catch (error) { throw new Error(`Failed to update room resource: ${error instanceof Error ? error.message : String(error)}`); } } /** * DELETE CALENDAR RESOURCE - ROOM */ private async deleteCalendarResourceRoom(params: MCPDeleteCalendarResourceParams): Promise<{ success: boolean; message: string }> { try { const response = await this.ghlClient.deleteCalendarResource('rooms', params.resourceId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, message: 'Room resource deleted successfully' }; } catch (error) { throw new Error(`Failed to delete room resource: ${error instanceof Error ? error.message : String(error)}`); } } /** * GET CALENDAR NOTIFICATIONS */ private async getCalendarNotifications(params: MCPGetCalendarNotificationsParams): Promise<{ success: boolean; notifications: any[]; message: string }> { try { const response = await this.ghlClient.getCalendarNotifications(params.calendarId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } const notifications = Array.isArray(response.data) ? response.data : []; return { success: true, notifications, message: `Retrieved ${notifications.length} calendar notifications` }; } catch (error) { throw new Error(`Failed to get calendar notifications: ${error instanceof Error ? error.message : String(error)}`); } } /** * CREATE CALENDAR NOTIFICATIONS */ private async createCalendarNotifications(params: MCPCreateCalendarNotificationParams): Promise<{ success: boolean; message: string }> { try { const { calendarId, notifications } = params; const response = await this.ghlClient.createCalendarNotifications(calendarId, notifications); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, message: 'Calendar notifications created successfully' }; } catch (error) { throw new Error(`Failed to create calendar notifications: ${error instanceof Error ? error.message : String(error)}`); } } /** * GET CALENDAR NOTIFICATION */ private async getCalendarNotification(params: MCPGetCalendarNotificationParams): Promise<{ success: boolean; notification: any; message: string }> { try { const response = await this.ghlClient.getCalendarNotification(params.calendarId, params.notificationId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, notification: response.data, message: 'Calendar notification retrieved successfully' }; } catch (error) { throw new Error(`Failed to get calendar notification: ${error instanceof Error ? error.message : String(error)}`); } } /** * UPDATE CALENDAR NOTIFICATION */ private async updateCalendarNotification(params: MCPUpdateCalendarNotificationParams): Promise<{ success: boolean; message: string }> { try { const { calendarId, notificationId, ...updateData } = params; const response = await this.ghlClient.updateCalendarNotification(calendarId, notificationId, updateData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, message: 'Calendar notification updated successfully' }; } catch (error) { throw new Error(`Failed to update calendar notification: ${error instanceof Error ? error.message : String(error)}`); } } /** * DELETE CALENDAR NOTIFICATION */ private async deleteCalendarNotification(params: MCPDeleteCalendarNotificationParams): Promise<{ success: boolean; message: string }> { try { const response = await this.ghlClient.deleteCalendarNotification(params.calendarId, params.notificationId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, message: 'Calendar notification deleted successfully' }; } catch (error) { throw new Error(`Failed to delete calendar notification: ${error instanceof Error ? error.message : String(error)}`); } } /** * GET BLOCKED SLOTS */ private async getBlockedSlots(params: MCPGetBlockedSlotsParams): Promise<{ success: boolean; slots: any[]; message: string }> { try { const eventParams = { locationId: this.ghlClient.getConfig().locationId, startTime: params.startTime, endTime: params.endTime, userId: params.userId, calendarId: params.calendarId, groupId: params.groupId }; const response = await this.ghlClient.getBlockedSlots(eventParams); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } const slots = Array.isArray(response.data.events) ? response.data.events : []; return { success: true, slots, message: `Retrieved ${slots.length} blocked time slots` }; } catch (error) { throw new Error(`Failed to get blocked slots: ${error instanceof Error ? error.message : String(error)}`); } } }

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/clickmediapropy/gohighlevel-mcp-server'

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