@elitedcs/ghl-mcp 3.19.1 → 3.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.20.0 — License gate for headless / env-var installs
4
+
5
+ **Security + headless support. No tool changes (212 across 43 modules).**
6
+
7
+ Closes a gap where setting `GHL_API_KEY` + `GHL_LOCATION_ID` via environment variables loaded the full tool set **without ever validating a license**. The server now requires a verified license before exposing the full tools:
8
+
9
+ - A `credentials.json` written by `setup_ghl_mcp` carries `verified_at` (validated at setup) and is trusted as before — **no change for normal Desktop/Claude Code installs.**
10
+ - The env-var / headless path must now supply `GHL_LICENSE_EMAIL` + `GHL_LICENSE_KEY`. These are validated once at boot and the verified result is cached to `credentials.json`, so there's no per-restart phone-home and device activations aren't re-counted on a stable machine.
11
+ - Without a verified license, the server stays in bootstrap mode (only `setup_ghl_mcp`, `request_license`, `get_mcp_version`) with a clear message.
12
+
13
+ This makes headless/server installs first-class: set `GHL_LICENSE_EMAIL`, `GHL_LICENSE_KEY`, `GHL_API_KEY`, `GHL_LOCATION_ID` (plus the Firebase vars for the workflow builder) and the server boots into the full tool set.
14
+
3
15
  ## 3.19.1 — MCP registry prep + README UTM tracking
4
16
 
