GHL Command — GoHighLevel MCP Server
Full GoHighLevel API access for Claude. 233 tools across 49 modules — manage contacts, conversations, pipelines, calendars, funnels, workflows, invoices, custom objects, webhooks, and more. Includes full workflow builder, funnel/page editor, form builder, pipeline builder, bulk operations, account export, and workflow cloning — capabilities no other GHL tool offers. Multi-tenant: one install can run the workflow builder across multiple clients' GHL accounts.
Distributed via npm as @elitedcs/ghl-mcp. Buyers install with one config block — no git, no Node.js setup, no terminal commands. Updates flow automatically (npx @latest re-resolves on every Claude restart).
Works with both the Claude Desktop App and Claude Code terminal — your choice.
License required. Get it at ghlcommand.com — $97/mo, covering UNLIMITED GoHighLevel sub-accounts on up to 3 machines (never billed per account). 30-day time-back guarantee: save 5+ hours on one client build or your first month back.
Try it FREE (read-only tier). Grab an instant free key at ghlcommand.com/free — 107 read-only tools on your own GHL account (89 before the one-login auditor unlock): the account-wide workflow audit (audit_workflows finds the silently broken references GHL never warns you about), account health, and every read across contacts, pipelines, funnels, and workflows. Write tools stay visible and answer with upgrade info. Buying later with the same email upgrades your key in place — 1 machine on free, 3 when you upgrade.
How this differs from HighLevel's official MCP. HighLevel ships an official Anthropic MCP that reads and writes your CRM (contacts, conversations, calendars, opportunities, payments, social) over the public API — it's free and it's good; use it for that. What it cannot do, because the public API doesn't expose it: build or edit workflows, build funnels/landing pages, or build forms. That's exactly what GHL Command does — the programmatic Workflow Builder, funnel/page builder, form builder, deep workflow cloning, the silent-failure audit_workflows, and Blueprint (build a whole client account from one intake — ships as a guided skill that installs itself automatically with this package; nothing to download), all on GHL's internal APIs. Official MCP = read/write your CRM. GHL Command = build and fix it. They stack fine together.
Bundled skills (install automatically). The package ships guided skills that teach Claude complete multi-step workflows on top of the raw tools. On every start the server installs/updates them into your ~/.claude/skills/ (never overwriting files you've edited — your version wins and is reported). Current skills: Blueprint — turn one client intake into a complete reviewed GHL account build; Clone Site — point at a live URL and get a rebranded, deploy-ready copy for a client, with a recorded rights declaration, a style-only lane when you have no rights, and a mandatory pre-launch report of every lead/booking/payment destination, borrowed testimonial and inherited claim still belonging to the original owner. Verify or repair any time by asking Claude to run install_skills, then fully restart Claude so new skills load.
Built by Elite DCs, LLC.
What Buyers Say
"I've already set it up, I'm using it and it works perfectly!"
— Andres G., paying customer
"Wow! That makes me VERY happy. Given what you've built (I can't wait to test it), I would have been willing to run it on Claude Desktop lol. But on my droplet, as an actual AI skill, even better."
— Garret W., paying customer (running it headless on a Linux droplet)
"That worked. Thank you."
— Ryan T., paying customer (bug reported Monday, fix shipped as v3.23.0 Tuesday, confirmed Tuesday)
"Thank you, Jerry. You're a star."
— Frankie B.
30+ releases on npm since launch (v3.6.0 → v3.34.0). Bugs get fixed in days, not quarters.
What Makes This Different
Most GHL integrations give you read access and basic CRUD. This server goes far beyond that — it includes capabilities that don't exist anywhere else, built on reverse-engineered internal APIs that GHL's public API doesn't expose.
| Programmatic Workflow Builder | The only tool on the market that can create, edit, and publish GHL workflows via code. GHL's public API has no workflow write endpoints — this uses their internal backend API (the same one their UI calls) to give Claude full workflow CRUD. Build entire automation sequences from a conversation. |
| Deep Workflow Cloning | Clone any workflow with full UUID remapping — every action, trigger, branch, and internal reference gets new IDs. No other tool can duplicate a workflow programmatically without ID collisions. |
| Funnel & Page Editor | Read and edit funnel page content — sections, elements, rows, CSS, tracking codes. Goes beyond the public API's list-only access. |
| Form Builder | Full form CRUD including field management, conditional logic, and auto-responder configuration via internal API. |
| Pipeline Builder | Create, edit, and delete pipelines and stages via internal API. The public API only lists pipelines — this lets Claude build them. |
| Template Deployment | Deploy a complete sub-account setup (tags, custom fields, pipelines, workflows, forms) from a single template. Set up a new client in minutes instead of hours. |
| Multi-Sub-Account Token Registry | Register multiple sub-accounts with their own API keys. Switch locations mid-session and the API key swaps automatically — no restart needed. |
| Full Account Export & Diff | Export an entire sub-account to JSON or compare two locations side-by-side. Useful for auditing, migration, and quality control. |
Everything else — CRM, conversations, calendars, invoices, bulk ops — works through GHL's official public API v2 with full read/write access.
What It Does
This MCP (Model Context Protocol) server connects Claude directly to GoHighLevel's API v2. Once installed, Claude can read and write to your GHL account — no browser, no Zapier, no middleware. Use it from the Claude Desktop App (no terminal needed) or from Claude Code in the terminal.
| CRM | Search, create, update, and delete contacts. Manage tags, notes, tasks. |
| Conversations | Read message threads, send SMS/email/WhatsApp, update message status. |
| Pipeline | Create and manage opportunities. Move deals through stages. |
| Scheduling | Check availability, book appointments, manage calendars. |
| Automation | Full workflow builder — create, read, edit, and publish workflows. See every action, trigger, condition, and branch. Clone workflows with deep ID remapping. |
| Marketing | Funnel/page editor — read and edit existing funnel page content (sections, elements, CSS). Full form builder — read/edit all fields, conditional logic, auto-responder. |
| Pipelines | Full pipeline builder — create, edit, delete pipelines. Add, remove, rename, reorder stages. |
| Bulk Ops | Batch tag, untag, update fields, enroll in workflows, or delete contacts — all rate-limited. |
| Backup | Export entire sub-account to JSON. Compare two locations side-by-side for auditing. |
| Multi-Location | Switch between sub-accounts mid-session. Token registry stores per-location API keys for seamless switching. |
| Billing | Create/send/void invoices, record payments, view orders and subscriptions. |
| Content | Manage blog posts, social media posts, courses, media files. |
| Custom Objects | Full CRUD on custom object schemas and records. Manage associations. |
| Estimates & Coupons | Create/send estimates, manage promo codes. |
| Webhooks | Create and manage webhook subscriptions. |
| Documents | List, send, and manage documents/contracts. |
| Admin | View/update sub-accounts, manage custom fields, custom values, location tags, users. |
Quick Start (5 minutes)
1. Buy a license
ghlcommand.com — $97/mo, every sub-account you manage. License key arrives by email within 1-2 minutes.
2. Install in Claude Desktop App
Open Claude Desktop. Click Claude menu (top-left) → Settings... → Developer → Edit Config. Paste this block (or merge into your existing mcpServers if you have other MCP servers):
{
"mcpServers": {
"ghl": {
"command": "npx",
"args": ["-y", "@elitedcs/ghl-mcp@latest"]
}
}
}
Save the file. Quit Claude completely (Cmd+Q on Mac) and reopen.
Claude Code (terminal) instead? One command:
claude mcp add --scope user -t stdio ghl -- npx -y @elitedcs/ghl-mcp@latest
Then restart Claude Code.
3. Activate
After restart, GHL Command is loaded but locked. Type this in Claude (replace the four placeholders with your real values):
Run setup_ghl_mcp to activate GHL Command:
email: YOUR_PURCHASE_EMAIL
license_key: YOUR_LICENSE_KEY
ghl_api_key: YOUR_GHL_API_KEY
ghl_location_id: YOUR_LOCATION_ID
Approve the tool call. Server validates your license, verifies your GHL credentials, writes them to a per-user config file. Quit Claude one more time and reopen — the full core toolset is now unlocked (233 tools total with the optional Workflow Builder Firebase add-on).
4. Try it
"List my GHL contacts"
"Show my pipelines"
"What calendars do I have?"
Full step-by-step setup with screenshots: elitedcs.com/ghl-mcp-setup-guide.html
Get Your GHL API Key
CRITICAL: Sub-Account Level Only
Private Integrations in GHL are scoped to individual sub-accounts, NOT to the agency level. You must create a separate Private Integration inside each sub-account you want to connect. An API key created in Sub-Account A will return 403 Forbidden if you try to use it with Sub-Account B's Location ID.
Your API key can only be copied ONCE — at the moment you create the integration. After you leave that screen, the key is permanently masked and cannot be retrieved. If you lose it, you must delete the integration and create a new one.
- Log into GoHighLevel
- Switch into the specific sub-account you want to connect (not the agency view)
- Go to Settings > Integrations
- Click Private Integrations > Create Private Integration
- Name it
Claude Code MCP
- Enable all scopes/permissions you want Claude to access
- Immediately copy the API Key and pass it to
setup_ghl_mcp as ghl_api_key — you will not be able to see it again
Find Your Location ID
Your Location ID (sub-account ID) is in the GHL URL when you'''re inside a sub-account:
https://app.gohighlevel.com/v2/location/YOUR_LOCATION_ID/dashboard
Enable the Workflow Builder
The builder + cloner + validator tools (workflow builder, funnel builder, form builder, pipeline builder, workflow cloner, validate_workflow) use GHL's internal API and require Firebase credentials. Without them, the other 179 tools work fine — you just won't have workflow/funnel/form/pipeline editing. This is the flagship feature: do this step.
One-click capture (v3.49.0+, the supported path):
- In Claude, ask:
Run capture_firebase_interactive. Your installed Chrome opens a dedicated window on the GHL login page (no browser download; it never touches your daily browsing profile).
- Log into your GHL account in that window. That's the whole job — the tool reads the three Firebase values itself, validates them against Firebase, and saves them. If the call says it's still waiting, finish logging in and run the same tool again.
- Restart Claude. The Firebase-gated tools are live.
Firebase refresh tokens can rotate. If workflow tools stop working after a few weeks (health_check shows Firebase auth: FAIL), just re-run capture_firebase_interactive — after your first login it re-captures silently, no window at all.
Console-paste fallback (no Chrome/Edge installed, the window path fails, or you're capturing a CLIENT account for multi-tenant)
- In Claude, ask:
Run auto_capture_firebase_script. It returns a small browser-console script.
- In Chrome, open a tab logged into your GHL account. Press F12 (Windows) or Cmd+Option+I (Mac), click the Console tab, paste the script, press Enter. If Chrome blocks the paste, type
allow pasting in the Console first, then paste again.
- The script extracts the three Firebase values and copies them to your clipboard as JSON.
- Back in Claude:
Run enable_workflow_builder and paste the JSON into the firebase_paste field. (First-time setup? You can instead add firebase_paste as a fifth field on setup_ghl_mcp.)
- Restart Claude. The Firebase-gated tools are live.
Screenshots and the same script behind a copy button: elitedcs.com/ghl-mcp-firebase
Manual fallback (locked-down browsers that block console pasting or clipboard access)
- Open
app.gohighlevel.com in Chrome (or any Chromium browser), log in.
- Open DevTools (Cmd+Opt+I on Mac, F12 on Windows) → Application tab → IndexedDB in the left panel.
- Expand:
firebaseLocalStorageDb → firebaseLocalStorage.
- Find the row whose key starts with
firebase:authUser:.
- The part between
authUser: and :[DEFAULT] is your ghl_firebase_api_key (starts with AIza).
- Inside that row's value object:
uid is your ghl_user_id.
- Inside
value.stsTokenManager.refreshToken is your ghl_firebase_refresh_token.
Then in Claude, run enable_workflow_builder (or re-run setup_ghl_mcp with your license fields) passing the three values individually as ghl_user_id, ghl_firebase_api_key, and ghl_firebase_refresh_token.
Working in Clients' Accounts (Multi-Tenant)
The public-API tools work in any sub-account you have a Private Integration key for. The workflow builder (and every Firebase-gated tool) is different: GHL Firebase refresh tokens are company-scoped, so your own token can't build workflows inside a client's GHL — even if you're an admin user there. Without the client's own Firebase, those accounts are effectively read-only.
To unlock full builder access across multiple clients from one install:
-
Register the client's sub-account key so the public API works there:
register_location
locationId: CLIENT_LOCATION_ID
name: "Client Name"
apiKey: pit-... (a Private Integration created INSIDE the client's sub-account)
This auto-detects and stores the owning companyId.
-
Capture the client's Firebase values from a browser session logged into their account (run auto_capture_firebase_script the same way as above, but paste it into a tab logged into the client's GHL).
-
Register the client's company Firebase:
register_company_firebase
companyId: CLIENT_COMPANY_ID (best-effort — see note)
name: "Client Name"
ghl_firebase_refresh_token: FROM_STEP_7
ghl_user_id: FROM_STEP_6
test_location_id: CLIENT_LOCATION_ID (optional — runs a live check that it works)
companyId is best-effort. GHL's agency-URL company ID is a different identifier than the internal one used for sub-accounts. The tool decodes the company ID the Firebase token itself authenticates as and stores the entry under that, so you don't have to track down the exact internal ID — pass whatever you have (e.g. from register_location's output) and it self-corrects.
-
Switch and build: switch_location CLIENT_LOCATION_ID swaps both the API key and the Firebase auth automatically. The workflow builder now operates in the client's account. Switching back to your own location restores your home Firebase.
list_registered_locations shows every location, its company, and which companies have Firebase wired up. health_check reports the active company. Rotated tokens are saved back to the correct client, never overwriting your own.
Server / Headless Deployment
GHL Command runs headless — Linux droplet, container, or behind an MCP gateway (MetaMCP, etc.). One license covers every GoHighLevel sub-account you manage, on up to 3 of your own machines. No per-account fees. A server counts as one machine; restarts never consume extra activations.
Highlights (full guide: docs/HEADLESS.md):
Tools
v3.10.0 adds Email Templates (list_email_templates, create_email_template, update_email_template) — Claude can now create new HTML email templates and save content into them via the public API. Templates power both standalone marketing emails and workflow email actions. Delete + rename remain UI-only (no public-API endpoint exists).
CRM & Contacts (15 tools)
search_contacts | Search contacts by name, email, phone, or tag |
get_contact | Get full contact details by ID |
create_contact | Create a new contact |
update_contact | Update contact fields |
delete_contact | Delete a contact |
upsert_contact | Create or update a contact (match by email/phone) |
add_contact_tags | Add tags to a contact |
remove_contact_tags | Remove tags from a contact |
get_contact_tasks | List tasks for a contact |
create_contact_task | Create a task on a contact |
get_contact_notes | List notes on a contact |
create_contact_note | Add a note to a contact |
get_contact_appointments | List a contact's appointments |
add_contact_to_workflow | Add a contact to a workflow |
remove_contact_from_workflow | Remove a contact from a workflow |
Conversations & Messaging (8 tools)
search_conversations | Search conversation threads |
get_conversation | Get a specific conversation |
create_conversation | Start a new conversation |
get_messages | Read messages in a conversation |
send_message | Send SMS, email, or WhatsApp message |
add_inbound_message | Log an inbound message |
update_message_status | Update read/unread status |
get_message | Get a specific message |
Opportunities & Pipelines (7 tools)
search_opportunities | Search deals across pipelines |
get_opportunity | Get opportunity details |
create_opportunity | Create a new deal |
update_opportunity | Update deal fields or move stages |
delete_opportunity | Delete a deal |
update_opportunity_status | Change opportunity status (won/lost/open) |
get_pipelines | List all pipelines and their stages |
Calendars & Scheduling (11 tools)
get_calendars | List all calendars |
get_calendar | Get calendar details |
create_calendar | Create a new calendar |
update_calendar | Update calendar settings |
delete_calendar | Delete a calendar |
get_free_slots | Check available time slots |
get_calendar_events | List events on a calendar |
get_appointment | Get appointment details |
create_appointment | Book an appointment |
update_appointment | Update an appointment |
delete_appointment | Cancel an appointment |
Locations & Sub-Accounts (15 tools)
get_location | Get sub-account details |
update_location | Update sub-account settings |
search_locations | Search locations |
get_location_tags | List all tags in a location |
create_location_tag | Create a new tag |
update_location_tag | Update an existing tag |
delete_location_tag | Delete a tag |
get_custom_fields | List all custom fields |
create_custom_field | Create a new custom field |
update_custom_field | Update a custom field |
delete_custom_field | Delete a custom field |
get_custom_values | List all custom values |
create_custom_value | Create a new custom value |
update_custom_value | Update a custom value |
delete_custom_value | Delete a custom value |
Custom Objects (7 tools)
list_custom_objects | List all custom object schemas |
get_custom_object | Get a custom object schema by key |
search_custom_object_records | Search records of a custom object |
get_custom_object_record | Get a single record by ID |
create_custom_object_record | Create a new record |
update_custom_object_record | Update an existing record |
delete_custom_object_record | Delete a record |
Associations (3 tools)
list_associations | List associations for a custom object record |
create_association | Link a record to a contact/opportunity/other record |
delete_association | Remove an association |
Invoices & Billing (8 tools)
list_invoices | List all invoices |
get_invoice | Get invoice details |
create_invoice | Create a new invoice |
update_invoice | Update an invoice |
send_invoice | Send invoice to recipient |
void_invoice | Void an invoice |
record_invoice_payment | Record a payment against an invoice |
delete_invoice | Delete an invoice |
Estimates (6 tools)
list_estimates | List estimates/quotes |
get_estimate | Get estimate details |
create_estimate | Create a new estimate |
update_estimate | Update an estimate |
delete_estimate | Delete an estimate |
send_estimate | Send an estimate to a contact |
Coupons (5 tools)
list_coupons | List all coupons/promo codes |
get_coupon | Get coupon details |
create_coupon | Create a new coupon |
update_coupon | Update a coupon |
delete_coupon | Delete a coupon |
Webhooks (5 tools)
list_webhooks | List all webhook subscriptions |
get_webhook | Get webhook details |
create_webhook | Create a new webhook |
update_webhook | Update a webhook |
delete_webhook | Delete a webhook |
Documents (4 tools)
list_documents | List documents and contracts |
get_document | Get document details and signature status |
delete_document | Delete a document |
send_document | Send a document for e-signature |
Payments (4 tools)
get_orders | View all orders |
get_order | Get order details |
get_subscriptions | List active subscriptions |
get_transactions | View transaction history |
Workflow Builder (9 tools) — Internal API
This is the flagship feature. GHL's public API has zero workflow write endpoints. These tools use GHL's internal backend API — the same API their own UI calls — reverse-engineered to give Claude full workflow CRUD. No other GHL integration, Zapier connector, or third-party tool can create or edit workflows programmatically. Requires additional Firebase auth setup (see "Enable Workflow Builder" in Quick Start above).
list_workflows_full | List all workflows with full metadata, versions, and permissions |
get_workflow_full | Get complete workflow internals: every action, trigger, condition, if/else branch, email template, SMS body |
create_workflow | Create a new workflow from scratch (starts as draft) |
update_workflow_actions | Add, edit, or remove actions, triggers, and branches in an existing workflow |
delete_workflow_full | Permanently delete a workflow |
publish_workflow | Publish a draft workflow to make it active |
get_trigger_registry | Discover GHL's marketplace trigger apps (Zoom, WooCommerce, Shopify, etc.) and their available trigger templates |
validate_workflow | Pre-flight validation: scans every action and trigger for references to pipelines, stages, custom fields, users, and other workflows; verifies each ID exists. Catches the silent-failure bug where invalid IDs make GHL skip subsequent actions |
build_goal_event | Build a correctly-shaped goal-event node. Goals sit inline in the action chain — when the goal condition fires (e.g., review_request_clicked), the configured action runs (default: exit the workflow). Returns a workflow_goal node ready to wire into your actions array |
What you can build: Complete automation sequences — lead nurture drip campaigns, appointment reminder sequences, onboarding flows, re-engagement workflows, internal notification chains, conditional exit workflows with goal events. Tell Claude what you want and it builds the workflow action by action.
Supported action types: sms, email, add_contact_tag, remove_contact_tag, update_contact_field, wait, if_else, webhook, create_opportunity, custom_code, add_notes, internal_notification, task_notification, remove_from_workflow, workflow_goal, and more.
Supported trigger types: All 57 native GHL trigger types are deeply typed with their own Zod variant. 42 have full field-path documentation (opportunity_*, form_submission, contact_changed, survey_submission, birthday_reminder, mailgun_email_event, and 36 others). 4 have partial docs, 2 are fieldless by design, 9 have type-only discrimination pending field-path capture. A permissive fallback handles any future trigger types GHL ships, so reads never crash. Plus 434 marketplace trigger entries across 85 third-party apps — query them via get_trigger_registry.
Pipeline Builder (5 tools) — Internal API
Also uses GHL's internal API. The public API only lists pipelines — this lets Claude create, edit, and delete pipelines and their stages.
list_pipelines_full | List all pipelines with full stage details, positions, and display settings |
get_pipeline_full | Get a single pipeline with complete stage configuration |
create_pipeline | Create a new pipeline with stages |
update_pipeline | Update name, add/remove/rename/reorder stages |
delete_pipeline | Permanently delete a pipeline |
Bulk Operations (5 tools)
bulk_add_tags | Add tags to multiple contacts at once (rate-limited) |
bulk_remove_tags | Remove tags from multiple contacts (rate-limited) |
bulk_update_contacts | Update the same fields on multiple contacts (rate-limited) |
bulk_add_to_workflow | Enroll multiple contacts into a workflow (rate-limited) |
bulk_delete_contacts | Delete multiple contacts (rate-limited, requires safety confirmation) |
Account Export & Comparison (2 tools)
export_account | Full sub-account backup — contacts, pipelines, workflows, funnels, forms, fields, tags, calendars, users |
compare_locations | Side-by-side diff of two sub-accounts for auditing or migration |
Location Switcher & Token Registry (6 tools)
get_current_location | Show which sub-account is active |
switch_location | Switch to a different sub-account mid-session (auto-swaps API key from registry) |
list_available_locations | List all accessible sub-accounts |
register_location | Add a sub-account and its API key to the token registry |
unregister_location | Remove a sub-account from the token registry |
list_registered_locations | List all sub-accounts stored in the token registry |
Workflow Cloner (1 tool)
Deep-clones a workflow with full UUID remapping. Every action, trigger, branch, and internal cross-reference gets a new unique ID. GHL has no built-in way to duplicate a workflow programmatically — this is the only tool that can.
clone_workflow | Deep clone a workflow with new UUIDs for all actions, triggers, and references |
Template Deployer (3 tools)
Deploy a complete sub-account setup from a pre-built template — tags, custom fields, pipelines, workflows, and forms — in one step. Claude walks the user through a questionnaire, then deploys everything. Includes dry-run mode to preview changes before applying.
list_templates | List available setup templates (clinic, med spa, dental, etc.) |
get_template_questionnaire | Get the questionnaire for a template — present to user conversationally |
deploy_template | Deploy a complete sub-account setup from a template (tags, fields, pipelines, workflows, forms). Supports dry-run mode. |
Setup & Diagnostics (3 tools)
get_mcp_version | Check installed version against the latest published to npm. Confirms an upgrade landed after restarting Claude. Available even before GHL credentials are configured. |
health_check | Run a full health check: npm registry + version status, GHL API key validity, default location reachability, Firebase auth status, token registry presence. Use when something feels broken. |
enable_workflow_builder | Add Firebase credentials to an existing install to unlock 54 additional Firebase-gated tools (workflow builder, funnel builder, form builder, pipeline builder, workflow cloner, smart lists, reputation, email campaigns, email templates, memberships, validate_workflow). No need to re-enter license / API key / location ID. Run this any time after the basic setup, on the buyer's schedule. |
Other Modules
| Social Planner | 5 | Create, list, delete posts, view connected accounts |
| Businesses | 5 | Full CRUD on business entities |
| Blogs | 5 | Posts, authors, categories, URL slugs |
| Funnels (public API) | 2 | List funnels and their pages |
| Forms (public API) | 2 | List forms and view submissions |
| Surveys | 2 | List surveys and view submissions |
| Users | 2 | List and view team members |
| Media | 2 | Browse and delete media files |
| Campaigns | 1 | List campaigns |
| Workflows (public API) | 1 | List all workflows |
| Courses | 1 | List courses |
| Emails | 1 | List email campaigns |
| Trigger Links | 1 | List trigger links |
How It Works
┌──────────────────┐ ┌──────────────────┐
│ Claude Desktop │ │ Claude Code │
│ App (GUI) │ │ (Terminal) │
└────────┬─────────┘ └────────┬─────────┘
│ │
└──────────┬───────────┘
│ MCP Protocol (stdio)
┌───────────────────┴─────────────────────┐
│ GHL MCP SERVER │
│ │
│ ┌──────────┐ ┌──────────┐ ┌────────┐ │
│ │ Contacts │ │ Calendar │ │Invoices│ │
│ │ 15 tools │ │ 11 tools │ │8 tools │ │
│ └────┬─────┘ └────┬─────┘ └───┬────┘ │
│ └─────────────┼───────────┘ │
│ ┌──────┴──────┐ │
│ │ GHL Client │ │
│ └──────┬──────┘ │
├─────────────────────┼───────────────────┤
│ ↓ │
│ GoHighLevel API v2 │
│ https://services.leadconnectorhq.com │
└─────────────────────────────────────────┘
Architecture
src/index.ts — MCP server entry, startup API key validation, tool registration.
src/ghl-client.ts — HTTP client for GHL API v2. Returns Promise<unknown> (no generic as T casts). Automatic retry with exponential backoff on 429/5xx/network errors. 30-second timeout with clear error messages.
src/workflow-builder-client.ts — Internal API client for workflow CRUD. Firebase auth with thread-safe token refresh (promise lock), retry/backoff, Zod-validated WorkflowFull responses, and pre-flight validateActionChain() that catches common action attribute errors before GHL can silently fail.
src/api-schemas.ts — Zod response schemas for contacts, pipelines, and calendars. Runtime validation on the most-used API paths.
src/workflow-action-types.ts — Discriminated union types for all 11 documented workflow action types. Compile-time enforcement of action-specific attributes (SMS needs body, email needs subject+html, etc.).
src/tool-helpers.ts — safeTool() wrapper (automatic try/catch + JSON formatting for 127 tools), response helpers, error formatting.
src/token-registry.ts — Per-location API key storage, Zod-validated on load with corruption backup.
src/tools/index.ts — Type-safe registry array. Compiler catches missing tool registrations.
src/tools/*.ts — One file per GHL domain. Most use safeTool() for zero-boilerplate handlers.
Build System
Uses esbuild for production builds (not tsc). TypeScript 5.9.3 + MCP SDK types cause tsc to run out of memory at 4GB+. esbuild bundles in ~5ms with zero memory issues.
npm run build
npm run dev
Data Flow
User prompt → Claude Code → MCP tool call → GHL Client → GHL API → JSON response → Claude Code → User
Every tool returns structured JSON. Claude interprets the response and presents it naturally. No data is stored locally — it's a pass-through to GHL's API.
Project Structure
ghl-command-mcp/
├── src/
│ ├── index.ts # MCP server entry point + startup validation
│ ├── ghl-client.ts # GHL API v2 HTTP client (retry/backoff, returns unknown)
│ ├── workflow-builder-client.ts # Internal API client (Firebase auth, Zod-validated responses)
│ ├── workflow-action-types.ts # Discriminated union types for workflow actions
│ ├── api-schemas.ts # Zod response schemas for contacts, pipelines, calendars
│ ├── token-registry.ts # Per-location API key storage (Zod-validated on load)
│ ├── tool-helpers.ts # safeTool() wrapper, response helpers, error formatting
│ └── tools/
│ ├── index.ts # Type-safe tool registry (compiler-checked)
│ ├── contacts.ts # 15 tools — CRM & contact management
│ ├── conversations.ts # 8 tools — messaging (SMS, email, WhatsApp)
│ ├── opportunities.ts # 7 tools — pipeline & deal management
│ ├── calendars.ts # 11 tools — scheduling & appointments
│ ├── locations.ts # 15 tools — sub-accounts, custom fields/values, tags
│ ├── invoices.ts # 8 tools — invoicing & payment recording
│ ├── custom-objects.ts # 7 tools — custom object schema & record CRUD
│ ├── estimates.ts # 6 tools — estimates/quotes
│ ├── social-planner.ts # 5 tools — social media management
│ ├── businesses.ts # 5 tools — business entity management
│ ├── blogs.ts # 5 tools — blog management
│ ├── coupons.ts # 5 tools — promo code management
│ ├── webhooks.ts # 5 tools — webhook subscriptions
│ ├── payments.ts # 4 tools — orders, subscriptions, transactions
│ ├── documents.ts # 4 tools — document & contract management
│ ├── associations.ts # 3 tools — custom object associations
│ ├── funnels.ts # 2 tools — funnel & page listing
│ ├── forms.ts # 2 tools — forms & submissions
│ ├── surveys.ts # 2 tools — surveys & submissions
│ ├── users.ts # 2 tools — team members
│ ├── media.ts # 2 tools — media file management
│ ├── campaigns.ts # 1 tool — campaign listing
│ ├── workflows.ts # 1 tool — workflow listing
│ ├── courses.ts # 1 tool — course listing
│ ├── emails.ts # 1 tool — email campaign listing
│ ├── trigger-links.ts # 1 tool — trigger link listing
│ ├── workflow-builder.ts # 6 tools — full workflow CRUD (internal API)
│ ├── funnel-builder.ts # 10 tools — funnel/page builder (internal API)
│ ├── form-builder.ts # 5 tools — form builder (internal API)
│ ├── pipeline-builder.ts # 5 tools — pipeline/stage builder (internal API)
│ ├── bulk-operations.ts # 5 tools — batch contact operations
│ ├── account-export.ts # 2 tools — backup & location comparison
│ ├── workflow-cloner.ts # 1 tool — deep workflow cloning
│ ├── location-switcher.ts # 6 tools — multi-location support + token registry
│ └── template-deployer.ts # 3 tools — deploy sub-account from template (Zod-validated)
├── templates/
│ ├── clinic-medspa.json # Clinic/Med Spa blueprint
│ └── action-schemas.json # Mandatory workflow action attribute schemas
├── dist/ # Compiled JavaScript (npm-published bundle)
├── bin/ghl-mcp.js # npm bin entry point
├── .github/workflows/publish.yml # GitHub Actions npm-publish workflow
├── package.json # @elitedcs/ghl-mcp
├── tsconfig.json
├── CLAUDE.md # Claude Code project instructions
├── CHANGELOG.md
├── CONTRIBUTING.md # Contributor guide
├── .gitignore
└── README.md
# Legacy (kept for self-hosted dev workflows; buyers don't need these):
# setup.sh, setup-wizard.mjs, start-mcp.example.sh
Known Limitations
These are GHL features the MCP server does not currently support. In most cases, the GHL API either doesn't expose these endpoints or the feature requires browser-level interaction.
| Contact deduplication | No merge or dedup tool. search_contacts can find potential duplicates by name/email/phone, but merging must be done manually in the GHL UI. |
| Account auditing | No one-click "find what's broken" scanner. export_account dumps full sub-account data and compare_locations diffs two accounts — Claude can analyze the output to spot issues, but it's not a turnkey audit button. |
| SMS/email templates | No template CRUD. You can send messages and build email actions in workflows, but managing reusable message templates isn't supported. |
| Payment gateway config | Read-only access to orders, subscriptions, and transactions. No Stripe/payment gateway setup or configuration. |
| Phone & call tracking | No call tools. VoIP, call tracking, and phone number management are not available via the API. |
| Memberships & communities | Not supported. GHL's membership/community features don't have public API endpoints. |
| Reporting & analytics | No dashboard or reporting tools. Use export_account for raw data, but there are no built-in analytics queries. |
| Trigger links | List only — no create, update, or delete. |
| Campaigns | List only — no create, update, or delete. |
| Courses | List only — no create, update, or delete. |
| Workflow builder auth | Requires Firebase credentials extracted from browser DevTools. The refresh token may rotate, requiring re-extraction. |
Contributing: If you'd like to help close any of these gaps, see CONTRIBUTING.md.
Security
This MCP server is safe to share via GitHub.
| API Keys | Stored in a per-user credentials file (~/Library/Application Support/elitedcs-ghl-mcp/credentials.json on Mac) at chmod 0600. Never in code, never committed. |
| License validation | Checked at setup_ghl_mcp against the elitedcs.com license server, then cached as a signed attestation (~30 days). The server renews the attestation in the background as expiry approaches — never per-request, and your GHL keys are never sent to us. |
| Multi-user | Each user brings their own license key + GHL API key. Complete account isolation. |
| Scope | The server only talks to GHL's API, the elitedcs.com license server (setup + periodic attestation renewal), and npm's registry (startup version banner — GHL_MCP_DISABLE_UPDATE_CHECK=1 to disable). No filesystem access beyond its config dir, no shell commands. |
| Permissions | Controlled by your GHL Private Integration scopes. Disable what you don't need. |
Reliability & Type Safety
This server has been through a rigorous, multi-pass audit for production reliability (v2.4.0–v2.7.0). Here's what's in place:
| Retry with backoff | Both HTTP clients automatically retry on 429 rate limits, 5xx server errors, and transient network failures (ECONNRESET, ETIMEDOUT). 3 retries with exponential backoff. Respects Retry-After headers. |
| Clear error messages | Timeouts show "Request timeout (30s): GET /path" instead of cryptic abort errors. API errors include status code, method, path, and response body. |
| Zod-validated responses | Critical API paths (contacts, pipelines, calendars, workflows) validate response structure at runtime with Zod schemas. Malformed responses throw immediately with clear errors instead of silently passing garbage. |
| Zod-validated config | Token registry (.ghl-tokens.json) and template files are validated against Zod schemas on load. Corrupted files are backed up and reported, not silently accepted. |
| Pre-flight workflow validation | validateActionChain() checks action attributes before sending to GHL — catches missing body on SMS, missing subject/html on email, missing pipelineId/stageId on create_opportunity, and more. Prevents GHL's silent failure mode where bad actions kill all subsequent steps. |
| Delete confirmation | 10 high-risk destructive operations (delete_contact, delete_workflow, delete_pipeline, delete_funnel, etc.) require confirm: "DELETE" parameter. Prevents accidental deletion. |
| Thread-safe token refresh | Firebase token refresh uses a promise-based lock — concurrent requests share one refresh instead of racing. Failed refresh clears the cache immediately instead of leaving a stale token for 55 minutes. |
| Startup validation | Server validates the API key at startup (non-blocking) and logs a clear warning if it's invalid. |
| Type-safe registration | Tool modules are registered via a typed array — the compiler catches missing registrations. |
| Honest types | HTTP client methods return Promise<unknown>, not Promise<T>. No as T casts on JSON.parse. The type system never lies about response shapes. |
Updates
Automatic. Every Claude restart, npx -y @elitedcs/ghl-mcp@latest re-resolves the latest published version. When v3.0.1 ships, every buyer is on it next time they reopen Claude. Zero action required.
To pin a specific version (e.g. for stability), change @latest to @3.0.0 in your MCP config.
Contributing
Source repo is private. Contributors need an invitation from drjerryrelth. The npm-published artifact is open; the build/source pipeline is not.
For contributors with repo access:
Environment Variables
GHL_API_KEY | Yes | Your GHL Private Integration API key. Must be created inside the sub-account you're connecting to (not at the agency level). Can only be copied once at creation. |
GHL_LOCATION_ID | No | Default sub-account ID. Must match the sub-account where you created the API key. Saves you from passing it with every tool call. |
GHL_USER_ID | No* | Your GHL user ID. Required for workflow builder tools. |
GHL_FIREBASE_API_KEY | No* | Firebase API key from GHL's auth system. Required for workflow builder tools. |
GHL_FIREBASE_REFRESH_TOKEN | No* | Firebase refresh token. Required for workflow builder tools. May rotate periodically. |
GHL_ENABLED_MODULES | No | Comma-separated module names to limit which tool groups register at startup (e.g. contacts,conversations,locations). Unset = every module registers (default). See "Reducing context / token usage" below. |
GHL_ENABLED_TOOLS | No | Comma-separated individual tool names to register (e.g. search_contacts,get_contact,update_custom_value). Set alongside GHL_ENABLED_MODULES to add specific tools on top of whole-module enables. |
*Required only for the workflow builder (internal API) tools. The standard API tools work without these.
Reducing context / token usage
Every registered MCP tool's schema is shipped to the model on every message. With 233 tools that's a meaningful per-message context cost even in chats that never touch GHL. If you only use a slice of GHL Command, restrict the tool surface with GHL_ENABLED_MODULES and/or GHL_ENABLED_TOOLS:
// Claude Desktop config — enable whole modules
"env": {
"GHL_API_KEY": "pit-...",
"GHL_LOCATION_ID": "...",
"GHL_ENABLED_MODULES": "contacts,conversations,locations,custom-objects"
}
// Or pin to individual tools
"env": {
"GHL_API_KEY": "pit-...",
"GHL_LOCATION_ID": "...",
"GHL_ENABLED_TOOLS": "search_contacts,get_contact,update_custom_value"
}
Rules of the road:
- Neither set → every tool registers (default, backward compatible — your existing config keeps working unchanged).
GHL_ENABLED_MODULES only → register tools in those modules.
GHL_ENABLED_TOOLS only → register only those exact tool names.
- Both set → register the union: a tool registers if its module is in
GHL_ENABLED_MODULES OR its name is in GHL_ENABLED_TOOLS. (Whole modules plus a few extra tools.)
- Whitespace and commas both work as separators. Matching is case-insensitive.
- Always-on tools register regardless of the allowlist so setup and recovery still work:
setup_ghl_mcp, request_license, get_mcp_version, auto_capture_firebase_script, enable_workflow_builder, health_check.
- Unrecognized module/tool names log a one-line WARNING to stderr and are ignored. Startup never aborts.
- On startup with the allowlist active, the server logs one summary line:
Tool allowlist active: registered N of M tools (...).
Valid module names (use these in GHL_ENABLED_MODULES):
contacts, conversations, opportunities, calendars, locations, workflows, funnels, forms, surveys, payments, products, invoices, campaigns, users, media, social-planner, courses, businesses, blogs, emails, trigger-links, custom-objects, associations, estimates, coupons, webhooks, documents, bulk-operations, account-export, template-deployer, workflow-builder, funnel-builder, form-builder, pipeline-builder, workflow-cloner, smart-lists, reputation, email-campaigns, email-builder, memberships, validators, diagnostics, location-switcher
Turning tools off (security)
Some teams keep certain operations human-only — for example sub-account management or messaging — so that a prompt-injected or misbehaving AI session can never touch them. Two controls exist for exactly that:
1. Sub-account create/delete is OFF by default. create_sub_account and delete_sub_account do not register unless you explicitly opt in:
"env": {
"GHL_ENABLE_ACCOUNT_ADMIN": "1" // exactly "1" — nothing else enables it
}
The setup wizard asks this question during install (default No). Listing these tools in GHL_ENABLED_TOOLS does not bypass the flag.
2. Any tool or module can be switched off with a deny-list:
"env": {
"GHL_DISABLED_TOOLS": "send_message,bulk_delete_contacts",
"GHL_DISABLED_MODULES": "snapshots"
}
How the deny-list behaves:
- Deny wins over everything — the allowlist, the always-on set, and
GHL_ENABLE_ACCOUNT_ADMIN. A denied tool never registers: it is invisible to the model, so it cannot be called or discovered from a conversation.
- There is deliberately no tool to change gating from inside Claude. Turning something back on requires editing your config file and fully restarting Claude — a human action.
- Recovery core stays reachable:
setup_ghl_mcp, request_license, get_mcp_version, and health_check ignore denial (with a logged warning) so you can never brick your install. Everything else — including the Firebase credential helpers enable_workflow_builder, auto_capture_firebase_script, capture_firebase_interactive, and install_skills (denying it also skips the bundled-skills auto-install) — is deniable.
- Verify it took effect: run
health_check in Claude. Its "Tool gating" section shows exactly what's disabled, whether account admin is on, and flags any misspelled name in your gating vars (typos do NOT disable anything — they warn instead).
- Single-location shops that never want cross-account movement can also deny
switch_location and register_location.
- Honest limit: this gate is enforced at server startup from your config file, so it is as strong as your machine's file permissions. What it guarantees is that nothing inside a Claude conversation can widen the tool surface.
Troubleshooting
Only setup_ghl_mcp shows up; no other tools | Bootstrap mode — credentials not yet activated | Run setup_ghl_mcp with all four required fields, then restart Claude |
| MCP tools don't appear (CLI) | Server not registered | Run claude mcp add --scope user -t stdio ghl -- npx -y @elitedcs/ghl-mcp@latest |
| MCP tools don't appear (Desktop App) | Config missing or wrong | Check ~/Library/Application Support/Claude/claude_desktop_config.json has a ghl entry under mcpServers (see Quick Start above for the exact block) |
| MCP tools don't appear (Desktop App) | App not restarted | Quit the Claude app completely (Cmd+Q on Mac) and reopen it |
License key not found | Wrong email or license_key | Both must match exactly what we have on file. Check spam for the welcome email. |
License key already activated on 3 devices | Activation limit hit | Email support@cliniclaunchlab.com to reset |
locationId is required | Tool needs a location ID | Set GHL_LOCATION_ID in your env, or tell Claude which location to use |
GHL API Error 401 | Invalid or expired key | Generate a new API key in GHL > Settings > Integrations |
GHL API Error 403 | Key from wrong sub-account | Create a new Private Integration inside the correct sub-account |
GHL API Error 403 (alt) | Missing permission scope | Edit your Private Integration in GHL and enable the required scope |
GHL API Error 422 | Invalid request data | Check the error message for which field is wrong |
GHL API Error 429 | Rate limited | Wait a moment and retry |
About
Built by Elite DCs, LLC — a digital marketing and automation agency specializing in GoHighLevel implementations for healthcare practices and local businesses.
Tech stack: TypeScript, Node.js, esbuild, MCP SDK, Zod, GHL API v2, Firebase Auth
Version: 3.52.1
License
MIT License — see LICENSE for full text.
Copyright (c) 2026 Elite DCs, LLC. All rights reserved.