@mcp-use/cli 3.0.0-canary.3 → 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/commands/auth.d.ts +2 -8
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/deploy.d.ts +0 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deployments.d.ts +0 -3
- package/dist/commands/deployments.d.ts.map +1 -1
- package/dist/commands/org.d.ts.map +1 -1
- package/dist/index.cjs +425 -722
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +425 -722
- package/dist/index.js.map +1 -1
- package/dist/utils/api.d.ts +63 -147
- package/dist/utils/api.d.ts.map +1 -1
- package/dist/utils/config.d.ts +10 -4
- package/dist/utils/config.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1167,14 +1167,21 @@ async function ensureConfigDir() {
|
|
|
1167
1167
|
async function readConfig() {
|
|
1168
1168
|
try {
|
|
1169
1169
|
const content = await import_node_fs4.promises.readFile(CONFIG_FILE, "utf-8");
|
|
1170
|
-
|
|
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
|
+
};
|
|
1171
1177
|
} catch (error) {
|
|
1172
1178
|
return {};
|
|
1173
1179
|
}
|
|
1174
1180
|
}
|
|
1175
1181
|
async function writeConfig(config) {
|
|
1176
1182
|
await ensureConfigDir();
|
|
1177
|
-
|
|
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");
|
|
1178
1185
|
}
|
|
1179
1186
|
async function deleteConfig() {
|
|
1180
1187
|
try {
|
|
@@ -1194,9 +1201,9 @@ async function isLoggedIn() {
|
|
|
1194
1201
|
const apiKey = await getApiKey();
|
|
1195
1202
|
return !!apiKey;
|
|
1196
1203
|
}
|
|
1197
|
-
async function
|
|
1204
|
+
async function getOrgId() {
|
|
1198
1205
|
const config = await readConfig();
|
|
1199
|
-
return config.
|
|
1206
|
+
return config.orgId || null;
|
|
1200
1207
|
}
|
|
1201
1208
|
async function getWebUrl() {
|
|
1202
1209
|
return DEFAULT_WEB_URL;
|
|
@@ -1210,30 +1217,21 @@ async function getAuthBaseUrl() {
|
|
|
1210
1217
|
var McpUseAPI = class _McpUseAPI {
|
|
1211
1218
|
baseUrl;
|
|
1212
1219
|
apiKey;
|
|
1213
|
-
|
|
1214
|
-
constructor(baseUrl, apiKey,
|
|
1220
|
+
orgId;
|
|
1221
|
+
constructor(baseUrl, apiKey, orgId) {
|
|
1215
1222
|
this.baseUrl = baseUrl || "";
|
|
1216
1223
|
this.apiKey = apiKey;
|
|
1217
|
-
this.
|
|
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
|
|
1226
|
-
return new _McpUseAPI(baseUrl, apiKey ?? void 0,
|
|
1229
|
+
const orgId = await getOrgId();
|
|
1230
|
+
return new _McpUseAPI(baseUrl, apiKey ?? void 0, orgId ?? void 0);
|
|
1227
1231
|
}
|
|
1228
|
-
|
|
1229
|
-
|
|
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.
|
|
1247
|
-
headers["x-profile-id"] = this.
|
|
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();
|
|
@@ -1271,16 +1269,13 @@ var McpUseAPI = class _McpUseAPI {
|
|
|
1271
1269
|
} catch (error) {
|
|
1272
1270
|
clearTimeout(timeoutId);
|
|
1273
1271
|
if (error.name === "AbortError") {
|
|
1274
|
-
throw new Error(
|
|
1275
|
-
`Request timeout after ${timeout / 1e3}s. Try using --follow flag to stream logs instead.`
|
|
1276
|
-
);
|
|
1272
|
+
throw new Error(`Request timeout after ${timeout / 1e3}s.`);
|
|
1277
1273
|
}
|
|
1278
1274
|
throw error;
|
|
1279
1275
|
}
|
|
1280
1276
|
}
|
|
1281
1277
|
/**
|
|
1282
1278
|
* Create a persistent API key using a Better Auth access token.
|
|
1283
|
-
* Calls Better Auth's built-in POST /api/auth/api-key/create endpoint.
|
|
1284
1279
|
*/
|
|
1285
1280
|
async createApiKeyWithAccessToken(accessToken, name = "CLI") {
|
|
1286
1281
|
const authBase = await getAuthBaseUrl();
|
|
@@ -1299,255 +1294,120 @@ var McpUseAPI = class _McpUseAPI {
|
|
|
1299
1294
|
}
|
|
1300
1295
|
return response.json();
|
|
1301
1296
|
}
|
|
1302
|
-
|
|
1303
|
-
* Test authentication
|
|
1304
|
-
*/
|
|
1297
|
+
// ── Auth ────────────────────────────────────────────────────────
|
|
1305
1298
|
async testAuth() {
|
|
1306
|
-
|
|
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
|
+
};
|
|
1307
1312
|
}
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
*/
|
|
1311
|
-
async setDefaultProfile(profileId) {
|
|
1312
|
-
await this.request(`/profiles/${profileId}/set-default`, {
|
|
1313
|
+
async setDefaultOrg(orgId) {
|
|
1314
|
+
await this.request(`/organizations/${orgId}/set-default`, {
|
|
1313
1315
|
method: "POST"
|
|
1314
1316
|
});
|
|
1315
1317
|
}
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
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) {
|
|
1320
1339
|
return this.request("/deployments", {
|
|
1321
1340
|
method: "POST",
|
|
1322
|
-
body: JSON.stringify(
|
|
1341
|
+
body: JSON.stringify(input)
|
|
1323
1342
|
});
|
|
1324
1343
|
}
|
|
1325
|
-
/**
|
|
1326
|
-
* Get deployment by ID
|
|
1327
|
-
*/
|
|
1328
1344
|
async getDeployment(deploymentId) {
|
|
1329
1345
|
return this.request(`/deployments/${deploymentId}`);
|
|
1330
1346
|
}
|
|
1331
|
-
/**
|
|
1332
|
-
* Stream deployment logs
|
|
1333
|
-
*/
|
|
1334
|
-
async *streamDeploymentLogs(deploymentId) {
|
|
1335
|
-
const url = `${this.baseUrl}/deployments/${deploymentId}/logs/stream`;
|
|
1336
|
-
const headers = {};
|
|
1337
|
-
if (this.apiKey) {
|
|
1338
|
-
headers["x-api-key"] = this.apiKey;
|
|
1339
|
-
}
|
|
1340
|
-
if (this.profileId) {
|
|
1341
|
-
headers["x-profile-id"] = this.profileId;
|
|
1342
|
-
}
|
|
1343
|
-
const response = await fetch(url, { headers });
|
|
1344
|
-
if (!response.ok) {
|
|
1345
|
-
throw new Error(`Failed to stream logs: ${response.status}`);
|
|
1346
|
-
}
|
|
1347
|
-
if (!response.body) {
|
|
1348
|
-
throw new Error("Response body is null");
|
|
1349
|
-
}
|
|
1350
|
-
const reader = response.body.getReader();
|
|
1351
|
-
const decoder = new TextDecoder();
|
|
1352
|
-
let buffer = "";
|
|
1353
|
-
try {
|
|
1354
|
-
while (true) {
|
|
1355
|
-
const { done, value } = await reader.read();
|
|
1356
|
-
if (done) break;
|
|
1357
|
-
buffer += decoder.decode(value, { stream: true });
|
|
1358
|
-
const lines = buffer.split("\n");
|
|
1359
|
-
buffer = lines.pop() || "";
|
|
1360
|
-
for (const line of lines) {
|
|
1361
|
-
if (line.startsWith("data: ")) {
|
|
1362
|
-
const data = line.slice(6);
|
|
1363
|
-
try {
|
|
1364
|
-
const parsed = JSON.parse(data);
|
|
1365
|
-
if (parsed.log) {
|
|
1366
|
-
yield parsed.log;
|
|
1367
|
-
} else if (parsed.error) {
|
|
1368
|
-
throw new Error(parsed.error);
|
|
1369
|
-
}
|
|
1370
|
-
} catch (e) {
|
|
1371
|
-
}
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
}
|
|
1375
|
-
} finally {
|
|
1376
|
-
reader.releaseLock();
|
|
1377
|
-
}
|
|
1378
|
-
}
|
|
1379
|
-
/**
|
|
1380
|
-
* Create deployment with source code upload
|
|
1381
|
-
*/
|
|
1382
|
-
async createDeploymentWithUpload(request, filePath) {
|
|
1383
|
-
const { readFile: readFile4 } = await import("fs/promises");
|
|
1384
|
-
const { basename } = await import("path");
|
|
1385
|
-
const { stat } = await import("fs/promises");
|
|
1386
|
-
const stats = await stat(filePath);
|
|
1387
|
-
const maxSize = 2 * 1024 * 1024;
|
|
1388
|
-
if (stats.size > maxSize) {
|
|
1389
|
-
throw new Error(
|
|
1390
|
-
`File size (${(stats.size / 1024 / 1024).toFixed(2)}MB) exceeds maximum of 2MB`
|
|
1391
|
-
);
|
|
1392
|
-
}
|
|
1393
|
-
const fileBuffer = await readFile4(filePath);
|
|
1394
|
-
const filename = basename(filePath);
|
|
1395
|
-
const formData = new FormData();
|
|
1396
|
-
const blob = new Blob([fileBuffer], { type: "application/gzip" });
|
|
1397
|
-
formData.append("source_file", blob, filename);
|
|
1398
|
-
formData.append("name", request.name);
|
|
1399
|
-
formData.append("source_type", "upload");
|
|
1400
|
-
if (request.source.type === "upload") {
|
|
1401
|
-
formData.append("runtime", request.source.runtime || "node");
|
|
1402
|
-
formData.append("port", String(request.source.port || 3e3));
|
|
1403
|
-
if (request.source.startCommand) {
|
|
1404
|
-
formData.append("startCommand", request.source.startCommand);
|
|
1405
|
-
}
|
|
1406
|
-
if (request.source.buildCommand) {
|
|
1407
|
-
formData.append("buildCommand", request.source.buildCommand);
|
|
1408
|
-
}
|
|
1409
|
-
if (request.source.env && Object.keys(request.source.env).length > 0) {
|
|
1410
|
-
formData.append("env", JSON.stringify(request.source.env));
|
|
1411
|
-
}
|
|
1412
|
-
}
|
|
1413
|
-
if (request.customDomain) {
|
|
1414
|
-
formData.append("customDomain", request.customDomain);
|
|
1415
|
-
}
|
|
1416
|
-
if (request.healthCheckPath) {
|
|
1417
|
-
formData.append("healthCheckPath", request.healthCheckPath);
|
|
1418
|
-
}
|
|
1419
|
-
const url = `${this.baseUrl}/deployments`;
|
|
1420
|
-
const headers = {};
|
|
1421
|
-
if (this.apiKey) {
|
|
1422
|
-
headers["x-api-key"] = this.apiKey;
|
|
1423
|
-
}
|
|
1424
|
-
if (this.profileId) {
|
|
1425
|
-
headers["x-profile-id"] = this.profileId;
|
|
1426
|
-
}
|
|
1427
|
-
const response = await fetch(url, {
|
|
1428
|
-
method: "POST",
|
|
1429
|
-
headers,
|
|
1430
|
-
body: formData
|
|
1431
|
-
});
|
|
1432
|
-
if (!response.ok) {
|
|
1433
|
-
const error = await response.text();
|
|
1434
|
-
throw new Error(`Deployment failed: ${error}`);
|
|
1435
|
-
}
|
|
1436
|
-
return response.json();
|
|
1437
|
-
}
|
|
1438
|
-
/**
|
|
1439
|
-
* List all deployments
|
|
1440
|
-
*/
|
|
1441
1347
|
async listDeployments() {
|
|
1442
|
-
|
|
1443
|
-
return response.deployments;
|
|
1348
|
+
return this.request("/deployments");
|
|
1444
1349
|
}
|
|
1445
|
-
/**
|
|
1446
|
-
* Delete deployment
|
|
1447
|
-
*/
|
|
1448
1350
|
async deleteDeployment(deploymentId) {
|
|
1449
1351
|
await this.request(`/deployments/${deploymentId}`, {
|
|
1450
1352
|
method: "DELETE"
|
|
1451
1353
|
});
|
|
1452
1354
|
}
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
async updateDeployment(deploymentId, updates) {
|
|
1457
|
-
return this.request(`/deployments/${deploymentId}`, {
|
|
1458
|
-
method: "PATCH",
|
|
1459
|
-
body: JSON.stringify(updates)
|
|
1460
|
-
});
|
|
1461
|
-
}
|
|
1462
|
-
/**
|
|
1463
|
-
* Redeploy deployment
|
|
1464
|
-
*
|
|
1465
|
-
* @param deploymentId - The deployment ID to redeploy
|
|
1466
|
-
* @param configOrFilePath - Either a RedeploymentConfig object with updated settings,
|
|
1467
|
-
* or a file path string for source code upload
|
|
1468
|
-
*/
|
|
1469
|
-
async redeployDeployment(deploymentId, configOrFilePath) {
|
|
1470
|
-
if (typeof configOrFilePath === "string") {
|
|
1471
|
-
const filePath = configOrFilePath;
|
|
1472
|
-
const { readFile: readFile4 } = await import("fs/promises");
|
|
1473
|
-
const { basename } = await import("path");
|
|
1474
|
-
const { stat } = await import("fs/promises");
|
|
1475
|
-
const stats = await stat(filePath);
|
|
1476
|
-
const maxSize = 2 * 1024 * 1024;
|
|
1477
|
-
if (stats.size > maxSize) {
|
|
1478
|
-
throw new Error(
|
|
1479
|
-
`File size (${(stats.size / 1024 / 1024).toFixed(2)}MB) exceeds maximum of 2MB`
|
|
1480
|
-
);
|
|
1481
|
-
}
|
|
1482
|
-
const fileBuffer = await readFile4(filePath);
|
|
1483
|
-
const formData = new FormData();
|
|
1484
|
-
const blob = new Blob([fileBuffer], { type: "application/gzip" });
|
|
1485
|
-
formData.append("source_file", blob, basename(filePath));
|
|
1486
|
-
const headers = {};
|
|
1487
|
-
if (this.apiKey) headers["x-api-key"] = this.apiKey;
|
|
1488
|
-
if (this.profileId) headers["x-profile-id"] = this.profileId;
|
|
1489
|
-
const response = await fetch(
|
|
1490
|
-
`${this.baseUrl}/deployments/${deploymentId}/redeploy`,
|
|
1491
|
-
{
|
|
1492
|
-
method: "POST",
|
|
1493
|
-
headers,
|
|
1494
|
-
body: formData
|
|
1495
|
-
}
|
|
1496
|
-
);
|
|
1497
|
-
if (!response.ok) {
|
|
1498
|
-
const error = await response.text();
|
|
1499
|
-
throw new Error(`Redeploy failed: ${error}`);
|
|
1500
|
-
}
|
|
1501
|
-
return response.json();
|
|
1502
|
-
}
|
|
1503
|
-
const config = configOrFilePath;
|
|
1504
|
-
return this.request(`/deployments/${deploymentId}/redeploy`, {
|
|
1505
|
-
method: "POST",
|
|
1506
|
-
body: config ? JSON.stringify(config) : void 0
|
|
1355
|
+
async stopDeployment(deploymentId) {
|
|
1356
|
+
await this.request(`/deployments/${deploymentId}/stop`, {
|
|
1357
|
+
method: "POST"
|
|
1507
1358
|
});
|
|
1508
1359
|
}
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
async getDeploymentLogs(deploymentId) {
|
|
1513
|
-
const response = await this.request(
|
|
1514
|
-
`/deployments/${deploymentId}/logs`,
|
|
1360
|
+
async getDeploymentLogs(deploymentId, lines = 500) {
|
|
1361
|
+
const resp = await this.request(
|
|
1362
|
+
`/deployments/${deploymentId}/logs?lines=${lines}`,
|
|
1515
1363
|
{ timeout: 6e4 }
|
|
1516
|
-
// 60 second timeout for logs
|
|
1517
1364
|
);
|
|
1518
|
-
return
|
|
1365
|
+
return resp.logs;
|
|
1519
1366
|
}
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
async getDeploymentBuildLogs(deploymentId) {
|
|
1524
|
-
const response = await this.request(
|
|
1525
|
-
`/deployments/${deploymentId}/logs/build`,
|
|
1367
|
+
async getDeploymentBuildLogs(deploymentId, offset = 0) {
|
|
1368
|
+
return this.request(
|
|
1369
|
+
`/deployments/${deploymentId}/build-logs?offset=${offset}`,
|
|
1526
1370
|
{ timeout: 6e4 }
|
|
1527
|
-
// 60 second timeout for logs
|
|
1528
1371
|
);
|
|
1529
|
-
return response.data.logs;
|
|
1530
1372
|
}
|
|
1531
|
-
|
|
1532
|
-
* Get GitHub connection status
|
|
1533
|
-
*/
|
|
1373
|
+
// ── GitHub ──────────────────────────────────────────────────────
|
|
1534
1374
|
async getGitHubConnectionStatus() {
|
|
1535
|
-
|
|
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
|
+
};
|
|
1536
1384
|
}
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
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
|
+
};
|
|
1543
1407
|
}
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
async getGitHubRepos(refresh = false) {
|
|
1548
|
-
return this.request(
|
|
1549
|
-
`/github/repos${refresh ? "?refresh=true" : ""}`
|
|
1550
|
-
);
|
|
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";
|
|
1551
1411
|
}
|
|
1552
1412
|
};
|
|
1553
1413
|
|
|
@@ -1612,19 +1472,17 @@ async function pollForDeviceToken(authBaseUrl, deviceCode, intervalSeconds) {
|
|
|
1612
1472
|
}
|
|
1613
1473
|
throw new Error("Login timed out. Please try again.");
|
|
1614
1474
|
}
|
|
1615
|
-
async function promptOrgSelection(
|
|
1616
|
-
if (
|
|
1617
|
-
if (
|
|
1618
|
-
return
|
|
1475
|
+
async function promptOrgSelection(orgs, defaultOrgId) {
|
|
1476
|
+
if (orgs.length === 0) return null;
|
|
1477
|
+
if (orgs.length === 1) {
|
|
1478
|
+
return orgs[0];
|
|
1619
1479
|
}
|
|
1620
1480
|
console.log(source_default.cyan.bold("\n\u{1F3E2} Select an organization:\n"));
|
|
1621
|
-
for (let i = 0; i <
|
|
1622
|
-
const
|
|
1623
|
-
const marker =
|
|
1624
|
-
const slug =
|
|
1625
|
-
console.log(
|
|
1626
|
-
` ${source_default.white(`${i + 1}.`)} ${p.profile_name}${slug}${marker}`
|
|
1627
|
-
);
|
|
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}`);
|
|
1628
1486
|
}
|
|
1629
1487
|
const readline = await import("readline");
|
|
1630
1488
|
const rl = readline.createInterface({
|
|
@@ -1632,7 +1490,7 @@ async function promptOrgSelection(profiles, defaultProfileId) {
|
|
|
1632
1490
|
output: process.stdout
|
|
1633
1491
|
});
|
|
1634
1492
|
return new Promise((resolve2) => {
|
|
1635
|
-
const defaultIdx =
|
|
1493
|
+
const defaultIdx = defaultOrgId ? orgs.findIndex((o) => o.id === defaultOrgId) : 0;
|
|
1636
1494
|
const defaultDisplay = defaultIdx >= 0 ? defaultIdx + 1 : 1;
|
|
1637
1495
|
rl.question(
|
|
1638
1496
|
source_default.gray(`
|
|
@@ -1641,11 +1499,11 @@ Enter number [${defaultDisplay}]: `),
|
|
|
1641
1499
|
rl.close();
|
|
1642
1500
|
const trimmed = answer.trim();
|
|
1643
1501
|
const idx = trimmed === "" ? defaultIdx : parseInt(trimmed, 10) - 1;
|
|
1644
|
-
if (idx >= 0 && idx <
|
|
1645
|
-
resolve2(
|
|
1502
|
+
if (idx >= 0 && idx < orgs.length) {
|
|
1503
|
+
resolve2(orgs[idx]);
|
|
1646
1504
|
} else {
|
|
1647
1505
|
console.log(source_default.yellow("Invalid selection, using default."));
|
|
1648
|
-
resolve2(
|
|
1506
|
+
resolve2(orgs[defaultIdx >= 0 ? defaultIdx : 0]);
|
|
1649
1507
|
}
|
|
1650
1508
|
}
|
|
1651
1509
|
);
|
|
@@ -1724,28 +1582,25 @@ async function loginCommand(options) {
|
|
|
1724
1582
|
const masked = storedKey.substring(0, 8) + "...";
|
|
1725
1583
|
console.log(source_default.white(" API Key: ") + source_default.gray(masked));
|
|
1726
1584
|
}
|
|
1727
|
-
const
|
|
1728
|
-
if (
|
|
1729
|
-
let
|
|
1730
|
-
if (
|
|
1731
|
-
|
|
1585
|
+
const orgs = authInfo.orgs ?? [];
|
|
1586
|
+
if (orgs.length > 0) {
|
|
1587
|
+
let selectedOrg = null;
|
|
1588
|
+
if (orgs.length === 1) {
|
|
1589
|
+
selectedOrg = orgs[0];
|
|
1732
1590
|
} else {
|
|
1733
|
-
|
|
1734
|
-
profiles,
|
|
1735
|
-
authInfo.default_profile_id
|
|
1736
|
-
);
|
|
1591
|
+
selectedOrg = await promptOrgSelection(orgs, authInfo.default_org_id);
|
|
1737
1592
|
}
|
|
1738
|
-
if (
|
|
1593
|
+
if (selectedOrg) {
|
|
1739
1594
|
const config = await readConfig();
|
|
1740
1595
|
await writeConfig({
|
|
1741
1596
|
...config,
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1597
|
+
orgId: selectedOrg.id,
|
|
1598
|
+
orgName: selectedOrg.name,
|
|
1599
|
+
orgSlug: selectedOrg.slug ?? void 0
|
|
1745
1600
|
});
|
|
1746
|
-
const slug =
|
|
1601
|
+
const slug = selectedOrg.slug ? source_default.gray(` (${selectedOrg.slug})`) : "";
|
|
1747
1602
|
console.log(
|
|
1748
|
-
source_default.white(" Org: ") + source_default.cyan(
|
|
1603
|
+
source_default.white(" Org: ") + source_default.cyan(selectedOrg.name) + slug
|
|
1749
1604
|
);
|
|
1750
1605
|
}
|
|
1751
1606
|
}
|
|
@@ -1815,22 +1670,22 @@ async function whoamiCommand() {
|
|
|
1815
1670
|
console.log(source_default.white("API Key: ") + source_default.gray(masked));
|
|
1816
1671
|
}
|
|
1817
1672
|
const config = await readConfig();
|
|
1818
|
-
const
|
|
1819
|
-
if (
|
|
1820
|
-
const
|
|
1821
|
-
(
|
|
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)
|
|
1822
1677
|
);
|
|
1823
|
-
if (
|
|
1824
|
-
const slug =
|
|
1678
|
+
if (activeOrg) {
|
|
1679
|
+
const slug = activeOrg.slug ? source_default.gray(` (${activeOrg.slug})`) : "";
|
|
1825
1680
|
console.log(
|
|
1826
|
-
source_default.white("Org: ") + source_default.cyan(
|
|
1681
|
+
source_default.white("Org: ") + source_default.cyan(activeOrg.name) + slug
|
|
1827
1682
|
);
|
|
1828
1683
|
}
|
|
1829
|
-
if (
|
|
1684
|
+
if (orgs.length > 1) {
|
|
1830
1685
|
console.log(
|
|
1831
1686
|
source_default.gray(
|
|
1832
1687
|
`
|
|
1833
|
-
${
|
|
1688
|
+
${orgs.length} organizations available. Use ` + source_default.white("npx mcp-use org list") + " to see all."
|
|
1834
1689
|
)
|
|
1835
1690
|
);
|
|
1836
1691
|
}
|
|
@@ -3225,25 +3080,20 @@ async function prompt(question, defaultValue = "n") {
|
|
|
3225
3080
|
});
|
|
3226
3081
|
}
|
|
3227
3082
|
function getMcpServerUrl(deployment) {
|
|
3228
|
-
if (deployment.
|
|
3229
|
-
return
|
|
3230
|
-
}
|
|
3231
|
-
|
|
3232
|
-
} else if (deployment.serverId) {
|
|
3083
|
+
if (deployment.mcpUrl) {
|
|
3084
|
+
return deployment.mcpUrl;
|
|
3085
|
+
}
|
|
3086
|
+
if (deployment.serverId) {
|
|
3233
3087
|
return buildGatewayUrl(deployment.serverId);
|
|
3234
|
-
} else {
|
|
3235
|
-
return `https://${deployment.domain}/mcp`;
|
|
3236
3088
|
}
|
|
3089
|
+
return "";
|
|
3237
3090
|
}
|
|
3238
|
-
async function displayDeploymentProgress(api,
|
|
3091
|
+
async function displayDeploymentProgress(api, deploymentId, progressOptions) {
|
|
3239
3092
|
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
3240
3093
|
let frameIndex = 0;
|
|
3241
3094
|
let spinnerInterval = null;
|
|
3242
|
-
let lastStep = "";
|
|
3243
3095
|
const startSpinner = (message) => {
|
|
3244
|
-
if (spinnerInterval)
|
|
3245
|
-
clearInterval(spinnerInterval);
|
|
3246
|
-
}
|
|
3096
|
+
if (spinnerInterval) clearInterval(spinnerInterval);
|
|
3247
3097
|
process.stdout.write("\r\x1B[K");
|
|
3248
3098
|
spinnerInterval = setInterval(() => {
|
|
3249
3099
|
const frame = frames[frameIndex];
|
|
@@ -3262,82 +3112,64 @@ async function displayDeploymentProgress(api, deployment, progressOptions) {
|
|
|
3262
3112
|
};
|
|
3263
3113
|
console.log();
|
|
3264
3114
|
startSpinner("Deploying...");
|
|
3265
|
-
try {
|
|
3266
|
-
for await (const log of api.streamDeploymentLogs(deployment.id)) {
|
|
3267
|
-
try {
|
|
3268
|
-
const logData = JSON.parse(log);
|
|
3269
|
-
if (logData.step && logData.step !== lastStep) {
|
|
3270
|
-
lastStep = logData.step;
|
|
3271
|
-
const stepMessages = {
|
|
3272
|
-
clone: "Preparing source code...",
|
|
3273
|
-
analyze: "Analyzing project...",
|
|
3274
|
-
build: "Building container image...",
|
|
3275
|
-
deploy: "Deploying to cloud..."
|
|
3276
|
-
};
|
|
3277
|
-
const message = stepMessages[logData.step] || "Deploying...";
|
|
3278
|
-
startSpinner(message);
|
|
3279
|
-
}
|
|
3280
|
-
if (logData.line) {
|
|
3281
|
-
stopSpinner();
|
|
3282
|
-
const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
|
|
3283
|
-
const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
|
|
3284
|
-
console.log(stepPrefix + levelColor(logData.line));
|
|
3285
|
-
}
|
|
3286
|
-
} catch {
|
|
3287
|
-
}
|
|
3288
|
-
}
|
|
3289
|
-
} catch (error) {
|
|
3290
|
-
stopSpinner();
|
|
3291
|
-
}
|
|
3292
3115
|
let checkCount = 0;
|
|
3293
|
-
const maxChecks =
|
|
3294
|
-
let delay =
|
|
3116
|
+
const maxChecks = 120;
|
|
3117
|
+
let delay = 2e3;
|
|
3295
3118
|
const maxDelay = 1e4;
|
|
3296
|
-
let
|
|
3119
|
+
let buildLogOffset = 0;
|
|
3120
|
+
const sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
3297
3121
|
while (checkCount < maxChecks) {
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3122
|
+
await sleep(delay);
|
|
3123
|
+
checkCount++;
|
|
3124
|
+
try {
|
|
3125
|
+
const buildLogsResp = await api.getDeploymentBuildLogs(
|
|
3126
|
+
deploymentId,
|
|
3127
|
+
buildLogOffset
|
|
3304
3128
|
);
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
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 {
|
|
3310
3141
|
stopSpinner();
|
|
3311
|
-
|
|
3312
|
-
const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
|
|
3313
|
-
console.log(stepPrefix + levelColor(logData.line));
|
|
3142
|
+
console.log(source_default.gray(line));
|
|
3314
3143
|
}
|
|
3315
|
-
} catch {
|
|
3316
3144
|
}
|
|
3145
|
+
buildLogOffset = buildLogsResp.offset;
|
|
3317
3146
|
}
|
|
3318
|
-
|
|
3147
|
+
} catch {
|
|
3319
3148
|
}
|
|
3320
|
-
|
|
3321
|
-
|
|
3149
|
+
const deployment = await api.getDeployment(deploymentId);
|
|
3150
|
+
if (deployment.status === "running") {
|
|
3151
|
+
stopSpinner();
|
|
3152
|
+
const mcpServerUrl = getMcpServerUrl(deployment);
|
|
3322
3153
|
let dashboardUrl = null;
|
|
3323
3154
|
const webUrl = (await getWebUrl()).replace(/\/$/, "");
|
|
3324
3155
|
const config = await readConfig();
|
|
3325
|
-
const orgSlug = config.
|
|
3326
|
-
|
|
3327
|
-
if (serverRef) {
|
|
3156
|
+
const orgSlug = config.orgSlug;
|
|
3157
|
+
if (deployment.serverId) {
|
|
3328
3158
|
if (orgSlug) {
|
|
3329
|
-
dashboardUrl = `${webUrl}/cloud/${orgSlug}/servers/${
|
|
3159
|
+
dashboardUrl = `${webUrl}/cloud/${orgSlug}/servers/${deployment.serverId}`;
|
|
3330
3160
|
} else {
|
|
3331
|
-
dashboardUrl = `${webUrl}/cloud/servers/${
|
|
3161
|
+
dashboardUrl = `${webUrl}/cloud/servers/${deployment.serverId}`;
|
|
3332
3162
|
}
|
|
3333
3163
|
}
|
|
3334
3164
|
const inspectorUrl = `https://inspector.manufact.com/inspector?autoConnect=${encodeURIComponent(
|
|
3335
3165
|
mcpServerUrl
|
|
3336
3166
|
)}`;
|
|
3337
3167
|
console.log(source_default.green.bold("\u2713 Deployment successful!\n"));
|
|
3338
|
-
|
|
3339
|
-
|
|
3168
|
+
if (mcpServerUrl) {
|
|
3169
|
+
console.log(source_default.white("\u{1F310} MCP Server URL:"));
|
|
3170
|
+
console.log(source_default.cyan.bold(` ${mcpServerUrl}
|
|
3340
3171
|
`));
|
|
3172
|
+
}
|
|
3341
3173
|
if (dashboardUrl) {
|
|
3342
3174
|
console.log(source_default.white("\u{1F4CA} Dashboard:"));
|
|
3343
3175
|
console.log(source_default.cyan.bold(` ${dashboardUrl}
|
|
@@ -3346,16 +3178,14 @@ async function displayDeploymentProgress(api, deployment, progressOptions) {
|
|
|
3346
3178
|
console.log(source_default.white("\u{1F50D} Inspector URL:"));
|
|
3347
3179
|
console.log(source_default.cyan.bold(` ${inspectorUrl}
|
|
3348
3180
|
`));
|
|
3349
|
-
console.log(
|
|
3350
|
-
source_default.gray("Deployment ID: ") + source_default.white(finalDeployment.id)
|
|
3351
|
-
);
|
|
3181
|
+
console.log(source_default.gray("Deployment ID: ") + source_default.white(deployment.id));
|
|
3352
3182
|
return;
|
|
3353
|
-
} else if (
|
|
3183
|
+
} else if (deployment.status === "failed") {
|
|
3354
3184
|
stopSpinner();
|
|
3355
3185
|
console.log(source_default.red.bold("\u2717 Deployment failed\n"));
|
|
3356
|
-
if (
|
|
3357
|
-
console.log(source_default.red("Error: ") +
|
|
3358
|
-
if (
|
|
3186
|
+
if (deployment.error) {
|
|
3187
|
+
console.log(source_default.red("Error: ") + deployment.error);
|
|
3188
|
+
if (deployment.error.includes("No GitHub installations found")) {
|
|
3359
3189
|
console.log();
|
|
3360
3190
|
const retry = await promptGitHubInstallation(
|
|
3361
3191
|
api,
|
|
@@ -3363,79 +3193,31 @@ async function displayDeploymentProgress(api, deployment, progressOptions) {
|
|
|
3363
3193
|
void 0,
|
|
3364
3194
|
{ yes: progressOptions?.yes }
|
|
3365
3195
|
);
|
|
3366
|
-
if (retry) {
|
|
3196
|
+
if (retry && deployment.serverId) {
|
|
3367
3197
|
console.log(source_default.cyan("\n\u{1F504} Retrying deployment...\n"));
|
|
3368
|
-
const
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
);
|
|
3374
|
-
return;
|
|
3375
|
-
}
|
|
3376
|
-
} else if (finalDeployment.error.includes("Authenticated git clone failed")) {
|
|
3377
|
-
let repoName;
|
|
3378
|
-
const repoMatch = finalDeployment.error.match(
|
|
3379
|
-
/github\.com\/([^/]+\/[^/\s]+)/
|
|
3380
|
-
);
|
|
3381
|
-
if (repoMatch) {
|
|
3382
|
-
repoName = repoMatch[1].replace(/\.git$/, "");
|
|
3383
|
-
} else if (finalDeployment.source.type === "github") {
|
|
3384
|
-
repoName = finalDeployment.source.repo;
|
|
3385
|
-
}
|
|
3386
|
-
console.log();
|
|
3387
|
-
const retry = await promptGitHubInstallation(
|
|
3388
|
-
api,
|
|
3389
|
-
"no_access",
|
|
3390
|
-
repoName,
|
|
3391
|
-
{ yes: progressOptions?.yes }
|
|
3392
|
-
);
|
|
3393
|
-
if (retry) {
|
|
3394
|
-
console.log(source_default.cyan("\n\u{1F504} Retrying deployment...\n"));
|
|
3395
|
-
const newDeployment = await api.redeployDeployment(deployment.id);
|
|
3396
|
-
await displayDeploymentProgress(
|
|
3397
|
-
api,
|
|
3398
|
-
newDeployment,
|
|
3399
|
-
progressOptions
|
|
3400
|
-
);
|
|
3198
|
+
const newDep = await api.createDeployment({
|
|
3199
|
+
serverId: deployment.serverId,
|
|
3200
|
+
trigger: "redeploy"
|
|
3201
|
+
});
|
|
3202
|
+
await displayDeploymentProgress(api, newDep.id, progressOptions);
|
|
3401
3203
|
return;
|
|
3402
3204
|
}
|
|
3403
3205
|
}
|
|
3404
3206
|
}
|
|
3405
|
-
if (finalDeployment.buildLogs) {
|
|
3406
|
-
console.log(source_default.gray("\nBuild logs:"));
|
|
3407
|
-
try {
|
|
3408
|
-
const logs = finalDeployment.buildLogs.split("\n").filter((l) => l.trim());
|
|
3409
|
-
for (const log of logs) {
|
|
3410
|
-
try {
|
|
3411
|
-
const logData = JSON.parse(log);
|
|
3412
|
-
if (logData.line) {
|
|
3413
|
-
console.log(source_default.gray(` ${logData.line}`));
|
|
3414
|
-
}
|
|
3415
|
-
} catch {
|
|
3416
|
-
console.log(source_default.gray(` ${log}`));
|
|
3417
|
-
}
|
|
3418
|
-
}
|
|
3419
|
-
} catch {
|
|
3420
|
-
console.log(source_default.gray(finalDeployment.buildLogs));
|
|
3421
|
-
}
|
|
3422
|
-
}
|
|
3423
3207
|
process.exit(1);
|
|
3424
|
-
} else if (
|
|
3208
|
+
} else if (deployment.status === "building" || deployment.status === "pending") {
|
|
3425
3209
|
startSpinner("Building and deploying...");
|
|
3426
|
-
checkCount++;
|
|
3427
3210
|
delay = Math.min(delay * 1.2, maxDelay);
|
|
3428
3211
|
} else {
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
);
|
|
3212
|
+
stopSpinner();
|
|
3213
|
+
console.log(source_default.yellow("\u26A0\uFE0F Deployment status: ") + deployment.status);
|
|
3432
3214
|
return;
|
|
3433
3215
|
}
|
|
3434
3216
|
}
|
|
3435
3217
|
stopSpinner();
|
|
3436
3218
|
console.log(source_default.yellow("\u26A0\uFE0F Deployment is taking longer than expected."));
|
|
3437
3219
|
console.log(
|
|
3438
|
-
source_default.gray("Check status with: ") + source_default.white(`mcp-use
|
|
3220
|
+
source_default.gray("Check status with: ") + source_default.white(`mcp-use deployments get ${deploymentId}`)
|
|
3439
3221
|
);
|
|
3440
3222
|
}
|
|
3441
3223
|
async function checkRepoAccess(api, owner, repo) {
|
|
@@ -3521,7 +3303,7 @@ async function promptGitHubInstallation(api, reason, repoName, opts) {
|
|
|
3521
3303
|
return false;
|
|
3522
3304
|
}
|
|
3523
3305
|
try {
|
|
3524
|
-
const appName =
|
|
3306
|
+
const appName = await api.getGitHubAppName();
|
|
3525
3307
|
const installUrl = reason === "not_connected" ? `https://github.com/apps/${appName}/installations/new` : `https://github.com/settings/installations`;
|
|
3526
3308
|
console.log(
|
|
3527
3309
|
source_default.cyan(
|
|
@@ -3801,14 +3583,14 @@ async function deployCommand(options) {
|
|
|
3801
3583
|
if (options.org) {
|
|
3802
3584
|
try {
|
|
3803
3585
|
const authInfo = await api.testAuth();
|
|
3804
|
-
const match = (authInfo.
|
|
3805
|
-
(
|
|
3586
|
+
const match = (authInfo.orgs ?? []).find(
|
|
3587
|
+
(o) => o.slug === options.org || o.id === options.org || o.name.toLowerCase() === options.org.toLowerCase()
|
|
3806
3588
|
);
|
|
3807
3589
|
if (match) {
|
|
3808
|
-
api.
|
|
3590
|
+
api.setOrgId(match.id);
|
|
3809
3591
|
const slug = match.slug ? source_default.gray(` (${match.slug})`) : "";
|
|
3810
3592
|
console.log(
|
|
3811
|
-
source_default.gray("Organization: ") + source_default.cyan(match.
|
|
3593
|
+
source_default.gray("Organization: ") + source_default.cyan(match.name) + slug
|
|
3812
3594
|
);
|
|
3813
3595
|
} else {
|
|
3814
3596
|
console.error(
|
|
@@ -3827,6 +3609,7 @@ async function deployCommand(options) {
|
|
|
3827
3609
|
}
|
|
3828
3610
|
}
|
|
3829
3611
|
let githubVerified = false;
|
|
3612
|
+
let installationDbId;
|
|
3830
3613
|
try {
|
|
3831
3614
|
console.log(source_default.gray(`[DEBUG] API URL: ${api.baseUrl}`));
|
|
3832
3615
|
const connectionStatus = await api.getGitHubConnectionStatus();
|
|
@@ -3853,8 +3636,10 @@ async function deployCommand(options) {
|
|
|
3853
3636
|
console.log(source_default.cyan(" https://manufact.com/cloud/settings\n"));
|
|
3854
3637
|
process.exit(1);
|
|
3855
3638
|
}
|
|
3639
|
+
installationDbId = retryStatus.installations?.[0]?.id;
|
|
3856
3640
|
githubVerified = true;
|
|
3857
3641
|
} else if (gitInfo.owner && gitInfo.repo) {
|
|
3642
|
+
installationDbId = connectionStatus.installations?.[0]?.id;
|
|
3858
3643
|
console.log(source_default.gray("Checking repository access..."));
|
|
3859
3644
|
const hasAccess = await checkRepoAccess(
|
|
3860
3645
|
api,
|
|
@@ -3933,7 +3718,7 @@ async function deployCommand(options) {
|
|
|
3933
3718
|
}
|
|
3934
3719
|
const existingLink = !options.new ? await getProjectLink(cwd) : null;
|
|
3935
3720
|
const serverId = existingLink?.serverId;
|
|
3936
|
-
if (existingLink) {
|
|
3721
|
+
if (existingLink && serverId) {
|
|
3937
3722
|
try {
|
|
3938
3723
|
const existingDeployment = await api.getDeployment(
|
|
3939
3724
|
existingLink.deploymentId
|
|
@@ -3945,29 +3730,19 @@ async function deployCommand(options) {
|
|
|
3945
3730
|
source_default.cyan(` URL: ${getMcpServerUrl(existingDeployment)}
|
|
3946
3731
|
`)
|
|
3947
3732
|
);
|
|
3948
|
-
const
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
rootDir: options.rootDir || void 0
|
|
3954
|
-
};
|
|
3955
|
-
const deployment2 = await api.redeployDeployment(
|
|
3956
|
-
existingLink.deploymentId,
|
|
3957
|
-
redeploymentConfig
|
|
3958
|
-
);
|
|
3733
|
+
const newDep = await api.createDeployment({
|
|
3734
|
+
serverId,
|
|
3735
|
+
branch: gitInfo.branch || "main",
|
|
3736
|
+
trigger: "redeploy"
|
|
3737
|
+
});
|
|
3959
3738
|
await saveProjectLink(cwd, {
|
|
3960
3739
|
...existingLink,
|
|
3961
|
-
linkedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3740
|
+
linkedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3741
|
+
deploymentId: newDep.id
|
|
3962
3742
|
});
|
|
3963
|
-
await displayDeploymentProgress(api,
|
|
3743
|
+
await displayDeploymentProgress(api, newDep.id, {
|
|
3964
3744
|
yes: options.yes
|
|
3965
3745
|
});
|
|
3966
|
-
if (options.open && deployment2.domain) {
|
|
3967
|
-
console.log();
|
|
3968
|
-
console.log(source_default.gray("Opening deployment in browser..."));
|
|
3969
|
-
await open_default(`https://${deployment2.domain}`);
|
|
3970
|
-
}
|
|
3971
3746
|
return;
|
|
3972
3747
|
} else {
|
|
3973
3748
|
console.log(
|
|
@@ -3975,72 +3750,97 @@ async function deployCommand(options) {
|
|
|
3975
3750
|
`\u26A0\uFE0F Linked deployment not found or failed, creating new one...`
|
|
3976
3751
|
)
|
|
3977
3752
|
);
|
|
3978
|
-
|
|
3979
|
-
console.log(
|
|
3980
|
-
source_default.gray(` Will reuse existing server: ${serverId}`)
|
|
3981
|
-
);
|
|
3982
|
-
}
|
|
3753
|
+
console.log(source_default.gray(` Will reuse existing server: ${serverId}`));
|
|
3983
3754
|
}
|
|
3984
3755
|
} catch (error) {
|
|
3985
3756
|
console.log(
|
|
3986
3757
|
source_default.yellow(`\u26A0\uFE0F Linked deployment not found, creating new one...`)
|
|
3987
3758
|
);
|
|
3988
|
-
|
|
3989
|
-
console.log(source_default.gray(` Will reuse existing server: ${serverId}`));
|
|
3990
|
-
}
|
|
3759
|
+
console.log(source_default.gray(` Will reuse existing server: ${serverId}`));
|
|
3991
3760
|
}
|
|
3992
3761
|
}
|
|
3993
|
-
const deploymentRequest = {
|
|
3994
|
-
name: projectName,
|
|
3995
|
-
source: {
|
|
3996
|
-
type: "github",
|
|
3997
|
-
repo: `${gitInfo.owner}/${gitInfo.repo}`,
|
|
3998
|
-
branch: gitInfo.branch || "main",
|
|
3999
|
-
rootDir: options.rootDir || void 0,
|
|
4000
|
-
runtime,
|
|
4001
|
-
port,
|
|
4002
|
-
buildCommand,
|
|
4003
|
-
startCommand,
|
|
4004
|
-
env: Object.keys(envVars).length > 0 ? envVars : void 0
|
|
4005
|
-
},
|
|
4006
|
-
healthCheckPath: "/healthz",
|
|
4007
|
-
serverId
|
|
4008
|
-
};
|
|
4009
3762
|
if (!options.org) {
|
|
4010
3763
|
try {
|
|
4011
3764
|
const config = await readConfig();
|
|
4012
|
-
if (config.
|
|
4013
|
-
const slug = config.
|
|
3765
|
+
if (config.orgName) {
|
|
3766
|
+
const slug = config.orgSlug ? source_default.gray(` (${config.orgSlug})`) : "";
|
|
4014
3767
|
console.log(
|
|
4015
|
-
source_default.gray("Organization: ") + source_default.cyan(config.
|
|
3768
|
+
source_default.gray("Organization: ") + source_default.cyan(config.orgName) + slug
|
|
4016
3769
|
);
|
|
4017
3770
|
}
|
|
4018
3771
|
} catch {
|
|
4019
3772
|
}
|
|
4020
3773
|
}
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
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
|
|
4037
3838
|
`));
|
|
4038
|
-
await displayDeploymentProgress(api, deployment, { yes: options.yes });
|
|
4039
|
-
if (options.open && deployment.domain) {
|
|
4040
|
-
console.log();
|
|
4041
|
-
console.log(source_default.gray("Opening deployment in browser..."));
|
|
4042
|
-
await open_default(`https://${deployment.domain}`);
|
|
4043
3839
|
}
|
|
3840
|
+
console.log(
|
|
3841
|
+
source_default.green("\u2713 Deployment created: ") + source_default.gray(deploymentId)
|
|
3842
|
+
);
|
|
3843
|
+
await displayDeploymentProgress(api, deploymentId, { yes: options.yes });
|
|
4044
3844
|
} catch (error) {
|
|
4045
3845
|
console.error(
|
|
4046
3846
|
source_default.red.bold("\n\u2717 Deployment failed:"),
|
|
@@ -4115,19 +3915,19 @@ async function listDeploymentsCommand() {
|
|
|
4115
3915
|
);
|
|
4116
3916
|
console.log(
|
|
4117
3917
|
source_default.white.bold(
|
|
4118
|
-
`${"ID".padEnd(40)} ${"NAME".padEnd(25)} ${"STATUS".padEnd(12)} ${"
|
|
3918
|
+
`${"ID".padEnd(40)} ${"NAME".padEnd(25)} ${"STATUS".padEnd(12)} ${"MCP URL".padEnd(45)} ${"CREATED"}`
|
|
4119
3919
|
)
|
|
4120
3920
|
);
|
|
4121
|
-
console.log(source_default.gray("\u2500".repeat(
|
|
3921
|
+
console.log(source_default.gray("\u2500".repeat(140)));
|
|
4122
3922
|
for (const deployment of sortedDeployments) {
|
|
4123
3923
|
const id = formatId(deployment.id).padEnd(40);
|
|
4124
3924
|
const name = deployment.name.substring(0, 24).padEnd(25);
|
|
4125
3925
|
const statusColor = getStatusColor(deployment.status);
|
|
4126
3926
|
const status = statusColor(deployment.status.padEnd(12));
|
|
4127
|
-
const
|
|
3927
|
+
const mcpUrl = (deployment.mcpUrl || "-").substring(0, 44).padEnd(45);
|
|
4128
3928
|
const created = formatRelativeTime(deployment.createdAt);
|
|
4129
3929
|
console.log(
|
|
4130
|
-
`${source_default.gray(id)} ${name} ${status} ${source_default.cyan(
|
|
3930
|
+
`${source_default.gray(id)} ${name} ${status} ${source_default.cyan(mcpUrl)} ${source_default.gray(created)}`
|
|
4131
3931
|
);
|
|
4132
3932
|
}
|
|
4133
3933
|
console.log();
|
|
@@ -4159,31 +3959,24 @@ async function getDeploymentCommand(deploymentId) {
|
|
|
4159
3959
|
console.log(
|
|
4160
3960
|
source_default.white("Status: ") + statusColor(deployment.status)
|
|
4161
3961
|
);
|
|
4162
|
-
if (deployment.
|
|
3962
|
+
if (deployment.mcpUrl) {
|
|
4163
3963
|
console.log(
|
|
4164
|
-
source_default.white("
|
|
3964
|
+
source_default.white("MCP URL: ") + source_default.cyan(deployment.mcpUrl)
|
|
4165
3965
|
);
|
|
4166
3966
|
}
|
|
4167
|
-
if (deployment.
|
|
3967
|
+
if (deployment.gitBranch) {
|
|
4168
3968
|
console.log(
|
|
4169
|
-
source_default.white("
|
|
3969
|
+
source_default.white("Branch: ") + source_default.gray(deployment.gitBranch)
|
|
4170
3970
|
);
|
|
4171
3971
|
}
|
|
4172
|
-
|
|
4173
|
-
source_default.white("Source: ") + source_default.gray(deployment.source.type)
|
|
4174
|
-
);
|
|
4175
|
-
if (deployment.source.type === "github") {
|
|
4176
|
-
console.log(
|
|
4177
|
-
source_default.white("Repository: ") + source_default.gray(deployment.source.repo)
|
|
4178
|
-
);
|
|
3972
|
+
if (deployment.gitCommitSha) {
|
|
4179
3973
|
console.log(
|
|
4180
|
-
source_default.white("
|
|
3974
|
+
source_default.white("Commit: ") + source_default.gray(deployment.gitCommitSha.substring(0, 7))
|
|
4181
3975
|
);
|
|
4182
3976
|
}
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
);
|
|
3977
|
+
if (deployment.port) {
|
|
3978
|
+
console.log(source_default.white("Port: ") + source_default.gray(deployment.port));
|
|
3979
|
+
}
|
|
4187
3980
|
if (deployment.provider) {
|
|
4188
3981
|
console.log(
|
|
4189
3982
|
source_default.white("Provider: ") + source_default.gray(deployment.provider)
|
|
@@ -4195,13 +3988,6 @@ async function getDeploymentCommand(deploymentId) {
|
|
|
4195
3988
|
console.log(
|
|
4196
3989
|
source_default.white("Updated: ") + source_default.gray(formatRelativeTime(deployment.updatedAt))
|
|
4197
3990
|
);
|
|
4198
|
-
if (deployment.source.env && Object.keys(deployment.source.env).length > 0) {
|
|
4199
|
-
console.log(source_default.white("\nEnvironment Variables:"));
|
|
4200
|
-
for (const [key, value] of Object.entries(deployment.source.env)) {
|
|
4201
|
-
const displayValue = key.toLowerCase().includes("key") || key.toLowerCase().includes("secret") || key.toLowerCase().includes("password") || key.toLowerCase().includes("token") ? "***" : value;
|
|
4202
|
-
console.log(source_default.gray(` ${key}=`) + source_default.white(displayValue));
|
|
4203
|
-
}
|
|
4204
|
-
}
|
|
4205
3991
|
if (deployment.status === "failed" && deployment.error) {
|
|
4206
3992
|
console.log(source_default.red("\nError:"));
|
|
4207
3993
|
console.log(source_default.red(` ${deployment.error}`));
|
|
@@ -4228,43 +4014,56 @@ async function restartDeploymentCommand(deploymentId, options) {
|
|
|
4228
4014
|
}
|
|
4229
4015
|
const api = await McpUseAPI.create();
|
|
4230
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
|
+
}
|
|
4231
4023
|
console.log(
|
|
4232
4024
|
source_default.cyan.bold(`
|
|
4233
4025
|
\u{1F504} Restarting deployment: ${deployment.name}
|
|
4234
4026
|
`)
|
|
4235
4027
|
);
|
|
4236
|
-
const
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
);
|
|
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));
|
|
4240
4033
|
if (options.follow) {
|
|
4241
|
-
console.log(source_default.gray("\nFollowing
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
))
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
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
|
+
}
|
|
4252
4054
|
}
|
|
4253
|
-
|
|
4254
|
-
console.log(source_default.gray(log));
|
|
4055
|
+
offset = resp.offset;
|
|
4255
4056
|
}
|
|
4057
|
+
if (resp.status === "running" || resp.status === "failed" || resp.status === "stopped") {
|
|
4058
|
+
terminal = true;
|
|
4059
|
+
}
|
|
4060
|
+
} catch {
|
|
4256
4061
|
}
|
|
4257
|
-
} catch (error) {
|
|
4258
|
-
console.log(
|
|
4259
|
-
source_default.gray(
|
|
4260
|
-
"\nLog stream ended. Use " + source_default.white(`mcp-use deployments get ${deploymentId}`) + " to check status."
|
|
4261
|
-
)
|
|
4262
|
-
);
|
|
4263
4062
|
}
|
|
4264
4063
|
} else {
|
|
4265
4064
|
console.log(
|
|
4266
4065
|
source_default.gray(
|
|
4267
|
-
"\nCheck status with: " + source_default.white(`mcp-use deployments get ${
|
|
4066
|
+
"\nCheck status with: " + source_default.white(`mcp-use deployments get ${newDep.id}`)
|
|
4268
4067
|
)
|
|
4269
4068
|
);
|
|
4270
4069
|
}
|
|
@@ -4298,8 +4097,10 @@ async function deleteDeploymentCommand(deploymentId, options) {
|
|
|
4298
4097
|
)
|
|
4299
4098
|
);
|
|
4300
4099
|
console.log(source_default.gray(` ID: ${deployment.id}`));
|
|
4301
|
-
|
|
4100
|
+
if (deployment.mcpUrl) {
|
|
4101
|
+
console.log(source_default.gray(` URL: ${deployment.mcpUrl}
|
|
4302
4102
|
`));
|
|
4103
|
+
}
|
|
4303
4104
|
const confirmed = await prompt2(
|
|
4304
4105
|
source_default.white("Are you sure you want to delete this deployment? (y/N): ")
|
|
4305
4106
|
);
|
|
@@ -4335,30 +4136,41 @@ async function logsCommand(deploymentId, options) {
|
|
|
4335
4136
|
}
|
|
4336
4137
|
const api = await McpUseAPI.create();
|
|
4337
4138
|
if (options.follow) {
|
|
4338
|
-
console.log(source_default.gray("
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
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
|
+
}
|
|
4347
4159
|
}
|
|
4348
|
-
|
|
4349
|
-
console.log(source_default.gray(log));
|
|
4160
|
+
offset = resp.offset;
|
|
4350
4161
|
}
|
|
4162
|
+
if (resp.status === "running" || resp.status === "failed" || resp.status === "stopped") {
|
|
4163
|
+
terminal = true;
|
|
4164
|
+
}
|
|
4165
|
+
} catch {
|
|
4351
4166
|
}
|
|
4352
|
-
} catch (error) {
|
|
4353
|
-
console.log(source_default.gray("\nLog stream ended."));
|
|
4354
4167
|
}
|
|
4355
|
-
} else {
|
|
4356
|
-
const
|
|
4168
|
+
} else if (options.build) {
|
|
4169
|
+
const resp = await api.getDeploymentBuildLogs(deploymentId);
|
|
4170
|
+
const logs = resp.logs;
|
|
4357
4171
|
if (!logs || logs.trim() === "") {
|
|
4358
4172
|
console.log(
|
|
4359
|
-
source_default.yellow(
|
|
4360
|
-
`No ${options.build ? "build " : ""}logs available for this deployment.`
|
|
4361
|
-
)
|
|
4173
|
+
source_default.yellow("No build logs available for this deployment.")
|
|
4362
4174
|
);
|
|
4363
4175
|
return;
|
|
4364
4176
|
}
|
|
@@ -4375,133 +4187,30 @@ async function logsCommand(deploymentId, options) {
|
|
|
4375
4187
|
console.log(source_default.gray(line));
|
|
4376
4188
|
}
|
|
4377
4189
|
}
|
|
4378
|
-
}
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
);
|
|
4397
|
-
process.exit(1);
|
|
4398
|
-
}
|
|
4399
|
-
const api = await McpUseAPI.create();
|
|
4400
|
-
const deployment = await api.getDeployment(deploymentId);
|
|
4401
|
-
console.log(
|
|
4402
|
-
source_default.cyan.bold(`
|
|
4403
|
-
\u{1F510} Environment Variables: ${deployment.name}
|
|
4404
|
-
`)
|
|
4405
|
-
);
|
|
4406
|
-
if (!deployment.source.env || Object.keys(deployment.source.env).length === 0) {
|
|
4407
|
-
console.log(source_default.yellow("No environment variables set."));
|
|
4408
|
-
console.log();
|
|
4409
|
-
return;
|
|
4410
|
-
}
|
|
4411
|
-
for (const [key, value] of Object.entries(deployment.source.env)) {
|
|
4412
|
-
const displayValue = key.toLowerCase().includes("key") || key.toLowerCase().includes("secret") || key.toLowerCase().includes("password") || key.toLowerCase().includes("token") ? "***" : value;
|
|
4413
|
-
console.log(
|
|
4414
|
-
source_default.white(key) + source_default.gray("=") + source_default.cyan(displayValue)
|
|
4415
|
-
);
|
|
4416
|
-
}
|
|
4417
|
-
console.log();
|
|
4418
|
-
} catch (error) {
|
|
4419
|
-
console.error(
|
|
4420
|
-
source_default.red.bold("\n\u2717 Failed to list environment variables:"),
|
|
4421
|
-
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
4422
|
-
);
|
|
4423
|
-
process.exit(1);
|
|
4424
|
-
}
|
|
4425
|
-
}
|
|
4426
|
-
async function setEnvCommand(deploymentId, envPairs) {
|
|
4427
|
-
try {
|
|
4428
|
-
if (!await isLoggedIn()) {
|
|
4429
|
-
console.log(source_default.red("\u2717 You are not logged in."));
|
|
4430
|
-
console.log(
|
|
4431
|
-
source_default.gray(
|
|
4432
|
-
"Run " + source_default.white("npx mcp-use login") + " to get started."
|
|
4433
|
-
)
|
|
4434
|
-
);
|
|
4435
|
-
process.exit(1);
|
|
4436
|
-
}
|
|
4437
|
-
const env2 = {};
|
|
4438
|
-
for (const pair of envPairs) {
|
|
4439
|
-
const [key, ...valueParts] = pair.split("=");
|
|
4440
|
-
if (!key || valueParts.length === 0) {
|
|
4441
|
-
console.log(source_default.red(`\u2717 Invalid format: ${pair}. Expected KEY=VALUE`));
|
|
4442
|
-
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
|
+
}
|
|
4443
4208
|
}
|
|
4444
|
-
env2[key.trim()] = valueParts.join("=").trim();
|
|
4445
|
-
}
|
|
4446
|
-
const api = await McpUseAPI.create();
|
|
4447
|
-
const deployment = await api.getDeployment(deploymentId);
|
|
4448
|
-
const currentEnv = deployment.source.env || {};
|
|
4449
|
-
const mergedEnv = { ...currentEnv, ...env2 };
|
|
4450
|
-
const updated = await api.updateDeployment(deploymentId, {
|
|
4451
|
-
env: mergedEnv
|
|
4452
|
-
});
|
|
4453
|
-
console.log(
|
|
4454
|
-
source_default.green.bold(`
|
|
4455
|
-
\u2713 Environment variables updated: ${updated.name}
|
|
4456
|
-
`)
|
|
4457
|
-
);
|
|
4458
|
-
for (const key of Object.keys(env2)) {
|
|
4459
|
-
const displayValue = key.toLowerCase().includes("key") || key.toLowerCase().includes("secret") || key.toLowerCase().includes("password") || key.toLowerCase().includes("token") ? "***" : env2[key];
|
|
4460
|
-
console.log(
|
|
4461
|
-
source_default.white(key) + source_default.gray("=") + source_default.cyan(displayValue)
|
|
4462
|
-
);
|
|
4463
|
-
}
|
|
4464
|
-
console.log();
|
|
4465
|
-
} catch (error) {
|
|
4466
|
-
console.error(
|
|
4467
|
-
source_default.red.bold("\n\u2717 Failed to set environment variables:"),
|
|
4468
|
-
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
4469
|
-
);
|
|
4470
|
-
process.exit(1);
|
|
4471
|
-
}
|
|
4472
|
-
}
|
|
4473
|
-
async function unsetEnvCommand(deploymentId, keys) {
|
|
4474
|
-
try {
|
|
4475
|
-
if (!await isLoggedIn()) {
|
|
4476
|
-
console.log(source_default.red("\u2717 You are not logged in."));
|
|
4477
|
-
console.log(
|
|
4478
|
-
source_default.gray(
|
|
4479
|
-
"Run " + source_default.white("npx mcp-use login") + " to get started."
|
|
4480
|
-
)
|
|
4481
|
-
);
|
|
4482
|
-
process.exit(1);
|
|
4483
|
-
}
|
|
4484
|
-
const api = await McpUseAPI.create();
|
|
4485
|
-
const deployment = await api.getDeployment(deploymentId);
|
|
4486
|
-
const currentEnv = { ...deployment.source.env || {} };
|
|
4487
|
-
for (const key of keys) {
|
|
4488
|
-
delete currentEnv[key];
|
|
4489
|
-
}
|
|
4490
|
-
const updated = await api.updateDeployment(deploymentId, {
|
|
4491
|
-
env: currentEnv
|
|
4492
|
-
});
|
|
4493
|
-
console.log(
|
|
4494
|
-
source_default.green.bold(`
|
|
4495
|
-
\u2713 Environment variables removed: ${updated.name}
|
|
4496
|
-
`)
|
|
4497
|
-
);
|
|
4498
|
-
for (const key of keys) {
|
|
4499
|
-
console.log(source_default.gray(` ${key}`));
|
|
4500
4209
|
}
|
|
4501
4210
|
console.log();
|
|
4502
4211
|
} catch (error) {
|
|
4503
4212
|
console.error(
|
|
4504
|
-
source_default.red.bold("\n\u2717 Failed to
|
|
4213
|
+
source_default.red.bold("\n\u2717 Failed to get logs:"),
|
|
4505
4214
|
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
4506
4215
|
);
|
|
4507
4216
|
process.exit(1);
|
|
@@ -4519,11 +4228,9 @@ async function stopDeploymentCommand(deploymentId) {
|
|
|
4519
4228
|
process.exit(1);
|
|
4520
4229
|
}
|
|
4521
4230
|
const api = await McpUseAPI.create();
|
|
4522
|
-
|
|
4523
|
-
status: "stopped"
|
|
4524
|
-
});
|
|
4231
|
+
await api.stopDeployment(deploymentId);
|
|
4525
4232
|
console.log(source_default.green.bold(`
|
|
4526
|
-
\u2713 Deployment stopped
|
|
4233
|
+
\u2713 Deployment stopped
|
|
4527
4234
|
`));
|
|
4528
4235
|
} catch (error) {
|
|
4529
4236
|
console.error(
|
|
@@ -4544,13 +4251,11 @@ async function startDeploymentCommand(deploymentId) {
|
|
|
4544
4251
|
);
|
|
4545
4252
|
process.exit(1);
|
|
4546
4253
|
}
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
\u2713 Deployment started: ${updated.name}
|
|
4553
|
-
`));
|
|
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
|
+
);
|
|
4554
4259
|
} catch (error) {
|
|
4555
4260
|
console.error(
|
|
4556
4261
|
source_default.red.bold("\n\u2717 Failed to start deployment:"),
|
|
@@ -4565,13 +4270,11 @@ function createDeploymentsCommand() {
|
|
|
4565
4270
|
);
|
|
4566
4271
|
deploymentsCommand.command("list").alias("ls").description("List all deployments").action(listDeploymentsCommand);
|
|
4567
4272
|
deploymentsCommand.command("get").argument("<deployment-id>", "Deployment ID").description("Get deployment details").action(getDeploymentCommand);
|
|
4568
|
-
deploymentsCommand.command("restart").argument("<deployment-id>", "Deployment ID").option("-f, --follow", "Follow
|
|
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);
|
|
4569
4276
|
deploymentsCommand.command("delete").alias("rm").argument("<deployment-id>", "Deployment ID").option("-y, --yes", "Skip confirmation prompt").description("Delete a deployment").action(deleteDeploymentCommand);
|
|
4570
|
-
deploymentsCommand.command("logs").argument("<deployment-id>", "Deployment ID").option("-b, --build", "Show build logs instead of runtime logs").option("-f, --follow", "
|
|
4571
|
-
const envCommand = deploymentsCommand.command("env").description("Manage environment variables");
|
|
4572
|
-
envCommand.command("list").argument("<deployment-id>", "Deployment ID").description("List environment variables").action(listEnvCommand);
|
|
4573
|
-
envCommand.command("set").argument("<deployment-id>", "Deployment ID").argument("<pairs...>", "Environment variables in KEY=VALUE format").description("Set environment variables").action(setEnvCommand);
|
|
4574
|
-
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);
|
|
4575
4278
|
deploymentsCommand.command("stop").argument("<deployment-id>", "Deployment ID").description("Stop a deployment").action(stopDeploymentCommand);
|
|
4576
4279
|
deploymentsCommand.command("start").argument("<deployment-id>", "Deployment ID").description("Start a stopped deployment").action(startDeploymentCommand);
|
|
4577
4280
|
return deploymentsCommand;
|
|
@@ -4594,22 +4297,22 @@ async function orgListCommand() {
|
|
|
4594
4297
|
const api = await McpUseAPI.create();
|
|
4595
4298
|
const authInfo = await api.testAuth();
|
|
4596
4299
|
const config = await readConfig();
|
|
4597
|
-
const
|
|
4598
|
-
const activeId = config.
|
|
4599
|
-
if (
|
|
4300
|
+
const orgs = authInfo.orgs ?? [];
|
|
4301
|
+
const activeId = config.orgId || authInfo.default_org_id;
|
|
4302
|
+
if (orgs.length === 0) {
|
|
4600
4303
|
console.log(source_default.yellow("No organizations found."));
|
|
4601
4304
|
return;
|
|
4602
4305
|
}
|
|
4603
4306
|
console.log(source_default.cyan.bold("\u{1F3E2} Your organizations:\n"));
|
|
4604
|
-
for (const
|
|
4605
|
-
const isActive =
|
|
4307
|
+
for (const o of orgs) {
|
|
4308
|
+
const isActive = o.id === activeId;
|
|
4606
4309
|
const marker = isActive ? source_default.green(" \u2190 active") : "";
|
|
4607
|
-
const slug =
|
|
4608
|
-
const role = source_default.gray(` [${
|
|
4609
|
-
const name = isActive ? source_default.cyan.bold(
|
|
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);
|
|
4610
4313
|
console.log(` ${name}${slug}${role}${marker}`);
|
|
4611
4314
|
}
|
|
4612
|
-
if (
|
|
4315
|
+
if (orgs.length > 1) {
|
|
4613
4316
|
console.log(
|
|
4614
4317
|
source_default.gray("\nSwitch with " + source_default.white("npx mcp-use org switch"))
|
|
4615
4318
|
);
|
|
@@ -4628,40 +4331,40 @@ async function orgSwitchCommand() {
|
|
|
4628
4331
|
const api = await McpUseAPI.create();
|
|
4629
4332
|
const authInfo = await api.testAuth();
|
|
4630
4333
|
const config = await readConfig();
|
|
4631
|
-
const
|
|
4632
|
-
if (
|
|
4334
|
+
const orgs = authInfo.orgs ?? [];
|
|
4335
|
+
if (orgs.length === 0) {
|
|
4633
4336
|
console.log(source_default.yellow("No organizations found."));
|
|
4634
4337
|
return;
|
|
4635
4338
|
}
|
|
4636
|
-
if (
|
|
4637
|
-
const
|
|
4638
|
-
const slug2 =
|
|
4339
|
+
if (orgs.length === 1) {
|
|
4340
|
+
const o = orgs[0];
|
|
4341
|
+
const slug2 = o.slug ? source_default.gray(` (${o.slug})`) : "";
|
|
4639
4342
|
console.log(
|
|
4640
4343
|
source_default.yellow(
|
|
4641
|
-
`You only have one organization: ${source_default.cyan(
|
|
4344
|
+
`You only have one organization: ${source_default.cyan(o.name)}${slug2}`
|
|
4642
4345
|
)
|
|
4643
4346
|
);
|
|
4644
4347
|
return;
|
|
4645
4348
|
}
|
|
4646
|
-
const activeId = config.
|
|
4647
|
-
const selected = await promptOrgSelection(
|
|
4349
|
+
const activeId = config.orgId || authInfo.default_org_id;
|
|
4350
|
+
const selected = await promptOrgSelection(orgs, activeId);
|
|
4648
4351
|
if (!selected) {
|
|
4649
4352
|
console.log(source_default.yellow("No organization selected."));
|
|
4650
4353
|
return;
|
|
4651
4354
|
}
|
|
4652
4355
|
await writeConfig({
|
|
4653
4356
|
...config,
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4357
|
+
orgId: selected.id,
|
|
4358
|
+
orgName: selected.name,
|
|
4359
|
+
orgSlug: selected.slug ?? void 0
|
|
4657
4360
|
});
|
|
4658
4361
|
try {
|
|
4659
|
-
await api.
|
|
4362
|
+
await api.setDefaultOrg(selected.id);
|
|
4660
4363
|
} catch {
|
|
4661
4364
|
}
|
|
4662
4365
|
const slug = selected.slug ? source_default.gray(` (${selected.slug})`) : "";
|
|
4663
4366
|
console.log(
|
|
4664
|
-
source_default.green.bold("\n\u2713 Switched to ") + source_default.cyan.bold(selected.
|
|
4367
|
+
source_default.green.bold("\n\u2713 Switched to ") + source_default.cyan.bold(selected.name) + slug
|
|
4665
4368
|
);
|
|
4666
4369
|
} catch (error) {
|
|
4667
4370
|
console.error(
|
|
@@ -4675,7 +4378,7 @@ async function orgCurrentCommand() {
|
|
|
4675
4378
|
try {
|
|
4676
4379
|
if (!await ensureLoggedIn()) return;
|
|
4677
4380
|
const config = await readConfig();
|
|
4678
|
-
if (!config.
|
|
4381
|
+
if (!config.orgId) {
|
|
4679
4382
|
console.log(
|
|
4680
4383
|
source_default.yellow(
|
|
4681
4384
|
"No organization selected. Run " + source_default.white("npx mcp-use org switch") + " to pick one."
|
|
@@ -4683,9 +4386,9 @@ async function orgCurrentCommand() {
|
|
|
4683
4386
|
);
|
|
4684
4387
|
return;
|
|
4685
4388
|
}
|
|
4686
|
-
const slug = config.
|
|
4389
|
+
const slug = config.orgSlug ? source_default.gray(` (${config.orgSlug})`) : "";
|
|
4687
4390
|
console.log(
|
|
4688
|
-
source_default.cyan.bold("\u{1F3E2} Active organization: ") + source_default.white(config.
|
|
4391
|
+
source_default.cyan.bold("\u{1F3E2} Active organization: ") + source_default.white(config.orgName || config.orgId) + slug
|
|
4689
4392
|
);
|
|
4690
4393
|
} catch (error) {
|
|
4691
4394
|
console.error(
|