GoHighLevel MCP Starter
# GoHighLevel MCP Starter
Talk to your GoHighLevel sub-account from Claude, in plain English.
A small, readable [Model Context Protocol](https://modelcontextprotocol.io) server for
GoHighLevel API v2. Six tools, roughly 300 lines, MIT licensed. Built to be read in one
sitting and forked into whatever you actually need.
```
You: Who booked with us last week, and is Tuesday at 2 open?
Claude: [search_contacts] [list_calendars] [get_free_slots]
Three new contacts. Tuesday 2:00 is not offered, the calendar runs
at quarter past. 2:15 and 3:15 are open.
```
## Why another GHL MCP server
Most of them are a thin wrapper around the API surface. This one is opinionated about
the three things that actually bite you in production:
**1. It never hides an error.** GHL explains its failures in the response body, but
almost every wrapper throws away the body and surfaces a bare `400`. That single
decision turns a ten second fix into an hour of guessing. This client always reads the
body and puts the real message in the error.
**2. Writes are opt-in.** Every mutating tool is a dry run by default. It returns the
exact payload it *would* send so you can look at it first. Add `confirm: true` to
actually write. Letting a model create records in a live CRM on the first try is how
you end up with 40 test contacts named "John Doe" in a client account.
**3. It looks before it leaps.** `book_appointment` pulls live availability and checks
your requested time against it before writing, then tells you the real open slots if
you missed. GHL would just return a bare 400.
Plus [GOTCHAS.md](GOTCHAS.md), which is the list of GHL API quirks that cost real
debugging time. That file may be more valuable than the code.
## Tools
| Tool | What it does |
|---|---|
| `search_contacts` | Find contacts by name, email, or phone |
| `get_contact` | Fetch one contact by id |
| `create_contact` | Create a contact (dry run by default) |
| `list_calendars` | All calendars with ids and slot durations |
| `get_free_slots` | Real bookable times, epoch conversion handled |
| `book_appointment` | Verify the slot, then book (dry run by default) |
## Setup
**1. Install**
```bash
git clone https://github.com/rockurbusinesscs-ship-it/gohighlevel-mcp-starter.git
cd gohighlevel-mcp-starter
npm install
```
**2. Get a Private Integration Token**
In GoHighLevel, go to your **sub-account** (not the agency):
`Settings > Private Integrations > Create new integration`
Grant the scopes you need. For these six tools: contacts read/write, calendars read,
calendars/events write. Copy the token, it is shown once.
Use a test sub-account while you are learning. See Safety below.
**3. Configure**
```bash
cp .env.example .env
```
Fill in `GHL_TOKEN` and `GHL_LOCATION_ID`. The server loads `.env` automatically, and
env vars set by your MCP client take precedence, so either approach works.
**4. Connect to Claude**
Claude Code:
```bash
claude mcp add ghl -- node /absolute/path/to/gohighlevel-mcp-starter/src/index.js
```
Claude Desktop, in `claude_desktop_config.json`:
```json
{
"mcpServers": {
"ghl": {
"command": "node",
"args": ["/absolute/path/to/gohighlevel-mcp-starter/src/index.js"],
"env": {
"GHL_TOKEN": "your_token",
"GHL_LOCATION_ID": "your_location_id"
}
}
}
}
```
Restart, then ask it to search your contacts.
## Use cases
**Pipeline triage without the UI.** "Show me everyone tagged hot who has not been
contacted in 14 days." Reading a CRM conversationally is faster than clicking through
filters, and it is where most of the daily value is.
**Booking without the back and forth.** "Is Wednesday afternoon open, and book Sarah
into the first slot." The slot verification means it fails loudly with real options
instead of a mystery error.
**Data hygiene.** Point it at your contacts and ask what is malformed: missing emails,
phone numbers that are not E.164, duplicates. It is very good at spotting the mess.
**Onboarding automation.** Chain contact creation and booking into a single request
when a new client signs, with the dry run keeping you in the loop before anything
writes.
**Learning the API.** Honestly, this is the big one. Fork it, add a seventh tool
against an endpoint you care about, and you will understand GHL's API better in an
afternoon than a week of reading docs.
## Safety
- **Never commit `.env`.** It is gitignored. Check before you push anyway.
- **Use a test sub-account first.** A Private Integration Token can write to a real
client's CRM. Learn on data you can afford to break.
- **Keep the dry run.** If you remove the `confirm` gate, you have handed write access
to a language model that occasionally misreads intent.
- **One token, one location.** Do not reach for an agency token to avoid setting
`locationId`.
## Contributing
Found a gotcha not in [GOTCHAS.md](GOTCHAS.md)? That is the most valuable PR you can
send. Bug reports and new tools welcome too.
## License
MIT. Use it commercially, fork it, ship it in your product, no obligations.
---
Not affiliated with or endorsed by GoHighLevel / HighLevel Inc.
TDQS
Scored across 6 tools
Each tool targets a distinct resource and action: calendar slot retrieval, contact search/by-id/creation, calendar listing, and appointment booking. There is no ambiguity between tools; even related tools like list_calendars and get_free_slots serve clearly different purposes.
All tool names follow a consistent snake_case verb_noun pattern: get_free_slots, search_contacts, get_contact, create_contact, list_calendars, book_appointment. This makes the toolset predictable and easy to navigate.
With 6 tools, the server is well-scoped for a GoHighLevel starter integration, covering contact management and calendar/appointment workflows without unnecessary bloat. Each tool serves a clear purpose within this domain.
The toolset covers contact creation, retrieval, search, and appointment booking, but lacks contact update/delete operations and appointment cancellation/listing. These are notable gaps, especially for a CRM-related server, though the core workflow of finding/creating contacts and booking appointments is intact.