ghl-mcp-server
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| PORT | No | HTTP transport port. | 3000 |
| GHL_API_KEY | Yes | Private Integration Token. Required. | |
| GHL_MODULES | No | Comma-separated modules to expose as dedicated tools, or 'all'. | contacts,conversations,opportunities,calendars,locations |
| GHL_META_TOOLS | No | Expose the three discovery/call meta-tools covering all endpoints. | true |
| MCP_AUTH_TOKEN | No | Bearer token clients must send to the HTTP transport. Required for HTTP transport; not needed for stdio. | |
| GHL_LOCATION_ID | No | Default sub-account; injected into any endpoint that takes locationId when the caller omits it. | |
| GHL_ALLOW_WRITES | No | Expose POST/PUT/PATCH tools. | false |
| GHL_ALLOW_DELETES | No | Expose DELETE tools (and remove-* style POSTs). | false |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| contacts_search_contacts_advancedB | Search Contacts Search contacts based on combinations of advanced filters. Documentation Link - https://doc.clickup.com/8631005/d/h/87cpx-158396/6e629989abe7fad [POST /contacts/search] Scopes: contacts.readonly. |
| contacts_get_duplicate_contactA | Get Duplicate Contact .If |
| contacts_get_all_tasksA | Get all Tasks [GET /contacts/{contactId}/tasks] Scopes: contacts.readonly. |
| contacts_get_taskB | Get Task [GET /contacts/{contactId}/tasks/{taskId}] Scopes: contacts.readonly. |
| contacts_get_appointments_for_contactA | Get Appointments for Contact [GET /contacts/{contactId}/appointments] Scopes: contacts.readonly. |
| contacts_get_all_notesB | Get All Notes [GET /contacts/{contactId}/notes] Scopes: contacts.readonly. |
| contacts_get_noteB | Get Note [GET /contacts/{contactId}/notes/{id}] Scopes: contacts.readonly. |
| contacts_get_contactB | Get Contact [GET /contacts/{contactId}] Scopes: contacts.readonly. |
| contacts_get_contacts_by_businessidA | Get Contacts By BusinessId [GET /contacts/business/{businessId}] Scopes: contacts.readonly. |
| contacts_get_contactsA | Get Contacts Note: This API endpoint is deprecated. Please use the Search Contacts endpoint instead. [GET /contacts/] Scopes: contacts.readonly. DEPRECATED. |
| conversations_search_conversationB | Search Conversations Returns a list of all conversations matching the search criteria along with the sort and filter options selected. [GET /conversations/search] Scopes: conversations.readonly. |
| conversations_get_conversationB | Get Conversation Get the conversation details based on the conversation ID [GET /conversations/{conversationId}] Scopes: conversations.readonly. |
| conversations_get_all_custom_subtypesC | Get All Custom Subtypes Get all custom subtypes for a location [GET /conversations/preferences/custom-subtypes] |
| conversations_get_contact_unsubscription_statusB | Get Contact Unsubscription Status Get all subscription statuses for a contact (all emails or specific email) [GET /conversations/preferences/unsubscriptions/status] |
| conversations_get_email_by_idC | Get email by Id [GET /conversations/messages/email/{id}] |
| conversations_export_messages_by_locationA | Export messages by location ID Export messages for a specific location with cursor-based pagination support. Response includes messageType (string), source, and subType fields. The channel parameter is optional - if not provided, all non-email message types will be returned including activity messages (opportunity updates, appointments, etc.). [GET /conversations/messages/export] Scopes: conversations/message.readonly. |
| conversations_get_messageA | Get message by message id . [GET /conversations/messages/{id}] Scopes: conversations/message.readonly. |
| conversations_get_messagesB | Get messages by conversation id . [GET /conversations/{conversationId}/messages] Scopes: conversations/message.readonly. |
| conversations_get_message_recordingB | Get Recording by Message ID Get the recording for a message by passing the message id [GET /conversations/messages/{messageId}/locations/{locationId}/recording] Token: location. Scopes: conversations/message.readonly. |
| conversations_get_message_transcriptionA | Get transcription by Message ID Get the recording transcription for a message by passing the message id [GET /conversations/locations/{locationId}/messages/{messageId}/transcription] Token: location. Scopes: conversations/message.readonly. |
| conversations_download_message_transcriptionC | Download transcription by Message ID Download the recording transcription for a message by passing the message id [GET /conversations/locations/{locationId}/messages/{messageId}/transcription/download] Token: location. Scopes: conversations/message.readonly. |
| opportunities_get_lost_reasonC | Get lost reason [GET /opportunities/lost-reason] Scopes: opportunities.readonly. |
| opportunities_search_opportunityB | Search Opportunity [GET /opportunities/search] Scopes: opportunities.readonly. |
| opportunities_search_opportunities_advancedC | Search Opportunities based on combinations of advanced filters. Documentation Link - https://doc.clickup.com/8631005/d/h/87cpx-424216/7bf11bc9b94f80f [POST /opportunities/search] Scopes: opportunities.readonly. |
| opportunities_get_pipelinesC | Get Pipelines [GET /opportunities/pipelines] Scopes: opportunities.readonly. |
| opportunities_get_opportunityB | Get Opportunity [GET /opportunities/{id}] Scopes: opportunities.readonly. |
| calendars_get_groupsA | Get Groups Get all calendar groups in a location. [GET /calendars/groups] Scopes: calendars/groups.readonly. |
| calendars_validate_groups_slugA | Validate group slug Validate if group slug is available or not. [POST /calendars/groups/validate-slug] Scopes: calendars/groups.write. |
| calendars_get_appointmentB | Get Appointment Get appointment by ID [GET /calendars/events/appointments/{eventId}] Scopes: calendars/events.readonly. |
| calendars_get_calendar_eventsC | Get Calendar Events [GET /calendars/events] Scopes: calendars/events.readonly. |
| calendars_get_blocked_slotsB | Get Blocked Slots [GET /calendars/blocked-slots] Scopes: calendars/events.readonly. |
| calendars_get_slotsB | Get Free Slots Get free slots for a calendar between a date range. Optionally a consumer can also request free slots in a particular timezone and also for a particular user. [GET /calendars/{calendarId}/free-slots] Scopes: calendars.readonly. |
| calendars_get_calendarA | Get Calendar Get calendar by ID [GET /calendars/{calendarId}] Scopes: calendars.readonly. |
| calendars_get_appointment_notesB | Get Notes Get Appointment Notes [GET /calendars/appointments/{appointmentId}/notes] Scopes: calendars/events.readonly. |
| calendars_get_calendar_resourceA | Get Calendar Resource Get calendar resource by ID [GET /calendars/resources/{resourceType}/{id}] Token: location. Scopes: calendars/resources.readonly. |
| calendars_fetch_calendar_resourcesA | List Calendar Resources List calendar resources by resource type and location ID [GET /calendars/resources/{resourceType}] Token: location. Scopes: calendars/resources.readonly. |
| calendars_get_event_notificationC | Get notifications Get calendar notifications based on query [GET /calendars/{calendarId}/notifications] Scopes: calendars/events.readonly. |
| calendars_find_event_notificationC | Get notification Find Event notification by notificationId [GET /calendars/{calendarId}/notifications/{notificationId}] Scopes: calendars/events.readonly. |
| calendars_getallschedulesA | List user availability schedule Retrieve user availability schedules based on various filters including location, calendar, and user. Supports pagination. [GET /calendars/schedules/search] Scopes: calendars.readonly. |
| calendars_getschedulebyidA | Get user availability schedule Retrieve a specific schedule by its unique identifier. Returns detailed information including rules, timezone, and associated calendars/users. [GET /calendars/schedules/{id}] Scopes: calendars.readonly. |
| calendars_get_calendarsA | Get Calendars Get all calendars in a location. [GET /calendars/] Scopes: calendars.readonly. |
| locations_search_locationsB | Search Sub-Account (Formerly Location) [GET /locations/search] Token: location or agency. Scopes: locations.readonly. |
| locations_get_locationA | Get Sub-Account (Formerly Location) Get details of a Sub-Account (Formerly Location) by passing the sub-account id [GET /locations/{locationId}] Token: location or agency. Scopes: locations.readonly. |
| locations_get_location_tagsA | Get Tags Get Sub-Account (Formerly Location) Tags [GET /locations/{locationId}/tags] Scopes: locations/tags.readonly. |
| locations_get_tag_by_idA | Get tag by id [GET /locations/{locationId}/tags/{tagId}] |
| locations_get_recurring_task_by_idC | Get Recurring Task By Id [GET /locations/{locationId}/recurring-tasks/{id}] |
| locations_get_custom_fieldsA | Get Custom Fields [GET /locations/{locationId}/customFields] Scopes: locations/customFields.readonly. |
| locations_get_custom_fieldC | Get Custom Field [GET /locations/{locationId}/customFields/{id}] |
| locations_get_custom_valuesB | Get Custom Values [GET /locations/{locationId}/customValues] Scopes: locations/customValues.readonly. |
| locations_get_custom_valueB | Get Custom Value [GET /locations/{locationId}/customValues/{id}] |
| locations_get_timezonesA | Fetch Timezones Fetch the available timezones [GET /locations/{locationId}/timezones] Token: location. Scopes: locations.readonly. |
| locations_get_all_or_email_sms_templatesA | GET all or email/sms templates [GET /locations/{locationId}/templates] Scopes: locations/templates.readonly. |
| ghl_search_endpointsA | Find GoHighLevel API endpoints by keyword across all 576 endpoints in 41 modules, including ones not loaded as dedicated tools. Returns tool names to pass to ghl_describe_endpoint / ghl_call_endpoint. Modules: ad-manager, affiliate-manager, agent-studio, associations, blogs, brand-boards, businesses, calendars, campaigns, companies, contacts, conversation-ai, conversations, courses, custom-fields, custom-menus, email-isv, emails, forms, funnels, invoices, knowledge-base, links, locations, marketplace, medias, oauth, objects, opportunities, payments, phone-system, products, proposals, saas-api, snapshots, social-media-posting, store, surveys, users, voice-ai, workflows. |
| ghl_describe_endpointA | Return the full input schema, required fields, auth scopes, and HTTP details for one endpoint by tool name. |
| ghl_call_endpointA | Execute any endpoint by tool name with a flat arguments object (path, query, and body fields all at top level; see ghl_describe_endpoint). Subject to the same write/delete gates as dedicated tools. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 55 tools
Several tools have unclear boundaries: opportunities_search_opportunity vs opportunities_search_opportunities_advanced, deprecated contacts_get_contacts vs contacts_search_contacts_advanced, and calendars_get_event_notification vs calendars_find_event_notification. The get/search/find verb variation across similar resources creates frequent ambiguity.
Naming is highly inconsistent: module prefixes are mixed with camelCase (calendars_getallschedules, calendars_getschedulebyid), verbs vary between get/search/fetch/find, and singular/plural forms are inconsistent (opportunity vs opportunities, resource vs resources). There is no predictable overall pattern.
At 55 tools, the server is far over the typical well-scoped range. While it covers multiple modules, the count feels bloated, especially since nearly all dedicated tools are read-only GETs and many could be consolidated.
The dedicated tool set has obvious gaps: there are no create/update/delete tools for contacts, conversations, tasks, notes, or appointments. However, the ghl_call_endpoint meta-tool exposes all 576 API endpoints, so agents can work around the missing operations, though this creates an awkward dependence on a generic escape hatch.