@mcp-use/cli 3.0.1 → 3.0.2-canary.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAuIA,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC5B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAuYD,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA2oBzE"}
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AA4IA,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC5B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAueD,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAwsBzE"}
package/dist/index.cjs CHANGED
@@ -1222,6 +1222,13 @@ var GitHubAuthRequiredError = class extends Error {
1222
1222
  this.authorizeUrl = authorizeUrl;
1223
1223
  }
1224
1224
  };
1225
+ var ApiUnauthorizedError = class extends Error {
1226
+ status = 401;
1227
+ constructor(message = "Your session has expired or your API key is invalid.") {
1228
+ super(message);
1229
+ this.name = "ApiUnauthorizedError";
1230
+ }
1231
+ };
1225
1232
  var McpUseAPI = class _McpUseAPI {
1226
1233
  baseUrl;
1227
1234
  apiKey;
@@ -1263,11 +1270,7 @@ var McpUseAPI = class _McpUseAPI {
1263
1270
  });
1264
1271
  clearTimeout(timeoutId);
1265
1272
  if (response.status === 401) {
1266
- const err = new Error(
1267
- "Your session has expired or your API key is invalid."
1268
- );
1269
- err.status = 401;
1270
- throw err;
1273
+ throw new ApiUnauthorizedError();
1271
1274
  }
