@mcp-use/cli 3.0.0-canary.4 → 3.0.0-canary.5
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/deploy.d.ts +3 -3
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deployments.d.ts.map +1 -1
- package/dist/commands/servers.d.ts +3 -0
- package/dist/commands/servers.d.ts.map +1 -0
- package/dist/index.cjs +941 -600
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +940 -599
- package/dist/index.js.map +1 -1
- package/dist/utils/api.d.ts +71 -1
- package/dist/utils/api.d.ts.map +1 -1
- package/dist/utils/cloud-urls.d.ts +14 -0
- package/dist/utils/cloud-urls.d.ts.map +1 -0
- package/dist/utils/git.d.ts +12 -0
- package/dist/utils/git.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -503,7 +503,7 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
|
503
503
|
var source_default = chalk;
|
|
504
504
|
|
|
505
505
|
// src/index.ts
|
|
506
|
-
import { Command as
|
|
506
|
+
import { Command as Command5 } from "commander";
|
|
507
507
|
import "dotenv/config";
|
|
508
508
|
import { spawn } from "child_process";
|
|
509
509
|
import { readFileSync as readFileSync2 } from "fs";
|
|
@@ -1314,6 +1314,35 @@ var McpUseAPI = class _McpUseAPI {
|
|
|
1314
1314
|
body: JSON.stringify(body)
|
|
1315
1315
|
});
|
|
1316
1316
|
}
|
|
1317
|
+
async listServers(params) {
|
|
1318
|
+
const search = new URLSearchParams();
|
|
1319
|
+
if (params?.organizationId) {
|
|
1320
|
+
search.set("organizationId", params.organizationId);
|
|
1321
|
+
}
|
|
1322
|
+
if (params?.limit != null) {
|
|
1323
|
+
search.set("limit", String(params.limit));
|
|
1324
|
+
}
|
|
1325
|
+
if (params?.skip != null) {
|
|
1326
|
+
search.set("skip", String(params.skip));
|
|
1327
|
+
}
|
|
1328
|
+
if (params?.sort) {
|
|
1329
|
+
search.set("sort", params.sort);
|
|
1330
|
+
}
|
|
1331
|
+
const q = search.toString();
|
|
1332
|
+
return this.request(`/servers${q ? `?${q}` : ""}`);
|
|
1333
|
+
}
|
|
1334
|
+
async getServer(idOrSlug) {
|
|
1335
|
+
const path8 = encodeURIComponent(idOrSlug);
|
|
1336
|
+
return this.request(`/servers/${path8}`);
|
|
1337
|
+
}
|
|
1338
|
+
async deleteServer(id) {
|
|
1339
|
+
await this.request(
|
|
1340
|
+
`/servers/${encodeURIComponent(id)}`,
|
|
1341
|
+
{
|
|
1342
|
+
method: "DELETE"
|
|
1343
|
+
}
|
|
1344
|
+
);
|
|
1345
|
+
}
|
|
1317
1346
|
// ── Deployments ─────────────────────────────────────────────────
|
|
1318
1347
|
async createDeployment(input) {
|
|
1319
1348
|
return this.request("/deployments", {
|
|
@@ -1358,7 +1387,9 @@ var McpUseAPI = class _McpUseAPI {
|
|
|
1358
1387
|
is_connected: resp.installations.length > 0,
|
|
1359
1388
|
installations: resp.installations.map((i) => ({
|
|
1360
1389
|
id: i.id,
|
|
1361
|
-
installation_id: i.installationId
|
|
1390
|
+
installation_id: i.installationId,
|
|
1391
|
+
account_login: i.account?.login ?? "",
|
|
1392
|
+
account_type: i.account?.type ?? "User"
|
|
1362
1393
|
}))
|
|
1363
1394
|
};
|
|
1364
1395
|
}
|
|
@@ -1387,7 +1418,27 @@ var McpUseAPI = class _McpUseAPI {
|
|
|
1387
1418
|
}
|
|
1388
1419
|
async getGitHubAppName() {
|
|
1389
1420
|
if (process.env.MCP_GITHUB_APP_NAME) return process.env.MCP_GITHUB_APP_NAME;
|
|
1390
|
-
|
|
1421
|
+
if (this.baseUrl.includes("localhost")) return "mcp-use-local";
|
|
1422
|
+
if (this.baseUrl.includes(".dev.")) return "mcp-use-dev";
|
|
1423
|
+
return "mcp-use";
|
|
1424
|
+
}
|
|
1425
|
+
/**
|
|
1426
|
+
* Returns the GitHub numeric installation ID (not the DB UUID) for the org.
|
|
1427
|
+
* Used for building direct installation settings URLs.
|
|
1428
|
+
*/
|
|
1429
|
+
async getGitHubInstallationId() {
|
|
1430
|
+
const status = await this.getGitHubConnectionStatus();
|
|
1431
|
+
return status.installations?.[0]?.installation_id ?? null;
|
|
1432
|
+
}
|
|
1433
|
+
async createGitHubRepo(opts) {
|
|
1434
|
+
return this.request(`/github/installations/${opts.installationId}/repos`, {
|
|
1435
|
+
method: "POST",
|
|
1436
|
+
body: JSON.stringify({
|
|
1437
|
+
name: opts.name,
|
|
1438
|
+
private: opts.private ?? true,
|
|
1439
|
+
org: opts.org
|
|
1440
|
+
})
|
|
1441
|
+
});
|
|
1391
1442
|
}
|
|
1392
1443
|
};
|
|
1393
1444
|
|
|
@@ -2442,9 +2493,9 @@ async function listPromptsCommand(options) {
|
|
|
2442
2493
|
}
|
|
2443
2494
|
console.log(formatHeader(`Available Prompts (${prompts.length}):`));
|
|
2444
2495
|
console.log("");
|
|
2445
|
-
const tableData = prompts.map((
|
|
2446
|
-
name: source_default.bold(
|
|
2447
|
-
description:
|
|
2496
|
+
const tableData = prompts.map((prompt4) => ({
|
|
2497
|
+
name: source_default.bold(prompt4.name),
|
|
2498
|
+
description: prompt4.description || source_default.gray("No description")
|
|
2448
2499
|
}));
|
|
2449
2500
|
console.log(
|
|
2450
2501
|
formatTable(tableData, [
|
|
@@ -2472,20 +2523,20 @@ async function getPromptCommand(promptName, argsJson, options) {
|
|
|
2472
2523
|
}
|
|
2473
2524
|
}
|
|
2474
2525
|
console.error(formatInfo(`Getting prompt '${promptName}'...`));
|
|
2475
|
-
const
|
|
2526
|
+
const prompt4 = await session.getPrompt(promptName, args);
|
|
2476
2527
|
if (options?.json) {
|
|
2477
|
-
console.log(formatJson(
|
|
2528
|
+
console.log(formatJson(prompt4));
|
|
2478
2529
|
} else {
|
|
2479
2530
|
console.log(formatHeader(`Prompt: ${promptName}`));
|
|
2480
2531
|
console.log("");
|
|
2481
|
-
if (
|
|
2482
|
-
console.log(
|
|
2532
|
+
if (prompt4.description) {
|
|
2533
|
+
console.log(prompt4.description);
|
|
2483
2534
|
console.log("");
|
|
2484
2535
|
}
|
|
2485
|
-
if (
|
|
2536
|
+
if (prompt4.messages) {
|
|
2486
2537
|
console.log(formatHeader("Messages:"));
|
|
2487
2538
|
console.log("");
|
|
2488
|
-
console.log(formatPromptMessages(
|
|
2539
|
+
console.log(formatPromptMessages(prompt4.messages));
|
|
2489
2540
|
}
|
|
2490
2541
|
}
|
|
2491
2542
|
} catch (error) {
|
|
@@ -2625,8 +2676,8 @@ async function interactiveCommand(options) {
|
|
|
2625
2676
|
async (argsInput) => {
|
|
2626
2677
|
try {
|
|
2627
2678
|
const args = argsInput.trim() ? JSON.parse(argsInput) : {};
|
|
2628
|
-
const
|
|
2629
|
-
console.log(formatPromptMessages(
|
|
2679
|
+
const prompt4 = await session.getPrompt(arg, args);
|
|
2680
|
+
console.log(formatPromptMessages(prompt4.messages));
|
|
2630
2681
|
} catch (error) {
|
|
2631
2682
|
console.error(formatError(error.message));
|
|
2632
2683
|
}
|
|
@@ -2792,6 +2843,20 @@ async function getGitInfo(cwd = process.cwd()) {
|
|
|
2792
2843
|
hasUncommittedChanges: uncommittedChanges
|
|
2793
2844
|
};
|
|
2794
2845
|
}
|
|
2846
|
+
async function gitInit(cwd, message = "Initial commit") {
|
|
2847
|
+
await gitCommand("git init", cwd);
|
|
2848
|
+
await gitCommand("git add .", cwd);
|
|
2849
|
+
await gitCommand(`git commit -m "${message}"`, cwd);
|
|
2850
|
+
}
|
|
2851
|
+
async function gitAddRemoteAndPush(cwd, cloneUrl, branch = "main") {
|
|
2852
|
+
await gitCommand(`git remote add origin ${cloneUrl}`, cwd);
|
|
2853
|
+
await gitCommand(`git push -u origin ${branch}`, cwd);
|
|
2854
|
+
}
|
|
2855
|
+
async function gitCommitAndPush(cwd, message, branch = "main") {
|
|
2856
|
+
await gitCommand("git add .", cwd);
|
|
2857
|
+
await gitCommand(`git commit -m "${message}"`, cwd);
|
|
2858
|
+
await gitCommand(`git push origin ${branch}`, cwd);
|
|
2859
|
+
}
|
|
2795
2860
|
function isGitHubUrl(url) {
|
|
2796
2861
|
try {
|
|
2797
2862
|
const parsedUrl = new URL(url);
|
|
@@ -2806,6 +2871,22 @@ function isGitHubUrl(url) {
|
|
|
2806
2871
|
return false;
|
|
2807
2872
|
}
|
|
2808
2873
|
|
|
2874
|
+
// src/utils/cloud-urls.ts
|
|
2875
|
+
var GATEWAY_DOMAIN = "run.mcp-use.com";
|
|
2876
|
+
function buildGatewayUrl(slugOrId) {
|
|
2877
|
+
return `https://${slugOrId}.${GATEWAY_DOMAIN}/mcp`;
|
|
2878
|
+
}
|
|
2879
|
+
function getMcpServerUrl(deployment) {
|
|
2880
|
+
if (deployment.mcpUrl) return deployment.mcpUrl;
|
|
2881
|
+
if (deployment.serverId) return buildGatewayUrl(deployment.serverId);
|
|
2882
|
+
return "";
|
|
2883
|
+
}
|
|
2884
|
+
function getMcpServerUrlForCloudServer(server) {
|
|
2885
|
+
if (server.mcpUrl) return server.mcpUrl;
|
|
2886
|
+
const hostKey = server.slug && server.slug.trim() || server.id;
|
|
2887
|
+
return buildGatewayUrl(hostKey);
|
|
2888
|
+
}
|
|
2889
|
+
|
|
2809
2890
|
// src/utils/project-link.ts
|
|
2810
2891
|
import { promises as fs8 } from "fs";
|
|
2811
2892
|
import path4 from "path";
|
|
@@ -2852,10 +2933,6 @@ ${MCP_USE_DIR}
|
|
|
2852
2933
|
}
|
|
2853
2934
|
|
|
2854
2935
|
// src/commands/deploy.ts
|
|
2855
|
-
var GATEWAY_DOMAIN = "run.mcp-use.com";
|
|
2856
|
-
function buildGatewayUrl(slugOrId) {
|
|
2857
|
-
return `https://${slugOrId}.${GATEWAY_DOMAIN}/mcp`;
|
|
2858
|
-
}
|
|
2859
2936
|
async function parseEnvFile(filePath) {
|
|
2860
2937
|
try {
|
|
2861
2938
|
const content = await fs9.readFile(filePath, "utf-8");
|
|
@@ -2865,9 +2942,7 @@ async function parseEnvFile(filePath) {
|
|
|
2865
2942
|
let currentValue = "";
|
|
2866
2943
|
for (let line of lines) {
|
|
2867
2944
|
line = line.trim();
|
|
2868
|
-
if (!line || line.startsWith("#"))
|
|
2869
|
-
continue;
|
|
2870
|
-
}
|
|
2945
|
+
if (!line || line.startsWith("#")) continue;
|
|
2871
2946
|
if (currentKey && !line.includes("=")) {
|
|
2872
2947
|
currentValue += "\n" + line;
|
|
2873
2948
|
continue;
|
|
@@ -2878,20 +2953,15 @@ async function parseEnvFile(filePath) {
|
|
|
2878
2953
|
currentValue = "";
|
|
2879
2954
|
}
|
|
2880
2955
|
const equalIndex = line.indexOf("=");
|
|
2881
|
-
if (equalIndex === -1)
|
|
2882
|
-
continue;
|
|
2883
|
-
}
|
|
2956
|
+
if (equalIndex === -1) continue;
|
|
2884
2957
|
const key = line.substring(0, equalIndex).trim();
|
|
2885
|
-
|
|
2958
|
+
const value = line.substring(equalIndex + 1).trim();
|
|
2886
2959
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
|
|
2887
|
-
console.log(
|
|
2888
|
-
source_default.yellow(`\u26A0\uFE0F Skipping invalid environment variable key: ${key}`)
|
|
2889
|
-
);
|
|
2960
|
+
console.log(source_default.yellow(`\u26A0\uFE0F Skipping invalid env key: ${key}`));
|
|
2890
2961
|
continue;
|
|
2891
2962
|
}
|
|
2892
2963
|
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
2893
|
-
|
|
2894
|
-
envVars[key] = value;
|
|
2964
|
+
envVars[key] = value.slice(1, -1);
|
|
2895
2965
|
} else if (value.startsWith('"') || value.startsWith("'")) {
|
|
2896
2966
|
currentKey = key;
|
|
2897
2967
|
currentValue = value.slice(1);
|
|
@@ -2915,16 +2985,12 @@ async function parseEnvFile(filePath) {
|
|
|
2915
2985
|
function parseEnvVar(envStr) {
|
|
2916
2986
|
const equalIndex = envStr.indexOf("=");
|
|
2917
2987
|
if (equalIndex === -1) {
|
|
2918
|
-
throw new Error(
|
|
2919
|
-
`Invalid environment variable format: "${envStr}". Expected KEY=VALUE`
|
|
2920
|
-
);
|
|
2988
|
+
throw new Error(`Invalid env format: "${envStr}". Expected KEY=VALUE`);
|
|
2921
2989
|
}
|
|
2922
2990
|
const key = envStr.substring(0, equalIndex).trim();
|
|
2923
2991
|
const value = envStr.substring(equalIndex + 1);
|
|
2924
2992
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
|
|
2925
|
-
throw new Error(
|
|
2926
|
-
`Invalid environment variable key: "${key}". Keys must start with a letter or underscore and contain only letters, numbers, and underscores.`
|
|
2927
|
-
);
|
|
2993
|
+
throw new Error(`Invalid env key: "${key}".`);
|
|
2928
2994
|
}
|
|
2929
2995
|
return { key, value };
|
|
2930
2996
|
}
|
|
@@ -2967,72 +3033,48 @@ async function buildEnvVars(options) {
|
|
|
2967
3033
|
}
|
|
2968
3034
|
async function isMcpProject(cwd = process.cwd()) {
|
|
2969
3035
|
try {
|
|
2970
|
-
const
|
|
2971
|
-
const
|
|
2972
|
-
|
|
2973
|
-
const hasMcpDeps = packageJson2.dependencies?.["mcp-use"] || packageJson2.dependencies?.["@modelcontextprotocol/sdk"] || packageJson2.devDependencies?.["mcp-use"] || packageJson2.devDependencies?.["@modelcontextprotocol/sdk"];
|
|
2974
|
-
const hasMcpScripts = packageJson2.scripts?.mcp || packageJson2.scripts?.["mcp:dev"];
|
|
2975
|
-
return !!(hasMcpDeps || hasMcpScripts);
|
|
3036
|
+
const content = await fs9.readFile(path5.join(cwd, "package.json"), "utf-8");
|
|
3037
|
+
const pkg = JSON.parse(content);
|
|
3038
|
+
return !!(pkg.dependencies?.["mcp-use"] || pkg.dependencies?.["@modelcontextprotocol/sdk"] || pkg.devDependencies?.["mcp-use"] || pkg.devDependencies?.["@modelcontextprotocol/sdk"]);
|
|
2976
3039
|
} catch {
|
|
2977
3040
|
return false;
|
|
2978
3041
|
}
|
|
2979
3042
|
}
|
|
2980
3043
|
async function getProjectName(cwd = process.cwd()) {
|
|
2981
3044
|
try {
|
|
2982
|
-
const
|
|
2983
|
-
const
|
|
2984
|
-
|
|
2985
|
-
if (packageJson2.name) {
|
|
2986
|
-
return packageJson2.name;
|
|
2987
|
-
}
|
|
3045
|
+
const content = await fs9.readFile(path5.join(cwd, "package.json"), "utf-8");
|
|
3046
|
+
const pkg = JSON.parse(content);
|
|
3047
|
+
if (pkg.name) return pkg.name;
|
|
2988
3048
|
} catch {
|
|
2989
3049
|
}
|
|
2990
3050
|
return path5.basename(cwd);
|
|
2991
3051
|
}
|
|
2992
|
-
async function detectBuildCommand(cwd
|
|
3052
|
+
async function detectBuildCommand(cwd) {
|
|
2993
3053
|
try {
|
|
2994
|
-
const
|
|
2995
|
-
|
|
2996
|
-
const packageJson2 = JSON.parse(content);
|
|
2997
|
-
if (packageJson2.scripts?.build) {
|
|
2998
|
-
return "npm run build";
|
|
2999
|
-
}
|
|
3054
|
+
const content = await fs9.readFile(path5.join(cwd, "package.json"), "utf-8");
|
|
3055
|
+
if (JSON.parse(content).scripts?.build) return "npm run build";
|
|
3000
3056
|
} catch {
|
|
3001
3057
|
}
|
|
3002
3058
|
return void 0;
|
|
3003
3059
|
}
|
|
3004
|
-
async function detectStartCommand(cwd
|
|
3060
|
+
async function detectStartCommand(cwd) {
|
|
3005
3061
|
try {
|
|
3006
|
-
const
|
|
3007
|
-
const
|
|
3008
|
-
|
|
3009
|
-
if (
|
|
3010
|
-
return "npm start";
|
|
3011
|
-
}
|
|
3012
|
-
if (packageJson2.main) {
|
|
3013
|
-
return `node ${packageJson2.main}`;
|
|
3014
|
-
}
|
|
3062
|
+
const content = await fs9.readFile(path5.join(cwd, "package.json"), "utf-8");
|
|
3063
|
+
const pkg = JSON.parse(content);
|
|
3064
|
+
if (pkg.scripts?.start) return "npm start";
|
|
3065
|
+
if (pkg.main) return `node ${pkg.main}`;
|
|
3015
3066
|
} catch {
|
|
3016
3067
|
}
|
|
3017
3068
|
return void 0;
|
|
3018
3069
|
}
|
|
3019
|
-
async function detectRuntime(cwd
|
|
3020
|
-
|
|
3021
|
-
const pythonFiles = ["requirements.txt", "pyproject.toml", "setup.py"];
|
|
3022
|
-
for (const file of pythonFiles) {
|
|
3023
|
-
try {
|
|
3024
|
-
await fs9.access(path5.join(cwd, file));
|
|
3025
|
-
return "python";
|
|
3026
|
-
} catch {
|
|
3027
|
-
continue;
|
|
3028
|
-
}
|
|
3029
|
-
}
|
|
3070
|
+
async function detectRuntime(cwd) {
|
|
3071
|
+
for (const f of ["requirements.txt", "pyproject.toml", "setup.py"]) {
|
|
3030
3072
|
try {
|
|
3031
|
-
await fs9.access(path5.join(cwd,
|
|
3032
|
-
return "
|
|
3073
|
+
await fs9.access(path5.join(cwd, f));
|
|
3074
|
+
return "python";
|
|
3033
3075
|
} catch {
|
|
3076
|
+
continue;
|
|
3034
3077
|
}
|
|
3035
|
-
} catch {
|
|
3036
3078
|
}
|
|
3037
3079
|
return "node";
|
|
3038
3080
|
}
|
|
@@ -3042,31 +3084,51 @@ async function prompt(question, defaultValue = "n") {
|
|
|
3042
3084
|
input: process.stdin,
|
|
3043
3085
|
output: process.stdout
|
|
3044
3086
|
});
|
|
3045
|
-
const
|
|
3046
|
-
const
|
|
3047
|
-
/(\(y\/n\):)/,
|
|
3048
|
-
`(${defaultIndicator}):`
|
|
3049
|
-
);
|
|
3087
|
+
const indicator = defaultValue === "y" ? "Y/n" : "y/N";
|
|
3088
|
+
const q = question.replace(/(\(y\/n\):)/, `(${indicator}):`);
|
|
3050
3089
|
return new Promise((resolve2) => {
|
|
3051
|
-
rl.question(
|
|
3090
|
+
rl.question(q, (answer) => {
|
|
3052
3091
|
rl.close();
|
|
3053
|
-
const
|
|
3054
|
-
if (
|
|
3055
|
-
|
|
3056
|
-
} else {
|
|
3057
|
-
resolve2(trimmedAnswer === "y" || trimmedAnswer === "yes");
|
|
3058
|
-
}
|
|
3092
|
+
const a = answer.trim().toLowerCase();
|
|
3093
|
+
if (a === "") resolve2(defaultValue === "y");
|
|
3094
|
+
else resolve2(a === "y" || a === "yes");
|
|
3059
3095
|
});
|
|
3060
3096
|
});
|
|
3061
3097
|
}
|
|
3062
|
-
function
|
|
3063
|
-
|
|
3064
|
-
|
|
3098
|
+
async function promptText(question, defaultValue) {
|
|
3099
|
+
const readline = await import("readline");
|
|
3100
|
+
const rl = readline.createInterface({
|
|
3101
|
+
input: process.stdin,
|
|
3102
|
+
output: process.stdout
|
|
3103
|
+
});
|
|
3104
|
+
const suffix = defaultValue ? source_default.gray(` [${defaultValue}]`) : "";
|
|
3105
|
+
return new Promise((resolve2) => {
|
|
3106
|
+
rl.question(question + suffix + " ", (answer) => {
|
|
3107
|
+
rl.close();
|
|
3108
|
+
resolve2(answer.trim() || defaultValue || "");
|
|
3109
|
+
});
|
|
3110
|
+
});
|
|
3111
|
+
}
|
|
3112
|
+
var REQUIRED_IGNORES = [
|
|
3113
|
+
"node_modules",
|
|
3114
|
+
"dist",
|
|
3115
|
+
".env",
|
|
3116
|
+
".env.local",
|
|
3117
|
+
".mcp-use"
|
|
3118
|
+
];
|
|
3119
|
+
async function ensureGitignore(cwd) {
|
|
3120
|
+
const gitignorePath = path5.join(cwd, ".gitignore");
|
|
3121
|
+
let content = "";
|
|
3122
|
+
try {
|
|
3123
|
+
content = await fs9.readFile(gitignorePath, "utf-8");
|
|
3124
|
+
} catch {
|
|
3065
3125
|
}
|
|
3066
|
-
|
|
3067
|
-
|
|
3126
|
+
const missing = REQUIRED_IGNORES.filter((entry) => !content.includes(entry));
|
|
3127
|
+
if (missing.length > 0) {
|
|
3128
|
+
const additions = missing.join("\n");
|
|
3129
|
+
const newContent = content + (content.endsWith("\n") ? "" : "\n") + additions + "\n";
|
|
3130
|
+
await fs9.writeFile(gitignorePath, newContent, "utf-8");
|
|
3068
3131
|
}
|
|
3069
|
-
return "";
|
|
3070
3132
|
}
|
|
3071
3133
|
async function displayDeploymentProgress(api, deploymentId, progressOptions) {
|
|
3072
3134
|
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
@@ -3076,11 +3138,10 @@ async function displayDeploymentProgress(api, deploymentId, progressOptions) {
|
|
|
3076
3138
|
if (spinnerInterval) clearInterval(spinnerInterval);
|
|
3077
3139
|
process.stdout.write("\r\x1B[K");
|
|
3078
3140
|
spinnerInterval = setInterval(() => {
|
|
3079
|
-
const frame = frames[frameIndex];
|
|
3080
|
-
frameIndex = (frameIndex + 1) % frames.length;
|
|
3081
3141
|
process.stdout.write(
|
|
3082
|
-
"\r" + source_default.cyan(
|
|
3142
|
+
"\r" + source_default.cyan(frames[frameIndex]) + " " + source_default.gray(message)
|
|
3083
3143
|
);
|
|
3144
|
+
frameIndex = (frameIndex + 1) % frames.length;
|
|
3084
3145
|
}, 80);
|
|
3085
3146
|
};
|
|
3086
3147
|
const stopSpinner = () => {
|
|
@@ -3097,57 +3158,49 @@ async function displayDeploymentProgress(api, deploymentId, progressOptions) {
|
|
|
3097
3158
|
let delay = 2e3;
|
|
3098
3159
|
const maxDelay = 1e4;
|
|
3099
3160
|
let buildLogOffset = 0;
|
|
3100
|
-
const sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
3101
3161
|
while (checkCount < maxChecks) {
|
|
3102
|
-
|
|
3162
|
+
const waitMs = delay;
|
|
3163
|
+
await new Promise((r) => setTimeout(r, waitMs));
|
|
3103
3164
|
checkCount++;
|
|
3104
3165
|
try {
|
|
3105
|
-
const
|
|
3166
|
+
const resp = await api.getDeploymentBuildLogs(
|
|
3106
3167
|
deploymentId,
|
|
3107
3168
|
buildLogOffset
|
|
3108
3169
|
);
|
|
3109
|
-
if (
|
|
3110
|
-
const
|
|
3111
|
-
for (const line of logLines) {
|
|
3170
|
+
if (resp.logs.length > 0) {
|
|
3171
|
+
for (const line of resp.logs.split("\n").filter((l) => l.trim())) {
|
|
3112
3172
|
try {
|
|
3113
|
-
const
|
|
3114
|
-
if (
|
|
3173
|
+
const d = JSON.parse(line);
|
|
3174
|
+
if (d.line) {
|
|
3115
3175
|
stopSpinner();
|
|
3116
|
-
const
|
|
3117
|
-
const
|
|
3118
|
-
console.log(
|
|
3176
|
+
const color = d.level === "error" ? source_default.red : d.level === "warn" ? source_default.yellow : source_default.gray;
|
|
3177
|
+
const prefix = d.step ? source_default.cyan(`[${d.step}]`) + " " : "";
|
|
3178
|
+
console.log(prefix + color(d.line));
|
|
3119
3179
|
}
|
|
3120
3180
|
} catch {
|
|
3121
3181
|
stopSpinner();
|
|
3122
3182
|
console.log(source_default.gray(line));
|
|
3123
3183
|
}
|
|
3124
3184
|
}
|
|
3125
|
-
buildLogOffset =
|
|
3185
|
+
buildLogOffset = resp.offset;
|
|
3126
3186
|
}
|
|
3127
3187
|
} catch {
|
|
3128
3188
|
}
|
|
3129
|
-
const
|
|
3130
|
-
if (
|
|
3189
|
+
const dep = await api.getDeployment(deploymentId);
|
|
3190
|
+
if (dep.status === "running") {
|
|
3131
3191
|
stopSpinner();
|
|
3132
|
-
const
|
|
3133
|
-
let dashboardUrl = null;
|
|
3192
|
+
const mcpUrl = getMcpServerUrl(dep);
|
|
3134
3193
|
const webUrl = (await getWebUrl()).replace(/\/$/, "");
|
|
3135
3194
|
const config = await readConfig();
|
|
3136
|
-
|
|
3137
|
-
if (
|
|
3138
|
-
|
|
3139
|
-
dashboardUrl = `${webUrl}/cloud/${orgSlug}/servers/${deployment.serverId}`;
|
|
3140
|
-
} else {
|
|
3141
|
-
dashboardUrl = `${webUrl}/cloud/servers/${deployment.serverId}`;
|
|
3142
|
-
}
|
|
3195
|
+
let dashboardUrl = null;
|
|
3196
|
+
if (dep.serverId) {
|
|
3197
|
+
dashboardUrl = config.orgSlug ? `${webUrl}/cloud/${config.orgSlug}/servers/${dep.serverId}` : `${webUrl}/cloud/servers/${dep.serverId}`;
|
|
3143
3198
|
}
|
|
3144
|
-
const inspectorUrl = `https://inspector.manufact.com/inspector?autoConnect=${encodeURIComponent(
|
|
3145
|
-
mcpServerUrl
|
|
3146
|
-
)}`;
|
|
3199
|
+
const inspectorUrl = `https://inspector.manufact.com/inspector?autoConnect=${encodeURIComponent(mcpUrl)}`;
|
|
3147
3200
|
console.log(source_default.green.bold("\u2713 Deployment successful!\n"));
|
|
3148
|
-
if (
|
|
3201
|
+
if (mcpUrl) {
|
|
3149
3202
|
console.log(source_default.white("\u{1F310} MCP Server URL:"));
|
|
3150
|
-
console.log(source_default.cyan.bold(` ${
|
|
3203
|
+
console.log(source_default.cyan.bold(` ${mcpUrl}
|
|
3151
3204
|
`));
|
|
3152
3205
|
}
|
|
3153
3206
|
if (dashboardUrl) {
|
|
@@ -3158,39 +3211,42 @@ async function displayDeploymentProgress(api, deploymentId, progressOptions) {
|
|
|
3158
3211
|
console.log(source_default.white("\u{1F50D} Inspector URL:"));
|
|
3159
3212
|
console.log(source_default.cyan.bold(` ${inspectorUrl}
|
|
3160
3213
|
`));
|
|
3161
|
-
console.log(source_default.gray("Deployment ID: ") + source_default.white(
|
|
3214
|
+
console.log(source_default.gray("Deployment ID: ") + source_default.white(dep.id));
|
|
3162
3215
|
return;
|
|
3163
|
-
} else if (
|
|
3216
|
+
} else if (dep.status === "failed") {
|
|
3164
3217
|
stopSpinner();
|
|
3165
3218
|
console.log(source_default.red.bold("\u2717 Deployment failed\n"));
|
|
3166
|
-
if (
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3219
|
+
if (dep.error) {
|
|
3220
|
+
const internalPatterns = [
|
|
3221
|
+
"GraphQL",
|
|
3222
|
+
"authenticated",
|
|
3223
|
+
"INTERNAL",
|
|
3224
|
+
"Fly API",
|
|
3225
|
+
"token validation",
|
|
3226
|
+
"context deadline",
|
|
3227
|
+
"Bad gateway",
|
|
3228
|
+
"502",
|
|
3229
|
+
"503"
|
|
3230
|
+
];
|
|
3231
|
+
const isInternalError = internalPatterns.some(
|
|
3232
|
+
(p) => dep.error.includes(p)
|
|
3233
|
+
);
|
|
3234
|
+
if (isInternalError) {
|
|
3235
|
+
console.log(
|
|
3236
|
+
source_default.red("Error: ") + "An internal infrastructure error occurred. Please try again."
|
|
3175
3237
|
);
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
serverId: deployment.serverId,
|
|
3180
|
-
trigger: "redeploy"
|
|
3181
|
-
});
|
|
3182
|
-
await displayDeploymentProgress(api, newDep.id, progressOptions);
|
|
3183
|
-
return;
|
|
3184
|
-
}
|
|
3238
|
+
console.log(source_default.gray(" Details: " + dep.error));
|
|
3239
|
+
} else {
|
|
3240
|
+
console.log(source_default.red("Error: ") + dep.error);
|
|
3185
3241
|
}
|
|
3186
3242
|
}
|
|
3187
3243
|
process.exit(1);
|
|
3188
|
-
} else if (
|
|
3244
|
+
} else if (dep.status === "building" || dep.status === "pending") {
|
|
3189
3245
|
startSpinner("Building and deploying...");
|
|
3190
3246
|
delay = Math.min(delay * 1.2, maxDelay);
|
|
3191
3247
|
} else {
|
|
3192
3248
|
stopSpinner();
|
|
3193
|
-
console.log(source_default.yellow("\u26A0\uFE0F Deployment status: ") +
|
|
3249
|
+
console.log(source_default.yellow("\u26A0\uFE0F Deployment status: ") + dep.status);
|
|
3194
3250
|
return;
|
|
3195
3251
|
}
|
|
3196
3252
|
}
|
|
@@ -3202,58 +3258,12 @@ async function displayDeploymentProgress(api, deploymentId, progressOptions) {
|
|
|
3202
3258
|
}
|
|
3203
3259
|
async function checkRepoAccess(api, owner, repo) {
|
|
3204
3260
|
try {
|
|
3205
|
-
const
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
} catch (error) {
|
|
3209
|
-
console.log(source_default.gray("Could not verify repository access"));
|
|
3261
|
+
const resp = await api.getGitHubRepos(true);
|
|
3262
|
+
return resp.repos.some((r) => r.full_name === `${owner}/${repo}`);
|
|
3263
|
+
} catch {
|
|
3210
3264
|
return false;
|
|
3211
3265
|
}
|
|
3212
3266
|
}
|
|
3213
|
-
var GITHUB_SETUP_POLL_INTERVAL_MS = 2e3;
|
|
3214
|
-
var GITHUB_SETUP_POLL_MAX_MS = 12e4;
|
|
3215
|
-
async function waitForGitHubSetupAfterBrowser(api, repoName, yes) {
|
|
3216
|
-
if (!yes) {
|
|
3217
|
-
console.log(source_default.gray("Waiting for GitHub configuration..."));
|
|
3218
|
-
await prompt(
|
|
3219
|
-
source_default.white("Press Enter when you've completed the GitHub setup..."),
|
|
3220
|
-
"y"
|
|
3221
|
-
);
|
|
3222
|
-
return;
|
|
3223
|
-
}
|
|
3224
|
-
console.log(
|
|
3225
|
-
source_default.gray(
|
|
3226
|
-
"Waiting for GitHub configuration (polling every 2s, up to 2 min)..."
|
|
3227
|
-
)
|
|
3228
|
-
);
|
|
3229
|
-
const deadline = Date.now() + GITHUB_SETUP_POLL_MAX_MS;
|
|
3230
|
-
while (Date.now() < deadline) {
|
|
3231
|
-
try {
|
|
3232
|
-
const status = await api.getGitHubConnectionStatus();
|
|
3233
|
-
if (!status.is_connected) {
|
|
3234
|
-
await new Promise((r) => setTimeout(r, GITHUB_SETUP_POLL_INTERVAL_MS));
|
|
3235
|
-
continue;
|
|
3236
|
-
}
|
|
3237
|
-
if (repoName) {
|
|
3238
|
-
const parts = repoName.split("/");
|
|
3239
|
-
const owner = parts[0];
|
|
3240
|
-
const repo = parts[1];
|
|
3241
|
-
if (owner && repo && await checkRepoAccess(api, owner, repo)) {
|
|
3242
|
-
return;
|
|
3243
|
-
}
|
|
3244
|
-
} else {
|
|
3245
|
-
return;
|
|
3246
|
-
}
|
|
3247
|
-
} catch {
|
|
3248
|
-
}
|
|
3249
|
-
await new Promise((r) => setTimeout(r, GITHUB_SETUP_POLL_INTERVAL_MS));
|
|
3250
|
-
}
|
|
3251
|
-
console.log(
|
|
3252
|
-
source_default.yellow(
|
|
3253
|
-
"\u26A0\uFE0F Timed out waiting for GitHub setup. Continuing with verification..."
|
|
3254
|
-
)
|
|
3255
|
-
);
|
|
3256
|
-
}
|
|
3257
3267
|
async function promptGitHubInstallation(api, reason, repoName, opts) {
|
|
3258
3268
|
const yes = !!opts?.yes;
|
|
3259
3269
|
console.log();
|
|
@@ -3279,96 +3289,48 @@ async function promptGitHubInstallation(api, reason, repoName, opts) {
|
|
|
3279
3289
|
),
|
|
3280
3290
|
"y"
|
|
3281
3291
|
);
|
|
3282
|
-
if (!shouldInstall)
|
|
3283
|
-
return false;
|
|
3284
|
-
}
|
|
3292
|
+
if (!shouldInstall) return false;
|
|
3285
3293
|
try {
|
|
3286
3294
|
const appName = await api.getGitHubAppName();
|
|
3287
|
-
const installUrl =
|
|
3288
|
-
console.log(
|
|
3289
|
-
|
|
3290
|
-
`
|
|
3291
|
-
Opening browser to ${reason === "not_connected" ? "install" : "configure"} GitHub App...`
|
|
3292
|
-
)
|
|
3293
|
-
);
|
|
3295
|
+
const installUrl = `https://github.com/apps/${appName}/installations/new`;
|
|
3296
|
+
console.log(source_default.cyan(`
|
|
3297
|
+
Opening browser...`));
|
|
3294
3298
|
console.log(source_default.gray(`URL: ${installUrl}
|
|
3295
3299
|
`));
|
|
3296
3300
|
if (reason === "no_access") {
|
|
3297
|
-
console.log(source_default.white("Please:"));
|
|
3298
3301
|
console.log(
|
|
3299
|
-
source_default.cyan("
|
|
3302
|
+
source_default.white("Please add ") + source_default.cyan.bold(repoName || "your repository") + source_default.white(" to the app's repository access, then return here.\n")
|
|
3300
3303
|
);
|
|
3301
|
-
|
|
3304
|
+
} else {
|
|
3302
3305
|
console.log(
|
|
3303
|
-
source_default.
|
|
3304
|
-
` 3. Grant access to ${source_default.bold(repoName || "your repository")}`
|
|
3305
|
-
)
|
|
3306
|
+
source_default.white("Complete the GitHub App installation, then return here.\n")
|
|
3306
3307
|
);
|
|
3307
|
-
console.log(source_default.cyan(" 4. Save your changes"));
|
|
3308
|
-
console.log(source_default.cyan(" 5. Return here when done\n"));
|
|
3309
|
-
} else {
|
|
3310
|
-
console.log(source_default.white("Please:"));
|
|
3311
|
-
console.log(source_default.cyan(" 1. Select the repositories to grant access"));
|
|
3312
|
-
if (repoName) {
|
|
3313
|
-
console.log(
|
|
3314
|
-
source_default.cyan(` 2. Make sure to include ${source_default.bold(repoName)}`)
|
|
3315
|
-
);
|
|
3316
|
-
console.log(source_default.cyan(" 3. Complete the installation"));
|
|
3317
|
-
} else {
|
|
3318
|
-
console.log(source_default.cyan(" 2. Complete the installation"));
|
|
3319
|
-
}
|
|
3320
|
-
console.log();
|
|
3321
3308
|
}
|
|
3322
3309
|
await open_default(installUrl);
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
const
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
)
|
|
3339
|
-
);
|
|
3340
|
-
} else {
|
|
3341
|
-
console.log(source_default.green(`\u2713 Repository ${repoName} is accessible!
|
|
3342
|
-
`));
|
|
3343
|
-
verified = true;
|
|
3310
|
+
if (!yes) {
|
|
3311
|
+
await prompt(source_default.white("Press Enter when done..."), "y");
|
|
3312
|
+
} else {
|
|
3313
|
+
console.log(source_default.gray("Waiting for GitHub configuration (polling)..."));
|
|
3314
|
+
const deadline = Date.now() + 12e4;
|
|
3315
|
+
while (Date.now() < deadline) {
|
|
3316
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
3317
|
+
try {
|
|
3318
|
+
const status = await api.getGitHubConnectionStatus();
|
|
3319
|
+
if (status.is_connected) {
|
|
3320
|
+
if (!repoName) return true;
|
|
3321
|
+
const [o, r] = repoName.split("/");
|
|
3322
|
+
if (o && r && await checkRepoAccess(api, o, r)) return true;
|
|
3323
|
+
}
|
|
3324
|
+
} catch {
|
|
3344
3325
|
}
|
|
3345
|
-
} else {
|
|
3346
|
-
console.log(source_default.green("\u2713 GitHub connected successfully!\n"));
|
|
3347
|
-
verified = true;
|
|
3348
3326
|
}
|
|
3349
|
-
} catch (error) {
|
|
3350
|
-
console.log(
|
|
3351
|
-
source_default.yellow("\u26A0\uFE0F Could not verify GitHub connection (API issue)")
|
|
3352
|
-
);
|
|
3353
|
-
}
|
|
3354
|
-
if (!verified) {
|
|
3355
|
-
console.log(
|
|
3356
|
-
source_default.gray(
|
|
3357
|
-
"\nNote: If you completed the GitHub setup, the deployment may work now.\n"
|
|
3358
|
-
)
|
|
3359
|
-
);
|
|
3360
3327
|
}
|
|
3361
3328
|
return true;
|
|
3362
|
-
} catch
|
|
3363
|
-
console.log(
|
|
3364
|
-
source_default.yellow("\n\u26A0\uFE0F Unable to open GitHub installation automatically")
|
|
3365
|
-
);
|
|
3329
|
+
} catch {
|
|
3330
|
+
console.log(source_default.yellow("\n\u26A0\uFE0F Unable to open browser automatically"));
|
|
3366
3331
|
console.log(
|
|
3367
3332
|
source_default.white("Please visit: ") + source_default.cyan("https://manufact.com/cloud/settings")
|
|
3368
3333
|
);
|
|
3369
|
-
console.log(
|
|
3370
|
-
source_default.gray("Then connect your GitHub account and try again.\n")
|
|
3371
|
-
);
|
|
3372
3334
|
return false;
|
|
3373
3335
|
}
|
|
3374
3336
|
}
|
|
@@ -3376,47 +3338,139 @@ async function deployCommand(options) {
|
|
|
3376
3338
|
try {
|
|
3377
3339
|
const cwd = process.cwd();
|
|
3378
3340
|
if (!await isLoggedIn()) {
|
|
3379
|
-
console.log(source_default.
|
|
3341
|
+
console.log(source_default.cyan.bold("Welcome to Manufact Cloud!\n"));
|
|
3380
3342
|
if (options.yes) {
|
|
3381
3343
|
console.log(
|
|
3382
|
-
source_default.
|
|
3383
|
-
"Run " + source_default.white("npx mcp-use login") + " first.
|
|
3344
|
+
source_default.red(
|
|
3345
|
+
"\u2717 Not logged in. Run " + source_default.white("npx mcp-use login") + " first."
|
|
3384
3346
|
)
|
|
3385
3347
|
);
|
|
3386
3348
|
process.exit(1);
|
|
3387
3349
|
}
|
|
3388
3350
|
const shouldLogin = await prompt(
|
|
3389
|
-
source_default.white("
|
|
3351
|
+
source_default.white("You need to log in to deploy. Log in now? (Y/n): "),
|
|
3390
3352
|
"y"
|
|
3391
3353
|
);
|
|
3392
|
-
if (shouldLogin) {
|
|
3393
|
-
try {
|
|
3394
|
-
await loginCommand({ silent: false });
|
|
3395
|
-
if (!await isLoggedIn()) {
|
|
3396
|
-
console.log(
|
|
3397
|
-
source_default.red("\u2717 Login verification failed. Please try again.")
|
|
3398
|
-
);
|
|
3399
|
-
process.exit(1);
|
|
3400
|
-
}
|
|
3401
|
-
console.log(source_default.gray("\nContinuing with deployment...\n"));
|
|
3402
|
-
} catch (error) {
|
|
3403
|
-
console.error(
|
|
3404
|
-
source_default.red.bold("\u2717 Login failed:"),
|
|
3405
|
-
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
3406
|
-
);
|
|
3407
|
-
process.exit(1);
|
|
3408
|
-
}
|
|
3409
|
-
} else {
|
|
3354
|
+
if (!shouldLogin) {
|
|
3410
3355
|
console.log(
|
|
3411
3356
|
source_default.gray(
|
|
3412
3357
|
"Run " + source_default.white("npx mcp-use login") + " to get started."
|
|
3413
3358
|
)
|
|
3414
3359
|
);
|
|
3360
|
+
process.exit(0);
|
|
3361
|
+
}
|
|
3362
|
+
try {
|
|
3363
|
+
await loginCommand({ silent: false });
|
|
3364
|
+
if (!await isLoggedIn()) {
|
|
3365
|
+
console.log(source_default.red("\u2717 Login failed. Please try again."));
|
|
3366
|
+
process.exit(1);
|
|
3367
|
+
}
|
|
3368
|
+
console.log(source_default.gray("\nContinuing with deployment...\n"));
|
|
3369
|
+
} catch (error) {
|
|
3370
|
+
console.error(
|
|
3371
|
+
source_default.red.bold("\u2717 Login failed:"),
|
|
3372
|
+
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
3373
|
+
);
|
|
3374
|
+
process.exit(1);
|
|
3375
|
+
}
|
|
3376
|
+
}
|
|
3377
|
+
const api = await McpUseAPI.create();
|
|
3378
|
+
if (options.org) {
|
|
3379
|
+
const authInfo = await api.testAuth();
|
|
3380
|
+
const match = (authInfo.orgs ?? []).find(
|
|
3381
|
+
(o) => o.slug === options.org || o.id === options.org || o.name.toLowerCase() === options.org.toLowerCase()
|
|
3382
|
+
);
|
|
3383
|
+
if (match) {
|
|
3384
|
+
api.setOrgId(match.id);
|
|
3385
|
+
const slug = match.slug ? source_default.gray(` (${match.slug})`) : "";
|
|
3386
|
+
console.log(
|
|
3387
|
+
source_default.gray("Organization: ") + source_default.cyan(match.name) + slug
|
|
3388
|
+
);
|
|
3389
|
+
} else {
|
|
3390
|
+
console.error(
|
|
3391
|
+
source_default.red(
|
|
3392
|
+
`\u2717 Organization "${options.org}" not found. Run ${source_default.white("npx mcp-use org list")} to see available organizations.`
|
|
3393
|
+
)
|
|
3394
|
+
);
|
|
3395
|
+
process.exit(1);
|
|
3396
|
+
}
|
|
3397
|
+
} else {
|
|
3398
|
+
const config = await readConfig();
|
|
3399
|
+
if (!config.orgId) {
|
|
3400
|
+
const authInfo = await api.testAuth();
|
|
3401
|
+
if (authInfo.orgs.length === 0) {
|
|
3402
|
+
console.log(
|
|
3403
|
+
source_default.red(
|
|
3404
|
+
"\u2717 No organizations found. Please create one at manufact.com/cloud."
|
|
3405
|
+
)
|
|
3406
|
+
);
|
|
3407
|
+
process.exit(1);
|
|
3408
|
+
}
|
|
3409
|
+
let selectedOrg;
|
|
3410
|
+
if (authInfo.orgs.length === 1) {
|
|
3411
|
+
selectedOrg = authInfo.orgs[0];
|
|
3412
|
+
} else {
|
|
3413
|
+
selectedOrg = await promptOrgSelection(
|
|
3414
|
+
authInfo.orgs,
|
|
3415
|
+
authInfo.default_org_id
|
|
3416
|
+
);
|
|
3417
|
+
}
|
|
3418
|
+
if (!selectedOrg) {
|
|
3419
|
+
console.log(source_default.red("\u2717 No organization selected."));
|
|
3420
|
+
process.exit(1);
|
|
3421
|
+
}
|
|
3422
|
+
api.setOrgId(selectedOrg.id);
|
|
3423
|
+
await writeConfig({
|
|
3424
|
+
...config,
|
|
3425
|
+
orgId: selectedOrg.id,
|
|
3426
|
+
orgName: selectedOrg.name,
|
|
3427
|
+
orgSlug: selectedOrg.slug ?? void 0
|
|
3428
|
+
});
|
|
3429
|
+
console.log(
|
|
3430
|
+
source_default.gray("Organization: ") + source_default.cyan(selectedOrg.name)
|
|
3431
|
+
);
|
|
3432
|
+
} else {
|
|
3433
|
+
if (config.orgName) {
|
|
3434
|
+
const slug = config.orgSlug ? source_default.gray(` (${config.orgSlug})`) : "";
|
|
3435
|
+
console.log(
|
|
3436
|
+
source_default.gray("Organization: ") + source_default.cyan(config.orgName) + slug
|
|
3437
|
+
);
|
|
3438
|
+
}
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3441
|
+
console.log(source_default.cyan.bold("\n\u{1F680} Deploying to Manufact cloud...\n"));
|
|
3442
|
+
let connectionStatus = await api.getGitHubConnectionStatus().catch(() => null);
|
|
3443
|
+
if (!connectionStatus?.is_connected) {
|
|
3444
|
+
const installed = await promptGitHubInstallation(
|
|
3445
|
+
api,
|
|
3446
|
+
"not_connected",
|
|
3447
|
+
void 0,
|
|
3448
|
+
{ yes: options.yes }
|
|
3449
|
+
);
|
|
3450
|
+
if (!installed) {
|
|
3415
3451
|
console.log(source_default.gray("Deployment cancelled."));
|
|
3416
3452
|
process.exit(0);
|
|
3417
3453
|
}
|
|
3454
|
+
connectionStatus = await api.getGitHubConnectionStatus().catch(() => null);
|
|
3455
|
+
if (!connectionStatus?.is_connected) {
|
|
3456
|
+
console.log(source_default.red("\n\u2717 GitHub connection could not be verified."));
|
|
3457
|
+
console.log(
|
|
3458
|
+
source_default.cyan(
|
|
3459
|
+
" Visit https://manufact.com/cloud/settings to connect GitHub.\n"
|
|
3460
|
+
)
|
|
3461
|
+
);
|
|
3462
|
+
process.exit(1);
|
|
3463
|
+
}
|
|
3464
|
+
}
|
|
3465
|
+
const installations = connectionStatus.installations ?? [];
|
|
3466
|
+
if (installations.length === 0) {
|
|
3467
|
+
console.log(source_default.red("\u2717 No GitHub installations found."));
|
|
3468
|
+
process.exit(1);
|
|
3418
3469
|
}
|
|
3419
|
-
|
|
3470
|
+
const defaultInstallation = installations.find((i) => i.account_type === "Organization") ?? installations[0];
|
|
3471
|
+
const installationDbId = defaultInstallation.id;
|
|
3472
|
+
const githubInstallationId = defaultInstallation.installation_id;
|
|
3473
|
+
console.log(source_default.green("\u2713 GitHub connected\n"));
|
|
3420
3474
|
const projectDir = options.rootDir ? path5.resolve(cwd, options.rootDir) : cwd;
|
|
3421
3475
|
if (options.rootDir) {
|
|
3422
3476
|
try {
|
|
@@ -3427,292 +3481,274 @@ async function deployCommand(options) {
|
|
|
3427
3481
|
);
|
|
3428
3482
|
process.exit(1);
|
|
3429
3483
|
}
|
|
3430
|
-
console.log(source_default.gray(` Root dir: `) + source_default.cyan(options.rootDir));
|
|
3431
3484
|
}
|
|
3432
3485
|
const isMcp = await isMcpProject(projectDir);
|
|
3433
|
-
if (!isMcp) {
|
|
3486
|
+
if (!isMcp && !options.yes) {
|
|
3434
3487
|
console.log(
|
|
3435
|
-
source_default.yellow(
|
|
3436
|
-
"\u26A0\uFE0F This doesn't appear to be an MCP server project (no mcp-use or @modelcontextprotocol/sdk dependency found)."
|
|
3437
|
-
)
|
|
3488
|
+
source_default.yellow("\u26A0\uFE0F This doesn't look like an MCP server project.")
|
|
3438
3489
|
);
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
console.log(source_default.gray("Deployment cancelled."));
|
|
3445
|
-
process.exit(0);
|
|
3446
|
-
}
|
|
3490
|
+
const shouldContinue = await prompt(
|
|
3491
|
+
source_default.white("Continue anyway? (y/n): ")
|
|
3492
|
+
);
|
|
3493
|
+
if (!shouldContinue) {
|
|
3494
|
+
process.exit(0);
|
|
3447
3495
|
}
|
|
3448
3496
|
console.log();
|
|
3449
3497
|
}
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
console.log(source_default.
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
console.log(source_default.cyan(" git push -u origin main\n"));
|
|
3463
|
-
process.exit(1);
|
|
3464
|
-
}
|
|
3465
|
-
if (!gitInfo.remoteUrl) {
|
|
3466
|
-
console.log(source_default.red("\u2717 No git remote configured\n"));
|
|
3467
|
-
console.log(source_default.white("Add a GitHub remote:"));
|
|
3468
|
-
console.log(source_default.cyan(" git remote add origin <your-github-url>\n"));
|
|
3469
|
-
process.exit(1);
|
|
3470
|
-
}
|
|
3471
|
-
if (!isGitHubUrl(gitInfo.remoteUrl)) {
|
|
3472
|
-
console.log(source_default.red("\u2717 Remote is not a GitHub repository"));
|
|
3473
|
-
console.log(source_default.yellow(` Current remote: ${gitInfo.remoteUrl}
|
|
3474
|
-
`));
|
|
3475
|
-
console.log(source_default.white("Please add a GitHub remote to deploy."));
|
|
3476
|
-
process.exit(1);
|
|
3477
|
-
}
|
|
3478
|
-
if (!gitInfo.owner || !gitInfo.repo) {
|
|
3479
|
-
console.log(source_default.red("\u2717 Could not parse GitHub repository information"));
|
|
3480
|
-
process.exit(1);
|
|
3481
|
-
}
|
|
3482
|
-
if (gitInfo.hasUncommittedChanges) {
|
|
3483
|
-
console.log(source_default.yellow("\u26A0\uFE0F You have uncommitted changes\n"));
|
|
3484
|
-
console.log(source_default.white("Deployments use the code pushed to GitHub."));
|
|
3485
|
-
console.log(
|
|
3486
|
-
source_default.white(
|
|
3487
|
-
"Local changes will not be included until you commit and push.\n"
|
|
3488
|
-
)
|
|
3489
|
-
);
|
|
3490
|
-
if (!options.yes) {
|
|
3491
|
-
const shouldContinue = await prompt(
|
|
3492
|
-
source_default.white("Continue with deployment from GitHub? (y/n): ")
|
|
3498
|
+
let gitInfo = await getGitInfo(cwd);
|
|
3499
|
+
let repoFullName;
|
|
3500
|
+
let branch = "main";
|
|
3501
|
+
if (!gitInfo.isGitRepo || !gitInfo.remoteUrl) {
|
|
3502
|
+
const projectName2 = options.name || await getProjectName(projectDir);
|
|
3503
|
+
console.log(source_default.yellow("\u26A0\uFE0F No GitHub remote found.\n"));
|
|
3504
|
+
if (options.yes) {
|
|
3505
|
+
console.log(source_default.gray("Creating GitHub repository automatically..."));
|
|
3506
|
+
} else {
|
|
3507
|
+
const shouldCreate = await prompt(
|
|
3508
|
+
source_default.white("Create a GitHub repository and push your code? (Y/n): "),
|
|
3509
|
+
"y"
|
|
3493
3510
|
);
|
|
3494
|
-
if (!
|
|
3495
|
-
console.log(
|
|
3511
|
+
if (!shouldCreate) {
|
|
3512
|
+
console.log(
|
|
3513
|
+
source_default.gray(
|
|
3514
|
+
"Deployment cancelled. Set up a GitHub remote and try again."
|
|
3515
|
+
)
|
|
3516
|
+
);
|
|
3496
3517
|
process.exit(0);
|
|
3497
3518
|
}
|
|
3498
3519
|
}
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
console.log(source_default.white("GitHub repository detected:"));
|
|
3502
|
-
console.log(
|
|
3503
|
-
source_default.gray(` Repository: `) + source_default.cyan(`${gitInfo.owner}/${gitInfo.repo}`)
|
|
3504
|
-
);
|
|
3505
|
-
console.log(
|
|
3506
|
-
source_default.gray(` Branch: `) + source_default.cyan(gitInfo.branch || "main")
|
|
3507
|
-
);
|
|
3508
|
-
if (gitInfo.commitSha) {
|
|
3509
|
-
console.log(
|
|
3510
|
-
source_default.gray(` Commit: `) + source_default.gray(gitInfo.commitSha.substring(0, 7))
|
|
3511
|
-
);
|
|
3512
|
-
}
|
|
3513
|
-
if (gitInfo.commitMessage) {
|
|
3514
|
-
console.log(
|
|
3515
|
-
source_default.gray(` Message: `) + source_default.gray(gitInfo.commitMessage.split("\n")[0])
|
|
3520
|
+
const defaultIdx = installations.findIndex(
|
|
3521
|
+
(i) => i.account_type === "Organization"
|
|
3516
3522
|
);
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3523
|
+
let selectedIdx = defaultIdx >= 0 ? defaultIdx : 0;
|
|
3524
|
+
if (installations.length > 1 && !options.yes) {
|
|
3525
|
+
console.log(
|
|
3526
|
+
source_default.cyan.bold("\u{1F419} Select a GitHub account for the repository:\n")
|
|
3527
|
+
);
|
|
3528
|
+
for (let i = 0; i < installations.length; i++) {
|
|
3529
|
+
const inst = installations[i];
|
|
3530
|
+
const typeLabel = inst.account_type === "Organization" ? source_default.gray(" (org)") : source_default.gray(" (personal)");
|
|
3531
|
+
const marker = i === selectedIdx ? source_default.green(" \u2190 default") : "";
|
|
3532
|
+
console.log(
|
|
3533
|
+
` ${source_default.white(`${i + 1}.`)} ${inst.account_login}${typeLabel}${marker}`
|
|
3534
|
+
);
|
|
3535
|
+
}
|
|
3536
|
+
console.log();
|
|
3537
|
+
const readline = await import("readline");
|
|
3538
|
+
const rl = readline.createInterface({
|
|
3539
|
+
input: process.stdin,
|
|
3540
|
+
output: process.stdout
|
|
3541
|
+
});
|
|
3542
|
+
const answer = await new Promise((resolve2) => {
|
|
3543
|
+
rl.question(
|
|
3544
|
+
source_default.gray(`Enter number [${selectedIdx + 1}]: `),
|
|
3545
|
+
(a) => {
|
|
3546
|
+
rl.close();
|
|
3547
|
+
resolve2(a.trim());
|
|
3548
|
+
}
|
|
3549
|
+
);
|
|
3550
|
+
});
|
|
3551
|
+
const parsed = answer === "" ? selectedIdx : parseInt(answer, 10) - 1;
|
|
3552
|
+
if (parsed >= 0 && parsed < installations.length) {
|
|
3553
|
+
selectedIdx = parsed;
|
|
3554
|
+
}
|
|
3555
|
+
}
|
|
3556
|
+
const repoInstallation = installations[selectedIdx];
|
|
3557
|
+
if (repoInstallation.account_type !== "Organization") {
|
|
3558
|
+
console.log(
|
|
3559
|
+
source_default.yellow(
|
|
3560
|
+
"\n\u26A0\uFE0F GitHub Apps cannot create repos on personal accounts.\n"
|
|
3561
|
+
)
|
|
3562
|
+
);
|
|
3563
|
+
console.log(
|
|
3564
|
+
source_default.white("To deploy from ") + source_default.cyan(repoInstallation.account_login) + source_default.white(", create a repository manually:\n")
|
|
3565
|
+
);
|
|
3566
|
+
console.log(
|
|
3567
|
+
source_default.cyan(" 1. ") + source_default.white("Go to ") + source_default.cyan("https://github.com/new")
|
|
3568
|
+
);
|
|
3569
|
+
console.log(
|
|
3570
|
+
source_default.cyan(" 2. ") + source_default.white("Create a repository (any name, can be private)")
|
|
3571
|
+
);
|
|
3572
|
+
console.log(source_default.cyan(" 3. ") + source_default.white("Add it as a remote:"));
|
|
3573
|
+
console.log(source_default.gray(" git init && git remote add origin <url>"));
|
|
3574
|
+
console.log(source_default.cyan(" 4. ") + source_default.white("Push your code:"));
|
|
3575
|
+
console.log(
|
|
3576
|
+
source_default.gray(
|
|
3577
|
+
" git add . && git commit -m 'Initial commit' && git push -u origin main"
|
|
3578
|
+
)
|
|
3579
|
+
);
|
|
3580
|
+
console.log(
|
|
3581
|
+
source_default.cyan(" 5. ") + source_default.white("Grant the GitHub App access to the repo:")
|
|
3582
|
+
);
|
|
3583
|
+
const appName = await api.getGitHubAppName();
|
|
3584
|
+
console.log(
|
|
3585
|
+
source_default.gray(
|
|
3586
|
+
` https://github.com/apps/${appName}/installations/new`
|
|
3587
|
+
)
|
|
3588
|
+
);
|
|
3589
|
+
console.log(
|
|
3590
|
+
source_default.cyan(" 6. ") + source_default.white("Run ") + source_default.cyan("mcp-use deploy") + source_default.white(" again\n")
|
|
3591
|
+
);
|
|
3528
3592
|
process.exit(0);
|
|
3529
3593
|
}
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
const runtime = options.runtime || await detectRuntime(projectDir);
|
|
3533
|
-
const port = options.port || 3e3;
|
|
3534
|
-
const buildCommand = await detectBuildCommand(projectDir);
|
|
3535
|
-
const startCommand = await detectStartCommand(projectDir);
|
|
3536
|
-
const envVars = await buildEnvVars(options);
|
|
3537
|
-
console.log();
|
|
3538
|
-
console.log(source_default.white("Deployment configuration:"));
|
|
3539
|
-
console.log(source_default.gray(` Name: `) + source_default.cyan(projectName));
|
|
3540
|
-
console.log(source_default.gray(` Runtime: `) + source_default.cyan(runtime));
|
|
3541
|
-
console.log(source_default.gray(` Port: `) + source_default.cyan(port));
|
|
3542
|
-
if (options.rootDir) {
|
|
3594
|
+
const repoName = options.yes ? projectName2 : await promptText(source_default.gray("Repository name:"), projectName2);
|
|
3595
|
+
await ensureGitignore(cwd);
|
|
3543
3596
|
console.log(
|
|
3544
|
-
source_default.gray(
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
if (buildCommand) {
|
|
3548
|
-
console.log(source_default.gray(` Build command: `) + source_default.cyan(buildCommand));
|
|
3549
|
-
}
|
|
3550
|
-
if (startCommand) {
|
|
3551
|
-
console.log(source_default.gray(` Start command: `) + source_default.cyan(startCommand));
|
|
3552
|
-
}
|
|
3553
|
-
if (envVars && Object.keys(envVars).length > 0) {
|
|
3554
|
-
console.log(
|
|
3555
|
-
source_default.gray(` Environment: `) + source_default.cyan(`${Object.keys(envVars).length} variable(s)`)
|
|
3556
|
-
);
|
|
3557
|
-
console.log(
|
|
3558
|
-
source_default.gray(` `) + source_default.gray(Object.keys(envVars).join(", "))
|
|
3597
|
+
source_default.gray(
|
|
3598
|
+
`Creating repository on ${repoInstallation.account_login}...`
|
|
3599
|
+
)
|
|
3559
3600
|
);
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3601
|
+
const repoResult = await api.createGitHubRepo({
|
|
3602
|
+
installationId: repoInstallation.installation_id,
|
|
3603
|
+
name: repoName,
|
|
3604
|
+
private: true,
|
|
3605
|
+
org: repoInstallation.account_login
|
|
3606
|
+
});
|
|
3607
|
+
console.log(source_default.green(`\u2713 Created ${source_default.cyan(repoResult.fullName)}`));
|
|
3608
|
+
if (!gitInfo.isGitRepo) {
|
|
3609
|
+
console.log(source_default.gray("Initializing git..."));
|
|
3610
|
+
await gitInit(cwd, "Initial commit");
|
|
3611
|
+
console.log(source_default.gray("Pushing to GitHub..."));
|
|
3612
|
+
await gitAddRemoteAndPush(cwd, repoResult.cloneUrl, "main");
|
|
3613
|
+
} else {
|
|
3614
|
+
console.log(source_default.gray("Adding remote and pushing..."));
|
|
3615
|
+
await gitAddRemoteAndPush(
|
|
3616
|
+
cwd,
|
|
3617
|
+
repoResult.cloneUrl,
|
|
3618
|
+
gitInfo.branch || "main"
|
|
3568
3619
|
);
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3620
|
+
}
|
|
3621
|
+
console.log(source_default.green("\u2713 Code pushed to GitHub\n"));
|
|
3622
|
+
gitInfo = await getGitInfo(cwd);
|
|
3623
|
+
repoFullName = repoResult.fullName;
|
|
3624
|
+
branch = gitInfo.branch || "main";
|
|
3625
|
+
} else if (!isGitHubUrl(gitInfo.remoteUrl)) {
|
|
3626
|
+
console.log(source_default.red("\u2717 Remote is not a GitHub repository"));
|
|
3627
|
+
console.log(source_default.yellow(` Current remote: ${gitInfo.remoteUrl}
|
|
3628
|
+
`));
|
|
3629
|
+
process.exit(1);
|
|
3630
|
+
} else if (!gitInfo.owner || !gitInfo.repo) {
|
|
3631
|
+
console.log(source_default.red("\u2717 Could not parse GitHub repository information"));
|
|
3632
|
+
process.exit(1);
|
|
3633
|
+
} else {
|
|
3634
|
+
repoFullName = `${gitInfo.owner}/${gitInfo.repo}`;
|
|
3635
|
+
branch = gitInfo.branch || "main";
|
|
3636
|
+
if (gitInfo.hasUncommittedChanges) {
|
|
3637
|
+
console.log(source_default.yellow("\u26A0\uFE0F You have uncommitted changes.\n"));
|
|
3638
|
+
if (!options.yes) {
|
|
3639
|
+
const shouldCommit = await prompt(
|
|
3640
|
+
source_default.white("Commit and push changes before deploying? (Y/n): "),
|
|
3641
|
+
"y"
|
|
3580
3642
|
);
|
|
3581
|
-
|
|
3643
|
+
if (shouldCommit) {
|
|
3644
|
+
await ensureGitignore(cwd);
|
|
3645
|
+
console.log(source_default.gray("Committing and pushing..."));
|
|
3646
|
+
await gitCommitAndPush(cwd, "Deploy changes", branch);
|
|
3647
|
+
gitInfo = await getGitInfo(cwd);
|
|
3648
|
+
console.log(source_default.green("\u2713 Changes pushed\n"));
|
|
3649
|
+
} else {
|
|
3650
|
+
console.log(source_default.gray("Deploying from last pushed commit.\n"));
|
|
3651
|
+
}
|
|
3582
3652
|
}
|
|
3583
|
-
} catch (error) {
|
|
3584
|
-
console.error(
|
|
3585
|
-
source_default.red("\u2717 Failed to resolve organization:"),
|
|
3586
|
-
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
3587
|
-
);
|
|
3588
|
-
process.exit(1);
|
|
3589
3653
|
}
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
if (!
|
|
3597
|
-
|
|
3598
|
-
|
|
3654
|
+
console.log(source_default.gray("Checking repository access..."));
|
|
3655
|
+
const hasAccess = await checkRepoAccess(
|
|
3656
|
+
api,
|
|
3657
|
+
gitInfo.owner,
|
|
3658
|
+
gitInfo.repo
|
|
3659
|
+
);
|
|
3660
|
+
if (!hasAccess) {
|
|
3661
|
+
console.log(
|
|
3662
|
+
source_default.yellow(
|
|
3663
|
+
`\u26A0\uFE0F GitHub App doesn't have access to ${source_default.cyan(repoFullName)}`
|
|
3664
|
+
)
|
|
3665
|
+
);
|
|
3666
|
+
const configured = await promptGitHubInstallation(
|
|
3599
3667
|
api,
|
|
3600
|
-
"
|
|
3668
|
+
"no_access",
|
|
3601
3669
|
repoFullName,
|
|
3602
|
-
{ yes: options.yes }
|
|
3670
|
+
{ yes: options.yes, installationId: githubInstallationId }
|
|
3603
3671
|
);
|
|
3604
|
-
if (!
|
|
3605
|
-
console.log(source_default.gray("Deployment cancelled."));
|
|
3672
|
+
if (!configured) {
|
|
3606
3673
|
process.exit(0);
|
|
3607
3674
|
}
|
|
3608
|
-
const
|
|
3609
|
-
if (!
|
|
3610
|
-
|
|
3611
|
-
source_default.red("\n\u2717 GitHub connection could not be verified.")
|
|
3612
|
-
);
|
|
3675
|
+
const retry = await checkRepoAccess(api, gitInfo.owner, gitInfo.repo);
|
|
3676
|
+
if (!retry) {
|
|
3677
|
+
const appName = await api.getGitHubAppName();
|
|
3613
3678
|
console.log(
|
|
3614
|
-
source_default.
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
process.exit(1);
|
|
3618
|
-
}
|
|
3619
|
-
installationDbId = retryStatus.installations?.[0]?.id;
|
|
3620
|
-
githubVerified = true;
|
|
3621
|
-
} else if (gitInfo.owner && gitInfo.repo) {
|
|
3622
|
-
installationDbId = connectionStatus.installations?.[0]?.id;
|
|
3623
|
-
console.log(source_default.gray("Checking repository access..."));
|
|
3624
|
-
const hasAccess = await checkRepoAccess(
|
|
3625
|
-
api,
|
|
3626
|
-
gitInfo.owner,
|
|
3627
|
-
gitInfo.repo
|
|
3628
|
-
);
|
|
3629
|
-
if (!hasAccess) {
|
|
3630
|
-
const repoFullName = `${gitInfo.owner}/${gitInfo.repo}`;
|
|
3631
|
-
console.log(
|
|
3632
|
-
source_default.yellow(
|
|
3633
|
-
`\u26A0\uFE0F GitHub App doesn't have access to ${source_default.cyan(repoFullName)}`
|
|
3679
|
+
source_default.red(
|
|
3680
|
+
`
|
|
3681
|
+
\u2717 Repository ${source_default.cyan(repoFullName)} is still not accessible.`
|
|
3634
3682
|
)
|
|
3635
3683
|
);
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
);
|
|
3642
|
-
|
|
3643
|
-
console.log(source_default.gray("Deployment cancelled."));
|
|
3644
|
-
process.exit(0);
|
|
3645
|
-
}
|
|
3646
|
-
const hasAccessRetry = await checkRepoAccess(
|
|
3647
|
-
api,
|
|
3648
|
-
gitInfo.owner,
|
|
3649
|
-
gitInfo.repo
|
|
3650
|
-
);
|
|
3651
|
-
if (!hasAccessRetry) {
|
|
3652
|
-
console.log(
|
|
3653
|
-
source_default.red(
|
|
3654
|
-
`
|
|
3655
|
-
\u2717 Repository ${source_default.cyan(repoFullName)} is still not accessible.`
|
|
3656
|
-
)
|
|
3657
|
-
);
|
|
3658
|
-
console.log(
|
|
3659
|
-
source_default.gray(
|
|
3660
|
-
"Please make sure the GitHub App has access to this repository."
|
|
3661
|
-
)
|
|
3662
|
-
);
|
|
3663
|
-
console.log(
|
|
3664
|
-
source_default.cyan(" https://github.com/settings/installations\n")
|
|
3665
|
-
);
|
|
3666
|
-
process.exit(1);
|
|
3667
|
-
}
|
|
3668
|
-
githubVerified = true;
|
|
3669
|
-
} else {
|
|
3670
|
-
console.log(source_default.green("\u2713 Repository access confirmed"));
|
|
3671
|
-
githubVerified = true;
|
|
3684
|
+
console.log(
|
|
3685
|
+
source_default.cyan(
|
|
3686
|
+
` https://github.com/apps/${appName}/installations/new
|
|
3687
|
+
`
|
|
3688
|
+
)
|
|
3689
|
+
);
|
|
3690
|
+
process.exit(1);
|
|
3672
3691
|
}
|
|
3673
3692
|
}
|
|
3674
|
-
|
|
3675
|
-
|
|
3693
|
+
console.log(source_default.green("\u2713 Repository access confirmed"));
|
|
3694
|
+
}
|
|
3695
|
+
const projectName = options.name || await getProjectName(projectDir);
|
|
3696
|
+
const port = options.port || 3e3;
|
|
3697
|
+
const buildCommand = await detectBuildCommand(projectDir);
|
|
3698
|
+
const startCommand = await detectStartCommand(projectDir);
|
|
3699
|
+
const runtime = options.runtime || await detectRuntime(projectDir);
|
|
3700
|
+
const envVars = await buildEnvVars(options);
|
|
3701
|
+
console.log();
|
|
3702
|
+
console.log(source_default.white("Deployment configuration:"));
|
|
3703
|
+
console.log(source_default.gray(` Repository: `) + source_default.cyan(repoFullName));
|
|
3704
|
+
console.log(source_default.gray(` Branch: `) + source_default.cyan(branch));
|
|
3705
|
+
console.log(source_default.gray(` Name: `) + source_default.cyan(projectName));
|
|
3706
|
+
console.log(source_default.gray(` Runtime: `) + source_default.cyan(runtime));
|
|
3707
|
+
console.log(source_default.gray(` Port: `) + source_default.cyan(port));
|
|
3708
|
+
if (options.region)
|
|
3709
|
+
console.log(source_default.gray(` Region: `) + source_default.cyan(options.region));
|
|
3710
|
+
if (options.buildCommand)
|
|
3676
3711
|
console.log(
|
|
3677
|
-
source_default.gray(
|
|
3678
|
-
"Error: " + (error instanceof Error ? error.message : "Unknown error")
|
|
3679
|
-
)
|
|
3712
|
+
source_default.gray(` Build command: `) + source_default.cyan(options.buildCommand)
|
|
3680
3713
|
);
|
|
3681
|
-
|
|
3714
|
+
else if (buildCommand)
|
|
3682
3715
|
console.log(
|
|
3683
|
-
source_default.
|
|
3684
|
-
" 1. You have connected GitHub at https://manufact.com/cloud/settings"
|
|
3685
|
-
)
|
|
3716
|
+
source_default.gray(` Build command: `) + source_default.gray(buildCommand + " (auto-detected)")
|
|
3686
3717
|
);
|
|
3718
|
+
if (options.startCommand)
|
|
3687
3719
|
console.log(
|
|
3688
|
-
source_default.
|
|
3720
|
+
source_default.gray(` Start command: `) + source_default.cyan(options.startCommand)
|
|
3689
3721
|
);
|
|
3690
|
-
|
|
3691
|
-
process.exit(1);
|
|
3692
|
-
}
|
|
3693
|
-
if (!githubVerified) {
|
|
3722
|
+
else if (startCommand)
|
|
3694
3723
|
console.log(
|
|
3695
|
-
source_default.
|
|
3724
|
+
source_default.gray(` Start command: `) + source_default.gray(startCommand + " (auto-detected)")
|
|
3696
3725
|
);
|
|
3697
|
-
|
|
3726
|
+
if (Object.keys(envVars).length > 0) {
|
|
3727
|
+
console.log(
|
|
3728
|
+
source_default.gray(` Environment: `) + source_default.cyan(`${Object.keys(envVars).length} variable(s)`)
|
|
3729
|
+
);
|
|
3730
|
+
}
|
|
3731
|
+
console.log();
|
|
3732
|
+
if (!options.yes) {
|
|
3733
|
+
const shouldDeploy = await prompt(source_default.white(`Deploy? (Y/n): `), "y");
|
|
3734
|
+
if (!shouldDeploy) {
|
|
3735
|
+
console.log(source_default.gray("Deployment cancelled."));
|
|
3736
|
+
process.exit(0);
|
|
3737
|
+
}
|
|
3698
3738
|
}
|
|
3699
3739
|
const existingLink = !options.new ? await getProjectLink(cwd) : null;
|
|
3700
|
-
|
|
3740
|
+
let serverId = existingLink?.serverId;
|
|
3701
3741
|
if (existingLink && serverId) {
|
|
3702
3742
|
try {
|
|
3703
|
-
const
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
if (existingDeployment && existingDeployment.status !== "failed") {
|
|
3707
|
-
console.log(source_default.green(`\u2713 Found linked deployment`));
|
|
3743
|
+
const existingDep = await api.getDeployment(existingLink.deploymentId);
|
|
3744
|
+
if (existingDep && existingDep.status !== "failed") {
|
|
3745
|
+
console.log(source_default.green(`\u2713 Found linked server`));
|
|
3708
3746
|
console.log(source_default.gray(` Redeploying to maintain the same URL...`));
|
|
3709
|
-
console.log(
|
|
3710
|
-
|
|
3711
|
-
`)
|
|
3712
|
-
);
|
|
3747
|
+
console.log(source_default.cyan(` URL: ${getMcpServerUrl(existingDep)}
|
|
3748
|
+
`));
|
|
3713
3749
|
const newDep = await api.createDeployment({
|
|
3714
3750
|
serverId,
|
|
3715
|
-
branch
|
|
3751
|
+
branch,
|
|
3716
3752
|
trigger: "redeploy"
|
|
3717
3753
|
});
|
|
3718
3754
|
await saveProjectLink(cwd, {
|
|
@@ -3720,89 +3756,79 @@ async function deployCommand(options) {
|
|
|
3720
3756
|
linkedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3721
3757
|
deploymentId: newDep.id
|
|
3722
3758
|
});
|
|
3723
|
-
await displayDeploymentProgress(api, newDep.id, {
|
|
3724
|
-
yes: options.yes
|
|
3725
|
-
});
|
|
3726
|
-
return;
|
|
3727
|
-
} else {
|
|
3728
3759
|
console.log(
|
|
3729
|
-
source_default.
|
|
3730
|
-
`\u26A0\uFE0F Linked deployment not found or failed, creating new one...`
|
|
3731
|
-
)
|
|
3760
|
+
source_default.green("\u2713 Deployment created: ") + source_default.gray(newDep.id)
|
|
3732
3761
|
);
|
|
3733
|
-
|
|
3762
|
+
await displayDeploymentProgress(api, newDep.id, { yes: options.yes });
|
|
3763
|
+
return;
|
|
3734
3764
|
}
|
|
3735
|
-
} catch (
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
);
|
|
3739
|
-
console.log(source_default.gray(` Will reuse existing server: ${serverId}`));
|
|
3740
|
-
}
|
|
3741
|
-
}
|
|
3742
|
-
if (!options.org) {
|
|
3743
|
-
try {
|
|
3744
|
-
const config = await readConfig();
|
|
3745
|
-
if (config.orgName) {
|
|
3746
|
-
const slug = config.orgSlug ? source_default.gray(` (${config.orgSlug})`) : "";
|
|
3765
|
+
} catch (err) {
|
|
3766
|
+
const is404 = err?.status === 404 || (err?.message ?? "").includes("404");
|
|
3767
|
+
if (is404) {
|
|
3747
3768
|
console.log(
|
|
3748
|
-
source_default.
|
|
3769
|
+
source_default.yellow("\u26A0\uFE0F Previously linked server no longer exists.\n")
|
|
3749
3770
|
);
|
|
3771
|
+
if (!options.yes) {
|
|
3772
|
+
const shouldRecreate = await prompt(
|
|
3773
|
+
source_default.white("Create a new server and deploy? (Y/n): "),
|
|
3774
|
+
"y"
|
|
3775
|
+
);
|
|
3776
|
+
if (!shouldRecreate) {
|
|
3777
|
+
console.log(source_default.gray("Deployment cancelled."));
|
|
3778
|
+
process.exit(0);
|
|
3779
|
+
}
|
|
3780
|
+
}
|
|
3781
|
+
serverId = void 0;
|
|
3750
3782
|
}
|
|
3751
|
-
} catch {
|
|
3752
3783
|
}
|
|
3753
3784
|
}
|
|
3754
3785
|
let deploymentId;
|
|
3755
3786
|
if (serverId) {
|
|
3756
3787
|
console.log(source_default.gray("Creating deployment..."));
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
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);
|
|
3788
|
+
try {
|
|
3789
|
+
const result = await api.createDeployment({
|
|
3790
|
+
serverId,
|
|
3791
|
+
branch,
|
|
3792
|
+
trigger: "manual"
|
|
3793
|
+
});
|
|
3794
|
+
deploymentId = result.id;
|
|
3795
|
+
} catch (err) {
|
|
3796
|
+
const is404 = err?.status === 404 || (err?.message ?? "").includes("404");
|
|
3797
|
+
if (is404) {
|
|
3798
|
+
console.log(
|
|
3799
|
+
source_default.yellow(
|
|
3800
|
+
"\u26A0\uFE0F Linked server no longer exists. Creating a new one...\n"
|
|
3801
|
+
)
|
|
3802
|
+
);
|
|
3803
|
+
serverId = void 0;
|
|
3804
|
+
} else {
|
|
3805
|
+
throw err;
|
|
3806
|
+
}
|
|
3781
3807
|
}
|
|
3808
|
+
}
|
|
3809
|
+
if (!serverId) {
|
|
3810
|
+
const orgId = await api.resolveOrganizationId();
|
|
3782
3811
|
console.log(source_default.gray("Creating server and deployment..."));
|
|
3783
3812
|
const serverResult = await api.createServer({
|
|
3784
3813
|
type: "github",
|
|
3785
3814
|
organizationId: orgId,
|
|
3786
3815
|
installationId: installationDbId,
|
|
3787
3816
|
name: projectName,
|
|
3788
|
-
repoFullName
|
|
3789
|
-
branch
|
|
3817
|
+
repoFullName,
|
|
3818
|
+
branch,
|
|
3790
3819
|
rootDir: options.rootDir,
|
|
3791
3820
|
port,
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3821
|
+
env: Object.keys(envVars).length > 0 ? envVars : void 0,
|
|
3822
|
+
region: options.region,
|
|
3823
|
+
buildCommand: options.buildCommand,
|
|
3824
|
+
startCommand: options.startCommand
|
|
3795
3825
|
});
|
|
3796
3826
|
deploymentId = serverResult.deploymentId ?? "";
|
|
3797
3827
|
if (!deploymentId) {
|
|
3798
3828
|
console.log(
|
|
3799
3829
|
source_default.green("\u2713 Server created: ") + source_default.gray(serverResult.server.id)
|
|
3800
3830
|
);
|
|
3801
|
-
console.log(
|
|
3802
|
-
source_default.yellow(
|
|
3803
|
-
"\u26A0\uFE0F No deployment was triggered. You may need to trigger one manually."
|
|
3804
|
-
)
|
|
3805
|
-
);
|
|
3831
|
+
console.log(source_default.yellow("\u26A0\uFE0F No deployment was triggered."));
|
|
3806
3832
|
return;
|
|
3807
3833
|
}
|
|
3808
3834
|
await saveProjectLink(cwd, {
|
|
@@ -3817,10 +3843,22 @@ async function deployCommand(options) {
|
|
|
3817
3843
|
console.log(source_default.gray(` Future deploys will reuse the same URL
|
|
3818
3844
|
`));
|
|
3819
3845
|
}
|
|
3846
|
+
if (!deploymentId) {
|
|
3847
|
+
console.log(source_default.red("\u2717 No deployment was created."));
|
|
3848
|
+
process.exit(1);
|
|
3849
|
+
}
|
|
3820
3850
|
console.log(
|
|
3821
3851
|
source_default.green("\u2713 Deployment created: ") + source_default.gray(deploymentId)
|
|
3822
3852
|
);
|
|
3823
3853
|
await displayDeploymentProgress(api, deploymentId, { yes: options.yes });
|
|
3854
|
+
if (options.open) {
|
|
3855
|
+
const dep = await api.getDeployment(deploymentId);
|
|
3856
|
+
const url = getMcpServerUrl(dep);
|
|
3857
|
+
if (url) {
|
|
3858
|
+
console.log(source_default.gray("\nOpening in browser..."));
|
|
3859
|
+
await open_default(url);
|
|
3860
|
+
}
|
|
3861
|
+
}
|
|
3824
3862
|
} catch (error) {
|
|
3825
3863
|
console.error(
|
|
3826
3864
|
source_default.red.bold("\n\u2717 Deployment failed:"),
|
|
@@ -3939,11 +3977,15 @@ async function getDeploymentCommand(deploymentId) {
|
|
|
3939
3977
|
console.log(
|
|
3940
3978
|
source_default.white("Status: ") + statusColor(deployment.status)
|
|
3941
3979
|
);
|
|
3942
|
-
if (deployment.
|
|
3980
|
+
if (deployment.serverId) {
|
|
3943
3981
|
console.log(
|
|
3944
|
-
source_default.white("
|
|
3982
|
+
source_default.white("Server ID: ") + source_default.gray(deployment.serverId)
|
|
3945
3983
|
);
|
|
3946
3984
|
}
|
|
3985
|
+
const mcpUrl = getMcpServerUrl(deployment);
|
|
3986
|
+
if (mcpUrl) {
|
|
3987
|
+
console.log(source_default.white("MCP URL: ") + source_default.cyan(mcpUrl));
|
|
3988
|
+
}
|
|
3947
3989
|
if (deployment.gitBranch) {
|
|
3948
3990
|
console.log(
|
|
3949
3991
|
source_default.white("Branch: ") + source_default.gray(deployment.gitBranch)
|
|
@@ -4260,6 +4302,295 @@ function createDeploymentsCommand() {
|
|
|
4260
4302
|
return deploymentsCommand;
|
|
4261
4303
|
}
|
|
4262
4304
|
|
|
4305
|
+
// src/commands/servers.ts
|
|
4306
|
+
import { Command as Command3 } from "commander";
|
|
4307
|
+
async function prompt3(question) {
|
|
4308
|
+
const readline = await import("readline");
|
|
4309
|
+
const rl = readline.createInterface({
|
|
4310
|
+
input: process.stdin,
|
|
4311
|
+
output: process.stdout
|
|
4312
|
+
});
|
|
4313
|
+
return new Promise((resolve2) => {
|
|
4314
|
+
rl.question(question, (answer) => {
|
|
4315
|
+
rl.close();
|
|
4316
|
+
const trimmedAnswer = answer.trim().toLowerCase();
|
|
4317
|
+
resolve2(trimmedAnswer === "y" || trimmedAnswer === "yes");
|
|
4318
|
+
});
|
|
4319
|
+
});
|
|
4320
|
+
}
|
|
4321
|
+
function isRecord(v) {
|
|
4322
|
+
return typeof v === "object" && v !== null;
|
|
4323
|
+
}
|
|
4324
|
+
function pickStr(obj, key) {
|
|
4325
|
+
if (!isRecord(obj)) return "-";
|
|
4326
|
+
const v = obj[key];
|
|
4327
|
+
if (typeof v === "string") return v;
|
|
4328
|
+
if (v != null && typeof v !== "object") return String(v);
|
|
4329
|
+
return "-";
|
|
4330
|
+
}
|
|
4331
|
+
async function applyOrgOption(api, org) {
|
|
4332
|
+
if (!org) return;
|
|
4333
|
+
const authInfo = await api.testAuth();
|
|
4334
|
+
const match = (authInfo.orgs ?? []).find(
|
|
4335
|
+
(o) => o.slug === org || o.id === org || o.name.toLowerCase() === org.toLowerCase()
|
|
4336
|
+
);
|
|
4337
|
+
if (!match) {
|
|
4338
|
+
console.error(
|
|
4339
|
+
source_default.red(
|
|
4340
|
+
`\u2717 Organization "${org}" not found. Run ${source_default.white("npx mcp-use org list")} to see available organizations.`
|
|
4341
|
+
)
|
|
4342
|
+
);
|
|
4343
|
+
process.exit(1);
|
|
4344
|
+
}
|
|
4345
|
+
api.setOrgId(match.id);
|
|
4346
|
+
const slug = match.slug ? source_default.gray(` (${match.slug})`) : "";
|
|
4347
|
+
console.log(source_default.gray("Organization: ") + source_default.cyan(match.name) + slug);
|
|
4348
|
+
}
|
|
4349
|
+
function getStatusColor2(status) {
|
|
4350
|
+
const s = status.toLowerCase();
|
|
4351
|
+
if (s.includes("run") || s === "active") return source_default.green;
|
|
4352
|
+
if (s.includes("fail") || s.includes("error")) return source_default.red;
|
|
4353
|
+
if (s.includes("build") || s.includes("pend")) return source_default.yellow;
|
|
4354
|
+
return source_default.gray;
|
|
4355
|
+
}
|
|
4356
|
+
async function listServersCommand(options) {
|
|
4357
|
+
try {
|
|
4358
|
+
if (!await isLoggedIn()) {
|
|
4359
|
+
console.log(source_default.red("\u2717 You are not logged in."));
|
|
4360
|
+
console.log(
|
|
4361
|
+
source_default.gray(
|
|
4362
|
+
"Run " + source_default.white("npx mcp-use login") + " to get started."
|
|
4363
|
+
)
|
|
4364
|
+
);
|
|
4365
|
+
process.exit(1);
|
|
4366
|
+
}
|
|
4367
|
+
const api = await McpUseAPI.create();
|
|
4368
|
+
await applyOrgOption(api, options.org);
|
|
4369
|
+
if (options.org) console.log();
|
|
4370
|
+
const limit = options.limit ? parseInt(options.limit, 10) : void 0;
|
|
4371
|
+
const skip = options.skip ? parseInt(options.skip, 10) : void 0;
|
|
4372
|
+
if (limit !== void 0 && (Number.isNaN(limit) || limit < 1)) {
|
|
4373
|
+
console.log(source_default.red("\u2717 Invalid --limit"));
|
|
4374
|
+
process.exit(1);
|
|
4375
|
+
}
|
|
4376
|
+
if (skip !== void 0 && (Number.isNaN(skip) || skip < 0)) {
|
|
4377
|
+
console.log(source_default.red("\u2717 Invalid --skip"));
|
|
4378
|
+
process.exit(1);
|
|
4379
|
+
}
|
|
4380
|
+
const servers = await api.listServers({
|
|
4381
|
+
limit,
|
|
4382
|
+
skip,
|
|
4383
|
+
sort: options.sort
|
|
4384
|
+
});
|
|
4385
|
+
if (servers.length === 0) {
|
|
4386
|
+
console.log(source_default.yellow("No servers found."));
|
|
4387
|
+
console.log(
|
|
4388
|
+
source_default.gray(
|
|
4389
|
+
"\nCreate one by deploying with " + source_default.white("mcp-use deploy")
|
|
4390
|
+
)
|
|
4391
|
+
);
|
|
4392
|
+
return;
|
|
4393
|
+
}
|
|
4394
|
+
console.log(source_default.cyan.bold(`
|
|
4395
|
+
\u{1F5A5} Servers (${servers.length})
|
|
4396
|
+
`));
|
|
4397
|
+
console.log(
|
|
4398
|
+
source_default.white.bold(
|
|
4399
|
+
`${"ID".padEnd(38)} ${"NAME".padEnd(22)} ${"STATUS".padEnd(14)} ${"REPO".padEnd(32)} ${"MCP URL".padEnd(52)}`
|
|
4400
|
+
)
|
|
4401
|
+
);
|
|
4402
|
+
console.log(source_default.gray("\u2500".repeat(165)));
|
|
4403
|
+
for (const s of servers) {
|
|
4404
|
+
const id = s.id.substring(0, 37).padEnd(38);
|
|
4405
|
+
const name = (s.name || s.slug || "-").substring(0, 21).padEnd(22);
|
|
4406
|
+
const statusColor = getStatusColor2(s.status);
|
|
4407
|
+
const status = statusColor(s.status.substring(0, 13).padEnd(14));
|
|
4408
|
+
const repo = (s.connectedRepository?.repoFullName ?? "-").substring(0, 31).padEnd(32);
|
|
4409
|
+
const mcp = getMcpServerUrlForCloudServer(s).substring(0, 51).padEnd(52);
|
|
4410
|
+
console.log(
|
|
4411
|
+
`${source_default.gray(id)} ${name} ${status} ${source_default.gray(repo)} ${source_default.cyan(mcp)}`
|
|
4412
|
+
);
|
|
4413
|
+
}
|
|
4414
|
+
console.log();
|
|
4415
|
+
} catch (error) {
|
|
4416
|
+
console.error(
|
|
4417
|
+
source_default.red.bold("\n\u2717 Failed to list servers:"),
|
|
4418
|
+
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
4419
|
+
);
|
|
4420
|
+
process.exit(1);
|
|
4421
|
+
}
|
|
4422
|
+
}
|
|
4423
|
+
async function getServerCommand(idOrSlug, options) {
|
|
4424
|
+
try {
|
|
4425
|
+
if (!await isLoggedIn()) {
|
|
4426
|
+
console.log(source_default.red("\u2717 You are not logged in."));
|
|
4427
|
+
console.log(
|
|
4428
|
+
source_default.gray(
|
|
4429
|
+
"Run " + source_default.white("npx mcp-use login") + " to get started."
|
|
4430
|
+
)
|
|
4431
|
+
);
|
|
4432
|
+
process.exit(1);
|
|
4433
|
+
}
|
|
4434
|
+
const api = await McpUseAPI.create();
|
|
4435
|
+
await applyOrgOption(api, options.org);
|
|
4436
|
+
if (options.org) console.log();
|
|
4437
|
+
const server = await api.getServer(idOrSlug);
|
|
4438
|
+
console.log(source_default.cyan.bold("\n\u{1F5A5} Server Details\n"));
|
|
4439
|
+
console.log(source_default.white("ID: ") + source_default.gray(server.id));
|
|
4440
|
+
if (server.slug) {
|
|
4441
|
+
console.log(source_default.white("Slug: ") + source_default.cyan(server.slug));
|
|
4442
|
+
}
|
|
4443
|
+
console.log(
|
|
4444
|
+
source_default.white("Name: ") + source_default.cyan(server.name ?? "-")
|
|
4445
|
+
);
|
|
4446
|
+
const statusColor = getStatusColor2(server.status);
|
|
4447
|
+
console.log(source_default.white("Status: ") + statusColor(server.status));
|
|
4448
|
+
if (server.latestDeploymentStatus) {
|
|
4449
|
+
console.log(
|
|
4450
|
+
source_default.white("Last deploy: ") + source_default.gray(server.latestDeploymentStatus)
|
|
4451
|
+
);
|
|
4452
|
+
}
|
|
4453
|
+
console.log(source_default.white("Region: ") + source_default.gray(server.region));
|
|
4454
|
+
console.log(
|
|
4455
|
+
source_default.white("MCP URL: ") + source_default.cyan(getMcpServerUrlForCloudServer(server))
|
|
4456
|
+
);
|
|
4457
|
+
if (server.connectedRepository) {
|
|
4458
|
+
const cr = server.connectedRepository;
|
|
4459
|
+
console.log(source_default.white("\nRepository"));
|
|
4460
|
+
console.log(source_default.white(" Full name: ") + source_default.gray(cr.repoFullName));
|
|
4461
|
+
console.log(
|
|
4462
|
+
source_default.white(" Prod branch: ") + source_default.gray(cr.productionBranch)
|
|
4463
|
+
);
|
|
4464
|
+
}
|
|
4465
|
+
if (server.activeDeploymentId) {
|
|
4466
|
+
console.log(
|
|
4467
|
+
source_default.white("\nActive deployment: ") + source_default.cyan(server.activeDeploymentId)
|
|
4468
|
+
);
|
|
4469
|
+
}
|
|
4470
|
+
if (server.previousDeploymentId) {
|
|
4471
|
+
console.log(
|
|
4472
|
+
source_default.white("Previous deployment: ") + source_default.gray(server.previousDeploymentId)
|
|
4473
|
+
);
|
|
4474
|
+
}
|
|
4475
|
+
const depCount = server._count?.deployments;
|
|
4476
|
+
if (depCount != null) {
|
|
4477
|
+
console.log(
|
|
4478
|
+
source_default.white("Deployment count: ") + source_default.gray(String(depCount))
|
|
4479
|
+
);
|
|
4480
|
+
}
|
|
4481
|
+
console.log(
|
|
4482
|
+
source_default.white("Created: ") + source_default.gray(formatRelativeTime(server.createdAt))
|
|
4483
|
+
);
|
|
4484
|
+
console.log(
|
|
4485
|
+
source_default.white("Updated: ") + source_default.gray(formatRelativeTime(server.updatedAt))
|
|
4486
|
+
);
|
|
4487
|
+
const config = await readConfig();
|
|
4488
|
+
const base = (await getWebUrl()).replace(/\/$/, "");
|
|
4489
|
+
if (config.orgSlug) {
|
|
4490
|
+
console.log(
|
|
4491
|
+
source_default.white("\nDashboard: ") + source_default.cyan(`${base}/cloud/${config.orgSlug}/servers/${server.id}`)
|
|
4492
|
+
);
|
|
4493
|
+
} else {
|
|
4494
|
+
console.log(
|
|
4495
|
+
source_default.white("\nDashboard: ") + source_default.cyan(`${base}/cloud/servers/${server.id}`)
|
|
4496
|
+
);
|
|
4497
|
+
}
|
|
4498
|
+
if (Array.isArray(server.deployments) && server.deployments.length > 0) {
|
|
4499
|
+
console.log(source_default.cyan.bold("\nRecent deployments\n"));
|
|
4500
|
+
console.log(
|
|
4501
|
+
source_default.white.bold(
|
|
4502
|
+
`${"ID".padEnd(40)} ${"NAME".padEnd(24)} ${"STATUS".padEnd(12)} ${"UPDATED"}`
|
|
4503
|
+
)
|
|
4504
|
+
);
|
|
4505
|
+
console.log(source_default.gray("\u2500".repeat(100)));
|
|
4506
|
+
for (const d of server.deployments) {
|
|
4507
|
+
const did = pickStr(d, "id").padEnd(40);
|
|
4508
|
+
const dname = pickStr(d, "name").substring(0, 23).padEnd(24);
|
|
4509
|
+
const dst = pickStr(d, "status").padEnd(12);
|
|
4510
|
+
const du = pickStr(d, "updatedAt");
|
|
4511
|
+
const updated = du !== "-" ? formatRelativeTime(du) : source_default.gray("-");
|
|
4512
|
+
const sc = getStatusColor2(dst.trim());
|
|
4513
|
+
console.log(
|
|
4514
|
+
`${source_default.gray(did)} ${dname} ${sc(dst)} ${source_default.gray(updated)}`
|
|
4515
|
+
);
|
|
4516
|
+
}
|
|
4517
|
+
}
|
|
4518
|
+
console.log();
|
|
4519
|
+
} catch (error) {
|
|
4520
|
+
console.error(
|
|
4521
|
+
source_default.red.bold("\n\u2717 Failed to get server:"),
|
|
4522
|
+
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
4523
|
+
);
|
|
4524
|
+
process.exit(1);
|
|
4525
|
+
}
|
|
4526
|
+
}
|
|
4527
|
+
async function deleteServerCommand(serverId, options) {
|
|
4528
|
+
try {
|
|
4529
|
+
if (!await isLoggedIn()) {
|
|
4530
|
+
console.log(source_default.red("\u2717 You are not logged in."));
|
|
4531
|
+
console.log(
|
|
4532
|
+
source_default.gray(
|
|
4533
|
+
"Run " + source_default.white("npx mcp-use login") + " to get started."
|
|
4534
|
+
)
|
|
4535
|
+
);
|
|
4536
|
+
process.exit(1);
|
|
4537
|
+
}
|
|
4538
|
+
const api = await McpUseAPI.create();
|
|
4539
|
+
await applyOrgOption(api, options.org);
|
|
4540
|
+
if (options.org) console.log();
|
|
4541
|
+
const server = await api.getServer(serverId);
|
|
4542
|
+
if (!options.yes) {
|
|
4543
|
+
console.log(
|
|
4544
|
+
source_default.yellow(
|
|
4545
|
+
`
|
|
4546
|
+
\u26A0\uFE0F You are about to delete server: ${source_default.white(server.name || server.slug || server.id)}`
|
|
4547
|
+
)
|
|
4548
|
+
);
|
|
4549
|
+
console.log(source_default.gray(` ID: ${server.id}`));
|
|
4550
|
+
if (server.connectedRepository?.repoFullName) {
|
|
4551
|
+
console.log(
|
|
4552
|
+
source_default.gray(` Repo: ${server.connectedRepository.repoFullName}
|
|
4553
|
+
`)
|
|
4554
|
+
);
|
|
4555
|
+
} else {
|
|
4556
|
+
console.log();
|
|
4557
|
+
}
|
|
4558
|
+
const confirmed = await prompt3(
|
|
4559
|
+
source_default.white(
|
|
4560
|
+
"This deletes the server and all its deployments. Continue? (y/N): "
|
|
4561
|
+
)
|
|
4562
|
+
);
|
|
4563
|
+
if (!confirmed) {
|
|
4564
|
+
console.log(source_default.gray("Deletion cancelled."));
|
|
4565
|
+
return;
|
|
4566
|
+
}
|
|
4567
|
+
}
|
|
4568
|
+
await api.deleteServer(server.id);
|
|
4569
|
+
console.log(
|
|
4570
|
+
source_default.green.bold(
|
|
4571
|
+
`
|
|
4572
|
+
\u2713 Server deleted: ${server.name || server.slug || server.id}
|
|
4573
|
+
`
|
|
4574
|
+
)
|
|
4575
|
+
);
|
|
4576
|
+
} catch (error) {
|
|
4577
|
+
console.error(
|
|
4578
|
+
source_default.red.bold("\n\u2717 Failed to delete server:"),
|
|
4579
|
+
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
4580
|
+
);
|
|
4581
|
+
process.exit(1);
|
|
4582
|
+
}
|
|
4583
|
+
}
|
|
4584
|
+
function createServersCommand() {
|
|
4585
|
+
const serversCommand = new Command3("servers").description(
|
|
4586
|
+
"Manage cloud servers (Git-backed deploy targets)"
|
|
4587
|
+
);
|
|
4588
|
+
serversCommand.command("list").alias("ls").description("List servers for the current organization").option("--org <slug-or-id>", "Target organization (slug, id, or name)").option("--limit <n>", "Page size (1\u2013100, default 50)").option("--skip <n>", "Offset for pagination").option("--sort <field:asc|desc>", "Sort (e.g. updatedAt:desc)").action(listServersCommand);
|
|
4589
|
+
serversCommand.command("get").argument("<id-or-slug>", "Server UUID or slug").option("--org <slug-or-id>", "Resolve org context before fetch").description("Show server details and recent deployments").action(getServerCommand);
|
|
4590
|
+
serversCommand.command("delete").alias("rm").argument("<server-id>", "Server UUID (or slug if API accepts it)").option("-y, --yes", "Skip confirmation prompt").option("--org <slug-or-id>", "Target organization").description("Delete a server and all its deployments").action(deleteServerCommand);
|
|
4591
|
+
return serversCommand;
|
|
4592
|
+
}
|
|
4593
|
+
|
|
4263
4594
|
// src/commands/org.ts
|
|
4264
4595
|
async function ensureLoggedIn() {
|
|
4265
4596
|
if (!await isLoggedIn()) {
|
|
@@ -4380,7 +4711,7 @@ async function orgCurrentCommand() {
|
|
|
4380
4711
|
}
|
|
4381
4712
|
|
|
4382
4713
|
// src/commands/skills.ts
|
|
4383
|
-
import { Command as
|
|
4714
|
+
import { Command as Command4 } from "commander";
|
|
4384
4715
|
import { cpSync, existsSync as existsSync2, mkdtempSync, readdirSync, rmSync } from "fs";
|
|
4385
4716
|
import { tmpdir } from "os";
|
|
4386
4717
|
import { join as join2, resolve } from "path";
|
|
@@ -4450,7 +4781,7 @@ async function addSkillsToProject(projectPath) {
|
|
|
4450
4781
|
}
|
|
4451
4782
|
}
|
|
4452
4783
|
function createSkillsCommand() {
|
|
4453
|
-
const skills = new
|
|
4784
|
+
const skills = new Command4("skills").description(
|
|
4454
4785
|
"Manage mcp-use AI agent skills"
|
|
4455
4786
|
);
|
|
4456
4787
|
const installAction = async (options) => {
|
|
@@ -4626,7 +4957,7 @@ A new release of ${source_default.bold(PACKAGE_NAME)} is available: ${source_def
|
|
|
4626
4957
|
}
|
|
4627
4958
|
|
|
4628
4959
|
// src/index.ts
|
|
4629
|
-
var program = new
|
|
4960
|
+
var program = new Command5();
|
|
4630
4961
|
var packageContent = readFileSync2(
|
|
4631
4962
|
path7.join(__dirname, "../package.json"),
|
|
4632
4963
|
"utf-8"
|
|
@@ -6454,7 +6785,13 @@ program.command("deploy").description("Deploy MCP server from GitHub to Manufact
|
|
|
6454
6785
|
).option(
|
|
6455
6786
|
"--org <slug-or-id>",
|
|
6456
6787
|
"Deploy to a specific organization (by slug or ID)"
|
|
6457
|
-
).option("-y, --yes", "Skip confirmation prompts").
|
|
6788
|
+
).option("-y, --yes", "Skip confirmation prompts").option("--region <region>", "Deploy region: US, EU, or APAC (default: US)").option(
|
|
6789
|
+
"--build-command <cmd>",
|
|
6790
|
+
"Custom build command (overrides auto-detection)"
|
|
6791
|
+
).option(
|
|
6792
|
+
"--start-command <cmd>",
|
|
6793
|
+
"Custom start command (overrides auto-detection)"
|
|
6794
|
+
).action(async (options) => {
|
|
6458
6795
|
await deployCommand({
|
|
6459
6796
|
open: options.open,
|
|
6460
6797
|
name: options.name,
|
|
@@ -6465,11 +6802,15 @@ program.command("deploy").description("Deploy MCP server from GitHub to Manufact
|
|
|
6465
6802
|
envFile: options.envFile,
|
|
6466
6803
|
rootDir: options.rootDir,
|
|
6467
6804
|
org: options.org,
|
|
6468
|
-
yes: options.yes
|
|
6805
|
+
yes: options.yes,
|
|
6806
|
+
region: options.region,
|
|
6807
|
+
buildCommand: options.buildCommand,
|
|
6808
|
+
startCommand: options.startCommand
|
|
6469
6809
|
});
|
|
6470
6810
|
});
|
|
6471
6811
|
program.addCommand(createClientCommand());
|
|
6472
6812
|
program.addCommand(createDeploymentsCommand());
|
|
6813
|
+
program.addCommand(createServersCommand());
|
|
6473
6814
|
program.addCommand(createSkillsCommand());
|
|
6474
6815
|
program.command("generate-types").description(
|
|
6475
6816
|
"Generate TypeScript type definitions for tools (writes .mcp-use/tool-registry.d.ts)"
|