@mcp-use/cli 2.10.2 → 2.10.3

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":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AA2PA;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,CAAC,EAAE;IAC3C,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkHhB;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CA8BnD;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAkCnD"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AA0SA;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,CAAC,EAAE;IAC3C,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqHhB;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CA8BnD;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAkCnD"}
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAsKA,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;CAClB;AAuWD;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAiSzE"}
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAsKA,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;CAClB;AA8kBD;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAuZzE"}
package/dist/index.cjs CHANGED
@@ -1134,6 +1134,7 @@ var open_default = open;
1134
1134
  var import_zod = require("zod");
1135
1135
 
1136
1136
  // src/commands/auth.ts
1137
+ var import_node_crypto = __toESM(require("crypto"), 1);
1137
1138
  var import_node_http = require("http");
1138
1139
 
1139
1140
  // src/utils/config.ts
@@ -1464,6 +1465,27 @@ var McpUseAPI = class _McpUseAPI {
1464
1465
  );
1465
1466
  return response.data.logs;
1466
1467
  }
1468
+ /**
1469
+ * Get GitHub connection status
1470
+ */
1471
+ async getGitHubConnectionStatus() {
1472
+ return this.request("/github/connection");
1473
+ }
1474
+ /**
1475
+ * Get GitHub app name
1476
+ */
1477
+ async getGitHubAppName() {
1478
+ const response = await this.request("/github/appname");
1479
+ return response.app_name;
1480
+ }
1481
+ /**
1482
+ * Get accessible GitHub repositories
1483
+ */
1484
+ async getGitHubRepos(refresh = false) {
1485
+ return this.request(
1486
+ `/github/repos${refresh ? "?refresh=true" : ""}`
1487
+ );
1488
+ }
1467
1489
  };
1468
1490
 
1469
1491
  // src/commands/auth.ts
@@ -1487,7 +1509,7 @@ async function findAvailablePort(startPort = 8765) {
1487
1509
  }
1488
1510
  throw new Error("No available ports found");
1489
1511
  }
