ghl-mcp-server-v2
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ghl-mcp-server-v2list my recent contacts"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ghl-mcp-server-v2 — The Definitive GoHighLevel MCP Server
A from-the-ground-up MCP server covering the full public GoHighLevel API surface: 667 unique operations enumerated from the complete official OpenAPI spec corpus (84 spec files, legacy + v3 tiers). 651 tools registered; the other 16 are explicit, itemized exceptions (see api-coverage-checklist.md) — never silent omissions.
Built 2026-07-16 in a Cowork session (orchestrator + 8 parallel domain-audit sub-agents), following the mcp-builder skill's four-phase workflow. TypeScript, stdio transport, multi-tenant (locationId/companyId are call-time parameters — nothing tenant-specific is hardcoded).
Why this exists
The previous production connector (MCP_Servers/_to_delete/ghl-mcp-server-v1-retired) was a thin wrapper with silently incomplete coverage. Confirmed failures, all fixed here and locked in as regression checks (verified per-domain in docs/audits/):
Old connector failure | This server |
|
|
|
|
| Root-caused: the API requires |
|
|
|
|
Single hardcoded | Version header resolved per operation from the spec that documents it (494 tools send |
Social | Schema verified faithful to spec; tool description carries a warning that the live endpoint had a server-side regression as of 2026-07-04 |
Related MCP server: ghl-mcp
Architecture — how "no silently dropped field" is guaranteed
Tools are generated from the official OpenAPI specs, not hand-transcribed:
scripts/extract-operations.mjsparses every spec file, fully dereferences$refs, dedupes byMETHOD /path(v3 spec variant preferred; legacy-only operations keep their legacyVersionheader), and emitssrc/generated/operations.jsonwith request schemas verbatim.src/registry.tsbuilds one MCP tool per operation: path/query/header params become top-level arguments; the request body schema is carried verbatim under abodyargument. Missing path-param declarations in the spec are inferred from the URL template.src/overrides/*.ts— eight domain-audit modules (one per sub-agent) carrying curated tool names, Version-header corrections, content-type overrides (multipart, form-urlencoded), agency-token warnings, and the 16 skip-with-reason exceptions.
Because the schema pipeline is mechanical, a field can only be missing if it is missing from GoHighLevel's own published spec — and the three known cases of that are documented in the audits (POST /contacts/search, object-record create/update, POST /forms/upload-custom-files), each exposed with a permissive body rather than dropped.
Setup
npm install
npm run build # tsc + copies src/generated into build/
npm start # stdio server
npm run inspect # MCP Inspector smoke testClient config (e.g. Claude Desktop / Cowork):
{
"mcpServers": {
"ghl-v2": {
"command": "node",
"args": ["<path>/ghl-mcp-server/build/index.js"],
"env": { "GHL_API_KEY": "...", "GHL_ENABLE_WRITES": "false" }
}
}
}Environment variables
Var | Default | Meaning |
| — | Private-integration token / OAuth access token. Env-only, never hardcoded. |
| unset = read-only | The dry-run safety gate. Unless set to |
| all | Comma-separated spec basenames (e.g. |
|
| Override for testing. |
|
| Request timeout. |
| (PPC corpus path) | Only used by |
Conventions
Tool names:
ghl_<resource>_<action>(snake_case, ≤64 chars), curated per domain (e.g.ghl_contact_update,ghl_opportunity_search,ghl_calendar_appointment_create,ghl_invoice_schedule_cancel).Annotations:
readOnlyHint(GET),destructiveHint(DELETE),idempotentHint(GET/PUT/DELETE),openWorldHintalways true.Multi-tenant: pass
locationId/companyId/altIdper call. ~44 platform ops require an agency-level (Company) token — their descriptions say so.Multipart uploads: pass file fields as
{ "filePath": "...", "filename?": "...", "mimeType?": "..." }insidebody; the server builds the multipart request.Responses:
structuredContent = { status, ok, data }plus pretty-printed text; errors return real HTTP status + body + actionable hints.
Deliverables map
api-coverage-checklist.md— all 667 operations, per-row status, exceptions itemized. This is the proof of coverage.docs/audits/*.md— the 8 domain audit reports (regression verifications, renames, spec bugs found).docs/evaluation.xml— 10 verified evaluation Q&A pairs (mcp-builder Phase 4 format).docs/generated-names.json—"METHOD /path"→ tool-name map.
Not done here (operator steps)
Live testing. This was a docs-driven build; no live GHL call was made. Smoke-test read-only against a real location, then enable writes deliberately.
Registering the server in a live MCP config (kept separate from the existing
ghl-mcp-serverregistration — do not overwrite it without deciding to retire the old one).Re-run
npm run extract && npm run buildwhen GHL ships API changes; the checklist regenerates from the same pipeline.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/zackscriven/ghl-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server