@mcpcloud/cli 0.14.0 → 0.15.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 (3) hide show
  1. package/README.md +1 -0
  2. package/dist/index.js +315 -180
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -377,6 +377,7 @@ _Generated from the live command tree by `bun run docs:readme` — do not edit b
377
377
  | `mcp skills installations <skill>` | List the installation footprint of a skill (which orgs / users installed it) |
378
378
  | `mcp skills invoke <skill>` | Run a deployed skill from the terminal. Resolves the skill’s MCP endpoint, auto-discovers its single tool, and calls it. |
379
379
  | `mcp skills list` | List skills in an organization |
380
+ | `mcp skills pull <registryArtifactId>` | Download an installed skill as SKILL.md + mcpcloud.json for your coding agent |
380
381
  | `mcp skills test-runs` | Inspect and trigger skill sandbox test runs |
381
382
  | `mcp skills test-runs get <testRunId>` | Show one skill test run with assertions, trace, and output |
382
383
  | `mcp skills test-runs list <skill>` | List sandbox test runs for a skill |
package/dist/index.js CHANGED
@@ -4030,7 +4030,7 @@ function configFile() {
4030
4030
  return join(configDir(), "config.json");
4031
4031
  }
4032
4032
  var DEFAULT_PROFILE_NAME = "default";
4033
- var DEFAULT_BASE_URL = "https://majestic-lobster-858.convex.site";
4033
+ var DEFAULT_BASE_URL = "https://api.mcpcloud.sh";
4034
4034
  var PRODUCTION_BASE_URL = DEFAULT_BASE_URL;
4035
4035
  var DEFAULT_APP_URL = "https://mcpcloud.sh";
4036
4036
 
@@ -10981,7 +10981,7 @@ function parseTimeoutMs(value, fallbackMs) {
10981
10981
  return Math.round(n * 1000);
10982
10982
  }
