@mcp-use/cli 2.21.5-canary.2 → 3.0.0-canary.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1150,10 +1150,6 @@ var open_default = open;
1150
1150
  var import_vite_plugin_singlefile = require("vite-plugin-singlefile");
1151
1151
  var import_zod = require("zod");
1152
1152
 
1153
- // src/commands/auth.ts
1154
- var import_node_crypto = __toESM(require("crypto"), 1);
1155
- var import_node_http = require("http");
1156
-
1157
1153
  // src/utils/config.ts
1158
1154
  var import_node_fs4 = require("fs");
1159
1155
  var import_node_os3 = __toESM(require("os"), 1);
@@ -1171,14 +1167,21 @@ async function ensureConfigDir() {
1171
1167
  async function readConfig() {
1172
1168
  try {
1173
1169
  const content = await import_node_fs4.promises.readFile(CONFIG_FILE, "utf-8");
1174
- return JSON.parse(content);
1170
+ const raw = JSON.parse(content);
1171
+ return {
1172
+ ...raw,
1173
+ orgId: raw.orgId ?? raw.profileId,
1174
+ orgName: raw.orgName ?? raw.profileName,
1175
+ orgSlug: raw.orgSlug ?? raw.profileSlug
1176
+ };
1175
1177
  } catch (error) {
1176
1178
  return {};
1177
1179
  }
1178
1180
  }
1179
1181
  async function writeConfig(config) {
1180
1182
  await ensureConfigDir();
1181
- await import_node_fs4.promises.writeFile(CONFIG_FILE, JSON.stringify(config, null, 2), "utf-8");
1183
+ const { profileId: _a, profileName: _b, profileSlug: _c, ...clean } = config;
1184
+ await import_node_fs4.promises.writeFile(CONFIG_FILE, JSON.stringify(clean, null, 2), "utf-8");
1182
1185
  }
1183
1186
  async function deleteConfig() {
1184
1187
  try {
@@ -1198,42 +1201,37 @@ async function isLoggedIn() {
1198
1201
  const apiKey = await getApiKey();
1199
1202
  return !!apiKey;
1200
1203
  }
1201
- async function getProfileId() {
1204
+ async function getOrgId() {
1202
1205
  const config = await readConfig();
1203
- return config.profileId || null;
1206
+ return config.orgId || null;
1204
1207
  }
1205
1208
  async function getWebUrl() {
1206
1209
  return DEFAULT_WEB_URL;
1207
1210
  }
1211
+ async function getAuthBaseUrl() {
1212
+ const apiUrl = await getApiUrl();
1213
+ return apiUrl.replace(/\/api\/v1$/, "");
1214
+ }
1208
1215
 
1209
1216
  // src/utils/api.ts
1210
1217
  var McpUseAPI = class _McpUseAPI {
1211
1218
  baseUrl;
1212
1219
  apiKey;
1213
- profileId;
1214
- constructor(baseUrl, apiKey, profileId) {
1220
+ orgId;
1221
+ constructor(baseUrl, apiKey, orgId) {
1215
1222
  this.baseUrl = baseUrl || "";
1216
1223
  this.apiKey = apiKey;
1217
- this.profileId = profileId;
1224
+ this.orgId = orgId;
1218
1225
  }
1219
- /**
1220
- * Initialize API client with config
1221
- */
1222
1226
  static async create() {
1223
1227
  const baseUrl = await getApiUrl();
1224
1228
  const apiKey = await getApiKey();
1225
- const profileId = await getProfileId();
1226
- return new _McpUseAPI(baseUrl, apiKey ?? void 0, profileId ?? void 0);
1229
+ const orgId = await getOrgId();
1230
+ return new _McpUseAPI(baseUrl, apiKey ?? void 0, orgId ?? void 0);
1227
1231
  }
1228
- /**
1229
- * Override the profile ID for this API client instance (e.g. from --org flag)
1230
- */
1231
- setProfileId(profileId) {
1232
- this.profileId = profileId;
1232
+ setOrgId(orgId) {
1233
+ this.orgId = orgId;
1233
1234
  }
1234
- /**
1235
- * Make authenticated request
1236
- */
1237
1235
  async request(endpoint, options = {}) {
1238
1236
  const url = `${this.baseUrl}${endpoint}`;
1239
1237
  const headers = {
@@ -1243,8 +1241,8 @@ var McpUseAPI = class _McpUseAPI {
1243
1241
  if (this.apiKey) {
1244
1242
  headers["x-api-key"] = this.apiKey;
1245
1243
  }
1246
- if (this.profileId) {
1247
- headers["x-profile-id"] = this.profileId;
1244
+ if (this.orgId) {
1245
+ headers["x-profile-id"] = this.orgId;
1248
1246
  }
1249
1247
  const timeout = options.timeout || 3e4;
1250
1248
  const controller = new AbortController();
@@ -1256,6 +1254,13 @@ var McpUseAPI = class _McpUseAPI {
1256
1254
  signal: controller.signal
1257
1255
  });
1258
1256
  clearTimeout(timeoutId);
1257
+ if (response.status === 401) {
1258
+ const err = new Error(
1259
+ "Your session has expired or your API key is invalid."
1260
+ );
1261
+ err.status = 401;
1262
+ throw err;
1263
+ }
1259
1264
  if (!response.ok) {
1260
1265
  const error = await response.text();
1261
1266
  throw new Error(`API request failed: ${response.status} ${error}`);
@@ -1264,25 +1269,24 @@ var McpUseAPI = class _McpUseAPI {
1264
1269
  } catch (error) {
1265
1270
  clearTimeout(timeoutId);
1266
1271
  if (error.name === "AbortError") {
1267
- throw new Error(
1268
- `Request timeout after ${timeout / 1e3}s. Try using --follow flag to stream logs instead.`
1269
- );
1272
+ throw new Error(`Request timeout after ${timeout / 1e3}s.`);
1270
1273
  }
1271
1274
  throw error;
1272
1275
  }
1273
1276
  }
1274
1277
  /**
1275
- * Create API key using JWT token
1278
+ * Create a persistent API key using a Better Auth access token.
1276
1279
  */
1277
- async createApiKey(jwtToken, name = "CLI") {
1278
- const url = `${this.baseUrl}/api-key`;
1280
+ async createApiKeyWithAccessToken(accessToken, name = "CLI") {
1281
+ const authBase = await getAuthBaseUrl();
1282
+ const url = `${authBase}/api/auth/api-key/create`;
1279
1283
  const response = await fetch(url, {
1280
1284
  method: "POST",
1281
1285
  headers: {
1282
1286
  "Content-Type": "application/json",
1283
- Authorization: `Bearer ${jwtToken}`
1287
+ Authorization: `Bearer ${accessToken}`
1284
1288
  },
1285
- body: JSON.stringify({ name })
1289
+ body: JSON.stringify({ name, prefix: "mcp_" })
1286
1290
  });
1287
1291
  if (!response.ok) {
1288
1292
  const error = await response.text();
@@ -1290,540 +1294,195 @@ var McpUseAPI = class _McpUseAPI {
1290
1294
  }
1291
1295
  return response.json();
1292
1296
  }
1293
- /**
1294
- * Test authentication
1295
- */
1297
+ // ── Auth ────────────────────────────────────────────────────────
1296
1298
  async testAuth() {
1297
- return this.request("/test-auth");
1299
+ const wire = await this.request("/test-auth");
1300
+ return {
1301
+ message: wire.message,
1302
+ user_id: wire.user_id,
1303
+ email: wire.email,
1304
+ default_org_id: wire.default_profile_id,
1305
+ orgs: (wire.profiles ?? []).map((p) => ({
1306
+ id: p.id,
1307
+ name: p.profile_name,
1308
+ slug: p.slug,
1309
+ role: p.role
1310
+ }))
1311
+ };
1298
1312
  }
1299
- /**
1300
- * Set the user's default profile (organization) on the server
1301
- */
1302
- async setDefaultProfile(profileId) {
1303
- await this.request(`/profiles/${profileId}/set-default`, {
1313
+ async setDefaultOrg(orgId) {
1314
+ await this.request(`/organizations/${orgId}/set-default`, {
1304
1315
  method: "POST"
1305
1316
  });
1306
1317
  }
1307
- /**
1308
- * Create deployment
1309
- */
1310
- async createDeployment(request) {
1318
+ // ── Organization ID resolution ──────────────────────────────────
1319
+ async resolveOrganizationId() {
1320
+ if (this.orgId) return this.orgId;
1321
+ const auth = await this.testAuth();
1322
+ const id = auth.default_org_id;
1323
+ if (!id) {
1324
+ throw new Error(
1325
+ "No organization set. Run `mcp-use org switch` or use --org to specify one."
1326
+ );
1327
+ }
1328
+ return id;
1329
+ }
1330
+ // ── Servers ─────────────────────────────────────────────────────
1331
+ async createServer(body) {
1332
+ return this.request("/servers", {
1333
+ method: "POST",
1334
+ body: JSON.stringify(body)
1335
+ });
1336
+ }
1337
+ // ── Deployments ─────────────────────────────────────────────────
1338
+ async createDeployment(input) {
1311
1339
  return this.request("/deployments", {
1312
1340
  method: "POST",
1313
- body: JSON.stringify(request)
1341
+ body: JSON.stringify(input)
1314
1342
  });
1315
1343
  }
1316
- /**
1317
- * Get deployment by ID
1318
- */
1319
1344
  async getDeployment(deploymentId) {
1320
1345
  return this.request(`/deployments/${deploymentId}`);
1321
1346
  }
1322
- /**
1323
- * Stream deployment logs
1324
- */
1325
- async *streamDeploymentLogs(deploymentId) {
1326
- const url = `${this.baseUrl}/deployments/${deploymentId}/logs/stream`;
1327
- const headers = {};
1328
- if (this.apiKey) {
1329
- headers["x-api-key"] = this.apiKey;
1330
- }
1331
- if (this.profileId) {
1332
- headers["x-profile-id"] = this.profileId;
1333
- }
1334
- const response = await fetch(url, { headers });
1335
- if (!response.ok) {
1336
- throw new Error(`Failed to stream logs: ${response.status}`);
1337
- }
1338
- if (!response.body) {
1339
- throw new Error("Response body is null");
1340
- }
1341
- const reader = response.body.getReader();
1342
- const decoder = new TextDecoder();
1343
- let buffer = "";
1344
- try {
1345
- while (true) {
1346
- const { done, value } = await reader.read();
1347
- if (done) break;
1348
- buffer += decoder.decode(value, { stream: true });
1349
- const lines = buffer.split("\n");
1350
- buffer = lines.pop() || "";
1351
- for (const line of lines) {
1352
- if (line.startsWith("data: ")) {
1353
- const data = line.slice(6);
1354
- try {
1355
- const parsed = JSON.parse(data);
1356
- if (parsed.log) {
1357
- yield parsed.log;
1358
- } else if (parsed.error) {
1359
- throw new Error(parsed.error);
1360
- }
1361
- } catch (e) {
1362
- }
1363
- }
1364
- }
1365
- }
1366
- } finally {
1367
- reader.releaseLock();
1368
- }
1369
- }
1370
- /**
1371
- * Create deployment with source code upload
1372
- */
1373
- async createDeploymentWithUpload(request, filePath) {
1374
- const { readFile: readFile4 } = await import("fs/promises");
1375
- const { basename } = await import("path");
1376
- const { stat } = await import("fs/promises");
1377
- const stats = await stat(filePath);
1378
- const maxSize = 2 * 1024 * 1024;
1379
- if (stats.size > maxSize) {
1380
- throw new Error(
1381
- `File size (${(stats.size / 1024 / 1024).toFixed(2)}MB) exceeds maximum of 2MB`
1382
- );
1383
- }
1384
- const fileBuffer = await readFile4(filePath);
1385
- const filename = basename(filePath);
1386
- const formData = new FormData();
1387
- const blob = new Blob([fileBuffer], { type: "application/gzip" });
1388
- formData.append("source_file", blob, filename);
1389
- formData.append("name", request.name);
1390
- formData.append("source_type", "upload");
1391
- if (request.source.type === "upload") {
1392
- formData.append("runtime", request.source.runtime || "node");
1393
- formData.append("port", String(request.source.port || 3e3));
1394
- if (request.source.startCommand) {
1395
- formData.append("startCommand", request.source.startCommand);
1396
- }
1397
- if (request.source.buildCommand) {
1398
- formData.append("buildCommand", request.source.buildCommand);
1399
- }
1400
- if (request.source.env && Object.keys(request.source.env).length > 0) {
1401
- formData.append("env", JSON.stringify(request.source.env));
1402
- }
1403
- }
1404
- if (request.customDomain) {
1405
- formData.append("customDomain", request.customDomain);
1406
- }
1407
- if (request.healthCheckPath) {
1408
- formData.append("healthCheckPath", request.healthCheckPath);
1409
- }
1410
- const url = `${this.baseUrl}/deployments`;
1411
- const headers = {};
1412
- if (this.apiKey) {
1413
- headers["x-api-key"] = this.apiKey;
1414
- }
1415
- if (this.profileId) {
1416
- headers["x-profile-id"] = this.profileId;
1417
- }
1418
- const response = await fetch(url, {
1419
- method: "POST",
1420
- headers,
1421
- body: formData
1422
- });
1423
- if (!response.ok) {
1424
- const error = await response.text();
1425
- throw new Error(`Deployment failed: ${error}`);
1426
- }
1427
- return response.json();
1428
- }
1429
- /**
1430
- * List all deployments
1431
- */
1432
1347
  async listDeployments() {
1433
- const response = await this.request("/deployments");
1434
- return response.deployments;
1348
+ return this.request("/deployments");
1435
1349
  }
1436
- /**
1437
- * Delete deployment
1438
- */
1439
1350
  async deleteDeployment(deploymentId) {
1440
1351
  await this.request(`/deployments/${deploymentId}`, {
1441
1352
  method: "DELETE"
1442
1353
  });
1443
1354
  }
1444
- /**
1445
- * Update deployment
1446
- */
1447
- async updateDeployment(deploymentId, updates) {
1448
- return this.request(`/deployments/${deploymentId}`, {
1449
- method: "PATCH",
1450
- body: JSON.stringify(updates)
1451
- });
1452
- }
1453
- /**
1454
- * Redeploy deployment
1455
- *
1456
- * @param deploymentId - The deployment ID to redeploy
1457
- * @param configOrFilePath - Either a RedeploymentConfig object with updated settings,
1458
- * or a file path string for source code upload
1459
- */
1460
- async redeployDeployment(deploymentId, configOrFilePath) {
1461
- if (typeof configOrFilePath === "string") {
1462
- const filePath = configOrFilePath;
1463
- const { readFile: readFile4 } = await import("fs/promises");
1464
- const { basename } = await import("path");
1465
- const { stat } = await import("fs/promises");
1466
- const stats = await stat(filePath);
1467
- const maxSize = 2 * 1024 * 1024;
1468
- if (stats.size > maxSize) {
1469
- throw new Error(
1470
- `File size (${(stats.size / 1024 / 1024).toFixed(2)}MB) exceeds maximum of 2MB`
1471
- );
1472
- }
1473
- const fileBuffer = await readFile4(filePath);
1474
- const formData = new FormData();
1475
- const blob = new Blob([fileBuffer], { type: "application/gzip" });
1476
- formData.append("source_file", blob, basename(filePath));
1477
- const headers = {};
1478
- if (this.apiKey) headers["x-api-key"] = this.apiKey;
1479
- if (this.profileId) headers["x-profile-id"] = this.profileId;
1480
- const response = await fetch(
1481
- `${this.baseUrl}/deployments/${deploymentId}/redeploy`,
1482
- {
1483
- method: "POST",
1484
- headers,
1485
- body: formData
1486
- }
1487
- );
1488
- if (!response.ok) {
1489
- const error = await response.text();
1490
- throw new Error(`Redeploy failed: ${error}`);
1491
- }
1492
- return response.json();
1493
- }
1494
- const config = configOrFilePath;
1495
- return this.request(`/deployments/${deploymentId}/redeploy`, {
1496
- method: "POST",
1497
- body: config ? JSON.stringify(config) : void 0
1355
+ async stopDeployment(deploymentId) {
1356
+ await this.request(`/deployments/${deploymentId}/stop`, {
1357
+ method: "POST"
1498
1358
  });
1499
1359
  }
1500
- /**
1501
- * Get deployment logs
1502
- */
1503
- async getDeploymentLogs(deploymentId) {
1504
- const response = await this.request(
1505
- `/deployments/${deploymentId}/logs`,
1360
+ async getDeploymentLogs(deploymentId, lines = 500) {
1361
+ const resp = await this.request(
1362
+ `/deployments/${deploymentId}/logs?lines=${lines}`,
1506
1363
  { timeout: 6e4 }
1507
- // 60 second timeout for logs
1508
1364
  );
1509
- return response.data.logs;
1365
+ return resp.logs;
1510
1366
  }
1511
- /**
1512
- * Get deployment build logs
1513
- */
1514
- async getDeploymentBuildLogs(deploymentId) {
1515
- const response = await this.request(
1516
- `/deployments/${deploymentId}/logs/build`,
1367
+ async getDeploymentBuildLogs(deploymentId, offset = 0) {
1368
+ return this.request(
1369
+ `/deployments/${deploymentId}/build-logs?offset=${offset}`,
1517
1370
  { timeout: 6e4 }
1518
- // 60 second timeout for logs
1519
1371
  );
1520
- return response.data.logs;
1521
1372
  }
1522
- /**
1523
- * Get GitHub connection status
1524
- */
1373
+ // ── GitHub ──────────────────────────────────────────────────────
1525
1374
  async getGitHubConnectionStatus() {
1526
- return this.request("/github/connection");
1375
+ const orgId = await this.resolveOrganizationId();
1376
+ const resp = await this.request(`/github/installations?organizationId=${orgId}`);
1377
+ return {
1378
+ is_connected: resp.installations.length > 0,
1379
+ installations: resp.installations.map((i) => ({
1380
+ id: i.id,
1381
+ installation_id: i.installationId
1382
+ }))
1383
+ };
1527
1384
  }
1528
- /**
1529
- * Get GitHub app name
1530
- */
1531
- async getGitHubAppName() {
1532
- const response = await this.request("/github/appname");
1533
- return response.app_name;
1385
+ async getGitHubRepos(_refresh) {
1386
+ const orgId = await this.resolveOrganizationId();
1387
+ const installResp = await this.request(`/github/installations?organizationId=${orgId}`);
1388
+ if (installResp.installations.length === 0) {
1389
+ return { user: { login: "", id: 0, avatar_url: "" }, repos: [] };
1390
+ }
1391
+ const inst = installResp.installations[0];
1392
+ const reposResp = await this.request(`/github/installations/${inst.installationId}/repos`);
1393
+ return {
1394
+ user: {
1395
+ login: inst.account?.login ?? "",
1396
+ id: 0,
1397
+ avatar_url: inst.account?.avatar_url ?? ""
1398
+ },
1399
+ repos: reposResp.repos.map((r) => ({
1400
+ id: r.id,
1401
+ name: r.name,
1402
+ full_name: r.fullName,
1403
+ private: r.private,
1404
+ owner: { login: r.fullName.split("/")[0] ?? "" }
1405
+ }))
1406
+ };
1534
1407
  }
1535
- /**
1536
- * Get accessible GitHub repositories
1537
- */
1538
- async getGitHubRepos(refresh = false) {
1539
- return this.request(
1540
- `/github/repos${refresh ? "?refresh=true" : ""}`
1541
- );
1408
+ async getGitHubAppName() {
1409
+ if (process.env.MCP_GITHUB_APP_NAME) return process.env.MCP_GITHUB_APP_NAME;
1410
+ return this.baseUrl.includes(".dev.") ? "mcp-use-dev" : "mcp-use";
1542
1411
  }
1543
1412
  };
1544
1413
 
1545
1414
  // src/commands/auth.ts
1546
- var LOGIN_TIMEOUT = 3e5;
1547
- async function findAvailablePort(startPort = 8765) {
1548
- for (let port = startPort; port < startPort + 100; port++) {
1549
- try {
1550
- await new Promise((resolve2, reject) => {
1551
- const server = (0, import_node_http.createServer)();
1552
- server.once("error", reject);
1553
- server.once("listening", () => {
1554
- server.close();
1555
- resolve2();
1556
- });
1557
- server.listen(port);
1558
- });
1559
- return port;
1560
- } catch {
1561
- continue;
1562
- }
1415
+ var DEVICE_CLIENT_ID = "mcp-use-cli";
1416
+ var DEVICE_POLL_TIMEOUT = 18e5;
1417
+ async function requestDeviceCode(authBaseUrl) {
1418
+ const url = `${authBaseUrl}/api/auth/device/code`;
1419
+ const response = await fetch(url, {
1420
+ method: "POST",
1421
+ headers: { "Content-Type": "application/json" },
1422
+ body: JSON.stringify({
1423
+ client_id: DEVICE_CLIENT_ID,
1424
+ scope: "openid profile email"
1425
+ })
1426
+ });
1427
+ if (!response.ok) {
1428
+ const error = await response.text();
1429
+ throw new Error(
1430
+ `Failed to request device code: ${response.status} ${error}`
1431
+ );
1563
1432
  }
1564
- throw new Error("No available ports found");
1433
+ return response.json();
1565
1434
  }
1566
- async function startCallbackServer(port, expectedState) {
1567
- return new Promise((resolve2, reject) => {
1568
- let tokenResolver = null;
1569
- const tokenPromise = new Promise((res) => {
1570
- tokenResolver = res;
1435
+ async function pollForDeviceToken(authBaseUrl, deviceCode, intervalSeconds) {
1436
+ let pollingInterval = intervalSeconds;
1437
+ const deadline = Date.now() + DEVICE_POLL_TIMEOUT;
1438
+ while (Date.now() < deadline) {
1439
+ const delayMs = pollingInterval * 1e3;
1440
+ await new Promise((r) => setTimeout(r, delayMs));
1441
+ const url = `${authBaseUrl}/api/auth/device/token`;
1442
+ const response = await fetch(url, {
1443
+ method: "POST",
1444
+ headers: { "Content-Type": "application/json" },
1445
+ body: JSON.stringify({
1446
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
1447
+ device_code: deviceCode,
1448
+ client_id: DEVICE_CLIENT_ID
1449
+ })
1571
1450
  });
1572
- const server = (0, import_node_http.createServer)(
1573
- {
1574
- maxHeaderSize: 65536
1575
- // 64KB - handle very long JWT tokens in URL (increased from default 8192)
1576
- },
1577
- (req, res) => {
1578
- if (req.url?.startsWith("/callback")) {
1579
- const url = new URL(req.url, `http://localhost:${port}`);
1580
- const token = url.searchParams.get("token");
1581
- const state = url.searchParams.get("state");
1582
- if (state !== expectedState) {
1583
- res.writeHead(400, { "Content-Type": "text/html" });
1584
- res.end(`
1585
- <!DOCTYPE html>
1586
- <html>
1587
- <head>
1588
- <title>Security Error</title>
1589
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
1590
- <style>
1591
- body {
1592
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1593
- display: flex;
1594
- justify-content: center;
1595
- align-items: center;
1596
- min-height: 100vh;
1597
- background: #000;
1598
- padding: 1rem;
1599
- margin: 0;
1600
- }
1601
- .container {
1602
- max-width: 28rem;
1603
- padding: 3rem;
1604
- text-align: center;
1605
- background: rgba(255, 255, 255, 0.1);
1606
- backdrop-filter: blur(40px);
1607
- border: 1px solid rgba(255, 255, 255, 0.2);
1608
- border-radius: 1.5rem;
1609
- }
1610
- h1 { color: #fff; font-size: 2rem; margin-bottom: 1rem; }
1611
- p { color: rgba(255, 255, 255, 0.8); font-size: 1rem; }
1612
- </style>
1613
- </head>
1614
- <body>
1615
- <div class="container">
1616
- <h1>Security Error</h1>
1617
- <p>Invalid state parameter. Please try logging in again.</p>
1618
- </div>
1619
- </body>
1620
- </html>
1621
- `);
1622
- return;
1623
- }
1624
- if (token && tokenResolver) {
1625
- res.writeHead(200, { "Content-Type": "text/html" });
1626
- res.end(`
1627
- <!DOCTYPE html>
1628
- <html>
1629
- <head>
1630
- <title>Login Successful</title>
1631
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
1632
- <style>
1633
- * {
1634
- margin: 0;
1635
- padding: 0;
1636
- box-sizing: border-box;
1637
- }
1638
- body {
1639
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
1640
- display: flex;
1641
- justify-content: center;
1642
- align-items: center;
1643
- min-height: 100vh;
1644
- background: #000;
1645
- padding: 1rem;
1646
- }
1647
- .container {
1648
- width: 100%;
1649
- max-width: 28rem;
1650
- padding: 3rem;
1651
- text-align: center;
1652
- -webkit-backdrop-filter: blur(40px);
1653
- border: 1px solid rgba(255, 255, 255, 0.2);
1654
- border-radius: 1.5rem;
1655
- box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
1656
- }
1657
- .icon-container {
1658
- display: inline-flex;
1659
- align-items: center;
1660
- justify-content: center;
1661
- width: 6rem;
1662
- height: 6rem;
1663
- margin-bottom: 2rem;
1664
- background: rgba(255, 255, 255, 0.1);
1665
- backdrop-filter: blur(10px);
1666
- -webkit-backdrop-filter: blur(10px);
1667
- border-radius: 50%;
1668
- }
1669
- .checkmark {
1670
- font-size: 4rem;
1671
- color: #fff;
1672
- line-height: 1;
1673
- animation: scaleIn 0.5s ease-out;
1674
- }
1675
- @keyframes scaleIn {
1676
- from {
1677
- transform: scale(0);
1678
- opacity: 0;
1679
- }
1680
- to {
1681
- transform: scale(1);
1682
- opacity: 1;
1683
- }
1684
- }
1685
- h1 {
1686
- color: #fff;
1687
- margin: 0 0 1rem 0;
1688
- font-size: 2.5rem;
1689
- font-weight: 700;
1690
- letter-spacing: -0.025em;
1691
- }
1692
- p {
1693
- color: rgba(255, 255, 255, 0.8);
1694
- margin: 0 0 2rem 0;
1695
- font-size: 1.125rem;
1696
- line-height: 1.5;
1697
- }
1698
- .spinner {
1699
- display: inline-block;
1700
- width: 2rem;
1701
- height: 2rem;
1702
- border: 3px solid rgba(255, 255, 255, 0.3);
1703
- border-top-color: #fff;
1704
- border-radius: 50%;
1705
- animation: spin 0.8s linear infinite;
1706
- }
1707
- @keyframes spin {
1708
- to { transform: rotate(360deg); }
1709
- }
1710
- .footer {
1711
- margin-top: 2rem;
1712
- color: rgba(255, 255, 255, 0.6);
1713
- font-size: 0.875rem;
1714
- }
1715
- </style>
1716
- </head>
1717
- <body>
1718
- <div class="container">
1719
- <h1>Authentication Successful!</h1>
1720
- <p>You can now close this window and return to the CLI.</p>
1721
- </div>
1722
- </body>
1723
- </html>
1724
- `);
1725
- tokenResolver(token);
1726
- } else {
1727
- res.writeHead(400, { "Content-Type": "text/html" });
1728
- res.end(`
1729
- <!DOCTYPE html>
1730
- <html>
1731
- <head>
1732
- <title>Login Failed</title>
1733
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
1734
- <style>
1735
- * {
1736
- margin: 0;
1737
- padding: 0;
1738
- box-sizing: border-box;
1739
- }
1740
- body {
1741
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
1742
- display: flex;
1743
- justify-content: center;
1744
- align-items: center;
1745
- min-height: 100vh;
1746
- background: #000;
1747
- padding: 1rem;
1748
- }
1749
- .container {
1750
- width: 100%;
1751
- max-width: 28rem;
1752
- padding: 3rem;
1753
- text-align: center;
1754
- background: rgba(255, 255, 255, 0.1);
1755
- backdrop-filter: blur(40px);
1756
- -webkit-backdrop-filter: blur(40px);
1757
- border: 1px solid rgba(255, 255, 255, 0.2);
1758
- border-radius: 1.5rem;
1759
- box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
1760
- }
1761
- .icon-container {
1762
- display: inline-flex;
1763
- align-items: center;
1764
- justify-content: center;
1765
- width: 6rem;
1766
- height: 6rem;
1767
- margin-bottom: 2rem;
1768
- background: rgba(255, 255, 255, 0.1);
1769
- backdrop-filter: blur(10px);
1770
- -webkit-backdrop-filter: blur(10px);
1771
- border-radius: 50%;
1772
- }
1773
- .cross {
1774
- font-size: 4rem;
1775
- color: #fff;
1776
- line-height: 1;
1777
- }
1778
- h1 {
1779
- color: #fff;
1780
- margin: 0 0 1rem 0;
1781
- font-size: 2.5rem;
1782
- font-weight: 700;
1783
- letter-spacing: -0.025em;
1784
- }
1785
- p {
1786
- color: rgba(255, 255, 255, 0.8);
1787
- margin: 0;
1788
- font-size: 1.125rem;
1789
- line-height: 1.5;
1790
- }
1791
- </style>
1792
- </head>
1793
- <body>
1794
- <div class="container">
1795
- <div class="icon-container">
1796
- <div class="cross">\u2717</div>
1797
- </div>
1798
- <h1>Login Failed</h1>
1799
- <p>No token received. Please try again.</p>
1800
- </div>
1801
- </body>
1802
- </html>
1803
- `);
1804
- }
1805
- }
1451
+ const data = await response.json();
1452
+ if (data.access_token) {
1453
+ return data.access_token;
1454
+ }
1455
+ if (data.error) {
1456
+ switch (data.error) {
1457
+ case "authorization_pending":
1458
+ break;
1459
+ case "slow_down":
1460
+ pollingInterval += 5;
1461
+ break;
1462
+ case "access_denied":
1463
+ throw new Error("Authorization was denied by the user.");
1464
+ case "expired_token":
1465
+ throw new Error("The device code has expired. Please try again.");
1466
+ default:
1467
+ throw new Error(
1468
+ data.error_description || `Device auth error: ${data.error}`
1469
+ );
1806
1470
  }
1807
- );
1808
- server.listen(port, () => {
1809
- resolve2({ server, token: tokenPromise });
1810
- });
1811
- server.on("error", reject);
1812
- });
1471
+ }
1472
+ }
1473
+ throw new Error("Login timed out. Please try again.");
1813
1474
  }
1814
- async function promptOrgSelection(profiles, defaultProfileId) {
1815
- if (profiles.length === 0) return null;
1816
- if (profiles.length === 1) {
1817
- return profiles[0];
1475
+ async function promptOrgSelection(orgs, defaultOrgId) {
1476
+ if (orgs.length === 0) return null;
1477
+ if (orgs.length === 1) {
1478
+ return orgs[0];
1818
1479
  }
1819
1480
  console.log(source_default.cyan.bold("\n\u{1F3E2} Select an organization:\n"));
1820
- for (let i = 0; i < profiles.length; i++) {
1821
- const p = profiles[i];
1822
- const marker = p.id === defaultProfileId ? source_default.green(" (current)") : "";
1823
- const slug = p.slug ? source_default.gray(` (${p.slug})`) : "";
1824
- console.log(
1825
- ` ${source_default.white(`${i + 1}.`)} ${p.profile_name}${slug}${marker}`
1826
- );
1481
+ for (let i = 0; i < orgs.length; i++) {
1482
+ const o = orgs[i];
1483
+ const marker = o.id === defaultOrgId ? source_default.green(" (current)") : "";
1484
+ const slug = o.slug ? source_default.gray(` (${o.slug})`) : "";
1485
+ console.log(` ${source_default.white(`${i + 1}.`)} ${o.name}${slug}${marker}`);
1827
1486
  }
1828
1487
  const readline = await import("readline");
1829
1488
  const rl = readline.createInterface({
@@ -1831,7 +1490,7 @@ async function promptOrgSelection(profiles, defaultProfileId) {
1831
1490
  output: process.stdout
1832
1491
  });
1833
1492
  return new Promise((resolve2) => {
1834
- const defaultIdx = defaultProfileId ? profiles.findIndex((p) => p.id === defaultProfileId) : 0;
1493
+ const defaultIdx = defaultOrgId ? orgs.findIndex((o) => o.id === defaultOrgId) : 0;
1835
1494
  const defaultDisplay = defaultIdx >= 0 ? defaultIdx + 1 : 1;
1836
1495
  rl.question(
1837
1496
  source_default.gray(`
@@ -1840,11 +1499,11 @@ Enter number [${defaultDisplay}]: `),
1840
1499
  rl.close();
1841
1500
  const trimmed = answer.trim();
1842
1501
  const idx = trimmed === "" ? defaultIdx : parseInt(trimmed, 10) - 1;
1843
- if (idx >= 0 && idx < profiles.length) {
1844
- resolve2(profiles[idx]);
1502
+ if (idx >= 0 && idx < orgs.length) {
1503
+ resolve2(orgs[idx]);
1845
1504
  } else {
1846
1505
  console.log(source_default.yellow("Invalid selection, using default."));
1847
- resolve2(profiles[defaultIdx >= 0 ? defaultIdx : 0]);
1506
+ resolve2(orgs[defaultIdx >= 0 ? defaultIdx : 0]);
1848
1507
  }
1849
1508
  }
1850
1509
  );
@@ -1852,105 +1511,114 @@ Enter number [${defaultDisplay}]: `),
1852
1511
  }
1853
1512
  async function loginCommand(options) {
1854
1513
  try {
1514
+ const directKey = options?.apiKey || process.env.MCP_USE_API_KEY;
1515
+ if (directKey) {
1516
+ await writeConfig({ apiKey: directKey });
1517
+ if (!options?.silent) {
1518
+ console.log(source_default.green.bold("\u2713 API key saved."));
1519
+ try {
1520
+ const api2 = await McpUseAPI.create();
1521
+ const authInfo = await api2.testAuth();
1522
+ console.log(source_default.gray(` Authenticated as ${authInfo.email}`));
1523
+ } catch {
1524
+ console.log(
1525
+ source_default.gray(
1526
+ " (could not verify key \u2014 will be checked on next command)"
1527
+ )
1528
+ );
1529
+ }
1530
+ }
1531
+ return;
1532
+ }
1855
1533
  if (await isLoggedIn()) {
1856
1534
  if (!options?.silent) {
1857
1535
  console.log(
1858
1536
  source_default.yellow(
1859
- "\u26A0\uFE0F You are already logged in. Run 'npx mcp-use logout' first if you want to login with a different account."
1537
+ "You are already logged in. Run 'npx mcp-use logout' first if you want to login with a different account."
1860
1538
  )
1861
1539
  );
1862
1540
  }
1863
1541
  return;
1864
1542
  }
1865
- console.log(source_default.cyan.bold("\u{1F510} Logging in to Manufact cloud...\n"));
1866
- const state = import_node_crypto.default.randomBytes(32).toString("hex");
1867
- const port = await findAvailablePort();
1868
- const redirectUri = `http://localhost:${port}/callback`;
1869
- console.log(source_default.gray(`Starting local server on port ${port}...`));
1870
- const { server, token } = await startCallbackServer(port, state);
1871
- const webUrl = await getWebUrl();
1872
- const loginUrl = `${webUrl}/auth/cli?redirect_uri=${encodeURIComponent(redirectUri)}&state=${state}`;
1873
- console.log(source_default.gray(`Opening browser to ${webUrl}/auth/cli...
1874
- `));
1875
- console.log(
1876
- source_default.white(
1877
- "If the browser doesn't open automatically, please visit:\n" + source_default.cyan(loginUrl)
1878
- )
1879
- );
1880
- await open_default(loginUrl);
1881
- console.log(
1882
- source_default.gray("\nWaiting for authentication... (this may take a moment)")
1883
- );
1884
- const jwtToken = await Promise.race([
1885
- token,
1886
- new Promise(
1887
- (_, reject) => setTimeout(
1888
- () => reject(new Error("Login timeout - please try again")),
1889
- LOGIN_TIMEOUT
1890
- )
1891
- )
1892
- ]);
1893
- server.close();
1894
- console.log(
1895
- source_default.gray("Received authentication token, creating API key...")
1543
+ console.log(source_default.cyan.bold("Logging in to mcp-use cloud...\n"));
1544
+ const authBaseUrl = await getAuthBaseUrl();
1545
+ const deviceResp = await requestDeviceCode(authBaseUrl);
1546
+ const {
1547
+ device_code,
1548
+ user_code,
1549
+ verification_uri,
1550
+ verification_uri_complete,
1551
+ interval
1552
+ } = deviceResp;
1553
+ const displayCode = user_code.length === 8 ? `${user_code.slice(0, 4)}-${user_code.slice(4)}` : user_code;
1554
+ console.log(source_default.white(" Visit: ") + source_default.cyan(verification_uri));
1555
+ console.log(source_default.white(" Code: ") + source_default.bold.white(displayCode));
1556
+ console.log();
1557
+ const urlToOpen = verification_uri_complete || verification_uri;
1558
+ try {
1559
+ await open_default(urlToOpen);
1560
+ console.log(source_default.gray(" Browser opened. Waiting for approval..."));
1561
+ } catch {
1562
+ console.log(source_default.gray(" Open the URL above in your browser."));
1563
+ }
1564
+ const accessToken = await pollForDeviceToken(
1565
+ authBaseUrl,
1566
+ device_code,
1567
+ interval || 5
1896
1568
  );
1569
+ console.log(source_default.gray("\n Creating persistent API key..."));
1897
1570
  const api = await McpUseAPI.create();
1898
- const apiKeyResponse = await api.createApiKey(jwtToken, "CLI");
1899
- await writeConfig({
1900
- apiKey: apiKeyResponse.api_key
1901
- });
1571
+ const keyResp = await api.createApiKeyWithAccessToken(accessToken, "CLI");
1572
+ await writeConfig({ apiKey: keyResp.key });
1902
1573
  console.log(source_default.green.bold("\n\u2713 Successfully logged in!"));
1903
1574
  try {
1904
- const api2 = await McpUseAPI.create();
1905
- const authInfo = await api2.testAuth();
1906
- console.log(source_default.cyan.bold("\n\u{1F464} Current user:\n"));
1907
- console.log(source_default.white("Email: ") + source_default.cyan(authInfo.email));
1908
- console.log(source_default.white("User ID: ") + source_default.gray(authInfo.user_id));
1909
- const apiKey = await getApiKey();
1910
- if (apiKey) {
1911
- const masked = apiKey.substring(0, 6) + "...";
1912
- console.log(source_default.white("API Key: ") + source_default.gray(masked));
1913
- }
1914
- const profiles = authInfo.profiles ?? [];
1915
- if (profiles.length > 0) {
1916
- let selectedProfile = null;
1917
- if (profiles.length === 1) {
1918
- selectedProfile = profiles[0];
1575
+ const freshApi = await McpUseAPI.create();
1576
+ const authInfo = await freshApi.testAuth();
1577
+ console.log(source_default.cyan.bold("\nCurrent user:\n"));
1578
+ console.log(source_default.white(" Email: ") + source_default.cyan(authInfo.email));
1579
+ console.log(source_default.white(" User ID: ") + source_default.gray(authInfo.user_id));
1580
+ const storedKey = await getApiKey();
1581
+ if (storedKey) {
1582
+ const masked = storedKey.substring(0, 8) + "...";
1583
+ console.log(source_default.white(" API Key: ") + source_default.gray(masked));
1584
+ }
1585
+ const orgs = authInfo.orgs ?? [];
1586
+ if (orgs.length > 0) {
1587
+ let selectedOrg = null;
1588
+ if (orgs.length === 1) {
1589
+ selectedOrg = orgs[0];
1919
1590
  } else {
1920
- selectedProfile = await promptOrgSelection(
1921
- profiles,
1922
- authInfo.default_profile_id
1923
- );
1591
+ selectedOrg = await promptOrgSelection(orgs, authInfo.default_org_id);
1924
1592
  }
1925
- if (selectedProfile) {
1593
+ if (selectedOrg) {
1926
1594
  const config = await readConfig();
1927
1595
  await writeConfig({
1928
1596
  ...config,
1929
- profileId: selectedProfile.id,
1930
- profileName: selectedProfile.profile_name,
1931
- profileSlug: selectedProfile.slug ?? void 0
1597
+ orgId: selectedOrg.id,
1598
+ orgName: selectedOrg.name,
1599
+ orgSlug: selectedOrg.slug ?? void 0
1932
1600
  });
1933
- const slug = selectedProfile.slug ? source_default.gray(` (${selectedProfile.slug})`) : "";
1601
+ const slug = selectedOrg.slug ? source_default.gray(` (${selectedOrg.slug})`) : "";
1934
1602
  console.log(
1935
- source_default.white("Org: ") + source_default.cyan(selectedProfile.profile_name) + slug
1603
+ source_default.white(" Org: ") + source_default.cyan(selectedOrg.name) + slug
1936
1604
  );
1937
1605
  }
1938
1606
  }
1939
- } catch (error) {
1607
+ } catch {
1940
1608
  console.log(
1941
1609
  source_default.gray(
1942
1610
  `
1943
- Your API key has been saved to ${source_default.white("~/.mcp-use/config.json")}`
1611
+ Your API key has been saved to ${source_default.white("~/.mcp-use/config.json")}`
1944
1612
  )
1945
1613
  );
1946
1614
  }
1947
1615
  console.log(
1948
1616
  source_default.gray(
1949
- "\nYou can now deploy your MCP servers with " + source_default.white("npx mcp-use deploy")
1617
+ "\n Deploy your MCP servers with " + source_default.white("npx mcp-use deploy")
1950
1618
  )
1951
1619
  );
1952
1620
  console.log(
1953
- source_default.gray("To logout later, run " + source_default.white("npx mcp-use logout"))
1621
+ source_default.gray(" To logout, run " + source_default.white("npx mcp-use logout"))
1954
1622
  );
1955
1623
  } catch (error) {
1956
1624
  throw new Error(
@@ -2002,31 +1670,41 @@ async function whoamiCommand() {
2002
1670
  console.log(source_default.white("API Key: ") + source_default.gray(masked));
2003
1671
  }
2004
1672
  const config = await readConfig();
2005
- const profiles = authInfo.profiles ?? [];
2006
- if (profiles.length > 0) {
2007
- const activeProfile = profiles.find(
2008
- (p) => p.id === (config.profileId || authInfo.default_profile_id)
1673
+ const orgs = authInfo.orgs ?? [];
1674
+ if (orgs.length > 0) {
1675
+ const activeOrg = orgs.find(
1676
+ (o) => o.id === (config.orgId || authInfo.default_org_id)
2009
1677
  );
2010
- if (activeProfile) {
2011
- const slug = activeProfile.slug ? source_default.gray(` (${activeProfile.slug})`) : "";
1678
+ if (activeOrg) {
1679
+ const slug = activeOrg.slug ? source_default.gray(` (${activeOrg.slug})`) : "";
2012
1680
  console.log(
2013
- source_default.white("Org: ") + source_default.cyan(activeProfile.profile_name) + slug
1681
+ source_default.white("Org: ") + source_default.cyan(activeOrg.name) + slug
2014
1682
  );
2015
1683
  }
2016
- if (profiles.length > 1) {
1684
+ if (orgs.length > 1) {
2017
1685
  console.log(
2018
1686
  source_default.gray(
2019
1687
  `
2020
- ${profiles.length} organizations available. Use ` + source_default.white("npx mcp-use org list") + " to see all."
1688
+ ${orgs.length} organizations available. Use ` + source_default.white("npx mcp-use org list") + " to see all."
2021
1689
  )
2022
1690
  );
2023
1691
  }
2024
1692
  }
2025
1693
  } catch (error) {
2026
- console.error(
2027
- source_default.red.bold("\n\u2717 Failed to get user info:"),
2028
- source_default.red(error instanceof Error ? error.message : "Unknown error")
2029
- );
1694
+ if (error?.status === 401) {
1695
+ console.error(
1696
+ source_default.red("\nYour session has expired or your API key is invalid.")
1697
+ );
1698
+ console.log(
1699
+ source_default.gray(`Run ${source_default.white("mcp-use login")} to re-authenticate.
1700
+ `)
1701
+ );
1702
+ } else {
1703
+ console.error(
1704
+ source_default.red.bold("\n\u2717 Failed to get user info:"),
1705
+ source_default.red(error instanceof Error ? error.message : "Unknown error")
1706
+ );
1707
+ }
2030
1708
  process.exit(1);
2031
1709
  }
2032
1710
  }
@@ -3402,25 +3080,20 @@ async function prompt(question, defaultValue = "n") {
3402
3080
  });
3403
3081
  }
3404
3082
  function getMcpServerUrl(deployment) {
3405
- if (deployment.customDomain) {
3406
- return `https://${deployment.customDomain}/mcp`;
3407
- } else if (deployment.serverSlug) {
3408
- return buildGatewayUrl(deployment.serverSlug);
3409
- } else if (deployment.serverId) {
3083
+ if (deployment.mcpUrl) {
3084
+ return deployment.mcpUrl;
3085
+ }
3086
+ if (deployment.serverId) {
3410
3087
  return buildGatewayUrl(deployment.serverId);
3411
- } else {
3412
- return `https://${deployment.domain}/mcp`;
3413
3088
  }
3089
+ return "";
3414
3090
  }
3415
- async function displayDeploymentProgress(api, deployment, progressOptions) {
3091
+ async function displayDeploymentProgress(api, deploymentId, progressOptions) {
3416
3092
  const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
3417
3093
  let frameIndex = 0;
3418
3094
  let spinnerInterval = null;
3419
- let lastStep = "";
3420
3095
  const startSpinner = (message) => {
3421
- if (spinnerInterval) {
3422
- clearInterval(spinnerInterval);
3423
- }
3096
+ if (spinnerInterval) clearInterval(spinnerInterval);
3424
3097
  process.stdout.write("\r\x1B[K");
3425
3098
  spinnerInterval = setInterval(() => {
3426
3099
  const frame = frames[frameIndex];
@@ -3439,82 +3112,64 @@ async function displayDeploymentProgress(api, deployment, progressOptions) {
3439
3112
  };
3440
3113
  console.log();
3441
3114
  startSpinner("Deploying...");
3442
- try {
3443
- for await (const log of api.streamDeploymentLogs(deployment.id)) {
3444
- try {
3445
- const logData = JSON.parse(log);
3446
- if (logData.step && logData.step !== lastStep) {
3447
- lastStep = logData.step;
3448
- const stepMessages = {
3449
- clone: "Preparing source code...",
3450
- analyze: "Analyzing project...",
3451
- build: "Building container image...",
3452
- deploy: "Deploying to cloud..."
3453
- };
3454
- const message = stepMessages[logData.step] || "Deploying...";
3455
- startSpinner(message);
3456
- }
3457
- if (logData.line) {
3458
- stopSpinner();
3459
- const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
3460
- const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
3461
- console.log(stepPrefix + levelColor(logData.line));
3462
- }
3463
- } catch {
3464
- }
3465
- }
3466
- } catch (error) {
3467
- stopSpinner();
3468
- }
3469
3115
  let checkCount = 0;
3470
- const maxChecks = 60;
3471
- let delay = 3e3;
3116
+ const maxChecks = 120;
3117
+ let delay = 2e3;
3472
3118
  const maxDelay = 1e4;
3473
- let lastDisplayedLogLength = 0;
3119
+ let buildLogOffset = 0;
3120
+ const sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
3474
3121
  while (checkCount < maxChecks) {
3475
- const currentDelay = delay;
3476
- await new Promise((resolve2) => setTimeout(resolve2, currentDelay));
3477
- const finalDeployment = await api.getDeployment(deployment.id);
3478
- if (finalDeployment.buildLogs && finalDeployment.buildLogs.length > lastDisplayedLogLength) {
3479
- const newLogs = finalDeployment.buildLogs.substring(
3480
- lastDisplayedLogLength
3122
+ await sleep(delay);
3123
+ checkCount++;
3124
+ try {
3125
+ const buildLogsResp = await api.getDeploymentBuildLogs(
3126
+ deploymentId,
3127
+ buildLogOffset
3481
3128
  );
3482
- const logLines = newLogs.split("\n").filter((l) => l.trim());
3483
- for (const line of logLines) {
3484
- try {
3485
- const logData = JSON.parse(line);
3486
- if (logData.line) {
3129
+ if (buildLogsResp.logs.length > 0) {
3130
+ const logLines = buildLogsResp.logs.split("\n").filter((l) => l.trim());
3131
+ for (const line of logLines) {
3132
+ try {
3133
+ const logData = JSON.parse(line);
3134
+ if (logData.line) {
3135
+ stopSpinner();
3136
+ const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
3137
+ const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
3138
+ console.log(stepPrefix + levelColor(logData.line));
3139
+ }
3140
+ } catch {
3487
3141
  stopSpinner();
3488
- const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
3489
- const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
3490
- console.log(stepPrefix + levelColor(logData.line));
3142
+ console.log(source_default.gray(line));
3491
3143
  }
3492
- } catch {
3493
3144
  }
3145
+ buildLogOffset = buildLogsResp.offset;
3494
3146
  }
3495
- lastDisplayedLogLength = finalDeployment.buildLogs.length;
3147
+ } catch {
3496
3148
  }
3497
- if (finalDeployment.status === "running") {
3498
- const mcpServerUrl = getMcpServerUrl(finalDeployment);
3149
+ const deployment = await api.getDeployment(deploymentId);
3150
+ if (deployment.status === "running") {
3151
+ stopSpinner();
3152
+ const mcpServerUrl = getMcpServerUrl(deployment);
3499
3153
  let dashboardUrl = null;
3500
3154
  const webUrl = (await getWebUrl()).replace(/\/$/, "");
3501
3155
  const config = await readConfig();
3502
- const orgSlug = config.profileSlug;
3503
- const serverRef = finalDeployment.serverSlug || finalDeployment.serverId;
3504
- if (serverRef) {
3156
+ const orgSlug = config.orgSlug;
3157
+ if (deployment.serverId) {
3505
3158
  if (orgSlug) {
3506
- dashboardUrl = `${webUrl}/cloud/${orgSlug}/servers/${serverRef}`;
3159
+ dashboardUrl = `${webUrl}/cloud/${orgSlug}/servers/${deployment.serverId}`;
3507
3160
  } else {
3508
- dashboardUrl = `${webUrl}/cloud/servers/${serverRef}`;
3161
+ dashboardUrl = `${webUrl}/cloud/servers/${deployment.serverId}`;
3509
3162
  }
3510
3163
  }
3511
3164
  const inspectorUrl = `https://inspector.manufact.com/inspector?autoConnect=${encodeURIComponent(
3512
3165
  mcpServerUrl
3513
3166
  )}`;
3514
3167
  console.log(source_default.green.bold("\u2713 Deployment successful!\n"));
3515
- console.log(source_default.white("\u{1F310} MCP Server URL:"));
3516
- console.log(source_default.cyan.bold(` ${mcpServerUrl}
3168
+ if (mcpServerUrl) {
3169
+ console.log(source_default.white("\u{1F310} MCP Server URL:"));
3170
+ console.log(source_default.cyan.bold(` ${mcpServerUrl}
3517
3171
  `));
3172
+ }
3518
3173
  if (dashboardUrl) {
3519
3174
  console.log(source_default.white("\u{1F4CA} Dashboard:"));
3520
3175
  console.log(source_default.cyan.bold(` ${dashboardUrl}
@@ -3523,16 +3178,14 @@ async function displayDeploymentProgress(api, deployment, progressOptions) {
3523
3178
  console.log(source_default.white("\u{1F50D} Inspector URL:"));
3524
3179
  console.log(source_default.cyan.bold(` ${inspectorUrl}
3525
3180
  `));
3526
- console.log(
3527
- source_default.gray("Deployment ID: ") + source_default.white(finalDeployment.id)
3528
- );
3181
+ console.log(source_default.gray("Deployment ID: ") + source_default.white(deployment.id));
3529
3182
  return;
3530
- } else if (finalDeployment.status === "failed") {
3183
+ } else if (deployment.status === "failed") {
3531
3184
  stopSpinner();
3532
3185
  console.log(source_default.red.bold("\u2717 Deployment failed\n"));
3533
- if (finalDeployment.error) {
3534
- console.log(source_default.red("Error: ") + finalDeployment.error);
3535
- if (finalDeployment.error.includes("No GitHub installations found")) {
3186
+ if (deployment.error) {
3187
+ console.log(source_default.red("Error: ") + deployment.error);
3188
+ if (deployment.error.includes("No GitHub installations found")) {
3536
3189
  console.log();
3537
3190
  const retry = await promptGitHubInstallation(
3538
3191
  api,
@@ -3540,79 +3193,31 @@ async function displayDeploymentProgress(api, deployment, progressOptions) {
3540
3193
  void 0,
3541
3194
  { yes: progressOptions?.yes }
3542
3195
  );
3543
- if (retry) {
3196
+ if (retry && deployment.serverId) {
3544
3197
  console.log(source_default.cyan("\n\u{1F504} Retrying deployment...\n"));
3545
- const newDeployment = await api.redeployDeployment(deployment.id);
3546
- await displayDeploymentProgress(
3547
- api,
3548
- newDeployment,
3549
- progressOptions
3550
- );
3551
- return;
3552
- }
3553
- } else if (finalDeployment.error.includes("Authenticated git clone failed")) {
3554
- let repoName;
3555
- const repoMatch = finalDeployment.error.match(
3556
- /github\.com\/([^/]+\/[^/\s]+)/
3557
- );
3558
- if (repoMatch) {
3559
- repoName = repoMatch[1].replace(/\.git$/, "");
3560
- } else if (finalDeployment.source.type === "github") {
3561
- repoName = finalDeployment.source.repo;
3562
- }
3563
- console.log();
3564
- const retry = await promptGitHubInstallation(
3565
- api,
3566
- "no_access",
3567
- repoName,
3568
- { yes: progressOptions?.yes }
3569
- );
3570
- if (retry) {
3571
- console.log(source_default.cyan("\n\u{1F504} Retrying deployment...\n"));
3572
- const newDeployment = await api.redeployDeployment(deployment.id);
3573
- await displayDeploymentProgress(
3574
- api,
3575
- newDeployment,
3576
- progressOptions
3577
- );
3198
+ const newDep = await api.createDeployment({
3199
+ serverId: deployment.serverId,
3200
+ trigger: "redeploy"
3201
+ });
3202
+ await displayDeploymentProgress(api, newDep.id, progressOptions);
3578
3203
  return;
3579
3204
  }
3580
3205
  }
3581
3206
  }
3582
- if (finalDeployment.buildLogs) {
3583
- console.log(source_default.gray("\nBuild logs:"));
3584
- try {
3585
- const logs = finalDeployment.buildLogs.split("\n").filter((l) => l.trim());
3586
- for (const log of logs) {
3587
- try {
3588
- const logData = JSON.parse(log);
3589
- if (logData.line) {
3590
- console.log(source_default.gray(` ${logData.line}`));
3591
- }
3592
- } catch {
3593
- console.log(source_default.gray(` ${log}`));
3594
- }
3595
- }
3596
- } catch {
3597
- console.log(source_default.gray(finalDeployment.buildLogs));
3598
- }
3599
- }
3600
3207
  process.exit(1);
3601
- } else if (finalDeployment.status === "building") {
3208
+ } else if (deployment.status === "building" || deployment.status === "pending") {
3602
3209
  startSpinner("Building and deploying...");
3603
- checkCount++;
3604
3210
  delay = Math.min(delay * 1.2, maxDelay);
3605
3211
  } else {
3606
- console.log(
3607
- source_default.yellow("\u26A0\uFE0F Deployment status: ") + finalDeployment.status
3608
- );
3212
+ stopSpinner();
3213
+ console.log(source_default.yellow("\u26A0\uFE0F Deployment status: ") + deployment.status);
3609
3214
  return;
3610
3215
  }
3611
3216
  }
3612
3217
  stopSpinner();
3613
3218
  console.log(source_default.yellow("\u26A0\uFE0F Deployment is taking longer than expected."));
3614
3219
  console.log(
3615
- source_default.gray("Check status with: ") + source_default.white(`mcp-use status ${deployment.id}`)
3220
+ source_default.gray("Check status with: ") + source_default.white(`mcp-use deployments get ${deploymentId}`)
3616
3221
  );
3617
3222
  }
3618
3223
  async function checkRepoAccess(api, owner, repo) {
@@ -3698,7 +3303,7 @@ async function promptGitHubInstallation(api, reason, repoName, opts) {
3698
3303
  return false;
3699
3304
  }
3700
3305
  try {
3701
- const appName = process.env.MCP_GITHUB_APP_NAME || "mcp-use";
3306
+ const appName = await api.getGitHubAppName();
3702
3307
  const installUrl = reason === "not_connected" ? `https://github.com/apps/${appName}/installations/new` : `https://github.com/settings/installations`;
3703
3308
  console.log(
3704
3309
  source_default.cyan(
@@ -3978,14 +3583,14 @@ async function deployCommand(options) {
3978
3583
  if (options.org) {
3979
3584
  try {
3980
3585
  const authInfo = await api.testAuth();
3981
- const match = (authInfo.profiles ?? []).find(
3982
- (p) => p.slug === options.org || p.id === options.org || p.profile_name.toLowerCase() === options.org.toLowerCase()
3586
+ const match = (authInfo.orgs ?? []).find(
3587
+ (o) => o.slug === options.org || o.id === options.org || o.name.toLowerCase() === options.org.toLowerCase()
3983
3588
  );
3984
3589
  if (match) {
3985
- api.setProfileId(match.id);
3590
+ api.setOrgId(match.id);
3986
3591
  const slug = match.slug ? source_default.gray(` (${match.slug})`) : "";
3987
3592
  console.log(
3988
- source_default.gray("Organization: ") + source_default.cyan(match.profile_name) + slug
3593
+ source_default.gray("Organization: ") + source_default.cyan(match.name) + slug
3989
3594
  );
3990
3595
  } else {
3991
3596
  console.error(
@@ -4004,6 +3609,7 @@ async function deployCommand(options) {
4004
3609
  }
4005
3610
  }
4006
3611
  let githubVerified = false;
3612
+ let installationDbId;
4007
3613
  try {
4008
3614
  console.log(source_default.gray(`[DEBUG] API URL: ${api.baseUrl}`));
4009
3615
  const connectionStatus = await api.getGitHubConnectionStatus();
@@ -4030,8 +3636,10 @@ async function deployCommand(options) {
4030
3636
  console.log(source_default.cyan(" https://manufact.com/cloud/settings\n"));
4031
3637
  process.exit(1);
4032
3638
  }
3639
+ installationDbId = retryStatus.installations?.[0]?.id;
4033
3640
  githubVerified = true;
4034
3641
  } else if (gitInfo.owner && gitInfo.repo) {
3642
+ installationDbId = connectionStatus.installations?.[0]?.id;
4035
3643
  console.log(source_default.gray("Checking repository access..."));
4036
3644
  const hasAccess = await checkRepoAccess(
4037
3645
  api,
@@ -4110,7 +3718,7 @@ async function deployCommand(options) {
4110
3718
  }
4111
3719
  const existingLink = !options.new ? await getProjectLink(cwd) : null;
4112
3720
  const serverId = existingLink?.serverId;
4113
- if (existingLink) {
3721
+ if (existingLink && serverId) {
4114
3722
  try {
4115
3723
  const existingDeployment = await api.getDeployment(
4116
3724
  existingLink.deploymentId
@@ -4122,29 +3730,19 @@ async function deployCommand(options) {
4122
3730
  source_default.cyan(` URL: ${getMcpServerUrl(existingDeployment)}
4123
3731
  `)
4124
3732
  );
4125
- const redeploymentConfig = {
4126
- buildCommand,
4127
- startCommand,
4128
- ...options.port !== void 0 ? { port: options.port } : {},
4129
- env: Object.keys(envVars).length > 0 ? envVars : void 0,
4130
- rootDir: options.rootDir || void 0
4131
- };
4132
- const deployment2 = await api.redeployDeployment(
4133
- existingLink.deploymentId,
4134
- redeploymentConfig
4135
- );
3733
+ const newDep = await api.createDeployment({
3734
+ serverId,
3735
+ branch: gitInfo.branch || "main",
3736
+ trigger: "redeploy"
3737
+ });
4136
3738
  await saveProjectLink(cwd, {
4137
3739
  ...existingLink,
4138
- linkedAt: (/* @__PURE__ */ new Date()).toISOString()
3740
+ linkedAt: (/* @__PURE__ */ new Date()).toISOString(),
3741
+ deploymentId: newDep.id
4139
3742
  });
4140
- await displayDeploymentProgress(api, deployment2, {
3743
+ await displayDeploymentProgress(api, newDep.id, {
4141
3744
  yes: options.yes
4142
3745
  });
4143
- if (options.open && deployment2.domain) {
4144
- console.log();
4145
- console.log(source_default.gray("Opening deployment in browser..."));
4146
- await open_default(`https://${deployment2.domain}`);
4147
- }
4148
3746
  return;
4149
3747
  } else {
4150
3748
  console.log(
@@ -4152,72 +3750,97 @@ async function deployCommand(options) {
4152
3750
  `\u26A0\uFE0F Linked deployment not found or failed, creating new one...`
4153
3751
  )
4154
3752
  );
4155
- if (serverId) {
4156
- console.log(
4157
- source_default.gray(` Will reuse existing server: ${serverId}`)
4158
- );
4159
- }
3753
+ console.log(source_default.gray(` Will reuse existing server: ${serverId}`));
4160
3754
  }
4161
3755
  } catch (error) {
4162
3756
  console.log(
4163
3757
  source_default.yellow(`\u26A0\uFE0F Linked deployment not found, creating new one...`)
4164
3758
  );
4165
- if (serverId) {
4166
- console.log(source_default.gray(` Will reuse existing server: ${serverId}`));
4167
- }
3759
+ console.log(source_default.gray(` Will reuse existing server: ${serverId}`));
4168
3760
  }
4169
3761
  }
4170
- const deploymentRequest = {
4171
- name: projectName,
4172
- source: {
4173
- type: "github",
4174
- repo: `${gitInfo.owner}/${gitInfo.repo}`,
4175
- branch: gitInfo.branch || "main",
4176
- rootDir: options.rootDir || void 0,
4177
- runtime,
4178
- port,
4179
- buildCommand,
4180
- startCommand,
4181
- env: Object.keys(envVars).length > 0 ? envVars : void 0
4182
- },
4183
- healthCheckPath: "/healthz",
4184
- serverId
4185
- };
4186
3762
  if (!options.org) {
4187
3763
  try {
4188
3764
  const config = await readConfig();
4189
- if (config.profileName) {
4190
- const slug = config.profileSlug ? source_default.gray(` (${config.profileSlug})`) : "";
3765
+ if (config.orgName) {
3766
+ const slug = config.orgSlug ? source_default.gray(` (${config.orgSlug})`) : "";
4191
3767
  console.log(
4192
- source_default.gray("Organization: ") + source_default.cyan(config.profileName) + slug
3768
+ source_default.gray("Organization: ") + source_default.cyan(config.orgName) + slug
4193
3769
  );
4194
3770
  }
4195
3771
  } catch {
4196
3772
  }
4197
3773
  }
4198
- console.log(source_default.gray("Creating deployment..."));
4199
- const deployment = await api.createDeployment(deploymentRequest);
4200
- console.log(
4201
- source_default.green("\u2713 Deployment created: ") + source_default.gray(deployment.id)
4202
- );
4203
- await saveProjectLink(cwd, {
4204
- deploymentId: deployment.id,
4205
- deploymentName: projectName,
4206
- deploymentUrl: deployment.domain,
4207
- linkedAt: (/* @__PURE__ */ new Date()).toISOString(),
4208
- serverId: deployment.serverId
4209
- });
4210
- console.log(
4211
- source_default.gray(` Linked to this project (stored in .mcp-use/project.json)`)
4212
- );
4213
- console.log(source_default.gray(` Future deploys will reuse the same URL
3774
+ let deploymentId;
3775
+ if (serverId) {
3776
+ console.log(source_default.gray("Creating deployment..."));
3777
+ const result = await api.createDeployment({
3778
+ serverId,
3779
+ branch: gitInfo.branch || "main",
3780
+ trigger: "manual"
3781
+ });
3782
+ deploymentId = result.id;
3783
+ } else {
3784
+ if (!installationDbId) {
3785
+ console.log(source_default.red("\u2717 Could not determine GitHub installation ID."));
3786
+ console.log(
3787
+ source_default.gray(
3788
+ "Please ensure your GitHub App is installed and try again."
3789
+ )
3790
+ );
3791
+ process.exit(1);
3792
+ }
3793
+ const config = await readConfig();
3794
+ const authInfo = await api.testAuth();
3795
+ const orgId = config.orgId || authInfo.default_org_id;
3796
+ if (!orgId) {
3797
+ console.log(
3798
+ source_default.red("\u2717 No organization set. Run `mcp-use org switch` first.")
3799
+ );
3800
+ process.exit(1);
3801
+ }
3802
+ console.log(source_default.gray("Creating server and deployment..."));
3803
+ const serverResult = await api.createServer({
3804
+ type: "github",
3805
+ organizationId: orgId,
3806
+ installationId: installationDbId,
3807
+ name: projectName,
3808
+ repoFullName: `${gitInfo.owner}/${gitInfo.repo}`,
3809
+ branch: gitInfo.branch || "main",
3810
+ rootDir: options.rootDir,
3811
+ port,
3812
+ buildCommand,
3813
+ startCommand,
3814
+ env: Object.keys(envVars).length > 0 ? envVars : void 0
3815
+ });
3816
+ deploymentId = serverResult.deploymentId ?? "";
3817
+ if (!deploymentId) {
3818
+ console.log(
3819
+ source_default.green("\u2713 Server created: ") + source_default.gray(serverResult.server.id)
3820
+ );
3821
+ console.log(
3822
+ source_default.yellow(
3823
+ "\u26A0\uFE0F No deployment was triggered. You may need to trigger one manually."
3824
+ )
3825
+ );
3826
+ return;
3827
+ }
3828
+ await saveProjectLink(cwd, {
3829
+ deploymentId,
3830
+ deploymentName: projectName,
3831
+ linkedAt: (/* @__PURE__ */ new Date()).toISOString(),
3832
+ serverId: serverResult.server.id
3833
+ });
3834
+ console.log(
3835
+ source_default.gray(` Linked to this project (stored in .mcp-use/project.json)`)
3836
+ );
3837
+ console.log(source_default.gray(` Future deploys will reuse the same URL
4214
3838
  `));
4215
- await displayDeploymentProgress(api, deployment, { yes: options.yes });
4216
- if (options.open && deployment.domain) {
4217
- console.log();
4218
- console.log(source_default.gray("Opening deployment in browser..."));
4219
- await open_default(`https://${deployment.domain}`);
4220
3839
  }
3840
+ console.log(
3841
+ source_default.green("\u2713 Deployment created: ") + source_default.gray(deploymentId)
3842
+ );
3843
+ await displayDeploymentProgress(api, deploymentId, { yes: options.yes });
4221
3844
  } catch (error) {
4222
3845
  console.error(
4223
3846
  source_default.red.bold("\n\u2717 Deployment failed:"),
@@ -4292,19 +3915,19 @@ async function listDeploymentsCommand() {
4292
3915
  );
4293
3916
  console.log(
4294
3917
  source_default.white.bold(
4295
- `${"ID".padEnd(40)} ${"NAME".padEnd(25)} ${"STATUS".padEnd(12)} ${"DOMAIN".padEnd(35)} ${"CREATED"}`
3918
+ `${"ID".padEnd(40)} ${"NAME".padEnd(25)} ${"STATUS".padEnd(12)} ${"MCP URL".padEnd(45)} ${"CREATED"}`
4296
3919
  )
4297
3920
  );
4298
- console.log(source_default.gray("\u2500".repeat(130)));
3921
+ console.log(source_default.gray("\u2500".repeat(140)));
4299
3922
  for (const deployment of sortedDeployments) {
4300
3923
  const id = formatId(deployment.id).padEnd(40);
4301
3924
  const name = deployment.name.substring(0, 24).padEnd(25);
4302
3925
  const statusColor = getStatusColor(deployment.status);
4303
3926
  const status = statusColor(deployment.status.padEnd(12));
4304
- const domain = (deployment.domain || "-").substring(0, 34).padEnd(35);
3927
+ const mcpUrl = (deployment.mcpUrl || "-").substring(0, 44).padEnd(45);
4305
3928
  const created = formatRelativeTime(deployment.createdAt);
4306
3929
  console.log(
4307
- `${source_default.gray(id)} ${name} ${status} ${source_default.cyan(domain)} ${source_default.gray(created)}`
3930
+ `${source_default.gray(id)} ${name} ${status} ${source_default.cyan(mcpUrl)} ${source_default.gray(created)}`
4308
3931
  );
4309
3932
  }
4310
3933
  console.log();
@@ -4336,31 +3959,24 @@ async function getDeploymentCommand(deploymentId) {
4336
3959
  console.log(
4337
3960
  source_default.white("Status: ") + statusColor(deployment.status)
4338
3961
  );
4339
- if (deployment.domain) {
3962
+ if (deployment.mcpUrl) {
4340
3963
  console.log(
4341
- source_default.white("Domain: ") + source_default.cyan(`https://${deployment.domain}`)
3964
+ source_default.white("MCP URL: ") + source_default.cyan(deployment.mcpUrl)
4342
3965
  );
4343
3966
  }
4344
- if (deployment.customDomain) {
3967
+ if (deployment.gitBranch) {
4345
3968
  console.log(
4346
- source_default.white("Custom Domain: ") + source_default.cyan(`https://${deployment.customDomain}`)
3969
+ source_default.white("Branch: ") + source_default.gray(deployment.gitBranch)
4347
3970
  );
4348
3971
  }
4349
- console.log(
4350
- source_default.white("Source: ") + source_default.gray(deployment.source.type)
4351
- );
4352
- if (deployment.source.type === "github") {
4353
- console.log(
4354
- source_default.white("Repository: ") + source_default.gray(deployment.source.repo)
4355
- );
3972
+ if (deployment.gitCommitSha) {
4356
3973
  console.log(
4357
- source_default.white("Branch: ") + source_default.gray(deployment.source.branch || "main")
3974
+ source_default.white("Commit: ") + source_default.gray(deployment.gitCommitSha.substring(0, 7))
4358
3975
  );
4359
3976
  }
4360
- console.log(source_default.white("Port: ") + source_default.gray(deployment.port));
4361
- console.log(
4362
- source_default.white("Runtime: ") + source_default.gray(deployment.source.runtime || "node")
4363
- );
3977
+ if (deployment.port) {
3978
+ console.log(source_default.white("Port: ") + source_default.gray(deployment.port));
3979
+ }
4364
3980
  if (deployment.provider) {
4365
3981
  console.log(
4366
3982
  source_default.white("Provider: ") + source_default.gray(deployment.provider)
@@ -4372,13 +3988,6 @@ async function getDeploymentCommand(deploymentId) {
4372
3988
  console.log(
4373
3989
  source_default.white("Updated: ") + source_default.gray(formatRelativeTime(deployment.updatedAt))
4374
3990
  );
4375
- if (deployment.source.env && Object.keys(deployment.source.env).length > 0) {
4376
- console.log(source_default.white("\nEnvironment Variables:"));
4377
- for (const [key, value] of Object.entries(deployment.source.env)) {
4378
- const displayValue = key.toLowerCase().includes("key") || key.toLowerCase().includes("secret") || key.toLowerCase().includes("password") || key.toLowerCase().includes("token") ? "***" : value;
4379
- console.log(source_default.gray(` ${key}=`) + source_default.white(displayValue));
4380
- }
4381
- }
4382
3991
  if (deployment.status === "failed" && deployment.error) {
4383
3992
  console.log(source_default.red("\nError:"));
4384
3993
  console.log(source_default.red(` ${deployment.error}`));
@@ -4405,43 +4014,56 @@ async function restartDeploymentCommand(deploymentId, options) {
4405
4014
  }
4406
4015
  const api = await McpUseAPI.create();
4407
4016
  const deployment = await api.getDeployment(deploymentId);
4017
+ if (!deployment.serverId) {
4018
+ console.log(
4019
+ source_default.red("\u2717 Cannot restart: deployment has no linked server.")
4020
+ );
4021
+ process.exit(1);
4022
+ }
4408
4023
  console.log(
4409
4024
  source_default.cyan.bold(`
4410
4025
  \u{1F504} Restarting deployment: ${deployment.name}
4411
4026
  `)
4412
4027
  );
4413
- const redeployedDeployment = await api.redeployDeployment(deploymentId);
4414
- console.log(
4415
- source_default.green("\u2713 Restart initiated: ") + source_default.gray(redeployedDeployment.id)
4416
- );
4028
+ const newDep = await api.createDeployment({
4029
+ serverId: deployment.serverId,
4030
+ trigger: "redeploy"
4031
+ });
4032
+ console.log(source_default.green("\u2713 Restart initiated: ") + source_default.gray(newDep.id));
4417
4033
  if (options.follow) {
4418
- console.log(source_default.gray("\nFollowing deployment logs...\n"));
4419
- try {
4420
- for await (const log of api.streamDeploymentLogs(
4421
- redeployedDeployment.id
4422
- )) {
4423
- try {
4424
- const logData = JSON.parse(log);
4425
- if (logData.line) {
4426
- const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
4427
- const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
4428
- console.log(stepPrefix + levelColor(logData.line));
4034
+ console.log(source_default.gray("\nFollowing build logs...\n"));
4035
+ let offset = 0;
4036
+ let terminal = false;
4037
+ while (!terminal) {
4038
+ await new Promise((r) => setTimeout(r, 2e3));
4039
+ try {
4040
+ const resp = await api.getDeploymentBuildLogs(newDep.id, offset);
4041
+ if (resp.logs.length > 0) {
4042
+ const lines = resp.logs.split("\n").filter((l) => l.trim());
4043
+ for (const line of lines) {
4044
+ try {
4045
+ const logData = JSON.parse(line);
4046
+ if (logData.line) {
4047
+ const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
4048
+ const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
4049
+ console.log(stepPrefix + levelColor(logData.line));
4050
+ }
4051
+ } catch {
4052
+ console.log(source_default.gray(line));
4053
+ }
4429
4054
  }
4430
- } catch {
4431
- console.log(source_default.gray(log));
4055
+ offset = resp.offset;
4432
4056
  }
4057
+ if (resp.status === "running" || resp.status === "failed" || resp.status === "stopped") {
4058
+ terminal = true;
4059
+ }
4060
+ } catch {
4433
4061
  }
4434
- } catch (error) {
4435
- console.log(
4436
- source_default.gray(
4437
- "\nLog stream ended. Use " + source_default.white(`mcp-use deployments get ${deploymentId}`) + " to check status."
4438
- )
4439
- );
4440
4062
  }
4441
4063
  } else {
4442
4064
  console.log(
4443
4065
  source_default.gray(
4444
- "\nCheck status with: " + source_default.white(`mcp-use deployments get ${deploymentId}`)
4066
+ "\nCheck status with: " + source_default.white(`mcp-use deployments get ${newDep.id}`)
4445
4067
  )
4446
4068
  );
4447
4069
  }
@@ -4475,8 +4097,10 @@ async function deleteDeploymentCommand(deploymentId, options) {
4475
4097
  )
4476
4098
  );
4477
4099
  console.log(source_default.gray(` ID: ${deployment.id}`));
4478
- console.log(source_default.gray(` Domain: ${deployment.domain || "none"}
4100
+ if (deployment.mcpUrl) {
4101
+ console.log(source_default.gray(` URL: ${deployment.mcpUrl}
4479
4102
  `));
4103
+ }
4480
4104
  const confirmed = await prompt2(
4481
4105
  source_default.white("Are you sure you want to delete this deployment? (y/N): ")
4482
4106
  );
@@ -4512,30 +4136,41 @@ async function logsCommand(deploymentId, options) {
4512
4136
  }
4513
4137
  const api = await McpUseAPI.create();
4514
4138
  if (options.follow) {
4515
- console.log(source_default.gray("Streaming logs...\n"));
4516
- try {
4517
- for await (const log of api.streamDeploymentLogs(deploymentId)) {
4518
- try {
4519
- const logData = JSON.parse(log);
4520
- if (logData.line) {
4521
- const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
4522
- const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
4523
- console.log(stepPrefix + levelColor(logData.line));
4139
+ console.log(source_default.gray("Following build logs...\n"));
4140
+ let offset = 0;
4141
+ let terminal = false;
4142
+ while (!terminal) {
4143
+ await new Promise((r) => setTimeout(r, 2e3));
4144
+ try {
4145
+ const resp = await api.getDeploymentBuildLogs(deploymentId, offset);
4146
+ if (resp.logs.length > 0) {
4147
+ const lines = resp.logs.split("\n").filter((l) => l.trim());
4148
+ for (const line of lines) {
4149
+ try {
4150
+ const logData = JSON.parse(line);
4151
+ if (logData.line) {
4152
+ const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
4153
+ const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
4154
+ console.log(stepPrefix + levelColor(logData.line));
4155
+ }
4156
+ } catch {
4157
+ console.log(source_default.gray(line));
4158
+ }
4524
4159
  }
4525
- } catch {
4526
- console.log(source_default.gray(log));
4160
+ offset = resp.offset;
4161
+ }
4162
+ if (resp.status === "running" || resp.status === "failed" || resp.status === "stopped") {
4163
+ terminal = true;
4527
4164
  }
4165
+ } catch {
4528
4166
  }
4529
- } catch (error) {
4530
- console.log(source_default.gray("\nLog stream ended."));
4531
4167
  }
4532
- } else {
4533
- const logs = options.build ? await api.getDeploymentBuildLogs(deploymentId) : await api.getDeploymentLogs(deploymentId);
4168
+ } else if (options.build) {
4169
+ const resp = await api.getDeploymentBuildLogs(deploymentId);
4170
+ const logs = resp.logs;
4534
4171
  if (!logs || logs.trim() === "") {
4535
4172
  console.log(
4536
- source_default.yellow(
4537
- `No ${options.build ? "build " : ""}logs available for this deployment.`
4538
- )
4173
+ source_default.yellow("No build logs available for this deployment.")
4539
4174
  );
4540
4175
  return;
4541
4176
  }
@@ -4552,133 +4187,30 @@ async function logsCommand(deploymentId, options) {
4552
4187
  console.log(source_default.gray(line));
4553
4188
  }
4554
4189
  }
4555
- }
4556
- console.log();
4557
- } catch (error) {
4558
- console.error(
4559
- source_default.red.bold("\n\u2717 Failed to get logs:"),
4560
- source_default.red(error instanceof Error ? error.message : "Unknown error")
4561
- );
4562
- process.exit(1);
4563
- }
4564
- }
4565
- async function listEnvCommand(deploymentId) {
4566
- try {
4567
- if (!await isLoggedIn()) {
4568
- console.log(source_default.red("\u2717 You are not logged in."));
4569
- console.log(
4570
- source_default.gray(
4571
- "Run " + source_default.white("npx mcp-use login") + " to get started."
4572
- )
4573
- );
4574
- process.exit(1);
4575
- }
4576
- const api = await McpUseAPI.create();
4577
- const deployment = await api.getDeployment(deploymentId);
4578
- console.log(
4579
- source_default.cyan.bold(`
4580
- \u{1F510} Environment Variables: ${deployment.name}
4581
- `)
4582
- );
4583
- if (!deployment.source.env || Object.keys(deployment.source.env).length === 0) {
4584
- console.log(source_default.yellow("No environment variables set."));
4585
- console.log();
4586
- return;
4587
- }
4588
- for (const [key, value] of Object.entries(deployment.source.env)) {
4589
- const displayValue = key.toLowerCase().includes("key") || key.toLowerCase().includes("secret") || key.toLowerCase().includes("password") || key.toLowerCase().includes("token") ? "***" : value;
4590
- console.log(
4591
- source_default.white(key) + source_default.gray("=") + source_default.cyan(displayValue)
4592
- );
4593
- }
4594
- console.log();
4595
- } catch (error) {
4596
- console.error(
4597
- source_default.red.bold("\n\u2717 Failed to list environment variables:"),
4598
- source_default.red(error instanceof Error ? error.message : "Unknown error")
4599
- );
4600
- process.exit(1);
4601
- }
4602
- }
4603
- async function setEnvCommand(deploymentId, envPairs) {
4604
- try {
4605
- if (!await isLoggedIn()) {
4606
- console.log(source_default.red("\u2717 You are not logged in."));
4607
- console.log(
4608
- source_default.gray(
4609
- "Run " + source_default.white("npx mcp-use login") + " to get started."
4610
- )
4611
- );
4612
- process.exit(1);
4613
- }
4614
- const env2 = {};
4615
- for (const pair of envPairs) {
4616
- const [key, ...valueParts] = pair.split("=");
4617
- if (!key || valueParts.length === 0) {
4618
- console.log(source_default.red(`\u2717 Invalid format: ${pair}. Expected KEY=VALUE`));
4619
- process.exit(1);
4190
+ } else {
4191
+ const logs = await api.getDeploymentLogs(deploymentId);
4192
+ if (!logs || logs.trim() === "") {
4193
+ console.log(source_default.yellow("No logs available for this deployment."));
4194
+ return;
4195
+ }
4196
+ const logLines = logs.split("\n").filter((l) => l.trim());
4197
+ for (const line of logLines) {
4198
+ try {
4199
+ const logData = JSON.parse(line);
4200
+ if (logData.line) {
4201
+ const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
4202
+ const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
4203
+ console.log(stepPrefix + levelColor(logData.line));
4204
+ }
4205
+ } catch {
4206
+ console.log(source_default.gray(line));
4207
+ }
4620
4208
  }
4621
- env2[key.trim()] = valueParts.join("=").trim();
4622
- }
4623
- const api = await McpUseAPI.create();
4624
- const deployment = await api.getDeployment(deploymentId);
4625
- const currentEnv = deployment.source.env || {};
4626
- const mergedEnv = { ...currentEnv, ...env2 };
4627
- const updated = await api.updateDeployment(deploymentId, {
4628
- env: mergedEnv
4629
- });
4630
- console.log(
4631
- source_default.green.bold(`
4632
- \u2713 Environment variables updated: ${updated.name}
4633
- `)
4634
- );
4635
- for (const key of Object.keys(env2)) {
4636
- const displayValue = key.toLowerCase().includes("key") || key.toLowerCase().includes("secret") || key.toLowerCase().includes("password") || key.toLowerCase().includes("token") ? "***" : env2[key];
4637
- console.log(
4638
- source_default.white(key) + source_default.gray("=") + source_default.cyan(displayValue)
4639
- );
4640
- }
4641
- console.log();
4642
- } catch (error) {
4643
- console.error(
4644
- source_default.red.bold("\n\u2717 Failed to set environment variables:"),
4645
- source_default.red(error instanceof Error ? error.message : "Unknown error")
4646
- );
4647
- process.exit(1);
4648
- }
4649
- }
4650
- async function unsetEnvCommand(deploymentId, keys) {
4651
- try {
4652
- if (!await isLoggedIn()) {
4653
- console.log(source_default.red("\u2717 You are not logged in."));
4654
- console.log(
4655
- source_default.gray(
4656
- "Run " + source_default.white("npx mcp-use login") + " to get started."
4657
- )
4658
- );
4659
- process.exit(1);
4660
- }
4661
- const api = await McpUseAPI.create();
4662
- const deployment = await api.getDeployment(deploymentId);
4663
- const currentEnv = { ...deployment.source.env || {} };
4664
- for (const key of keys) {
4665
- delete currentEnv[key];
4666
- }
4667
- const updated = await api.updateDeployment(deploymentId, {
4668
- env: currentEnv
4669
- });
4670
- console.log(
4671
- source_default.green.bold(`
4672
- \u2713 Environment variables removed: ${updated.name}
4673
- `)
4674
- );
4675
- for (const key of keys) {
4676
- console.log(source_default.gray(` ${key}`));
4677
4209
  }
4678
4210
  console.log();
4679
4211
  } catch (error) {
4680
4212
  console.error(
4681
- source_default.red.bold("\n\u2717 Failed to unset environment variables:"),
4213
+ source_default.red.bold("\n\u2717 Failed to get logs:"),
4682
4214
  source_default.red(error instanceof Error ? error.message : "Unknown error")
4683
4215
  );
4684
4216
  process.exit(1);
@@ -4696,11 +4228,9 @@ async function stopDeploymentCommand(deploymentId) {
4696
4228
  process.exit(1);
4697
4229
  }
4698
4230
  const api = await McpUseAPI.create();
4699
- const updated = await api.updateDeployment(deploymentId, {
4700
- status: "stopped"
4701
- });
4231
+ await api.stopDeployment(deploymentId);
4702
4232
  console.log(source_default.green.bold(`
4703
- \u2713 Deployment stopped: ${updated.name}
4233
+ \u2713 Deployment stopped
4704
4234
  `));
4705
4235
  } catch (error) {
4706
4236
  console.error(
@@ -4721,13 +4251,11 @@ async function startDeploymentCommand(deploymentId) {
4721
4251
  );
4722
4252
  process.exit(1);
4723
4253
  }
4724
- const api = await McpUseAPI.create();
4725
- const updated = await api.updateDeployment(deploymentId, {
4726
- status: "running"
4727
- });
4728
- console.log(source_default.green.bold(`
4729
- \u2713 Deployment started: ${updated.name}
4730
- `));
4254
+ console.log(
4255
+ source_default.yellow(
4256
+ "\u26A0\uFE0F Start is not supported in this version. Use `mcp-use deployments restart` to redeploy."
4257
+ )
4258
+ );
4731
4259
  } catch (error) {
4732
4260
  console.error(
4733
4261
  source_default.red.bold("\n\u2717 Failed to start deployment:"),
@@ -4742,13 +4270,11 @@ function createDeploymentsCommand() {
4742
4270
  );
4743
4271
  deploymentsCommand.command("list").alias("ls").description("List all deployments").action(listDeploymentsCommand);
4744
4272
  deploymentsCommand.command("get").argument("<deployment-id>", "Deployment ID").description("Get deployment details").action(getDeploymentCommand);
4745
- deploymentsCommand.command("restart").argument("<deployment-id>", "Deployment ID").option("-f, --follow", "Follow deployment logs").description("Restart a deployment").action(restartDeploymentCommand);
4273
+ deploymentsCommand.command("restart").argument("<deployment-id>", "Deployment ID").option("-f, --follow", "Follow build logs").description(
4274
+ "Restart a deployment (triggers a new deployment on the same server)"
4275
+ ).action(restartDeploymentCommand);
4746
4276
  deploymentsCommand.command("delete").alias("rm").argument("<deployment-id>", "Deployment ID").option("-y, --yes", "Skip confirmation prompt").description("Delete a deployment").action(deleteDeploymentCommand);
4747
- deploymentsCommand.command("logs").argument("<deployment-id>", "Deployment ID").option("-b, --build", "Show build logs instead of runtime logs").option("-f, --follow", "Stream logs in real-time").description("View deployment logs").action(logsCommand);
4748
- const envCommand = deploymentsCommand.command("env").description("Manage environment variables");
4749
- envCommand.command("list").argument("<deployment-id>", "Deployment ID").description("List environment variables").action(listEnvCommand);
4750
- envCommand.command("set").argument("<deployment-id>", "Deployment ID").argument("<pairs...>", "Environment variables in KEY=VALUE format").description("Set environment variables").action(setEnvCommand);
4751
- envCommand.command("unset").argument("<deployment-id>", "Deployment ID").argument("<keys...>", "Environment variable keys to remove").description("Unset environment variables").action(unsetEnvCommand);
4277
+ deploymentsCommand.command("logs").argument("<deployment-id>", "Deployment ID").option("-b, --build", "Show build logs instead of runtime logs").option("-f, --follow", "Follow build logs in real-time").description("View deployment logs").action(logsCommand);
4752
4278
  deploymentsCommand.command("stop").argument("<deployment-id>", "Deployment ID").description("Stop a deployment").action(stopDeploymentCommand);
4753
4279
  deploymentsCommand.command("start").argument("<deployment-id>", "Deployment ID").description("Start a stopped deployment").action(startDeploymentCommand);
4754
4280
  return deploymentsCommand;
@@ -4771,22 +4297,22 @@ async function orgListCommand() {
4771
4297
  const api = await McpUseAPI.create();
4772
4298
  const authInfo = await api.testAuth();
4773
4299
  const config = await readConfig();
4774
- const profiles = authInfo.profiles ?? [];
4775
- const activeId = config.profileId || authInfo.default_profile_id;
4776
- if (profiles.length === 0) {
4300
+ const orgs = authInfo.orgs ?? [];
4301
+ const activeId = config.orgId || authInfo.default_org_id;
4302
+ if (orgs.length === 0) {
4777
4303
  console.log(source_default.yellow("No organizations found."));
4778
4304
  return;
4779
4305
  }
4780
4306
  console.log(source_default.cyan.bold("\u{1F3E2} Your organizations:\n"));
4781
- for (const p of profiles) {
4782
- const isActive = p.id === activeId;
4307
+ for (const o of orgs) {
4308
+ const isActive = o.id === activeId;
4783
4309
  const marker = isActive ? source_default.green(" \u2190 active") : "";
4784
- const slug = p.slug ? source_default.gray(` (${p.slug})`) : "";
4785
- const role = source_default.gray(` [${p.role}]`);
4786
- const name = isActive ? source_default.cyan.bold(p.profile_name) : source_default.white(p.profile_name);
4310
+ const slug = o.slug ? source_default.gray(` (${o.slug})`) : "";
4311
+ const role = source_default.gray(` [${o.role}]`);
4312
+ const name = isActive ? source_default.cyan.bold(o.name) : source_default.white(o.name);
4787
4313
  console.log(` ${name}${slug}${role}${marker}`);
4788
4314
  }
4789
- if (profiles.length > 1) {
4315
+ if (orgs.length > 1) {
4790
4316
  console.log(
4791
4317
  source_default.gray("\nSwitch with " + source_default.white("npx mcp-use org switch"))
4792
4318
  );
@@ -4805,40 +4331,40 @@ async function orgSwitchCommand() {
4805
4331
  const api = await McpUseAPI.create();
4806
4332
  const authInfo = await api.testAuth();
4807
4333
  const config = await readConfig();
4808
- const profiles = authInfo.profiles ?? [];
4809
- if (profiles.length === 0) {
4334
+ const orgs = authInfo.orgs ?? [];
4335
+ if (orgs.length === 0) {
4810
4336
  console.log(source_default.yellow("No organizations found."));
4811
4337
  return;
4812
4338
  }
4813
- if (profiles.length === 1) {
4814
- const p = profiles[0];
4815
- const slug2 = p.slug ? source_default.gray(` (${p.slug})`) : "";
4339
+ if (orgs.length === 1) {
4340
+ const o = orgs[0];
4341
+ const slug2 = o.slug ? source_default.gray(` (${o.slug})`) : "";
4816
4342
  console.log(
4817
4343
  source_default.yellow(
4818
- `You only have one organization: ${source_default.cyan(p.profile_name)}${slug2}`
4344
+ `You only have one organization: ${source_default.cyan(o.name)}${slug2}`
4819
4345
  )
4820
4346
  );
4821
4347
  return;
4822
4348
  }
4823
- const activeId = config.profileId || authInfo.default_profile_id;
4824
- const selected = await promptOrgSelection(profiles, activeId);
4349
+ const activeId = config.orgId || authInfo.default_org_id;
4350
+ const selected = await promptOrgSelection(orgs, activeId);
4825
4351
  if (!selected) {
4826
4352
  console.log(source_default.yellow("No organization selected."));
4827
4353
  return;
4828
4354
  }
4829
4355
  await writeConfig({
4830
4356
  ...config,
4831
- profileId: selected.id,
4832
- profileName: selected.profile_name,
4833
- profileSlug: selected.slug ?? void 0
4357
+ orgId: selected.id,
4358
+ orgName: selected.name,
4359
+ orgSlug: selected.slug ?? void 0
4834
4360
  });
4835
4361
  try {
4836
- await api.setDefaultProfile(selected.id);
4362
+ await api.setDefaultOrg(selected.id);
4837
4363
  } catch {
4838
4364
  }
4839
4365
  const slug = selected.slug ? source_default.gray(` (${selected.slug})`) : "";
4840
4366
  console.log(
4841
- source_default.green.bold("\n\u2713 Switched to ") + source_default.cyan.bold(selected.profile_name) + slug
4367
+ source_default.green.bold("\n\u2713 Switched to ") + source_default.cyan.bold(selected.name) + slug
4842
4368
  );
4843
4369
  } catch (error) {
4844
4370
  console.error(
@@ -4852,7 +4378,7 @@ async function orgCurrentCommand() {
4852
4378
  try {
4853
4379
  if (!await ensureLoggedIn()) return;
4854
4380
  const config = await readConfig();
4855
- if (!config.profileId) {
4381
+ if (!config.orgId) {
4856
4382
  console.log(
4857
4383
  source_default.yellow(
4858
4384
  "No organization selected. Run " + source_default.white("npx mcp-use org switch") + " to pick one."
@@ -4860,9 +4386,9 @@ async function orgCurrentCommand() {
4860
4386
  );
4861
4387
  return;
4862
4388
  }
4863
- const slug = config.profileSlug ? source_default.gray(` (${config.profileSlug})`) : "";
4389
+ const slug = config.orgSlug ? source_default.gray(` (${config.orgSlug})`) : "";
4864
4390
  console.log(
4865
- source_default.cyan.bold("\u{1F3E2} Active organization: ") + source_default.white(config.profileName || config.profileId) + slug
4391
+ source_default.cyan.bold("\u{1F3E2} Active organization: ") + source_default.white(config.orgName || config.orgId) + slug
4866
4392
  );
4867
4393
  } catch (error) {
4868
4394
  console.error(
@@ -5187,7 +4713,7 @@ async function isPortAvailable(port, host = "localhost") {
5187
4713
  return true;
5188
4714
  }
5189
4715
  }
5190
- async function findAvailablePort2(startPort, host = "localhost") {
4716
+ async function findAvailablePort(startPort, host = "localhost") {
5191
4717
  for (let port = startPort; port < startPort + 100; port++) {
5192
4718
  if (await isPortAvailable(port, host)) {
5193
4719
  return port;
@@ -5478,7 +5004,7 @@ if (container && Component) {
5478
5004
  `${widgetName}-metadata`
5479
5005
  );
5480
5006
  await fs10.mkdir(metadataTempDir, { recursive: true });
5481
- const { createServer: createServer2 } = await import("vite");
5007
+ const { createServer } = await import("vite");
5482
5008
  const nodeStubsPlugin = {
5483
5009
  name: "node-stubs",
5484
5010
  enforce: "pre",
@@ -5505,7 +5031,7 @@ export default PostHog;
5505
5031
  return null;
5506
5032
  }
5507
5033
  };
5508
- const metadataServer = await createServer2({
5034
+ const metadataServer = await createServer({
5509
5035
  root: metadataTempDir,
5510
5036
  cacheDir: import_node_path8.default.join(metadataTempDir, ".vite-cache"),
5511
5037
  plugins: [nodeStubsPlugin, tailwindcss(), react()],
@@ -6070,7 +5596,7 @@ program.command("dev").description("Run development server with auto-reload and
6070
5596
  displayPackageVersions(projectPath);
6071
5597
  if (!await isPortAvailable(port, host)) {
6072
5598
  console.log(source_default.yellow.bold(`\u26A0\uFE0F Port ${port} is already in use`));
6073
- const availablePort = await findAvailablePort2(port, host);
5599
+ const availablePort = await findAvailablePort(port, host);
6074
5600
  console.log(source_default.green.bold(`\u2713 Using port ${availablePort} instead`));
6075
5601
  port = availablePort;
6076
5602
  }
@@ -6905,9 +6431,12 @@ Looked for:
6905
6431
  process.exit(1);
6906
6432
  }
6907
6433
  });
6908
- program.command("login").description("Login to Manufact cloud").action(async () => {
6434
+ program.command("login").description("Login to mcp-use cloud").option(
6435
+ "--api-key <key>",
6436
+ "Login with an API key directly (non-interactive, for CI/CD)"
6437
+ ).action(async (opts) => {
6909
6438
  try {
6910
- await loginCommand();
6439
+ await loginCommand({ apiKey: opts.apiKey });
6911
6440
  process.exit(0);
6912
6441
  } catch (error) {
6913
6442
  console.error(