@greennx/sales-mcp 1.1.0 → 1.3.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.
Files changed (2) hide show
  1. package/dist/scripts/cli.js +101 -8
  2. package/package.json +1 -1
@@ -7,12 +7,22 @@ import { mkdirSync, copyFileSync, existsSync, readFileSync, writeFileSync } from
7
7
  import { join, dirname } from "node:path";
8
8
  import { fileURLToPath } from "node:url";
9
9
  import { homedir, platform } from "node:os";
10
+ import { createInterface } from "node:readline";
10
11
  var here = dirname(fileURLToPath(import.meta.url));
11
12
  var DIST_DIR = join(here, "..");
12
13
  var BUNDLE_SRC = join(DIST_DIR, "bundle.cjs");
13
14
  var IS_WIN = platform() === "win32";
14
15
  var IS_MAC = platform() === "darwin";
15
16
  var CLAUDE_CMD = IS_WIN ? "claude.cmd" : "claude";
17
+ function promptToken() {
18
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
19
+ return new Promise((resolve) => {
20
+ rl.question(` ${bold("Greenn token:")} `, (answer) => {
21
+ rl.close();
22
+ resolve(answer.trim());
23
+ });
24
+ });
25
+ }
16
26
  function expandTilde(p) {
17
27
  if (p === "~") return homedir();
18
28
  if (p.startsWith("~/") || p.startsWith("~\\")) return join(homedir(), p.slice(2));
@@ -50,6 +60,7 @@ function printHelp() {
50
60
  ${bold("COMMANDS")}
51
61
 
52
62
  ${cyan("setup")} Auto-detect and configure all installed MCP clients
63
+ ${cyan("update")} Update the server bundle to the latest installed version
53
64
  ${cyan("uninstall")} Remove sales-mcp from all detected tools
54
65
 
55
66
  ${bold("OPTIONS")}
@@ -65,6 +76,9 @@ function printHelp() {
65
76
  ${dim("# Use a custom directory for HTML backups")}
66
77
  ${cyan(`npx @greenn/sales-mcp setup --token`)} <your-token> ${cyan("--history-path")} ~/backups/greenn
67
78
 
79
+ ${dim("# Update server to the latest version")}
80
+ ${cyan("npx @greenn/sales-mcp update")}
81
+
68
82
  ${dim("# Remove from all tools")}
69
83
  ${cyan("npx @greenn/sales-mcp uninstall")}
70
84
 
@@ -122,6 +136,12 @@ function resolveConfigPath(tool) {
122
136
  case "claude-code-user":
123
137
  if (IS_WIN) return join(process.env["USERPROFILE"] ?? home, ".claude.json");
124
138
  return join(home, ".claude.json");
139
+ case "gemini-cli":
140
+ if (IS_WIN) return join(process.env["USERPROFILE"] ?? home, ".gemini", "settings.json");
141
+ return join(home, ".gemini", "settings.json");
142
+ case "codex":
143
+ if (IS_WIN) return join(process.env["USERPROFILE"] ?? home, ".codex", "config.toml");
144
+ return join(home, ".codex", "config.toml");
125
145
  default:
126
146
  return null;
127
147
  }
@@ -165,6 +185,51 @@ function removeSalesMcpFromJsonConfig(configPath) {
165
185
  writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
166
186
  return true;
167
187
  }
188
+ function removeSalesMcpTomlSections(content) {
189
+ const lines = content.split("\n");
190
+ const out = [];
191
+ let skip = false;
192
+ for (const line of lines) {
193
+ const trimmed = line.trim();
194
+ if (trimmed === "[mcp_servers.sales-mcp]" || trimmed === "[mcp_servers.sales-mcp.env]") {
195
+ skip = true;
196
+ continue;
197
+ }
198
+ if (skip && trimmed.startsWith("[")) skip = false;
199
+ if (!skip) out.push(line);
200
+ }
201
+ return out.join("\n");
202
+ }
203
+ function patchTomlConfig(configPath, serverPath, mcpContext) {
204
+ let content = "";
205
+ let wasCreated = true;
206
+ if (existsSync(configPath)) {
207
+ content = removeSalesMcpTomlSections(readFileSync(configPath, "utf-8")).trimEnd();
208
+ wasCreated = false;
209
+ } else {
210
+ mkdirSync(dirname(configPath), { recursive: true });
211
+ }
212
+ const entry = [
213
+ "",
214
+ "[mcp_servers.sales-mcp]",
215
+ `command = ${JSON.stringify(process.execPath)}`,
216
+ `args = [${JSON.stringify(serverPath)}]`,
217
+ "",
218
+ "[mcp_servers.sales-mcp.env]",
219
+ `MCP_CONTEXT = ${JSON.stringify(mcpContext)}`,
220
+ ""
221
+ ].join("\n");
222
+ writeFileSync(configPath, content + entry);
223
+ return wasCreated ? "created" : "patched";
224
+ }
225
+ function removeSalesMcpFromTomlConfig(configPath) {
226
+ if (!existsSync(configPath)) return false;
227
+ const original = readFileSync(configPath, "utf-8");
228
+ const updated = removeSalesMcpTomlSections(original).trimEnd() + "\n";
229
+ if (updated === original) return false;
230
+ writeFileSync(configPath, updated);
231
+ return true;
232
+ }
168
233
  var [command, ...rest] = process.argv.slice(2);
169
234
  var hasHelp = rest.includes("--help") || rest.includes("-h");
170
235
  if (!command || command === "--help" || command === "-h") {
@@ -188,12 +253,15 @@ if (command === "setup") {
188
253
  },
189
254
  strict: false
190
255
  });
191
- const token = values["token"];
256
+ let token = values["token"];
257
+ if (!token) {
258
+ console.log(`
259
+ ${dim("Tip: paste your token here to avoid shell escaping issues with special characters.")}`);
260
+ token = await promptToken();
261
+ }
192
262
  if (!token) {
193
263
  console.error(`
194
- ${red("error")} --token is required
195
- `);
196
- console.error(` Run ${cyan('"sales-mcp setup --help"')} for more information.
264
+ ${red("error")} token is required
197
265
  `);
198
266
  process.exit(1);
199
267
  }
@@ -220,7 +288,9 @@ if (command === "setup") {
220
288
  { id: "claude-desktop", name: "Claude Desktop", restart: "Restart Claude Desktop." },
221
289
  { id: "cursor", name: "Cursor", restart: 'Settings > MCP > click "Refresh".' },
222
290
  { id: "antigravity", name: "Antigravity (Windsurf)", restart: 'Manage MCP Servers > click "Refresh".' },
223
- { id: "cline", name: "Cline (VS Code)", restart: 'Cline sidebar > MCP Servers > click "Refresh".' }
291
+ { id: "cline", name: "Cline (VS Code)", restart: 'Cline sidebar > MCP Servers > click "Refresh".' },
292
+ { id: "gemini-cli", name: "Gemini CLI", restart: "Restart Gemini CLI." },
293
+ { id: "codex", name: "Codex CLI", restart: "Restart Codex CLI.", toml: true }
224
294
  ];
225
295
  let configured = 0;
226
296
  for (const tool of tools) {
@@ -234,7 +304,7 @@ if (command === "setup") {
234
304
  continue;
235
305
  }
236
306
  try {
237
- const action = patchJsonConfig(configPath, serverDest, mcpContext);
307
+ const action = tool.toml ? patchTomlConfig(configPath, serverDest, mcpContext) : patchJsonConfig(configPath, serverDest, mcpContext);
238
308
  console.log(` ${green("ok")} ${bold(tool.name)} ${dim(`\u2014 config ${action}.`)}`);
239
309
  console.log(` ${dim("file:")} ${configPath}`);
240
310
  console.log(` ${dim("next:")} ${tool.restart}`);
@@ -284,6 +354,27 @@ if (command === "setup") {
284
354
  console.log(` ${dim("3.")} You should see your Greenn funnels listed \u2014 setup is complete.
285
355
  `);
286
356
  }
357
+ } else if (command === "update") {
358
+ const serverDest = join(DEFAULT_INSTALL_DIR, "server.cjs");
359
+ if (!existsSync(serverDest)) {
360
+ console.error(`
361
+ ${red("error")} sales-mcp is not installed. Run ${cyan('"sales-mcp setup"')} first.
362
+ `);
363
+ process.exit(1);
364
+ }
365
+ if (!existsSync(BUNDLE_SRC)) {
366
+ console.error(`
367
+ ${red("error")} bundle not found at ${BUNDLE_SRC}
368
+ `);
369
+ process.exit(1);
370
+ }
371
+ copyFileSync(BUNDLE_SRC, serverDest);
372
+ console.log(`
373
+ ${bold(green("sales-mcp updated"))} ${dim(`\u2192 v${VERSION}`)}`);
374
+ console.log(` ${dim("server:")} ${serverDest}`);
375
+ console.log(`
376
+ Restart your AI tools to apply the update.
377
+ `);
287
378
  } else if (command === "uninstall") {
288
379
  console.log("");
289
380
  for (const scope of ["user", "project", "local"]) {
@@ -294,14 +385,16 @@ if (command === "setup") {
294
385
  { id: "claude-desktop", name: "Claude Desktop" },
295
386
  { id: "cursor", name: "Cursor" },
296
387
  { id: "antigravity", name: "Antigravity (Windsurf)" },
297
- { id: "cline", name: "Cline (VS Code)" }
388
+ { id: "cline", name: "Cline (VS Code)" },
389
+ { id: "gemini-cli", name: "Gemini CLI" },
390
+ { id: "codex", name: "Codex CLI", toml: true }
298
391
  ];
299
392
  let removed = 0;
300
393
  for (const tool of tools) {
301
394
  const configPath = resolveConfigPath(tool.id);
302
395
  if (!configPath) continue;
303
396
  try {
304
- const ok = removeSalesMcpFromJsonConfig(configPath);
397
+ const ok = tool.toml ? removeSalesMcpFromTomlConfig(configPath) : removeSalesMcpFromJsonConfig(configPath);
305
398
  if (ok) {
306
399
  console.log(` ${green("ok")} ${tool.name} ${dim("\u2014 removed.")}`);
307
400
  removed++;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greennx/sales-mcp",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "MCP server for AI-generated landing pages on the Greenn Sales platform",
5
5
  "type": "module",
6
6
  "bin": {