1490
- async function startCallbackServer(port) {
1512
+ async function startCallbackServer(port, expectedState) {
1491
1513
  return new Promise((resolve, reject) => {
1492
1514
  let tokenResolver = null;
1493
1515
  const tokenPromise = new Promise((res) => {
@@ -1497,6 +1519,49 @@ async function startCallbackServer(port) {
1497
1519
  if (req.url?.startsWith("/callback")) {
1498
1520
  const url = new URL(req.url, `http://localhost:${port}`);
1499
1521
  const token = url.searchParams.get("token");
1522
+ const state = url.searchParams.get("state");
1523
+ if (state !== expectedState) {
1524
+ res.writeHead(400, { "Content-Type": "text/html" });
1525
+ res.end(`
1526
+ <!DOCTYPE html>
1527
+ <html>
1528
+ <head>
1529
+ <title>Security Error</title>
1530
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
1531
+ <style>
1532
+ body {
1533
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1534
+ display: flex;
1535
+ justify-content: center;
1536
+ align-items: center;
1537
+ min-height: 100vh;
1538
+ background: #000;
1539
+ padding: 1rem;
1540
+ margin: 0;
1541
+ }
1542
+ .container {
1543
+ max-width: 28rem;
1544
+ padding: 3rem;
1545
+ text-align: center;
1546
+ background: rgba(255, 255, 255, 0.1);
1547
+ backdrop-filter: blur(40px);
1548
+ border: 1px solid rgba(255, 255, 255, 0.2);
1549
+ border-radius: 1.5rem;
1550
+ }
1551
+ h1 { color: #fff; font-size: 2rem; margin-bottom: 1rem; }
1552
+ p { color: rgba(255, 255, 255, 0.8); font-size: 1rem; }
1553
+ </style>
1554
+ </head>
1555
+ <body>
1556
+ <div class="container">
1557
+ <h1>Security Error</h1>
1558
+ <p>Invalid state parameter. Please try logging in again.</p>
1559
+ </div>
1560
+ </body>
1561
+ </html>
1562
+ `);
1563
+ return;
1564
+ }
1500
1565
  if (token && tokenResolver) {
1501
1566
  res.writeHead(200, { "Content-Type": "text/html" });
1502
1567
  res.end(`
@@ -1699,12 +1764,13 @@ async function loginCommand(options) {
1699
1764
  return;
1700
1765
  }
1701
1766
  console.log(source_default.cyan.bold("\u{1F510} Logging in to mcp-use cloud...\n"));
1767
+ const state = import_node_crypto.default.randomBytes(32).toString("hex");
1702
1768
  const port = await findAvailablePort();
1703
1769
  const redirectUri = `http://localhost:${port}/callback`;
1704
1770
  console.log(source_default.gray(`Starting local server on port ${port}...`));
1705
- const { server, token } = await startCallbackServer(port);
1771
+ const { server, token } = await startCallbackServer(port, state);
1706
1772
  const webUrl = await getWebUrl();
1707
- const loginUrl = `${webUrl}/auth/cli?redirect_uri=${encodeURIComponent(redirectUri)}`;
1773
+ const loginUrl = `${webUrl}/auth/cli?redirect_uri=${encodeURIComponent(redirectUri)}&state=${state}`;
1708
1774
  console.log(source_default.gray(`Opening browser to ${webUrl}/auth/cli...
1709
1775
  `));
1710
1776
  console.log(
@@ -3269,33 +3335,78 @@ async function displayDeploymentProgress(api, deployment) {
3269
3335
  lastDisplayedLogLength = finalDeployment.buildLogs.length;
3270
3336
  }
3271
3337
  if (finalDeployment.status === "running") {
3272
- const mcpUrl = `https://${finalDeployment.domain}/mcp`;
3273
- const inspectorUrl = `https://inspector.mcp-use.com/inspector?autoConnect=${encodeURIComponent(mcpUrl)}`;
3338
+ let mcpServerUrl;
3339
+ let dashboardUrl = null;
3340
+ if (finalDeployment.customDomain) {
3341
+ mcpServerUrl = `https://${finalDeployment.customDomain}/mcp`;
3342
+ if (finalDeployment.serverSlug) {
3343
+ dashboardUrl = `https://mcp-use.com/cloud/servers/${finalDeployment.serverSlug}`;
3344
+ }
3345
+ } else if (finalDeployment.serverSlug) {
3346
+ mcpServerUrl = `https://${finalDeployment.serverSlug}.mcp-use.run/mcp`;
3347
+ dashboardUrl = `https://mcp-use.com/cloud/servers/${finalDeployment.serverSlug}`;
3348
+ } else if (finalDeployment.serverId) {
3349
+ mcpServerUrl = `https://${finalDeployment.serverId}.mcp-use.run/mcp`;
3350
+ dashboardUrl = `https://mcp-use.com/cloud/servers/${finalDeployment.serverId}`;
3351
+ } else {
3352
+ mcpServerUrl = `https://${finalDeployment.domain}/mcp`;
3353
+ }
3354
+ const inspectorUrl = `https://inspector.mcp-use.com/inspector?autoConnect=${encodeURIComponent(
3355
+ mcpServerUrl
3356
+ )}`;
3274
3357
  console.log(source_default.green.bold("\u2713 Deployment successful!\n"));
3275
3358
  console.log(source_default.white("\u{1F310} MCP Server URL:"));
3276
- console.log(source_default.cyan.bold(` ${mcpUrl}
3359
+ console.log(source_default.cyan.bold(` ${mcpServerUrl}
3277
3360
  `));
3361
+ if (dashboardUrl) {
3362
+ console.log(source_default.white("\u{1F4CA} Dashboard:"));
3363
+ console.log(source_default.cyan.bold(` ${dashboardUrl}
3364
+ `));
3365
+ }
3278
3366
  console.log(source_default.white("\u{1F50D} Inspector URL:"));
3279
3367
  console.log(source_default.cyan.bold(` ${inspectorUrl}
3280
3368
  `));
3281
- if (finalDeployment.customDomain) {
3282
- const customMcpUrl = `https://${finalDeployment.customDomain}/mcp`;
3283
- const customInspectorUrl = `https://inspector.mcp-use.com/inspect?autoConnect=${encodeURIComponent(customMcpUrl)}`;
3284
- console.log(source_default.white("\u{1F517} Custom Domain:"));
3285
- console.log(source_default.cyan.bold(` ${customMcpUrl}
3286
- `));
3287
- console.log(source_default.white("\u{1F50D} Custom Inspector:"));
3288
- console.log(source_default.cyan.bold(` ${customInspectorUrl}
3289
- `));
3290
- }
3291
3369
  console.log(
3292
3370
  source_default.gray("Deployment ID: ") + source_default.white(finalDeployment.id)
3293
3371
  );
3294
3372
  return;
3295
3373
  } else if (finalDeployment.status === "failed") {
3374
+ stopSpinner();
3296
3375
  console.log(source_default.red.bold("\u2717 Deployment failed\n"));
3297
3376
  if (finalDeployment.error) {
3298
3377
  console.log(source_default.red("Error: ") + finalDeployment.error);
3378
+ if (finalDeployment.error.includes("No GitHub installations found")) {
3379
+ console.log();
3380
+ const retry = await promptGitHubInstallation(api, "not_connected");
3381
+ if (retry) {
3382
+ console.log(source_default.cyan("\n\u{1F504} Retrying deployment...\n"));
3383
+ const newDeployment = await api.redeployDeployment(deployment.id);
3384
+ await displayDeploymentProgress(api, newDeployment);
3385
+ return;
3386
+ }
3387
+ } else if (finalDeployment.error.includes("Authenticated git clone failed")) {
3388
+ let repoName;
3389
+ const repoMatch = finalDeployment.error.match(
3390
+ /github\.com\/([^/]+\/[^/\s]+)/
3391
+ );
3392
+ if (repoMatch) {
3393
+ repoName = repoMatch[1].replace(/\.git$/, "");
3394
+ } else if (finalDeployment.source.type === "github") {
3395
+ repoName = finalDeployment.source.repo;
3396
+ }
3397
+ console.log();
3398
+ const retry = await promptGitHubInstallation(
3399
+ api,
3400
+ "no_access",
3401
+ repoName
3402
+ );
3403
+ if (retry) {
3404
+ console.log(source_default.cyan("\n\u{1F504} Retrying deployment...\n"));
3405
+ const newDeployment = await api.redeployDeployment(deployment.id);
3406
+ await displayDeploymentProgress(api, newDeployment);
3407
+ return;
3408
+ }
3409
+ }
3299
3410
  }
3300
3411
  if (finalDeployment.buildLogs) {
3301
3412
  console.log(source_default.gray("\nBuild logs:"));
@@ -3333,6 +3444,137 @@ async function displayDeploymentProgress(api, deployment) {
3333
3444
  source_default.gray("Check status with: ") + source_default.white(`mcp-use status ${deployment.id}`)
3334
3445
  );
3335
3446
  }
3447
+ async function checkRepoAccess(api, owner, repo) {
3448
+ try {
3449
+ const reposResponse = await api.getGitHubRepos(true);
3450
+ const repoFullName = `${owner}/${repo}`;
3451
+ return reposResponse.repos.some((r) => r.full_name === repoFullName);
3452
+ } catch (error) {
3453
+ console.log(source_default.gray("Could not verify repository access"));
3454
+ return false;
3455
+ }
3456
+ }
3457
+ async function promptGitHubInstallation(api, reason, repoName) {
3458
+ console.log();
3459
+ if (reason === "not_connected") {
3460
+ console.log(source_default.yellow("\u26A0\uFE0F GitHub account not connected"));
3461
+ console.log(
3462
+ source_default.white("Deployments require a connected GitHub account.\n")
3463
+ );
3464
+ } else {
3465
+ console.log(
3466
+ source_default.yellow("\u26A0\uFE0F GitHub App doesn't have access to this repository")
3467
+ );
3468
+ console.log(
3469
+ source_default.white(
3470
+ `The GitHub App needs permission to access ${source_default.cyan(repoName || "this repository")}.
3471
+ `
3472
+ )
3473
+ );
3474
+ }
3475
+ const shouldInstall = await prompt(
3476
+ source_default.white(
3477
+ `Would you like to ${reason === "not_connected" ? "connect" : "configure"} GitHub now? (Y/n): `
3478
+ ),
3479
+ "y"
3480
+ );
3481
+ if (!shouldInstall) {
3482
+ return false;
3483
+ }
3484
+ try {
3485
+ const appName = process.env.MCP_GITHUB_APP_NAME || "mcp-use";
3486
+ const installUrl = reason === "not_connected" ? `https://github.com/apps/${appName}/installations/new` : `https://github.com/settings/installations`;
3487
+ console.log(
3488
+ source_default.cyan(
3489
+ `
3490
+ Opening browser to ${reason === "not_connected" ? "install" : "configure"} GitHub App...`
3491
+ )
3492
+ );
3493
+ console.log(source_default.gray(`URL: ${installUrl}
3494
+ `));
3495
+ if (reason === "no_access") {
3496
+ console.log(source_default.white("Please:"));
3497
+ console.log(
3498
+ source_default.cyan(" 1. Find the 'mcp-use' (or similar) GitHub App")
3499
+ );
3500
+ console.log(source_default.cyan(" 2. Click 'Configure'"));
3501
+ console.log(
3502
+ source_default.cyan(
3503
+ ` 3. Grant access to ${source_default.bold(repoName || "your repository")}`
3504
+ )
3505
+ );
3506
+ console.log(source_default.cyan(" 4. Save your changes"));
3507
+ console.log(source_default.cyan(" 5. Return here when done\n"));
3508
+ } else {
3509
+ console.log(source_default.white("Please:"));
3510
+ console.log(source_default.cyan(" 1. Select the repositories to grant access"));
3511
+ if (repoName) {
3512
+ console.log(
3513
+ source_default.cyan(` 2. Make sure to include ${source_default.bold(repoName)}`)
3514
+ );
3515
+ console.log(source_default.cyan(" 3. Complete the installation"));
3516
+ } else {
3517
+ console.log(source_default.cyan(" 2. Complete the installation"));
3518
+ }
3519
+ console.log();
3520
+ }
3521
+ await open_default(installUrl);
3522
+ console.log(source_default.gray("Waiting for GitHub configuration..."));
3523
+ await prompt(
3524
+ source_default.white("Press Enter when you've completed the GitHub setup..."),
3525
+ "y"
3526
+ );
3527
+ console.log(source_default.gray("Verifying GitHub connection..."));
3528
+ let verified = false;
3529
+ try {
3530
+ const status = await api.getGitHubConnectionStatus();
3531
+ if (!status.is_connected) {
3532
+ console.log(source_default.yellow("\u26A0\uFE0F GitHub connection not detected."));
3533
+ } else if (repoName) {
3534
+ const [owner, repo] = repoName.split("/");
3535
+ console.log(source_default.gray(`Checking access to ${repoName}...`));
3536
+ const hasAccess = await checkRepoAccess(api, owner, repo);
3537
+ if (!hasAccess) {
3538
+ console.log(
3539
+ source_default.yellow(
3540
+ `\u26A0\uFE0F The GitHub App may not have access to ${source_default.cyan(repoName)} yet`
3541
+ )
3542
+ );
3543
+ } else {
3544
+ console.log(source_default.green(`\u2713 Repository ${repoName} is accessible!
3545
+ `));
3546
+ verified = true;
3547
+ }
3548
+ } else {
3549
+ console.log(source_default.green("\u2713 GitHub connected successfully!\n"));
3550
+ verified = true;
3551
+ }
3552
+ } catch (error) {
3553
+ console.log(
3554
+ source_default.yellow("\u26A0\uFE0F Could not verify GitHub connection (API issue)")
3555
+ );
3556
+ }
3557
+ if (!verified) {
3558
+ console.log(
3559
+ source_default.gray(
3560
+ "\nNote: If you completed the GitHub setup, the deployment may work now.\n"
3561
+ )
3562
+ );
3563
+ }
3564
+ return true;
3565
+ } catch (error) {
3566
+ console.log(
3567
+ source_default.yellow("\n\u26A0\uFE0F Unable to open GitHub installation automatically")
3568
+ );
3569
+ console.log(
3570
+ source_default.white("Please visit: ") + source_default.cyan("https://cloud.mcp-use.com/cloud/settings")
3571
+ );
3572
+ console.log(
3573
+ source_default.gray("Then connect your GitHub account and try again.\n")
3574
+ );
3575
+ return false;
3576
+ }
3577
+ }
3336
3578
  async function deployCommand(options) {
3337
3579
  try {
3338
3580
  const cwd = process.cwd();
@@ -3455,8 +3697,9 @@ async function deployCommand(options) {
3455
3697
  console.log();
3456
3698
  const shouldDeploy = await prompt(
3457
3699
  source_default.white(
3458
- `Deploy from GitHub repository ${gitInfo.owner}/${gitInfo.repo}? (y/n): `
3459
- )
3700
+ `Deploy from GitHub repository ${gitInfo.owner}/${gitInfo.repo}? (Y/n): `
3701
+ ),
3702
+ "y"
3460
3703
  );
3461
3704
  if (!shouldDeploy) {
3462
3705
  console.log(source_default.gray("Deployment cancelled."));
@@ -3489,6 +3732,111 @@ async function deployCommand(options) {
3489
3732
  }
3490
3733
  console.log();
3491
3734
  const api = await McpUseAPI.create();
3735
+ let githubVerified = false;
3736
+ try {
3737
+ console.log(source_default.gray(`[DEBUG] API URL: ${api.baseUrl}`));
3738
+ const connectionStatus = await api.getGitHubConnectionStatus();
3739
+ if (!connectionStatus.is_connected) {
3740
+ const repoFullName = `${gitInfo.owner}/${gitInfo.repo}`;
3741
+ const installed = await promptGitHubInstallation(
3742
+ api,
3743
+ "not_connected",
3744
+ repoFullName
3745
+ );
3746
+ if (!installed) {
3747
+ console.log(source_default.gray("Deployment cancelled."));
3748
+ process.exit(0);
3749
+ }
3750
+ const retryStatus = await api.getGitHubConnectionStatus();
3751
+ if (!retryStatus.is_connected) {
3752
+ console.log(
3753
+ source_default.red("\n\u2717 GitHub connection could not be verified.")
3754
+ );
3755
+ console.log(
3756
+ source_default.gray("Please try connecting GitHub from the web UI:")
3757
+ );
3758
+ console.log(
3759
+ source_default.cyan(" https://cloud.mcp-use.com/cloud/settings\n")
3760
+ );
3761
+ process.exit(1);
3762
+ }
3763
+ githubVerified = true;
3764
+ } else if (gitInfo.owner && gitInfo.repo) {
3765
+ console.log(source_default.gray("Checking repository access..."));
3766
+ const hasAccess = await checkRepoAccess(
3767
+ api,
3768
+ gitInfo.owner,
3769
+ gitInfo.repo
3770
+ );
3771
+ if (!hasAccess) {
3772
+ const repoFullName = `${gitInfo.owner}/${gitInfo.repo}`;
3773
+ console.log(
3774
+ source_default.yellow(
3775
+ `\u26A0\uFE0F GitHub App doesn't have access to ${source_default.cyan(repoFullName)}`
3776
+ )
3777
+ );
3778
+ const configured = await promptGitHubInstallation(
3779
+ api,
3780
+ "no_access",
3781
+ repoFullName
3782
+ );
3783
+ if (!configured) {
3784
+ console.log(source_default.gray("Deployment cancelled."));
3785
+ process.exit(0);
3786
+ }
3787
+ const hasAccessRetry = await checkRepoAccess(
3788
+ api,
3789
+ gitInfo.owner,
3790
+ gitInfo.repo
3791
+ );
3792
+ if (!hasAccessRetry) {
3793
+ console.log(
3794
+ source_default.red(
3795
+ `
3796
+ \u2717 Repository ${source_default.cyan(repoFullName)} is still not accessible.`
3797
+ )
3798
+ );
3799
+ console.log(
3800
+ source_default.gray(
3801
+ "Please make sure the GitHub App has access to this repository."
3802
+ )
3803
+ );
3804
+ console.log(
3805
+ source_default.cyan(" https://github.com/settings/installations\n")
3806
+ );
3807
+ process.exit(1);
3808
+ }
3809
+ githubVerified = true;
3810
+ } else {
3811
+ console.log(source_default.green("\u2713 Repository access confirmed"));
3812
+ githubVerified = true;
3813
+ }
3814
+ }
3815
+ } catch (error) {
3816
+ console.log(source_default.red("\u2717 Could not verify GitHub connection"));
3817
+ console.log(
3818
+ source_default.gray(
3819
+ "Error: " + (error instanceof Error ? error.message : "Unknown error")
3820
+ )
3821
+ );
3822
+ console.log(source_default.gray("\nPlease ensure:"));
3823
+ console.log(
3824
+ source_default.cyan(
3825
+ " 1. You have connected GitHub at https://cloud.mcp-use.com/cloud/settings"
3826
+ )
3827
+ );
3828
+ console.log(
3829
+ source_default.cyan(" 2. The GitHub App has access to your repository")
3830
+ );
3831
+ console.log(source_default.cyan(" 3. Your internet connection is stable\n"));
3832
+ process.exit(1);
3833
+ }
3834
+ if (!githubVerified) {
3835
+ console.log(
3836
+ source_default.red("\n\u2717 GitHub verification required for this deployment")
3837
+ );
3838
+ process.exit(1);
3839
+ }
3492
3840
  const existingLink = !options.new ? await getProjectLink(cwd) : null;
3493
3841
  if (existingLink) {
3494
3842
  try {