npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@theethosteam/ghl-mcp

v1.0.0

Published

Agency-wide read + write MCP server (and CLI) for GoHighLevel / LeadConnector. ~69 typed tools (contacts, forms & submissions, conversations, opportunities, calendars/appointments, users, tags, custom fields, workflows, products, invoices/payments) + a se

Readme

@theethosteam/ghl-mcp

Rock-solid, agency-wide MCP server + CLI for GoHighLevel / LeadConnector. ~69 typed tools across the hot domains, a searchable catalog of all 576 v2 endpoints (ghl_catalog), and a ghl_raw passthrough to anything — so every endpoint is reachable. Runs via npx, identically locally or in a cloud session.

Built on the same pattern as the GA4 / GTM / GSC / Google Ads MCPs: one shared core/, exposed as both an MCP server (mcp.ts) and a commander CLI (cli.ts), run directly with tsx (no build step).

What makes it agency-grade

  1. Agency OAuth, durable across cloud restarts. One private Marketplace app installed at the agency mints a short-lived token for any sub-account on demand. GHL rotates the refresh token on every refresh (single-use), so the live token lives in a durable token store (Supabase when configured) with compare-and-swap — local and ephemeral cloud share one source of truth and concurrent cold-starts never strand a token. A per-location PIT still works as an override.
  2. Account-awareness is structural. Every call binds to exactly one sub-account and every response echoes { locationId, locationName }. You always know which account you touched.
  3. Tiered write-safety. Routine single-record writes (create/update contact, tags, notes, tasks, send a requested message, move a stage, book an appointment) execute directly. Destructive (deletes), bulk, and money (invoices/payments) ops are confirm-gated dry-runs — GHL has no server-side validate, so without confirm:true they don't call the API; they return a preview naming the target account. Cross-account writes are refused.
  4. Hardened transport. Retry on 429 / 5xx / network with exponential backoff + jitter, per-call timeout, structured GhlError, defensive auto-pagination, response trimming.

Auth

(A) Agency OAuth — reach every sub-account (recommended)

npx -y @theethosteam/ghl-mcp ghl auth:scopes            # the full scope set to select on the app
npx -y @theethosteam/ghl-mcp ghl auth:url --client-id <id> --redirect <uri>   # open, approve, copy ?code=…
npx -y @theethosteam/ghl-mcp ghl auth:exchange <code> --redirect <uri>        # prints refresh_token + companyId
  1. Create a Private Marketplace app at https://marketplace.gohighlevel.com (private = no review; 5-agency-install cap is fine for one agency).
  2. Select the scopes from auth:scopes, set the redirect URI, generate the Client ID/Secret, and install at the agency (Company) level.
  3. Run auth:url → approve → auth:exchange <code> to mint the seed refresh token.
  4. Configure env + seed the token store:
ZJ_GHL_OAUTH_CLIENT_ID=...
ZJ_GHL_OAUTH_CLIENT_SECRET=...
ZJ_GHL_OAUTH_REFRESH_TOKEN=...     # seed; the live token then lives in the store
ZJ_GHL_COMPANY_ID=...
ZJ_SUPABASE_URL=...                # durable token store (see Token store below)
ZJ_GHL_SUPABASE_SERVICE_KEY=...    # service-role key

(B) Per-location PIT — immediate, single sub-account

ZJ_GHL_PIT=pit-xxxxxxxx
ZJ_GHL_LOCATION=<locationId>       # multi-account: ZJ_GHL_PIT_<locationId>=pit-...

A configured PIT wins; otherwise the connector mints a location token via OAuth.

Token store (durable OAuth)

Apply sql/ghl_oauth_token_store.sql once to the Supabase project named by ZJ_SUPABASE_URL — a tiny table + two security definer RPCs (ghl_token_get / ghl_token_rotate), service-role only. The connector reads/CAS-writes the rotating refresh token there so cloud + local stay in sync. Without it, the connector falls back to ZJ_GHL_OAUTH_REFRESH_TOKEN in env (fine for local; not durable in ephemeral cloud).

Optional: ZJ_GHL_API_VERSION (default 2021-07-28), ZJ_GHL_BASE_URL, ZJ_GHL_TIMEOUT_MS, ZJ_GHL_MAX_PAGES, ZJ_GHL_MAX_RESPONSE_ITEMS.

Connect to Claude

Cloud (Claude Code on the web) — add to the repo .mcp.json (env via ${VAR}; secrets live in the environment box, never in git):

{
  "mcpServers": {
    "ghl": {
      "command": "npx",
      "args": ["-y", "@theethosteam/ghl-mcp"],
      "env": {
        "ZJ_GHL_OAUTH_CLIENT_ID": "${ZJ_GHL_OAUTH_CLIENT_ID}",
        "ZJ_GHL_OAUTH_CLIENT_SECRET": "${ZJ_GHL_OAUTH_CLIENT_SECRET}",
        "ZJ_GHL_OAUTH_REFRESH_TOKEN": "${ZJ_GHL_OAUTH_REFRESH_TOKEN}",
        "ZJ_GHL_COMPANY_ID": "${ZJ_GHL_COMPANY_ID}",
        "ZJ_SUPABASE_URL": "${ZJ_SUPABASE_URL}",
        "ZJ_GHL_SUPABASE_SERVICE_KEY": "${ZJ_GHL_SUPABASE_SERVICE_KEY}"
      }
    }
  }
}

Pass each client's sub-account locationId per call (don't pin ZJ_GHL_LOCATION in a multi-client repo). For a single-location PIT setup, swap the OAuth env for ZJ_GHL_PIT + ZJ_GHL_LOCATION.

Local (Claude Code CLI):

claude mcp add ghl --scope user \
  -e ZJ_GHL_OAUTH_CLIENT_ID=... -e ZJ_GHL_OAUTH_CLIENT_SECRET=... \
  -e ZJ_GHL_OAUTH_REFRESH_TOKEN=... -e ZJ_GHL_COMPANY_ID=... \
  -e ZJ_SUPABASE_URL=... -e ZJ_GHL_SUPABASE_SERVICE_KEY=... \
  -- npx -y @theethosteam/ghl-mcp

Tools (~69 typed + catalog + raw)

  • Awareness: ghl_whoami · ghl_list_locations · ghl_get_location · ghl_use_location · ghl_compare
  • Contacts: list · search · get · create · update · upsert · delete · add/remove tags · notes (list/add) · tasks (list/add/complete) · appointments
  • Conversations: search · get · create · messages · send · update status
  • Opportunities: search · get · create · upsert · delete · pipelines · update · status
  • Calendars / appointments: calendars CRUD · groups · free-slots · events · appointment get/create/update/delete
  • Forms: ghl_list_forms · ghl_list_form_submissions
  • Users · tags · custom fields/values · workflows · campaigns · products
  • Invoices & payments (money tier): list/get invoices · create/send/record-payment (gated) · transactions · orders
  • ghl_catalog — search all 576 v2 endpoints (method/path/scopes/required params) → feed to ghl_raw
  • ghl_raw — call ANY v2 endpoint (GET runs; non-GET confirm-gated; companyAuth:true for agency-level)

Every gated write is a DRY-RUN unless confirm:true.

CLI (handy for testing)

npx -y @theethosteam/ghl-mcp ghl whoami
npx -y @theethosteam/ghl-mcp ghl locations                       # agency OAuth
npx -y @theethosteam/ghl-mcp ghl form-submissions -l <locationId> --formId <id>
npx -y @theethosteam/ghl-mcp ghl catalog "refund invoice"
npx -y @theethosteam/ghl-mcp ghl raw GET /contacts/search -l <locationId>

License

MIT