@atlashub/smartstack-cli 2.5.1 → 2.5.2

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/dist/index.js CHANGED
@@ -112144,11 +112144,19 @@ function ora(options) {
112144
112144
  }
112145
112145
 
112146
112146
  // src/lib/logger.ts
112147
+ var _verbose = false;
112147
112148
  var logger = {
112149
+ setVerbose: (value) => {
112150
+ _verbose = value;
112151
+ },
112152
+ isVerbose: () => _verbose,
112148
112153
  info: (message) => console.log(source_default.blue("\u2139"), message),
112149
112154
  success: (message) => console.log(source_default.green("\u2713"), message),
112150
112155
  warning: (message) => console.log(source_default.yellow("\u26A0"), message),
112151
112156
  error: (message) => console.log(source_default.red("\u2717"), message),
112157
+ debug: (message) => {
112158
+ if (_verbose) console.log(source_default.gray("\u22A1"), source_default.gray(message));
112159
+ },
112152
112160
  header: (title) => {
112153
112161
  console.log();
112154
112162
  console.log(source_default.cyan("\u2550".repeat(60)));
@@ -112365,6 +112373,114 @@ async function getVsCodeMcpServers() {
112365
112373
  const mcpServers = settings["claudeCode.mcpServers"] || {};
112366
112374
  return { found: true, path: settingsResult.path, servers: mcpServers };
112367
112375
  }
112376
+ function getClaudeSettingsPath() {
112377
+ return (0, import_path.join)((0, import_os.homedir)(), ".claude", "settings.json");
112378
+ }
112379
+ async function readClaudeSettings() {
112380
+ const settingsPath = getClaudeSettingsPath();
112381
+ try {
112382
+ if (!await import_fs_extra.default.pathExists(settingsPath)) {
112383
+ return null;
112384
+ }
112385
+ const raw = await import_fs_extra.default.readFile(settingsPath, "utf-8");
112386
+ return JSON.parse(raw);
112387
+ } catch {
112388
+ return null;
112389
+ }
112390
+ }
112391
+ async function writeClaudeSettings(settings) {
112392
+ const settingsPath = getClaudeSettingsPath();
112393
+ const claudeDir = (0, import_path.join)((0, import_os.homedir)(), ".claude");
112394
+ let backupPath = null;
112395
+ logger.debug(`Creating directory: ${claudeDir}`);
112396
+ await import_fs_extra.default.ensureDir(claudeDir);
112397
+ const dirExists = await import_fs_extra.default.pathExists(claudeDir);
112398
+ if (!dirExists) {
112399
+ throw new Error(`Failed to create directory: ${claudeDir}`);
112400
+ }
112401
+ if (await import_fs_extra.default.pathExists(settingsPath)) {
112402
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
112403
+ backupPath = settingsPath.replace(".json", `.backup-${timestamp}.json`);
112404
+ await import_fs_extra.default.copy(settingsPath, backupPath);
112405
+ }
112406
+ const content = JSON.stringify(settings, null, 2);
112407
+ logger.debug(`Writing ${content.length} bytes to: ${settingsPath}`);
112408
+ await import_fs_extra.default.writeFile(settingsPath, content, "utf-8");
112409
+ const fileExists = await import_fs_extra.default.pathExists(settingsPath);
112410
+ if (!fileExists) {
112411
+ throw new Error(`File not found after write: ${settingsPath}`);
112412
+ }
112413
+ return { path: settingsPath, backupPath };
112414
+ }
112415
+ async function registerMcpInClaudeSettings(servers) {
112416
+ const settingsPath = getClaudeSettingsPath();
112417
+ try {
112418
+ logger.debug(`Home directory: ${(0, import_os.homedir)()}`);
112419
+ logger.debug(`Target settings path: ${settingsPath}`);
112420
+ const settings = await readClaudeSettings() || {};
112421
+ const mcpServers = settings["mcpServers"] || {};
112422
+ for (const server of servers) {
112423
+ mcpServers[server.name] = {
112424
+ command: server.command,
112425
+ args: server.args
112426
+ };
112427
+ }
112428
+ settings["mcpServers"] = mcpServers;
112429
+ await writeClaudeSettings(settings);
112430
+ const verification = await import_fs_extra.default.readFile(settingsPath, "utf-8");
112431
+ const parsed = JSON.parse(verification);
112432
+ if (!parsed["mcpServers"]) {
112433
+ throw new Error("Verification failed: mcpServers key missing after write");
112434
+ }
112435
+ logger.debug(`Verified: ${Object.keys(parsed["mcpServers"]).length} MCP server(s) in ${settingsPath}`);
112436
+ return { success: true, path: settingsPath };
112437
+ } catch (error) {
112438
+ const errMsg = error instanceof Error ? error.message : "Unknown error";
112439
+ const errStack = error instanceof Error ? error.stack : "";
112440
+ logger.debug(`registerMcpInClaudeSettings failed: ${errMsg}
112441
+ ${errStack}`);
112442
+ return {
112443
+ success: false,
112444
+ path: settingsPath,
112445
+ error: errMsg
112446
+ };
112447
+ }
112448
+ }
112449
+ async function unregisterMcpFromClaudeSettings(serverNames) {
112450
+ const settingsPath = getClaudeSettingsPath();
112451
+ try {
112452
+ const settings = await readClaudeSettings();
112453
+ if (!settings) {
112454
+ return { success: true, path: settingsPath };
112455
+ }
112456
+ const mcpServers = settings["mcpServers"] || {};
112457
+ for (const name of serverNames) {
112458
+ delete mcpServers[name];
112459
+ }
112460
+ if (Object.keys(mcpServers).length === 0) {
112461
+ delete settings["mcpServers"];
112462
+ } else {
112463
+ settings["mcpServers"] = mcpServers;
112464
+ }
112465
+ await writeClaudeSettings(settings);
112466
+ return { success: true, path: settingsPath };
112467
+ } catch (error) {
112468
+ return {
112469
+ success: false,
112470
+ path: settingsPath,
112471
+ error: error instanceof Error ? error.message : "Unknown error"
112472
+ };
112473
+ }
112474
+ }
112475
+ async function getClaudeMcpServers() {
112476
+ const settingsPath = getClaudeSettingsPath();
112477
+ const settings = await readClaudeSettings();
112478
+ if (!settings) {
112479
+ return { found: false, path: settingsPath, servers: {} };
112480
+ }
112481
+ const mcpServers = settings["mcpServers"] || {};
112482
+ return { found: true, path: settingsPath, servers: mcpServers };
112483
+ }
112368
112484
 
112369
112485
  // src/lib/mcp-checker.ts
112370
112486
  var import_child_process = require("child_process");
@@ -112684,6 +112800,21 @@ async function registerMcpServer() {
112684
112800
  logger.info("SmartStack MCP server already registered");
112685
112801
  }
112686
112802
  }
112803
+ try {
112804
+ const servers = REQUIRED_MCP_SERVERS.map((s) => ({
112805
+ name: s.name,
112806
+ command: s.command,
112807
+ args: s.args
112808
+ }));
112809
+ const claudeResult = await registerMcpInClaudeSettings(servers);
112810
+ if (claudeResult.success) {
112811
+ logger.success(`Registered MCP servers in ${claudeResult.path}`);
112812
+ } else {
112813
+ logger.warning(`Failed to register MCP in Claude settings: ${claudeResult.error}`);
112814
+ }
112815
+ } catch (error) {
112816
+ logger.warning(`MCP settings registration error: ${error instanceof Error ? error.message : "Unknown"}`);
112817
+ }
112687
112818
  try {
112688
112819
  const servers = REQUIRED_MCP_SERVERS.map((s) => ({
112689
112820
  name: s.name,
@@ -125858,6 +125989,7 @@ adminCommand.command("reset").description("Reset the localAdmin account password
125858
125989
  // src/commands/mcp.ts
125859
125990
  var import_cli_table35 = __toESM(require_cli_table3());
125860
125991
  var import_child_process9 = require("child_process");
125992
+ var import_os4 = require("os");
125861
125993
  var mcpCommand = new Command("mcp").description("MCP server management (CLI + VS Code)").action(() => {
125862
125994
  console.log(source_default.cyan(`
125863
125995
  \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
@@ -125870,23 +126002,46 @@ var mcpCommand = new Command("mcp").description("MCP server management (CLI + VS
125870
126002
  console.log(` ${source_default.cyan("smartstack mcp remove")} - Unregister MCP servers`);
125871
126003
  console.log();
125872
126004
  });
125873
- mcpCommand.command("install").description("Register MCP servers in Claude Code CLI and VS Code").option("--cli-only", "Only register in Claude Code CLI").option("--vscode-only", "Only register in VS Code settings").option("-f, --force", "Re-register even if already present").action(async (options) => {
126005
+ mcpCommand.command("install").description("Register MCP servers in Claude Code CLI and VS Code").option("--cli-only", "Only register in Claude Code CLI").option("--vscode-only", "Only register in VS Code settings").option("-f, --force", "Re-register even if already present").option("-v, --verbose", "Show detailed debug output").action(async (options) => {
126006
+ if (options.verbose) logger.setVerbose(true);
125874
126007
  logger.header("MCP Server Installation");
125875
126008
  const doCli = !options.vscodeOnly;
125876
126009
  const doVsCode = !options.cliOnly;
125877
- const totalSteps = (doCli ? 1 : 0) + (doVsCode ? 1 : 0);
126010
+ const totalSteps = (doCli ? 1 : 0) + (doVsCode ? 1 : 0) + 1;
125878
126011
  let currentStep = 0;
125879
126012
  let cliSuccess = true;
125880
126013
  let vscodeSuccess = true;
126014
+ let claudeSettingsSuccess = true;
126015
+ const servers = REQUIRED_MCP_SERVERS.map((s) => ({
126016
+ name: s.name,
126017
+ command: s.command,
126018
+ args: s.args
126019
+ }));
126020
+ currentStep++;
126021
+ logger.step(currentStep, totalSteps, "Registering in ~/.claude/settings.json...");
126022
+ logger.debug(`Home directory: ${(0, import_os4.homedir)()}`);
126023
+ logger.debug(`Target: ${getClaudeSettingsPath()}`);
126024
+ const claudeResult = await registerMcpInClaudeSettings(servers);
126025
+ if (claudeResult.success) {
126026
+ logger.success("MCP servers registered in Claude Code settings");
126027
+ logger.info(`Settings: ${source_default.cyan(claudeResult.path)}`);
126028
+ } else {
126029
+ logger.error(`Failed to register in Claude Code settings: ${claudeResult.error}`);
126030
+ logger.error(`Target path: ${claudeResult.path}`);
126031
+ logger.info(`Try manually: create ${source_default.cyan(claudeResult.path)} with MCP server config`);
126032
+ claudeSettingsSuccess = false;
126033
+ }
126034
+ console.log();
125881
126035
  if (doCli) {
125882
126036
  currentStep++;
125883
126037
  logger.step(currentStep, totalSteps, "Registering in Claude Code CLI...");
125884
126038
  if (!isClaudeCodeInstalled()) {
125885
126039
  logger.warning("Claude Code CLI not available - skipping CLI registration");
126040
+ logger.info("MCP servers are registered in ~/.claude/settings.json (sufficient for VS Code)");
125886
126041
  if (options.cliOnly) {
125887
126042
  process.exit(1);
125888
126043
  }
125889
- cliSuccess = false;
126044
+ cliSuccess = true;
125890
126045
  } else {
125891
126046
  const cliResult = checkRequiredMcpServers();
125892
126047
  if (cliResult.allInstalled && !options.force) {
@@ -125917,11 +126072,6 @@ mcpCommand.command("install").description("Register MCP servers in Claude Code C
125917
126072
  if (doVsCode) {
125918
126073
  currentStep++;
125919
126074
  logger.step(currentStep, totalSteps, "Registering in VS Code settings...");
125920
- const servers = REQUIRED_MCP_SERVERS.map((s) => ({
125921
- name: s.name,
125922
- command: s.command,
125923
- args: s.args
125924
- }));
125925
126075
  const vsResult = await registerMcpInVsCode(servers);
125926
126076
  if (vsResult.skipped) {
125927
126077
  logger.warning("VS Code settings.json not found - skipping");
@@ -125936,10 +126086,12 @@ mcpCommand.command("install").description("Register MCP servers in Claude Code C
125936
126086
  }
125937
126087
  console.log();
125938
126088
  }
125939
- if (cliSuccess && vscodeSuccess) {
126089
+ if (cliSuccess && vscodeSuccess && claudeSettingsSuccess) {
125940
126090
  const lines = ["MCP servers registered successfully!", ""];
126091
+ lines.push(`Claude: ${source_default.cyan(getClaudeSettingsPath())}`);
125941
126092
  if (doCli) lines.push("CLI: claude mcp list");
125942
126093
  if (doVsCode) lines.push("VS Code: Check claudeCode.mcpServers in settings");
126094
+ lines.push("", "Reload VS Code to activate MCP servers.");
125943
126095
  logger.box(lines, "success");
125944
126096
  } else {
125945
126097
  logger.box([
@@ -125950,12 +126102,14 @@ mcpCommand.command("install").description("Register MCP servers in Claude Code C
125950
126102
  process.exit(1);
125951
126103
  }
125952
126104
  });
125953
- mcpCommand.command("status").description("Show MCP server registration status").option("--json", "Output as JSON").action(async (options) => {
126105
+ mcpCommand.command("status").description("Show MCP server registration status").option("--json", "Output as JSON").option("-v, --verbose", "Show detailed debug output").action(async (options) => {
126106
+ if (options.verbose) logger.setVerbose(true);
125954
126107
  const claudeInstalled = isClaudeCodeInstalled();
125955
126108
  const claudeVersion = claudeInstalled ? getClaudeCodeVersion() : null;
125956
126109
  const cliResult = claudeInstalled ? checkRequiredMcpServers() : null;
125957
126110
  const vsCodeResult = await getVsCodeMcpServers();
125958
126111
  const vsCodeSettings = await findVsCodeSettings();
126112
+ const claudeSettings = await getClaudeMcpServers();
125959
126113
  if (options.json) {
125960
126114
  console.log(JSON.stringify({
125961
126115
  claudeCode: {
@@ -125963,6 +126117,11 @@ mcpCommand.command("status").description("Show MCP server registration status").
125963
126117
  version: claudeVersion,
125964
126118
  servers: cliResult?.servers || []
125965
126119
  },
126120
+ claudeSettings: {
126121
+ found: claudeSettings.found,
126122
+ path: claudeSettings.path,
126123
+ servers: claudeSettings.servers
126124
+ },
125966
126125
  vscode: {
125967
126126
  found: vsCodeResult.found,
125968
126127
  path: vsCodeResult.path,
@@ -125983,25 +126142,34 @@ mcpCommand.command("status").description("Show MCP server registration status").
125983
126142
  const table = new import_cli_table35.default({
125984
126143
  head: [
125985
126144
  source_default.cyan("MCP Server"),
126145
+ source_default.cyan("~/.claude"),
125986
126146
  source_default.cyan("CLI"),
125987
126147
  source_default.cyan("VS Code"),
125988
126148
  source_default.cyan("Description")
125989
126149
  ],
125990
126150
  style: { head: [], border: [] },
125991
- colWidths: [18, 15, 15, 40]
126151
+ colWidths: [16, 15, 15, 15, 32]
125992
126152
  });
125993
126153
  for (const server of REQUIRED_MCP_SERVERS) {
126154
+ const claudeInstalled2 = server.name in (claudeSettings.servers || {});
125994
126155
  const cliInstalled = cliResult?.servers.find((s) => s.name === server.name)?.installed ?? false;
125995
126156
  const vsInstalled = server.name in (vsCodeResult.servers || {});
125996
126157
  table.push([
125997
126158
  server.name,
125998
- cliInstalled ? source_default.green("\u2713 Registered") : source_default.red("\u2717 Missing"),
125999
- vsInstalled ? source_default.green("\u2713 Registered") : source_default.red("\u2717 Missing"),
126159
+ claudeInstalled2 ? source_default.green("\u2713 OK") : source_default.red("\u2717 Missing"),
126160
+ cliInstalled ? source_default.green("\u2713 OK") : source_default.red("\u2717 Missing"),
126161
+ vsInstalled ? source_default.green("\u2713 OK") : source_default.red("\u2717 Missing"),
126000
126162
  server.description
126001
126163
  ]);
126002
126164
  }
126003
126165
  console.log(table.toString());
126004
126166
  console.log();
126167
+ console.log(source_default.bold("Claude Code Settings"));
126168
+ if (claudeSettings.found) {
126169
+ console.log(` ${source_default.green("\u2713")} ${source_default.gray(claudeSettings.path)}`);
126170
+ } else {
126171
+ console.log(` ${source_default.red("\u2717")} ${source_default.gray(claudeSettings.path)} ${source_default.red("(not found)")}`);
126172
+ }
126005
126173
  console.log(source_default.bold("VS Code"));
126006
126174
  if (vsCodeResult.found) {
126007
126175
  console.log(` ${source_default.green("\u2713")} Settings found: ${source_default.gray(vsCodeResult.path)}`);
@@ -126009,20 +126177,37 @@ mcpCommand.command("status").description("Show MCP server registration status").
126009
126177
  console.log(` ${source_default.yellow("\u26A0")} settings.json not found`);
126010
126178
  }
126011
126179
  console.log();
126180
+ const allClaude = REQUIRED_MCP_SERVERS.every((s) => s.name in (claudeSettings.servers || {}));
126012
126181
  const allCli = cliResult?.allInstalled ?? false;
126013
126182
  const allVsCode = REQUIRED_MCP_SERVERS.every((s) => s.name in (vsCodeResult.servers || {}));
126014
- if (allCli && allVsCode) {
126015
- logger.box(["All MCP servers registered in CLI and VS Code!"], "success");
126183
+ if (allClaude && allCli && allVsCode) {
126184
+ logger.box(["All MCP servers registered everywhere!"], "success");
126185
+ } else if (allClaude) {
126186
+ logger.box([
126187
+ "MCP servers registered in Claude Code settings.",
126188
+ !allCli ? "CLI: Missing (run ss mcp install)" : "",
126189
+ !allVsCode ? "VS Code: Missing (run ss mcp install)" : ""
126190
+ ].filter(Boolean), "warning");
126016
126191
  } else {
126017
126192
  logger.box([
126018
- "Some MCP servers are not registered.",
126193
+ "MCP servers NOT registered in ~/.claude/settings.json!",
126194
+ "This is required for VS Code extension to work.",
126019
126195
  "",
126020
126196
  `Fix with: ${source_default.cyan("ss mcp install")}`
126021
- ], "warning");
126197
+ ], "error");
126022
126198
  }
126023
126199
  });
126024
126200
  mcpCommand.command("remove").description("Unregister MCP servers from CLI and VS Code").option("--cli-only", "Only remove from Claude Code CLI").option("--vscode-only", "Only remove from VS Code settings").action(async (options) => {
126025
126201
  logger.header("MCP Server Removal");
126202
+ const serverNames = REQUIRED_MCP_SERVERS.map((s) => s.name);
126203
+ logger.info("Removing from ~/.claude/settings.json...");
126204
+ const claudeResult = await unregisterMcpFromClaudeSettings(serverNames);
126205
+ if (claudeResult.success) {
126206
+ logger.success("Removed MCP servers from Claude Code settings");
126207
+ } else {
126208
+ logger.error(`Failed to remove from Claude Code settings: ${claudeResult.error}`);
126209
+ }
126210
+ console.log();
126026
126211
  if (!options.vscodeOnly) {
126027
126212
  logger.info("Removing from Claude Code CLI...");
126028
126213
  for (const server of REQUIRED_MCP_SERVERS) {
@@ -126041,7 +126226,6 @@ mcpCommand.command("remove").description("Unregister MCP servers from CLI and VS
126041
126226
  }
126042
126227
  if (!options.cliOnly) {
126043
126228
  logger.info("Removing from VS Code settings...");
126044
- const serverNames = REQUIRED_MCP_SERVERS.map((s) => s.name);
126045
126229
  const result = await unregisterMcpFromVsCode(serverNames);
126046
126230
  if (result.skipped) {
126047
126231
  logger.warning("VS Code settings.json not found - skipping");