10983
10983
  function registerSkillInvokeCommand(skills) {
10984
- skills.command("invoke <skill>").description("Run a deployed skill from the terminal. Resolves the skill’s MCP endpoint, auto-discovers its single tool, and calls it.").option("--org <organizationId>", "Organization ID (overrides default)").option("--input <json>", "Skill input as inline JSON, `@path/to/input.json`, or `@-` for stdin. Defaults to `{}`.").option("--tool <name>", "Override the auto-discovered tool name (a deployed skill normally exposes exactly one)").option("--timeout <seconds>", "Request timeout in seconds (default 60, max 600)").option("--raw", "Print the raw JSON-RPC `result` envelope").addHelpText("after", [
10984
+ skills.command("invoke <skill>").description("Run a deployed skill from the terminal. Resolves the skill’s MCP endpoint, auto-discovers its single tool, and calls it.").option("--org <organizationId>", "Organization ID (overrides default)").option("--input <json>", "Skill input as inline JSON, `@path/to/input.json`, or `@-` for stdin. Defaults to `{}`.").option("--tool <name>", "Override the auto-discovered tool name (a deployed skill normally exposes exactly one)").option("--timeout <seconds>", "Request timeout in seconds (default 60, max 600)").option("--raw", "Print the raw JSON-RPC `result` envelope").option("--token <token>", "Skill runtime token (skr_…). Prefer --token-stdin.").option("--token-stdin", "Read the skill runtime token from stdin (recommended — keeps it out of argv)").addHelpText("after", [
10985
10985
  "",
10986
10986
  "Examples:",
10987
10987
  ` $ mcp skills invoke skill_123 --input '{"topic":"weather"}'`,
@@ -11017,13 +11017,29 @@ async function runSkillInvoke(skillRef, opts) {
11017
11017
  if (active.status !== "active") {
11018
11018
  printWarn(`Skill deployment is ${active.status}, not active — the call may be refused.`);
11019
11019
  }
11020
+ const runtimeToken = opts.tokenStdin ? await readStdin2() : opts.token?.trim() ?? "";
11021
+ if (!runtimeToken) {
11022
+ if (isJsonMode()) {
11023
+ printJson({
11024
+ ok: false,
11025
+ error: "runtime_token_required",
11026
+ hint: "Pass --token-stdin (or --token). Reveal the token on the skill's deployment card."
11027
+ });
11028
+ } else {
11029
+ printError("A skill endpoint requires an Authorization: Bearer token — none was provided.");
11030
+ printWarn(`Reveal it on the skill's deployment card, then: echo "$SKILL_TOKEN" | mcp skills invoke <skill> --token-stdin`);
11031
+ }
11032
+ throw new CliExitError(1);
11033
+ }
11034
+ const headers = { Authorization: `Bearer ${runtimeToken}` };
11020
11035
  const timeoutMs = parseTimeoutMs(opts.timeout, 60000);
11021
- const toolName = opts.tool ?? await discoverSkillTool(active.mcpUrl, timeoutMs);
11036
+ const toolName = opts.tool ?? await discoverSkillTool(active.mcpUrl, timeoutMs, headers);
11022
11037
  const result = await invokeMcpTool({
11023
11038
  url: active.mcpUrl,
11024
11039
  toolName,
11025
11040
  toolArguments: parsedInput.ok ? parsedInput.value : {},
11026
- timeoutMs
11041
+ timeoutMs,
11042
+ headers
11027
11043
  });
11028
11044
  if (isJsonMode()) {
11029
11045
  printJson({
@@ -11057,8 +11073,15 @@ async function runSkillInvoke(skillRef, opts) {
11057
11073
  printWarn(`Skill reported isError=true. Inspect ${c.bold("--json")} or ${c.bold("--raw")} for the full envelope.`);
11058
11074
  }
11059
11075
  }
11060
- async function discoverSkillTool(mcpUrl, timeoutMs) {
11061
- const listed = await listMcpTools({ url: mcpUrl, timeoutMs });
11076
+ async function readStdin2() {
11077
+ const chunks = [];
11078
+ for await (const chunk of process.stdin) {
11079
+ chunks.push(Buffer.from(chunk));
11080
+ }
11081
+ return Buffer.concat(chunks).toString("utf8").trim();
11082
+ }
11083
+ async function discoverSkillTool(mcpUrl, timeoutMs, headers) {
11084
+ const listed = await listMcpTools({ url: mcpUrl, timeoutMs, headers });
11062
11085
  if (!listed.ok) {
11063
11086
  const detail = listed.reason === "rpc-error" ? listed.error.message : `${listed.status > 0 ? `HTTP ${listed.status}` : "network error"}: ${listed.message}`;
11064
11087
  printError(`Could not list the skill's tools to auto-discover the entry point (${detail}). Pass --tool <name> to call it directly.`);
@@ -11104,15 +11127,98 @@ function invokeResultToJson(result) {
11104
11127
  };
11105
11128
  }
11106
11129
 
11130
+ // src/commands/skills-pull.ts
11131
+ import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync7 } from "node:fs";
11132
+ import { dirname as dirname6, isAbsolute as isAbsolute3, join as join11, resolve as resolve7 } from "node:path";
11133
+ function formatBytes2(bytes) {
11134
+ if (bytes < 1024)
11135
+ return `${bytes} B`;
11136
+ return `${(bytes / 1024).toFixed(1)} KB`;
11137
+ }
11138
+ function assertSafeRelativePath2(path) {
11139
+ if (isAbsolute3(path) || path.split(/[\\/]/).includes("..")) {
11140
+ throw new Error(`Refusing to write unsafe package path: ${path}`);
11141
+ }
11142
+ }
11143
+ function registerSkillPullCommand(skills) {
11144
+ skills.command("pull <registryArtifactId>").description("Download an installed skill as SKILL.md + mcpcloud.json for your coding agent").option("--org <organizationId>", "Organization ID").option("--output <dir>", "Write the package files to a directory (default: ./<slug>)").option("--skill-version <semver>", "Published version (defaults to the latest)").addHelpText("after", [
11145
+ "",
11146
+ "Examples:",
11147
+ " # Pull a skill you installed from the marketplace:",
11148
+ " $ mcp skills pull p179hst... --output ./skills/ship-an-mcp-server",
11149
+ "",
11150
+ " # Then point your agent at the servers it needs:",
11151
+ " $ cat ./skills/ship-an-mcp-server/mcpcloud.json"
11152
+ ].join(`
11153
+ `)).action(runAction(async (registryArtifactId, opts) => {
11154
+ const organizationId = await resolveOrgId(opts.org);
11155
+ const result = await api.post("/api/v1/skill/package", {
11156
+ organizationId,
11157
+ registryArtifactId,
11158
+ ...opts.skillVersion ? { version: opts.skillVersion } : {}
11159
+ });
11160
+ const dir = resolve7(opts.output ?? `./${result.skill.slug}`);
11161
+ for (const file of result.files) {
11162
+ assertSafeRelativePath2(file.path);
11163
+ const full = join11(dir, file.path);
11164
+ mkdirSync8(dirname6(full), { recursive: true });
11165
+ writeFileSync7(full, file.content);
11166
+ }
11167
+ if (isJsonMode()) {
11168
+ printJson({
11169
+ skill: result.skill,
11170
+ fileCount: result.fileCount,
11171
+ byteSize: result.byteSize,
11172
+ dependencies: result.dependencies,
11173
+ output: dir
11174
+ });
11175
+ return;
11176
+ }
11177
+ printSuccess(`Pulled ${result.skill.name} v${result.skill.version} (${result.fileCount} files, ${formatBytes2(result.byteSize)}) to ${dir}.`);
11178
+ const missing = result.dependencies.filter((entry) => !entry.installed);
11179
+ if (result.dependencies.length === 0) {
11180
+ printKeyValue({
11181
+ Next: `Copy ${join11(dir, "SKILL.md")} into the skills directory your agent reads.`
11182
+ });
11183
+ return;
11184
+ }
11185
+ printKeyValue({
11186
+ Next: `Copy ${join11(dir, "SKILL.md")} into the skills directory your agent reads.`,
11187
+ Servers: result.dependencies.map((entry) => `${entry.name}${entry.installed ? "" : " (not installed)"}`).join(", ")
11188
+ });
11189
+ if (missing.length > 0) {
11190
+ printKeyValue({
11191
+ "Heads up": `Install ${missing.map((entry) => entry.name).join(", ")} before running this skill.`
11192
+ });
11193
+ }
11194
+ }));
11195
+ }
11196
+
11107
11197
  // src/commands/skills.ts
11108
- async function runClaudeMcpAdd(connectionName, mcpUrl) {
11109
- return new Promise((resolve7) => {
11110
- const child = spawn3("claude", ["mcp", "add", "--transport", "http", connectionName, mcpUrl], {
11198
+ async function readStdin3() {
11199
+ const chunks = [];
11200
+ for await (const chunk of process.stdin) {
11201
+ chunks.push(Buffer.from(chunk));
11202
+ }
11203
+ return Buffer.concat(chunks).toString("utf8").trim();
11204
+ }
11205
+ async function runClaudeMcpAdd(connectionName, mcpUrl, bearerToken) {
11206
+ return new Promise((resolve8) => {
11207
+ const child = spawn3("claude", [
11208
+ "mcp",
11209
+ "add",
11210
+ "--transport",
11211
+ "http",
11212
+ connectionName,
11213
+ mcpUrl,
11214
+ "--header",
11215
+ `Authorization: Bearer ${bearerToken}`
11216
+ ], {
11111
11217
  stdio: "inherit",
11112
11218
  shell: false
11113
11219
  });
11114
- child.on("error", () => resolve7(127));
11115
- child.on("exit", (code) => resolve7(code ?? 1));
11220
+ child.on("error", () => resolve8(127));
11221
+ child.on("exit", (code) => resolve8(code ?? 1));
11116
11222
  });
11117
11223
  }
11118
11224
  function registerSkillCommands(program2) {
@@ -11120,6 +11226,7 @@ function registerSkillCommands(program2) {
11120
11226
  registerSkillMutationCommands(skills);
11121
11227
  registerSkillTestCommands(skills);
11122
11228
  registerSkillInvokeCommand(skills);
11229
+ registerSkillPullCommand(skills);
11123
11230
  skills.command("list").description("List skills in an organization").option("--org <organizationId>", "Organization ID").option("--project <project>", "Filter by project (id or name)").option("--limit <n>", "Maximum results (default 25)", parsePositiveIntOption("limit"), "25").addHelpText("after", [
11124
11231
  "",
11125
11232
  "Examples:",
@@ -11181,7 +11288,8 @@ function registerSkillCommands(program2) {
11181
11288
  "mcp endpoint": s.activeDeployment?.mcpUrl ?? "—"
11182
11289
  });
11183
11290
  }));
11184
- skills.command("connect <skill>").description("Print (or apply) the MCP configuration that connects this skill to your coding agent").option("--org <organizationId>", "Organization ID").option("--agent <agent>", `Agent preset: ${AGENT_KEYS.join(", ")}`, "claude-code").option("--name <name>", "Override the connection name shown in the agent (defaults to the skill slug)").option("--apply", 'For claude-code: invoke "claude mcp add" automatically. Other agents print only.').action(runAction(async (skillRef, opts) => {
11291
+ skills.command("connect <skill>").description("Print (or apply) the MCP configuration that connects this skill to your coding agent").option("--org <organizationId>", "Organization ID").option("--agent <agent>", `Agent preset: ${AGENT_KEYS.join(", ")}`, "claude-code").option("--name <name>", "Override the connection name shown in the agent (defaults to the skill slug)").option("--apply", 'For claude-code: invoke "claude mcp add" automatically. Other agents print only.').option("--token <token>", "Skill runtime token (skr_…) to inline into --apply. Prefer --token-stdin.").option("--token-stdin", "Read the skill runtime token from stdin (recommended — keeps it out of argv)").action(runAction(async (skillRef, opts) => {
11292
+ const runtimeToken = opts.tokenStdin ? await readStdin3() : opts.token?.trim() ?? "";
11185
11293
  if (!isAgentKey(opts.agent)) {
11186
11294
  printError(`Unknown --agent '${opts.agent}'. Valid values: ${AGENT_KEYS.join(", ")}.`);
11187
11295
  throw new CliExitError(1);
@@ -11227,10 +11335,23 @@ function registerSkillCommands(program2) {
11227
11335
  }
11228
11336
  throw new CliExitError(1);
11229
11337
  }
11338
+ if (!runtimeToken) {
11339
+ if (isJsonMode()) {
11340
+ printJson({
11341
+ ok: false,
11342
+ error: "runtime_token_required",
11343
+ hint: "Pass --token-stdin (or --token). Reveal the token on the skill's deployment card."
11344
+ });
11345
+ } else {
11346
+ printError("A skill endpoint requires an Authorization: Bearer token, so --apply needs one too.");
11347
+ printInfo(`Reveal it on the skill's deployment card, then: echo "$SKILL_TOKEN" | mcp skills connect <skill> --apply --token-stdin`);
11348
+ }
11349
+ throw new CliExitError(1);
11350
+ }
11230
11351
  if (!isJsonMode()) {
11231
- printInfo(`Applying via "claude mcp add --transport http ${connectionName} ${deployment.mcpUrl}"…`);
11352
+ printInfo(`Applying via "claude mcp add --transport http ${connectionName} ${deployment.mcpUrl} --header …"…`);
11232
11353
  }
11233
- const code = await runClaudeMcpAdd(connectionName, deployment.mcpUrl);
11354
+ const code = await runClaudeMcpAdd(connectionName, deployment.mcpUrl, runtimeToken);
11234
11355
  if (code === 127) {
11235
11356
  if (isJsonMode()) {
11236
11357
  printJson({
@@ -11286,7 +11407,10 @@ function registerSkillCommands(program2) {
11286
11407
  agent: preset.key,
11287
11408
  connectionName,
11288
11409
  location: preset.location,
11289
- snippet: preset.snippet
11410
+ snippet: preset.snippet,
11411
+ requiresAuthHeader: true,
11412
+ authHeader: "Authorization",
11413
+ authScheme: "Bearer"
11290
11414
  });
11291
11415
  return;
11292
11416
  }
@@ -11298,6 +11422,12 @@ function registerSkillCommands(program2) {
11298
11422
  printInfo(`Add this to ${preset.location}`);
11299
11423
  printInfo("");
11300
11424
  printInfo(preset.snippet);
11425
+ printInfo("");
11426
+ printWarn("This endpoint requires an Authorization: Bearer <skill runtime token> header — the snippet above does not include one.");
11427
+ printInfo("Reveal the token on the skill's deployment card, then add it to your client's header config.");
11428
+ if (agent === "claude-code") {
11429
+ printInfo(` claude mcp add --transport http ${connectionName} ${deployment.mcpUrl} --header "Authorization: Bearer <token>"`);
11430
+ }
11301
11431
  if (preset.applyHint) {
11302
11432
  printInfo("");
11303
11433
  printInfo(preset.applyHint);
@@ -11780,9 +11910,9 @@ function registerDomainCommands(program2) {
11780
11910
 
11781
11911
  // src/commands/config.ts
11782
11912
  import { homedir as homedir2 } from "node:os";
11783
- import { join as join11 } from "node:path";
11913
+ import { join as join12 } from "node:path";
11784
11914
  function configFilePath() {
11785
- return join11(homedir2(), ".mcpcloud", "config.json");
11915
+ return join12(homedir2(), ".mcpcloud", "config.json");
11786
11916
  }
11787
11917
  function previewKey2(key) {
11788
11918
  if (!key)
@@ -12028,34 +12158,34 @@ function registerConfigCommands(program2) {
12028
12158
 
12029
12159
  // src/commands/dev.ts
12030
12160
  import { existsSync as existsSync33 } from "node:fs";
12031
- import { isAbsolute as isAbsolute3, relative as relative7, resolve as resolve8 } from "node:path";
12161
+ import { isAbsolute as isAbsolute4, relative as relative7, resolve as resolve9 } from "node:path";
12032
12162
 
12033
12163
  // src/lib/dev/sessions.ts
12034
12164
  import {
12035
12165
  existsSync as existsSync14,
12036
- mkdirSync as mkdirSync8,
12166
+ mkdirSync as mkdirSync9,
12037
12167
  readFileSync as readFileSync12,
12038
12168
  readdirSync as readdirSync2,
12039
12169
  unlinkSync,
12040
- writeFileSync as writeFileSync7
12170
+ writeFileSync as writeFileSync8
12041
12171
  } from "node:fs";
12042
12172
  import { homedir as homedir3 } from "node:os";
12043
- import { join as join12 } from "node:path";
12173
+ import { join as join13 } from "node:path";
12044
12174
  var SESSIONS_DIR_NAME = "dev-sessions";
12045
12175
  function sessionsDir() {
12046
- return join12(homedir3(), ".mcpcloud", SESSIONS_DIR_NAME);
12176
+ return join13(homedir3(), ".mcpcloud", SESSIONS_DIR_NAME);
12047
12177
  }
12048
12178
  function sessionFile(pid) {
12049
- return join12(sessionsDir(), `${pid}.json`);
12179
+ return join13(sessionsDir(), `${pid}.json`);
12050
12180
  }
12051
12181
  function ensureDir() {
12052
12182
  const dir = sessionsDir();
12053
12183
  if (!existsSync14(dir))
12054
- mkdirSync8(dir, { recursive: true, mode: 448 });
12184
+ mkdirSync9(dir, { recursive: true, mode: 448 });
12055
12185
  }
12056
12186
  function recordSession(record) {
12057
12187
  ensureDir();
12058
- writeFileSync7(sessionFile(record.pid), JSON.stringify(record, null, 2), {
12188
+ writeFileSync8(sessionFile(record.pid), JSON.stringify(record, null, 2), {
12059
12189
  encoding: "utf-8",
12060
12190
  mode: 384
12061
12191
  });
@@ -12076,7 +12206,7 @@ function listSessions() {
12076
12206
  for (const entry of readdirSync2(dir)) {
12077
12207
  if (!entry.endsWith(".json"))
12078
12208
  continue;
12079
- const path = join12(dir, entry);
12209
+ const path = join13(dir, entry);
12080
12210
  try {
12081
12211
  const parsed = JSON.parse(readFileSync12(path, "utf-8"));
12082
12212
  if (typeof parsed.pid !== "number") {
@@ -12271,27 +12401,27 @@ function invokeResultToJson2(result) {
12271
12401
  import {
12272
12402
  appendFileSync as appendFileSync2,
12273
12403
  existsSync as existsSync15,
12274
- mkdirSync as mkdirSync9,
12404
+ mkdirSync as mkdirSync10,
12275
12405
  readFileSync as readFileSync13,
12276
12406
  readdirSync as readdirSync3,
12277
12407
  renameSync,
12278
12408
  statSync as statSync2
12279
12409
  } from "node:fs";
12280
- import { join as join13 } from "node:path";
12410
+ import { join as join14 } from "node:path";
12281
12411
  var INSPECTOR_DIRNAME = "inspector";
12282
12412
  var ACTIVE_FILE = "calls.ndjson";
12283
12413
  var ROTATED_PREFIX = "calls.";
12284
12414
  var ROTATED_SUFFIX = ".ndjson";
12285
12415
  var ROTATION_LIMIT_BYTES = 50 * 1024 * 1024;
12286
12416
  function inspectorDir(cwd) {
12287
- return join13(devRoot(cwd), INSPECTOR_DIRNAME);
12417
+ return join14(devRoot(cwd), INSPECTOR_DIRNAME);
12288
12418
  }
12289
12419
  function ensureInspectorDir(dir) {
12290
12420
  if (!existsSync15(dir))
12291
- mkdirSync9(dir, { recursive: true });
12421
+ mkdirSync10(dir, { recursive: true });
12292
12422
  }
12293
12423
  function activeFilePath(dir) {
12294
- return join13(dir, ACTIVE_FILE);
12424
+ return join14(dir, ACTIVE_FILE);
12295
12425
  }
12296
12426
  function isRotatedName(name) {
12297
12427
  return name !== ACTIVE_FILE && name.startsWith(ROTATED_PREFIX) && name.endsWith(ROTATED_SUFFIX);
@@ -12301,7 +12431,7 @@ function listRotatedFiles(dir) {
12301
12431
  return [];
12302
12432
  const rotated = readdirSync3(dir).filter(isRotatedName);
12303
12433
  rotated.sort();
12304
- return rotated.map((n) => join13(dir, n));
12434
+ return rotated.map((n) => join14(dir, n));
12305
12435
  }
12306
12436
  function parseLines(text) {
12307
12437
  if (!text)
@@ -12526,7 +12656,7 @@ import {
12526
12656
  closeSync,
12527
12657
  statSync as statSync3
12528
12658
  } from "node:fs";
12529
- import { join as join14 } from "node:path";
12659
+ import { join as join15 } from "node:path";
12530
12660
  var DEFAULT_INTERVAL_MS = 250;
12531
12661
  var MAX_READ_CHUNK = 64 * 1024;
12532
12662
  function registerDevTailCommand(dev) {
@@ -12535,7 +12665,7 @@ function registerDevTailCommand(dev) {
12535
12665
  async function runDevTail(opts) {
12536
12666
  const cwd = process.cwd();
12537
12667
  const dir = inspectorDir(cwd);
12538
- const activePath = join14(dir, ACTIVE_FILE);
12668
+ const activePath = join15(dir, ACTIVE_FILE);
12539
12669
  const intervalMs = parseInterval(opts.intervalMs);
12540
12670
  if (!existsSync16(dir)) {
12541
12671
  printInfo(`No inspector history yet at ${dir}. Run \`mcp dev\` to start capturing.`);
@@ -12643,7 +12773,7 @@ function emitLines(text, filter) {
12643
12773
  }
12644
12774
  }
12645
12775
  function sleep(ms) {
12646
- return new Promise((resolve7) => setTimeout(resolve7, ms));
12776
+ return new Promise((resolve8) => setTimeout(resolve8, ms));
12647
12777
  }
12648
12778
 
12649
12779
  // src/lib/dev/bootstrap.ts
@@ -12761,12 +12891,12 @@ async function runInteractiveBootstrap() {
12761
12891
  // src/lib/dev/bundle-sync.ts
12762
12892
  import {
12763
12893
  existsSync as existsSync17,
12764
- mkdirSync as mkdirSync10,
12894
+ mkdirSync as mkdirSync11,
12765
12895
  readFileSync as readFileSync14,
12766
12896
  rmSync as rmSync2,
12767
- writeFileSync as writeFileSync8
12897
+ writeFileSync as writeFileSync9
12768
12898
  } from "node:fs";
12769
- import { dirname as dirname6, join as join15 } from "node:path";
12899
+ import { dirname as dirname7, join as join16 } from "node:path";
12770
12900
  async function resolveServerProject(args) {
12771
12901
  const data = await api.get("/api/v1/server", {
12772
12902
  organizationId: args.organizationId,
@@ -12828,7 +12958,7 @@ async function fetchBundle(args) {
12828
12958
  }
12829
12959
  function materializeBundle(destDir, bundle, options = {}) {
12830
12960
  if (!existsSync17(destDir)) {
12831
- mkdirSync10(destDir, { recursive: true });
12961
+ mkdirSync11(destDir, { recursive: true });
12832
12962
  }
12833
12963
  const preserve = options.preservePaths;
12834
12964
  const kept = new Set;
@@ -12843,9 +12973,9 @@ function materializeBundle(destDir, bundle, options = {}) {
12843
12973
  preservedCount += 1;
12844
12974
  continue;
12845
12975
  }
12846
- const target = join15(destDir, safePath);
12847
- mkdirSync10(dirname6(target), { recursive: true });
12848
- writeFileSync8(target, file.content, "utf-8");
12976
+ const target = join16(destDir, safePath);
12977
+ mkdirSync11(dirname7(target), { recursive: true });
12978
+ writeFileSync9(target, file.content, "utf-8");
12849
12979
  writtenCount += 1;
12850
12980
  }
12851
12981
  let removed = 0;
@@ -12873,7 +13003,7 @@ function pruneStaleFiles(rootDir, currentDir, kept) {
12873
13003
  const { relative: relative6 } = __require("node:path");
12874
13004
  let removed = 0;
12875
13005
  for (const entry of readdirSync4(currentDir)) {
12876
- const abs = join15(currentDir, entry);
13006
+ const abs = join16(currentDir, entry);
12877
13007
  const stat = statSync4(abs);
12878
13008
  if (stat.isDirectory()) {
12879
13009
  removed += pruneStaleFiles(rootDir, abs, kept);
@@ -12940,7 +13070,7 @@ function startGitPullPoll(args) {
12940
13070
  // src/lib/dev/editor.ts
12941
13071
  import { spawn as spawn4 } from "node:child_process";
12942
13072
  import { existsSync as existsSync18, statSync as statSync4 } from "node:fs";
12943
- import { delimiter as delimiter2, join as join16 } from "node:path";
13073
+ import { delimiter as delimiter2, join as join17 } from "node:path";
12944
13074
  import { platform as platform3 } from "node:os";
12945
13075
  var TARGET_LABEL = {
12946
13076
  tools: "tool metadata",
@@ -12976,7 +13106,7 @@ function findOnPath2(command) {
12976
13106
  if (!dir)
12977
13107
  continue;
12978
13108
  for (const ext of exts) {
12979
- const candidate = join16(dir, command + ext);
13109
+ const candidate = join17(dir, command + ext);
12980
13110
  if (existsSync18(candidate) && isExecutable(candidate))
12981
13111
  return candidate;
12982
13112
  }
@@ -13258,7 +13388,7 @@ function parseOpenChoice(raw) {
13258
13388
 
13259
13389
  // src/lib/dev/file-watcher.ts
13260
13390
  import { existsSync as existsSync19, statSync as statSync5, watch as fsWatch2 } from "node:fs";
13261
- import { join as join17 } from "node:path";
13391
+ import { join as join18 } from "node:path";
13262
13392
  var DEFAULT_IGNORE = ["node_modules", ".git", "_mcpsh_host.mjs"];
13263
13393
  function watchDir(options) {
13264
13394
  if (!existsSync19(options.rootDir)) {
@@ -13297,7 +13427,7 @@ function watchDir(options) {
13297
13427
  for (const entry of readdirSync4(options.rootDir)) {
13298
13428
  if (ignore.has(entry))
13299
13429
  continue;
13300
- const sub = join17(options.rootDir, entry);
13430
+ const sub = join18(options.rootDir, entry);
13301
13431
  try {
13302
13432
  const stat = statSync5(sub);
13303
13433
  if (!stat.isDirectory())
@@ -13564,7 +13694,7 @@ async function handleOne2(args) {
13564
13694
  // src/lib/dev/local-runtime.ts
13565
13695
  import { spawn as spawn5 } from "node:child_process";
13566
13696
  import { existsSync as existsSync22 } from "node:fs";
13567
- import { join as join18 } from "node:path";
13697
+ import { join as join19 } from "node:path";
13568
13698
  function detectRuntime(preferred = "auto") {
13569
13699
  if (preferred === "bun" || preferred === "node")
13570
13700
  return preferred;
@@ -13601,52 +13731,52 @@ function startRuntime(options) {
13601
13731
  if (child.exitCode !== null)
13602
13732
  return;
13603
13733
  child.kill("SIGTERM");
13604
- await new Promise((resolve7) => {
13734
+ await new Promise((resolve8) => {
13605
13735
  const timer = setTimeout(() => {
13606
13736
  if (child.exitCode === null)
13607
13737
  child.kill("SIGKILL");
13608
- resolve7();
13738
+ resolve8();
13609
13739
  }, 3000);
13610
13740
  child.once("exit", () => {
13611
13741
  clearTimeout(timer);
13612
- resolve7();
13742
+ resolve8();
13613
13743
  });
13614
13744
  });
13615
13745
  }
13616
13746
  };
13617
13747
  }
13618
13748
  async function installDependencies(options) {
13619
- const pkgPath = join18(options.serverDir, "package.json");
13749
+ const pkgPath = join19(options.serverDir, "package.json");
13620
13750
  if (!existsSync22(pkgPath))
13621
13751
  return { ran: false, exitCode: null };
13622
- const nodeModules = join18(options.serverDir, "node_modules");
13752
+ const nodeModules = join19(options.serverDir, "node_modules");
13623
13753
  if (options.skipIfPresent !== false && existsSync22(nodeModules)) {
13624
13754
  return { ran: false, exitCode: 0 };
13625
13755
  }
13626
13756
  options.onStep?.("Installing dependencies (bun install)…");
13627
- return await new Promise((resolve7) => {
13757
+ return await new Promise((resolve8) => {
13628
13758
  const child = spawn5("bun", ["install", "--silent"], {
13629
13759
  cwd: options.serverDir,
13630
13760
  stdio: "inherit"
13631
13761
  });
13632
- child.on("error", () => resolve7({ ran: true, exitCode: 127 }));
13633
- child.on("exit", (code) => resolve7({ ran: true, exitCode: code }));
13762
+ child.on("error", () => resolve8({ ran: true, exitCode: 127 }));
13763
+ child.on("exit", (code) => resolve8({ ran: true, exitCode: code }));
13634
13764
  });
13635
13765
  }
13636
13766
 
13637
13767
  // src/lib/dev/prepare.ts
13638
- import { existsSync as existsSync26, writeFileSync as writeFileSync12 } from "node:fs";
13639
- import { join as join22, relative as relative6 } from "node:path";
13768
+ import { existsSync as existsSync26, writeFileSync as writeFileSync13 } from "node:fs";
13769
+ import { join as join23, relative as relative6 } from "node:path";
13640
13770
 
13641
13771
  // src/lib/dev/git-clone.ts
13642
13772
  import { spawnSync } from "node:child_process";
13643
13773
  import {
13644
13774
  existsSync as existsSync23,
13645
- mkdirSync as mkdirSync11,
13775
+ mkdirSync as mkdirSync12,
13646
13776
  readFileSync as readFileSync15,
13647
- writeFileSync as writeFileSync9
13777
+ writeFileSync as writeFileSync10
13648
13778
  } from "node:fs";
13649
- import { dirname as dirname7, join as join19 } from "node:path";
13779
+ import { dirname as dirname8, join as join20 } from "node:path";
13650
13780
 
13651
13781
  class GitNotAvailableError extends Error {
13652
13782
  constructor() {
@@ -13719,21 +13849,21 @@ function isGitAvailable() {
13719
13849
  }
13720
13850
  }
13721
13851
  function applyLocalExcludes(repoDir) {
13722
- const excludePath = join19(repoDir, ".git", "info", "exclude");
13852
+ const excludePath = join20(repoDir, ".git", "info", "exclude");
13723
13853
  const existing = existsSync23(excludePath) ? readFileSync15(excludePath, "utf-8") : "";
13724
13854
  const next = mergeLocalExcludes(existing);
13725
13855
  if (next === null)
13726
13856
  return;
13727
- if (!existsSync23(dirname7(excludePath))) {
13728
- mkdirSync11(dirname7(excludePath), { recursive: true });
13857
+ if (!existsSync23(dirname8(excludePath))) {
13858
+ mkdirSync12(dirname8(excludePath), { recursive: true });
13729
13859
  }
13730
- writeFileSync9(excludePath, next, "utf-8");
13860
+ writeFileSync10(excludePath, next, "utf-8");
13731
13861
  }
13732
13862
  function ensureClone(opts) {
13733
13863
  if (!isGitAvailable()) {
13734
13864
  throw new GitNotAvailableError;
13735
13865
  }
13736
- if (existsSync23(join19(opts.repoDir, ".git"))) {
13866
+ if (existsSync23(join20(opts.repoDir, ".git"))) {
13737
13867
  opts.onStep?.("Refreshing existing clone (git fetch)…");
13738
13868
  runGit(gitFetchArgs(opts.branch), opts.repoDir);
13739
13869
  applyLocalExcludes(opts.repoDir);
@@ -13749,12 +13879,12 @@ function ensureClone(opts) {
13749
13879
  }
13750
13880
 
13751
13881
  // src/lib/dev/host-runtime.ts
13752
- import { existsSync as existsSync25, mkdirSync as mkdirSync13, writeFileSync as writeFileSync11 } from "node:fs";
13753
- import { dirname as dirname8, join as join21 } from "node:path";
13882
+ import { existsSync as existsSync25, mkdirSync as mkdirSync14, writeFileSync as writeFileSync12 } from "node:fs";
13883
+ import { dirname as dirname9, join as join22 } from "node:path";
13754
13884
 
13755
13885
  // src/lib/dev/inspector-module.ts
13756
- import { existsSync as existsSync24, mkdirSync as mkdirSync12, writeFileSync as writeFileSync10 } from "node:fs";
13757
- import { join as join20 } from "node:path";
13886
+ import { existsSync as existsSync24, mkdirSync as mkdirSync13, writeFileSync as writeFileSync11 } from "node:fs";
13887
+ import { join as join21 } from "node:path";
13758
13888
 
13759
13889
  // src/lib/dev/inspector-assets.ts
13760
13890
  var INSPECTOR_HTML = `<!doctype html>
@@ -28890,9 +29020,9 @@ function buildInspectorModule() {
28890
29020
  }
28891
29021
  function writeInspectorModule(serverDir2) {
28892
29022
  if (!existsSync24(serverDir2))
28893
- mkdirSync12(serverDir2, { recursive: true });
28894
- const target = join20(serverDir2, INSPECTOR_FILE_NAME);
28895
- writeFileSync10(target, buildInspectorModule(), "utf-8");
29023
+ mkdirSync13(serverDir2, { recursive: true });
29024
+ const target = join21(serverDir2, INSPECTOR_FILE_NAME);
29025
+ writeFileSync11(target, buildInspectorModule(), "utf-8");
28896
29026
  return target;
28897
29027
  }
28898
29028
 
@@ -29072,10 +29202,10 @@ function buildHostScript(options) {
29072
29202
  }
29073
29203
  function writeHostScript(serverDir2, options) {
29074
29204
  if (!existsSync25(serverDir2))
29075
- mkdirSync13(serverDir2, { recursive: true });
29076
- const target = join21(serverDir2, HOST_FILE_NAME);
29077
- mkdirSync13(dirname8(target), { recursive: true });
29078
- writeFileSync11(target, buildHostScript(options), "utf-8");
29205
+ mkdirSync14(serverDir2, { recursive: true });
29206
+ const target = join22(serverDir2, HOST_FILE_NAME);
29207
+ mkdirSync14(dirname9(target), { recursive: true });
29208
+ writeFileSync12(target, buildHostScript(options), "utf-8");
29079
29209
  if (options.inspector) {
29080
29210
  writeInspectorModule(serverDir2);
29081
29211
  }
@@ -29108,7 +29238,7 @@ async function prepareDev(opts) {
29108
29238
  projectId = projectId ?? gitLink.projectId;
29109
29239
  serverName = `${gitLink.owner}/${gitLink.name}`;
29110
29240
  repoDir = gitCloneDir(cwd, gitLink.owner, gitLink.name);
29111
- dest = gitLink.pathPrefix ? join22(repoDir, gitLink.pathPrefix) : repoDir;
29241
+ dest = gitLink.pathPrefix ? join23(repoDir, gitLink.pathPrefix) : repoDir;
29112
29242
  printStep(`Git-linked server — cloning ${gitLink.owner}/${gitLink.name}@${gitLink.branch}…`);
29113
29243
  try {
29114
29244
  const result = ensureClone({
@@ -29129,7 +29259,7 @@ async function prepareDev(opts) {
29129
29259
  process.exit(1);
29130
29260
  }
29131
29261
  if (!existsSync26(env)) {
29132
- writeFileSync12(env, `{}
29262
+ writeFileSync13(env, `{}
29133
29263
  `, "utf-8");
29134
29264
  printInfo(` → seeded ${relative6(cwd, env)} (empty; fill secrets here)`);
29135
29265
  }
@@ -29154,7 +29284,7 @@ async function prepareDev(opts) {
29154
29284
  const result = materializeBundle(dest, bundle, { prune: true });
29155
29285
  printInfo(` → wrote ${result.filesWritten} files (pruned ${result.filesRemoved})`);
29156
29286
  if (!existsSync26(env)) {
29157
- writeFileSync12(env, `{}
29287
+ writeFileSync13(env, `{}
29158
29288
  `, "utf-8");
29159
29289
  printInfo(` → seeded ${relative6(cwd, env)} (empty; fill secrets here)`);
29160
29290
  }
@@ -29180,7 +29310,7 @@ async function prepareDev(opts) {
29180
29310
  process.exit(1);
29181
29311
  }
29182
29312
  }
29183
- const entryRel = ENTRY_CANDIDATES.find((c2) => existsSync26(join22(dest, c2)));
29313
+ const entryRel = ENTRY_CANDIDATES.find((c2) => existsSync26(join23(dest, c2)));
29184
29314
  if (!entryRel) {
29185
29315
  printError("Could not locate an entry file (expected src/worker.ts).");
29186
29316
  process.exit(1);
@@ -29338,13 +29468,13 @@ function createBurstGuard() {
29338
29468
  }
29339
29469
 
29340
29470
  // src/lib/dev/agent-connectors/claude-code.ts
29341
- import { existsSync as existsSync28, unlinkSync as unlinkSync2, writeFileSync as writeFileSync14 } from "node:fs";
29471
+ import { existsSync as existsSync28, unlinkSync as unlinkSync2, writeFileSync as writeFileSync15 } from "node:fs";
29342
29472
  import { homedir as homedir4 } from "node:os";
29343
- import { join as join24 } from "node:path";
29473
+ import { join as join25 } from "node:path";
29344
29474
 
29345
29475
  // src/lib/dev/agent-connectors/json-config-utils.ts
29346
- import { existsSync as existsSync27, mkdirSync as mkdirSync14, readFileSync as readFileSync16, writeFileSync as writeFileSync13 } from "node:fs";
29347
- import { dirname as dirname9, join as join23, basename } from "node:path";
29476
+ import { existsSync as existsSync27, mkdirSync as mkdirSync15, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "node:fs";
29477
+ import { dirname as dirname10, join as join24, basename } from "node:path";
29348
29478
  function readJsonFile(path) {
29349
29479
  if (!existsSync27(path))
29350
29480
  return { ok: true, value: {} };
@@ -29362,9 +29492,9 @@ function readJsonFile(path) {
29362
29492
  }
29363
29493
  }
29364
29494
  function atomicWriteJson(path, value) {
29365
- mkdirSync14(dirname9(path), { recursive: true });
29495
+ mkdirSync15(dirname10(path), { recursive: true });
29366
29496
  const tmp = `${path}.mcpsh-${process.pid}-${Date.now()}.tmp`;
29367
- writeFileSync13(tmp, JSON.stringify(value, null, 2) + `
29497
+ writeFileSync14(tmp, JSON.stringify(value, null, 2) + `
29368
29498
  `, "utf-8");
29369
29499
  const { renameSync: renameSync2 } = __require("node:fs");
29370
29500
  renameSync2(tmp, path);
@@ -29373,33 +29503,33 @@ function backupConfig(args) {
29373
29503
  if (!existsSync27(args.configPath)) {
29374
29504
  return { backupPath: null, existed: false };
29375
29505
  }
29376
- mkdirSync14(args.backupsDir, { recursive: true });
29506
+ mkdirSync15(args.backupsDir, { recursive: true });
29377
29507
  const filename = `${args.agentId}__${basename(args.configPath)}.bak`;
29378
- const backupPath = join23(args.backupsDir, filename);
29508
+ const backupPath = join24(args.backupsDir, filename);
29379
29509
  if (!existsSync27(backupPath)) {
29380
29510
  const raw = readFileSync16(args.configPath, "utf-8");
29381
- writeFileSync13(backupPath, raw, "utf-8");
29511
+ writeFileSync14(backupPath, raw, "utf-8");
29382
29512
  }
29383
29513
  return { backupPath, existed: true };
29384
29514
  }
29385
29515
  function restoreFromBackup(args) {
29386
29516
  const filename = `${args.agentId}__${basename(args.configPath)}.bak`;
29387
- const backupPath = join23(args.backupsDir, filename);
29517
+ const backupPath = join24(args.backupsDir, filename);
29388
29518
  if (!existsSync27(backupPath)) {
29389
29519
  return { restored: false };
29390
29520
  }
29391
29521
  const raw = readFileSync16(backupPath, "utf-8");
29392
- mkdirSync14(dirname9(args.configPath), { recursive: true });
29393
- writeFileSync13(args.configPath, raw, "utf-8");
29522
+ mkdirSync15(dirname10(args.configPath), { recursive: true });
29523
+ writeFileSync14(args.configPath, raw, "utf-8");
29394
29524
  return { restored: true };
29395
29525
  }
29396
29526
 
29397
29527
  // src/lib/dev/agent-connectors/claude-code.ts
29398
29528
  function configPath() {
29399
- return join24(homedir4(), ".claude.json");
29529
+ return join25(homedir4(), ".claude.json");
29400
29530
  }
29401
29531
  function legacyConfigPath() {
29402
- return join24(homedir4(), ".claude", "mcp.json");
29532
+ return join25(homedir4(), ".claude", "mcp.json");
29403
29533
  }
29404
29534
  function resolveConfigPath() {
29405
29535
  if (existsSync28(configPath()))
@@ -29414,7 +29544,7 @@ var claudeCodeConnector = {
29414
29544
  hotkey: "c",
29415
29545
  describeLocation: () => resolveConfigPath(),
29416
29546
  async detect() {
29417
- const claudeDir = join24(homedir4(), ".claude");
29547
+ const claudeDir = join25(homedir4(), ".claude");
29418
29548
  if (existsSync28(configPath()) || existsSync28(legacyConfigPath()) || existsSync28(claudeDir)) {
29419
29549
  return { installed: true, note: "Found Claude Code config" };
29420
29550
  }
@@ -29463,7 +29593,7 @@ var claudeCodeConnector = {
29463
29593
  try {
29464
29594
  unlinkSync2(path);
29465
29595
  } catch {
29466
- writeFileSync14(path, `{}
29596
+ writeFileSync15(path, `{}
29467
29597
  `, "utf-8");
29468
29598
  }
29469
29599
  }
@@ -29476,15 +29606,15 @@ var claudeCodeConnector = {
29476
29606
  // src/lib/dev/agent-connectors/codex.ts
29477
29607
  import {
29478
29608
  existsSync as existsSync29,
29479
- mkdirSync as mkdirSync15,
29609
+ mkdirSync as mkdirSync16,
29480
29610
  readFileSync as readFileSync17,
29481
29611
  unlinkSync as unlinkSync3,
29482
- writeFileSync as writeFileSync15
29612
+ writeFileSync as writeFileSync16
29483
29613
  } from "node:fs";
29484
29614
  import { homedir as homedir5 } from "node:os";
29485
- import { dirname as dirname10, join as join25 } from "node:path";
29615
+ import { dirname as dirname11, join as join26 } from "node:path";
29486
29616
  function configPath2() {
29487
- return join25(homedir5(), ".codex", "config.toml");
29617
+ return join26(homedir5(), ".codex", "config.toml");
29488
29618
  }
29489
29619
  var SECTION_PREFIX = "mcp_servers.";
29490
29620
  function buildSection(name, url) {
@@ -29522,7 +29652,7 @@ var codexConnector = {
29522
29652
  hotkey: "x",
29523
29653
  describeLocation: () => configPath2(),
29524
29654
  async detect() {
29525
- if (existsSync29(join25(homedir5(), ".codex")) || existsSync29(configPath2())) {
29655
+ if (existsSync29(join26(homedir5(), ".codex")) || existsSync29(configPath2())) {
29526
29656
  return { installed: true, note: "Found ~/.codex/" };
29527
29657
  }
29528
29658
  return { installed: false };
@@ -29551,8 +29681,8 @@ var codexConnector = {
29551
29681
  next += `
29552
29682
  `;
29553
29683
  next += buildSection(args.name, args.url);
29554
- mkdirSync15(dirname10(path), { recursive: true });
29555
- writeFileSync15(path, next, "utf-8");
29684
+ mkdirSync16(dirname11(path), { recursive: true });
29685
+ writeFileSync16(path, next, "utf-8");
29556
29686
  return { added: !conflict, conflict };
29557
29687
  },
29558
29688
  async remove(args) {
@@ -29562,7 +29692,7 @@ var codexConnector = {
29562
29692
  const range = findSectionRange(existing, args.name);
29563
29693
  if (range) {
29564
29694
  const next = existing.slice(0, range.start) + existing.slice(range.end);
29565
- writeFileSync15(path, next, "utf-8");
29695
+ writeFileSync16(path, next, "utf-8");
29566
29696
  }
29567
29697
  }
29568
29698
  const restored = restoreFromBackup({
@@ -29583,11 +29713,11 @@ var codexConnector = {
29583
29713
  };
29584
29714
 
29585
29715
  // src/lib/dev/agent-connectors/continue.ts
29586
- import { existsSync as existsSync30, unlinkSync as unlinkSync4, writeFileSync as writeFileSync16 } from "node:fs";
29716
+ import { existsSync as existsSync30, unlinkSync as unlinkSync4, writeFileSync as writeFileSync17 } from "node:fs";
29587
29717
  import { homedir as homedir6 } from "node:os";
29588
- import { join as join26 } from "node:path";
29718
+ import { join as join27 } from "node:path";
29589
29719
  function configPath3() {
29590
- return join26(homedir6(), ".continue", "config.json");
29720
+ return join27(homedir6(), ".continue", "config.json");
29591
29721
  }
29592
29722
  function isContinueServerEntry(value) {
29593
29723
  return Boolean(value && typeof value === "object" && typeof value.name === "string");
@@ -29598,7 +29728,7 @@ var continueConnector = {
29598
29728
  hotkey: "n",
29599
29729
  describeLocation: () => configPath3(),
29600
29730
  async detect() {
29601
- const dir = join26(homedir6(), ".continue");
29731
+ const dir = join27(homedir6(), ".continue");
29602
29732
  if (existsSync30(dir) || existsSync30(configPath3())) {
29603
29733
  return { installed: true, note: "Found ~/.continue/" };
29604
29734
  }
@@ -29647,7 +29777,7 @@ var continueConnector = {
29647
29777
  try {
29648
29778
  unlinkSync4(path);
29649
29779
  } catch {
29650
- writeFileSync16(path, `{}
29780
+ writeFileSync17(path, `{}
29651
29781
  `, "utf-8");
29652
29782
  }
29653
29783
  }
@@ -29658,11 +29788,11 @@ var continueConnector = {
29658
29788
  };
29659
29789
 
29660
29790
  // src/lib/dev/agent-connectors/cursor.ts
29661
- import { existsSync as existsSync31, unlinkSync as unlinkSync5, writeFileSync as writeFileSync17 } from "node:fs";
29791
+ import { existsSync as existsSync31, unlinkSync as unlinkSync5, writeFileSync as writeFileSync18 } from "node:fs";
29662
29792
  import { homedir as homedir7 } from "node:os";
29663
- import { join as join27 } from "node:path";
29793
+ import { join as join28 } from "node:path";
29664
29794
  function globalConfigPath() {
29665
- return join27(homedir7(), ".cursor", "mcp.json");
29795
+ return join28(homedir7(), ".cursor", "mcp.json");
29666
29796
  }
29667
29797
  var cursorConnector = {
29668
29798
  id: "cursor",
@@ -29670,8 +29800,8 @@ var cursorConnector = {
29670
29800
  hotkey: "u",
29671
29801
  describeLocation: () => globalConfigPath(),
29672
29802
  async detect() {
29673
- const cursorDir = join27(homedir7(), ".cursor");
29674
- const macAppSupport = join27(homedir7(), "Library", "Application Support", "Cursor");
29803
+ const cursorDir = join28(homedir7(), ".cursor");
29804
+ const macAppSupport = join28(homedir7(), "Library", "Application Support", "Cursor");
29675
29805
  if (existsSync31(cursorDir) || existsSync31(macAppSupport)) {
29676
29806
  return { installed: true, note: "Found Cursor config dir" };
29677
29807
  }
@@ -29720,7 +29850,7 @@ var cursorConnector = {
29720
29850
  try {
29721
29851
  unlinkSync5(path);
29722
29852
  } catch {
29723
- writeFileSync17(path, `{}
29853
+ writeFileSync18(path, `{}
29724
29854
  `, "utf-8");
29725
29855
  }
29726
29856
  }
@@ -29731,30 +29861,30 @@ var cursorConnector = {
29731
29861
  };
29732
29862
 
29733
29863
  // src/lib/dev/agent-connectors/vscode-copilot.ts
29734
- import { existsSync as existsSync32, unlinkSync as unlinkSync6, writeFileSync as writeFileSync18 } from "node:fs";
29864
+ import { existsSync as existsSync32, unlinkSync as unlinkSync6, writeFileSync as writeFileSync19 } from "node:fs";
29735
29865
  import { homedir as homedir8, platform as platform4 } from "node:os";
29736
- import { join as join28, resolve as resolve7 } from "node:path";
29866
+ import { join as join29, resolve as resolve8 } from "node:path";
29737
29867
  function userLevelConfigPath() {
29738
29868
  const home = homedir8();
29739
29869
  const p2 = platform4();
29740
29870
  if (p2 === "darwin")
29741
- return join28(home, "Library", "Application Support", "Code", "User", "mcp.json");
29871
+ return join29(home, "Library", "Application Support", "Code", "User", "mcp.json");
29742
29872
  if (p2 === "win32") {
29743
- const appData = process.env["APPDATA"] ?? join28(home, "AppData", "Roaming");
29744
- return join28(appData, "Code", "User", "mcp.json");
29873
+ const appData = process.env["APPDATA"] ?? join29(home, "AppData", "Roaming");
29874
+ return join29(appData, "Code", "User", "mcp.json");
29745
29875
  }
29746
- const xdg = process.env["XDG_CONFIG_HOME"] ?? join28(home, ".config");
29747
- return join28(xdg, "Code", "User", "mcp.json");
29876
+ const xdg = process.env["XDG_CONFIG_HOME"] ?? join29(home, ".config");
29877
+ return join29(xdg, "Code", "User", "mcp.json");
29748
29878
  }
29749
29879
  function isHomeDir(cwd) {
29750
- return resolve7(cwd) === resolve7(homedir8());
29880
+ return resolve8(cwd) === resolve8(homedir8());
29751
29881
  }
29752
29882
  function hasWorkspaceVscode(cwd) {
29753
- return existsSync32(join28(cwd, ".vscode"));
29883
+ return existsSync32(join29(cwd, ".vscode"));
29754
29884
  }
29755
29885
  function configPath4(cwd) {
29756
29886
  if (!isHomeDir(cwd) && hasWorkspaceVscode(cwd)) {
29757
- return join28(cwd, ".vscode", "mcp.json");
29887
+ return join29(cwd, ".vscode", "mcp.json");
29758
29888
  }
29759
29889
  return userLevelConfigPath();
29760
29890
  }
@@ -29816,7 +29946,7 @@ var vscodeCopilotConnector = {
29816
29946
  try {
29817
29947
  unlinkSync6(path);
29818
29948
  } catch {
29819
- writeFileSync18(path, `{}
29949
+ writeFileSync19(path, `{}
29820
29950
  `, "utf-8");
29821
29951
  }
29822
29952
  }
@@ -29960,7 +30090,7 @@ function parseGraceMs(value, fallbackMs) {
29960
30090
  return Math.round(n * 1000);
29961
30091
  }
29962
30092
  function resolveSpecPath(cwd, raw) {
29963
- return isAbsolute3(raw) ? raw : resolve8(cwd, raw);
30093
+ return isAbsolute4(raw) ? raw : resolve9(cwd, raw);
29964
30094
  }
29965
30095
  function buildConnectionName(serverId) {
29966
30096
  const slug = serverId.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 24) || "mcp-server";
@@ -31062,11 +31192,11 @@ async function confirmRollback(deploymentId) {
31062
31192
  // src/commands/doctor.ts
31063
31193
  import { existsSync as existsSync35, statSync as statSync6, readFileSync as readFileSync19 } from "node:fs";
31064
31194
  import { homedir as homedir9, platform as platform6 } from "node:os";
31065
- import { join as join30, delimiter as delimiter3 } from "node:path";
31195
+ import { join as join31, delimiter as delimiter3 } from "node:path";
31066
31196
 
31067
31197
  // src/lib/version-check.ts
31068
- import { existsSync as existsSync34, mkdirSync as mkdirSync16, readFileSync as readFileSync18, writeFileSync as writeFileSync19 } from "node:fs";
31069
- import { join as join29 } from "node:path";
31198
+ import { existsSync as existsSync34, mkdirSync as mkdirSync17, readFileSync as readFileSync18, writeFileSync as writeFileSync20 } from "node:fs";
31199
+ import { join as join30 } from "node:path";
31070
31200
  var CACHE_TTL_MS = 24 * 60 * 60 * 1000;
31071
31201
  var FETCH_TIMEOUT_MS2 = 2000;
31072
31202
  var REGISTRY_URL = "https://registry.npmjs.org/@mcpcloud/cli/latest";
@@ -31074,7 +31204,7 @@ function cacheDir() {
31074
31204
  return configDir();
31075
31205
  }
31076
31206
  function cacheFile() {
31077
- return join29(cacheDir(), "version-check.json");
31207
+ return join30(cacheDir(), "version-check.json");
31078
31208
  }
31079
31209
  function readCache() {
31080
31210
  if (!existsSync34(cacheFile()))
@@ -31091,8 +31221,8 @@ function readCache() {
31091
31221
  function writeCache(entry) {
31092
31222
  try {
31093
31223
  if (!existsSync34(cacheDir()))
31094
- mkdirSync16(cacheDir(), { recursive: true, mode: 448 });
31095
- writeFileSync19(cacheFile(), JSON.stringify(entry, null, 2), { mode: 384 });
31224
+ mkdirSync17(cacheDir(), { recursive: true, mode: 448 });
31225
+ writeFileSync20(cacheFile(), JSON.stringify(entry, null, 2), { mode: 384 });
31096
31226
  } catch {}
31097
31227
  }
31098
31228
  function compareVersions(a, b2) {
@@ -31203,7 +31333,7 @@ function checkNode() {
31203
31333
  }
31204
31334
  function checkConfigFile() {
31205
31335
  const t0 = Date.now();
31206
- const path = join30(homedir9(), ".mcpcloud", "config.json");
31336
+ const path = join31(homedir9(), ".mcpcloud", "config.json");
31207
31337
  if (!existsSync35(path)) {
31208
31338
  return {
31209
31339
  name: "Config file",
@@ -31357,7 +31487,7 @@ function checkClaudeCli() {
31357
31487
  for (const dir of PATH.split(delimiter3)) {
31358
31488
  if (!dir)
31359
31489
  continue;
31360
- const candidate = join30(dir, exe);
31490
+ const candidate = join31(dir, exe);
31361
31491
  if (existsSync35(candidate)) {
31362
31492
  return {
31363
31493
  name: "claude CLI",
@@ -31697,10 +31827,10 @@ function prompt2(question) {
31697
31827
  throw new Error("Interactive prompts are disabled in CI mode. Pass --org / --project / --name explicitly or run `mcp init` outside CI.");
31698
31828
  }
31699
31829
  const rl = createInterface3({ input: process.stdin, output: process.stderr });
31700
- return new Promise((resolve9) => {
31830
+ return new Promise((resolve10) => {
31701
31831
  rl.question(question, (answer) => {
31702
31832
  rl.close();
31703
- resolve9(answer.trim());
31833
+ resolve10(answer.trim());
31704
31834
  });
31705
31835
  });
31706
31836
  }
@@ -32312,6 +32442,9 @@ function invokeResultToJson3(result) {
32312
32442
  };
32313
32443
  }
32314
32444
 
32445
+ // src/commands/marketplace.ts
32446
+ import { readFile } from "node:fs/promises";
32447
+
32315
32448
  // src/lib/resolve-marketplace.ts
32316
32449
  var ARTIFACT_KIND = {
32317
32450
  label: "artifact",
@@ -32563,14 +32696,14 @@ function registerMarketplaceCommands(program2) {
32563
32696
  printSuccess(`Forked ${c.bold(data.fork.artifactType)} → ${data.fork.forkedId} (draft).`);
32564
32697
  printStep(data.fork.artifactType === "server" ? `Iterate: \`mcp dev\` then \`mcp servers deploy ${data.fork.forkedId} --wait\`.` : `Iterate on skill ${data.fork.forkedId} then \`mcp skills deploy\`.`);
32565
32698
  }));
32566
- marketplace.command("publish <server|skill>").description("Publish a deployed server or a versioned skill to the registry (requires org admin)").requiredOption("--type <type>", "Artifact type: server | skill").requiredOption("--project <project>", "The artifact's project (id or name)").option("--semver <semver>", "Version to publish (required for servers; skills use their current version)").option("--visibility <visibility>", "public (marketplace) | private (your org only). Default public.", "public").option("--changelog <text>", "Optional changelog for this version").option("--org <organizationId>", "Organization ID").addHelpText("after", [
32699
+ marketplace.command("publish <server|skill>").description("Publish a deployed server or a versioned skill to the registry (requires org admin)").requiredOption("--type <type>", "Artifact type: server | skill").requiredOption("--project <project>", "The artifact's project (id or name)").option("--semver <semver>", "Version to publish (required for servers; skills use their current version)").option("--visibility <visibility>", "public (marketplace) | private (your org only). Default public.", "public").option("--changelog <text>", "Changelog for this version. Required for every version after the first.").option("--readme <path>", "Path to a markdown README for the listing. Required on first publish; omit later to keep the published one.").option("--org <organizationId>", "Organization ID").addHelpText("after", [
32567
32700
  "",
32568
32701
  "Notes:",
32569
32702
  " Servers must be successfully deployed before publishing. Publishing to",
32570
32703
  " the public marketplace or a private-org registry requires the Pro plan.",
32571
32704
  "",
32572
32705
  "Examples:",
32573
- " $ mcp marketplace publish srv_123 --type server --project proj_1 --semver 1.0.0",
32706
+ " $ mcp marketplace publish srv_123 --type server --project proj_1 --semver 1.0.0 --readme ./README.md",
32574
32707
  " $ mcp marketplace publish skill_9 --type skill --project proj_1 --visibility private"
32575
32708
  ].join(`
32576
32709
  `)).action(runAction(async (id, opts) => {
@@ -32585,12 +32718,14 @@ function registerMarketplaceCommands(program2) {
32585
32718
  }
32586
32719
  const access = visibility === "private" ? "privateOrg" : "public";
32587
32720
  const projectId = await resolveProjectId(opts.project, orgId);
32721
+ const readmeContent = opts.readme ? await readFile(opts.readme, "utf8") : null;
32588
32722
  const body = {
32589
32723
  organizationId: orgId,
32590
32724
  artifactType: type,
32591
32725
  projectId,
32592
32726
  access,
32593
- ...opts.changelog ? { changelog: opts.changelog } : {}
32727
+ ...opts.changelog ? { changelog: opts.changelog } : {},
32728
+ ...readmeContent ? { readmeContent } : {}
32594
32729
  };
32595
32730
  if (type === "server") {
32596
32731
  if (!opts.semver) {
@@ -33200,24 +33335,24 @@ function registerConnectionsCommands(program2) {
33200
33335
  import { spawn as spawn7 } from "node:child_process";
33201
33336
  import {
33202
33337
  existsSync as existsSync36,
33203
- mkdirSync as mkdirSync17,
33338
+ mkdirSync as mkdirSync18,
33204
33339
  readdirSync as readdirSync4,
33205
33340
  readFileSync as readFileSync20,
33206
33341
  rmSync as rmSync3,
33207
33342
  statSync as statSync7
33208
33343
  } from "node:fs";
33209
- import { join as join31 } from "node:path";
33344
+ import { join as join32 } from "node:path";
33210
33345
  import { pathToFileURL } from "node:url";
33211
33346
  function pluginsDir() {
33212
- return join31(configDir(), "plugins");
33347
+ return join32(configDir(), "plugins");
33213
33348
  }
33214
33349
  function ensureDir2() {
33215
33350
  const dir = pluginsDir();
33216
33351
  if (!existsSync36(dir))
33217
- mkdirSync17(dir, { recursive: true, mode: 448 });
33352
+ mkdirSync18(dir, { recursive: true, mode: 448 });
33218
33353
  }
33219
33354
  function readManifestFromPackageDir(packageDir) {
33220
- const pkgPath = join31(packageDir, "package.json");
33355
+ const pkgPath = join32(packageDir, "package.json");
33221
33356
  if (!existsSync36(pkgPath))
33222
33357
  return null;
33223
33358
  let pkg;
@@ -33229,7 +33364,7 @@ function readManifestFromPackageDir(packageDir) {
33229
33364
  if (!pkg.name)
33230
33365
  return null;
33231
33366
  const relEntry = pkg.mcpsh?.register ?? pkg.mcp?.register ?? pkg.main ?? "index.js";
33232
- const entry = join31(packageDir, relEntry);
33367
+ const entry = join32(packageDir, relEntry);
33233
33368
  if (!existsSync36(entry))
33234
33369
  return null;
33235
33370
  return {
@@ -33245,7 +33380,7 @@ function listInstalledPlugins() {
33245
33380
  return [];
33246
33381
  const out = [];
33247
33382
  for (const entry of readdirSync4(dir)) {
33248
- const full = join31(dir, entry);
33383
+ const full = join32(dir, entry);
33249
33384
  let s;
33250
33385
  try {
33251
33386
  s = statSync7(full);
@@ -33256,7 +33391,7 @@ function listInstalledPlugins() {
33256
33391
  continue;
33257
33392
  if (entry.startsWith("@")) {
33258
33393
  for (const child of readdirSync4(full)) {
33259
- const m2 = readManifestFromPackageDir(join31(full, child));
33394
+ const m2 = readManifestFromPackageDir(join32(full, child));
33260
33395
  if (m2)
33261
33396
  out.push(m2);
33262
33397
  }
@@ -33291,15 +33426,15 @@ async function loadPlugins(program2) {
33291
33426
  }
33292
33427
  var PACKAGE_SPEC_PATTERN = /^(@[a-z0-9~-][\w.~-]*\/)?[a-z0-9~-][\w.~-]*(@[-\w.^~><=*+|]+)?$/i;
33293
33428
  function runNpm(args, cwd) {
33294
- return new Promise((resolve9) => {
33429
+ return new Promise((resolve10) => {
33295
33430
  const isWindows = process.platform === "win32";
33296
33431
  const child = spawn7(isWindows ? "npm.cmd" : "npm", args, {
33297
33432
  shell: isWindows,
33298
33433
  cwd,
33299
33434
  stdio: "inherit"
33300
33435
  });
33301
- child.on("close", (code) => resolve9(code ?? 1));
33302
- child.on("error", () => resolve9(1));
33436
+ child.on("close", (code) => resolve10(code ?? 1));
33437
+ child.on("error", () => resolve10(1));
33303
33438
  });
33304
33439
  }
33305
33440
  async function installPlugin(packageSpec) {
@@ -33320,12 +33455,12 @@ async function installPlugin(packageSpec) {
33320
33455
  if (code !== 0) {
33321
33456
  throw new Error(`npm install ${packageSpec} exited with code ${code}.`);
33322
33457
  }
33323
- const nm = join31(dir, "node_modules");
33458
+ const nm = join32(dir, "node_modules");
33324
33459
  if (!existsSync36(nm)) {
33325
33460
  throw new Error(`npm install ran but produced no node_modules under ${dir}.`);
33326
33461
  }
33327
33462
  const baseName = packageSpec.replace(/@[^@/]+$/, "");
33328
- const candidatePath = baseName.startsWith("@") ? join31(nm, baseName.split("/")[0], baseName.split("/")[1] ?? "") : join31(nm, baseName);
33463
+ const candidatePath = baseName.startsWith("@") ? join32(nm, baseName.split("/")[0], baseName.split("/")[1] ?? "") : join32(nm, baseName);
33329
33464
  const manifest = readManifestFromPackageDir(candidatePath);
33330
33465
  if (!manifest) {
33331
33466
  throw new Error(`Installed but could not read plugin manifest at ${candidatePath}.`);
@@ -33333,10 +33468,10 @@ async function installPlugin(packageSpec) {
33333
33468
  return { name: manifest.name, entry: manifest.entry };
33334
33469
  }
33335
33470
  function removePlugin(name) {
33336
- const nm = join31(pluginsDir(), "node_modules");
33471
+ const nm = join32(pluginsDir(), "node_modules");
33337
33472
  if (!existsSync36(nm))
33338
33473
  return false;
33339
- const target = name.startsWith("@") ? join31(nm, name.split("/")[0], name.split("/")[1] ?? "") : join31(nm, name);
33474
+ const target = name.startsWith("@") ? join32(nm, name.split("/")[0], name.split("/")[1] ?? "") : join32(nm, name);
33340
33475
  if (!existsSync36(target))
33341
33476
  return false;
33342
33477
  rmSync3(target, { recursive: true, force: true });
@@ -33344,7 +33479,7 @@ function removePlugin(name) {
33344
33479
  }
33345
33480
  function listInstalledPluginsCombined() {
33346
33481
  const direct = listInstalledPlugins();
33347
- const nm = join31(pluginsDir(), "node_modules");
33482
+ const nm = join32(pluginsDir(), "node_modules");
33348
33483
  if (!existsSync36(nm))
33349
33484
  return direct;
33350
33485
  const seen = new Set(direct.map((p2) => p2.name));
@@ -33352,7 +33487,7 @@ function listInstalledPluginsCombined() {
33352
33487
  for (const entry of readdirSync4(nm)) {
33353
33488
  if (entry === ".bin" || entry === ".package-lock.json")
33354
33489
  continue;
33355
- const full = join31(nm, entry);
33490
+ const full = join32(nm, entry);
33356
33491
  let s;
33357
33492
  try {
33358
33493
  s = statSync7(full);
@@ -33363,7 +33498,7 @@ function listInstalledPluginsCombined() {
33363
33498
  continue;
33364
33499
  if (entry.startsWith("@")) {
33365
33500
  for (const child of readdirSync4(full)) {
33366
- const m2 = readManifestFromPackageDir(join31(full, child));
33501
+ const m2 = readManifestFromPackageDir(join32(full, child));
33367
33502
  if (m2 && !seen.has(m2.name)) {
33368
33503
  seen.add(m2.name);
33369
33504
  out.push(m2);
@@ -33823,7 +33958,7 @@ function clipboardCandidatesFor(platform7, waylandDisplay) {
33823
33958
  return linux;
33824
33959
  }
33825
33960
  async function defaultIsExecutable(binary) {
33826
- return await new Promise((resolve9) => {
33961
+ return await new Promise((resolve10) => {
33827
33962
  const isWin = process.platform === "win32";
33828
33963
  const cmd = isWin ? "where" : "command";
33829
33964
  const args = isWin ? [binary] : ["-v", binary];
@@ -33831,8 +33966,8 @@ async function defaultIsExecutable(binary) {
33831
33966
  shell: !isWin,
33832
33967
  stdio: "ignore"
33833
33968
  });
33834
- child.on("error", () => resolve9(false));
33835
- child.on("exit", (code) => resolve9(code === 0));
33969
+ child.on("error", () => resolve10(false));
33970
+ child.on("exit", (code) => resolve10(code === 0));
33836
33971
  });
33837
33972
  }
33838
33973
  async function detectClipboard(probe) {
@@ -33854,7 +33989,7 @@ async function copyToClipboard(text, probe) {
33854
33989
  };
33855
33990
  }
33856
33991
  const spawnImpl = probe?.spawnImpl ?? spawn8;
33857
- return await new Promise((resolve9) => {
33992
+ return await new Promise((resolve10) => {
33858
33993
  const child = spawnImpl(candidate.binary, candidate.args, {
33859
33994
  stdio: ["pipe", "ignore", "pipe"]
33860
33995
  });
@@ -33863,7 +33998,7 @@ async function copyToClipboard(text, probe) {
33863
33998
  stderr += chunk.toString("utf-8");
33864
33999
  });
33865
34000
  child.on("error", (err) => {
33866
- resolve9({
34001
+ resolve10({
33867
34002
  kind: "failed",
33868
34003
  binary: candidate.binary,
33869
34004
  message: err instanceof Error ? err.message : String(err)
@@ -33871,9 +34006,9 @@ async function copyToClipboard(text, probe) {
33871
34006
  });
33872
34007
  child.on("exit", (code) => {
33873
34008
  if (code === 0) {
33874
- resolve9({ kind: "ok", binary: candidate.binary });
34009
+ resolve10({ kind: "ok", binary: candidate.binary });
33875
34010
  } else {
33876
- resolve9({
34011
+ resolve10({
33877
34012
  kind: "failed",
33878
34013
  binary: candidate.binary,
33879
34014
  message: stderr.trim() || `${candidate.binary} exited with status ${code ?? "?"}`
@@ -33883,7 +34018,7 @@ async function copyToClipboard(text, probe) {
33883
34018
  try {
33884
34019
  child.stdin?.end(text);
33885
34020
  } catch (err) {
33886
- resolve9({
34021
+ resolve10({
33887
34022
  kind: "failed",
33888
34023
  binary: candidate.binary,
33889
34024
  message: err instanceof Error ? err.message : String(err)
@@ -34954,11 +35089,11 @@ function displayValueFor(field, value) {
34954
35089
  // src/lib/tui/state-store.ts
34955
35090
  import {
34956
35091
  existsSync as existsSync37,
34957
- mkdirSync as mkdirSync18,
35092
+ mkdirSync as mkdirSync19,
34958
35093
  readFileSync as readFileSync21,
34959
- writeFileSync as writeFileSync20
35094
+ writeFileSync as writeFileSync21
34960
35095
  } from "node:fs";
34961
- import { join as join32 } from "node:path";
35096
+ import { join as join33 } from "node:path";
34962
35097
  var ALL_TABS = [
34963
35098
  "servers",
34964
35099
  "projects",
@@ -34968,7 +35103,7 @@ var ALL_TABS = [
34968
35103
  "devSessions"
34969
35104
  ];
34970
35105
  function tuiStateFile() {
34971
- return join32(configDir(), "tui-state.json");
35106
+ return join33(configDir(), "tui-state.json");
34972
35107
  }
34973
35108
  function isTab(v2) {
34974
35109
  return typeof v2 === "string" && ALL_TABS.includes(v2);
@@ -35046,9 +35181,9 @@ function readTuiState() {
35046
35181
  function writeTuiState(state) {
35047
35182
  try {
35048
35183
  if (!existsSync37(configDir())) {
35049
- mkdirSync18(configDir(), { recursive: true, mode: 448 });
35184
+ mkdirSync19(configDir(), { recursive: true, mode: 448 });
35050
35185
  }
35051
- writeFileSync20(tuiStateFile(), JSON.stringify(state, null, 2), {
35186
+ writeFileSync21(tuiStateFile(), JSON.stringify(state, null, 2), {
35052
35187
  encoding: "utf-8",
35053
35188
  mode: 384
35054
35189
  });
@@ -37053,7 +37188,7 @@ function registerUiCommand(program2) {
37053
37188
  }
37054
37189
  return false;
37055
37190
  };
37056
- await new Promise((resolve9) => {
37191
+ await new Promise((resolve10) => {
37057
37192
  const flushAndExit = () => {
37058
37193
  try {
37059
37194
  if (persistTimer) {
@@ -37063,7 +37198,7 @@ function registerUiCommand(program2) {
37063
37198
  writeTuiState(snapshotForPersist());
37064
37199
  } catch {}
37065
37200
  shutdown(handles);
37066
- resolve9();
37201
+ resolve10();
37067
37202
  };
37068
37203
  const executePaletteCommand = (id) => {
37069
37204
  if (id.startsWith("tab:")) {
@@ -37672,7 +37807,7 @@ function registerUiCommand(program2) {
37672
37807
 
37673
37808
  // src/commands/update.ts
37674
37809
  import { spawn as spawn9 } from "node:child_process";
37675
- import { dirname as dirname11 } from "node:path";
37810
+ import { dirname as dirname12 } from "node:path";
37676
37811
  import { fileURLToPath as fileURLToPath2 } from "node:url";
37677
37812
  function detectInstallContext() {
37678
37813
  const override = process.env["MCPSH_PACKAGE_MANAGER"]?.trim().toLowerCase();
@@ -37685,7 +37820,7 @@ function detectInstallContext() {
37685
37820
  }
37686
37821
  const here = (() => {
37687
37822
  try {
37688
- return dirname11(fileURLToPath2(import.meta.url));
37823
+ return dirname12(fileURLToPath2(import.meta.url));
37689
37824
  } catch {
37690
37825
  return process.argv[1] ?? "";
37691
37826
  }
@@ -37733,10 +37868,10 @@ function buildCommand(manager) {
37733
37868
  }
37734
37869
  }
37735
37870
  function runShell(command) {
37736
- return new Promise((resolve9) => {
37871
+ return new Promise((resolve10) => {
37737
37872
  const child = spawn9(command, { shell: true, stdio: "inherit" });
37738
- child.on("close", (code) => resolve9(code ?? 1));
37739
- child.on("error", () => resolve9(1));
37873
+ child.on("close", (code) => resolve10(code ?? 1));
37874
+ child.on("error", () => resolve10(1));
37740
37875
  });
37741
37876
  }
37742
37877
  function registerUpdateCommand(program2) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcpcloud/cli",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "The official CLI for MCPCloud — manage projects, servers, skills, and API keys from the terminal",
5
5
  "type": "module",
6
6
  "bin": {