Skip to main content
Glama
abdul-34

GoHighLevel MCP Server

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`.