Skip to main content
Glama
traynewreck

GoHighLevel MCP Server

by traynewreck
README.md
# GoHighLevel MCP Server (Self-Hosted)

Use case: Connect AI apps like [RetellAI](https://dashboard.retellai.com/?ref=justin) and [Vapi](https://vapi.ai/?aff=justin6q) directly to [GoHighLevel (GHL)](https://www.gohighlevel.com/?fp_ref=lead-brain-llc81) for contact + booking workflows.
This project may also work with other MCP-compatible apps.

**No middleware required: direct RetellAI/Vapi -> GHL integration without apps like n8n or make.com.**

If this is your first time using [Vercel](https://vercel.com) or MCP, setup typically takes **15-30 minutes**.

You maybe asking why not just use GHL's native MCP? At the time of development they do not provide tooling for querying calendars for open slots or booking appointments.

## Table of Contents

- [What This Server Does](#what-this-server-does)
- [Quick Start Checklist](#quick-start-checklist)
- [1. Deploy on Vercel](#1-deploy-on-vercel)
- [2. Connect MCP in Your Agent Platform](#2-connect-mcp-in-your-agent-platform)
- [3. Recommended Agent Flow](#3-recommended-agent-flow)
- [4. Troubleshooting](#4-troubleshooting)

## What This Server Does

- Create or update contacts (`ghl_create_contact`)
- Search contacts (`ghl_search_contacts`)
- Retrieve calendar free slots (`ghl_get_calendar_free_slots`)
- Create confirmed appointments (`ghl_create_appointment`)

Endpoint:

- `POST /mcp`

## Quick Start Checklist

- Deploy this repo to [Vercel](https://vercel.com)
- Add required environment variables
- Copy your Vercel `/mcp` URL
- Add MCP in RetellAI with required headers
- Add all 4 tools to your Retell agent
- Run one end-to-end test call

---

## 1. Deploy on [Vercel](https://vercel.com)

### 1.1 Import this repo

1. Go to [Vercel](https://vercel.com).
2. Create a new project.
3. Import this GitHub repository.
4. Deploy.

### 1.2 Add environment variables

In [Vercel](https://vercel.com) project settings, add the following:


| Variable                        | Required | What it is                                                  | How to get it                                                                     |
| ------------------------------- | -------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `GHL_PRIVATE_INTEGRATION_TOKEN` | Yes      | GHL API token used by this MCP                              | GHL -> Settings -> Private Integrations -> create integration -> copy token |
| `DEFAULT_LOCATION_ID`           | Yes      | Sub-account location ID this server is scoped to            | GHL sub-account -> Settings -> Business Information |
| `MCP_SHARED_SECRET`             | Yes      | Shared secret that authenticates MCP clients to your server | Choose your own secret (like a password) or generate with `openssl rand -hex 32`  |
| `DEFAULT_TIMEZONE`              | No       | Default timezone fallback                                   | Optional, default is `America/New_York`                                           |
| `ALLOWED_LOCATION_IDS`          | No       | Optional multi-tenant allowlist                             | Comma-separated list of location IDs                                              |


Private Integration scopes required:

- `contacts.readonly`
- `contacts.write`
- `calendars.readonly`
- `calendars/events.write`

Hardcoded in app (no env needed):

- GHL base URL: `https://services.leadconnectorhq.com`
- GHL API version header: `2021-07-28`

### 1.3 Confirm endpoint

Your MCP URL will be:

- `https://<your-vercel-domain>/mcp`

## 2. Connect MCP in Your Agent Platform

Choose one platform below. RetellAI and Vapi are separate alternatives.
This MCP server may also work with other MCP-capable platforms, but testing for this project was conducted using RetellAI and Vapi.

### Option A: RetellAI

### 2.1 Add MCP (matches Retell UI)

In RetellAI -> **Add MCP**:

- **Name**: `GHL MCP` (or any label)
- **URL**: `https://<your-vercel-domain>/mcp`
- **Timeout (ms)**: `10000`

Under **Headers**, add:

- `Authorization` = `Bearer <GHL_PRIVATE_INTEGRATION_TOKEN>`
- `locationId` = `<DEFAULT_LOCATION_ID>`
- `X-MCP-KEY` = `<MCP_SHARED_SECRET>`
- `calendarId` = `<GHL_CALENDAR_ID>`

Under **Query Parameters**:

- leave empty

Then click **Save**.

### 2.2 Add tools to your agent

In RetellAI -> **Add Tool**, add:

1. `ghl_create_contact`
2. `ghl_search_contacts`
3. `ghl_get_calendar_free_slots`
4. `ghl_create_appointment`

Recommended toggles:

- **Speak During Execution**: off
- **Speak After Execution**: on

Optional variable mapping:

- Store `ghl_create_contact.contactId` as `contact_id`
- Use `contact_id` for `ghl_create_appointment.contactId`

Important notes:

- `calendarId` header is required for calendar tools.
- `X-MCP-KEY` must exactly match your Vercel `MCP_SHARED_SECRET`.
- Get `calendarId` from GHL calendar settings.

---

### Option B: Vapi

### 2.3 Create the MCP tool

In Vapi:

1. Go to **Tools** (left menu).
2. Click **Create Tool**.
3. Select **MCP**.

Configure these fields:

- **Tool Name**: `ghl_mcp` (or any label)
- **Description**: `GHL MCP`
- **Server URL**: `https://<your-vercel-domain>/mcp`
- **Timeout**: `20` seconds (recommended)

Under **HTTP Headers**, add:

- `Authorization` = `Bearer <GHL_PRIVATE_INTEGRATION_TOKEN>`
- `locationId` = `<DEFAULT_LOCATION_ID>`
- `X-MCP-KEY` = `<MCP_SHARED_SECRET>`
- `calendarId` = `<GHL_CALENDAR_ID>`

Under **MCP Settings**:

- Select **Streamable HTTP (SHTTP)** (recommended)
- SSE is also supported if needed

Then click **Save**.

### 2.4 Assign the MCP tool to your assistant

After saving the MCP tool:

1. Go to **Assistants**.
2. Select your assistant.
3. Open the **Tools** dropdown/menu.
4. Assign the MCP tool you created.

Important:

- If the tool is not assigned to the assistant, calls will not use this MCP server.
- `X-MCP-KEY` must match your Vercel `MCP_SHARED_SECRET` exactly.
- `calendarId` header is required for calendar tools.

---

## 3. Recommended Agent Flow

1. `ghl_search_contacts`
2. `ghl_create_contact` (only if no match)
3. `ghl_get_calendar_free_slots`
4. `ghl_create_appointment`

### Copy/Paste system prompt tool policy

Use this in your Retell system prompt. You can customize it, but test with real calls before production.

```txt
Use MCP tools for all contact + booking actions.
Do not invent contact IDs, availability, or confirmations.
Never mention tool names, tool calls, or internal MCP/tool errors to the caller.

Flow:
1) Run ghl_search_contacts first using available phone/email/query.
2) If exactly one contact is found, use that contactId.
3) If no contact is found, collect missing phone/email and run ghl_create_contact.
4) If multiple contacts are found, disambiguate before booking.
5) Run ghl_get_calendar_free_slots and only offer returned slots.
6) Run ghl_create_appointment only with a confirmed contactId and an offered slot.

If no slots, ask for a different date range.
If tool error, say there is a technical issue and retry or escalate.
Confirm booking only after ghl_create_appointment succeeds.
```

---

## 4. Troubleshooting

- `401 AUTH_ERROR`: a required header is missing or invalid.
- `403` location access error: verify token access and `locationId`.
- Empty free slots:
  - verify `calendarId` header
  - verify date range + timezone
  - verify calendar availability in GHL