5
17
  - Added `mcpName` (`io.github.drjerryrelth/ghl-command`) to package.json so the package can be published to the official MCP registry (many directories pull from it).
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ var require_package = __commonJS({
31
31
  "package.json"(exports2, module2) {
32
32
  module2.exports = {
33
33
  name: "@elitedcs/ghl-mcp",
34
- version: "3.19.1",
34
+ version: "3.20.0",
35
35
  mcpName: "io.github.drjerryrelth/ghl-command",
36
36
  description: "GoHighLevel MCP Server for Claude. 212 tools \u2014 full CRM, automation, marketing control, and the only programmatic GHL workflow builder, now multi-tenant across client accounts.",
37
37
  main: "dist/index.js",
@@ -60,9 +60,15 @@ var require_package = __commonJS({
60
60
  "model-context-protocol",
61
61
  "gohighlevel",
62
62
  "ghl",
63
+ "gohighlevel-mcp",
64
+ "ghl-automation",
63
65
  "crm",
64
66
  "claude",
65
- "anthropic"
67
+ "anthropic",
68
+ "workflow-builder",
69
+ "marketing-automation",
70
+ "ai-agent",
71
+ "agency"
66
72
  ],
67
73
  author: "Elite DCs, LLC",
68
74
  license: "MIT",
@@ -8321,24 +8327,60 @@ var server = new import_mcp.McpServer({
8321
8327
  name: "elite-dcs-ghl",
8322
8328
  version: pkg.version
8323
8329
  });
8324
- var inBootstrapMode = !apiKey || !locationId;
8325
8330
  registerMetaTools(server, pkg.version);
8326
- if (inBootstrapMode) {
8327
- process.stderr.write(
8328
- `[ghl-mcp] Bootstrap mode: no credentials found.
8329
- [ghl-mcp] Looked for env vars (GHL_API_KEY, GHL_LOCATION_ID) and credentials file (${credentialsPath()}).
8331
+ var inBootstrapMode = true;
8332
+ async function resolveAccessAndRegister() {
8333
+ let licenseVerified = Boolean(fileCreds?.verified_at && fileCreds?.license_key);
8334
+ if (!licenseVerified && apiKey && locationId) {
8335
+ const licEmail = (process.env.GHL_LICENSE_EMAIL || fileCreds?.email)?.trim();
8336
+ const licKey = (process.env.GHL_LICENSE_KEY || fileCreds?.license_key)?.trim();
8337
+ if (licEmail && licKey) {
8338
+ const lic = await validateLicense(licEmail, licKey);
8339
+ if (lic.ok) {
8340
+ licenseVerified = true;
8341
+ try {
8342
+ writeCredentials({
8343
+ license_key: licKey,
8344
+ email: licEmail,
8345
+ verified_at: (/* @__PURE__ */ new Date()).toISOString(),
8346
+ ghl_api_key: apiKey,
8347
+ ghl_location_id: locationId,
8348
+ ...process.env.GHL_COMPANY_ID ? { ghl_company_id: process.env.GHL_COMPANY_ID } : {},
8349
+ ...process.env.GHL_USER_ID ? { ghl_user_id: process.env.GHL_USER_ID } : {},
8350
+ ...process.env.GHL_FIREBASE_API_KEY ? { ghl_firebase_api_key: process.env.GHL_FIREBASE_API_KEY } : {},
8351
+ ...process.env.GHL_FIREBASE_REFRESH_TOKEN ? { ghl_firebase_refresh_token: process.env.GHL_FIREBASE_REFRESH_TOKEN } : {}
8352
+ });
8353
+ process.stderr.write("[ghl-mcp] License validated and cached.\n");
8354
+ } catch {
8355
+ }
8356
+ } else {
8357
+ process.stderr.write(`[ghl-mcp] License check failed: ${lic.error}
8358
+ `);
8359
+ }
8360
+ } else {
8361
+ process.stderr.write(
8362
+ "[ghl-mcp] No verified license. For a headless/server install set GHL_LICENSE_EMAIL + GHL_LICENSE_KEY alongside GHL_API_KEY + GHL_LOCATION_ID; otherwise run setup_ghl_mcp.\n"
8363
+ );
8364
+ }
8365
+ }
8366
+ inBootstrapMode = !apiKey || !locationId || !licenseVerified;
8367
+ if (inBootstrapMode) {
8368
+ process.stderr.write(
8369
+ `[ghl-mcp] Bootstrap mode.
8370
+ [ghl-mcp] Need a valid license plus GHL_API_KEY + GHL_LOCATION_ID (env vars or credentials file at ${credentialsPath()}).
8330
8371
  [ghl-mcp] Only setup_ghl_mcp, request_license, and get_mcp_version are available. Run setup_ghl_mcp with your license + GHL credentials \u2014 or request_license if you don't have a license yet.
8331
8372
  `
8332
- );
8333
- registerSetupTool(server);
8334
- registerLeadCaptureTool(server);
8335
- } else {
8336
- const client = new GHLClient({ apiKey, locationId });
8337
- registerAllTools(server, client, registry, pkg.version);
8338
- registerEnableWorkflowBuilderTool(server);
8339
- if (fileCreds && !process.env.GHL_API_KEY) {
8340
- process.stderr.write(`[ghl-mcp] Loaded credentials from ${credentialsPath()}
8373
+ );
8374
+ registerSetupTool(server);
8375
+ registerLeadCaptureTool(server);
8376
+ } else {
8377
+ const client = new GHLClient({ apiKey, locationId });
8378
+ registerAllTools(server, client, registry, pkg.version);
8379
+ registerEnableWorkflowBuilderTool(server);
8380
+ if (fileCreds && !process.env.GHL_API_KEY) {
8381
+ process.stderr.write(`[ghl-mcp] Loaded credentials from ${credentialsPath()}
8341
8382
  `);
8383
+ }
8342
8384
  }
8343
8385
  }
8344
8386
  async function validateApiKey() {
@@ -8375,6 +8417,7 @@ async function checkForUpdates() {
8375
8417
  }
8376
8418
  }
8377
8419
  async function main() {
8420
+ await resolveAccessAndRegister();
8378
8421
  const transport = new import_stdio.StdioServerTransport();
8379
8422
  await server.connect(transport);
8380
8423
  if (inBootstrapMode) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elitedcs/ghl-mcp",
3
- "version": "3.19.1",
3
+ "version": "3.20.0",
4
4
  "mcpName": "io.github.drjerryrelth/ghl-command",
5
5
  "description": "GoHighLevel MCP Server for Claude. 212 tools — full CRM, automation, marketing control, and the only programmatic GHL workflow builder, now multi-tenant across client accounts.",
6
6
  "main": "dist/index.js",
@@ -29,9 +29,15 @@
29
29
  "model-context-protocol",
30
30
  "gohighlevel",
31
31
  "ghl",
32
+ "gohighlevel-mcp",
33
+ "ghl-automation",
32
34
  "crm",
33
35
  "claude",
34
- "anthropic"
36
+ "anthropic",
37
+ "workflow-builder",
38
+ "marketing-automation",
39
+ "ai-agent",
40
+ "agency"
35
41
  ],
36
42
  "author": "Elite DCs, LLC",
37
43
  "license": "MIT",