GoHighLevel MCP Server
by abdul-34
README.md
# CRM MCP — self-hosted, multi-sub-account MCP server
**Built & maintained by [Abdulrehman Moaz](https://www.xylatorai.com/) · [XylatorAI](https://www.xylatorai.com/)** — custom GoHighLevel/CRM integrations & AI systems for agencies.
> **Built on [mastanley13/GoHighLevel-MCP](https://github.com/mastanley13/GoHighLevel-MCP)**
> by **StrategixAI LLC (Mykel Stanley)**. This is a derivative work that adds a
> self-hosted, multi-sub-account deployment layer on top of that project's CRM
> tools. The original code remains © 2024 StrategixAI LLC and is used under its
> Community License. See [`NOTICE`](NOTICE) and [`LICENSE`](LICENSE).
>
> ⚠️ The Community License permits **non-commercial** use only. Commercial
> resale or paid products based primarily on this software require written
> permission from the original author (`mykelandrewstanley@gmail.com`).
A self-hosted [Model Context Protocol](https://modelcontextprotocol.io) server
for your CRM, built for **agencies**. Connect any number of CRM sub-accounts,
choose which tools each client can use, and hand every client a unique,
revocable MCP URL.
- **Multiple sub-accounts** — one deployment serves all your sub-accounts.
- **Per-client URLs** — generate a unique `/mcp/<token>` link scoped to a single
sub-account (or your whole agency).
- **Pick the tools** — each link exposes only the tools you select.
- **Self-hosted** — runs anywhere Docker runs; no third-party backend.
- **Secure by design** — tokens are encrypted at rest, link secrets are hashed,
and the dashboard is protected by Supabase Auth + Row Level Security.
---
## Architecture
```
┌──────────────────────────┐ ┌──────────────────────────┐
│ Dashboard (Next.js) │ │ MCP Server (Express) │
│ - Supabase Auth login │ │ - /mcp/<link-token> │
│ - add sub-account PITs │ │ - resolves token→subacct│
│ - generate client URLs │ │ - per-link tool filter │
│ - pick tools per link │ │ - builds session pool │
└────────────┬─────────────┘ └────────────┬─────────────┘
writes (RLS, anon key) reads (service-role key)
└───────────────┬───────────────────┘
▼
┌──────────────┐
│ Supabase │
│ (Postgres) │
└──────────────┘
```
- **`/` (repo root)** — the MCP server (TypeScript + Express).
- **`dashboard/`** — the agency dashboard (Next.js, App Router).
- **`supabase/migrations/`** — database schema + RLS policies.
Sub-accounts authenticate to the CRM using **Private Integration Tokens (PIT)**,
which are long-lived, so there is no OAuth refresh machinery to run.
---
## Prerequisites
- Docker + Docker Compose
- A [Supabase](https://supabase.com) project (free tier is fine)
- A CRM Private Integration Token for each sub-account you want to connect
---
## Setup
### 1. Create the database schema
In the Supabase dashboard → **SQL Editor**, run the contents of
[`supabase/migrations/0001_init.sql`](supabase/migrations/0001_init.sql).
(Or apply it with the Supabase CLI: `supabase db push`.)
This creates the `subaccounts` and `mcp_links` tables and their RLS policies.
### 2. Configure environment
```bash
cp .env.example .env
```
Fill in:
| Variable | Where to find it | Used by |
| --- | --- | --- |
| `SUPABASE_URL` / `NEXT_PUBLIC_SUPABASE_URL` | Supabase → Project Settings → API | both |
| `NEXT_PUBLIC_SUPABASE_ANON_KEY` | same page (anon public key) | dashboard |
| `SUPABASE_SERVICE_ROLE_KEY` | same page (service role key) | server only |
| `ENCRYPTION_KEY` | `openssl rand -hex 32` | both (must match) |
| `NEXT_PUBLIC_MCP_BASE_URL` | your server's public URL | dashboard |
> **`ENCRYPTION_KEY` must be identical** for the dashboard and the server, or
> PITs encrypted by the dashboard won't decrypt on the server.
### 3. Run
```bash
docker compose up --build
```
- Dashboard → http://localhost:3000
- MCP server → http://localhost:8000
---
## Deploy to Render (both services, one Blueprint)
Render doesn't run `docker-compose`, but the included
[`render.yaml`](render.yaml) Blueprint deploys **both** services together.
1. Run `supabase/migrations/0001_init.sql` in your Supabase project (one time).
2. Push this repo to GitHub.
3. In Render: **New + → Blueprint →** select your repo. Render detects
`render.yaml` and creates both services.
4. When prompted, fill in the secrets (same `ENCRYPTION_KEY` on both):
- `crm-mcp-server`: `SUPABASE_URL`, `SUPABASE_SERVICE_ROLE_KEY`, `ENCRYPTION_KEY`
- `crm-mcp-dashboard`: `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_ANON_KEY`,
`ENCRYPTION_KEY`, `NEXT_PUBLIC_MCP_BASE_URL`
5. **One follow-up step:** the dashboard needs the server's public URL at build
time, which isn't known until the server's first deploy. After the first
deploy, copy the `crm-mcp-server` URL into the dashboard's
`NEXT_PUBLIC_MCP_BASE_URL` and redeploy the dashboard. (Only needed once.)
> On a plain VPS with Docker, `docker compose up -d` does all of this in a
> single command with no follow-up step.
---
## Usage
1. Open the dashboard, **sign up / sign in**.
2. **Sub-accounts** → add each CRM sub-account: a name, its **Location ID**, and
its **Private Integration Token**. The token is encrypted before it's stored.
3. **MCP Links** → create a link:
- **Scope**: a single sub-account (for a client) or all your sub-accounts.
- **Tools**: expose all, or pick a specific subset.
- Copy the generated URL — **the token is shown only once**.
4. Give the client the URL. They add it to Claude / ChatGPT / any MCP client:
`https://your-host/mcp/<token>`.
Revoke a link any time from the dashboard — access stops immediately.
---
## Security model
| Concern | Mechanism |
| --- | --- |
| Only the agency can write tokens | Supabase Auth + RLS (`owner_id = auth.uid()`) |
| Client URLs can't be guessed | 256-bit random secret in the URL |
| DB leak doesn't expose live URLs | only `sha256(secret)` is stored |
| PITs unreadable from a DB dump | AES-256-GCM encryption at rest |
| Clients isolated to their sub-account | location scope + pool membership check |
| Instant revocation | `revoked` flag checked on every connect |
| Service role key never in browser | server-only; browser uses anon key + RLS |
---
## Local (stdio) usage
For a single sub-account locally (e.g. Claude Desktop), no Supabase required:
```bash
npm install
npm run build
CRM_PIT_TOKEN=pit-xxxx CRM_LOCATION_ID=your-location-id npm run start:stdio
```
Or point it at a dashboard link with `MCP_LINK_TOKEN` (+ the Supabase env vars).
---
## Development
```bash
# MCP server
npm install
npm run dev
# Dashboard
cd dashboard
npm install
npm run dev
```
---
## Author & Maintainer
### ⭐ Abdulrehman Moaz — Founder, [XylatorAI](https://www.xylatorai.com/)
This self-hosted, multi-sub-account edition is built and maintained by
**Abdulrehman Moaz**, founder of **[XylatorAI](https://www.xylatorai.com/)** —
custom CRM/GoHighLevel integrations & AI systems for agencies and SaaS builders.
- 🌐 Website: **[xylatorai.com](https://www.xylatorai.com/)**
- 📧 Contact: **rehman@xylatorai.com**
Need a custom CRM marketplace app, conversation/payment provider, AI agent, or a
bespoke MCP integration? [Book a call with XylatorAI](https://www.xylatorai.com/).
## Credits
This project builds on the original
**[GoHighLevel MCP Server](https://github.com/mastanley13/GoHighLevel-MCP)** by
**StrategixAI LLC (Mykel Stanley)**. The CRM API client and the full tool set
(`src/tools/`, `src/clients/`) originate from that project. Huge thanks to the
original author and the GoHighLevel community.
The self-hosted, multi-sub-account layer — Supabase-backed encrypted token
storage, per-link MCP URLs, per-link tool selection, and the management
dashboard — was added by [XylatorAI](https://www.xylatorai.com/).
## License
Governed by the **GoHighLevel MCP Server Community License** — see
[`LICENSE`](LICENSE) and [`NOTICE`](NOTICE).
- ✅ Personal, educational, and non-commercial use
- ✅ Modification and free distribution
- ❌ Commercial resale/licensing or paid products based primarily on this software
- ❌ Removing or altering the license or copyright notices
For commercial use, contact the original author: `mykelandrewstanley@gmail.com`.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing