@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.js
CHANGED
|
@@ -1147,14 +1147,21 @@ async function ensureConfigDir() {
|
|
|
1147
1147
|
async function readConfig() {
|
|
1148
1148
|
try {
|
|
1149
1149
|
const content = await fs7.readFile(CONFIG_FILE, "utf-8");
|
|
1150
|
-
|
|
1150
|
+
const raw = JSON.parse(content);
|
|
1151
|
+
return {
|
|
1152
|
+
...raw,
|
|
1153
|
+
orgId: raw.orgId ?? raw.profileId,
|
|
1154
|
+
orgName: raw.orgName ?? raw.profileName,
|
|
1155
|
+
orgSlug: raw.orgSlug ?? raw.profileSlug
|
|
1156
|
+
};
|
|
1151
1157
|
} catch (error) {
|
|
1152
1158
|
return {};
|
|
1153
1159
|
}
|
|
1154
1160
|
}
|
|
1155
1161
|
async function writeConfig(config) {
|
|
1156
1162
|
await ensureConfigDir();
|
|
1157
|
-
|
|
1163
|
+
const { profileId: _a, profileName: _b, profileSlug: _c, ...clean } = config;
|
|
1164
|
+
await fs7.writeFile(CONFIG_FILE, JSON.stringify(clean, null, 2), "utf-8");
|
|
1158
1165
|
}
|
|
1159
1166
|
async function deleteConfig() {
|
|
1160
1167
|
try {
|
|
@@ -1174,9 +1181,9 @@ async function isLoggedIn() {
|
|
|
1174
1181
|
const apiKey = await getApiKey();
|
|
1175
1182
|
return !!apiKey;
|
|
1176
1183
|
}
|
|
1177
|
-
async function
|
|
1184
|
+
async function getOrgId() {
|
|
1178
1185
|
const config = await readConfig();
|
|
1179
|
-
return config.
|
|
1186
|
+
return config.orgId || null;
|
|
1180
1187
|
}
|
|
1181
1188
|
async function getWebUrl() {
|
|
1182
1189
|
return DEFAULT_WEB_URL;
|
|
@@ -1190,30 +1197,21 @@ async function getAuthBaseUrl() {
|
|
|
1190
1197
|
var McpUseAPI = class _McpUseAPI {
|
|
1191
1198
|
baseUrl;
|
|
1192
1199
|
apiKey;
|
|
1193
|
-
|
|
1194
|
-
constructor(baseUrl, apiKey,
|
|
1200
|
+
orgId;
|
|
1201
|
+
constructor(baseUrl, apiKey, orgId) {
|
|
1195
1202
|
this.baseUrl = baseUrl || "";
|
|
1196
1203
|
this.apiKey = apiKey;
|
|
1197
|
-
this.
|
|
1204
|
+
this.orgId = orgId;
|
|
1198
1205
|
}
|
|
1199
|
-
/**
|
|
1200
|
-
* Initialize API client with config
|
|
1201
|
-
*/
|
|
1202
1206
|
static async create() {
|
|
1203
1207
|
const baseUrl = await getApiUrl();
|
|
1204
1208
|
const apiKey = await getApiKey();
|
|
1205
|
-
const
|
|
1206
|
-
return new _McpUseAPI(baseUrl, apiKey ?? void 0,
|
|
1209
|
+
const orgId = await getOrgId();
|
|
1210
|
+
return new _McpUseAPI(baseUrl, apiKey ?? void 0, orgId ?? void 0);
|
|
1207
1211
|
}
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
*/
|
|
1211
|
-
setProfileId(profileId) {
|
|
1212
|
-
this.profileId = profileId;
|
|
1212
|
+
setOrgId(orgId) {
|
|
1213
|
+
this.orgId = orgId;
|
|
1213
1214
|
}
|
|
1214
|
-
/**
|
|
1215
|
-
* Make authenticated request
|
|
1216
|
-
*/
|
|
1217
1215
|
async request(endpoint, options = {}) {
|
|
1218
1216
|
const url = `${this.baseUrl}${endpoint}`;
|
|
1219
1217
|
const headers = {
|
|
@@ -1223,8 +1221,8 @@ var McpUseAPI = class _McpUseAPI {
|
|
|
1223
1221
|
if (this.apiKey) {
|
|
1224
1222
|
headers["x-api-key"] = this.apiKey;
|
|
1225
1223
|
}
|
|
1226
|
-
if (this.
|
|
1227
|
-
headers["x-profile-id"] = this.
|
|
1224
|
+
if (this.orgId) {
|
|
1225
|
+
headers["x-profile-id"] = this.orgId;
|
|
1228
1226
|
}
|
|
1229
1227
|
const timeout = options.timeout || 3e4;
|
|
1230
1228
|
const controller = new AbortController();
|
|
@@ -1251,16 +1249,13 @@ var McpUseAPI = class _McpUseAPI {
|
|
|
1251
1249
|
} catch (error) {
|
|
1252
1250
|
clearTimeout(timeoutId);
|
|
1253
1251
|
if (error.name === "AbortError") {
|
|
1254
|
-
throw new Error(
|
|
1255
|
-
`Request timeout after ${timeout / 1e3}s. Try using --follow flag to stream logs instead.`
|
|
1256
|
-
);
|
|
1252
|
+
throw new Error(`Request timeout after ${timeout / 1e3}s.`);
|
|
1257
1253
|
}
|
|
1258
1254
|
throw error;
|
|
1259
1255
|
}
|
|
1260
1256
|
}
|
|
1261
1257
|
/**
|
|
1262
1258
|
* Create a persistent API key using a Better Auth access token.
|
|
1263
|
-
* Calls Better Auth's built-in POST /api/auth/api-key/create endpoint.
|
|
1264
1259
|
*/
|
|
1265
1260
|
async createApiKeyWithAccessToken(accessToken, name = "CLI") {
|
|
1266
1261
|
const authBase = await getAuthBaseUrl();
|
|
@@ -1279,255 +1274,120 @@ var McpUseAPI = class _McpUseAPI {
|
|
|
1279
1274
|
}
|
|
1280
1275
|
return response.json();
|
|
1281
1276
|
}
|
|
1282
|
-
|
|
1283
|
-
* Test authentication
|
|
1284
|
-
*/
|
|
1277
|
+
// ── Auth ────────────────────────────────────────────────────────
|
|
1285
1278
|
async testAuth() {
|
|
1286
|
-
|
|
1279
|
+
const wire = await this.request("/test-auth");
|
|
1280
|
+
return {
|
|
1281
|
+
message: wire.message,
|
|
1282
|
+
user_id: wire.user_id,
|
|
1283
|
+
email: wire.email,
|
|
1284
|
+
default_org_id: wire.default_profile_id,
|
|
1285
|
+
orgs: (wire.profiles ?? []).map((p) => ({
|
|
1286
|
+
id: p.id,
|
|
1287
|
+
name: p.profile_name,
|
|
1288
|
+
slug: p.slug,
|
|
1289
|
+
role: p.role
|
|
1290
|
+
}))
|
|
1291
|
+
};
|
|
1287
1292
|
}
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
*/
|
|
1291
|
-
async setDefaultProfile(profileId) {
|
|
1292
|
-
await this.request(`/profiles/${profileId}/set-default`, {
|
|
1293
|
+
async setDefaultOrg(orgId) {
|
|
1294
|
+
await this.request(`/organizations/${orgId}/set-default`, {
|
|
1293
1295
|
method: "POST"
|
|
1294
1296
|
});
|
|
1295
1297
|
}
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1298
|
+
// ── Organization ID resolution ──────────────────────────────────
|
|
1299
|
+
async resolveOrganizationId() {
|
|
1300
|
+
if (this.orgId) return this.orgId;
|
|
1301
|
+
const auth = await this.testAuth();
|
|
1302
|
+
const id = auth.default_org_id;
|
|
1303
|
+
if (!id) {
|
|
1304
|
+
throw new Error(
|
|
1305
|
+
"No organization set. Run `mcp-use org switch` or use --org to specify one."
|
|
1306
|
+
);
|
|
1307
|
+
}
|
|
1308
|
+
return id;
|
|
1309
|
+
}
|
|
1310
|
+
// ── Servers ─────────────────────────────────────────────────────
|
|
1311
|
+
async createServer(body) {
|
|
1312
|
+
return this.request("/servers", {
|
|
1313
|
+
method: "POST",
|
|
1314
|
+
body: JSON.stringify(body)
|
|
1315
|
+
});
|
|
1316
|
+
}
|
|
1317
|
+
// ── Deployments ─────────────────────────────────────────────────
|
|
1318
|
+
async createDeployment(input) {
|
|
1300
1319
|
return this.request("/deployments", {
|
|
1301
1320
|
method: "POST",
|
|
1302
|
-
body: JSON.stringify(
|
|
1321
|
+
body: JSON.stringify(input)
|
|
1303
1322
|
});
|
|
1304
1323
|
}
|
|
1305
|
-
/**
|
|
1306
|
-
* Get deployment by ID
|
|
1307
|
-
*/
|
|
1308
1324
|
async getDeployment(deploymentId) {
|
|
1309
1325
|
return this.request(`/deployments/${deploymentId}`);
|
|
1310
1326
|
}
|
|
1311
|
-
/**
|
|
1312
|
-
* Stream deployment logs
|
|
1313
|
-
*/
|
|
1314
|
-
async *streamDeploymentLogs(deploymentId) {
|
|
1315
|
-
const url = `${this.baseUrl}/deployments/${deploymentId}/logs/stream`;
|
|
1316
|
-
const headers = {};
|
|
1317
|
-
if (this.apiKey) {
|
|
1318
|
-
headers["x-api-key"] = this.apiKey;
|
|
1319
|
-
}
|
|
1320
|
-
if (this.profileId) {
|
|
1321
|
-
headers["x-profile-id"] = this.profileId;
|
|
1322
|
-
}
|
|
1323
|
-
const response = await fetch(url, { headers });
|
|
1324
|
-
if (!response.ok) {
|
|
1325
|
-
throw new Error(`Failed to stream logs: ${response.status}`);
|
|
1326
|
-
}
|
|
1327
|
-
if (!response.body) {
|
|
1328
|
-
throw new Error("Response body is null");
|
|
1329
|
-
}
|
|
1330
|
-
const reader = response.body.getReader();
|
|
1331
|
-
const decoder = new TextDecoder();
|
|
1332
|
-
let buffer = "";
|
|
1333
|
-
try {
|
|
1334
|
-
while (true) {
|
|
1335
|
-
const { done, value } = await reader.read();
|
|
1336
|
-
if (done) break;
|
|
1337
|
-
buffer += decoder.decode(value, { stream: true });
|
|
1338
|
-
const lines = buffer.split("\n");
|
|
1339
|
-
buffer = lines.pop() || "";
|
|
1340
|
-
for (const line of lines) {
|
|
1341
|
-
if (line.startsWith("data: ")) {
|
|
1342
|
-
const data = line.slice(6);
|
|
1343
|
-
try {
|
|
1344
|
-
const parsed = JSON.parse(data);
|
|
1345
|
-
if (parsed.log) {
|
|
1346
|
-
yield parsed.log;
|
|
1347
|
-
} else if (parsed.error) {
|
|
1348
|
-
throw new Error(parsed.error);
|
|
1349
|
-
}
|
|
1350
|
-
} catch (e) {
|
|
1351
|
-
}
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
}
|
|
1355
|
-
} finally {
|
|
1356
|
-
reader.releaseLock();
|
|
1357
|
-
}
|
|
1358
|
-
}
|
|
1359
|
-
/**
|
|
1360
|
-
* Create deployment with source code upload
|
|
1361
|
-
*/
|
|
1362
|
-
async createDeploymentWithUpload(request, filePath) {
|
|
1363
|
-
const { readFile: readFile4 } = await import("fs/promises");
|
|
1364
|
-
const { basename } = await import("path");
|
|
1365
|
-
const { stat } = await import("fs/promises");
|
|
1366
|
-
const stats = await stat(filePath);
|
|
1367
|
-
const maxSize = 2 * 1024 * 1024;
|
|
1368
|
-
if (stats.size > maxSize) {
|
|
1369
|
-
throw new Error(
|
|
1370
|
-
`File size (${(stats.size / 1024 / 1024).toFixed(2)}MB) exceeds maximum of 2MB`
|
|
1371
|
-
);
|
|
1372
|
-
}
|
|
1373
|
-
const fileBuffer = await readFile4(filePath);
|
|
1374
|
-
const filename = basename(filePath);
|
|
1375
|
-
const formData = new FormData();
|
|
1376
|
-
const blob = new Blob([fileBuffer], { type: "application/gzip" });
|
|
1377
|
-
formData.append("source_file", blob, filename);
|
|
1378
|
-
formData.append("name", request.name);
|
|
1379
|
-
formData.append("source_type", "upload");
|
|
1380
|
-
if (request.source.type === "upload") {
|
|
1381
|
-
formData.append("runtime", request.source.runtime || "node");
|
|
1382
|
-
formData.append("port", String(request.source.port || 3e3));
|
|
1383
|
-
if (request.source.startCommand) {
|
|
1384
|
-
formData.append("startCommand", request.source.startCommand);
|
|
1385
|
-
}
|
|
1386
|
-
if (request.source.buildCommand) {
|
|
1387
|
-
formData.append("buildCommand", request.source.buildCommand);
|
|
1388
|
-
}
|
|
1389
|
-
if (request.source.env && Object.keys(request.source.env).length > 0) {
|
|
1390
|
-
formData.append("env", JSON.stringify(request.source.env));
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1393
|
-
if (request.customDomain) {
|
|
1394
|
-
formData.append("customDomain", request.customDomain);
|
|
1395
|
-
}
|
|
1396
|
-
if (request.healthCheckPath) {
|
|
1397
|
-
formData.append("healthCheckPath", request.healthCheckPath);
|
|
1398
|
-
}
|
|
1399
|
-
const url = `${this.baseUrl}/deployments`;
|
|
1400
|
-
const headers = {};
|
|
1401
|
-
if (this.apiKey) {
|
|
1402
|
-
headers["x-api-key"] = this.apiKey;
|
|
1403
|
-
}
|
|
1404
|
-
if (this.profileId) {
|
|
1405
|
-
headers["x-profile-id"] = this.profileId;
|
|
1406
|
-
}
|
|
1407
|
-
const response = await fetch(url, {
|
|
1408
|
-
method: "POST",
|
|
1409
|
-
headers,
|
|
1410
|
-
body: formData
|
|
1411
|
-
});
|
|
1412
|
-
if (!response.ok) {
|
|
1413
|
-
const error = await response.text();
|
|
1414
|
-
throw new Error(`Deployment failed: ${error}`);
|
|
1415
|
-
}
|
|
1416
|
-
return response.json();
|
|
1417
|
-
}
|
|
1418
|
-
/**
|
|
1419
|
-
* List all deployments
|
|
1420
|
-
*/
|
|
1421
1327
|
async listDeployments() {
|
|
1422
|
-
|
|
1423
|
-
return response.deployments;
|
|
1328
|
+
return this.request("/deployments");
|
|
1424
1329
|
}
|
|
1425
|
-
/**
|
|
1426
|
-
* Delete deployment
|
|
1427
|
-
*/
|
|
1428
1330
|
async deleteDeployment(deploymentId) {
|
|
1429
1331
|
await this.request(`/deployments/${deploymentId}`, {
|
|
1430
1332
|
method: "DELETE"
|
|
1431
1333
|
});
|
|
1432
1334
|
}
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
async updateDeployment(deploymentId, updates) {
|
|
1437
|
-
return this.request(`/deployments/${deploymentId}`, {
|
|
1438
|
-
method: "PATCH",
|
|
1439
|
-
body: JSON.stringify(updates)
|
|
1440
|
-
});
|
|
1441
|
-
}
|
|
1442
|
-
/**
|
|
1443
|
-
* Redeploy deployment
|
|
1444
|
-
*
|
|
1445
|
-
* @param deploymentId - The deployment ID to redeploy
|
|
1446
|
-
* @param configOrFilePath - Either a RedeploymentConfig object with updated settings,
|
|
1447
|
-
* or a file path string for source code upload
|
|
1448
|
-
*/
|
|
1449
|
-
async redeployDeployment(deploymentId, configOrFilePath) {
|
|
1450
|
-
if (typeof configOrFilePath === "string") {
|
|
1451
|
-
const filePath = configOrFilePath;
|
|
1452
|
-
const { readFile: readFile4 } = await import("fs/promises");
|
|
1453
|
-
const { basename } = await import("path");
|
|
1454
|
-
const { stat } = await import("fs/promises");
|
|
1455
|
-
const stats = await stat(filePath);
|
|
1456
|
-
const maxSize = 2 * 1024 * 1024;
|
|
1457
|
-
if (stats.size > maxSize) {
|
|
1458
|
-
throw new Error(
|
|
1459
|
-
`File size (${(stats.size / 1024 / 1024).toFixed(2)}MB) exceeds maximum of 2MB`
|
|
1460
|
-
);
|
|
1461
|
-
}
|
|
1462
|
-
const fileBuffer = await readFile4(filePath);
|
|
1463
|
-
const formData = new FormData();
|
|
1464
|
-
const blob = new Blob([fileBuffer], { type: "application/gzip" });
|
|
1465
|
-
formData.append("source_file", blob, basename(filePath));
|
|
1466
|
-
const headers = {};
|
|
1467
|
-
if (this.apiKey) headers["x-api-key"] = this.apiKey;
|
|
1468
|
-
if (this.profileId) headers["x-profile-id"] = this.profileId;
|
|
1469
|
-
const response = await fetch(
|
|
1470
|
-
`${this.baseUrl}/deployments/${deploymentId}/redeploy`,
|
|
1471
|
-
{
|
|
1472
|
-
method: "POST",
|
|
1473
|
-
headers,
|
|
1474
|
-
body: formData
|
|
1475
|
-
}
|
|
1476
|
-
);
|
|
1477
|
-
if (!response.ok) {
|
|
1478
|
-
const error = await response.text();
|
|
1479
|
-
throw new Error(`Redeploy failed: ${error}`);
|
|
1480
|
-
}
|
|
1481
|
-
return response.json();
|
|
1482
|
-
}
|
|
1483
|
-
const config = configOrFilePath;
|
|
1484
|
-
return this.request(`/deployments/${deploymentId}/redeploy`, {
|
|
1485
|
-
method: "POST",
|
|
1486
|
-
body: config ? JSON.stringify(config) : void 0
|
|
1335
|
+
async stopDeployment(deploymentId) {
|
|
1336
|
+
await this.request(`/deployments/${deploymentId}/stop`, {
|
|
1337
|
+
method: "POST"
|
|
1487
1338
|
});
|
|
1488
1339
|
}
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
async getDeploymentLogs(deploymentId) {
|
|
1493
|
-
const response = await this.request(
|
|
1494
|
-
`/deployments/${deploymentId}/logs`,
|
|
1340
|
+
async getDeploymentLogs(deploymentId, lines = 500) {
|
|
1341
|
+
const resp = await this.request(
|
|
1342
|
+
`/deployments/${deploymentId}/logs?lines=${lines}`,
|
|
1495
1343
|
{ timeout: 6e4 }
|
|
1496
|
-
// 60 second timeout for logs
|
|
1497
1344
|
);
|
|
1498
|
-
return
|
|
1345
|
+
return resp.logs;
|
|
1499
1346
|
}
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
async getDeploymentBuildLogs(deploymentId) {
|
|
1504
|
-
const response = await this.request(
|
|
1505
|
-
`/deployments/${deploymentId}/logs/build`,
|
|
1347
|
+
async getDeploymentBuildLogs(deploymentId, offset = 0) {
|
|
1348
|
+
return this.request(
|
|
1349
|
+
`/deployments/${deploymentId}/build-logs?offset=${offset}`,
|
|
1506
1350
|
{ timeout: 6e4 }
|
|
1507
|
-
// 60 second timeout for logs
|
|
1508
1351
|
);
|
|
1509
|
-
return response.data.logs;
|
|
1510
1352
|
}
|
|
1511
|
-
|
|
1512
|
-
* Get GitHub connection status
|
|
1513
|
-
*/
|
|
1353
|
+
// ── GitHub ──────────────────────────────────────────────────────
|
|
1514
1354
|
async getGitHubConnectionStatus() {
|
|
1515
|
-
|
|
1355
|
+
const orgId = await this.resolveOrganizationId();
|
|
1356
|
+
const resp = await this.request(`/github/installations?organizationId=${orgId}`);
|
|
1357
|
+
return {
|
|
1358
|
+
is_connected: resp.installations.length > 0,
|
|
1359
|
+
installations: resp.installations.map((i) => ({
|
|
1360
|
+
id: i.id,
|
|
1361
|
+
installation_id: i.installationId
|
|
1362
|
+
}))
|
|
1363
|
+
};
|
|
1516
1364
|
}
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1365
|
+
async getGitHubRepos(_refresh) {
|
|
1366
|
+
const orgId = await this.resolveOrganizationId();
|
|
1367
|
+
const installResp = await this.request(`/github/installations?organizationId=${orgId}`);
|
|
1368
|
+
if (installResp.installations.length === 0) {
|
|
1369
|
+
return { user: { login: "", id: 0, avatar_url: "" }, repos: [] };
|
|
1370
|
+
}
|
|
1371
|
+
const inst = installResp.installations[0];
|
|
1372
|
+
const reposResp = await this.request(`/github/installations/${inst.installationId}/repos`);
|
|
1373
|
+
return {
|
|
1374
|
+
user: {
|
|
1375
|
+
login: inst.account?.login ?? "",
|
|
1376
|
+
id: 0,
|
|
1377
|
+
avatar_url: inst.account?.avatar_url ?? ""
|
|
1378
|
+
},
|
|
1379
|
+
repos: reposResp.repos.map((r) => ({
|
|
1380
|
+
id: r.id,
|
|
1381
|
+
name: r.name,
|
|
1382
|
+
full_name: r.fullName,
|
|
1383
|
+
private: r.private,
|
|
1384
|
+
owner: { login: r.fullName.split("/")[0] ?? "" }
|
|
1385
|
+
}))
|
|
1386
|
+
};
|
|
1523
1387
|
}
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
async getGitHubRepos(refresh = false) {
|
|
1528
|
-
return this.request(
|
|
1529
|
-
`/github/repos${refresh ? "?refresh=true" : ""}`
|
|
1530
|
-
);
|
|
1388
|
+
async getGitHubAppName() {
|
|
1389
|
+
if (process.env.MCP_GITHUB_APP_NAME) return process.env.MCP_GITHUB_APP_NAME;
|
|
1390
|
+
return this.baseUrl.includes(".dev.") ? "mcp-use-dev" : "mcp-use";
|
|
1531
1391
|
}
|
|
1532
1392
|
};
|
|
1533
1393
|
|
|
@@ -1592,19 +1452,17 @@ async function pollForDeviceToken(authBaseUrl, deviceCode, intervalSeconds) {
|
|
|
1592
1452
|
}
|
|
1593
1453
|
throw new Error("Login timed out. Please try again.");
|
|
1594
1454
|
}
|
|
1595
|
-
async function promptOrgSelection(
|
|
1596
|
-
if (
|
|
1597
|
-
if (
|
|
1598
|
-
return
|
|
1455
|
+
async function promptOrgSelection(orgs, defaultOrgId) {
|
|
1456
|
+
if (orgs.length === 0) return null;
|
|
1457
|
+
if (orgs.length === 1) {
|
|
1458
|
+
return orgs[0];
|
|
1599
1459
|
}
|
|
1600
1460
|
console.log(source_default.cyan.bold("\n\u{1F3E2} Select an organization:\n"));
|
|
1601
|
-
for (let i = 0; i <
|
|
1602
|
-
const
|
|
1603
|
-
const marker =
|
|
1604
|
-
const slug =
|
|
1605
|
-
console.log(
|
|
1606
|
-
` ${source_default.white(`${i + 1}.`)} ${p.profile_name}${slug}${marker}`
|
|
1607
|
-
);
|
|
1461
|
+
for (let i = 0; i < orgs.length; i++) {
|
|
1462
|
+
const o = orgs[i];
|
|
1463
|
+
const marker = o.id === defaultOrgId ? source_default.green(" (current)") : "";
|
|
1464
|
+
const slug = o.slug ? source_default.gray(` (${o.slug})`) : "";
|
|
1465
|
+
console.log(` ${source_default.white(`${i + 1}.`)} ${o.name}${slug}${marker}`);
|
|
1608
1466
|
}
|
|
1609
1467
|
const readline = await import("readline");
|
|
1610
1468
|
const rl = readline.createInterface({
|
|
@@ -1612,7 +1470,7 @@ async function promptOrgSelection(profiles, defaultProfileId) {
|
|
|
1612
1470
|
output: process.stdout
|
|
1613
1471
|
});
|
|
1614
1472
|
return new Promise((resolve2) => {
|
|
1615
|
-
const defaultIdx =
|
|
1473
|
+
const defaultIdx = defaultOrgId ? orgs.findIndex((o) => o.id === defaultOrgId) : 0;
|
|
1616
1474
|
const defaultDisplay = defaultIdx >= 0 ? defaultIdx + 1 : 1;
|
|
1617
1475
|
rl.question(
|
|
1618
1476
|
source_default.gray(`
|
|
@@ -1621,11 +1479,11 @@ Enter number [${defaultDisplay}]: `),
|
|
|
1621
1479
|
rl.close();
|
|
1622
1480
|
const trimmed = answer.trim();
|
|
1623
1481
|
const idx = trimmed === "" ? defaultIdx : parseInt(trimmed, 10) - 1;
|
|
1624
|
-
if (idx >= 0 && idx <
|
|
1625
|
-
resolve2(
|
|
1482
|
+
if (idx >= 0 && idx < orgs.length) {
|
|
1483
|
+
resolve2(orgs[idx]);
|
|
1626
1484
|
} else {
|
|
1627
1485
|
console.log(source_default.yellow("Invalid selection, using default."));
|
|
1628
|
-
resolve2(
|
|
1486
|
+
resolve2(orgs[defaultIdx >= 0 ? defaultIdx : 0]);
|
|
1629
1487
|
}
|
|
1630
1488
|
}
|
|
1631
1489
|
);
|
|
@@ -1704,28 +1562,25 @@ async function loginCommand(options) {
|
|
|
1704
1562
|
const masked = storedKey.substring(0, 8) + "...";
|
|
1705
1563
|
console.log(source_default.white(" API Key: ") + source_default.gray(masked));
|
|
1706
1564
|
}
|
|
1707
|
-
const
|
|
1708
|
-
if (
|
|
1709
|
-
let
|
|
1710
|
-
if (
|
|
1711
|
-
|
|
1565
|
+
const orgs = authInfo.orgs ?? [];
|
|
1566
|
+
if (orgs.length > 0) {
|
|
1567
|
+
let selectedOrg = null;
|
|
1568
|
+
if (orgs.length === 1) {
|
|
1569
|
+
selectedOrg = orgs[0];
|
|
1712
1570
|
} else {
|
|
1713
|
-
|
|
1714
|
-
profiles,
|
|
1715
|
-
authInfo.default_profile_id
|
|
1716
|
-
);
|
|
1571
|
+
selectedOrg = await promptOrgSelection(orgs, authInfo.default_org_id);
|
|
1717
1572
|
}
|
|
1718
|
-
if (
|
|
1573
|
+
if (selectedOrg) {
|
|
1719
1574
|
const config = await readConfig();
|
|
1720
1575
|
await writeConfig({
|
|
1721
1576
|
...config,
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1577
|
+
orgId: selectedOrg.id,
|
|
1578
|
+
orgName: selectedOrg.name,
|
|
1579
|
+
orgSlug: selectedOrg.slug ?? void 0
|
|
1725
1580
|
});
|
|
1726
|
-
const slug =
|
|
1581
|
+
const slug = selectedOrg.slug ? source_default.gray(` (${selectedOrg.slug})`) : "";
|
|
1727
1582
|
console.log(
|
|
1728
|
-
source_default.white(" Org: ") + source_default.cyan(
|
|
1583
|
+
source_default.white(" Org: ") + source_default.cyan(selectedOrg.name) + slug
|
|
1729
1584
|
);
|
|
1730
1585
|
}
|
|
1731
1586
|
}
|
|
@@ -1795,22 +1650,22 @@ async function whoamiCommand() {
|
|
|
1795
1650
|
console.log(source_default.white("API Key: ") + source_default.gray(masked));
|
|
1796
1651
|
}
|
|
1797
1652
|
const config = await readConfig();
|
|
1798
|
-
const
|
|
1799
|
-
if (
|
|
1800
|
-
const
|
|
1801
|
-
(
|
|
1653
|
+
const orgs = authInfo.orgs ?? [];
|
|
1654
|
+
if (orgs.length > 0) {
|
|
1655
|
+
const activeOrg = orgs.find(
|
|
1656
|
+
(o) => o.id === (config.orgId || authInfo.default_org_id)
|
|
1802
1657
|
);
|
|
1803
|
-
if (
|
|
1804
|
-
const slug =
|
|
1658
|
+
if (activeOrg) {
|
|
1659
|
+
const slug = activeOrg.slug ? source_default.gray(` (${activeOrg.slug})`) : "";
|
|
1805
1660
|
console.log(
|
|
1806
|
-
source_default.white("Org: ") + source_default.cyan(
|
|
1661
|
+
source_default.white("Org: ") + source_default.cyan(activeOrg.name) + slug
|
|
1807
1662
|
);
|
|
1808
1663
|
}
|
|
1809
|
-
if (
|
|
1664
|
+
if (orgs.length > 1) {
|
|
1810
1665
|
console.log(
|
|
1811
1666
|
source_default.gray(
|
|
1812
1667
|
`
|
|
1813
|
-
${
|
|
1668
|
+
${orgs.length} organizations available. Use ` + source_default.white("npx mcp-use org list") + " to see all."
|
|
1814
1669
|
)
|
|
1815
1670
|
);
|
|
1816
1671
|
}
|
|
@@ -3205,25 +3060,20 @@ async function prompt(question, defaultValue = "n") {
|
|
|
3205
3060
|
});
|
|
3206
3061
|
}
|
|
3207
3062
|
function getMcpServerUrl(deployment) {
|
|
3208
|
-
if (deployment.
|
|
3209
|
-
return
|
|
3210
|
-
}
|
|
3211
|
-
|
|
3212
|
-
} else if (deployment.serverId) {
|
|
3063
|
+
if (deployment.mcpUrl) {
|
|
3064
|
+
return deployment.mcpUrl;
|
|
3065
|
+
}
|
|
3066
|
+
if (deployment.serverId) {
|
|
3213
3067
|
return buildGatewayUrl(deployment.serverId);
|
|
3214
|
-
} else {
|
|
3215
|
-
return `https://${deployment.domain}/mcp`;
|
|
3216
3068
|
}
|
|
3069
|
+
return "";
|
|
3217
3070
|
}
|
|
3218
|
-
async function displayDeploymentProgress(api,
|
|
3071
|
+
async function displayDeploymentProgress(api, deploymentId, progressOptions) {
|
|
3219
3072
|
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
3220
3073
|
let frameIndex = 0;
|
|
3221
3074
|
let spinnerInterval = null;
|
|
3222
|
-
let lastStep = "";
|
|
3223
3075
|
const startSpinner = (message) => {
|
|
3224
|
-
if (spinnerInterval)
|
|
3225
|
-
clearInterval(spinnerInterval);
|
|
3226
|
-
}
|
|
3076
|
+
if (spinnerInterval) clearInterval(spinnerInterval);
|
|
3227
3077
|
process.stdout.write("\r\x1B[K");
|
|
3228
3078
|
spinnerInterval = setInterval(() => {
|
|
3229
3079
|
const frame = frames[frameIndex];
|
|
@@ -3242,82 +3092,64 @@ async function displayDeploymentProgress(api, deployment, progressOptions) {
|
|
|
3242
3092
|
};
|
|
3243
3093
|
console.log();
|
|
3244
3094
|
startSpinner("Deploying...");
|
|
3245
|
-
try {
|
|
3246
|
-
for await (const log of api.streamDeploymentLogs(deployment.id)) {
|
|
3247
|
-
try {
|
|
3248
|
-
const logData = JSON.parse(log);
|
|
3249
|
-
if (logData.step && logData.step !== lastStep) {
|
|
3250
|
-
lastStep = logData.step;
|
|
3251
|
-
const stepMessages = {
|
|
3252
|
-
clone: "Preparing source code...",
|
|
3253
|
-
analyze: "Analyzing project...",
|
|
3254
|
-
build: "Building container image...",
|
|
3255
|
-
deploy: "Deploying to cloud..."
|
|
3256
|
-
};
|
|
3257
|
-
const message = stepMessages[logData.step] || "Deploying...";
|
|
3258
|
-
startSpinner(message);
|
|
3259
|
-
}
|
|
3260
|
-
if (logData.line) {
|
|
3261
|
-
stopSpinner();
|
|
3262
|
-
const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
|
|
3263
|
-
const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
|
|
3264
|
-
console.log(stepPrefix + levelColor(logData.line));
|
|
3265
|
-
}
|
|
3266
|
-
} catch {
|
|
3267
|
-
}
|
|
3268
|
-
}
|
|
3269
|
-
} catch (error) {
|
|
3270
|
-
stopSpinner();
|
|
3271
|
-
}
|
|
3272
3095
|
let checkCount = 0;
|
|
3273
|
-
const maxChecks =
|
|
3274
|
-
let delay =
|
|
3096
|
+
const maxChecks = 120;
|
|
3097
|
+
let delay = 2e3;
|
|
3275
3098
|
const maxDelay = 1e4;
|
|
3276
|
-
let
|
|
3099
|
+
let buildLogOffset = 0;
|
|
3100
|
+
const sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
3277
3101
|
while (checkCount < maxChecks) {
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3102
|
+
await sleep(delay);
|
|
3103
|
+
checkCount++;
|
|
3104
|
+
try {
|
|
3105
|
+
const buildLogsResp = await api.getDeploymentBuildLogs(
|
|
3106
|
+
deploymentId,
|
|
3107
|
+
buildLogOffset
|
|
3284
3108
|
);
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3109
|
+
if (buildLogsResp.logs.length > 0) {
|
|
3110
|
+
const logLines = buildLogsResp.logs.split("\n").filter((l) => l.trim());
|
|
3111
|
+
for (const line of logLines) {
|
|
3112
|
+
try {
|
|
3113
|
+
const logData = JSON.parse(line);
|
|
3114
|
+
if (logData.line) {
|
|
3115
|
+
stopSpinner();
|
|
3116
|
+
const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
|
|
3117
|
+
const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
|
|
3118
|
+
console.log(stepPrefix + levelColor(logData.line));
|
|
3119
|
+
}
|
|
3120
|
+
} catch {
|
|
3290
3121
|
stopSpinner();
|
|
3291
|
-
|
|
3292
|
-
const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
|
|
3293
|
-
console.log(stepPrefix + levelColor(logData.line));
|
|
3122
|
+
console.log(source_default.gray(line));
|
|
3294
3123
|
}
|
|
3295
|
-
} catch {
|
|
3296
3124
|
}
|
|
3125
|
+
buildLogOffset = buildLogsResp.offset;
|
|
3297
3126
|
}
|
|
3298
|
-
|
|
3127
|
+
} catch {
|
|
3299
3128
|
}
|
|
3300
|
-
|
|
3301
|
-
|
|
3129
|
+
const deployment = await api.getDeployment(deploymentId);
|
|
3130
|
+
if (deployment.status === "running") {
|
|
3131
|
+
stopSpinner();
|
|
3132
|
+
const mcpServerUrl = getMcpServerUrl(deployment);
|
|
3302
3133
|
let dashboardUrl = null;
|
|
3303
3134
|
const webUrl = (await getWebUrl()).replace(/\/$/, "");
|
|
3304
3135
|
const config = await readConfig();
|
|
3305
|
-
const orgSlug = config.
|
|
3306
|
-
|
|
3307
|
-
if (serverRef) {
|
|
3136
|
+
const orgSlug = config.orgSlug;
|
|
3137
|
+
if (deployment.serverId) {
|
|
3308
3138
|
if (orgSlug) {
|
|
3309
|
-
dashboardUrl = `${webUrl}/cloud/${orgSlug}/servers/${
|
|
3139
|
+
dashboardUrl = `${webUrl}/cloud/${orgSlug}/servers/${deployment.serverId}`;
|
|
3310
3140
|
} else {
|
|
3311
|
-
dashboardUrl = `${webUrl}/cloud/servers/${
|
|
3141
|
+
dashboardUrl = `${webUrl}/cloud/servers/${deployment.serverId}`;
|
|
3312
3142
|
}
|
|
3313
3143
|
}
|
|
3314
3144
|
const inspectorUrl = `https://inspector.manufact.com/inspector?autoConnect=${encodeURIComponent(
|
|
3315
3145
|
mcpServerUrl
|
|
3316
3146
|
)}`;
|
|
3317
3147
|
console.log(source_default.green.bold("\u2713 Deployment successful!\n"));
|
|
3318
|
-
|
|
3319
|
-
|
|
3148
|
+
if (mcpServerUrl) {
|
|
3149
|
+
console.log(source_default.white("\u{1F310} MCP Server URL:"));
|
|
3150
|
+
console.log(source_default.cyan.bold(` ${mcpServerUrl}
|
|
3320
3151
|
`));
|
|
3152
|
+
}
|
|
3321
3153
|
if (dashboardUrl) {
|
|
3322
3154
|
console.log(source_default.white("\u{1F4CA} Dashboard:"));
|
|
3323
3155
|
console.log(source_default.cyan.bold(` ${dashboardUrl}
|
|
@@ -3326,16 +3158,14 @@ async function displayDeploymentProgress(api, deployment, progressOptions) {
|
|
|
3326
3158
|
console.log(source_default.white("\u{1F50D} Inspector URL:"));
|
|
3327
3159
|
console.log(source_default.cyan.bold(` ${inspectorUrl}
|
|
3328
3160
|
`));
|
|
3329
|
-
console.log(
|
|
3330
|
-
source_default.gray("Deployment ID: ") + source_default.white(finalDeployment.id)
|
|
3331
|
-
);
|
|
3161
|
+
console.log(source_default.gray("Deployment ID: ") + source_default.white(deployment.id));
|
|
3332
3162
|
return;
|
|
3333
|
-
} else if (
|
|
3163
|
+
} else if (deployment.status === "failed") {
|
|
3334
3164
|
stopSpinner();
|
|
3335
3165
|
console.log(source_default.red.bold("\u2717 Deployment failed\n"));
|
|
3336
|
-
if (
|
|
3337
|
-
console.log(source_default.red("Error: ") +
|
|
3338
|
-
if (
|
|
3166
|
+
if (deployment.error) {
|
|
3167
|
+
console.log(source_default.red("Error: ") + deployment.error);
|
|
3168
|
+
if (deployment.error.includes("No GitHub installations found")) {
|
|
3339
3169
|
console.log();
|
|
3340
3170
|
const retry = await promptGitHubInstallation(
|
|
3341
3171
|
api,
|
|
@@ -3343,79 +3173,31 @@ async function displayDeploymentProgress(api, deployment, progressOptions) {
|
|
|
3343
3173
|
void 0,
|
|
3344
3174
|
{ yes: progressOptions?.yes }
|
|
3345
3175
|
);
|
|
3346
|
-
if (retry) {
|
|
3176
|
+
if (retry && deployment.serverId) {
|
|
3347
3177
|
console.log(source_default.cyan("\n\u{1F504} Retrying deployment...\n"));
|
|
3348
|
-
const
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
);
|
|
3354
|
-
return;
|
|
3355
|
-
}
|
|
3356
|
-
} else if (finalDeployment.error.includes("Authenticated git clone failed")) {
|
|
3357
|
-
let repoName;
|
|
3358
|
-
const repoMatch = finalDeployment.error.match(
|
|
3359
|
-
/github\.com\/([^/]+\/[^/\s]+)/
|
|
3360
|
-
);
|
|
3361
|
-
if (repoMatch) {
|
|
3362
|
-
repoName = repoMatch[1].replace(/\.git$/, "");
|
|
3363
|
-
} else if (finalDeployment.source.type === "github") {
|
|
3364
|
-
repoName = finalDeployment.source.repo;
|
|
3365
|
-
}
|
|
3366
|
-
console.log();
|
|
3367
|
-
const retry = await promptGitHubInstallation(
|
|
3368
|
-
api,
|
|
3369
|
-
"no_access",
|
|
3370
|
-
repoName,
|
|
3371
|
-
{ yes: progressOptions?.yes }
|
|
3372
|
-
);
|
|
3373
|
-
if (retry) {
|
|
3374
|
-
console.log(source_default.cyan("\n\u{1F504} Retrying deployment...\n"));
|
|
3375
|
-
const newDeployment = await api.redeployDeployment(deployment.id);
|
|
3376
|
-
await displayDeploymentProgress(
|
|
3377
|
-
api,
|
|
3378
|
-
newDeployment,
|
|
3379
|
-
progressOptions
|
|
3380
|
-
);
|
|
3178
|
+
const newDep = await api.createDeployment({
|
|
3179
|
+
serverId: deployment.serverId,
|
|
3180
|
+
trigger: "redeploy"
|
|
3181
|
+
});
|
|
3182
|
+
await displayDeploymentProgress(api, newDep.id, progressOptions);
|
|
3381
3183
|
return;
|
|
3382
3184
|
}
|
|
3383
3185
|
}
|
|
3384
3186
|
}
|
|
3385
|
-
if (finalDeployment.buildLogs) {
|
|
3386
|
-
console.log(source_default.gray("\nBuild logs:"));
|
|
3387
|
-
try {
|
|
3388
|
-
const logs = finalDeployment.buildLogs.split("\n").filter((l) => l.trim());
|
|
3389
|
-
for (const log of logs) {
|
|
3390
|
-
try {
|
|
3391
|
-
const logData = JSON.parse(log);
|
|
3392
|
-
if (logData.line) {
|
|
3393
|
-
console.log(source_default.gray(` ${logData.line}`));
|
|
3394
|
-
}
|
|
3395
|
-
} catch {
|
|
3396
|
-
console.log(source_default.gray(` ${log}`));
|
|
3397
|
-
}
|
|
3398
|
-
}
|
|
3399
|
-
} catch {
|
|
3400
|
-
console.log(source_default.gray(finalDeployment.buildLogs));
|
|
3401
|
-
}
|
|
3402
|
-
}
|
|
3403
3187
|
process.exit(1);
|
|
3404
|
-
} else if (
|
|
3188
|
+
} else if (deployment.status === "building" || deployment.status === "pending") {
|
|
3405
3189
|
startSpinner("Building and deploying...");
|
|
3406
|
-
checkCount++;
|
|
3407
3190
|
delay = Math.min(delay * 1.2, maxDelay);
|
|
3408
3191
|
} else {
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
);
|
|
3192
|
+
stopSpinner();
|
|
3193
|
+
console.log(source_default.yellow("\u26A0\uFE0F Deployment status: ") + deployment.status);
|
|
3412
3194
|
return;
|
|
3413
3195
|
}
|
|
3414
3196
|
}
|
|
3415
3197
|
stopSpinner();
|
|
3416
3198
|
console.log(source_default.yellow("\u26A0\uFE0F Deployment is taking longer than expected."));
|
|
3417
3199
|
console.log(
|
|
3418
|
-
source_default.gray("Check status with: ") + source_default.white(`mcp-use
|
|
3200
|
+
source_default.gray("Check status with: ") + source_default.white(`mcp-use deployments get ${deploymentId}`)
|
|
3419
3201
|
);
|
|
3420
3202
|
}
|
|
3421
3203
|
async function checkRepoAccess(api, owner, repo) {
|
|
@@ -3501,7 +3283,7 @@ async function promptGitHubInstallation(api, reason, repoName, opts) {
|
|
|
3501
3283
|
return false;
|
|
3502
3284
|
}
|
|
3503
3285
|
try {
|
|
3504
|
-
const appName =
|
|
3286
|
+
const appName = await api.getGitHubAppName();
|
|
3505
3287
|
const installUrl = reason === "not_connected" ? `https://github.com/apps/${appName}/installations/new` : `https://github.com/settings/installations`;
|
|
3506
3288
|
console.log(
|
|
3507
3289
|
source_default.cyan(
|
|
@@ -3781,14 +3563,14 @@ async function deployCommand(options) {
|
|
|
3781
3563
|
if (options.org) {
|
|
3782
3564
|
try {
|
|
3783
3565
|
const authInfo = await api.testAuth();
|
|
3784
|
-
const match = (authInfo.
|
|
3785
|
-
(
|
|
3566
|
+
const match = (authInfo.orgs ?? []).find(
|
|
3567
|
+
(o) => o.slug === options.org || o.id === options.org || o.name.toLowerCase() === options.org.toLowerCase()
|
|
3786
3568
|
);
|
|
3787
3569
|
if (match) {
|
|
3788
|
-
api.
|
|
3570
|
+
api.setOrgId(match.id);
|
|
3789
3571
|
const slug = match.slug ? source_default.gray(` (${match.slug})`) : "";
|
|
3790
3572
|
console.log(
|
|
3791
|
-
source_default.gray("Organization: ") + source_default.cyan(match.
|
|
3573
|
+
source_default.gray("Organization: ") + source_default.cyan(match.name) + slug
|
|
3792
3574
|
);
|
|
3793
3575
|
} else {
|
|
3794
3576
|
console.error(
|
|
@@ -3807,6 +3589,7 @@ async function deployCommand(options) {
|
|
|
3807
3589
|
}
|
|
3808
3590
|
}
|
|
3809
3591
|
let githubVerified = false;
|
|
3592
|
+
let installationDbId;
|
|
3810
3593
|
try {
|
|
3811
3594
|
console.log(source_default.gray(`[DEBUG] API URL: ${api.baseUrl}`));
|
|
3812
3595
|
const connectionStatus = await api.getGitHubConnectionStatus();
|
|
@@ -3833,8 +3616,10 @@ async function deployCommand(options) {
|
|
|
3833
3616
|
console.log(source_default.cyan(" https://manufact.com/cloud/settings\n"));
|
|
3834
3617
|
process.exit(1);
|
|
3835
3618
|
}
|
|
3619
|
+
installationDbId = retryStatus.installations?.[0]?.id;
|
|
3836
3620
|
githubVerified = true;
|
|
3837
3621
|
} else if (gitInfo.owner && gitInfo.repo) {
|
|
3622
|
+
installationDbId = connectionStatus.installations?.[0]?.id;
|
|
3838
3623
|
console.log(source_default.gray("Checking repository access..."));
|
|
3839
3624
|
const hasAccess = await checkRepoAccess(
|
|
3840
3625
|
api,
|
|
@@ -3913,7 +3698,7 @@ async function deployCommand(options) {
|
|
|
3913
3698
|
}
|
|
3914
3699
|
const existingLink = !options.new ? await getProjectLink(cwd) : null;
|
|
3915
3700
|
const serverId = existingLink?.serverId;
|
|
3916
|
-
if (existingLink) {
|
|
3701
|
+
if (existingLink && serverId) {
|
|
3917
3702
|
try {
|
|
3918
3703
|
const existingDeployment = await api.getDeployment(
|
|
3919
3704
|
existingLink.deploymentId
|
|
@@ -3925,29 +3710,19 @@ async function deployCommand(options) {
|
|
|
3925
3710
|
source_default.cyan(` URL: ${getMcpServerUrl(existingDeployment)}
|
|
3926
3711
|
`)
|
|
3927
3712
|
);
|
|
3928
|
-
const
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
rootDir: options.rootDir || void 0
|
|
3934
|
-
};
|
|
3935
|
-
const deployment2 = await api.redeployDeployment(
|
|
3936
|
-
existingLink.deploymentId,
|
|
3937
|
-
redeploymentConfig
|
|
3938
|
-
);
|
|
3713
|
+
const newDep = await api.createDeployment({
|
|
3714
|
+
serverId,
|
|
3715
|
+
branch: gitInfo.branch || "main",
|
|
3716
|
+
trigger: "redeploy"
|
|
3717
|
+
});
|
|
3939
3718
|
await saveProjectLink(cwd, {
|
|
3940
3719
|
...existingLink,
|
|
3941
|
-
linkedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3720
|
+
linkedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3721
|
+
deploymentId: newDep.id
|
|
3942
3722
|
});
|
|
3943
|
-
await displayDeploymentProgress(api,
|
|
3723
|
+
await displayDeploymentProgress(api, newDep.id, {
|
|
3944
3724
|
yes: options.yes
|
|
3945
3725
|
});
|
|
3946
|
-
if (options.open && deployment2.domain) {
|
|
3947
|
-
console.log();
|
|
3948
|
-
console.log(source_default.gray("Opening deployment in browser..."));
|
|
3949
|
-
await open_default(`https://${deployment2.domain}`);
|
|
3950
|
-
}
|
|
3951
3726
|
return;
|
|
3952
3727
|
} else {
|
|
3953
3728
|
console.log(
|
|
@@ -3955,72 +3730,97 @@ async function deployCommand(options) {
|
|
|
3955
3730
|
`\u26A0\uFE0F Linked deployment not found or failed, creating new one...`
|
|
3956
3731
|
)
|
|
3957
3732
|
);
|
|
3958
|
-
|
|
3959
|
-
console.log(
|
|
3960
|
-
source_default.gray(` Will reuse existing server: ${serverId}`)
|
|
3961
|
-
);
|
|
3962
|
-
}
|
|
3733
|
+
console.log(source_default.gray(` Will reuse existing server: ${serverId}`));
|
|
3963
3734
|
}
|
|
3964
3735
|
} catch (error) {
|
|
3965
3736
|
console.log(
|
|
3966
3737
|
source_default.yellow(`\u26A0\uFE0F Linked deployment not found, creating new one...`)
|
|
3967
3738
|
);
|
|
3968
|
-
|
|
3969
|
-
console.log(source_default.gray(` Will reuse existing server: ${serverId}`));
|
|
3970
|
-
}
|
|
3739
|
+
console.log(source_default.gray(` Will reuse existing server: ${serverId}`));
|
|
3971
3740
|
}
|
|
3972
3741
|
}
|
|
3973
|
-
const deploymentRequest = {
|
|
3974
|
-
name: projectName,
|
|
3975
|
-
source: {
|
|
3976
|
-
type: "github",
|
|
3977
|
-
repo: `${gitInfo.owner}/${gitInfo.repo}`,
|
|
3978
|
-
branch: gitInfo.branch || "main",
|
|
3979
|
-
rootDir: options.rootDir || void 0,
|
|
3980
|
-
runtime,
|
|
3981
|
-
port,
|
|
3982
|
-
buildCommand,
|
|
3983
|
-
startCommand,
|
|
3984
|
-
env: Object.keys(envVars).length > 0 ? envVars : void 0
|
|
3985
|
-
},
|
|
3986
|
-
healthCheckPath: "/healthz",
|
|
3987
|
-
serverId
|
|
3988
|
-
};
|
|
3989
3742
|
if (!options.org) {
|
|
3990
3743
|
try {
|
|
3991
3744
|
const config = await readConfig();
|
|
3992
|
-
if (config.
|
|
3993
|
-
const slug = config.
|
|
3745
|
+
if (config.orgName) {
|
|
3746
|
+
const slug = config.orgSlug ? source_default.gray(` (${config.orgSlug})`) : "";
|
|
3994
3747
|
console.log(
|
|
3995
|
-
source_default.gray("Organization: ") + source_default.cyan(config.
|
|
3748
|
+
source_default.gray("Organization: ") + source_default.cyan(config.orgName) + slug
|
|
3996
3749
|
);
|
|
3997
3750
|
}
|
|
3998
3751
|
} catch {
|
|
3999
3752
|
}
|
|
4000
3753
|
}
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
3754
|
+
let deploymentId;
|
|
3755
|
+
if (serverId) {
|
|
3756
|
+
console.log(source_default.gray("Creating deployment..."));
|
|
3757
|
+
const result = await api.createDeployment({
|
|
3758
|
+
serverId,
|
|
3759
|
+
branch: gitInfo.branch || "main",
|
|
3760
|
+
trigger: "manual"
|
|
3761
|
+
});
|
|
3762
|
+
deploymentId = result.id;
|
|
3763
|
+
} else {
|
|
3764
|
+
if (!installationDbId) {
|
|
3765
|
+
console.log(source_default.red("\u2717 Could not determine GitHub installation ID."));
|
|
3766
|
+
console.log(
|
|
3767
|
+
source_default.gray(
|
|
3768
|
+
"Please ensure your GitHub App is installed and try again."
|
|
3769
|
+
)
|
|
3770
|
+
);
|
|
3771
|
+
process.exit(1);
|
|
3772
|
+
}
|
|
3773
|
+
const config = await readConfig();
|
|
3774
|
+
const authInfo = await api.testAuth();
|
|
3775
|
+
const orgId = config.orgId || authInfo.default_org_id;
|
|
3776
|
+
if (!orgId) {
|
|
3777
|
+
console.log(
|
|
3778
|
+
source_default.red("\u2717 No organization set. Run `mcp-use org switch` first.")
|
|
3779
|
+
);
|
|
3780
|
+
process.exit(1);
|
|
3781
|
+
}
|
|
3782
|
+
console.log(source_default.gray("Creating server and deployment..."));
|
|
3783
|
+
const serverResult = await api.createServer({
|
|
3784
|
+
type: "github",
|
|
3785
|
+
organizationId: orgId,
|
|
3786
|
+
installationId: installationDbId,
|
|
3787
|
+
name: projectName,
|
|
3788
|
+
repoFullName: `${gitInfo.owner}/${gitInfo.repo}`,
|
|
3789
|
+
branch: gitInfo.branch || "main",
|
|
3790
|
+
rootDir: options.rootDir,
|
|
3791
|
+
port,
|
|
3792
|
+
buildCommand,
|
|
3793
|
+
startCommand,
|
|
3794
|
+
env: Object.keys(envVars).length > 0 ? envVars : void 0
|
|
3795
|
+
});
|
|
3796
|
+
deploymentId = serverResult.deploymentId ?? "";
|
|
3797
|
+
if (!deploymentId) {
|
|
3798
|
+
console.log(
|
|
3799
|
+
source_default.green("\u2713 Server created: ") + source_default.gray(serverResult.server.id)
|
|
3800
|
+
);
|
|
3801
|
+
console.log(
|
|
3802
|
+
source_default.yellow(
|
|
3803
|
+
"\u26A0\uFE0F No deployment was triggered. You may need to trigger one manually."
|
|
3804
|
+
)
|
|
3805
|
+
);
|
|
3806
|
+
return;
|
|
3807
|
+
}
|
|
3808
|
+
await saveProjectLink(cwd, {
|
|
3809
|
+
deploymentId,
|
|
3810
|
+
deploymentName: projectName,
|
|
3811
|
+
linkedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3812
|
+
serverId: serverResult.server.id
|
|
3813
|
+
});
|
|
3814
|
+
console.log(
|
|
3815
|
+
source_default.gray(` Linked to this project (stored in .mcp-use/project.json)`)
|
|
3816
|
+
);
|
|
3817
|
+
console.log(source_default.gray(` Future deploys will reuse the same URL
|
|
4017
3818
|
`));
|
|
4018
|
-
await displayDeploymentProgress(api, deployment, { yes: options.yes });
|
|
4019
|
-
if (options.open && deployment.domain) {
|
|
4020
|
-
console.log();
|
|
4021
|
-
console.log(source_default.gray("Opening deployment in browser..."));
|
|
4022
|
-
await open_default(`https://${deployment.domain}`);
|
|
4023
3819
|
}
|
|
3820
|
+
console.log(
|
|
3821
|
+
source_default.green("\u2713 Deployment created: ") + source_default.gray(deploymentId)
|
|
3822
|
+
);
|
|
3823
|
+
await displayDeploymentProgress(api, deploymentId, { yes: options.yes });
|
|
4024
3824
|
} catch (error) {
|
|
4025
3825
|
console.error(
|
|
4026
3826
|
source_default.red.bold("\n\u2717 Deployment failed:"),
|
|
@@ -4095,19 +3895,19 @@ async function listDeploymentsCommand() {
|
|
|
4095
3895
|
);
|
|
4096
3896
|
console.log(
|
|
4097
3897
|
source_default.white.bold(
|
|
4098
|
-
`${"ID".padEnd(40)} ${"NAME".padEnd(25)} ${"STATUS".padEnd(12)} ${"
|
|
3898
|
+
`${"ID".padEnd(40)} ${"NAME".padEnd(25)} ${"STATUS".padEnd(12)} ${"MCP URL".padEnd(45)} ${"CREATED"}`
|
|
4099
3899
|
)
|
|
4100
3900
|
);
|
|
4101
|
-
console.log(source_default.gray("\u2500".repeat(
|
|
3901
|
+
console.log(source_default.gray("\u2500".repeat(140)));
|
|
4102
3902
|
for (const deployment of sortedDeployments) {
|
|
4103
3903
|
const id = formatId(deployment.id).padEnd(40);
|
|
4104
3904
|
const name = deployment.name.substring(0, 24).padEnd(25);
|
|
4105
3905
|
const statusColor = getStatusColor(deployment.status);
|
|
4106
3906
|
const status = statusColor(deployment.status.padEnd(12));
|
|
4107
|
-
const
|
|
3907
|
+
const mcpUrl = (deployment.mcpUrl || "-").substring(0, 44).padEnd(45);
|
|
4108
3908
|
const created = formatRelativeTime(deployment.createdAt);
|
|
4109
3909
|
console.log(
|
|
4110
|
-
`${source_default.gray(id)} ${name} ${status} ${source_default.cyan(
|
|
3910
|
+
`${source_default.gray(id)} ${name} ${status} ${source_default.cyan(mcpUrl)} ${source_default.gray(created)}`
|
|
4111
3911
|
);
|
|
4112
3912
|
}
|
|
4113
3913
|
console.log();
|
|
@@ -4139,31 +3939,24 @@ async function getDeploymentCommand(deploymentId) {
|
|
|
4139
3939
|
console.log(
|
|
4140
3940
|
source_default.white("Status: ") + statusColor(deployment.status)
|
|
4141
3941
|
);
|
|
4142
|
-
if (deployment.
|
|
3942
|
+
if (deployment.mcpUrl) {
|
|
4143
3943
|
console.log(
|
|
4144
|
-
source_default.white("
|
|
3944
|
+
source_default.white("MCP URL: ") + source_default.cyan(deployment.mcpUrl)
|
|
4145
3945
|
);
|
|
4146
3946
|
}
|
|
4147
|
-
if (deployment.
|
|
3947
|
+
if (deployment.gitBranch) {
|
|
4148
3948
|
console.log(
|
|
4149
|
-
source_default.white("
|
|
3949
|
+
source_default.white("Branch: ") + source_default.gray(deployment.gitBranch)
|
|
4150
3950
|
);
|
|
4151
3951
|
}
|
|
4152
|
-
|
|
4153
|
-
source_default.white("Source: ") + source_default.gray(deployment.source.type)
|
|
4154
|
-
);
|
|
4155
|
-
if (deployment.source.type === "github") {
|
|
4156
|
-
console.log(
|
|
4157
|
-
source_default.white("Repository: ") + source_default.gray(deployment.source.repo)
|
|
4158
|
-
);
|
|
3952
|
+
if (deployment.gitCommitSha) {
|
|
4159
3953
|
console.log(
|
|
4160
|
-
source_default.white("
|
|
3954
|
+
source_default.white("Commit: ") + source_default.gray(deployment.gitCommitSha.substring(0, 7))
|
|
4161
3955
|
);
|
|
4162
3956
|
}
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
);
|
|
3957
|
+
if (deployment.port) {
|
|
3958
|
+
console.log(source_default.white("Port: ") + source_default.gray(deployment.port));
|
|
3959
|
+
}
|
|
4167
3960
|
if (deployment.provider) {
|
|
4168
3961
|
console.log(
|
|
4169
3962
|
source_default.white("Provider: ") + source_default.gray(deployment.provider)
|
|
@@ -4175,13 +3968,6 @@ async function getDeploymentCommand(deploymentId) {
|
|
|
4175
3968
|
console.log(
|
|
4176
3969
|
source_default.white("Updated: ") + source_default.gray(formatRelativeTime(deployment.updatedAt))
|
|
4177
3970
|
);
|
|
4178
|
-
if (deployment.source.env && Object.keys(deployment.source.env).length > 0) {
|
|
4179
|
-
console.log(source_default.white("\nEnvironment Variables:"));
|
|
4180
|
-
for (const [key, value] of Object.entries(deployment.source.env)) {
|
|
4181
|
-
const displayValue = key.toLowerCase().includes("key") || key.toLowerCase().includes("secret") || key.toLowerCase().includes("password") || key.toLowerCase().includes("token") ? "***" : value;
|
|
4182
|
-
console.log(source_default.gray(` ${key}=`) + source_default.white(displayValue));
|
|
4183
|
-
}
|
|
4184
|
-
}
|
|
4185
3971
|
if (deployment.status === "failed" && deployment.error) {
|
|
4186
3972
|
console.log(source_default.red("\nError:"));
|
|
4187
3973
|
console.log(source_default.red(` ${deployment.error}`));
|
|
@@ -4208,43 +3994,56 @@ async function restartDeploymentCommand(deploymentId, options) {
|
|
|
4208
3994
|
}
|
|
4209
3995
|
const api = await McpUseAPI.create();
|
|
4210
3996
|
const deployment = await api.getDeployment(deploymentId);
|
|
3997
|
+
if (!deployment.serverId) {
|
|
3998
|
+
console.log(
|
|
3999
|
+
source_default.red("\u2717 Cannot restart: deployment has no linked server.")
|
|
4000
|
+
);
|
|
4001
|
+
process.exit(1);
|
|
4002
|
+
}
|
|
4211
4003
|
console.log(
|
|
4212
4004
|
source_default.cyan.bold(`
|
|
4213
4005
|
\u{1F504} Restarting deployment: ${deployment.name}
|
|
4214
4006
|
`)
|
|
4215
4007
|
);
|
|
4216
|
-
const
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
);
|
|
4008
|
+
const newDep = await api.createDeployment({
|
|
4009
|
+
serverId: deployment.serverId,
|
|
4010
|
+
trigger: "redeploy"
|
|
4011
|
+
});
|
|
4012
|
+
console.log(source_default.green("\u2713 Restart initiated: ") + source_default.gray(newDep.id));
|
|
4220
4013
|
if (options.follow) {
|
|
4221
|
-
console.log(source_default.gray("\nFollowing
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
))
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4014
|
+
console.log(source_default.gray("\nFollowing build logs...\n"));
|
|
4015
|
+
let offset = 0;
|
|
4016
|
+
let terminal = false;
|
|
4017
|
+
while (!terminal) {
|
|
4018
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
4019
|
+
try {
|
|
4020
|
+
const resp = await api.getDeploymentBuildLogs(newDep.id, offset);
|
|
4021
|
+
if (resp.logs.length > 0) {
|
|
4022
|
+
const lines = resp.logs.split("\n").filter((l) => l.trim());
|
|
4023
|
+
for (const line of lines) {
|
|
4024
|
+
try {
|
|
4025
|
+
const logData = JSON.parse(line);
|
|
4026
|
+
if (logData.line) {
|
|
4027
|
+
const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
|
|
4028
|
+
const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
|
|
4029
|
+
console.log(stepPrefix + levelColor(logData.line));
|
|
4030
|
+
}
|
|
4031
|
+
} catch {
|
|
4032
|
+
console.log(source_default.gray(line));
|
|
4033
|
+
}
|
|
4232
4034
|
}
|
|
4233
|
-
|
|
4234
|
-
console.log(source_default.gray(log));
|
|
4035
|
+
offset = resp.offset;
|
|
4235
4036
|
}
|
|
4037
|
+
if (resp.status === "running" || resp.status === "failed" || resp.status === "stopped") {
|
|
4038
|
+
terminal = true;
|
|
4039
|
+
}
|
|
4040
|
+
} catch {
|
|
4236
4041
|
}
|
|
4237
|
-
} catch (error) {
|
|
4238
|
-
console.log(
|
|
4239
|
-
source_default.gray(
|
|
4240
|
-
"\nLog stream ended. Use " + source_default.white(`mcp-use deployments get ${deploymentId}`) + " to check status."
|
|
4241
|
-
)
|
|
4242
|
-
);
|
|
4243
4042
|
}
|
|
4244
4043
|
} else {
|
|
4245
4044
|
console.log(
|
|
4246
4045
|
source_default.gray(
|
|
4247
|
-
"\nCheck status with: " + source_default.white(`mcp-use deployments get ${
|
|
4046
|
+
"\nCheck status with: " + source_default.white(`mcp-use deployments get ${newDep.id}`)
|
|
4248
4047
|
)
|
|
4249
4048
|
);
|
|
4250
4049
|
}
|
|
@@ -4278,8 +4077,10 @@ async function deleteDeploymentCommand(deploymentId, options) {
|
|
|
4278
4077
|
)
|
|
4279
4078
|
);
|
|
4280
4079
|
console.log(source_default.gray(` ID: ${deployment.id}`));
|
|
4281
|
-
|
|
4080
|
+
if (deployment.mcpUrl) {
|
|
4081
|
+
console.log(source_default.gray(` URL: ${deployment.mcpUrl}
|
|
4282
4082
|
`));
|
|
4083
|
+
}
|
|
4283
4084
|
const confirmed = await prompt2(
|
|
4284
4085
|
source_default.white("Are you sure you want to delete this deployment? (y/N): ")
|
|
4285
4086
|
);
|
|
@@ -4315,30 +4116,41 @@ async function logsCommand(deploymentId, options) {
|
|
|
4315
4116
|
}
|
|
4316
4117
|
const api = await McpUseAPI.create();
|
|
4317
4118
|
if (options.follow) {
|
|
4318
|
-
console.log(source_default.gray("
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4119
|
+
console.log(source_default.gray("Following build logs...\n"));
|
|
4120
|
+
let offset = 0;
|
|
4121
|
+
let terminal = false;
|
|
4122
|
+
while (!terminal) {
|
|
4123
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
4124
|
+
try {
|
|
4125
|
+
const resp = await api.getDeploymentBuildLogs(deploymentId, offset);
|
|
4126
|
+
if (resp.logs.length > 0) {
|
|
4127
|
+
const lines = resp.logs.split("\n").filter((l) => l.trim());
|
|
4128
|
+
for (const line of lines) {
|
|
4129
|
+
try {
|
|
4130
|
+
const logData = JSON.parse(line);
|
|
4131
|
+
if (logData.line) {
|
|
4132
|
+
const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
|
|
4133
|
+
const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
|
|
4134
|
+
console.log(stepPrefix + levelColor(logData.line));
|
|
4135
|
+
}
|
|
4136
|
+
} catch {
|
|
4137
|
+
console.log(source_default.gray(line));
|
|
4138
|
+
}
|
|
4327
4139
|
}
|
|
4328
|
-
|
|
4329
|
-
console.log(source_default.gray(log));
|
|
4140
|
+
offset = resp.offset;
|
|
4330
4141
|
}
|
|
4142
|
+
if (resp.status === "running" || resp.status === "failed" || resp.status === "stopped") {
|
|
4143
|
+
terminal = true;
|
|
4144
|
+
}
|
|
4145
|
+
} catch {
|
|
4331
4146
|
}
|
|
4332
|
-
} catch (error) {
|
|
4333
|
-
console.log(source_default.gray("\nLog stream ended."));
|
|
4334
4147
|
}
|
|
4335
|
-
} else {
|
|
4336
|
-
const
|
|
4148
|
+
} else if (options.build) {
|
|
4149
|
+
const resp = await api.getDeploymentBuildLogs(deploymentId);
|
|
4150
|
+
const logs = resp.logs;
|
|
4337
4151
|
if (!logs || logs.trim() === "") {
|
|
4338
4152
|
console.log(
|
|
4339
|
-
source_default.yellow(
|
|
4340
|
-
`No ${options.build ? "build " : ""}logs available for this deployment.`
|
|
4341
|
-
)
|
|
4153
|
+
source_default.yellow("No build logs available for this deployment.")
|
|
4342
4154
|
);
|
|
4343
4155
|
return;
|
|
4344
4156
|
}
|
|
@@ -4355,133 +4167,30 @@ async function logsCommand(deploymentId, options) {
|
|
|
4355
4167
|
console.log(source_default.gray(line));
|
|
4356
4168
|
}
|
|
4357
4169
|
}
|
|
4358
|
-
}
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
);
|
|
4377
|
-
process.exit(1);
|
|
4378
|
-
}
|
|
4379
|
-
const api = await McpUseAPI.create();
|
|
4380
|
-
const deployment = await api.getDeployment(deploymentId);
|
|
4381
|
-
console.log(
|
|
4382
|
-
source_default.cyan.bold(`
|
|
4383
|
-
\u{1F510} Environment Variables: ${deployment.name}
|
|
4384
|
-
`)
|
|
4385
|
-
);
|
|
4386
|
-
if (!deployment.source.env || Object.keys(deployment.source.env).length === 0) {
|
|
4387
|
-
console.log(source_default.yellow("No environment variables set."));
|
|
4388
|
-
console.log();
|
|
4389
|
-
return;
|
|
4390
|
-
}
|
|
4391
|
-
for (const [key, value] of Object.entries(deployment.source.env)) {
|
|
4392
|
-
const displayValue = key.toLowerCase().includes("key") || key.toLowerCase().includes("secret") || key.toLowerCase().includes("password") || key.toLowerCase().includes("token") ? "***" : value;
|
|
4393
|
-
console.log(
|
|
4394
|
-
source_default.white(key) + source_default.gray("=") + source_default.cyan(displayValue)
|
|
4395
|
-
);
|
|
4396
|
-
}
|
|
4397
|
-
console.log();
|
|
4398
|
-
} catch (error) {
|
|
4399
|
-
console.error(
|
|
4400
|
-
source_default.red.bold("\n\u2717 Failed to list environment variables:"),
|
|
4401
|
-
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
4402
|
-
);
|
|
4403
|
-
process.exit(1);
|
|
4404
|
-
}
|
|
4405
|
-
}
|
|
4406
|
-
async function setEnvCommand(deploymentId, envPairs) {
|
|
4407
|
-
try {
|
|
4408
|
-
if (!await isLoggedIn()) {
|
|
4409
|
-
console.log(source_default.red("\u2717 You are not logged in."));
|
|
4410
|
-
console.log(
|
|
4411
|
-
source_default.gray(
|
|
4412
|
-
"Run " + source_default.white("npx mcp-use login") + " to get started."
|
|
4413
|
-
)
|
|
4414
|
-
);
|
|
4415
|
-
process.exit(1);
|
|
4416
|
-
}
|
|
4417
|
-
const env2 = {};
|
|
4418
|
-
for (const pair of envPairs) {
|
|
4419
|
-
const [key, ...valueParts] = pair.split("=");
|
|
4420
|
-
if (!key || valueParts.length === 0) {
|
|
4421
|
-
console.log(source_default.red(`\u2717 Invalid format: ${pair}. Expected KEY=VALUE`));
|
|
4422
|
-
process.exit(1);
|
|
4170
|
+
} else {
|
|
4171
|
+
const logs = await api.getDeploymentLogs(deploymentId);
|
|
4172
|
+
if (!logs || logs.trim() === "") {
|
|
4173
|
+
console.log(source_default.yellow("No logs available for this deployment."));
|
|
4174
|
+
return;
|
|
4175
|
+
}
|
|
4176
|
+
const logLines = logs.split("\n").filter((l) => l.trim());
|
|
4177
|
+
for (const line of logLines) {
|
|
4178
|
+
try {
|
|
4179
|
+
const logData = JSON.parse(line);
|
|
4180
|
+
if (logData.line) {
|
|
4181
|
+
const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
|
|
4182
|
+
const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
|
|
4183
|
+
console.log(stepPrefix + levelColor(logData.line));
|
|
4184
|
+
}
|
|
4185
|
+
} catch {
|
|
4186
|
+
console.log(source_default.gray(line));
|
|
4187
|
+
}
|
|
4423
4188
|
}
|
|
4424
|
-
env2[key.trim()] = valueParts.join("=").trim();
|
|
4425
|
-
}
|
|
4426
|
-
const api = await McpUseAPI.create();
|
|
4427
|
-
const deployment = await api.getDeployment(deploymentId);
|
|
4428
|
-
const currentEnv = deployment.source.env || {};
|
|
4429
|
-
const mergedEnv = { ...currentEnv, ...env2 };
|
|
4430
|
-
const updated = await api.updateDeployment(deploymentId, {
|
|
4431
|
-
env: mergedEnv
|
|
4432
|
-
});
|
|
4433
|
-
console.log(
|
|
4434
|
-
source_default.green.bold(`
|
|
4435
|
-
\u2713 Environment variables updated: ${updated.name}
|
|
4436
|
-
`)
|
|
4437
|
-
);
|
|
4438
|
-
for (const key of Object.keys(env2)) {
|
|
4439
|
-
const displayValue = key.toLowerCase().includes("key") || key.toLowerCase().includes("secret") || key.toLowerCase().includes("password") || key.toLowerCase().includes("token") ? "***" : env2[key];
|
|
4440
|
-
console.log(
|
|
4441
|
-
source_default.white(key) + source_default.gray("=") + source_default.cyan(displayValue)
|
|
4442
|
-
);
|
|
4443
|
-
}
|
|
4444
|
-
console.log();
|
|
4445
|
-
} catch (error) {
|
|
4446
|
-
console.error(
|
|
4447
|
-
source_default.red.bold("\n\u2717 Failed to set environment variables:"),
|
|
4448
|
-
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
4449
|
-
);
|
|
4450
|
-
process.exit(1);
|
|
4451
|
-
}
|
|
4452
|
-
}
|
|
4453
|
-
async function unsetEnvCommand(deploymentId, keys) {
|
|
4454
|
-
try {
|
|
4455
|
-
if (!await isLoggedIn()) {
|
|
4456
|
-
console.log(source_default.red("\u2717 You are not logged in."));
|
|
4457
|
-
console.log(
|
|
4458
|
-
source_default.gray(
|
|
4459
|
-
"Run " + source_default.white("npx mcp-use login") + " to get started."
|
|
4460
|
-
)
|
|
4461
|
-
);
|
|
4462
|
-
process.exit(1);
|
|
4463
|
-
}
|
|
4464
|
-
const api = await McpUseAPI.create();
|
|
4465
|
-
const deployment = await api.getDeployment(deploymentId);
|
|
4466
|
-
const currentEnv = { ...deployment.source.env || {} };
|
|
4467
|
-
for (const key of keys) {
|
|
4468
|
-
delete currentEnv[key];
|
|
4469
|
-
}
|
|
4470
|
-
const updated = await api.updateDeployment(deploymentId, {
|
|
4471
|
-
env: currentEnv
|
|
4472
|
-
});
|
|
4473
|
-
console.log(
|
|
4474
|
-
source_default.green.bold(`
|
|
4475
|
-
\u2713 Environment variables removed: ${updated.name}
|
|
4476
|
-
`)
|
|
4477
|
-
);
|
|
4478
|
-
for (const key of keys) {
|
|
4479
|
-
console.log(source_default.gray(` ${key}`));
|
|
4480
4189
|
}
|
|
4481
4190
|
console.log();
|
|
4482
4191
|
} catch (error) {
|
|
4483
4192
|
console.error(
|
|
4484
|
-
source_default.red.bold("\n\u2717 Failed to
|
|
4193
|
+
source_default.red.bold("\n\u2717 Failed to get logs:"),
|
|
4485
4194
|
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
4486
4195
|
);
|
|
4487
4196
|
process.exit(1);
|
|
@@ -4499,11 +4208,9 @@ async function stopDeploymentCommand(deploymentId) {
|
|
|
4499
4208
|
process.exit(1);
|
|
4500
4209
|
}
|
|
4501
4210
|
const api = await McpUseAPI.create();
|
|
4502
|
-
|
|
4503
|
-
status: "stopped"
|
|
4504
|
-
});
|
|
4211
|
+
await api.stopDeployment(deploymentId);
|
|
4505
4212
|
console.log(source_default.green.bold(`
|
|
4506
|
-
\u2713 Deployment stopped
|
|
4213
|
+
\u2713 Deployment stopped
|
|
4507
4214
|
`));
|
|
4508
4215
|
} catch (error) {
|
|
4509
4216
|
console.error(
|
|
@@ -4524,13 +4231,11 @@ async function startDeploymentCommand(deploymentId) {
|
|
|
4524
4231
|
);
|
|
4525
4232
|
process.exit(1);
|
|
4526
4233
|
}
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
\u2713 Deployment started: ${updated.name}
|
|
4533
|
-
`));
|
|
4234
|
+
console.log(
|
|
4235
|
+
source_default.yellow(
|
|
4236
|
+
"\u26A0\uFE0F Start is not supported in this version. Use `mcp-use deployments restart` to redeploy."
|
|
4237
|
+
)
|
|
4238
|
+
);
|
|
4534
4239
|
} catch (error) {
|
|
4535
4240
|
console.error(
|
|
4536
4241
|
source_default.red.bold("\n\u2717 Failed to start deployment:"),
|
|
@@ -4545,13 +4250,11 @@ function createDeploymentsCommand() {
|
|
|
4545
4250
|
);
|
|
4546
4251
|
deploymentsCommand.command("list").alias("ls").description("List all deployments").action(listDeploymentsCommand);
|
|
4547
4252
|
deploymentsCommand.command("get").argument("<deployment-id>", "Deployment ID").description("Get deployment details").action(getDeploymentCommand);
|
|
4548
|
-
deploymentsCommand.command("restart").argument("<deployment-id>", "Deployment ID").option("-f, --follow", "Follow
|
|
4253
|
+
deploymentsCommand.command("restart").argument("<deployment-id>", "Deployment ID").option("-f, --follow", "Follow build logs").description(
|
|
4254
|
+
"Restart a deployment (triggers a new deployment on the same server)"
|
|
4255
|
+
).action(restartDeploymentCommand);
|
|
4549
4256
|
deploymentsCommand.command("delete").alias("rm").argument("<deployment-id>", "Deployment ID").option("-y, --yes", "Skip confirmation prompt").description("Delete a deployment").action(deleteDeploymentCommand);
|
|
4550
|
-
deploymentsCommand.command("logs").argument("<deployment-id>", "Deployment ID").option("-b, --build", "Show build logs instead of runtime logs").option("-f, --follow", "
|
|
4551
|
-
const envCommand = deploymentsCommand.command("env").description("Manage environment variables");
|
|
4552
|
-
envCommand.command("list").argument("<deployment-id>", "Deployment ID").description("List environment variables").action(listEnvCommand);
|
|
4553
|
-
envCommand.command("set").argument("<deployment-id>", "Deployment ID").argument("<pairs...>", "Environment variables in KEY=VALUE format").description("Set environment variables").action(setEnvCommand);
|
|
4554
|
-
envCommand.command("unset").argument("<deployment-id>", "Deployment ID").argument("<keys...>", "Environment variable keys to remove").description("Unset environment variables").action(unsetEnvCommand);
|
|
4257
|
+
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);
|
|
4555
4258
|
deploymentsCommand.command("stop").argument("<deployment-id>", "Deployment ID").description("Stop a deployment").action(stopDeploymentCommand);
|
|
4556
4259
|
deploymentsCommand.command("start").argument("<deployment-id>", "Deployment ID").description("Start a stopped deployment").action(startDeploymentCommand);
|
|
4557
4260
|
return deploymentsCommand;
|
|
@@ -4574,22 +4277,22 @@ async function orgListCommand() {
|
|
|
4574
4277
|
const api = await McpUseAPI.create();
|
|
4575
4278
|
const authInfo = await api.testAuth();
|
|
4576
4279
|
const config = await readConfig();
|
|
4577
|
-
const
|
|
4578
|
-
const activeId = config.
|
|
4579
|
-
if (
|
|
4280
|
+
const orgs = authInfo.orgs ?? [];
|
|
4281
|
+
const activeId = config.orgId || authInfo.default_org_id;
|
|
4282
|
+
if (orgs.length === 0) {
|
|
4580
4283
|
console.log(source_default.yellow("No organizations found."));
|
|
4581
4284
|
return;
|
|
4582
4285
|
}
|
|
4583
4286
|
console.log(source_default.cyan.bold("\u{1F3E2} Your organizations:\n"));
|
|
4584
|
-
for (const
|
|
4585
|
-
const isActive =
|
|
4287
|
+
for (const o of orgs) {
|
|
4288
|
+
const isActive = o.id === activeId;
|
|
4586
4289
|
const marker = isActive ? source_default.green(" \u2190 active") : "";
|
|
4587
|
-
const slug =
|
|
4588
|
-
const role = source_default.gray(` [${
|
|
4589
|
-
const name = isActive ? source_default.cyan.bold(
|
|
4290
|
+
const slug = o.slug ? source_default.gray(` (${o.slug})`) : "";
|
|
4291
|
+
const role = source_default.gray(` [${o.role}]`);
|
|
4292
|
+
const name = isActive ? source_default.cyan.bold(o.name) : source_default.white(o.name);
|
|
4590
4293
|
console.log(` ${name}${slug}${role}${marker}`);
|
|
4591
4294
|
}
|
|
4592
|
-
if (
|
|
4295
|
+
if (orgs.length > 1) {
|
|
4593
4296
|
console.log(
|
|
4594
4297
|
source_default.gray("\nSwitch with " + source_default.white("npx mcp-use org switch"))
|
|
4595
4298
|
);
|
|
@@ -4608,40 +4311,40 @@ async function orgSwitchCommand() {
|
|
|
4608
4311
|
const api = await McpUseAPI.create();
|
|
4609
4312
|
const authInfo = await api.testAuth();
|
|
4610
4313
|
const config = await readConfig();
|
|
4611
|
-
const
|
|
4612
|
-
if (
|
|
4314
|
+
const orgs = authInfo.orgs ?? [];
|
|
4315
|
+
if (orgs.length === 0) {
|
|
4613
4316
|
console.log(source_default.yellow("No organizations found."));
|
|
4614
4317
|
return;
|
|
4615
4318
|
}
|
|
4616
|
-
if (
|
|
4617
|
-
const
|
|
4618
|
-
const slug2 =
|
|
4319
|
+
if (orgs.length === 1) {
|
|
4320
|
+
const o = orgs[0];
|
|
4321
|
+
const slug2 = o.slug ? source_default.gray(` (${o.slug})`) : "";
|
|
4619
4322
|
console.log(
|
|
4620
4323
|
source_default.yellow(
|
|
4621
|
-
`You only have one organization: ${source_default.cyan(
|
|
4324
|
+
`You only have one organization: ${source_default.cyan(o.name)}${slug2}`
|
|
4622
4325
|
)
|
|
4623
4326
|
);
|
|
4624
4327
|
return;
|
|
4625
4328
|
}
|
|
4626
|
-
const activeId = config.
|
|
4627
|
-
const selected = await promptOrgSelection(
|
|
4329
|
+
const activeId = config.orgId || authInfo.default_org_id;
|
|
4330
|
+
const selected = await promptOrgSelection(orgs, activeId);
|
|
4628
4331
|
if (!selected) {
|
|
4629
4332
|
console.log(source_default.yellow("No organization selected."));
|
|
4630
4333
|
return;
|
|
4631
4334
|
}
|
|
4632
4335
|
await writeConfig({
|
|
4633
4336
|
...config,
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4337
|
+
orgId: selected.id,
|
|
4338
|
+
orgName: selected.name,
|
|
4339
|
+
orgSlug: selected.slug ?? void 0
|
|
4637
4340
|
});
|
|
4638
4341
|
try {
|
|
4639
|
-
await api.
|
|
4342
|
+
await api.setDefaultOrg(selected.id);
|
|
4640
4343
|
} catch {
|
|
4641
4344
|
}
|
|
4642
4345
|
const slug = selected.slug ? source_default.gray(` (${selected.slug})`) : "";
|
|
4643
4346
|
console.log(
|
|
4644
|
-
source_default.green.bold("\n\u2713 Switched to ") + source_default.cyan.bold(selected.
|
|
4347
|
+
source_default.green.bold("\n\u2713 Switched to ") + source_default.cyan.bold(selected.name) + slug
|
|
4645
4348
|
);
|
|
4646
4349
|
} catch (error) {
|
|
4647
4350
|
console.error(
|
|
@@ -4655,7 +4358,7 @@ async function orgCurrentCommand() {
|
|
|
4655
4358
|
try {
|
|
4656
4359
|
if (!await ensureLoggedIn()) return;
|
|
4657
4360
|
const config = await readConfig();
|
|
4658
|
-
if (!config.
|
|
4361
|
+
if (!config.orgId) {
|
|
4659
4362
|
console.log(
|
|
4660
4363
|
source_default.yellow(
|
|
4661
4364
|
"No organization selected. Run " + source_default.white("npx mcp-use org switch") + " to pick one."
|
|
@@ -4663,9 +4366,9 @@ async function orgCurrentCommand() {
|
|
|
4663
4366
|
);
|
|
4664
4367
|
return;
|
|
4665
4368
|
}
|
|
4666
|
-
const slug = config.
|
|
4369
|
+
const slug = config.orgSlug ? source_default.gray(` (${config.orgSlug})`) : "";
|
|
4667
4370
|
console.log(
|
|
4668
|
-
source_default.cyan.bold("\u{1F3E2} Active organization: ") + source_default.white(config.
|
|
4371
|
+
source_default.cyan.bold("\u{1F3E2} Active organization: ") + source_default.white(config.orgName || config.orgId) + slug
|
|
4669
4372
|
);
|
|
4670
4373
|
} catch (error) {
|
|
4671
4374
|
console.error(
|