@mcpcloud/cli 0.20.1-next-20260906202728 → 0.21.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 +102 -0
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -551,6 +551,7 @@ _Generated from the live command tree by `bun run docs:readme` — do not edit b
551
551
  | `mcp servers test-suites get <suiteId>` | Show one server test suite including its scenario membership |
552
552
  | `mcp servers test-suites list <server>` | List test suites bound to a server |
553
553
  | `mcp servers test-suites run <server>` | Run the server’s test scenarios and report the suite result |
554
+ | `mcp servers transfer <server>` | Move a server into another organization you administer, keeping its id, slug, deployment, custom domain, end-user keys and git link. Shows the plan; add --yes to execute. |
554
555
  | `mcp servers update <server>` | Update a server (name, description, tool surface, upstream key mode, runtime token TTL) |
555
556
  | `mcp servers variables` | Inspect and set the sandbox variables that scenario arguments reference |
556
557
  | `mcp servers variables list <server>` | List a server’s sandbox variables and which ones still need a value |
package/dist/index.js CHANGED
@@ -7747,6 +7747,107 @@ function registerServerLifecycleCommands(servers) {
7747
7747
  }));
7748
7748
  }
7749
7749
 
7750
+ // src/commands/servers-transfer.ts
7751
+ var TRANSFER_PATH = "/api/v1/server/transfer";
7752
+ async function resolveTargetOrganizationId(reference) {
7753
+ const ref = reference.trim();
7754
+ const data = await api.get("/api/v1/organizations");
7755
+ const rows = data.organizations;
7756
+ const match = rows.find((row) => row.id === ref) ?? rows.find((row) => row.slug === ref) ?? rows.find((row) => row.name.toLowerCase() === ref.toLowerCase());
7757
+ if (!match) {
7758
+ printError(`No organization you belong to matches ${c.bold(ref)} (by id, slug, or name).`);
7759
+ if (rows.length > 0) {
7760
+ printInfo(` ${c.dim("Yours:")} ${rows.map((row) => `${row.name} (${row.slug ?? row.id})`).join(", ")}`);
7761
+ }
7762
+ throw new CliExitError(1);
7763
+ }
7764
+ return match.id;
7765
+ }
7766
+ function printPlan(result) {
7767
+ printKeyValue({
7768
+ server: `${result.server.name} (${result.server.slug})`,
7769
+ from: `${result.from.organizationName ?? result.from.organizationId} / ${result.from.projectName ?? result.from.projectId}`,
7770
+ to: `${result.to.organizationName} / ${result.to.projectName ?? result.to.projectId ?? "(new project)"}`,
7771
+ "git link": result.plan.gitLink,
7772
+ domains: result.domains.length > 0 ? result.domains.join(", ") : "—"
7773
+ });
7774
+ const moving = result.manifest.filter((entry) => entry.count > 0);
7775
+ if (moving.length > 0) {
7776
+ printInfo(c.dim(" Rows that move:"));
7777
+ for (const entry of moving) {
7778
+ printInfo(` ${entry.table.padEnd(34)} ${entry.count}${entry.more ? "+" : ""}`);
7779
+ }
7780
+ }
7781
+ for (const note of result.plan.notes)
7782
+ printWarn(` ! ${note}`);
7783
+ }
7784
+ function reportApiError6(err) {
7785
+ if (err instanceof McpCloudApiError) {
7786
+ printError(`Transfer failed (HTTP ${err.status}): ${err.error.message}`);
7787
+ const blockers = err.error.details?.blockers;
7788
+ if (Array.isArray(blockers)) {
7789
+ for (const blocker of blockers) {
7790
+ printInfo(` ${c.dim(blocker.code + ":")} ${blocker.message}`);
7791
+ }
7792
+ }
7793
+ } else {
7794
+ printError(`Transfer failed: ${err instanceof Error ? err.message : String(err)}`);
7795
+ }
7796
+ throw new CliExitError(1);
7797
+ }
7798
+ function registerServerTransferCommand(servers) {
7799
+ servers.command("transfer <server>").description("Move a server into another organization you administer, keeping its id, slug, deployment, custom domain, end-user keys and git link. Shows the plan; add --yes to execute.").requiredOption("--to-org <organization>", "Destination organization (id, slug, or name) — you must be owner or admin there").option("--to-project <project>", "Destination project (id or name, within the destination organization)").option("--create-project <name>", "Create this project in the destination organization and move the server into it").option("--org <organizationId>", "Source organization ID").option("--drop-git-link", "Move without the GitHub link when no installation in the destination reaches the repository").option("--yes", "Execute the transfer (without it, only the plan is shown)").addHelpText("after", [
7800
+ "",
7801
+ "What moves: the server row and project placement, tools, prompts, resources,",
7802
+ "deployments and their edge policy, versions, code + commits, sandbox and test",
7803
+ "artifacts, end-user access (branding, allowlist, federation), members’ pasted",
7804
+ "keys and end-user records, the custom domain (no traffic interruption), the",
7805
+ "API source, and registry listings (installers keep them).",
7806
+ "What stays: usage and billing history (the source org was billed for it),",
7807
+ "and member-scoped grants of source-org members, which become inert.",
7808
+ "",
7809
+ "Members of the source organization lose access to the server."
7810
+ ].join(`
7811
+ `)).action(runAction(async (serverRef, opts) => {
7812
+ const orgId = await resolveOrgId(opts.org);
7813
+ const serverId = await resolveServerId(serverRef, orgId);
7814
+ const targetOrganizationId = await resolveTargetOrganizationId(opts.toOrg);
7815
+ const targetProjectId = await resolveOptionalProjectId(opts.toProject, targetOrganizationId);
7816
+ if (opts.yes && !targetProjectId && !opts.createProject) {
7817
+ printError("Pass --to-project <project> or --create-project <name> for the destination.");
7818
+ throw new CliExitError(1);
7819
+ }
7820
+ const body = {
7821
+ organizationId: orgId,
7822
+ targetOrganizationId,
7823
+ serverId,
7824
+ ...targetProjectId ? { targetProjectId } : {},
7825
+ ...opts.createProject ? { createProjectName: opts.createProject } : {},
7826
+ dryRun: !opts.yes,
7827
+ dropGitLink: Boolean(opts.dropGitLink)
7828
+ };
7829
+ let result;
7830
+ try {
7831
+ if (opts.yes && !isJsonMode()) {
7832
+ printStep(`Transferring ${c.bold(serverRef)} to ${c.bold(opts.toOrg)}…`);
7833
+ }
7834
+ result = await api.post(TRANSFER_PATH, body);
7835
+ } catch (err) {
7836
+ reportApiError6(err);
7837
+ }
7838
+ if (isJsonMode()) {
7839
+ printJson(result);
7840
+ return;
7841
+ }
7842
+ printPlan(result);
7843
+ if (result.dryRun) {
7844
+ printInfo(c.dim(` → nothing moved. Re-run with --yes${targetProjectId || opts.createProject ? "" : " and --to-project <project> (or --create-project <name>)"} to transfer.`));
7845
+ return;
7846
+ }
7847
+ printSuccess(`${result.server.name} now lives in ${result.to.organizationName} / ${result.to.projectName ?? result.to.projectId}${result.to.projectCreated ? " (project created)" : ""}. ${result.patchedRows} row(s) rehomed; id and slug unchanged.`);
7848
+ }));
7849
+ }
7850
+
7750
7851
  // src/commands/servers-mutations.ts
7751
7852
  function registerServerMutationCommands(servers) {
7752
7853
  servers.command("create").description("Create an empty server skeleton in a project").requiredOption("--project <project>", "Project (id or name)").requiredOption("--name <name>", "Display name (1–100 chars)").option("--org <organizationId>", "Organization ID").option("--description <text>", "Optional description").option("--git-repo <owner/name>", "Host the generated code on this GitHub repo (links now, mirrors after first generation)").option("--git-path-prefix <prefix>", "Sync into this path inside the repo").option("--no-git-auto-sync", "Do not mirror commits automatically").addHelpText("after", [
@@ -8590,6 +8691,7 @@ function registerServerCommands(program) {
8590
8691
  registerServerGetCommand(servers);
8591
8692
  registerServerExportCommands(servers);
8592
8693
  registerServerLifecycleCommands(servers);
8694
+ registerServerTransferCommand(servers);
8593
8695
  registerServerMutationCommands(servers);
8594
8696
  registerServerSpecCommands(servers);
8595
8697
  registerServerTestCommands(servers);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcpcloud/cli",
3
- "version": "0.20.1-next-20260906202728",
3
+ "version": "0.21.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": {