1272
1275
  if (!response.ok) {
1273
1276
  const errorText = await response.text();
@@ -2825,21 +2828,52 @@ var import_node_path5 = __toESM(require("path"), 1);
2825
2828
  // src/utils/git.ts
2826
2829
  var import_node_child_process8 = require("child_process");
2827
2830
  var import_node_util7 = require("util");
2828
- var execAsync = (0, import_node_util7.promisify)(import_node_child_process8.exec);
2829
- async function gitCommand(command, cwd = process.cwd()) {
2831
+ var execFileAsync5 = (0, import_node_util7.promisify)(import_node_child_process8.execFile);
2832
+ async function gitCommand(args, cwd = process.cwd()) {
2830
2833
  try {
2831
- const { stdout } = await execAsync(command, { cwd });
2834
+ const { stdout } = await execFileAsync5("git", args, { cwd });
2832
2835
  return stdout.trim();
2833
2836
  } catch (error) {
2834
2837
  return null;
2835
2838
  }
2836
2839
  }
2840
+ var GitCommandError = class extends Error {
2841
+ command;
2842
+ stderr;
2843
+ stdout;
2844
+ exitCode;
2845
+ constructor(opts) {
2846
+ const trimmed = opts.stderr.trim() || opts.stdout.trim() || "unknown error";
2847
+ super(`git command failed: \`${opts.command}\`
2848
+ ${trimmed}`);
2849
+ this.name = "GitCommandError";
2850
+ this.command = opts.command;
2851
+ this.stderr = opts.stderr;
2852
+ this.stdout = opts.stdout;
2853
+ this.exitCode = opts.exitCode;
2854
+ }
2855
+ };
2856
+ async function gitCommandOrThrow(args, cwd = process.cwd()) {
2857
+ const command = `git ${args.join(" ")}`;
2858
+ try {
2859
+ const { stdout } = await execFileAsync5("git", args, { cwd });
2860
+ return stdout.trim();
2861
+ } catch (error) {
2862
+ const e = error;
2863
+ throw new GitCommandError({
2864
+ command,
2865
+ stderr: (e.stderr ?? "").toString(),
2866
+ stdout: (e.stdout ?? "").toString(),
2867
+ exitCode: typeof e.code === "number" ? e.code : null
2868
+ });
2869
+ }
2870
+ }
2837
2871
  async function isGitRepo(cwd = process.cwd()) {
2838
- const result = await gitCommand("git rev-parse --is-inside-work-tree", cwd);
2872
+ const result = await gitCommand(["rev-parse", "--is-inside-work-tree"], cwd);
2839
2873
  return result === "true";
2840
2874
  }
2841
2875
  async function getRemoteUrl(cwd = process.cwd()) {
2842
- return gitCommand("git config --get remote.origin.url", cwd);
2876
+ return gitCommand(["config", "--get", "remote.origin.url"], cwd);
2843
2877
  }
2844
2878
  function parseGitHubUrl(url) {
2845
2879
  const sshMatch = url.match(/git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/);
@@ -2854,16 +2888,16 @@ function parseGitHubUrl(url) {
2854
2888
  };
2855
2889
  }
2856
2890
  async function getCurrentBranch(cwd = process.cwd()) {
2857
- return gitCommand("git rev-parse --abbrev-ref HEAD", cwd);
2891
+ return gitCommand(["rev-parse", "--abbrev-ref", "HEAD"], cwd);
2858
2892
  }
2859
2893
  async function getCommitSha(cwd = process.cwd()) {
2860
- return gitCommand("git rev-parse HEAD", cwd);
2894
+ return gitCommand(["rev-parse", "HEAD"], cwd);
2861
2895
  }
2862
2896
  async function getCommitMessage(cwd = process.cwd()) {
2863
- return gitCommand("git log -1 --pretty=%B", cwd);
2897
+ return gitCommand(["log", "-1", "--pretty=%B"], cwd);
2864
2898
  }
2865
2899
  async function hasUncommittedChanges(cwd = process.cwd()) {
2866
- const result = await gitCommand("git status --porcelain", cwd);
2900
+ const result = await gitCommand(["status", "--porcelain"], cwd);
2867
2901
  return result !== null && result.length > 0;
2868
2902
  }
2869
2903
  async function getGitInfo(cwd = process.cwd()) {
@@ -2897,18 +2931,20 @@ async function getGitInfo(cwd = process.cwd()) {
2897
2931
  };
2898
2932
  }
2899
2933
  async function gitInit(cwd, message = "Initial commit") {
2900
- await gitCommand("git init", cwd);
2901
- await gitCommand("git add .", cwd);
2902
- await gitCommand(`git commit -m "${message}"`, cwd);
2934
+ await gitCommandOrThrow(["init"], cwd);
2935
+ await gitCommandOrThrow(["add", "."], cwd);
2936
+ await gitCommandOrThrow(["commit", "-m", message], cwd);
2937
+ await gitCommandOrThrow(["branch", "-M", "main"], cwd);
2938
+ await gitCommandOrThrow(["rev-parse", "HEAD"], cwd);
2903
2939
  }
2904
2940
  async function gitAddRemoteAndPush(cwd, cloneUrl, branch = "main") {
2905
- await gitCommand(`git remote add origin ${cloneUrl}`, cwd);
2906
- await gitCommand(`git push -u origin ${branch}`, cwd);
2941
+ await gitCommandOrThrow(["remote", "add", "origin", cloneUrl], cwd);
2942
+ await gitCommandOrThrow(["push", "-u", "origin", branch], cwd);
2907
2943
  }
2908
2944
  async function gitCommitAndPush(cwd, message, branch = "main") {
2909
- await gitCommand("git add .", cwd);
2910
- await gitCommand(`git commit -m "${message}"`, cwd);
2911
- await gitCommand(`git push origin ${branch}`, cwd);
2945
+ await gitCommandOrThrow(["add", "."], cwd);
2946
+ await gitCommandOrThrow(["commit", "-m", message], cwd);
2947
+ await gitCommandOrThrow(["push", "origin", branch], cwd);
2912
2948
  }
2913
2949
  function isGitHubUrl(url) {
2914
2950
  try {
@@ -3309,6 +3345,58 @@ async function displayDeploymentProgress(api, deploymentId, progressOptions) {
3309
3345
  source_default.gray("Check status with: ") + source_default.white(`mcp-use deployments get ${deploymentId}`)
3310
3346
  );
3311
3347
  }
3348
+ async function promptReauthenticateOn401(options, orgIdToRestore) {
3349
+ console.log(source_default.red("\n\u2717 Session expired or API key invalid."));
3350
+ if (options.yes) {
3351
+ console.log(
3352
+ source_default.gray(" Run mcp-use login to re-authenticate, then retry.")
3353
+ );
3354
+ process.exit(1);
3355
+ }
3356
+ const should = await prompt(source_default.white("Log in again? (Y/n): "), "y");
3357
+ if (!should) {
3358
+ process.exit(1);
3359
+ }
3360
+ await loginCommand({ silent: false });
3361
+ if (!await isLoggedIn()) {
3362
+ console.log(source_default.red("\u2717 Login failed. Please try again."));
3363
+ process.exit(1);
3364
+ }
3365
+ const fresh = await McpUseAPI.create();
3366
+ if (orgIdToRestore) {
3367
+ fresh.setOrgId(orgIdToRestore);
3368
+ }
3369
+ return fresh;
3370
+ }
3371
+ async function ensureApiSessionForDeploy(api, options, orgIdToRestore) {
3372
+ let client = api;
3373
+ for (; ; ) {
3374
+ try {
3375
+ await client.testAuth();
3376
+ return client;
3377
+ } catch (e) {
3378
+ if (!(e instanceof ApiUnauthorizedError)) throw e;
3379
+ client = await promptReauthenticateOn401(options, orgIdToRestore);
3380
+ }
3381
+ }
3382
+ }
3383
+ async function getGitHubConnectionStatusWith401Retry(api, options, orgIdToRestore) {
3384
+ let client = api;
3385
+ for (let attempt = 0; attempt < 2; attempt++) {
3386
+ try {
3387
+ const status = await client.getGitHubConnectionStatus();
3388
+ return { api: client, status };
3389
+ } catch (e) {
3390
+ if (e instanceof ApiUnauthorizedError && attempt === 0) {
3391
+ client = await promptReauthenticateOn401(options, orgIdToRestore);
3392
+ await client.testAuth();
3393
+ continue;
3394
+ }
3395
+ throw e;
3396
+ }
3397
+ }
3398
+ throw new Error("Unreachable");
3399
+ }
3312
3400
  async function checkRepoAccess(api, owner, repo) {
3313
3401
  try {
3314
3402
  const resp = await api.getGitHubRepos(true);
@@ -3319,6 +3407,7 @@ async function checkRepoAccess(api, owner, repo) {
3319
3407
  }
3320
3408
  async function promptGitHubInstallation(api, reason, repoName, opts) {
3321
3409
  const yes = !!opts?.yes;
3410
+ const reauth = opts?.reauth;
3322
3411
  console.log();
3323
3412
  if (reason === "not_connected") {
3324
3413
  console.log(source_default.yellow("\u26A0\uFE0F GitHub account not connected"));
@@ -3342,9 +3431,23 @@ async function promptGitHubInstallation(api, reason, repoName, opts) {
3342
3431
  ),
3343
3432
  "y"
3344
3433
  );
3345
- if (!shouldInstall) return false;
3434
+ if (!shouldInstall) return { ok: false, api };
3435
+ let client = api;
3346
3436
  try {
3347
- const appName = await api.getGitHubAppName();
3437
+ let appName;
3438
+ for (; ; ) {
3439
+ try {
3440
+ appName = await client.getGitHubAppName();
3441
+ break;
3442
+ } catch (e) {
3443
+ if (e instanceof ApiUnauthorizedError && reauth) {
3444
+ client = await reauth();
3445
+ await client.testAuth();
3446
+ continue;
3447
+ }
3448
+ throw e;
3449
+ }
3450
+ }
3348
3451
  const installUrl = `https://github.com/apps/${appName}/installations/new`;
3349
3452
  console.log(source_default.cyan(`
3350
3453
  Opening browser...`));
@@ -3368,23 +3471,34 @@ Opening browser...`));
3368
3471
  while (Date.now() < deadline) {
3369
3472
  await new Promise((r) => setTimeout(r, 2e3));
3370
3473
  try {
3371
- const status = await api.getGitHubConnectionStatus();
3474
+ const status = await client.getGitHubConnectionStatus();
3372
3475
  if (status.is_connected) {
3373
- if (!repoName) return true;
3476
+ if (!repoName) return { ok: true, api: client };
3374
3477
  const [o, r] = repoName.split("/");
3375
- if (o && r && await checkRepoAccess(api, o, r)) return true;
3478
+ if (o && r && await checkRepoAccess(client, o, r)) {
3479
+ return { ok: true, api: client };
3480
+ }
3481
+ }
3482
+ } catch (e) {
3483
+ if (e instanceof ApiUnauthorizedError && reauth) {
3484
+ client = await reauth();
3485
+ await client.testAuth();
3486
+ continue;
3376
3487
  }
3377
- } catch {
3378
3488
  }
3379
3489
  }
3380
3490
  }
3381
- return true;
3382
- } catch {
3491
+ return { ok: true, api: client };
3492
+ } catch (e) {
3493
+ if (e instanceof ApiUnauthorizedError) {
3494
+ console.log(source_default.red("\n\u2717 Session expired or API key invalid."));
3495
+ process.exit(1);
3496
+ }
3383
3497
  console.log(source_default.yellow("\n\u26A0\uFE0F Unable to open browser automatically"));
3384
3498
  console.log(
3385
3499
  source_default.white("Please visit: ") + source_default.cyan("https://manufact.com/cloud/settings")
3386
3500
  );
3387
- return false;
3501
+ return { ok: false, api: client };
3388
3502
  }
3389
3503
  }
3390
3504
  async function deployCommand(options) {
@@ -3427,7 +3541,8 @@ async function deployCommand(options) {
3427
3541
  process.exit(1);
3428
3542
  }
3429
3543
  }
3430
- const api = await McpUseAPI.create();
3544
+ let api = await McpUseAPI.create();
3545
+ let resolvedOrgId;
3431
3546
  if (options.org) {
3432
3547
  const authInfo = await api.testAuth();
3433
3548
  const match = (authInfo.orgs ?? []).find(
@@ -3435,6 +3550,7 @@ async function deployCommand(options) {
3435
3550
  );
3436
3551
  if (match) {
3437
3552
  api.setOrgId(match.id);
3553
+ resolvedOrgId = match.id;
3438
3554
  const slug = match.slug ? source_default.gray(` (${match.slug})`) : "";
3439
3555
  console.log(
3440
3556
  source_default.gray("Organization: ") + source_default.cyan(match.name) + slug
@@ -3473,6 +3589,7 @@ async function deployCommand(options) {
3473
3589
  process.exit(1);
3474
3590
  }
3475
3591
  api.setOrgId(selectedOrg.id);
3592
+ resolvedOrgId = selectedOrg.id;
3476
3593
  await writeConfig({
3477
3594
  ...config,
3478
3595
  orgId: selectedOrg.id,
@@ -3483,6 +3600,8 @@ async function deployCommand(options) {
3483
3600
  source_default.gray("Organization: ") + source_default.cyan(selectedOrg.name)
3484
3601
  );
3485
3602
  } else {
3603
+ resolvedOrgId = config.orgId;
3604
+ api.setOrgId(config.orgId);
3486
3605
  if (config.orgName) {
3487
3606
  const slug = config.orgSlug ? source_default.gray(` (${config.orgSlug})`) : "";
3488
3607
  console.log(
@@ -3491,21 +3610,39 @@ async function deployCommand(options) {
3491
3610
  }
3492
3611
  }
3493
3612
  }
3613
+ api = await ensureApiSessionForDeploy(api, options, resolvedOrgId);
3494
3614
  console.log(source_default.cyan.bold("\n\u{1F680} Deploying to Manufact cloud...\n"));
3495
- let connectionStatus = await api.getGitHubConnectionStatus().catch(() => null);
3496
- if (!connectionStatus?.is_connected) {
3615
+ const reauth = () => promptReauthenticateOn401(options, resolvedOrgId);
3616
+ let ghConn = await getGitHubConnectionStatusWith401Retry(
3617
+ api,
3618
+ options,
3619
+ resolvedOrgId
3620
+ );
3621
+ api = ghConn.api;
3622
+ let connectionStatus = ghConn.status;
3623
+ if (!connectionStatus.is_connected) {
3497
3624
  const installed = await promptGitHubInstallation(
3498
3625
  api,
3499
3626
  "not_connected",
3500
3627
  void 0,
3501
- { yes: options.yes }
3628
+ {
3629
+ yes: options.yes,
3630
+ reauth
3631
+ }
3502
3632
  );
3503
- if (!installed) {
3633
+ if (!installed.ok) {
3504
3634
  console.log(source_default.gray("Deployment cancelled."));
3505
3635
  process.exit(0);
3506
3636
  }
3507
- connectionStatus = await api.getGitHubConnectionStatus().catch(() => null);
3508
- if (!connectionStatus?.is_connected) {
3637
+ api = installed.api;
3638
+ ghConn = await getGitHubConnectionStatusWith401Retry(
3639
+ api,
3640
+ options,
3641
+ resolvedOrgId
3642
+ );
3643
+ api = ghConn.api;
3644
+ connectionStatus = ghConn.status;
3645
+ if (!connectionStatus.is_connected) {
3509
3646
  console.log(source_default.red("\n\u2717 GitHub connection could not be verified."));
3510
3647
  console.log(
3511
3648
  source_default.cyan(
@@ -3672,27 +3809,56 @@ async function deployCommand(options) {
3672
3809
  }
3673
3810
  }
3674
3811
  console.log(source_default.green(`\u2713 Created ${source_default.cyan(repoResult.fullName)}`));
3675
- if (!gitInfo.isGitRepo) {
3676
- await ensureGitignore(cwd);
3677
- console.log(source_default.gray("Initializing git..."));
3678
- await gitInit(cwd, "Initial commit");
3679
- console.log(source_default.gray("Pushing to GitHub..."));
3680
- await gitAddRemoteAndPush(cwd, repoResult.cloneUrl, "main");
3681
- } else {
3682
- if (await hasUncommittedChanges(cwd)) {
3683
- console.log(
3684
- source_default.red(
3685
- "\u2717 You have uncommitted changes. Commit and push before deploying."
3686
- )
3812
+ try {
3813
+ if (!gitInfo.isGitRepo) {
3814
+ await ensureGitignore(cwd);
3815
+ console.log(source_default.gray("Initializing git..."));
3816
+ await gitInit(cwd, "Initial commit");
3817
+ console.log(source_default.gray("Pushing to GitHub..."));
3818
+ await gitAddRemoteAndPush(cwd, repoResult.cloneUrl, "main");
3819
+ } else {
3820
+ if (await hasUncommittedChanges(cwd)) {
3821
+ console.log(
3822
+ source_default.red(
3823
+ "\u2717 You have uncommitted changes. Commit and push before deploying."
3824
+ )
3825
+ );
3826
+ process.exit(1);
3827
+ }
3828
+ console.log(source_default.gray("Adding remote and pushing..."));
3829
+ await gitAddRemoteAndPush(
3830
+ cwd,
3831
+ repoResult.cloneUrl,
3832
+ gitInfo.branch || "main"
3687
3833
  );
3834
+ }
3835
+ } catch (err) {
3836
+ if (err instanceof GitCommandError) {
3837
+ console.log(source_default.red(`
3838
+ \u2717 Git step failed: \`${err.command}\``));
3839
+ const stderrTrimmed = (err.stderr || err.stdout).trim();
3840
+ if (stderrTrimmed) {
3841
+ console.log(source_default.gray(stderrTrimmed));
3842
+ }
3843
+ if (/tell me who you are|user\.email|user\.name/i.test(err.stderr)) {
3844
+ console.log(
3845
+ source_default.yellow(
3846
+ `
3847
+ Set your git identity for this project and retry:
3848
+ git -C ${JSON.stringify(cwd)} config user.email "you@example.com"
3849
+ git -C ${JSON.stringify(cwd)} config user.name "Your Name"`
3850
+ )
3851
+ );
3852
+ } else if (/non-fast-forward|rejected|unrelated histories/i.test(err.stderr)) {
3853
+ console.log(
3854
+ source_default.yellow(
3855
+ "\n The remote branch already has commits. Either delete the empty GitHub repo and retry, or reconcile manually:\n git pull --rebase origin main --allow-unrelated-histories\n git push -u origin main"
3856
+ )
3857
+ );
3858
+ }
3688
3859
  process.exit(1);
3689
3860
  }
3690
- console.log(source_default.gray("Adding remote and pushing..."));
3691
- await gitAddRemoteAndPush(
3692
- cwd,
3693
- repoResult.cloneUrl,
3694
- gitInfo.branch || "main"
3695
- );
3861
+ throw err;
3696
3862
  }
3697
3863
  console.log(source_default.green("\u2713 Code pushed to GitHub\n"));
3698
3864
  gitInfo = await getGitInfo(cwd);
@@ -3755,11 +3921,16 @@ async function deployCommand(options) {
3755
3921
  api,
3756
3922
  "no_access",
3757
3923
  repoFullName,
3758
- { yes: options.yes, installationId: githubInstallationId }
3924
+ {
3925
+ yes: options.yes,
3926
+ installationId: githubInstallationId,
3927
+ reauth: () => promptReauthenticateOn401(options, resolvedOrgId)
3928
+ }
3759
3929
  );
3760
- if (!configured) {
3930
+ if (!configured.ok) {
3761
3931
  process.exit(0);
3762
3932
  }
3933
+ api = configured.api;
3763
3934
  const retry = await checkRepoAccess(api, gitInfo.owner, gitInfo.repo);
3764
3935
  if (!retry) {
3765
3936
  const appName = await api.getGitHubAppName();