Skip to main content
Glama
location-tools.ts41.1 kB
/** * MCP Location Tools for GoHighLevel Integration * Exposes location/sub-account management capabilities to the MCP server */ import { Tool } from '@modelcontextprotocol/sdk/types.js'; import { GHLApiClient } from '../clients/ghl-api-client.js'; import { MCPSearchLocationsParams, MCPGetLocationParams, MCPCreateLocationParams, MCPUpdateLocationParams, MCPDeleteLocationParams, MCPGetLocationTagsParams, MCPCreateLocationTagParams, MCPGetLocationTagParams, MCPUpdateLocationTagParams, MCPDeleteLocationTagParams, MCPSearchLocationTasksParams, MCPGetCustomFieldsParams, MCPCreateCustomFieldParams, MCPGetCustomFieldParams, MCPUpdateCustomFieldParams, MCPDeleteCustomFieldParams, MCPGetCustomValuesParams, MCPCreateCustomValueParams, MCPGetCustomValueParams, MCPUpdateCustomValueParams, MCPDeleteCustomValueParams, MCPGetLocationTemplatesParams, MCPDeleteLocationTemplateParams, MCPGetTimezonesParams, GHLLocation, GHLLocationDetailed, GHLLocationTag, GHLLocationCustomField, GHLLocationCustomValue } from '../types/ghl-types.js'; /** * Location Tools Class * Implements MCP tools for location and sub-account management */ export class LocationTools { constructor(private ghlClient: GHLApiClient) {} /** * Get all location tool definitions for MCP server */ getToolDefinitions(): Tool[] { return [ { name: 'search_locations', description: 'Search for locations/sub-accounts in GoHighLevel with filtering options', inputSchema: { type: 'object', properties: { companyId: { type: 'string', description: 'Company/Agency ID to filter locations' }, skip: { type: 'number', description: 'Number of results to skip for pagination (default: 0)', default: 0 }, limit: { type: 'number', description: 'Maximum number of locations to return (default: 10)', default: 10 }, order: { type: 'string', enum: ['asc', 'desc'], description: 'Order of results (default: asc)', default: 'asc' }, email: { type: 'string', description: 'Filter by email address', format: 'email' } } } }, { name: 'get_location', description: 'Get detailed information about a specific location/sub-account by ID', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The unique ID of the location to retrieve' } }, required: ['locationId'] } }, { name: 'create_location', description: 'Create a new sub-account/location in GoHighLevel (Agency Pro plan required)', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Name of the sub-account/location' }, companyId: { type: 'string', description: 'Company/Agency ID' }, phone: { type: 'string', description: 'Phone number with country code (e.g., +1410039940)' }, address: { type: 'string', description: 'Business address' }, city: { type: 'string', description: 'City where business is located' }, state: { type: 'string', description: 'State where business operates' }, country: { type: 'string', description: '2-letter country code (e.g., US, CA, GB)' }, postalCode: { type: 'string', description: 'Postal/ZIP code' }, website: { type: 'string', description: 'Business website URL' }, timezone: { type: 'string', description: 'Business timezone (e.g., US/Central)' }, prospectInfo: { type: 'object', properties: { firstName: { type: 'string', description: 'Prospect first name' }, lastName: { type: 'string', description: 'Prospect last name' }, email: { type: 'string', format: 'email', description: 'Prospect email' } }, required: ['firstName', 'lastName', 'email'], description: 'Prospect information for the location' }, snapshotId: { type: 'string', description: 'Snapshot ID to load into the location' } }, required: ['name', 'companyId'] } }, { name: 'update_location', description: 'Update an existing sub-account/location in GoHighLevel', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The unique ID of the location to update' }, name: { type: 'string', description: 'Updated name of the sub-account/location' }, companyId: { type: 'string', description: 'Company/Agency ID' }, phone: { type: 'string', description: 'Updated phone number' }, address: { type: 'string', description: 'Updated business address' }, city: { type: 'string', description: 'Updated city' }, state: { type: 'string', description: 'Updated state' }, country: { type: 'string', description: 'Updated 2-letter country code' }, postalCode: { type: 'string', description: 'Updated postal/ZIP code' }, website: { type: 'string', description: 'Updated website URL' }, timezone: { type: 'string', description: 'Updated timezone' } }, required: ['locationId', 'companyId'] } }, { name: 'delete_location', description: 'Delete a sub-account/location from GoHighLevel', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The unique ID of the location to delete' }, deleteTwilioAccount: { type: 'boolean', description: 'Whether to delete associated Twilio account', default: false } }, required: ['locationId', 'deleteTwilioAccount'] } }, // Location Tags Tools { name: 'get_location_tags', description: 'Get all tags for a specific location', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID to get tags from' } }, required: ['locationId'] } }, { name: 'create_location_tag', description: 'Create a new tag for a location', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID to create tag in' }, name: { type: 'string', description: 'Name of the tag to create' } }, required: ['locationId', 'name'] } }, { name: 'get_location_tag', description: 'Get a specific location tag by ID', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID' }, tagId: { type: 'string', description: 'The tag ID to retrieve' } }, required: ['locationId', 'tagId'] } }, { name: 'update_location_tag', description: 'Update an existing location tag', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID' }, tagId: { type: 'string', description: 'The tag ID to update' }, name: { type: 'string', description: 'Updated name for the tag' } }, required: ['locationId', 'tagId', 'name'] } }, { name: 'delete_location_tag', description: 'Delete a location tag', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID' }, tagId: { type: 'string', description: 'The tag ID to delete' } }, required: ['locationId', 'tagId'] } }, // Location Tasks Tools { name: 'search_location_tasks', description: 'Search tasks within a location with advanced filtering', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID to search tasks in' }, contactId: { type: 'array', items: { type: 'string' }, description: 'Filter by specific contact IDs' }, completed: { type: 'boolean', description: 'Filter by completion status' }, assignedTo: { type: 'array', items: { type: 'string' }, description: 'Filter by assigned user IDs' }, query: { type: 'string', description: 'Search query for task content' }, limit: { type: 'number', description: 'Maximum number of tasks to return (default: 25)', default: 25 }, skip: { type: 'number', description: 'Number of tasks to skip for pagination (default: 0)', default: 0 }, businessId: { type: 'string', description: 'Business ID filter' } }, required: ['locationId'] } }, // Custom Fields Tools { name: 'get_location_custom_fields', description: 'Get custom fields for a location, optionally filtered by model type', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID' }, model: { type: 'string', enum: ['contact', 'opportunity', 'all'], description: 'Filter by model type (default: all)', default: 'all' } }, required: ['locationId'] } }, { name: 'create_location_custom_field', description: 'Create a new custom field for a location', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID' }, name: { type: 'string', description: 'Name of the custom field' }, dataType: { type: 'string', description: 'Data type of the field (TEXT, NUMBER, DATE, etc.)' }, placeholder: { type: 'string', description: 'Placeholder text for the field' }, model: { type: 'string', enum: ['contact', 'opportunity'], description: 'Model to create the field for', default: 'contact' }, position: { type: 'number', description: 'Position/order of the field (default: 0)', default: 0 } }, required: ['locationId', 'name', 'dataType'] } }, { name: 'get_location_custom_field', description: 'Get a specific custom field by ID', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID' }, customFieldId: { type: 'string', description: 'The custom field ID to retrieve' } }, required: ['locationId', 'customFieldId'] } }, { name: 'update_location_custom_field', description: 'Update an existing custom field', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID' }, customFieldId: { type: 'string', description: 'The custom field ID to update' }, name: { type: 'string', description: 'Updated name of the custom field' }, placeholder: { type: 'string', description: 'Updated placeholder text' }, position: { type: 'number', description: 'Updated position/order' } }, required: ['locationId', 'customFieldId', 'name'] } }, { name: 'delete_location_custom_field', description: 'Delete a custom field from a location', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID' }, customFieldId: { type: 'string', description: 'The custom field ID to delete' } }, required: ['locationId', 'customFieldId'] } }, // Custom Values Tools { name: 'get_location_custom_values', description: 'Get all custom values for a location', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID' } }, required: ['locationId'] } }, { name: 'create_location_custom_value', description: 'Create a new custom value for a location', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID' }, name: { type: 'string', description: 'Name of the custom value field' }, value: { type: 'string', description: 'Value to assign' } }, required: ['locationId', 'name', 'value'] } }, { name: 'get_location_custom_value', description: 'Get a specific custom value by ID', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID' }, customValueId: { type: 'string', description: 'The custom value ID to retrieve' } }, required: ['locationId', 'customValueId'] } }, { name: 'update_location_custom_value', description: 'Update an existing custom value', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID' }, customValueId: { type: 'string', description: 'The custom value ID to update' }, name: { type: 'string', description: 'Updated name' }, value: { type: 'string', description: 'Updated value' } }, required: ['locationId', 'customValueId', 'name', 'value'] } }, { name: 'delete_location_custom_value', description: 'Delete a custom value from a location', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID' }, customValueId: { type: 'string', description: 'The custom value ID to delete' } }, required: ['locationId', 'customValueId'] } }, // Templates Tools { name: 'get_location_templates', description: 'Get SMS/Email templates for a location', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID' }, originId: { type: 'string', description: 'Origin ID (required parameter)' }, deleted: { type: 'boolean', description: 'Include deleted templates (default: false)', default: false }, skip: { type: 'number', description: 'Number to skip for pagination (default: 0)', default: 0 }, limit: { type: 'number', description: 'Maximum number to return (default: 25)', default: 25 }, type: { type: 'string', enum: ['sms', 'email', 'whatsapp'], description: 'Filter by template type' } }, required: ['locationId', 'originId'] } }, { name: 'delete_location_template', description: 'Delete a template from a location', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'The location ID' }, templateId: { type: 'string', description: 'The template ID to delete' } }, required: ['locationId', 'templateId'] } }, // Timezones Tool { name: 'get_timezones', description: 'Get available timezones for location configuration', inputSchema: { type: 'object', properties: { locationId: { type: 'string', description: 'Optional location ID' } } } } ]; } /** * Execute location tool based on tool name and arguments */ async executeTool(name: string, args: any): Promise<any> { switch (name) { // Location Management case 'search_locations': return this.searchLocations(args as MCPSearchLocationsParams); case 'get_location': return this.getLocation(args as MCPGetLocationParams); case 'create_location': return this.createLocation(args as MCPCreateLocationParams); case 'update_location': return this.updateLocation(args as MCPUpdateLocationParams); case 'delete_location': return this.deleteLocation(args as MCPDeleteLocationParams); // Location Tags case 'get_location_tags': return this.getLocationTags(args as MCPGetLocationTagsParams); case 'create_location_tag': return this.createLocationTag(args as MCPCreateLocationTagParams); case 'get_location_tag': return this.getLocationTag(args as MCPGetLocationTagParams); case 'update_location_tag': return this.updateLocationTag(args as MCPUpdateLocationTagParams); case 'delete_location_tag': return this.deleteLocationTag(args as MCPDeleteLocationTagParams); // Location Tasks case 'search_location_tasks': return this.searchLocationTasks(args as MCPSearchLocationTasksParams); // Custom Fields case 'get_location_custom_fields': return this.getLocationCustomFields(args as MCPGetCustomFieldsParams); case 'create_location_custom_field': return this.createLocationCustomField(args as MCPCreateCustomFieldParams); case 'get_location_custom_field': return this.getLocationCustomField(args as MCPGetCustomFieldParams); case 'update_location_custom_field': return this.updateLocationCustomField(args as MCPUpdateCustomFieldParams); case 'delete_location_custom_field': return this.deleteLocationCustomField(args as MCPDeleteCustomFieldParams); // Custom Values case 'get_location_custom_values': return this.getLocationCustomValues(args as MCPGetCustomValuesParams); case 'create_location_custom_value': return this.createLocationCustomValue(args as MCPCreateCustomValueParams); case 'get_location_custom_value': return this.getLocationCustomValue(args as MCPGetCustomValueParams); case 'update_location_custom_value': return this.updateLocationCustomValue(args as MCPUpdateCustomValueParams); case 'delete_location_custom_value': return this.deleteLocationCustomValue(args as MCPDeleteCustomValueParams); // Templates case 'get_location_templates': return this.getLocationTemplates(args as MCPGetLocationTemplatesParams); case 'delete_location_template': return this.deleteLocationTemplate(args as MCPDeleteLocationTemplateParams); // Timezones case 'get_timezones': return this.getTimezones(args as MCPGetTimezonesParams); default: throw new Error(`Unknown location tool: ${name}`); } } private async searchLocations(params: MCPSearchLocationsParams): Promise<{ success: boolean; locations: GHLLocation[]; message: string }> { try { const response = await this.ghlClient.searchLocations(params); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } const locations = response.data.locations || []; return { success: true, locations, message: `Found ${locations.length} locations` }; } catch (error) { throw new Error(`Failed to search locations: ${error instanceof Error ? error.message : String(error)}`); } } private async getLocation(params: MCPGetLocationParams): Promise<{ success: boolean; location: GHLLocationDetailed; message: string }> { try { const response = await this.ghlClient.getLocationById(params.locationId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, location: response.data.location, message: 'Location retrieved successfully' }; } catch (error) { throw new Error(`Failed to get location: ${error instanceof Error ? error.message : String(error)}`); } } private async getLocationTags(params: MCPGetLocationTagsParams): Promise<{ success: boolean; tags: GHLLocationTag[]; message: string }> { try { const response = await this.ghlClient.getLocationTags(params.locationId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } const tags = response.data.tags || []; return { success: true, tags, message: `Retrieved ${tags.length} location tags` }; } catch (error) { throw new Error(`Failed to get location tags: ${error instanceof Error ? error.message : String(error)}`); } } private async createLocation(params: MCPCreateLocationParams): Promise<{ success: boolean; location: GHLLocationDetailed; message: string }> { try { const response = await this.ghlClient.createLocation(params); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, location: response.data, message: `Location "${params.name}" created successfully` }; } catch (error) { throw new Error(`Failed to create location: ${error instanceof Error ? error.message : String(error)}`); } } private async updateLocation(params: MCPUpdateLocationParams): Promise<{ success: boolean; location: GHLLocationDetailed; message: string }> { try { const { locationId, ...updateData } = params; const response = await this.ghlClient.updateLocation(locationId, updateData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, location: response.data, message: 'Location updated successfully' }; } catch (error) { throw new Error(`Failed to update location: ${error instanceof Error ? error.message : String(error)}`); } } private async deleteLocation(params: MCPDeleteLocationParams): Promise<{ success: boolean; message: string }> { try { const response = await this.ghlClient.deleteLocation(params.locationId, params.deleteTwilioAccount); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, message: response.data.message || 'Location deleted successfully' }; } catch (error) { throw new Error(`Failed to delete location: ${error instanceof Error ? error.message : String(error)}`); } } private async createLocationTag(params: MCPCreateLocationTagParams): Promise<{ success: boolean; tag: GHLLocationTag; message: string }> { try { const response = await this.ghlClient.createLocationTag(params.locationId, { name: params.name }); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, tag: response.data.tag, message: `Tag "${params.name}" created successfully` }; } catch (error) { throw new Error(`Failed to create location tag: ${error instanceof Error ? error.message : String(error)}`); } } private async getLocationTag(params: MCPGetLocationTagParams): Promise<{ success: boolean; tag: GHLLocationTag; message: string }> { try { const response = await this.ghlClient.getLocationTag(params.locationId, params.tagId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, tag: response.data.tag, message: 'Location tag retrieved successfully' }; } catch (error) { throw new Error(`Failed to get location tag: ${error instanceof Error ? error.message : String(error)}`); } } private async updateLocationTag(params: MCPUpdateLocationTagParams): Promise<{ success: boolean; tag: GHLLocationTag; message: string }> { try { const response = await this.ghlClient.updateLocationTag(params.locationId, params.tagId, { name: params.name }); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, tag: response.data.tag, message: 'Location tag updated successfully' }; } catch (error) { throw new Error(`Failed to update location tag: ${error instanceof Error ? error.message : String(error)}`); } } private async deleteLocationTag(params: MCPDeleteLocationTagParams): Promise<{ success: boolean; message: string }> { try { const response = await this.ghlClient.deleteLocationTag(params.locationId, params.tagId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, message: 'Location tag deleted successfully' }; } catch (error) { throw new Error(`Failed to delete location tag: ${error instanceof Error ? error.message : String(error)}`); } } private async searchLocationTasks(params: MCPSearchLocationTasksParams): Promise<{ success: boolean; tasks: any[]; message: string }> { try { const { locationId, ...searchParams } = params; const response = await this.ghlClient.searchLocationTasks(locationId, searchParams); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } const tasks = response.data.tasks || []; return { success: true, tasks, message: `Found ${tasks.length} tasks` }; } catch (error) { throw new Error(`Failed to search location tasks: ${error instanceof Error ? error.message : String(error)}`); } } private async getLocationCustomFields(params: MCPGetCustomFieldsParams): Promise<{ success: boolean; customFields: GHLLocationCustomField[]; message: string }> { try { const response = await this.ghlClient.getLocationCustomFields(params.locationId, params.model); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } const customFields = response.data.customFields || []; return { success: true, customFields, message: `Retrieved ${customFields.length} custom fields` }; } catch (error) { throw new Error(`Failed to get custom fields: ${error instanceof Error ? error.message : String(error)}`); } } private async createLocationCustomField(params: MCPCreateCustomFieldParams): Promise<{ success: boolean; customField: GHLLocationCustomField; message: string }> { try { const { locationId, ...fieldData } = params; const response = await this.ghlClient.createLocationCustomField(locationId, fieldData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, customField: response.data.customField, message: `Custom field "${params.name}" created successfully` }; } catch (error) { throw new Error(`Failed to create custom field: ${error instanceof Error ? error.message : String(error)}`); } } private async getLocationCustomField(params: MCPGetCustomFieldParams): Promise<{ success: boolean; customField: GHLLocationCustomField; message: string }> { try { const response = await this.ghlClient.getLocationCustomField(params.locationId, params.customFieldId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, customField: response.data.customField, message: 'Custom field retrieved successfully' }; } catch (error) { throw new Error(`Failed to get custom field: ${error instanceof Error ? error.message : String(error)}`); } } private async updateLocationCustomField(params: MCPUpdateCustomFieldParams): Promise<{ success: boolean; customField: GHLLocationCustomField; message: string }> { try { const { locationId, customFieldId, ...fieldData } = params; const response = await this.ghlClient.updateLocationCustomField(locationId, customFieldId, fieldData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, customField: response.data.customField, message: 'Custom field updated successfully' }; } catch (error) { throw new Error(`Failed to update custom field: ${error instanceof Error ? error.message : String(error)}`); } } private async deleteLocationCustomField(params: MCPDeleteCustomFieldParams): Promise<{ success: boolean; message: string }> { try { const response = await this.ghlClient.deleteLocationCustomField(params.locationId, params.customFieldId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, message: 'Custom field deleted successfully' }; } catch (error) { throw new Error(`Failed to delete custom field: ${error instanceof Error ? error.message : String(error)}`); } } private async getLocationCustomValues(params: MCPGetCustomValuesParams): Promise<{ success: boolean; customValues: GHLLocationCustomValue[]; message: string }> { try { const response = await this.ghlClient.getLocationCustomValues(params.locationId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } const customValues = response.data.customValues || []; return { success: true, customValues, message: `Retrieved ${customValues.length} custom values` }; } catch (error) { throw new Error(`Failed to get custom values: ${error instanceof Error ? error.message : String(error)}`); } } private async createLocationCustomValue(params: MCPCreateCustomValueParams): Promise<{ success: boolean; customValue: GHLLocationCustomValue; message: string }> { try { const { locationId, ...valueData } = params; const response = await this.ghlClient.createLocationCustomValue(locationId, valueData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, customValue: response.data.customValue, message: `Custom value "${params.name}" created successfully` }; } catch (error) { throw new Error(`Failed to create custom value: ${error instanceof Error ? error.message : String(error)}`); } } private async getLocationCustomValue(params: MCPGetCustomValueParams): Promise<{ success: boolean; customValue: GHLLocationCustomValue; message: string }> { try { const response = await this.ghlClient.getLocationCustomValue(params.locationId, params.customValueId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, customValue: response.data.customValue, message: 'Custom value retrieved successfully' }; } catch (error) { throw new Error(`Failed to get custom value: ${error instanceof Error ? error.message : String(error)}`); } } private async updateLocationCustomValue(params: MCPUpdateCustomValueParams): Promise<{ success: boolean; customValue: GHLLocationCustomValue; message: string }> { try { const { locationId, customValueId, ...valueData } = params; const response = await this.ghlClient.updateLocationCustomValue(locationId, customValueId, valueData); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, customValue: response.data.customValue, message: 'Custom value updated successfully' }; } catch (error) { throw new Error(`Failed to update custom value: ${error instanceof Error ? error.message : String(error)}`); } } private async deleteLocationCustomValue(params: MCPDeleteCustomValueParams): Promise<{ success: boolean; message: string }> { try { const response = await this.ghlClient.deleteLocationCustomValue(params.locationId, params.customValueId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, message: 'Custom value deleted successfully' }; } catch (error) { throw new Error(`Failed to delete custom value: ${error instanceof Error ? error.message : String(error)}`); } } private async getLocationTemplates(params: MCPGetLocationTemplatesParams): Promise<{ success: boolean; templates: any[]; totalCount: number; message: string }> { try { const { locationId, ...templateParams } = params; const response = await this.ghlClient.getLocationTemplates(locationId, templateParams); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } const templates = response.data.templates || []; const totalCount = response.data.totalCount || templates.length; return { success: true, templates, totalCount, message: `Retrieved ${templates.length} templates (${totalCount} total)` }; } catch (error) { throw new Error(`Failed to get location templates: ${error instanceof Error ? error.message : String(error)}`); } } private async deleteLocationTemplate(params: MCPDeleteLocationTemplateParams): Promise<{ success: boolean; message: string }> { try { const response = await this.ghlClient.deleteLocationTemplate(params.locationId, params.templateId); if (!response.success) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } return { success: true, message: 'Template deleted successfully' }; } catch (error) { throw new Error(`Failed to delete template: ${error instanceof Error ? error.message : String(error)}`); } } private async getTimezones(params: MCPGetTimezonesParams): Promise<{ success: boolean; timezones: string[]; message: string }> { try { const response = await this.ghlClient.getTimezones(params.locationId); if (!response.success || !response.data) { const errorMsg = response.error?.message || 'Unknown API error'; throw new Error(`API request failed: ${errorMsg}`); } const timezones = Array.isArray(response.data) ? response.data : []; return { success: true, timezones, message: `Retrieved ${timezones.length} available timezones` }; } catch (error) { throw new Error(`Failed to get timezones: ${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