@mcp-use/cli 2.5.1 → 2.6.0-canary.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/client.d.ts +95 -0
- package/dist/commands/client.d.ts.map +1 -0
- package/dist/index.cjs +3970 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +3078 -1028
- package/dist/index.js.map +1 -0
- package/dist/utils/format.d.ts +58 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/session-storage.d.ts +65 -0
- package/dist/utils/session-storage.d.ts.map +1 -0
- package/package.json +20 -8
- package/dist/index.mjs +0 -1881
package/dist/index.js
CHANGED
|
@@ -1,371 +1,1444 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
-
for (let key of __getOwnPropNames(from))
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
-
}
|
|
15
|
-
return to;
|
|
16
|
-
};
|
|
17
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
-
mod
|
|
24
|
-
));
|
|
25
|
-
|
|
26
|
-
// src/index.ts
|
|
27
|
-
var import_chalk3 = __toESM(require("chalk"));
|
|
28
|
-
var import_commander = require("commander");
|
|
29
|
-
var import_config4 = require("dotenv/config");
|
|
30
|
-
var import_node_child_process3 = require("child_process");
|
|
31
|
-
var import_node_fs3 = require("fs");
|
|
32
|
-
var import_promises = require("fs/promises");
|
|
33
|
-
var import_node_path3 = __toESM(require("path"));
|
|
34
|
-
var import_open3 = __toESM(require("open"));
|
|
35
2
|
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
var
|
|
3
|
+
// ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3_yaml@2.8.1/node_modules/tsup/assets/esm_shims.js
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
var getFilename = () => fileURLToPath(import.meta.url);
|
|
7
|
+
var getDirname = () => path.dirname(getFilename());
|
|
8
|
+
var __dirname = /* @__PURE__ */ getDirname();
|
|
40
9
|
|
|
41
|
-
//
|
|
42
|
-
var
|
|
43
|
-
var
|
|
44
|
-
var
|
|
45
|
-
var
|
|
46
|
-
var
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
10
|
+
// ../../node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
11
|
+
var ANSI_BACKGROUND_OFFSET = 10;
|
|
12
|
+
var wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
|
|
13
|
+
var wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
|
|
14
|
+
var wrapAnsi16m = (offset = 0) => (red, green, blue) => `\x1B[${38 + offset};2;${red};${green};${blue}m`;
|
|
15
|
+
var styles = {
|
|
16
|
+
modifier: {
|
|
17
|
+
reset: [0, 0],
|
|
18
|
+
// 21 isn't widely supported and 22 does the same thing
|
|
19
|
+
bold: [1, 22],
|
|
20
|
+
dim: [2, 22],
|
|
21
|
+
italic: [3, 23],
|
|
22
|
+
underline: [4, 24],
|
|
23
|
+
overline: [53, 55],
|
|
24
|
+
inverse: [7, 27],
|
|
25
|
+
hidden: [8, 28],
|
|
26
|
+
strikethrough: [9, 29]
|
|
27
|
+
},
|
|
28
|
+
color: {
|
|
29
|
+
black: [30, 39],
|
|
30
|
+
red: [31, 39],
|
|
31
|
+
green: [32, 39],
|
|
32
|
+
yellow: [33, 39],
|
|
33
|
+
blue: [34, 39],
|
|
34
|
+
magenta: [35, 39],
|
|
35
|
+
cyan: [36, 39],
|
|
36
|
+
white: [37, 39],
|
|
37
|
+
// Bright color
|
|
38
|
+
blackBright: [90, 39],
|
|
39
|
+
gray: [90, 39],
|
|
40
|
+
// Alias of `blackBright`
|
|
41
|
+
grey: [90, 39],
|
|
42
|
+
// Alias of `blackBright`
|
|
43
|
+
redBright: [91, 39],
|
|
44
|
+
greenBright: [92, 39],
|
|
45
|
+
yellowBright: [93, 39],
|
|
46
|
+
blueBright: [94, 39],
|
|
47
|
+
magentaBright: [95, 39],
|
|
48
|
+
cyanBright: [96, 39],
|
|
49
|
+
whiteBright: [97, 39]
|
|
50
|
+
},
|
|
51
|
+
bgColor: {
|
|
52
|
+
bgBlack: [40, 49],
|
|
53
|
+
bgRed: [41, 49],
|
|
54
|
+
bgGreen: [42, 49],
|
|
55
|
+
bgYellow: [43, 49],
|
|
56
|
+
bgBlue: [44, 49],
|
|
57
|
+
bgMagenta: [45, 49],
|
|
58
|
+
bgCyan: [46, 49],
|
|
59
|
+
bgWhite: [47, 49],
|
|
60
|
+
// Bright color
|
|
61
|
+
bgBlackBright: [100, 49],
|
|
62
|
+
bgGray: [100, 49],
|
|
63
|
+
// Alias of `bgBlackBright`
|
|
64
|
+
bgGrey: [100, 49],
|
|
65
|
+
// Alias of `bgBlackBright`
|
|
66
|
+
bgRedBright: [101, 49],
|
|
67
|
+
bgGreenBright: [102, 49],
|
|
68
|
+
bgYellowBright: [103, 49],
|
|
69
|
+
bgBlueBright: [104, 49],
|
|
70
|
+
bgMagentaBright: [105, 49],
|
|
71
|
+
bgCyanBright: [106, 49],
|
|
72
|
+
bgWhiteBright: [107, 49]
|
|
61
73
|
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
74
|
+
};
|
|
75
|
+
var modifierNames = Object.keys(styles.modifier);
|
|
76
|
+
var foregroundColorNames = Object.keys(styles.color);
|
|
77
|
+
var backgroundColorNames = Object.keys(styles.bgColor);
|
|
78
|
+
var colorNames = [...foregroundColorNames, ...backgroundColorNames];
|
|
79
|
+
function assembleStyles() {
|
|
80
|
+
const codes = /* @__PURE__ */ new Map();
|
|
81
|
+
for (const [groupName, group] of Object.entries(styles)) {
|
|
82
|
+
for (const [styleName, style] of Object.entries(group)) {
|
|
83
|
+
styles[styleName] = {
|
|
84
|
+
open: `\x1B[${style[0]}m`,
|
|
85
|
+
close: `\x1B[${style[1]}m`
|
|
86
|
+
};
|
|
87
|
+
group[styleName] = styles[styleName];
|
|
88
|
+
codes.set(style[0], style[1]);
|
|
89
|
+
}
|
|
90
|
+
Object.defineProperty(styles, groupName, {
|
|
91
|
+
value: group,
|
|
92
|
+
enumerable: false
|
|
93
|
+
});
|
|
71
94
|
}
|
|
95
|
+
Object.defineProperty(styles, "codes", {
|
|
96
|
+
value: codes,
|
|
97
|
+
enumerable: false
|
|
98
|
+
});
|
|
99
|
+
styles.color.close = "\x1B[39m";
|
|
100
|
+
styles.bgColor.close = "\x1B[49m";
|
|
101
|
+
styles.color.ansi = wrapAnsi16();
|
|
102
|
+
styles.color.ansi256 = wrapAnsi256();
|
|
103
|
+
styles.color.ansi16m = wrapAnsi16m();
|
|
104
|
+
styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
|
|
105
|
+
styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
|
|
106
|
+
styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
|
|
107
|
+
Object.defineProperties(styles, {
|
|
108
|
+
rgbToAnsi256: {
|
|
109
|
+
value(red, green, blue) {
|
|
110
|
+
if (red === green && green === blue) {
|
|
111
|
+
if (red < 8) {
|
|
112
|
+
return 16;
|
|
113
|
+
}
|
|
114
|
+
if (red > 248) {
|
|
115
|
+
return 231;
|
|
116
|
+
}
|
|
117
|
+
return Math.round((red - 8) / 247 * 24) + 232;
|
|
118
|
+
}
|
|
119
|
+
return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
|
|
120
|
+
},
|
|
121
|
+
enumerable: false
|
|
122
|
+
},
|
|
123
|
+
hexToRgb: {
|
|
124
|
+
value(hex) {
|
|
125
|
+
const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
|
|
126
|
+
if (!matches) {
|
|
127
|
+
return [0, 0, 0];
|
|
128
|
+
}
|
|
129
|
+
let [colorString] = matches;
|
|
130
|
+
if (colorString.length === 3) {
|
|
131
|
+
colorString = [...colorString].map((character) => character + character).join("");
|
|
132
|
+
}
|
|
133
|
+
const integer = Number.parseInt(colorString, 16);
|
|
134
|
+
return [
|
|
135
|
+
/* eslint-disable no-bitwise */
|
|
136
|
+
integer >> 16 & 255,
|
|
137
|
+
integer >> 8 & 255,
|
|
138
|
+
integer & 255
|
|
139
|
+
/* eslint-enable no-bitwise */
|
|
140
|
+
];
|
|
141
|
+
},
|
|
142
|
+
enumerable: false
|
|
143
|
+
},
|
|
144
|
+
hexToAnsi256: {
|
|
145
|
+
value: (hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
|
|
146
|
+
enumerable: false
|
|
147
|
+
},
|
|
148
|
+
ansi256ToAnsi: {
|
|
149
|
+
value(code) {
|
|
150
|
+
if (code < 8) {
|
|
151
|
+
return 30 + code;
|
|
152
|
+
}
|
|
153
|
+
if (code < 16) {
|
|
154
|
+
return 90 + (code - 8);
|
|
155
|
+
}
|
|
156
|
+
let red;
|
|
157
|
+
let green;
|
|
158
|
+
let blue;
|
|
159
|
+
if (code >= 232) {
|
|
160
|
+
red = ((code - 232) * 10 + 8) / 255;
|
|
161
|
+
green = red;
|
|
162
|
+
blue = red;
|
|
163
|
+
} else {
|
|
164
|
+
code -= 16;
|
|
165
|
+
const remainder = code % 36;
|
|
166
|
+
red = Math.floor(code / 36) / 5;
|
|
167
|
+
green = Math.floor(remainder / 6) / 5;
|
|
168
|
+
blue = remainder % 6 / 5;
|
|
169
|
+
}
|
|
170
|
+
const value = Math.max(red, green, blue) * 2;
|
|
171
|
+
if (value === 0) {
|
|
172
|
+
return 30;
|
|
173
|
+
}
|
|
174
|
+
let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
|
|
175
|
+
if (value === 2) {
|
|
176
|
+
result += 60;
|
|
177
|
+
}
|
|
178
|
+
return result;
|
|
179
|
+
},
|
|
180
|
+
enumerable: false
|
|
181
|
+
},
|
|
182
|
+
rgbToAnsi: {
|
|
183
|
+
value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
|
|
184
|
+
enumerable: false
|
|
185
|
+
},
|
|
186
|
+
hexToAnsi: {
|
|
187
|
+
value: (hex) => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),
|
|
188
|
+
enumerable: false
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
return styles;
|
|
72
192
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
193
|
+
var ansiStyles = assembleStyles();
|
|
194
|
+
var ansi_styles_default = ansiStyles;
|
|
195
|
+
|
|
196
|
+
// ../../node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/vendor/supports-color/index.js
|
|
197
|
+
import process2 from "process";
|
|
198
|
+
import os from "os";
|
|
199
|
+
import tty from "tty";
|
|
200
|
+
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process2.argv) {
|
|
201
|
+
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
202
|
+
const position = argv.indexOf(prefix + flag);
|
|
203
|
+
const terminatorPosition = argv.indexOf("--");
|
|
204
|
+
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
76
205
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
206
|
+
var { env } = process2;
|
|
207
|
+
var flagForceColor;
|
|
208
|
+
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
|
|
209
|
+
flagForceColor = 0;
|
|
210
|
+
} else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
|
|
211
|
+
flagForceColor = 1;
|
|
80
212
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
213
|
+
function envForceColor() {
|
|
214
|
+
if ("FORCE_COLOR" in env) {
|
|
215
|
+
if (env.FORCE_COLOR === "true") {
|
|
216
|
+
return 1;
|
|
217
|
+
}
|
|
218
|
+
if (env.FORCE_COLOR === "false") {
|
|
219
|
+
return 0;
|
|
220
|
+
}
|
|
221
|
+
return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
|
|
222
|
+
}
|
|
84
223
|
}
|
|
85
|
-
|
|
86
|
-
|
|
224
|
+
function translateLevel(level) {
|
|
225
|
+
if (level === 0) {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
level,
|
|
230
|
+
hasBasic: true,
|
|
231
|
+
has256: level >= 2,
|
|
232
|
+
has16m: level >= 3
|
|
233
|
+
};
|
|
87
234
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
apiKey;
|
|
93
|
-
constructor(baseUrl, apiKey) {
|
|
94
|
-
this.baseUrl = baseUrl || "";
|
|
95
|
-
this.apiKey = apiKey;
|
|
235
|
+
function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
236
|
+
const noFlagForceColor = envForceColor();
|
|
237
|
+
if (noFlagForceColor !== void 0) {
|
|
238
|
+
flagForceColor = noFlagForceColor;
|
|
96
239
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
static async create() {
|
|
101
|
-
const baseUrl = await getApiUrl();
|
|
102
|
-
const apiKey = await getApiKey();
|
|
103
|
-
return new _McpUseAPI(baseUrl, apiKey ?? void 0);
|
|
240
|
+
const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
|
|
241
|
+
if (forceColor === 0) {
|
|
242
|
+
return 0;
|
|
104
243
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
async request(endpoint, options = {}) {
|
|
109
|
-
const url = `${this.baseUrl}${endpoint}`;
|
|
110
|
-
const headers = {
|
|
111
|
-
"Content-Type": "application/json",
|
|
112
|
-
...options.headers || {}
|
|
113
|
-
};
|
|
114
|
-
if (this.apiKey) {
|
|
115
|
-
headers["x-api-key"] = this.apiKey;
|
|
116
|
-
}
|
|
117
|
-
const response = await fetch(url, {
|
|
118
|
-
...options,
|
|
119
|
-
headers
|
|
120
|
-
});
|
|
121
|
-
if (!response.ok) {
|
|
122
|
-
const error = await response.text();
|
|
123
|
-
throw new Error(`API request failed: ${response.status} ${error}`);
|
|
244
|
+
if (sniffFlags) {
|
|
245
|
+
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
|
|
246
|
+
return 3;
|
|
124
247
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Create API key using JWT token
|
|
129
|
-
*/
|
|
130
|
-
async createApiKey(jwtToken, name = "CLI") {
|
|
131
|
-
const url = `${this.baseUrl}/api-key`;
|
|
132
|
-
const response = await fetch(url, {
|
|
133
|
-
method: "POST",
|
|
134
|
-
headers: {
|
|
135
|
-
"Content-Type": "application/json",
|
|
136
|
-
Authorization: `Bearer ${jwtToken}`
|
|
137
|
-
},
|
|
138
|
-
body: JSON.stringify({ name })
|
|
139
|
-
});
|
|
140
|
-
if (!response.ok) {
|
|
141
|
-
const error = await response.text();
|
|
142
|
-
throw new Error(`Failed to create API key: ${response.status} ${error}`);
|
|
248
|
+
if (hasFlag("color=256")) {
|
|
249
|
+
return 2;
|
|
143
250
|
}
|
|
144
|
-
return response.json();
|
|
145
251
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
*/
|
|
149
|
-
async testAuth() {
|
|
150
|
-
return this.request("/test-auth");
|
|
252
|
+
if ("TF_BUILD" in env && "AGENT_NAME" in env) {
|
|
253
|
+
return 1;
|
|
151
254
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
*/
|
|
155
|
-
async createDeployment(request) {
|
|
156
|
-
return this.request("/deployments", {
|
|
157
|
-
method: "POST",
|
|
158
|
-
body: JSON.stringify(request)
|
|
159
|
-
});
|
|
255
|
+
if (haveStream && !streamIsTTY && forceColor === void 0) {
|
|
256
|
+
return 0;
|
|
160
257
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
async getDeployment(deploymentId) {
|
|
165
|
-
return this.request(`/deployments/${deploymentId}`);
|
|
258
|
+
const min = forceColor || 0;
|
|
259
|
+
if (env.TERM === "dumb") {
|
|
260
|
+
return min;
|
|
166
261
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const url = `${this.baseUrl}/deployments/${deploymentId}/logs/stream`;
|
|
172
|
-
const headers = {};
|
|
173
|
-
if (this.apiKey) {
|
|
174
|
-
headers["x-api-key"] = this.apiKey;
|
|
175
|
-
}
|
|
176
|
-
const response = await fetch(url, { headers });
|
|
177
|
-
if (!response.ok) {
|
|
178
|
-
throw new Error(`Failed to stream logs: ${response.status}`);
|
|
262
|
+
if (process2.platform === "win32") {
|
|
263
|
+
const osRelease = os.release().split(".");
|
|
264
|
+
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
265
|
+
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
179
266
|
}
|
|
180
|
-
|
|
181
|
-
|
|
267
|
+
return 1;
|
|
268
|
+
}
|
|
269
|
+
if ("CI" in env) {
|
|
270
|
+
if (["GITHUB_ACTIONS", "GITEA_ACTIONS", "CIRCLECI"].some((key) => key in env)) {
|
|
271
|
+
return 3;
|
|
182
272
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
let buffer = "";
|
|
186
|
-
try {
|
|
187
|
-
while (true) {
|
|
188
|
-
const { done, value } = await reader.read();
|
|
189
|
-
if (done) break;
|
|
190
|
-
buffer += decoder.decode(value, { stream: true });
|
|
191
|
-
const lines = buffer.split("\n");
|
|
192
|
-
buffer = lines.pop() || "";
|
|
193
|
-
for (const line of lines) {
|
|
194
|
-
if (line.startsWith("data: ")) {
|
|
195
|
-
const data = line.slice(6);
|
|
196
|
-
try {
|
|
197
|
-
const parsed = JSON.parse(data);
|
|
198
|
-
if (parsed.log) {
|
|
199
|
-
yield parsed.log;
|
|
200
|
-
} else if (parsed.error) {
|
|
201
|
-
throw new Error(parsed.error);
|
|
202
|
-
}
|
|
203
|
-
} catch (e) {
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
} finally {
|
|
209
|
-
reader.releaseLock();
|
|
273
|
+
if (["TRAVIS", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
|
|
274
|
+
return 1;
|
|
210
275
|
}
|
|
276
|
+
return min;
|
|
211
277
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
formData.append("source_type", "upload");
|
|
233
|
-
if (request.source.type === "upload") {
|
|
234
|
-
formData.append("runtime", request.source.runtime || "node");
|
|
235
|
-
formData.append("port", String(request.source.port || 3e3));
|
|
236
|
-
if (request.source.startCommand) {
|
|
237
|
-
formData.append("startCommand", request.source.startCommand);
|
|
238
|
-
}
|
|
239
|
-
if (request.source.buildCommand) {
|
|
240
|
-
formData.append("buildCommand", request.source.buildCommand);
|
|
278
|
+
if ("TEAMCITY_VERSION" in env) {
|
|
279
|
+
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|
280
|
+
}
|
|
281
|
+
if (env.COLORTERM === "truecolor") {
|
|
282
|
+
return 3;
|
|
283
|
+
}
|
|
284
|
+
if (env.TERM === "xterm-kitty") {
|
|
285
|
+
return 3;
|
|
286
|
+
}
|
|
287
|
+
if (env.TERM === "xterm-ghostty") {
|
|
288
|
+
return 3;
|
|
289
|
+
}
|
|
290
|
+
if (env.TERM === "wezterm") {
|
|
291
|
+
return 3;
|
|
292
|
+
}
|
|
293
|
+
if ("TERM_PROGRAM" in env) {
|
|
294
|
+
const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
295
|
+
switch (env.TERM_PROGRAM) {
|
|
296
|
+
case "iTerm.app": {
|
|
297
|
+
return version >= 3 ? 3 : 2;
|
|
241
298
|
}
|
|
242
|
-
|
|
243
|
-
|
|
299
|
+
case "Apple_Terminal": {
|
|
300
|
+
return 2;
|
|
244
301
|
}
|
|
245
302
|
}
|
|
246
|
-
if (request.customDomain) {
|
|
247
|
-
formData.append("customDomain", request.customDomain);
|
|
248
|
-
}
|
|
249
|
-
if (request.healthCheckPath) {
|
|
250
|
-
formData.append("healthCheckPath", request.healthCheckPath);
|
|
251
|
-
}
|
|
252
|
-
const url = `${this.baseUrl}/deployments`;
|
|
253
|
-
const headers = {};
|
|
254
|
-
if (this.apiKey) {
|
|
255
|
-
headers["x-api-key"] = this.apiKey;
|
|
256
|
-
}
|
|
257
|
-
const response = await fetch(url, {
|
|
258
|
-
method: "POST",
|
|
259
|
-
headers,
|
|
260
|
-
body: formData
|
|
261
|
-
});
|
|
262
|
-
if (!response.ok) {
|
|
263
|
-
const error = await response.text();
|
|
264
|
-
throw new Error(`Deployment failed: ${error}`);
|
|
265
|
-
}
|
|
266
|
-
return response.json();
|
|
267
303
|
}
|
|
304
|
+
if (/-256(color)?$/i.test(env.TERM)) {
|
|
305
|
+
return 2;
|
|
306
|
+
}
|
|
307
|
+
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
|
308
|
+
return 1;
|
|
309
|
+
}
|
|
310
|
+
if ("COLORTERM" in env) {
|
|
311
|
+
return 1;
|
|
312
|
+
}
|
|
313
|
+
return min;
|
|
314
|
+
}
|
|
315
|
+
function createSupportsColor(stream, options = {}) {
|
|
316
|
+
const level = _supportsColor(stream, {
|
|
317
|
+
streamIsTTY: stream && stream.isTTY,
|
|
318
|
+
...options
|
|
319
|
+
});
|
|
320
|
+
return translateLevel(level);
|
|
321
|
+
}
|
|
322
|
+
var supportsColor = {
|
|
323
|
+
stdout: createSupportsColor({ isTTY: tty.isatty(1) }),
|
|
324
|
+
stderr: createSupportsColor({ isTTY: tty.isatty(2) })
|
|
268
325
|
};
|
|
326
|
+
var supports_color_default = supportsColor;
|
|
269
327
|
|
|
270
|
-
//
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
await new Promise((resolve, reject) => {
|
|
276
|
-
const server = (0, import_node_http.createServer)();
|
|
277
|
-
server.once("error", reject);
|
|
278
|
-
server.once("listening", () => {
|
|
279
|
-
server.close();
|
|
280
|
-
resolve();
|
|
281
|
-
});
|
|
282
|
-
server.listen(port);
|
|
283
|
-
});
|
|
284
|
-
return port;
|
|
285
|
-
} catch {
|
|
286
|
-
continue;
|
|
287
|
-
}
|
|
328
|
+
// ../../node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/utilities.js
|
|
329
|
+
function stringReplaceAll(string, substring, replacer) {
|
|
330
|
+
let index = string.indexOf(substring);
|
|
331
|
+
if (index === -1) {
|
|
332
|
+
return string;
|
|
288
333
|
}
|
|
289
|
-
|
|
334
|
+
const substringLength = substring.length;
|
|
335
|
+
let endIndex = 0;
|
|
336
|
+
let returnValue = "";
|
|
337
|
+
do {
|
|
338
|
+
returnValue += string.slice(endIndex, index) + substring + replacer;
|
|
339
|
+
endIndex = index + substringLength;
|
|
340
|
+
index = string.indexOf(substring, endIndex);
|
|
341
|
+
} while (index !== -1);
|
|
342
|
+
returnValue += string.slice(endIndex);
|
|
343
|
+
return returnValue;
|
|
290
344
|
}
|
|
291
|
-
|
|
345
|
+
function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
|
|
346
|
+
let endIndex = 0;
|
|
347
|
+
let returnValue = "";
|
|
348
|
+
do {
|
|
349
|
+
const gotCR = string[index - 1] === "\r";
|
|
350
|
+
returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
|
|
351
|
+
endIndex = index + 1;
|
|
352
|
+
index = string.indexOf("\n", endIndex);
|
|
353
|
+
} while (index !== -1);
|
|
354
|
+
returnValue += string.slice(endIndex);
|
|
355
|
+
return returnValue;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// ../../node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/index.js
|
|
359
|
+
var { stdout: stdoutColor, stderr: stderrColor } = supports_color_default;
|
|
360
|
+
var GENERATOR = Symbol("GENERATOR");
|
|
361
|
+
var STYLER = Symbol("STYLER");
|
|
362
|
+
var IS_EMPTY = Symbol("IS_EMPTY");
|
|
363
|
+
var levelMapping = [
|
|
364
|
+
"ansi",
|
|
365
|
+
"ansi",
|
|
366
|
+
"ansi256",
|
|
367
|
+
"ansi16m"
|
|
368
|
+
];
|
|
369
|
+
var styles2 = /* @__PURE__ */ Object.create(null);
|
|
370
|
+
var applyOptions = (object, options = {}) => {
|
|
371
|
+
if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
|
|
372
|
+
throw new Error("The `level` option should be an integer from 0 to 3");
|
|
373
|
+
}
|
|
374
|
+
const colorLevel = stdoutColor ? stdoutColor.level : 0;
|
|
375
|
+
object.level = options.level === void 0 ? colorLevel : options.level;
|
|
376
|
+
};
|
|
377
|
+
var chalkFactory = (options) => {
|
|
378
|
+
const chalk2 = (...strings) => strings.join(" ");
|
|
379
|
+
applyOptions(chalk2, options);
|
|
380
|
+
Object.setPrototypeOf(chalk2, createChalk.prototype);
|
|
381
|
+
return chalk2;
|
|
382
|
+
};
|
|
383
|
+
function createChalk(options) {
|
|
384
|
+
return chalkFactory(options);
|
|
385
|
+
}
|
|
386
|
+
Object.setPrototypeOf(createChalk.prototype, Function.prototype);
|
|
387
|
+
for (const [styleName, style] of Object.entries(ansi_styles_default)) {
|
|
388
|
+
styles2[styleName] = {
|
|
389
|
+
get() {
|
|
390
|
+
const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
|
|
391
|
+
Object.defineProperty(this, styleName, { value: builder });
|
|
392
|
+
return builder;
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
styles2.visible = {
|
|
397
|
+
get() {
|
|
398
|
+
const builder = createBuilder(this, this[STYLER], true);
|
|
399
|
+
Object.defineProperty(this, "visible", { value: builder });
|
|
400
|
+
return builder;
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
var getModelAnsi = (model, level, type, ...arguments_) => {
|
|
404
|
+
if (model === "rgb") {
|
|
405
|
+
if (level === "ansi16m") {
|
|
406
|
+
return ansi_styles_default[type].ansi16m(...arguments_);
|
|
407
|
+
}
|
|
408
|
+
if (level === "ansi256") {
|
|
409
|
+
return ansi_styles_default[type].ansi256(ansi_styles_default.rgbToAnsi256(...arguments_));
|
|
410
|
+
}
|
|
411
|
+
return ansi_styles_default[type].ansi(ansi_styles_default.rgbToAnsi(...arguments_));
|
|
412
|
+
}
|
|
413
|
+
if (model === "hex") {
|
|
414
|
+
return getModelAnsi("rgb", level, type, ...ansi_styles_default.hexToRgb(...arguments_));
|
|
415
|
+
}
|
|
416
|
+
return ansi_styles_default[type][model](...arguments_);
|
|
417
|
+
};
|
|
418
|
+
var usedModels = ["rgb", "hex", "ansi256"];
|
|
419
|
+
for (const model of usedModels) {
|
|
420
|
+
styles2[model] = {
|
|
421
|
+
get() {
|
|
422
|
+
const { level } = this;
|
|
423
|
+
return function(...arguments_) {
|
|
424
|
+
const styler = createStyler(getModelAnsi(model, levelMapping[level], "color", ...arguments_), ansi_styles_default.color.close, this[STYLER]);
|
|
425
|
+
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
|
|
430
|
+
styles2[bgModel] = {
|
|
431
|
+
get() {
|
|
432
|
+
const { level } = this;
|
|
433
|
+
return function(...arguments_) {
|
|
434
|
+
const styler = createStyler(getModelAnsi(model, levelMapping[level], "bgColor", ...arguments_), ansi_styles_default.bgColor.close, this[STYLER]);
|
|
435
|
+
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
var proto = Object.defineProperties(() => {
|
|
441
|
+
}, {
|
|
442
|
+
...styles2,
|
|
443
|
+
level: {
|
|
444
|
+
enumerable: true,
|
|
445
|
+
get() {
|
|
446
|
+
return this[GENERATOR].level;
|
|
447
|
+
},
|
|
448
|
+
set(level) {
|
|
449
|
+
this[GENERATOR].level = level;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
var createStyler = (open2, close, parent) => {
|
|
454
|
+
let openAll;
|
|
455
|
+
let closeAll;
|
|
456
|
+
if (parent === void 0) {
|
|
457
|
+
openAll = open2;
|
|
458
|
+
closeAll = close;
|
|
459
|
+
} else {
|
|
460
|
+
openAll = parent.openAll + open2;
|
|
461
|
+
closeAll = close + parent.closeAll;
|
|
462
|
+
}
|
|
463
|
+
return {
|
|
464
|
+
open: open2,
|
|
465
|
+
close,
|
|
466
|
+
openAll,
|
|
467
|
+
closeAll,
|
|
468
|
+
parent
|
|
469
|
+
};
|
|
470
|
+
};
|
|
471
|
+
var createBuilder = (self, _styler, _isEmpty) => {
|
|
472
|
+
const builder = (...arguments_) => applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" "));
|
|
473
|
+
Object.setPrototypeOf(builder, proto);
|
|
474
|
+
builder[GENERATOR] = self;
|
|
475
|
+
builder[STYLER] = _styler;
|
|
476
|
+
builder[IS_EMPTY] = _isEmpty;
|
|
477
|
+
return builder;
|
|
478
|
+
};
|
|
479
|
+
var applyStyle = (self, string) => {
|
|
480
|
+
if (self.level <= 0 || !string) {
|
|
481
|
+
return self[IS_EMPTY] ? "" : string;
|
|
482
|
+
}
|
|
483
|
+
let styler = self[STYLER];
|
|
484
|
+
if (styler === void 0) {
|
|
485
|
+
return string;
|
|
486
|
+
}
|
|
487
|
+
const { openAll, closeAll } = styler;
|
|
488
|
+
if (string.includes("\x1B")) {
|
|
489
|
+
while (styler !== void 0) {
|
|
490
|
+
string = stringReplaceAll(string, styler.close, styler.open);
|
|
491
|
+
styler = styler.parent;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
const lfIndex = string.indexOf("\n");
|
|
495
|
+
if (lfIndex !== -1) {
|
|
496
|
+
string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
|
|
497
|
+
}
|
|
498
|
+
return openAll + string + closeAll;
|
|
499
|
+
};
|
|
500
|
+
Object.defineProperties(createChalk.prototype, styles2);
|
|
501
|
+
var chalk = createChalk();
|
|
502
|
+
var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
503
|
+
var source_default = chalk;
|
|
504
|
+
|
|
505
|
+
// src/index.ts
|
|
506
|
+
import { Command as Command2 } from "commander";
|
|
507
|
+
import "dotenv/config";
|
|
508
|
+
import { spawn } from "child_process";
|
|
509
|
+
import { readFileSync } from "fs";
|
|
510
|
+
import { access, mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
511
|
+
import path5 from "path";
|
|
512
|
+
|
|
513
|
+
// ../../node_modules/.pnpm/open@11.0.0/node_modules/open/index.js
|
|
514
|
+
import process9 from "process";
|
|
515
|
+
import path2 from "path";
|
|
516
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
517
|
+
import childProcess3 from "child_process";
|
|
518
|
+
import fs6, { constants as fsConstants3 } from "fs/promises";
|
|
519
|
+
|
|
520
|
+
// ../../node_modules/.pnpm/wsl-utils@0.3.0/node_modules/wsl-utils/index.js
|
|
521
|
+
import { promisify as promisify2 } from "util";
|
|
522
|
+
import childProcess2 from "child_process";
|
|
523
|
+
import fs5, { constants as fsConstants2 } from "fs/promises";
|
|
524
|
+
|
|
525
|
+
// ../../node_modules/.pnpm/is-wsl@3.1.0/node_modules/is-wsl/index.js
|
|
526
|
+
import process3 from "process";
|
|
527
|
+
import os2 from "os";
|
|
528
|
+
import fs3 from "fs";
|
|
529
|
+
|
|
530
|
+
// ../../node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.js
|
|
531
|
+
import fs2 from "fs";
|
|
532
|
+
|
|
533
|
+
// ../../node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.js
|
|
534
|
+
import fs from "fs";
|
|
535
|
+
var isDockerCached;
|
|
536
|
+
function hasDockerEnv() {
|
|
537
|
+
try {
|
|
538
|
+
fs.statSync("/.dockerenv");
|
|
539
|
+
return true;
|
|
540
|
+
} catch {
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
function hasDockerCGroup() {
|
|
545
|
+
try {
|
|
546
|
+
return fs.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
|
|
547
|
+
} catch {
|
|
548
|
+
return false;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
function isDocker() {
|
|
552
|
+
if (isDockerCached === void 0) {
|
|
553
|
+
isDockerCached = hasDockerEnv() || hasDockerCGroup();
|
|
554
|
+
}
|
|
555
|
+
return isDockerCached;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// ../../node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.js
|
|
559
|
+
var cachedResult;
|
|
560
|
+
var hasContainerEnv = () => {
|
|
561
|
+
try {
|
|
562
|
+
fs2.statSync("/run/.containerenv");
|
|
563
|
+
return true;
|
|
564
|
+
} catch {
|
|
565
|
+
return false;
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
function isInsideContainer() {
|
|
569
|
+
if (cachedResult === void 0) {
|
|
570
|
+
cachedResult = hasContainerEnv() || isDocker();
|
|
571
|
+
}
|
|
572
|
+
return cachedResult;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// ../../node_modules/.pnpm/is-wsl@3.1.0/node_modules/is-wsl/index.js
|
|
576
|
+
var isWsl = () => {
|
|
577
|
+
if (process3.platform !== "linux") {
|
|
578
|
+
return false;
|
|
579
|
+
}
|
|
580
|
+
if (os2.release().toLowerCase().includes("microsoft")) {
|
|
581
|
+
if (isInsideContainer()) {
|
|
582
|
+
return false;
|
|
583
|
+
}
|
|
584
|
+
return true;
|
|
585
|
+
}
|
|
586
|
+
try {
|
|
587
|
+
return fs3.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !isInsideContainer() : false;
|
|
588
|
+
} catch {
|
|
589
|
+
return false;
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
var is_wsl_default = process3.env.__IS_WSL_TEST__ ? isWsl : isWsl();
|
|
593
|
+
|
|
594
|
+
// ../../node_modules/.pnpm/powershell-utils@0.1.0/node_modules/powershell-utils/index.js
|
|
595
|
+
import process4 from "process";
|
|
596
|
+
import { Buffer } from "buffer";
|
|
597
|
+
import { promisify } from "util";
|
|
598
|
+
import childProcess from "child_process";
|
|
599
|
+
import fs4, { constants as fsConstants } from "fs/promises";
|
|
600
|
+
var execFile = promisify(childProcess.execFile);
|
|
601
|
+
var powerShellPath = () => `${process4.env.SYSTEMROOT || process4.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
|
|
602
|
+
var executePowerShell = async (command, options = {}) => {
|
|
603
|
+
const {
|
|
604
|
+
powerShellPath: psPath,
|
|
605
|
+
...execFileOptions
|
|
606
|
+
} = options;
|
|
607
|
+
const encodedCommand = executePowerShell.encodeCommand(command);
|
|
608
|
+
return execFile(
|
|
609
|
+
psPath ?? powerShellPath(),
|
|
610
|
+
[
|
|
611
|
+
...executePowerShell.argumentsPrefix,
|
|
612
|
+
encodedCommand
|
|
613
|
+
],
|
|
614
|
+
{
|
|
615
|
+
encoding: "utf8",
|
|
616
|
+
...execFileOptions
|
|
617
|
+
}
|
|
618
|
+
);
|
|
619
|
+
};
|
|
620
|
+
executePowerShell.argumentsPrefix = [
|
|
621
|
+
"-NoProfile",
|
|
622
|
+
"-NonInteractive",
|
|
623
|
+
"-ExecutionPolicy",
|
|
624
|
+
"Bypass",
|
|
625
|
+
"-EncodedCommand"
|
|
626
|
+
];
|
|
627
|
+
executePowerShell.encodeCommand = (command) => Buffer.from(command, "utf16le").toString("base64");
|
|
628
|
+
executePowerShell.escapeArgument = (value) => `'${String(value).replaceAll("'", "''")}'`;
|
|
629
|
+
|
|
630
|
+
// ../../node_modules/.pnpm/wsl-utils@0.3.0/node_modules/wsl-utils/index.js
|
|
631
|
+
var execFile2 = promisify2(childProcess2.execFile);
|
|
632
|
+
var wslDrivesMountPoint = /* @__PURE__ */ (() => {
|
|
633
|
+
const defaultMountPoint = "/mnt/";
|
|
634
|
+
let mountPoint;
|
|
635
|
+
return async function() {
|
|
636
|
+
if (mountPoint) {
|
|
637
|
+
return mountPoint;
|
|
638
|
+
}
|
|
639
|
+
const configFilePath = "/etc/wsl.conf";
|
|
640
|
+
let isConfigFileExists = false;
|
|
641
|
+
try {
|
|
642
|
+
await fs5.access(configFilePath, fsConstants2.F_OK);
|
|
643
|
+
isConfigFileExists = true;
|
|
644
|
+
} catch {
|
|
645
|
+
}
|
|
646
|
+
if (!isConfigFileExists) {
|
|
647
|
+
return defaultMountPoint;
|
|
648
|
+
}
|
|
649
|
+
const configContent = await fs5.readFile(configFilePath, { encoding: "utf8" });
|
|
650
|
+
const configMountPoint = /(?<!#.*)root\s*=\s*(?<mountPoint>.*)/g.exec(configContent);
|
|
651
|
+
if (!configMountPoint) {
|
|
652
|
+
return defaultMountPoint;
|
|
653
|
+
}
|
|
654
|
+
mountPoint = configMountPoint.groups.mountPoint.trim();
|
|
655
|
+
mountPoint = mountPoint.endsWith("/") ? mountPoint : `${mountPoint}/`;
|
|
656
|
+
return mountPoint;
|
|
657
|
+
};
|
|
658
|
+
})();
|
|
659
|
+
var powerShellPathFromWsl = async () => {
|
|
660
|
+
const mountPoint = await wslDrivesMountPoint();
|
|
661
|
+
return `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`;
|
|
662
|
+
};
|
|
663
|
+
var powerShellPath2 = is_wsl_default ? powerShellPathFromWsl : powerShellPath;
|
|
664
|
+
var canAccessPowerShellPromise;
|
|
665
|
+
var canAccessPowerShell = async () => {
|
|
666
|
+
canAccessPowerShellPromise ??= (async () => {
|
|
667
|
+
try {
|
|
668
|
+
const psPath = await powerShellPath2();
|
|
669
|
+
await fs5.access(psPath, fsConstants2.X_OK);
|
|
670
|
+
return true;
|
|
671
|
+
} catch {
|
|
672
|
+
return false;
|
|
673
|
+
}
|
|
674
|
+
})();
|
|
675
|
+
return canAccessPowerShellPromise;
|
|
676
|
+
};
|
|
677
|
+
var wslDefaultBrowser = async () => {
|
|
678
|
+
const psPath = await powerShellPath2();
|
|
679
|
+
const command = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
|
|
680
|
+
const { stdout } = await executePowerShell(command, { powerShellPath: psPath });
|
|
681
|
+
return stdout.trim();
|
|
682
|
+
};
|
|
683
|
+
var convertWslPathToWindows = async (path6) => {
|
|
684
|
+
if (/^[a-z]+:\/\//i.test(path6)) {
|
|
685
|
+
return path6;
|
|
686
|
+
}
|
|
687
|
+
try {
|
|
688
|
+
const { stdout } = await execFile2("wslpath", ["-aw", path6], { encoding: "utf8" });
|
|
689
|
+
return stdout.trim();
|
|
690
|
+
} catch {
|
|
691
|
+
return path6;
|
|
692
|
+
}
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
// ../../node_modules/.pnpm/define-lazy-prop@3.0.0/node_modules/define-lazy-prop/index.js
|
|
696
|
+
function defineLazyProperty(object, propertyName, valueGetter) {
|
|
697
|
+
const define = (value) => Object.defineProperty(object, propertyName, { value, enumerable: true, writable: true });
|
|
698
|
+
Object.defineProperty(object, propertyName, {
|
|
699
|
+
configurable: true,
|
|
700
|
+
enumerable: true,
|
|
701
|
+
get() {
|
|
702
|
+
const result = valueGetter();
|
|
703
|
+
define(result);
|
|
704
|
+
return result;
|
|
705
|
+
},
|
|
706
|
+
set(value) {
|
|
707
|
+
define(value);
|
|
708
|
+
}
|
|
709
|
+
});
|
|
710
|
+
return object;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// ../../node_modules/.pnpm/default-browser@5.4.0/node_modules/default-browser/index.js
|
|
714
|
+
import { promisify as promisify6 } from "util";
|
|
715
|
+
import process7 from "process";
|
|
716
|
+
import { execFile as execFile6 } from "child_process";
|
|
717
|
+
|
|
718
|
+
// ../../node_modules/.pnpm/default-browser-id@5.0.0/node_modules/default-browser-id/index.js
|
|
719
|
+
import { promisify as promisify3 } from "util";
|
|
720
|
+
import process5 from "process";
|
|
721
|
+
import { execFile as execFile3 } from "child_process";
|
|
722
|
+
var execFileAsync = promisify3(execFile3);
|
|
723
|
+
async function defaultBrowserId() {
|
|
724
|
+
if (process5.platform !== "darwin") {
|
|
725
|
+
throw new Error("macOS only");
|
|
726
|
+
}
|
|
727
|
+
const { stdout } = await execFileAsync("defaults", ["read", "com.apple.LaunchServices/com.apple.launchservices.secure", "LSHandlers"]);
|
|
728
|
+
const match = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
|
|
729
|
+
return match?.groups.id ?? "com.apple.Safari";
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// ../../node_modules/.pnpm/run-applescript@7.1.0/node_modules/run-applescript/index.js
|
|
733
|
+
import process6 from "process";
|
|
734
|
+
import { promisify as promisify4 } from "util";
|
|
735
|
+
import { execFile as execFile4, execFileSync } from "child_process";
|
|
736
|
+
var execFileAsync2 = promisify4(execFile4);
|
|
737
|
+
async function runAppleScript(script, { humanReadableOutput = true, signal } = {}) {
|
|
738
|
+
if (process6.platform !== "darwin") {
|
|
739
|
+
throw new Error("macOS only");
|
|
740
|
+
}
|
|
741
|
+
const outputArguments = humanReadableOutput ? [] : ["-ss"];
|
|
742
|
+
const execOptions = {};
|
|
743
|
+
if (signal) {
|
|
744
|
+
execOptions.signal = signal;
|
|
745
|
+
}
|
|
746
|
+
const { stdout } = await execFileAsync2("osascript", ["-e", script, outputArguments], execOptions);
|
|
747
|
+
return stdout.trim();
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// ../../node_modules/.pnpm/bundle-name@4.1.0/node_modules/bundle-name/index.js
|
|
751
|
+
async function bundleName(bundleId) {
|
|
752
|
+
return runAppleScript(`tell application "Finder" to set app_path to application file id "${bundleId}" as string
|
|
753
|
+
tell application "System Events" to get value of property list item "CFBundleName" of property list file (app_path & ":Contents:Info.plist")`);
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// ../../node_modules/.pnpm/default-browser@5.4.0/node_modules/default-browser/windows.js
|
|
757
|
+
import { promisify as promisify5 } from "util";
|
|
758
|
+
import { execFile as execFile5 } from "child_process";
|
|
759
|
+
var execFileAsync3 = promisify5(execFile5);
|
|
760
|
+
var windowsBrowserProgIds = {
|
|
761
|
+
MSEdgeHTM: { name: "Edge", id: "com.microsoft.edge" },
|
|
762
|
+
// The missing `L` is correct.
|
|
763
|
+
MSEdgeBHTML: { name: "Edge Beta", id: "com.microsoft.edge.beta" },
|
|
764
|
+
MSEdgeDHTML: { name: "Edge Dev", id: "com.microsoft.edge.dev" },
|
|
765
|
+
AppXq0fevzme2pys62n3e0fbqa7peapykr8v: { name: "Edge", id: "com.microsoft.edge.old" },
|
|
766
|
+
ChromeHTML: { name: "Chrome", id: "com.google.chrome" },
|
|
767
|
+
ChromeBHTML: { name: "Chrome Beta", id: "com.google.chrome.beta" },
|
|
768
|
+
ChromeDHTML: { name: "Chrome Dev", id: "com.google.chrome.dev" },
|
|
769
|
+
ChromiumHTM: { name: "Chromium", id: "org.chromium.Chromium" },
|
|
770
|
+
BraveHTML: { name: "Brave", id: "com.brave.Browser" },
|
|
771
|
+
BraveBHTML: { name: "Brave Beta", id: "com.brave.Browser.beta" },
|
|
772
|
+
BraveDHTML: { name: "Brave Dev", id: "com.brave.Browser.dev" },
|
|
773
|
+
BraveSSHTM: { name: "Brave Nightly", id: "com.brave.Browser.nightly" },
|
|
774
|
+
FirefoxURL: { name: "Firefox", id: "org.mozilla.firefox" },
|
|
775
|
+
OperaStable: { name: "Opera", id: "com.operasoftware.Opera" },
|
|
776
|
+
VivaldiHTM: { name: "Vivaldi", id: "com.vivaldi.Vivaldi" },
|
|
777
|
+
"IE.HTTP": { name: "Internet Explorer", id: "com.microsoft.ie" }
|
|
778
|
+
};
|
|
779
|
+
var _windowsBrowserProgIdMap = new Map(Object.entries(windowsBrowserProgIds));
|
|
780
|
+
var UnknownBrowserError = class extends Error {
|
|
781
|
+
};
|
|
782
|
+
async function defaultBrowser(_execFileAsync = execFileAsync3) {
|
|
783
|
+
const { stdout } = await _execFileAsync("reg", [
|
|
784
|
+
"QUERY",
|
|
785
|
+
" HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice",
|
|
786
|
+
"/v",
|
|
787
|
+
"ProgId"
|
|
788
|
+
]);
|
|
789
|
+
const match = /ProgId\s*REG_SZ\s*(?<id>\S+)/.exec(stdout);
|
|
790
|
+
if (!match) {
|
|
791
|
+
throw new UnknownBrowserError(`Cannot find Windows browser in stdout: ${JSON.stringify(stdout)}`);
|
|
792
|
+
}
|
|
793
|
+
const { id } = match.groups;
|
|
794
|
+
const browser = windowsBrowserProgIds[id];
|
|
795
|
+
if (!browser) {
|
|
796
|
+
throw new UnknownBrowserError(`Unknown browser ID: ${id}`);
|
|
797
|
+
}
|
|
798
|
+
return browser;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// ../../node_modules/.pnpm/default-browser@5.4.0/node_modules/default-browser/index.js
|
|
802
|
+
var execFileAsync4 = promisify6(execFile6);
|
|
803
|
+
var titleize = (string) => string.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x) => x.toUpperCase());
|
|
804
|
+
async function defaultBrowser2() {
|
|
805
|
+
if (process7.platform === "darwin") {
|
|
806
|
+
const id = await defaultBrowserId();
|
|
807
|
+
const name = await bundleName(id);
|
|
808
|
+
return { name, id };
|
|
809
|
+
}
|
|
810
|
+
if (process7.platform === "linux") {
|
|
811
|
+
const { stdout } = await execFileAsync4("xdg-mime", ["query", "default", "x-scheme-handler/http"]);
|
|
812
|
+
const id = stdout.trim();
|
|
813
|
+
const name = titleize(id.replace(/.desktop$/, "").replace("-", " "));
|
|
814
|
+
return { name, id };
|
|
815
|
+
}
|
|
816
|
+
if (process7.platform === "win32") {
|
|
817
|
+
return defaultBrowser();
|
|
818
|
+
}
|
|
819
|
+
throw new Error("Only macOS, Linux, and Windows are supported");
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// ../../node_modules/.pnpm/is-in-ssh@1.0.0/node_modules/is-in-ssh/index.js
|
|
823
|
+
import process8 from "process";
|
|
824
|
+
var isInSsh = Boolean(process8.env.SSH_CONNECTION || process8.env.SSH_CLIENT || process8.env.SSH_TTY);
|
|
825
|
+
var is_in_ssh_default = isInSsh;
|
|
826
|
+
|
|
827
|
+
// ../../node_modules/.pnpm/open@11.0.0/node_modules/open/index.js
|
|
828
|
+
var fallbackAttemptSymbol = Symbol("fallbackAttempt");
|
|
829
|
+
var __dirname2 = import.meta.url ? path2.dirname(fileURLToPath2(import.meta.url)) : "";
|
|
830
|
+
var localXdgOpenPath = path2.join(__dirname2, "xdg-open");
|
|
831
|
+
var { platform, arch } = process9;
|
|
832
|
+
var tryEachApp = async (apps2, opener) => {
|
|
833
|
+
if (apps2.length === 0) {
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
const errors = [];
|
|
837
|
+
for (const app of apps2) {
|
|
838
|
+
try {
|
|
839
|
+
return await opener(app);
|
|
840
|
+
} catch (error) {
|
|
841
|
+
errors.push(error);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
throw new AggregateError(errors, "Failed to open in all supported apps");
|
|
845
|
+
};
|
|
846
|
+
var baseOpen = async (options) => {
|
|
847
|
+
options = {
|
|
848
|
+
wait: false,
|
|
849
|
+
background: false,
|
|
850
|
+
newInstance: false,
|
|
851
|
+
allowNonzeroExitCode: false,
|
|
852
|
+
...options
|
|
853
|
+
};
|
|
854
|
+
const isFallbackAttempt = options[fallbackAttemptSymbol] === true;
|
|
855
|
+
delete options[fallbackAttemptSymbol];
|
|
856
|
+
if (Array.isArray(options.app)) {
|
|
857
|
+
return tryEachApp(options.app, (singleApp) => baseOpen({
|
|
858
|
+
...options,
|
|
859
|
+
app: singleApp,
|
|
860
|
+
[fallbackAttemptSymbol]: true
|
|
861
|
+
}));
|
|
862
|
+
}
|
|
863
|
+
let { name: app, arguments: appArguments = [] } = options.app ?? {};
|
|
864
|
+
appArguments = [...appArguments];
|
|
865
|
+
if (Array.isArray(app)) {
|
|
866
|
+
return tryEachApp(app, (appName) => baseOpen({
|
|
867
|
+
...options,
|
|
868
|
+
app: {
|
|
869
|
+
name: appName,
|
|
870
|
+
arguments: appArguments
|
|
871
|
+
},
|
|
872
|
+
[fallbackAttemptSymbol]: true
|
|
873
|
+
}));
|
|
874
|
+
}
|
|
875
|
+
if (app === "browser" || app === "browserPrivate") {
|
|
876
|
+
const ids = {
|
|
877
|
+
"com.google.chrome": "chrome",
|
|
878
|
+
"google-chrome.desktop": "chrome",
|
|
879
|
+
"com.brave.browser": "brave",
|
|
880
|
+
"org.mozilla.firefox": "firefox",
|
|
881
|
+
"firefox.desktop": "firefox",
|
|
882
|
+
"com.microsoft.msedge": "edge",
|
|
883
|
+
"com.microsoft.edge": "edge",
|
|
884
|
+
"com.microsoft.edgemac": "edge",
|
|
885
|
+
"microsoft-edge.desktop": "edge",
|
|
886
|
+
"com.apple.safari": "safari"
|
|
887
|
+
};
|
|
888
|
+
const flags = {
|
|
889
|
+
chrome: "--incognito",
|
|
890
|
+
brave: "--incognito",
|
|
891
|
+
firefox: "--private-window",
|
|
892
|
+
edge: "--inPrivate"
|
|
893
|
+
// Safari doesn't support private mode via command line
|
|
894
|
+
};
|
|
895
|
+
let browser;
|
|
896
|
+
if (is_wsl_default) {
|
|
897
|
+
const progId = await wslDefaultBrowser();
|
|
898
|
+
const browserInfo = _windowsBrowserProgIdMap.get(progId);
|
|
899
|
+
browser = browserInfo ?? {};
|
|
900
|
+
} else {
|
|
901
|
+
browser = await defaultBrowser2();
|
|
902
|
+
}
|
|
903
|
+
if (browser.id in ids) {
|
|
904
|
+
const browserName = ids[browser.id.toLowerCase()];
|
|
905
|
+
if (app === "browserPrivate") {
|
|
906
|
+
if (browserName === "safari") {
|
|
907
|
+
throw new Error("Safari doesn't support opening in private mode via command line");
|
|
908
|
+
}
|
|
909
|
+
appArguments.push(flags[browserName]);
|
|
910
|
+
}
|
|
911
|
+
return baseOpen({
|
|
912
|
+
...options,
|
|
913
|
+
app: {
|
|
914
|
+
name: apps[browserName],
|
|
915
|
+
arguments: appArguments
|
|
916
|
+
}
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
throw new Error(`${browser.name} is not supported as a default browser`);
|
|
920
|
+
}
|
|
921
|
+
let command;
|
|
922
|
+
const cliArguments = [];
|
|
923
|
+
const childProcessOptions = {};
|
|
924
|
+
let shouldUseWindowsInWsl = false;
|
|
925
|
+
if (is_wsl_default && !isInsideContainer() && !is_in_ssh_default && !app) {
|
|
926
|
+
shouldUseWindowsInWsl = await canAccessPowerShell();
|
|
927
|
+
}
|
|
928
|
+
if (platform === "darwin") {
|
|
929
|
+
command = "open";
|
|
930
|
+
if (options.wait) {
|
|
931
|
+
cliArguments.push("--wait-apps");
|
|
932
|
+
}
|
|
933
|
+
if (options.background) {
|
|
934
|
+
cliArguments.push("--background");
|
|
935
|
+
}
|
|
936
|
+
if (options.newInstance) {
|
|
937
|
+
cliArguments.push("--new");
|
|
938
|
+
}
|
|
939
|
+
if (app) {
|
|
940
|
+
cliArguments.push("-a", app);
|
|
941
|
+
}
|
|
942
|
+
} else if (platform === "win32" || shouldUseWindowsInWsl) {
|
|
943
|
+
command = await powerShellPath2();
|
|
944
|
+
cliArguments.push(...executePowerShell.argumentsPrefix);
|
|
945
|
+
if (!is_wsl_default) {
|
|
946
|
+
childProcessOptions.windowsVerbatimArguments = true;
|
|
947
|
+
}
|
|
948
|
+
if (is_wsl_default && options.target) {
|
|
949
|
+
options.target = await convertWslPathToWindows(options.target);
|
|
950
|
+
}
|
|
951
|
+
const encodedArguments = ["$ProgressPreference = 'SilentlyContinue';", "Start"];
|
|
952
|
+
if (options.wait) {
|
|
953
|
+
encodedArguments.push("-Wait");
|
|
954
|
+
}
|
|
955
|
+
if (app) {
|
|
956
|
+
encodedArguments.push(executePowerShell.escapeArgument(app));
|
|
957
|
+
if (options.target) {
|
|
958
|
+
appArguments.push(options.target);
|
|
959
|
+
}
|
|
960
|
+
} else if (options.target) {
|
|
961
|
+
encodedArguments.push(executePowerShell.escapeArgument(options.target));
|
|
962
|
+
}
|
|
963
|
+
if (appArguments.length > 0) {
|
|
964
|
+
appArguments = appArguments.map((argument) => executePowerShell.escapeArgument(argument));
|
|
965
|
+
encodedArguments.push("-ArgumentList", appArguments.join(","));
|
|
966
|
+
}
|
|
967
|
+
options.target = executePowerShell.encodeCommand(encodedArguments.join(" "));
|
|
968
|
+
if (!options.wait) {
|
|
969
|
+
childProcessOptions.stdio = "ignore";
|
|
970
|
+
}
|
|
971
|
+
} else {
|
|
972
|
+
if (app) {
|
|
973
|
+
command = app;
|
|
974
|
+
} else {
|
|
975
|
+
const isBundled = !__dirname2 || __dirname2 === "/";
|
|
976
|
+
let exeLocalXdgOpen = false;
|
|
977
|
+
try {
|
|
978
|
+
await fs6.access(localXdgOpenPath, fsConstants3.X_OK);
|
|
979
|
+
exeLocalXdgOpen = true;
|
|
980
|
+
} catch {
|
|
981
|
+
}
|
|
982
|
+
const useSystemXdgOpen = process9.versions.electron ?? (platform === "android" || isBundled || !exeLocalXdgOpen);
|
|
983
|
+
command = useSystemXdgOpen ? "xdg-open" : localXdgOpenPath;
|
|
984
|
+
}
|
|
985
|
+
if (appArguments.length > 0) {
|
|
986
|
+
cliArguments.push(...appArguments);
|
|
987
|
+
}
|
|
988
|
+
if (!options.wait) {
|
|
989
|
+
childProcessOptions.stdio = "ignore";
|
|
990
|
+
childProcessOptions.detached = true;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
if (platform === "darwin" && appArguments.length > 0) {
|
|
994
|
+
cliArguments.push("--args", ...appArguments);
|
|
995
|
+
}
|
|
996
|
+
if (options.target) {
|
|
997
|
+
cliArguments.push(options.target);
|
|
998
|
+
}
|
|
999
|
+
const subprocess = childProcess3.spawn(command, cliArguments, childProcessOptions);
|
|
1000
|
+
if (options.wait) {
|
|
1001
|
+
return new Promise((resolve, reject) => {
|
|
1002
|
+
subprocess.once("error", reject);
|
|
1003
|
+
subprocess.once("close", (exitCode) => {
|
|
1004
|
+
if (!options.allowNonzeroExitCode && exitCode !== 0) {
|
|
1005
|
+
reject(new Error(`Exited with code ${exitCode}`));
|
|
1006
|
+
return;
|
|
1007
|
+
}
|
|
1008
|
+
resolve(subprocess);
|
|
1009
|
+
});
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
if (isFallbackAttempt) {
|
|
1013
|
+
return new Promise((resolve, reject) => {
|
|
1014
|
+
subprocess.once("error", reject);
|
|
1015
|
+
subprocess.once("spawn", () => {
|
|
1016
|
+
subprocess.once("close", (exitCode) => {
|
|
1017
|
+
subprocess.off("error", reject);
|
|
1018
|
+
if (exitCode !== 0) {
|
|
1019
|
+
reject(new Error(`Exited with code ${exitCode}`));
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
1022
|
+
subprocess.unref();
|
|
1023
|
+
resolve(subprocess);
|
|
1024
|
+
});
|
|
1025
|
+
});
|
|
1026
|
+
});
|
|
1027
|
+
}
|
|
1028
|
+
subprocess.unref();
|
|
292
1029
|
return new Promise((resolve, reject) => {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
1030
|
+
subprocess.once("error", reject);
|
|
1031
|
+
subprocess.once("spawn", () => {
|
|
1032
|
+
subprocess.off("error", reject);
|
|
1033
|
+
resolve(subprocess);
|
|
296
1034
|
});
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
1035
|
+
});
|
|
1036
|
+
};
|
|
1037
|
+
var open = (target, options) => {
|
|
1038
|
+
if (typeof target !== "string") {
|
|
1039
|
+
throw new TypeError("Expected a `target`");
|
|
1040
|
+
}
|
|
1041
|
+
return baseOpen({
|
|
1042
|
+
...options,
|
|
1043
|
+
target
|
|
1044
|
+
});
|
|
1045
|
+
};
|
|
1046
|
+
function detectArchBinary(binary) {
|
|
1047
|
+
if (typeof binary === "string" || Array.isArray(binary)) {
|
|
1048
|
+
return binary;
|
|
1049
|
+
}
|
|
1050
|
+
const { [arch]: archBinary } = binary;
|
|
1051
|
+
if (!archBinary) {
|
|
1052
|
+
throw new Error(`${arch} is not supported`);
|
|
1053
|
+
}
|
|
1054
|
+
return archBinary;
|
|
1055
|
+
}
|
|
1056
|
+
function detectPlatformBinary({ [platform]: platformBinary }, { wsl } = {}) {
|
|
1057
|
+
if (wsl && is_wsl_default) {
|
|
1058
|
+
return detectArchBinary(wsl);
|
|
1059
|
+
}
|
|
1060
|
+
if (!platformBinary) {
|
|
1061
|
+
throw new Error(`${platform} is not supported`);
|
|
1062
|
+
}
|
|
1063
|
+
return detectArchBinary(platformBinary);
|
|
1064
|
+
}
|
|
1065
|
+
var apps = {
|
|
1066
|
+
browser: "browser",
|
|
1067
|
+
browserPrivate: "browserPrivate"
|
|
1068
|
+
};
|
|
1069
|
+
defineLazyProperty(apps, "chrome", () => detectPlatformBinary({
|
|
1070
|
+
darwin: "google chrome",
|
|
1071
|
+
win32: "chrome",
|
|
1072
|
+
// `chromium-browser` is the older deb package name used by Ubuntu/Debian before snap.
|
|
1073
|
+
linux: ["google-chrome", "google-chrome-stable", "chromium", "chromium-browser"]
|
|
1074
|
+
}, {
|
|
1075
|
+
wsl: {
|
|
1076
|
+
ia32: "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe",
|
|
1077
|
+
x64: ["/mnt/c/Program Files/Google/Chrome/Application/chrome.exe", "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe"]
|
|
1078
|
+
}
|
|
1079
|
+
}));
|
|
1080
|
+
defineLazyProperty(apps, "brave", () => detectPlatformBinary({
|
|
1081
|
+
darwin: "brave browser",
|
|
1082
|
+
win32: "brave",
|
|
1083
|
+
linux: ["brave-browser", "brave"]
|
|
1084
|
+
}, {
|
|
1085
|
+
wsl: {
|
|
1086
|
+
ia32: "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe",
|
|
1087
|
+
x64: ["/mnt/c/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe", "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe"]
|
|
1088
|
+
}
|
|
1089
|
+
}));
|
|
1090
|
+
defineLazyProperty(apps, "firefox", () => detectPlatformBinary({
|
|
1091
|
+
darwin: "firefox",
|
|
1092
|
+
win32: String.raw`C:\Program Files\Mozilla Firefox\firefox.exe`,
|
|
1093
|
+
linux: "firefox"
|
|
1094
|
+
}, {
|
|
1095
|
+
wsl: "/mnt/c/Program Files/Mozilla Firefox/firefox.exe"
|
|
1096
|
+
}));
|
|
1097
|
+
defineLazyProperty(apps, "edge", () => detectPlatformBinary({
|
|
1098
|
+
darwin: "microsoft edge",
|
|
1099
|
+
win32: "msedge",
|
|
1100
|
+
linux: ["microsoft-edge", "microsoft-edge-dev"]
|
|
1101
|
+
}, {
|
|
1102
|
+
wsl: "/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"
|
|
1103
|
+
}));
|
|
1104
|
+
defineLazyProperty(apps, "safari", () => detectPlatformBinary({
|
|
1105
|
+
darwin: "Safari"
|
|
1106
|
+
}));
|
|
1107
|
+
var open_default = open;
|
|
1108
|
+
|
|
1109
|
+
// src/commands/auth.ts
|
|
1110
|
+
import {
|
|
1111
|
+
createServer
|
|
1112
|
+
} from "http";
|
|
1113
|
+
|
|
1114
|
+
// src/utils/config.ts
|
|
1115
|
+
import { promises as fs7 } from "fs";
|
|
1116
|
+
import path3 from "path";
|
|
1117
|
+
import os3 from "os";
|
|
1118
|
+
var CONFIG_DIR = path3.join(os3.homedir(), ".mcp-use");
|
|
1119
|
+
var CONFIG_FILE = path3.join(CONFIG_DIR, "config.json");
|
|
1120
|
+
var DEFAULT_API_URL = process.env.MCP_API_URL ? process.env.MCP_API_URL.replace(/\/api\/v1$/, "") + "/api/v1" : "https://cloud.mcp-use.com/api/v1";
|
|
1121
|
+
var DEFAULT_WEB_URL = process.env.MCP_WEB_URL ? process.env.MCP_WEB_URL : "https://mcp-use.com";
|
|
1122
|
+
async function ensureConfigDir() {
|
|
1123
|
+
try {
|
|
1124
|
+
await fs7.mkdir(CONFIG_DIR, { recursive: true });
|
|
1125
|
+
} catch (error) {
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
async function readConfig() {
|
|
1129
|
+
try {
|
|
1130
|
+
const content = await fs7.readFile(CONFIG_FILE, "utf-8");
|
|
1131
|
+
return JSON.parse(content);
|
|
1132
|
+
} catch (error) {
|
|
1133
|
+
return {};
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
async function writeConfig(config) {
|
|
1137
|
+
await ensureConfigDir();
|
|
1138
|
+
await fs7.writeFile(CONFIG_FILE, JSON.stringify(config, null, 2), "utf-8");
|
|
1139
|
+
}
|
|
1140
|
+
async function deleteConfig() {
|
|
1141
|
+
try {
|
|
1142
|
+
await fs7.unlink(CONFIG_FILE);
|
|
1143
|
+
} catch (error) {
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
async function getApiUrl() {
|
|
1147
|
+
const config = await readConfig();
|
|
1148
|
+
return config.apiUrl || DEFAULT_API_URL;
|
|
1149
|
+
}
|
|
1150
|
+
async function getApiKey() {
|
|
1151
|
+
const config = await readConfig();
|
|
1152
|
+
return config.apiKey || null;
|
|
1153
|
+
}
|
|
1154
|
+
async function isLoggedIn() {
|
|
1155
|
+
const apiKey = await getApiKey();
|
|
1156
|
+
return !!apiKey;
|
|
1157
|
+
}
|
|
1158
|
+
async function getWebUrl() {
|
|
1159
|
+
return DEFAULT_WEB_URL;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
// src/utils/api.ts
|
|
1163
|
+
var McpUseAPI = class _McpUseAPI {
|
|
1164
|
+
baseUrl;
|
|
1165
|
+
apiKey;
|
|
1166
|
+
constructor(baseUrl, apiKey) {
|
|
1167
|
+
this.baseUrl = baseUrl || "";
|
|
1168
|
+
this.apiKey = apiKey;
|
|
1169
|
+
}
|
|
1170
|
+
/**
|
|
1171
|
+
* Initialize API client with config
|
|
1172
|
+
*/
|
|
1173
|
+
static async create() {
|
|
1174
|
+
const baseUrl = await getApiUrl();
|
|
1175
|
+
const apiKey = await getApiKey();
|
|
1176
|
+
return new _McpUseAPI(baseUrl, apiKey ?? void 0);
|
|
1177
|
+
}
|
|
1178
|
+
/**
|
|
1179
|
+
* Make authenticated request
|
|
1180
|
+
*/
|
|
1181
|
+
async request(endpoint, options = {}) {
|
|
1182
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
1183
|
+
const headers = {
|
|
1184
|
+
"Content-Type": "application/json",
|
|
1185
|
+
...options.headers || {}
|
|
1186
|
+
};
|
|
1187
|
+
if (this.apiKey) {
|
|
1188
|
+
headers["x-api-key"] = this.apiKey;
|
|
1189
|
+
}
|
|
1190
|
+
const response = await fetch(url, {
|
|
1191
|
+
...options,
|
|
1192
|
+
headers
|
|
1193
|
+
});
|
|
1194
|
+
if (!response.ok) {
|
|
1195
|
+
const error = await response.text();
|
|
1196
|
+
throw new Error(`API request failed: ${response.status} ${error}`);
|
|
1197
|
+
}
|
|
1198
|
+
return response.json();
|
|
1199
|
+
}
|
|
1200
|
+
/**
|
|
1201
|
+
* Create API key using JWT token
|
|
1202
|
+
*/
|
|
1203
|
+
async createApiKey(jwtToken, name = "CLI") {
|
|
1204
|
+
const url = `${this.baseUrl}/api-key`;
|
|
1205
|
+
const response = await fetch(url, {
|
|
1206
|
+
method: "POST",
|
|
1207
|
+
headers: {
|
|
1208
|
+
"Content-Type": "application/json",
|
|
1209
|
+
Authorization: `Bearer ${jwtToken}`
|
|
1210
|
+
},
|
|
1211
|
+
body: JSON.stringify({ name })
|
|
1212
|
+
});
|
|
1213
|
+
if (!response.ok) {
|
|
1214
|
+
const error = await response.text();
|
|
1215
|
+
throw new Error(`Failed to create API key: ${response.status} ${error}`);
|
|
1216
|
+
}
|
|
1217
|
+
return response.json();
|
|
1218
|
+
}
|
|
1219
|
+
/**
|
|
1220
|
+
* Test authentication
|
|
1221
|
+
*/
|
|
1222
|
+
async testAuth() {
|
|
1223
|
+
return this.request("/test-auth");
|
|
1224
|
+
}
|
|
1225
|
+
/**
|
|
1226
|
+
* Create deployment
|
|
1227
|
+
*/
|
|
1228
|
+
async createDeployment(request) {
|
|
1229
|
+
return this.request("/deployments", {
|
|
1230
|
+
method: "POST",
|
|
1231
|
+
body: JSON.stringify(request)
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
1234
|
+
/**
|
|
1235
|
+
* Get deployment by ID
|
|
1236
|
+
*/
|
|
1237
|
+
async getDeployment(deploymentId) {
|
|
1238
|
+
return this.request(`/deployments/${deploymentId}`);
|
|
1239
|
+
}
|
|
1240
|
+
/**
|
|
1241
|
+
* Stream deployment logs
|
|
1242
|
+
*/
|
|
1243
|
+
async *streamDeploymentLogs(deploymentId) {
|
|
1244
|
+
const url = `${this.baseUrl}/deployments/${deploymentId}/logs/stream`;
|
|
1245
|
+
const headers = {};
|
|
1246
|
+
if (this.apiKey) {
|
|
1247
|
+
headers["x-api-key"] = this.apiKey;
|
|
1248
|
+
}
|
|
1249
|
+
const response = await fetch(url, { headers });
|
|
1250
|
+
if (!response.ok) {
|
|
1251
|
+
throw new Error(`Failed to stream logs: ${response.status}`);
|
|
1252
|
+
}
|
|
1253
|
+
if (!response.body) {
|
|
1254
|
+
throw new Error("Response body is null");
|
|
1255
|
+
}
|
|
1256
|
+
const reader = response.body.getReader();
|
|
1257
|
+
const decoder = new TextDecoder();
|
|
1258
|
+
let buffer = "";
|
|
1259
|
+
try {
|
|
1260
|
+
while (true) {
|
|
1261
|
+
const { done, value } = await reader.read();
|
|
1262
|
+
if (done) break;
|
|
1263
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1264
|
+
const lines = buffer.split("\n");
|
|
1265
|
+
buffer = lines.pop() || "";
|
|
1266
|
+
for (const line of lines) {
|
|
1267
|
+
if (line.startsWith("data: ")) {
|
|
1268
|
+
const data = line.slice(6);
|
|
1269
|
+
try {
|
|
1270
|
+
const parsed = JSON.parse(data);
|
|
1271
|
+
if (parsed.log) {
|
|
1272
|
+
yield parsed.log;
|
|
1273
|
+
} else if (parsed.error) {
|
|
1274
|
+
throw new Error(parsed.error);
|
|
1275
|
+
}
|
|
1276
|
+
} catch (e) {
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
} finally {
|
|
1282
|
+
reader.releaseLock();
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
/**
|
|
1286
|
+
* Create deployment with source code upload
|
|
1287
|
+
*/
|
|
1288
|
+
async createDeploymentWithUpload(request, filePath) {
|
|
1289
|
+
const { readFile: readFile3 } = await import("fs/promises");
|
|
1290
|
+
const { basename } = await import("path");
|
|
1291
|
+
const { stat } = await import("fs/promises");
|
|
1292
|
+
const stats = await stat(filePath);
|
|
1293
|
+
const maxSize = 2 * 1024 * 1024;
|
|
1294
|
+
if (stats.size > maxSize) {
|
|
1295
|
+
throw new Error(
|
|
1296
|
+
`File size (${(stats.size / 1024 / 1024).toFixed(2)}MB) exceeds maximum of 2MB`
|
|
1297
|
+
);
|
|
1298
|
+
}
|
|
1299
|
+
const fileBuffer = await readFile3(filePath);
|
|
1300
|
+
const filename = basename(filePath);
|
|
1301
|
+
const formData = new FormData();
|
|
1302
|
+
const blob = new Blob([fileBuffer], { type: "application/gzip" });
|
|
1303
|
+
formData.append("source_file", blob, filename);
|
|
1304
|
+
formData.append("name", request.name);
|
|
1305
|
+
formData.append("source_type", "upload");
|
|
1306
|
+
if (request.source.type === "upload") {
|
|
1307
|
+
formData.append("runtime", request.source.runtime || "node");
|
|
1308
|
+
formData.append("port", String(request.source.port || 3e3));
|
|
1309
|
+
if (request.source.startCommand) {
|
|
1310
|
+
formData.append("startCommand", request.source.startCommand);
|
|
1311
|
+
}
|
|
1312
|
+
if (request.source.buildCommand) {
|
|
1313
|
+
formData.append("buildCommand", request.source.buildCommand);
|
|
1314
|
+
}
|
|
1315
|
+
if (request.source.env && Object.keys(request.source.env).length > 0) {
|
|
1316
|
+
formData.append("env", JSON.stringify(request.source.env));
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
if (request.customDomain) {
|
|
1320
|
+
formData.append("customDomain", request.customDomain);
|
|
1321
|
+
}
|
|
1322
|
+
if (request.healthCheckPath) {
|
|
1323
|
+
formData.append("healthCheckPath", request.healthCheckPath);
|
|
1324
|
+
}
|
|
1325
|
+
const url = `${this.baseUrl}/deployments`;
|
|
1326
|
+
const headers = {};
|
|
1327
|
+
if (this.apiKey) {
|
|
1328
|
+
headers["x-api-key"] = this.apiKey;
|
|
1329
|
+
}
|
|
1330
|
+
const response = await fetch(url, {
|
|
1331
|
+
method: "POST",
|
|
1332
|
+
headers,
|
|
1333
|
+
body: formData
|
|
1334
|
+
});
|
|
1335
|
+
if (!response.ok) {
|
|
1336
|
+
const error = await response.text();
|
|
1337
|
+
throw new Error(`Deployment failed: ${error}`);
|
|
1338
|
+
}
|
|
1339
|
+
return response.json();
|
|
1340
|
+
}
|
|
1341
|
+
};
|
|
1342
|
+
|
|
1343
|
+
// src/commands/auth.ts
|
|
1344
|
+
var LOGIN_TIMEOUT = 3e5;
|
|
1345
|
+
async function findAvailablePort(startPort = 8765) {
|
|
1346
|
+
for (let port = startPort; port < startPort + 100; port++) {
|
|
1347
|
+
try {
|
|
1348
|
+
await new Promise((resolve, reject) => {
|
|
1349
|
+
const server = createServer();
|
|
1350
|
+
server.once("error", reject);
|
|
1351
|
+
server.once("listening", () => {
|
|
1352
|
+
server.close();
|
|
1353
|
+
resolve();
|
|
1354
|
+
});
|
|
1355
|
+
server.listen(port);
|
|
1356
|
+
});
|
|
1357
|
+
return port;
|
|
1358
|
+
} catch {
|
|
1359
|
+
continue;
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
throw new Error("No available ports found");
|
|
1363
|
+
}
|
|
1364
|
+
async function startCallbackServer(port) {
|
|
1365
|
+
return new Promise((resolve, reject) => {
|
|
1366
|
+
let tokenResolver = null;
|
|
1367
|
+
const tokenPromise = new Promise((res) => {
|
|
1368
|
+
tokenResolver = res;
|
|
1369
|
+
});
|
|
1370
|
+
const server = createServer((req, res) => {
|
|
1371
|
+
if (req.url?.startsWith("/callback")) {
|
|
1372
|
+
const url = new URL(req.url, `http://localhost:${port}`);
|
|
1373
|
+
const token = url.searchParams.get("token");
|
|
1374
|
+
if (token && tokenResolver) {
|
|
1375
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
1376
|
+
res.end(`
|
|
1377
|
+
<!DOCTYPE html>
|
|
1378
|
+
<html>
|
|
1379
|
+
<head>
|
|
1380
|
+
<title>Login Successful</title>
|
|
1381
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1382
|
+
<style>
|
|
1383
|
+
* {
|
|
1384
|
+
margin: 0;
|
|
1385
|
+
padding: 0;
|
|
1386
|
+
box-sizing: border-box;
|
|
1387
|
+
}
|
|
1388
|
+
body {
|
|
1389
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
1390
|
+
display: flex;
|
|
1391
|
+
justify-content: center;
|
|
1392
|
+
align-items: center;
|
|
1393
|
+
min-height: 100vh;
|
|
1394
|
+
background: #000;
|
|
1395
|
+
padding: 1rem;
|
|
1396
|
+
}
|
|
1397
|
+
.container {
|
|
1398
|
+
width: 100%;
|
|
1399
|
+
max-width: 28rem;
|
|
1400
|
+
padding: 3rem;
|
|
1401
|
+
text-align: center;
|
|
1402
|
+
-webkit-backdrop-filter: blur(40px);
|
|
1403
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
1404
|
+
border-radius: 1.5rem;
|
|
1405
|
+
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
|
|
1406
|
+
}
|
|
1407
|
+
.icon-container {
|
|
1408
|
+
display: inline-flex;
|
|
1409
|
+
align-items: center;
|
|
1410
|
+
justify-content: center;
|
|
1411
|
+
width: 6rem;
|
|
1412
|
+
height: 6rem;
|
|
1413
|
+
margin-bottom: 2rem;
|
|
1414
|
+
background: rgba(255, 255, 255, 0.1);
|
|
1415
|
+
backdrop-filter: blur(10px);
|
|
1416
|
+
-webkit-backdrop-filter: blur(10px);
|
|
1417
|
+
border-radius: 50%;
|
|
1418
|
+
}
|
|
1419
|
+
.checkmark {
|
|
1420
|
+
font-size: 4rem;
|
|
1421
|
+
color: #fff;
|
|
1422
|
+
line-height: 1;
|
|
1423
|
+
animation: scaleIn 0.5s ease-out;
|
|
1424
|
+
}
|
|
1425
|
+
@keyframes scaleIn {
|
|
1426
|
+
from {
|
|
1427
|
+
transform: scale(0);
|
|
1428
|
+
opacity: 0;
|
|
1429
|
+
}
|
|
1430
|
+
to {
|
|
1431
|
+
transform: scale(1);
|
|
1432
|
+
opacity: 1;
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
h1 {
|
|
1436
|
+
color: #fff;
|
|
1437
|
+
margin: 0 0 1rem 0;
|
|
1438
|
+
font-size: 2.5rem;
|
|
1439
|
+
font-weight: 700;
|
|
1440
|
+
letter-spacing: -0.025em;
|
|
1441
|
+
}
|
|
369
1442
|
p {
|
|
370
1443
|
color: rgba(255, 255, 255, 0.8);
|
|
371
1444
|
margin: 0 0 2rem 0;
|
|
@@ -480,695 +1553,1670 @@ async function startCallbackServer(port) {
|
|
|
480
1553
|
`);
|
|
481
1554
|
}
|
|
482
1555
|
}
|
|
483
|
-
});
|
|
484
|
-
server.listen(port, () => {
|
|
485
|
-
resolve({ server, token: tokenPromise });
|
|
486
|
-
});
|
|
487
|
-
server.on("error", reject);
|
|
488
|
-
});
|
|
489
|
-
}
|
|
490
|
-
async function loginCommand() {
|
|
491
|
-
try {
|
|
492
|
-
if (await isLoggedIn()) {
|
|
1556
|
+
});
|
|
1557
|
+
server.listen(port, () => {
|
|
1558
|
+
resolve({ server, token: tokenPromise });
|
|
1559
|
+
});
|
|
1560
|
+
server.on("error", reject);
|
|
1561
|
+
});
|
|
1562
|
+
}
|
|
1563
|
+
async function loginCommand() {
|
|
1564
|
+
try {
|
|
1565
|
+
if (await isLoggedIn()) {
|
|
1566
|
+
console.log(
|
|
1567
|
+
source_default.yellow(
|
|
1568
|
+
"\u26A0\uFE0F You are already logged in. Run 'mcp-use logout' first if you want to login with a different account."
|
|
1569
|
+
)
|
|
1570
|
+
);
|
|
1571
|
+
return;
|
|
1572
|
+
}
|
|
1573
|
+
console.log(source_default.cyan.bold("\u{1F510} Logging in to mcp-use cloud...\n"));
|
|
1574
|
+
const port = await findAvailablePort();
|
|
1575
|
+
const redirectUri = `http://localhost:${port}/callback`;
|
|
1576
|
+
console.log(source_default.gray(`Starting local server on port ${port}...`));
|
|
1577
|
+
const { server, token } = await startCallbackServer(port);
|
|
1578
|
+
const webUrl = await getWebUrl();
|
|
1579
|
+
const loginUrl = `${webUrl}/auth/cli?redirect_uri=${encodeURIComponent(redirectUri)}`;
|
|
1580
|
+
console.log(source_default.gray(`Opening browser to ${webUrl}/auth/cli...
|
|
1581
|
+
`));
|
|
1582
|
+
console.log(
|
|
1583
|
+
source_default.white(
|
|
1584
|
+
"If the browser doesn't open automatically, please visit:\n" + source_default.cyan(loginUrl)
|
|
1585
|
+
)
|
|
1586
|
+
);
|
|
1587
|
+
await open_default(loginUrl);
|
|
1588
|
+
console.log(
|
|
1589
|
+
source_default.gray("\nWaiting for authentication... (this may take a moment)")
|
|
1590
|
+
);
|
|
1591
|
+
const jwtToken = await Promise.race([
|
|
1592
|
+
token,
|
|
1593
|
+
new Promise(
|
|
1594
|
+
(_, reject) => setTimeout(
|
|
1595
|
+
() => reject(new Error("Login timeout - please try again")),
|
|
1596
|
+
LOGIN_TIMEOUT
|
|
1597
|
+
)
|
|
1598
|
+
)
|
|
1599
|
+
]);
|
|
1600
|
+
server.close();
|
|
1601
|
+
console.log(
|
|
1602
|
+
source_default.gray("Received authentication token, creating API key...")
|
|
1603
|
+
);
|
|
1604
|
+
const api = await McpUseAPI.create();
|
|
1605
|
+
const apiKeyResponse = await api.createApiKey(jwtToken, "CLI");
|
|
1606
|
+
await writeConfig({
|
|
1607
|
+
apiKey: apiKeyResponse.api_key
|
|
1608
|
+
});
|
|
1609
|
+
console.log(source_default.green.bold("\n\u2713 Successfully logged in!"));
|
|
1610
|
+
console.log(
|
|
1611
|
+
source_default.gray(
|
|
1612
|
+
`
|
|
1613
|
+
Your API key has been saved to ${source_default.white("~/.mcp-use/config.json")}`
|
|
1614
|
+
)
|
|
1615
|
+
);
|
|
1616
|
+
console.log(
|
|
1617
|
+
source_default.gray(
|
|
1618
|
+
"You can now deploy your MCP servers with " + source_default.white("mcp-use deploy")
|
|
1619
|
+
)
|
|
1620
|
+
);
|
|
1621
|
+
process.exit(0);
|
|
1622
|
+
} catch (error) {
|
|
1623
|
+
console.error(
|
|
1624
|
+
source_default.red.bold("\n\u2717 Login failed:"),
|
|
1625
|
+
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
1626
|
+
);
|
|
1627
|
+
process.exit(1);
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
async function logoutCommand() {
|
|
1631
|
+
try {
|
|
1632
|
+
if (!await isLoggedIn()) {
|
|
1633
|
+
console.log(source_default.yellow("\u26A0\uFE0F You are not logged in."));
|
|
1634
|
+
return;
|
|
1635
|
+
}
|
|
1636
|
+
console.log(source_default.cyan.bold("\u{1F513} Logging out...\n"));
|
|
1637
|
+
await deleteConfig();
|
|
1638
|
+
console.log(source_default.green.bold("\u2713 Successfully logged out!"));
|
|
1639
|
+
console.log(
|
|
1640
|
+
source_default.gray(
|
|
1641
|
+
"\nYour local config has been deleted. The API key will remain active until revoked from the web interface."
|
|
1642
|
+
)
|
|
1643
|
+
);
|
|
1644
|
+
} catch (error) {
|
|
1645
|
+
console.error(
|
|
1646
|
+
source_default.red.bold("\n\u2717 Logout failed:"),
|
|
1647
|
+
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
1648
|
+
);
|
|
1649
|
+
process.exit(1);
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
async function whoamiCommand() {
|
|
1653
|
+
try {
|
|
1654
|
+
if (!await isLoggedIn()) {
|
|
1655
|
+
console.log(source_default.yellow("\u26A0\uFE0F You are not logged in."));
|
|
1656
|
+
console.log(
|
|
1657
|
+
source_default.gray("Run " + source_default.white("mcp-use login") + " to get started.")
|
|
1658
|
+
);
|
|
1659
|
+
return;
|
|
1660
|
+
}
|
|
1661
|
+
console.log(source_default.cyan.bold("\u{1F464} Current user:\n"));
|
|
1662
|
+
const api = await McpUseAPI.create();
|
|
1663
|
+
const authInfo = await api.testAuth();
|
|
1664
|
+
console.log(source_default.white("Email: ") + source_default.cyan(authInfo.email));
|
|
1665
|
+
console.log(source_default.white("User ID: ") + source_default.gray(authInfo.user_id));
|
|
1666
|
+
const apiKey = await getApiKey();
|
|
1667
|
+
if (apiKey) {
|
|
1668
|
+
const masked = apiKey.substring(0, 8) + "..." + apiKey.substring(apiKey.length - 4);
|
|
1669
|
+
console.log(source_default.white("API Key: ") + source_default.gray(masked));
|
|
1670
|
+
}
|
|
1671
|
+
} catch (error) {
|
|
1672
|
+
console.error(
|
|
1673
|
+
source_default.red.bold("\n\u2717 Failed to get user info:"),
|
|
1674
|
+
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
1675
|
+
);
|
|
1676
|
+
process.exit(1);
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
// src/commands/deploy.ts
|
|
1681
|
+
import { promises as fs8 } from "fs";
|
|
1682
|
+
import path4 from "path";
|
|
1683
|
+
import os4 from "os";
|
|
1684
|
+
import { exec as exec2 } from "child_process";
|
|
1685
|
+
import { promisify as promisify8 } from "util";
|
|
1686
|
+
|
|
1687
|
+
// src/utils/git.ts
|
|
1688
|
+
import { exec } from "child_process";
|
|
1689
|
+
import { promisify as promisify7 } from "util";
|
|
1690
|
+
var execAsync = promisify7(exec);
|
|
1691
|
+
async function gitCommand(command, cwd = process.cwd()) {
|
|
1692
|
+
try {
|
|
1693
|
+
const { stdout } = await execAsync(command, { cwd });
|
|
1694
|
+
return stdout.trim();
|
|
1695
|
+
} catch (error) {
|
|
1696
|
+
return null;
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
async function isGitRepo(cwd = process.cwd()) {
|
|
1700
|
+
const result = await gitCommand("git rev-parse --is-inside-work-tree", cwd);
|
|
1701
|
+
return result === "true";
|
|
1702
|
+
}
|
|
1703
|
+
async function getRemoteUrl(cwd = process.cwd()) {
|
|
1704
|
+
return gitCommand("git config --get remote.origin.url", cwd);
|
|
1705
|
+
}
|
|
1706
|
+
function parseGitHubUrl(url) {
|
|
1707
|
+
const sshMatch = url.match(/git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/);
|
|
1708
|
+
const httpsMatch = url.match(
|
|
1709
|
+
/https:\/\/github\.com\/([^/]+)\/(.+?)(?:\.git)?$/
|
|
1710
|
+
);
|
|
1711
|
+
const match = sshMatch || httpsMatch;
|
|
1712
|
+
if (!match) return null;
|
|
1713
|
+
return {
|
|
1714
|
+
owner: match[1],
|
|
1715
|
+
repo: match[2]
|
|
1716
|
+
};
|
|
1717
|
+
}
|
|
1718
|
+
async function getCurrentBranch(cwd = process.cwd()) {
|
|
1719
|
+
return gitCommand("git rev-parse --abbrev-ref HEAD", cwd);
|
|
1720
|
+
}
|
|
1721
|
+
async function getCommitSha(cwd = process.cwd()) {
|
|
1722
|
+
return gitCommand("git rev-parse HEAD", cwd);
|
|
1723
|
+
}
|
|
1724
|
+
async function getCommitMessage(cwd = process.cwd()) {
|
|
1725
|
+
return gitCommand("git log -1 --pretty=%B", cwd);
|
|
1726
|
+
}
|
|
1727
|
+
async function getGitInfo(cwd = process.cwd()) {
|
|
1728
|
+
const isRepo = await isGitRepo(cwd);
|
|
1729
|
+
if (!isRepo) {
|
|
1730
|
+
return { isGitRepo: false };
|
|
1731
|
+
}
|
|
1732
|
+
const remoteUrl = await getRemoteUrl(cwd);
|
|
1733
|
+
const branch = await getCurrentBranch(cwd);
|
|
1734
|
+
const commitSha = await getCommitSha(cwd);
|
|
1735
|
+
const commitMessage = await getCommitMessage(cwd);
|
|
1736
|
+
let owner;
|
|
1737
|
+
let repo;
|
|
1738
|
+
if (remoteUrl) {
|
|
1739
|
+
const parsed = parseGitHubUrl(remoteUrl);
|
|
1740
|
+
if (parsed) {
|
|
1741
|
+
owner = parsed.owner;
|
|
1742
|
+
repo = parsed.repo;
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
return {
|
|
1746
|
+
isGitRepo: true,
|
|
1747
|
+
remoteUrl: remoteUrl || void 0,
|
|
1748
|
+
owner,
|
|
1749
|
+
repo,
|
|
1750
|
+
branch: branch || void 0,
|
|
1751
|
+
commitSha: commitSha || void 0,
|
|
1752
|
+
commitMessage: commitMessage || void 0
|
|
1753
|
+
};
|
|
1754
|
+
}
|
|
1755
|
+
function isGitHubUrl(url) {
|
|
1756
|
+
return url.includes("github.com");
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
// src/commands/deploy.ts
|
|
1760
|
+
var execAsync2 = promisify8(exec2);
|
|
1761
|
+
async function isMcpProject(cwd = process.cwd()) {
|
|
1762
|
+
try {
|
|
1763
|
+
const packageJsonPath = path4.join(cwd, "package.json");
|
|
1764
|
+
const content = await fs8.readFile(packageJsonPath, "utf-8");
|
|
1765
|
+
const packageJson2 = JSON.parse(content);
|
|
1766
|
+
const hasMcpDeps = packageJson2.dependencies?.["mcp-use"] || packageJson2.dependencies?.["@modelcontextprotocol/sdk"] || packageJson2.devDependencies?.["mcp-use"] || packageJson2.devDependencies?.["@modelcontextprotocol/sdk"];
|
|
1767
|
+
const hasMcpScripts = packageJson2.scripts?.mcp || packageJson2.scripts?.["mcp:dev"];
|
|
1768
|
+
return !!(hasMcpDeps || hasMcpScripts);
|
|
1769
|
+
} catch {
|
|
1770
|
+
return false;
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
async function getProjectName(cwd = process.cwd()) {
|
|
1774
|
+
try {
|
|
1775
|
+
const packageJsonPath = path4.join(cwd, "package.json");
|
|
1776
|
+
const content = await fs8.readFile(packageJsonPath, "utf-8");
|
|
1777
|
+
const packageJson2 = JSON.parse(content);
|
|
1778
|
+
if (packageJson2.name) {
|
|
1779
|
+
return packageJson2.name;
|
|
1780
|
+
}
|
|
1781
|
+
} catch {
|
|
1782
|
+
}
|
|
1783
|
+
return path4.basename(cwd);
|
|
1784
|
+
}
|
|
1785
|
+
async function detectBuildCommand(cwd = process.cwd()) {
|
|
1786
|
+
try {
|
|
1787
|
+
const packageJsonPath = path4.join(cwd, "package.json");
|
|
1788
|
+
const content = await fs8.readFile(packageJsonPath, "utf-8");
|
|
1789
|
+
const packageJson2 = JSON.parse(content);
|
|
1790
|
+
if (packageJson2.scripts?.build) {
|
|
1791
|
+
return "npm run build";
|
|
1792
|
+
}
|
|
1793
|
+
} catch {
|
|
1794
|
+
}
|
|
1795
|
+
return void 0;
|
|
1796
|
+
}
|
|
1797
|
+
async function detectStartCommand(cwd = process.cwd()) {
|
|
1798
|
+
try {
|
|
1799
|
+
const packageJsonPath = path4.join(cwd, "package.json");
|
|
1800
|
+
const content = await fs8.readFile(packageJsonPath, "utf-8");
|
|
1801
|
+
const packageJson2 = JSON.parse(content);
|
|
1802
|
+
if (packageJson2.scripts?.start) {
|
|
1803
|
+
return "npm start";
|
|
1804
|
+
}
|
|
1805
|
+
if (packageJson2.main) {
|
|
1806
|
+
return `node ${packageJson2.main}`;
|
|
1807
|
+
}
|
|
1808
|
+
} catch {
|
|
1809
|
+
}
|
|
1810
|
+
return void 0;
|
|
1811
|
+
}
|
|
1812
|
+
async function detectRuntime(cwd = process.cwd()) {
|
|
1813
|
+
try {
|
|
1814
|
+
const pythonFiles = ["requirements.txt", "pyproject.toml", "setup.py"];
|
|
1815
|
+
for (const file of pythonFiles) {
|
|
1816
|
+
try {
|
|
1817
|
+
await fs8.access(path4.join(cwd, file));
|
|
1818
|
+
return "python";
|
|
1819
|
+
} catch {
|
|
1820
|
+
continue;
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
try {
|
|
1824
|
+
await fs8.access(path4.join(cwd, "package.json"));
|
|
1825
|
+
return "node";
|
|
1826
|
+
} catch {
|
|
1827
|
+
}
|
|
1828
|
+
} catch {
|
|
1829
|
+
}
|
|
1830
|
+
return "node";
|
|
1831
|
+
}
|
|
1832
|
+
async function prompt(question, defaultValue = "n") {
|
|
1833
|
+
const readline = await import("readline");
|
|
1834
|
+
const rl = readline.createInterface({
|
|
1835
|
+
input: process.stdin,
|
|
1836
|
+
output: process.stdout
|
|
1837
|
+
});
|
|
1838
|
+
const defaultIndicator = defaultValue === "y" ? "Y/n" : "y/N";
|
|
1839
|
+
const questionWithDefault = question.replace(
|
|
1840
|
+
/(\(y\/n\):)/,
|
|
1841
|
+
`(${defaultIndicator}):`
|
|
1842
|
+
);
|
|
1843
|
+
return new Promise((resolve) => {
|
|
1844
|
+
rl.question(questionWithDefault, (answer) => {
|
|
1845
|
+
rl.close();
|
|
1846
|
+
const trimmedAnswer = answer.trim().toLowerCase();
|
|
1847
|
+
if (trimmedAnswer === "") {
|
|
1848
|
+
resolve(defaultValue === "y");
|
|
1849
|
+
} else {
|
|
1850
|
+
resolve(trimmedAnswer === "y" || trimmedAnswer === "yes");
|
|
1851
|
+
}
|
|
1852
|
+
});
|
|
1853
|
+
});
|
|
1854
|
+
}
|
|
1855
|
+
async function createTarball(cwd) {
|
|
1856
|
+
const tmpDir = os4.tmpdir();
|
|
1857
|
+
const tarballPath = path4.join(tmpDir, `mcp-deploy-${Date.now()}.tar.gz`);
|
|
1858
|
+
const excludePatterns = [
|
|
1859
|
+
"node_modules",
|
|
1860
|
+
".git",
|
|
1861
|
+
"dist",
|
|
1862
|
+
"build",
|
|
1863
|
+
".next",
|
|
1864
|
+
".venv",
|
|
1865
|
+
"__pycache__",
|
|
1866
|
+
"*.pyc",
|
|
1867
|
+
".DS_Store",
|
|
1868
|
+
"._*",
|
|
1869
|
+
// macOS resource fork files
|
|
1870
|
+
".mcp-use",
|
|
1871
|
+
// Build artifacts directory
|
|
1872
|
+
".env",
|
|
1873
|
+
".env.local",
|
|
1874
|
+
"*.log"
|
|
1875
|
+
];
|
|
1876
|
+
const excludeFlags = excludePatterns.map((pattern) => `--exclude=${pattern}`).join(" ");
|
|
1877
|
+
const command = `tar ${excludeFlags} -czf "${tarballPath}" -C "${cwd}" . 2>&1 || true`;
|
|
1878
|
+
try {
|
|
1879
|
+
await execAsync2(command);
|
|
1880
|
+
return tarballPath;
|
|
1881
|
+
} catch (error) {
|
|
1882
|
+
throw new Error(
|
|
1883
|
+
`Failed to create tarball: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
1884
|
+
);
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
function formatFileSize(bytes) {
|
|
1888
|
+
if (bytes === 0) return "0 B";
|
|
1889
|
+
const k = 1024;
|
|
1890
|
+
const sizes = ["B", "KB", "MB", "GB"];
|
|
1891
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
1892
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
1893
|
+
}
|
|
1894
|
+
async function displayDeploymentProgress(api, deployment) {
|
|
1895
|
+
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
1896
|
+
let frameIndex = 0;
|
|
1897
|
+
let spinnerInterval = null;
|
|
1898
|
+
let lastStep = "";
|
|
1899
|
+
const startSpinner = (message) => {
|
|
1900
|
+
if (spinnerInterval) {
|
|
1901
|
+
clearInterval(spinnerInterval);
|
|
1902
|
+
}
|
|
1903
|
+
process.stdout.write("\r\x1B[K");
|
|
1904
|
+
spinnerInterval = setInterval(() => {
|
|
1905
|
+
const frame = frames[frameIndex];
|
|
1906
|
+
frameIndex = (frameIndex + 1) % frames.length;
|
|
1907
|
+
process.stdout.write(
|
|
1908
|
+
"\r" + source_default.cyan(frame) + " " + source_default.gray(message)
|
|
1909
|
+
);
|
|
1910
|
+
}, 80);
|
|
1911
|
+
};
|
|
1912
|
+
const stopSpinner = () => {
|
|
1913
|
+
if (spinnerInterval) {
|
|
1914
|
+
clearInterval(spinnerInterval);
|
|
1915
|
+
spinnerInterval = null;
|
|
1916
|
+
process.stdout.write("\r\x1B[K");
|
|
1917
|
+
}
|
|
1918
|
+
};
|
|
1919
|
+
console.log();
|
|
1920
|
+
startSpinner("Deploying...");
|
|
1921
|
+
try {
|
|
1922
|
+
for await (const log of api.streamDeploymentLogs(deployment.id)) {
|
|
1923
|
+
try {
|
|
1924
|
+
const logData = JSON.parse(log);
|
|
1925
|
+
if (logData.step && logData.step !== lastStep) {
|
|
1926
|
+
lastStep = logData.step;
|
|
1927
|
+
const stepMessages = {
|
|
1928
|
+
clone: "Preparing source code...",
|
|
1929
|
+
analyze: "Analyzing project...",
|
|
1930
|
+
build: "Building container image...",
|
|
1931
|
+
deploy: "Deploying to cloud..."
|
|
1932
|
+
};
|
|
1933
|
+
const message = stepMessages[logData.step] || "Deploying...";
|
|
1934
|
+
startSpinner(message);
|
|
1935
|
+
}
|
|
1936
|
+
if (logData.line) {
|
|
1937
|
+
stopSpinner();
|
|
1938
|
+
const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
|
|
1939
|
+
const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
|
|
1940
|
+
console.log(stepPrefix + levelColor(logData.line));
|
|
1941
|
+
}
|
|
1942
|
+
} catch {
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
} catch (error) {
|
|
1946
|
+
stopSpinner();
|
|
1947
|
+
}
|
|
1948
|
+
let checkCount = 0;
|
|
1949
|
+
const maxChecks = 60;
|
|
1950
|
+
let delay = 3e3;
|
|
1951
|
+
const maxDelay = 1e4;
|
|
1952
|
+
let lastDisplayedLogLength = 0;
|
|
1953
|
+
while (checkCount < maxChecks) {
|
|
1954
|
+
const currentDelay = delay;
|
|
1955
|
+
await new Promise((resolve) => setTimeout(resolve, currentDelay));
|
|
1956
|
+
const finalDeployment = await api.getDeployment(deployment.id);
|
|
1957
|
+
if (finalDeployment.buildLogs && finalDeployment.buildLogs.length > lastDisplayedLogLength) {
|
|
1958
|
+
const newLogs = finalDeployment.buildLogs.substring(
|
|
1959
|
+
lastDisplayedLogLength
|
|
1960
|
+
);
|
|
1961
|
+
const logLines = newLogs.split("\n").filter((l) => l.trim());
|
|
1962
|
+
for (const line of logLines) {
|
|
1963
|
+
try {
|
|
1964
|
+
const logData = JSON.parse(line);
|
|
1965
|
+
if (logData.line) {
|
|
1966
|
+
stopSpinner();
|
|
1967
|
+
const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
|
|
1968
|
+
const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
|
|
1969
|
+
console.log(stepPrefix + levelColor(logData.line));
|
|
1970
|
+
}
|
|
1971
|
+
} catch {
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
lastDisplayedLogLength = finalDeployment.buildLogs.length;
|
|
1975
|
+
}
|
|
1976
|
+
if (finalDeployment.status === "running") {
|
|
1977
|
+
const mcpUrl = `https://${finalDeployment.domain}/mcp`;
|
|
1978
|
+
const inspectorUrl = `https://inspector.mcp-use.com/inspector?autoConnect=${encodeURIComponent(mcpUrl)}`;
|
|
1979
|
+
console.log(source_default.green.bold("\u2713 Deployment successful!\n"));
|
|
1980
|
+
console.log(source_default.white("\u{1F310} MCP Server URL:"));
|
|
1981
|
+
console.log(source_default.cyan.bold(` ${mcpUrl}
|
|
1982
|
+
`));
|
|
1983
|
+
console.log(source_default.white("\u{1F50D} Inspector URL:"));
|
|
1984
|
+
console.log(source_default.cyan.bold(` ${inspectorUrl}
|
|
1985
|
+
`));
|
|
1986
|
+
if (finalDeployment.customDomain) {
|
|
1987
|
+
const customMcpUrl = `https://${finalDeployment.customDomain}/mcp`;
|
|
1988
|
+
const customInspectorUrl = `https://inspector.mcp-use.com/inspect?autoConnect=${encodeURIComponent(customMcpUrl)}`;
|
|
1989
|
+
console.log(source_default.white("\u{1F517} Custom Domain:"));
|
|
1990
|
+
console.log(source_default.cyan.bold(` ${customMcpUrl}
|
|
1991
|
+
`));
|
|
1992
|
+
console.log(source_default.white("\u{1F50D} Custom Inspector:"));
|
|
1993
|
+
console.log(source_default.cyan.bold(` ${customInspectorUrl}
|
|
1994
|
+
`));
|
|
1995
|
+
}
|
|
1996
|
+
console.log(
|
|
1997
|
+
source_default.gray("Deployment ID: ") + source_default.white(finalDeployment.id)
|
|
1998
|
+
);
|
|
1999
|
+
return;
|
|
2000
|
+
} else if (finalDeployment.status === "failed") {
|
|
2001
|
+
console.log(source_default.red.bold("\u2717 Deployment failed\n"));
|
|
2002
|
+
if (finalDeployment.error) {
|
|
2003
|
+
console.log(source_default.red("Error: ") + finalDeployment.error);
|
|
2004
|
+
}
|
|
2005
|
+
if (finalDeployment.buildLogs) {
|
|
2006
|
+
console.log(source_default.gray("\nBuild logs:"));
|
|
2007
|
+
try {
|
|
2008
|
+
const logs = finalDeployment.buildLogs.split("\n").filter((l) => l.trim());
|
|
2009
|
+
for (const log of logs) {
|
|
2010
|
+
try {
|
|
2011
|
+
const logData = JSON.parse(log);
|
|
2012
|
+
if (logData.line) {
|
|
2013
|
+
console.log(source_default.gray(` ${logData.line}`));
|
|
2014
|
+
}
|
|
2015
|
+
} catch {
|
|
2016
|
+
console.log(source_default.gray(` ${log}`));
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
} catch {
|
|
2020
|
+
console.log(source_default.gray(finalDeployment.buildLogs));
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
process.exit(1);
|
|
2024
|
+
} else if (finalDeployment.status === "building") {
|
|
2025
|
+
startSpinner("Building and deploying...");
|
|
2026
|
+
checkCount++;
|
|
2027
|
+
delay = Math.min(delay * 1.2, maxDelay);
|
|
2028
|
+
} else {
|
|
2029
|
+
console.log(
|
|
2030
|
+
source_default.yellow("\u26A0\uFE0F Deployment status: ") + finalDeployment.status
|
|
2031
|
+
);
|
|
2032
|
+
return;
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
stopSpinner();
|
|
2036
|
+
console.log(source_default.yellow("\u26A0\uFE0F Deployment is taking longer than expected."));
|
|
2037
|
+
console.log(
|
|
2038
|
+
source_default.gray("Check status with: ") + source_default.white(`mcp-use status ${deployment.id}`)
|
|
2039
|
+
);
|
|
2040
|
+
}
|
|
2041
|
+
async function deployCommand(options) {
|
|
2042
|
+
try {
|
|
2043
|
+
const cwd = process.cwd();
|
|
2044
|
+
if (!await isLoggedIn()) {
|
|
2045
|
+
console.log(source_default.red("\u2717 You are not logged in."));
|
|
2046
|
+
console.log(
|
|
2047
|
+
source_default.gray("Run " + source_default.white("mcp-use login") + " to get started.")
|
|
2048
|
+
);
|
|
2049
|
+
process.exit(1);
|
|
2050
|
+
}
|
|
2051
|
+
console.log(source_default.cyan.bold("\u{1F680} Deploying to mcp-use cloud...\n"));
|
|
2052
|
+
const isMcp = await isMcpProject(cwd);
|
|
2053
|
+
if (!isMcp) {
|
|
2054
|
+
console.log(
|
|
2055
|
+
source_default.yellow(
|
|
2056
|
+
"\u26A0\uFE0F This doesn't appear to be an MCP server project (no mcp-use or @modelcontextprotocol/sdk dependency found)."
|
|
2057
|
+
)
|
|
2058
|
+
);
|
|
2059
|
+
const shouldContinue = await prompt(
|
|
2060
|
+
source_default.white("Continue anyway? (y/n): ")
|
|
2061
|
+
);
|
|
2062
|
+
if (!shouldContinue) {
|
|
2063
|
+
console.log(source_default.gray("Deployment cancelled."));
|
|
2064
|
+
process.exit(0);
|
|
2065
|
+
}
|
|
2066
|
+
console.log();
|
|
2067
|
+
}
|
|
2068
|
+
const gitInfo = await getGitInfo(cwd);
|
|
2069
|
+
if (!options.fromSource && gitInfo.isGitRepo && gitInfo.remoteUrl && isGitHubUrl(gitInfo.remoteUrl)) {
|
|
2070
|
+
if (!gitInfo.owner || !gitInfo.repo) {
|
|
2071
|
+
console.log(
|
|
2072
|
+
source_default.red(
|
|
2073
|
+
"\u2717 Could not parse GitHub repository information from remote URL."
|
|
2074
|
+
)
|
|
2075
|
+
);
|
|
2076
|
+
process.exit(1);
|
|
2077
|
+
}
|
|
2078
|
+
console.log(source_default.white("GitHub repository detected:"));
|
|
2079
|
+
console.log(
|
|
2080
|
+
source_default.gray(` Repository: `) + source_default.cyan(`${gitInfo.owner}/${gitInfo.repo}`)
|
|
2081
|
+
);
|
|
2082
|
+
console.log(
|
|
2083
|
+
source_default.gray(` Branch: `) + source_default.cyan(gitInfo.branch || "main")
|
|
2084
|
+
);
|
|
2085
|
+
if (gitInfo.commitSha) {
|
|
2086
|
+
console.log(
|
|
2087
|
+
source_default.gray(` Commit: `) + source_default.gray(gitInfo.commitSha.substring(0, 7))
|
|
2088
|
+
);
|
|
2089
|
+
}
|
|
2090
|
+
if (gitInfo.commitMessage) {
|
|
2091
|
+
console.log(
|
|
2092
|
+
source_default.gray(` Message: `) + source_default.gray(gitInfo.commitMessage.split("\n")[0])
|
|
2093
|
+
);
|
|
2094
|
+
}
|
|
2095
|
+
console.log();
|
|
2096
|
+
const shouldDeploy = await prompt(
|
|
2097
|
+
source_default.white(
|
|
2098
|
+
`Deploy from GitHub repository ${gitInfo.owner}/${gitInfo.repo}? (y/n): `
|
|
2099
|
+
)
|
|
2100
|
+
);
|
|
2101
|
+
if (!shouldDeploy) {
|
|
2102
|
+
console.log(source_default.gray("Deployment cancelled."));
|
|
2103
|
+
process.exit(0);
|
|
2104
|
+
}
|
|
2105
|
+
const projectName = options.name || await getProjectName(cwd);
|
|
2106
|
+
const runtime = options.runtime || await detectRuntime(cwd);
|
|
2107
|
+
const port = options.port || 3e3;
|
|
2108
|
+
const buildCommand = await detectBuildCommand(cwd);
|
|
2109
|
+
const startCommand = await detectStartCommand(cwd);
|
|
2110
|
+
console.log();
|
|
2111
|
+
console.log(source_default.white("Deployment configuration:"));
|
|
2112
|
+
console.log(source_default.gray(` Name: `) + source_default.cyan(projectName));
|
|
2113
|
+
console.log(source_default.gray(` Runtime: `) + source_default.cyan(runtime));
|
|
2114
|
+
console.log(source_default.gray(` Port: `) + source_default.cyan(port));
|
|
2115
|
+
if (buildCommand) {
|
|
2116
|
+
console.log(source_default.gray(` Build command: `) + source_default.cyan(buildCommand));
|
|
2117
|
+
}
|
|
2118
|
+
if (startCommand) {
|
|
2119
|
+
console.log(source_default.gray(` Start command: `) + source_default.cyan(startCommand));
|
|
2120
|
+
}
|
|
2121
|
+
console.log();
|
|
2122
|
+
const deploymentRequest = {
|
|
2123
|
+
name: projectName,
|
|
2124
|
+
source: {
|
|
2125
|
+
type: "github",
|
|
2126
|
+
repo: `${gitInfo.owner}/${gitInfo.repo}`,
|
|
2127
|
+
branch: gitInfo.branch || "main",
|
|
2128
|
+
runtime,
|
|
2129
|
+
port,
|
|
2130
|
+
buildCommand,
|
|
2131
|
+
startCommand
|
|
2132
|
+
},
|
|
2133
|
+
healthCheckPath: "/healthz"
|
|
2134
|
+
};
|
|
2135
|
+
console.log(source_default.gray("Creating deployment..."));
|
|
2136
|
+
const api = await McpUseAPI.create();
|
|
2137
|
+
const deployment = await api.createDeployment(deploymentRequest);
|
|
2138
|
+
console.log(
|
|
2139
|
+
source_default.green("\u2713 Deployment created: ") + source_default.gray(deployment.id)
|
|
2140
|
+
);
|
|
2141
|
+
await displayDeploymentProgress(api, deployment);
|
|
2142
|
+
if (options.open && deployment.domain) {
|
|
2143
|
+
console.log();
|
|
2144
|
+
console.log(source_default.gray("Opening deployment in browser..."));
|
|
2145
|
+
await open_default(`https://${deployment.domain}`);
|
|
2146
|
+
}
|
|
2147
|
+
} else {
|
|
2148
|
+
if (options.fromSource) {
|
|
2149
|
+
console.log(
|
|
2150
|
+
source_default.white("\u{1F4E6} Deploying from local source code (--from-source)...")
|
|
2151
|
+
);
|
|
2152
|
+
} else {
|
|
2153
|
+
console.log(
|
|
2154
|
+
source_default.yellow(
|
|
2155
|
+
"\u26A0\uFE0F This is not a GitHub repository or no remote is configured."
|
|
2156
|
+
)
|
|
2157
|
+
);
|
|
2158
|
+
console.log(source_default.white("Deploying from local source code instead..."));
|
|
2159
|
+
}
|
|
2160
|
+
console.log();
|
|
2161
|
+
const projectName = options.name || await getProjectName(cwd);
|
|
2162
|
+
const runtime = options.runtime || await detectRuntime(cwd);
|
|
2163
|
+
const port = options.port || 3e3;
|
|
2164
|
+
const buildCommand = await detectBuildCommand(cwd);
|
|
2165
|
+
const startCommand = await detectStartCommand(cwd);
|
|
2166
|
+
console.log(source_default.white("Deployment configuration:"));
|
|
2167
|
+
console.log(source_default.gray(` Name: `) + source_default.cyan(projectName));
|
|
2168
|
+
console.log(source_default.gray(` Runtime: `) + source_default.cyan(runtime));
|
|
2169
|
+
console.log(source_default.gray(` Port: `) + source_default.cyan(port));
|
|
2170
|
+
if (buildCommand) {
|
|
2171
|
+
console.log(source_default.gray(` Build command: `) + source_default.cyan(buildCommand));
|
|
2172
|
+
}
|
|
2173
|
+
if (startCommand) {
|
|
2174
|
+
console.log(source_default.gray(` Start command: `) + source_default.cyan(startCommand));
|
|
2175
|
+
}
|
|
2176
|
+
console.log();
|
|
2177
|
+
const shouldDeploy = await prompt(
|
|
2178
|
+
source_default.white("Deploy from local source? (y/n): "),
|
|
2179
|
+
"y"
|
|
2180
|
+
);
|
|
2181
|
+
if (!shouldDeploy) {
|
|
2182
|
+
console.log(source_default.gray("Deployment cancelled."));
|
|
2183
|
+
process.exit(0);
|
|
2184
|
+
}
|
|
2185
|
+
console.log();
|
|
2186
|
+
console.log(source_default.gray("Packaging source code..."));
|
|
2187
|
+
const tarballPath = await createTarball(cwd);
|
|
2188
|
+
const stats = await fs8.stat(tarballPath);
|
|
493
2189
|
console.log(
|
|
494
|
-
|
|
495
|
-
"\u26A0\uFE0F You are already logged in. Run 'mcp-use logout' first if you want to login with a different account."
|
|
496
|
-
)
|
|
2190
|
+
source_default.green("\u2713 Packaged: ") + source_default.gray(formatFileSize(stats.size))
|
|
497
2191
|
);
|
|
498
|
-
|
|
2192
|
+
const maxSize = 2 * 1024 * 1024;
|
|
2193
|
+
if (stats.size > maxSize) {
|
|
2194
|
+
console.log(
|
|
2195
|
+
source_default.red(
|
|
2196
|
+
`\u2717 File size (${formatFileSize(stats.size)}) exceeds maximum of 2MB`
|
|
2197
|
+
)
|
|
2198
|
+
);
|
|
2199
|
+
await fs8.unlink(tarballPath);
|
|
2200
|
+
process.exit(1);
|
|
2201
|
+
}
|
|
2202
|
+
const deploymentRequest = {
|
|
2203
|
+
name: projectName,
|
|
2204
|
+
source: {
|
|
2205
|
+
type: "upload",
|
|
2206
|
+
runtime,
|
|
2207
|
+
port,
|
|
2208
|
+
buildCommand,
|
|
2209
|
+
startCommand
|
|
2210
|
+
},
|
|
2211
|
+
healthCheckPath: "/healthz"
|
|
2212
|
+
};
|
|
2213
|
+
console.log(source_default.gray("Creating deployment..."));
|
|
2214
|
+
const api = await McpUseAPI.create();
|
|
2215
|
+
const deployment = await api.createDeploymentWithUpload(
|
|
2216
|
+
deploymentRequest,
|
|
2217
|
+
tarballPath
|
|
2218
|
+
);
|
|
2219
|
+
await fs8.unlink(tarballPath);
|
|
2220
|
+
console.log(
|
|
2221
|
+
source_default.green("\u2713 Deployment created: ") + source_default.gray(deployment.id)
|
|
2222
|
+
);
|
|
2223
|
+
await displayDeploymentProgress(api, deployment);
|
|
2224
|
+
if (options.open && deployment.domain) {
|
|
2225
|
+
console.log();
|
|
2226
|
+
console.log(source_default.gray("Opening deployment in browser..."));
|
|
2227
|
+
await open_default(`https://${deployment.domain}`);
|
|
2228
|
+
}
|
|
499
2229
|
}
|
|
500
|
-
console.log(import_chalk.default.cyan.bold("\u{1F510} Logging in to mcp-use cloud...\n"));
|
|
501
|
-
const port = await findAvailablePort();
|
|
502
|
-
const redirectUri = `http://localhost:${port}/callback`;
|
|
503
|
-
console.log(import_chalk.default.gray(`Starting local server on port ${port}...`));
|
|
504
|
-
const { server, token } = await startCallbackServer(port);
|
|
505
|
-
const webUrl = await getWebUrl();
|
|
506
|
-
const loginUrl = `${webUrl}/auth/cli?redirect_uri=${encodeURIComponent(redirectUri)}`;
|
|
507
|
-
console.log(import_chalk.default.gray(`Opening browser to ${webUrl}/auth/cli...
|
|
508
|
-
`));
|
|
509
|
-
console.log(
|
|
510
|
-
import_chalk.default.white(
|
|
511
|
-
"If the browser doesn't open automatically, please visit:\n" + import_chalk.default.cyan(loginUrl)
|
|
512
|
-
)
|
|
513
|
-
);
|
|
514
|
-
await (0, import_open.default)(loginUrl);
|
|
515
|
-
console.log(
|
|
516
|
-
import_chalk.default.gray("\nWaiting for authentication... (this may take a moment)")
|
|
517
|
-
);
|
|
518
|
-
const jwtToken = await Promise.race([
|
|
519
|
-
token,
|
|
520
|
-
new Promise(
|
|
521
|
-
(_, reject) => setTimeout(
|
|
522
|
-
() => reject(new Error("Login timeout - please try again")),
|
|
523
|
-
LOGIN_TIMEOUT
|
|
524
|
-
)
|
|
525
|
-
)
|
|
526
|
-
]);
|
|
527
|
-
server.close();
|
|
528
|
-
console.log(
|
|
529
|
-
import_chalk.default.gray("Received authentication token, creating API key...")
|
|
530
|
-
);
|
|
531
|
-
const api = await McpUseAPI.create();
|
|
532
|
-
const apiKeyResponse = await api.createApiKey(jwtToken, "CLI");
|
|
533
|
-
await writeConfig({
|
|
534
|
-
apiKey: apiKeyResponse.api_key
|
|
535
|
-
});
|
|
536
|
-
console.log(import_chalk.default.green.bold("\n\u2713 Successfully logged in!"));
|
|
537
|
-
console.log(
|
|
538
|
-
import_chalk.default.gray(
|
|
539
|
-
`
|
|
540
|
-
Your API key has been saved to ${import_chalk.default.white("~/.mcp-use/config.json")}`
|
|
541
|
-
)
|
|
542
|
-
);
|
|
543
|
-
console.log(
|
|
544
|
-
import_chalk.default.gray(
|
|
545
|
-
"You can now deploy your MCP servers with " + import_chalk.default.white("mcp-use deploy")
|
|
546
|
-
)
|
|
547
|
-
);
|
|
548
|
-
process.exit(0);
|
|
549
2230
|
} catch (error) {
|
|
550
2231
|
console.error(
|
|
551
|
-
|
|
552
|
-
|
|
2232
|
+
source_default.red.bold("\n\u2717 Deployment failed:"),
|
|
2233
|
+
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
553
2234
|
);
|
|
554
2235
|
process.exit(1);
|
|
555
2236
|
}
|
|
556
2237
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
import_chalk.default.red.bold("\n\u2717 Logout failed:"),
|
|
574
|
-
import_chalk.default.red(error instanceof Error ? error.message : "Unknown error")
|
|
575
|
-
);
|
|
576
|
-
process.exit(1);
|
|
2238
|
+
|
|
2239
|
+
// src/commands/client.ts
|
|
2240
|
+
import { Command } from "commander";
|
|
2241
|
+
import { createInterface } from "readline";
|
|
2242
|
+
import { MCPClient } from "mcp-use";
|
|
2243
|
+
|
|
2244
|
+
// src/utils/session-storage.ts
|
|
2245
|
+
import { homedir } from "os";
|
|
2246
|
+
import { join } from "path";
|
|
2247
|
+
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
2248
|
+
import { existsSync } from "fs";
|
|
2249
|
+
var SESSION_FILE_PATH = join(homedir(), ".mcp-use", "cli-sessions.json");
|
|
2250
|
+
async function ensureSessionDir() {
|
|
2251
|
+
const dir = join(homedir(), ".mcp-use");
|
|
2252
|
+
if (!existsSync(dir)) {
|
|
2253
|
+
await mkdir(dir, { recursive: true });
|
|
577
2254
|
}
|
|
578
2255
|
}
|
|
579
|
-
async function
|
|
2256
|
+
async function loadSessions() {
|
|
580
2257
|
try {
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
import_chalk.default.gray("Run " + import_chalk.default.white("mcp-use login") + " to get started.")
|
|
585
|
-
);
|
|
586
|
-
return;
|
|
587
|
-
}
|
|
588
|
-
console.log(import_chalk.default.cyan.bold("\u{1F464} Current user:\n"));
|
|
589
|
-
const api = await McpUseAPI.create();
|
|
590
|
-
const authInfo = await api.testAuth();
|
|
591
|
-
console.log(import_chalk.default.white("Email: ") + import_chalk.default.cyan(authInfo.email));
|
|
592
|
-
console.log(import_chalk.default.white("User ID: ") + import_chalk.default.gray(authInfo.user_id));
|
|
593
|
-
const apiKey = await getApiKey();
|
|
594
|
-
if (apiKey) {
|
|
595
|
-
const masked = apiKey.substring(0, 8) + "..." + apiKey.substring(apiKey.length - 4);
|
|
596
|
-
console.log(import_chalk.default.white("API Key: ") + import_chalk.default.gray(masked));
|
|
2258
|
+
await ensureSessionDir();
|
|
2259
|
+
if (!existsSync(SESSION_FILE_PATH)) {
|
|
2260
|
+
return { activeSession: null, sessions: {} };
|
|
597
2261
|
}
|
|
2262
|
+
const content = await readFile(SESSION_FILE_PATH, "utf-8");
|
|
2263
|
+
return JSON.parse(content);
|
|
598
2264
|
} catch (error) {
|
|
599
|
-
|
|
600
|
-
import_chalk.default.red.bold("\n\u2717 Failed to get user info:"),
|
|
601
|
-
import_chalk.default.red(error instanceof Error ? error.message : "Unknown error")
|
|
602
|
-
);
|
|
603
|
-
process.exit(1);
|
|
2265
|
+
return { activeSession: null, sessions: {} };
|
|
604
2266
|
}
|
|
605
2267
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
2268
|
+
async function saveSessions(storage) {
|
|
2269
|
+
await ensureSessionDir();
|
|
2270
|
+
await writeFile(SESSION_FILE_PATH, JSON.stringify(storage, null, 2), "utf-8");
|
|
2271
|
+
}
|
|
2272
|
+
async function saveSession(name, config) {
|
|
2273
|
+
const storage = await loadSessions();
|
|
2274
|
+
storage.sessions[name] = {
|
|
2275
|
+
...config,
|
|
2276
|
+
lastUsed: (/* @__PURE__ */ new Date()).toISOString()
|
|
2277
|
+
};
|
|
2278
|
+
if (!storage.activeSession) {
|
|
2279
|
+
storage.activeSession = name;
|
|
2280
|
+
}
|
|
2281
|
+
await saveSessions(storage);
|
|
2282
|
+
}
|
|
2283
|
+
async function getActiveSession() {
|
|
2284
|
+
const storage = await loadSessions();
|
|
2285
|
+
if (!storage.activeSession || !storage.sessions[storage.activeSession]) {
|
|
624
2286
|
return null;
|
|
625
2287
|
}
|
|
2288
|
+
return {
|
|
2289
|
+
name: storage.activeSession,
|
|
2290
|
+
config: storage.sessions[storage.activeSession]
|
|
2291
|
+
};
|
|
626
2292
|
}
|
|
627
|
-
async function
|
|
628
|
-
const
|
|
629
|
-
return
|
|
2293
|
+
async function getSession(name) {
|
|
2294
|
+
const storage = await loadSessions();
|
|
2295
|
+
return storage.sessions[name] || null;
|
|
630
2296
|
}
|
|
631
|
-
async function
|
|
632
|
-
|
|
2297
|
+
async function setActiveSession(name) {
|
|
2298
|
+
const storage = await loadSessions();
|
|
2299
|
+
if (!storage.sessions[name]) {
|
|
2300
|
+
throw new Error(`Session '${name}' not found`);
|
|
2301
|
+
}
|
|
2302
|
+
storage.activeSession = name;
|
|
2303
|
+
storage.sessions[name].lastUsed = (/* @__PURE__ */ new Date()).toISOString();
|
|
2304
|
+
await saveSessions(storage);
|
|
633
2305
|
}
|
|
634
|
-
function
|
|
635
|
-
const
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
2306
|
+
async function listAllSessions() {
|
|
2307
|
+
const storage = await loadSessions();
|
|
2308
|
+
return Object.entries(storage.sessions).map(([name, config]) => ({
|
|
2309
|
+
name,
|
|
2310
|
+
config,
|
|
2311
|
+
isActive: name === storage.activeSession
|
|
2312
|
+
}));
|
|
2313
|
+
}
|
|
2314
|
+
async function updateSessionInfo(name, serverInfo, capabilities) {
|
|
2315
|
+
const storage = await loadSessions();
|
|
2316
|
+
if (storage.sessions[name]) {
|
|
2317
|
+
storage.sessions[name].serverInfo = serverInfo;
|
|
2318
|
+
storage.sessions[name].capabilities = capabilities;
|
|
2319
|
+
storage.sessions[name].lastUsed = (/* @__PURE__ */ new Date()).toISOString();
|
|
2320
|
+
await saveSessions(storage);
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
|
|
2324
|
+
// src/utils/format.ts
|
|
2325
|
+
function formatTable(data, columns) {
|
|
2326
|
+
if (data.length === 0) {
|
|
2327
|
+
return source_default.gray("No items found");
|
|
2328
|
+
}
|
|
2329
|
+
const widths = columns.map((col) => {
|
|
2330
|
+
const maxDataWidth = Math.max(
|
|
2331
|
+
...data.map((row) => String(row[col.key] || "").length)
|
|
2332
|
+
);
|
|
2333
|
+
const headerWidth = col.header.length;
|
|
2334
|
+
return col.width || Math.max(maxDataWidth, headerWidth, 10);
|
|
2335
|
+
});
|
|
2336
|
+
const createRow = (values, bold = false) => {
|
|
2337
|
+
const cells = values.map((val, i) => {
|
|
2338
|
+
const padded = val.padEnd(widths[i]);
|
|
2339
|
+
return bold ? source_default.bold(padded) : padded;
|
|
2340
|
+
});
|
|
2341
|
+
return `\u2502 ${cells.join(" \u2502 ")} \u2502`;
|
|
644
2342
|
};
|
|
2343
|
+
const separator = (char) => {
|
|
2344
|
+
const parts = widths.map((w) => char.repeat(w + 2));
|
|
2345
|
+
if (char === "\u2500") {
|
|
2346
|
+
return `\u251C${parts.join("\u253C")}\u2524`;
|
|
2347
|
+
}
|
|
2348
|
+
return `\u2514${parts.join("\u2534")}\u2518`;
|
|
2349
|
+
};
|
|
2350
|
+
const lines = [];
|
|
2351
|
+
lines.push(`\u250C${widths.map((w) => "\u2500".repeat(w + 2)).join("\u252C")}\u2510`);
|
|
2352
|
+
lines.push(
|
|
2353
|
+
createRow(
|
|
2354
|
+
columns.map((c) => c.header),
|
|
2355
|
+
true
|
|
2356
|
+
)
|
|
2357
|
+
);
|
|
2358
|
+
lines.push(separator("\u2500"));
|
|
2359
|
+
data.forEach((row) => {
|
|
2360
|
+
lines.push(createRow(columns.map((c) => String(row[c.key] || ""))));
|
|
2361
|
+
});
|
|
2362
|
+
lines.push(separator("\u2500"));
|
|
2363
|
+
return lines.join("\n");
|
|
645
2364
|
}
|
|
646
|
-
|
|
647
|
-
|
|
2365
|
+
function formatJson(data, pretty = true) {
|
|
2366
|
+
if (pretty) {
|
|
2367
|
+
return JSON.stringify(data, null, 2);
|
|
2368
|
+
}
|
|
2369
|
+
return JSON.stringify(data);
|
|
648
2370
|
}
|
|
649
|
-
|
|
650
|
-
|
|
2371
|
+
function formatToolCall(result) {
|
|
2372
|
+
const lines = [];
|
|
2373
|
+
if (result.isError) {
|
|
2374
|
+
lines.push(source_default.red("\u2717 Tool execution failed"));
|
|
2375
|
+
lines.push("");
|
|
2376
|
+
} else {
|
|
2377
|
+
lines.push(source_default.green("\u2713 Tool executed successfully"));
|
|
2378
|
+
lines.push("");
|
|
2379
|
+
}
|
|
2380
|
+
if (result.content && result.content.length > 0) {
|
|
2381
|
+
result.content.forEach((item, index) => {
|
|
2382
|
+
if (result.content.length > 1) {
|
|
2383
|
+
lines.push(source_default.bold(`Content ${index + 1}:`));
|
|
2384
|
+
}
|
|
2385
|
+
if (item.type === "text") {
|
|
2386
|
+
lines.push(item.text);
|
|
2387
|
+
} else if (item.type === "image") {
|
|
2388
|
+
lines.push(source_default.cyan(`[Image: ${item.mimeType || "unknown type"}]`));
|
|
2389
|
+
if (item.data) {
|
|
2390
|
+
lines.push(source_default.gray(`Data: ${item.data.substring(0, 50)}...`));
|
|
2391
|
+
}
|
|
2392
|
+
} else if (item.type === "resource") {
|
|
2393
|
+
lines.push(source_default.cyan(`[Resource]`));
|
|
2394
|
+
if (item.resource?.uri) {
|
|
2395
|
+
lines.push(source_default.gray(`URI: ${item.resource.uri}`));
|
|
2396
|
+
}
|
|
2397
|
+
if (item.resource && "text" in item.resource && item.resource.text) {
|
|
2398
|
+
lines.push(item.resource.text);
|
|
2399
|
+
}
|
|
2400
|
+
} else {
|
|
2401
|
+
lines.push(source_default.gray(`[Unknown content type: ${item.type}]`));
|
|
2402
|
+
}
|
|
2403
|
+
if (index < result.content.length - 1) {
|
|
2404
|
+
lines.push("");
|
|
2405
|
+
}
|
|
2406
|
+
});
|
|
2407
|
+
}
|
|
2408
|
+
return lines.join("\n");
|
|
651
2409
|
}
|
|
652
|
-
|
|
653
|
-
|
|
2410
|
+
function formatResourceContent(content) {
|
|
2411
|
+
if (!content || !content.contents) {
|
|
2412
|
+
return source_default.gray("No content");
|
|
2413
|
+
}
|
|
2414
|
+
const lines = [];
|
|
2415
|
+
content.contents.forEach((item, index) => {
|
|
2416
|
+
if (content.contents.length > 1) {
|
|
2417
|
+
lines.push(source_default.bold(`Content ${index + 1}:`));
|
|
2418
|
+
}
|
|
2419
|
+
if (item.uri) {
|
|
2420
|
+
lines.push(source_default.gray(`URI: ${item.uri}`));
|
|
2421
|
+
}
|
|
2422
|
+
if (item.mimeType) {
|
|
2423
|
+
lines.push(source_default.gray(`Type: ${item.mimeType}`));
|
|
2424
|
+
}
|
|
2425
|
+
if ("text" in item && item.text) {
|
|
2426
|
+
lines.push("");
|
|
2427
|
+
lines.push(item.text);
|
|
2428
|
+
} else if ("blob" in item && item.blob) {
|
|
2429
|
+
lines.push("");
|
|
2430
|
+
lines.push(source_default.cyan(`[Binary data: ${item.blob.length} bytes]`));
|
|
2431
|
+
}
|
|
2432
|
+
if (index < content.contents.length - 1) {
|
|
2433
|
+
lines.push("");
|
|
2434
|
+
lines.push(source_default.gray("\u2500".repeat(50)));
|
|
2435
|
+
lines.push("");
|
|
2436
|
+
}
|
|
2437
|
+
});
|
|
2438
|
+
return lines.join("\n");
|
|
654
2439
|
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
return { isGitRepo: false };
|
|
2440
|
+
function formatSchema(schema, indent = 0) {
|
|
2441
|
+
if (!schema) {
|
|
2442
|
+
return source_default.gray("No schema");
|
|
659
2443
|
}
|
|
660
|
-
const
|
|
661
|
-
const
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
2444
|
+
const lines = [];
|
|
2445
|
+
const pad = " ".repeat(indent);
|
|
2446
|
+
if (schema.type === "object" && schema.properties) {
|
|
2447
|
+
Object.entries(schema.properties).forEach(([key, value]) => {
|
|
2448
|
+
const required = schema.required?.includes(key);
|
|
2449
|
+
const type = value.type || "any";
|
|
2450
|
+
const desc = value.description || "";
|
|
2451
|
+
const keyStr = required ? source_default.bold(key) : key;
|
|
2452
|
+
const typeStr = source_default.cyan(`(${type})`);
|
|
2453
|
+
const requiredStr = required ? source_default.red(" *required") : "";
|
|
2454
|
+
lines.push(`${pad}${keyStr} ${typeStr}${requiredStr}`);
|
|
2455
|
+
if (desc) {
|
|
2456
|
+
lines.push(`${pad} ${source_default.gray(desc)}`);
|
|
2457
|
+
}
|
|
2458
|
+
if (value.type === "object" && value.properties) {
|
|
2459
|
+
lines.push(formatSchema(value, indent + 1));
|
|
2460
|
+
}
|
|
2461
|
+
if (value.type === "array" && value.items) {
|
|
2462
|
+
lines.push(`${pad} ${source_default.gray("Items:")}`);
|
|
2463
|
+
if (value.items.type === "object") {
|
|
2464
|
+
lines.push(formatSchema(value.items, indent + 2));
|
|
2465
|
+
} else {
|
|
2466
|
+
lines.push(
|
|
2467
|
+
`${pad} ${source_default.cyan(`(${value.items.type || "any"})`)}`
|
|
2468
|
+
);
|
|
2469
|
+
}
|
|
2470
|
+
}
|
|
2471
|
+
});
|
|
2472
|
+
} else {
|
|
2473
|
+
lines.push(`${pad}${source_default.cyan(`Type: ${schema.type || "any"}`)}`);
|
|
2474
|
+
if (schema.description) {
|
|
2475
|
+
lines.push(`${pad}${source_default.gray(schema.description)}`);
|
|
671
2476
|
}
|
|
672
2477
|
}
|
|
673
|
-
return
|
|
674
|
-
isGitRepo: true,
|
|
675
|
-
remoteUrl: remoteUrl || void 0,
|
|
676
|
-
owner,
|
|
677
|
-
repo,
|
|
678
|
-
branch: branch || void 0,
|
|
679
|
-
commitSha: commitSha || void 0,
|
|
680
|
-
commitMessage: commitMessage || void 0
|
|
681
|
-
};
|
|
2478
|
+
return lines.join("\n");
|
|
682
2479
|
}
|
|
683
|
-
function
|
|
684
|
-
|
|
2480
|
+
function formatError(error) {
|
|
2481
|
+
const message = typeof error === "string" ? error : error.message;
|
|
2482
|
+
return source_default.red(`\u2717 Error: ${message}`);
|
|
685
2483
|
}
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
2484
|
+
function formatSuccess(message) {
|
|
2485
|
+
return source_default.green(`\u2713 ${message}`);
|
|
2486
|
+
}
|
|
2487
|
+
function formatInfo(message) {
|
|
2488
|
+
return source_default.cyan(message);
|
|
2489
|
+
}
|
|
2490
|
+
function formatWarning(message) {
|
|
2491
|
+
return source_default.yellow(`\u26A0 ${message}`);
|
|
2492
|
+
}
|
|
2493
|
+
function formatHeader(text) {
|
|
2494
|
+
return source_default.bold.white(text);
|
|
2495
|
+
}
|
|
2496
|
+
function formatKeyValue(pairs) {
|
|
2497
|
+
const maxKeyLength = Math.max(...Object.keys(pairs).map((k) => k.length), 0);
|
|
2498
|
+
return Object.entries(pairs).map(([key, value]) => {
|
|
2499
|
+
const paddedKey = key.padEnd(maxKeyLength);
|
|
2500
|
+
return ` ${source_default.gray(paddedKey)}: ${value}`;
|
|
2501
|
+
}).join("\n");
|
|
2502
|
+
}
|
|
2503
|
+
function formatPromptMessages(messages) {
|
|
2504
|
+
if (!messages || messages.length === 0) {
|
|
2505
|
+
return source_default.gray("No messages");
|
|
700
2506
|
}
|
|
2507
|
+
const lines = [];
|
|
2508
|
+
messages.forEach((msg, index) => {
|
|
2509
|
+
const role = msg.role || "unknown";
|
|
2510
|
+
const roleStr = role === "user" ? source_default.blue("[User]") : role === "assistant" ? source_default.green("[Assistant]") : source_default.gray(`[${role}]`);
|
|
2511
|
+
lines.push(`${roleStr}`);
|
|
2512
|
+
if (msg.content) {
|
|
2513
|
+
if (typeof msg.content === "string") {
|
|
2514
|
+
lines.push(msg.content);
|
|
2515
|
+
} else if (msg.content.type === "text") {
|
|
2516
|
+
lines.push(msg.content.text);
|
|
2517
|
+
} else if (msg.content.type === "image") {
|
|
2518
|
+
lines.push(source_default.cyan(`[Image: ${msg.content.mimeType}]`));
|
|
2519
|
+
} else if (msg.content.type === "resource") {
|
|
2520
|
+
lines.push(source_default.cyan(`[Resource: ${msg.content.resource?.uri}]`));
|
|
2521
|
+
if (msg.content.resource?.text) {
|
|
2522
|
+
lines.push(msg.content.resource.text);
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
if (index < messages.length - 1) {
|
|
2527
|
+
lines.push("");
|
|
2528
|
+
}
|
|
2529
|
+
});
|
|
2530
|
+
return lines.join("\n");
|
|
701
2531
|
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
2532
|
+
|
|
2533
|
+
// src/commands/client.ts
|
|
2534
|
+
var activeSessions = /* @__PURE__ */ new Map();
|
|
2535
|
+
async function getOrRestoreSession(sessionName) {
|
|
2536
|
+
if (!sessionName) {
|
|
2537
|
+
const active = await getActiveSession();
|
|
2538
|
+
if (!active) {
|
|
2539
|
+
console.error(
|
|
2540
|
+
formatError("No active session. Connect to a server first.")
|
|
2541
|
+
);
|
|
2542
|
+
console.error(
|
|
2543
|
+
formatInfo("Use: npx mcp-use client connect <url> --name <name>")
|
|
2544
|
+
);
|
|
2545
|
+
return null;
|
|
709
2546
|
}
|
|
710
|
-
|
|
2547
|
+
sessionName = active.name;
|
|
2548
|
+
}
|
|
2549
|
+
if (activeSessions.has(sessionName)) {
|
|
2550
|
+
const { session } = activeSessions.get(sessionName);
|
|
2551
|
+
return { name: sessionName, session };
|
|
2552
|
+
}
|
|
2553
|
+
const config = await getSession(sessionName);
|
|
2554
|
+
if (!config) {
|
|
2555
|
+
console.error(formatError(`Session '${sessionName}' not found`));
|
|
2556
|
+
return null;
|
|
711
2557
|
}
|
|
712
|
-
return import_node_path2.default.basename(cwd);
|
|
713
|
-
}
|
|
714
|
-
async function detectBuildCommand(cwd = process.cwd()) {
|
|
715
2558
|
try {
|
|
716
|
-
const
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
2559
|
+
const client = new MCPClient();
|
|
2560
|
+
if (config.type === "http") {
|
|
2561
|
+
client.addServer(sessionName, {
|
|
2562
|
+
url: config.url,
|
|
2563
|
+
headers: config.authToken ? { Authorization: `Bearer ${config.authToken}` } : void 0
|
|
2564
|
+
});
|
|
2565
|
+
} else if (config.type === "stdio") {
|
|
2566
|
+
client.addServer(sessionName, {
|
|
2567
|
+
command: config.command,
|
|
2568
|
+
args: config.args || [],
|
|
2569
|
+
env: config.env
|
|
2570
|
+
});
|
|
2571
|
+
} else {
|
|
2572
|
+
console.error(formatError(`Unknown session type: ${config.type}`));
|
|
2573
|
+
return null;
|
|
721
2574
|
}
|
|
722
|
-
|
|
2575
|
+
const session = await client.createSession(sessionName);
|
|
2576
|
+
activeSessions.set(sessionName, { client, session });
|
|
2577
|
+
console.error(formatInfo(`Reconnected to session '${sessionName}'`));
|
|
2578
|
+
return { name: sessionName, session };
|
|
2579
|
+
} catch (error) {
|
|
2580
|
+
console.error(formatError(`Failed to restore session: ${error.message}`));
|
|
2581
|
+
return null;
|
|
723
2582
|
}
|
|
724
|
-
return void 0;
|
|
725
2583
|
}
|
|
726
|
-
async function
|
|
2584
|
+
async function connectCommand(urlOrCommand, options) {
|
|
727
2585
|
try {
|
|
728
|
-
const
|
|
729
|
-
const
|
|
730
|
-
|
|
731
|
-
if (
|
|
732
|
-
|
|
2586
|
+
const sessionName = options.name || `session-${Date.now()}`;
|
|
2587
|
+
const client = new MCPClient();
|
|
2588
|
+
let session;
|
|
2589
|
+
if (options.stdio) {
|
|
2590
|
+
const parts = urlOrCommand.split(" ");
|
|
2591
|
+
const command = parts[0];
|
|
2592
|
+
const args = parts.slice(1);
|
|
2593
|
+
console.error(
|
|
2594
|
+
formatInfo(`Connecting to stdio server: ${command} ${args.join(" ")}`)
|
|
2595
|
+
);
|
|
2596
|
+
client.addServer(sessionName, {
|
|
2597
|
+
command,
|
|
2598
|
+
args
|
|
2599
|
+
});
|
|
2600
|
+
session = await client.createSession(sessionName);
|
|
2601
|
+
await saveSession(sessionName, {
|
|
2602
|
+
type: "stdio",
|
|
2603
|
+
command,
|
|
2604
|
+
args,
|
|
2605
|
+
lastUsed: (/* @__PURE__ */ new Date()).toISOString()
|
|
2606
|
+
});
|
|
2607
|
+
} else {
|
|
2608
|
+
console.error(formatInfo(`Connecting to ${urlOrCommand}...`));
|
|
2609
|
+
client.addServer(sessionName, {
|
|
2610
|
+
url: urlOrCommand,
|
|
2611
|
+
headers: options.auth ? { Authorization: `Bearer ${options.auth}` } : void 0
|
|
2612
|
+
});
|
|
2613
|
+
session = await client.createSession(sessionName);
|
|
2614
|
+
await saveSession(sessionName, {
|
|
2615
|
+
type: "http",
|
|
2616
|
+
url: urlOrCommand,
|
|
2617
|
+
authToken: options.auth,
|
|
2618
|
+
lastUsed: (/* @__PURE__ */ new Date()).toISOString()
|
|
2619
|
+
});
|
|
733
2620
|
}
|
|
734
|
-
|
|
735
|
-
|
|
2621
|
+
activeSessions.set(sessionName, { client, session });
|
|
2622
|
+
const serverInfo = session.serverInfo;
|
|
2623
|
+
const capabilities = session.serverCapabilities;
|
|
2624
|
+
if (serverInfo) {
|
|
2625
|
+
await updateSessionInfo(sessionName, serverInfo, capabilities);
|
|
736
2626
|
}
|
|
737
|
-
|
|
2627
|
+
console.log(formatSuccess(`Connected to ${sessionName}`));
|
|
2628
|
+
if (serverInfo) {
|
|
2629
|
+
console.log("");
|
|
2630
|
+
console.log(formatHeader("Server Information:"));
|
|
2631
|
+
console.log(
|
|
2632
|
+
formatKeyValue({
|
|
2633
|
+
Name: serverInfo.name,
|
|
2634
|
+
Version: serverInfo.version || "unknown"
|
|
2635
|
+
})
|
|
2636
|
+
);
|
|
2637
|
+
}
|
|
2638
|
+
if (capabilities) {
|
|
2639
|
+
console.log("");
|
|
2640
|
+
console.log(formatHeader("Capabilities:"));
|
|
2641
|
+
const caps = Object.keys(capabilities).join(", ");
|
|
2642
|
+
console.log(` ${caps || "none"}`);
|
|
2643
|
+
}
|
|
2644
|
+
const tools = session.tools;
|
|
2645
|
+
console.log("");
|
|
2646
|
+
console.log(
|
|
2647
|
+
formatInfo(
|
|
2648
|
+
`Available: ${tools.length} tool${tools.length !== 1 ? "s" : ""}`
|
|
2649
|
+
)
|
|
2650
|
+
);
|
|
2651
|
+
} catch (error) {
|
|
2652
|
+
console.error(formatError(`Connection failed: ${error.message}`));
|
|
2653
|
+
process.exit(1);
|
|
738
2654
|
}
|
|
739
|
-
return void 0;
|
|
740
2655
|
}
|
|
741
|
-
async function
|
|
2656
|
+
async function disconnectCommand(sessionName, options) {
|
|
742
2657
|
try {
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
} catch {
|
|
749
|
-
continue;
|
|
2658
|
+
if (options?.all) {
|
|
2659
|
+
for (const [name, { client }] of activeSessions.entries()) {
|
|
2660
|
+
await client.closeAllSessions();
|
|
2661
|
+
activeSessions.delete(name);
|
|
2662
|
+
console.log(formatSuccess(`Disconnected from ${name}`));
|
|
750
2663
|
}
|
|
2664
|
+
return;
|
|
751
2665
|
}
|
|
752
|
-
|
|
753
|
-
await
|
|
754
|
-
|
|
755
|
-
|
|
2666
|
+
if (!sessionName) {
|
|
2667
|
+
const active = await getActiveSession();
|
|
2668
|
+
if (!active) {
|
|
2669
|
+
console.error(formatError("No active session to disconnect"));
|
|
2670
|
+
return;
|
|
2671
|
+
}
|
|
2672
|
+
sessionName = active.name;
|
|
756
2673
|
}
|
|
757
|
-
|
|
2674
|
+
const sessionData = activeSessions.get(sessionName);
|
|
2675
|
+
if (sessionData) {
|
|
2676
|
+
await sessionData.client.closeAllSessions();
|
|
2677
|
+
activeSessions.delete(sessionName);
|
|
2678
|
+
console.log(formatSuccess(`Disconnected from ${sessionName}`));
|
|
2679
|
+
} else {
|
|
2680
|
+
console.log(formatInfo(`Session '${sessionName}' is not connected`));
|
|
2681
|
+
}
|
|
2682
|
+
} catch (error) {
|
|
2683
|
+
console.error(formatError(`Failed to disconnect: ${error.message}`));
|
|
2684
|
+
process.exit(1);
|
|
758
2685
|
}
|
|
759
|
-
return "node";
|
|
760
|
-
}
|
|
761
|
-
async function prompt(question, defaultValue = "n") {
|
|
762
|
-
const readline = await import("readline");
|
|
763
|
-
const rl = readline.createInterface({
|
|
764
|
-
input: process.stdin,
|
|
765
|
-
output: process.stdout
|
|
766
|
-
});
|
|
767
|
-
const defaultIndicator = defaultValue === "y" ? "Y/n" : "y/N";
|
|
768
|
-
const questionWithDefault = question.replace(
|
|
769
|
-
/(\(y\/n\):)/,
|
|
770
|
-
`(${defaultIndicator}):`
|
|
771
|
-
);
|
|
772
|
-
return new Promise((resolve) => {
|
|
773
|
-
rl.question(questionWithDefault, (answer) => {
|
|
774
|
-
rl.close();
|
|
775
|
-
const trimmedAnswer = answer.trim().toLowerCase();
|
|
776
|
-
if (trimmedAnswer === "") {
|
|
777
|
-
resolve(defaultValue === "y");
|
|
778
|
-
} else {
|
|
779
|
-
resolve(trimmedAnswer === "y" || trimmedAnswer === "yes");
|
|
780
|
-
}
|
|
781
|
-
});
|
|
782
|
-
});
|
|
783
2686
|
}
|
|
784
|
-
async function
|
|
785
|
-
const tmpDir = import_node_os2.default.tmpdir();
|
|
786
|
-
const tarballPath = import_node_path2.default.join(tmpDir, `mcp-deploy-${Date.now()}.tar.gz`);
|
|
787
|
-
const excludePatterns = [
|
|
788
|
-
"node_modules",
|
|
789
|
-
".git",
|
|
790
|
-
"dist",
|
|
791
|
-
"build",
|
|
792
|
-
".next",
|
|
793
|
-
".venv",
|
|
794
|
-
"__pycache__",
|
|
795
|
-
"*.pyc",
|
|
796
|
-
".DS_Store",
|
|
797
|
-
"._*",
|
|
798
|
-
// macOS resource fork files
|
|
799
|
-
".mcp-use",
|
|
800
|
-
// Build artifacts directory
|
|
801
|
-
".env",
|
|
802
|
-
".env.local",
|
|
803
|
-
"*.log"
|
|
804
|
-
];
|
|
805
|
-
const excludeFlags = excludePatterns.map((pattern) => `--exclude=${pattern}`).join(" ");
|
|
806
|
-
const command = `tar ${excludeFlags} -czf "${tarballPath}" -C "${cwd}" . 2>&1 || true`;
|
|
2687
|
+
async function listSessionsCommand() {
|
|
807
2688
|
try {
|
|
808
|
-
await
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
2689
|
+
const sessions = await listAllSessions();
|
|
2690
|
+
if (sessions.length === 0) {
|
|
2691
|
+
console.log(formatInfo("No saved sessions"));
|
|
2692
|
+
console.log(
|
|
2693
|
+
formatInfo("Connect to a server with: npx mcp-use client connect <url>")
|
|
2694
|
+
);
|
|
2695
|
+
return;
|
|
2696
|
+
}
|
|
2697
|
+
console.log(formatHeader("Saved Sessions:"));
|
|
2698
|
+
console.log("");
|
|
2699
|
+
const tableData = sessions.map((s) => ({
|
|
2700
|
+
name: s.isActive ? source_default.green.bold(`${s.name} *`) : s.name,
|
|
2701
|
+
type: s.config.type,
|
|
2702
|
+
target: s.config.type === "http" ? s.config.url || "" : `${s.config.command} ${(s.config.args || []).join(" ")}`,
|
|
2703
|
+
server: s.config.serverInfo?.name || "unknown",
|
|
2704
|
+
status: activeSessions.has(s.name) ? source_default.green("connected") : source_default.gray("disconnected")
|
|
2705
|
+
}));
|
|
2706
|
+
console.log(
|
|
2707
|
+
formatTable(tableData, [
|
|
2708
|
+
{ key: "name", header: "Name" },
|
|
2709
|
+
{ key: "type", header: "Type" },
|
|
2710
|
+
{ key: "target", header: "Target", width: 40 },
|
|
2711
|
+
{ key: "server", header: "Server" },
|
|
2712
|
+
{ key: "status", header: "Status" }
|
|
2713
|
+
])
|
|
813
2714
|
);
|
|
2715
|
+
console.log("");
|
|
2716
|
+
console.log(source_default.gray("* = active session"));
|
|
2717
|
+
} catch (error) {
|
|
2718
|
+
console.error(formatError(`Failed to list sessions: ${error.message}`));
|
|
2719
|
+
process.exit(1);
|
|
814
2720
|
}
|
|
815
2721
|
}
|
|
816
|
-
function
|
|
817
|
-
if (bytes === 0) return "0 B";
|
|
818
|
-
const k = 1024;
|
|
819
|
-
const sizes = ["B", "KB", "MB", "GB"];
|
|
820
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
821
|
-
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
822
|
-
}
|
|
823
|
-
async function displayDeploymentProgress(api, deployment) {
|
|
824
|
-
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
825
|
-
let frameIndex = 0;
|
|
826
|
-
let spinnerInterval = null;
|
|
827
|
-
let lastStep = "";
|
|
828
|
-
const startSpinner = (message) => {
|
|
829
|
-
if (spinnerInterval) {
|
|
830
|
-
clearInterval(spinnerInterval);
|
|
831
|
-
}
|
|
832
|
-
process.stdout.write("\r\x1B[K");
|
|
833
|
-
spinnerInterval = setInterval(() => {
|
|
834
|
-
const frame = frames[frameIndex];
|
|
835
|
-
frameIndex = (frameIndex + 1) % frames.length;
|
|
836
|
-
process.stdout.write(
|
|
837
|
-
"\r" + import_chalk2.default.cyan(frame) + " " + import_chalk2.default.gray(message)
|
|
838
|
-
);
|
|
839
|
-
}, 80);
|
|
840
|
-
};
|
|
841
|
-
const stopSpinner = () => {
|
|
842
|
-
if (spinnerInterval) {
|
|
843
|
-
clearInterval(spinnerInterval);
|
|
844
|
-
spinnerInterval = null;
|
|
845
|
-
process.stdout.write("\r\x1B[K");
|
|
846
|
-
}
|
|
847
|
-
};
|
|
848
|
-
console.log();
|
|
849
|
-
startSpinner("Deploying...");
|
|
2722
|
+
async function switchSessionCommand(name) {
|
|
850
2723
|
try {
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
const logData = JSON.parse(log);
|
|
854
|
-
if (logData.step && logData.step !== lastStep) {
|
|
855
|
-
lastStep = logData.step;
|
|
856
|
-
const stepMessages = {
|
|
857
|
-
clone: "Preparing source code...",
|
|
858
|
-
analyze: "Analyzing project...",
|
|
859
|
-
build: "Building container image...",
|
|
860
|
-
deploy: "Deploying to cloud..."
|
|
861
|
-
};
|
|
862
|
-
const message = stepMessages[logData.step] || "Deploying...";
|
|
863
|
-
startSpinner(message);
|
|
864
|
-
}
|
|
865
|
-
if (logData.line) {
|
|
866
|
-
stopSpinner();
|
|
867
|
-
const levelColor = logData.level === "error" ? import_chalk2.default.red : logData.level === "warn" ? import_chalk2.default.yellow : import_chalk2.default.gray;
|
|
868
|
-
const stepPrefix = logData.step ? import_chalk2.default.cyan(`[${logData.step}]`) + " " : "";
|
|
869
|
-
console.log(stepPrefix + levelColor(logData.line));
|
|
870
|
-
}
|
|
871
|
-
} catch {
|
|
872
|
-
}
|
|
873
|
-
}
|
|
2724
|
+
await setActiveSession(name);
|
|
2725
|
+
console.log(formatSuccess(`Switched to session '${name}'`));
|
|
874
2726
|
} catch (error) {
|
|
875
|
-
|
|
2727
|
+
console.error(formatError(`Failed to switch session: ${error.message}`));
|
|
2728
|
+
process.exit(1);
|
|
876
2729
|
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
const
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
const newLogs = finalDeployment.buildLogs.substring(
|
|
888
|
-
lastDisplayedLogLength
|
|
889
|
-
);
|
|
890
|
-
const logLines = newLogs.split("\n").filter((l) => l.trim());
|
|
891
|
-
for (const line of logLines) {
|
|
892
|
-
try {
|
|
893
|
-
const logData = JSON.parse(line);
|
|
894
|
-
if (logData.line) {
|
|
895
|
-
stopSpinner();
|
|
896
|
-
const levelColor = logData.level === "error" ? import_chalk2.default.red : logData.level === "warn" ? import_chalk2.default.yellow : import_chalk2.default.gray;
|
|
897
|
-
const stepPrefix = logData.step ? import_chalk2.default.cyan(`[${logData.step}]`) + " " : "";
|
|
898
|
-
console.log(stepPrefix + levelColor(logData.line));
|
|
899
|
-
}
|
|
900
|
-
} catch {
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
lastDisplayedLogLength = finalDeployment.buildLogs.length;
|
|
2730
|
+
}
|
|
2731
|
+
async function listToolsCommand(options) {
|
|
2732
|
+
try {
|
|
2733
|
+
const result = await getOrRestoreSession(options.session || null);
|
|
2734
|
+
if (!result) return;
|
|
2735
|
+
const { session } = result;
|
|
2736
|
+
const tools = await session.listTools();
|
|
2737
|
+
if (options.json) {
|
|
2738
|
+
console.log(formatJson(tools));
|
|
2739
|
+
return;
|
|
904
2740
|
}
|
|
905
|
-
if (
|
|
906
|
-
|
|
907
|
-
const inspectorUrl = `https://inspector.mcp-use.com/inspector?autoConnect=${encodeURIComponent(mcpUrl)}`;
|
|
908
|
-
console.log(import_chalk2.default.green.bold("\u2713 Deployment successful!\n"));
|
|
909
|
-
console.log(import_chalk2.default.white("\u{1F310} MCP Server URL:"));
|
|
910
|
-
console.log(import_chalk2.default.cyan.bold(` ${mcpUrl}
|
|
911
|
-
`));
|
|
912
|
-
console.log(import_chalk2.default.white("\u{1F50D} Inspector URL:"));
|
|
913
|
-
console.log(import_chalk2.default.cyan.bold(` ${inspectorUrl}
|
|
914
|
-
`));
|
|
915
|
-
if (finalDeployment.customDomain) {
|
|
916
|
-
const customMcpUrl = `https://${finalDeployment.customDomain}/mcp`;
|
|
917
|
-
const customInspectorUrl = `https://inspector.mcp-use.com/inspect?autoConnect=${encodeURIComponent(customMcpUrl)}`;
|
|
918
|
-
console.log(import_chalk2.default.white("\u{1F517} Custom Domain:"));
|
|
919
|
-
console.log(import_chalk2.default.cyan.bold(` ${customMcpUrl}
|
|
920
|
-
`));
|
|
921
|
-
console.log(import_chalk2.default.white("\u{1F50D} Custom Inspector:"));
|
|
922
|
-
console.log(import_chalk2.default.cyan.bold(` ${customInspectorUrl}
|
|
923
|
-
`));
|
|
924
|
-
}
|
|
925
|
-
console.log(
|
|
926
|
-
import_chalk2.default.gray("Deployment ID: ") + import_chalk2.default.white(finalDeployment.id)
|
|
927
|
-
);
|
|
2741
|
+
if (tools.length === 0) {
|
|
2742
|
+
console.log(formatInfo("No tools available"));
|
|
928
2743
|
return;
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
console.log(
|
|
959
|
-
import_chalk2.default.yellow("\u26A0\uFE0F Deployment status: ") + finalDeployment.status
|
|
960
|
-
);
|
|
2744
|
+
}
|
|
2745
|
+
console.log(formatHeader(`Available Tools (${tools.length}):`));
|
|
2746
|
+
console.log("");
|
|
2747
|
+
const tableData = tools.map((tool) => ({
|
|
2748
|
+
name: source_default.bold(tool.name),
|
|
2749
|
+
description: tool.description || source_default.gray("No description")
|
|
2750
|
+
}));
|
|
2751
|
+
console.log(
|
|
2752
|
+
formatTable(tableData, [
|
|
2753
|
+
{ key: "name", header: "Tool", width: 25 },
|
|
2754
|
+
{ key: "description", header: "Description", width: 50 }
|
|
2755
|
+
])
|
|
2756
|
+
);
|
|
2757
|
+
} catch (error) {
|
|
2758
|
+
console.error(formatError(`Failed to list tools: ${error.message}`));
|
|
2759
|
+
process.exit(1);
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
async function describeToolCommand(toolName, options) {
|
|
2763
|
+
try {
|
|
2764
|
+
const result = await getOrRestoreSession(options.session || null);
|
|
2765
|
+
if (!result) return;
|
|
2766
|
+
const { session } = result;
|
|
2767
|
+
const tools = session.tools;
|
|
2768
|
+
const tool = tools.find((t) => t.name === toolName);
|
|
2769
|
+
if (!tool) {
|
|
2770
|
+
console.error(formatError(`Tool '${toolName}' not found`));
|
|
2771
|
+
console.log("");
|
|
2772
|
+
console.log(formatInfo("Available tools:"));
|
|
2773
|
+
tools.forEach((t) => console.log(` \u2022 ${t.name}`));
|
|
961
2774
|
return;
|
|
962
2775
|
}
|
|
2776
|
+
console.log(formatHeader(`Tool: ${tool.name}`));
|
|
2777
|
+
console.log("");
|
|
2778
|
+
if (tool.description) {
|
|
2779
|
+
console.log(tool.description);
|
|
2780
|
+
console.log("");
|
|
2781
|
+
}
|
|
2782
|
+
if (tool.inputSchema) {
|
|
2783
|
+
console.log(formatHeader("Input Schema:"));
|
|
2784
|
+
console.log(formatSchema(tool.inputSchema));
|
|
2785
|
+
}
|
|
2786
|
+
} catch (error) {
|
|
2787
|
+
console.error(formatError(`Failed to describe tool: ${error.message}`));
|
|
2788
|
+
process.exit(1);
|
|
963
2789
|
}
|
|
964
|
-
stopSpinner();
|
|
965
|
-
console.log(import_chalk2.default.yellow("\u26A0\uFE0F Deployment is taking longer than expected."));
|
|
966
|
-
console.log(
|
|
967
|
-
import_chalk2.default.gray("Check status with: ") + import_chalk2.default.white(`mcp-use status ${deployment.id}`)
|
|
968
|
-
);
|
|
969
2790
|
}
|
|
970
|
-
async function
|
|
2791
|
+
async function callToolCommand(toolName, argsJson, options) {
|
|
971
2792
|
try {
|
|
972
|
-
const
|
|
973
|
-
if (!
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
if (!isMcp) {
|
|
983
|
-
console.log(
|
|
984
|
-
import_chalk2.default.yellow(
|
|
985
|
-
"\u26A0\uFE0F This doesn't appear to be an MCP server project (no mcp-use or @modelcontextprotocol/sdk dependency found)."
|
|
986
|
-
)
|
|
987
|
-
);
|
|
988
|
-
const shouldContinue = await prompt(
|
|
989
|
-
import_chalk2.default.white("Continue anyway? (y/n): ")
|
|
990
|
-
);
|
|
991
|
-
if (!shouldContinue) {
|
|
992
|
-
console.log(import_chalk2.default.gray("Deployment cancelled."));
|
|
993
|
-
process.exit(0);
|
|
2793
|
+
const result = await getOrRestoreSession(options?.session || null);
|
|
2794
|
+
if (!result) return;
|
|
2795
|
+
const { session } = result;
|
|
2796
|
+
let args = {};
|
|
2797
|
+
if (argsJson) {
|
|
2798
|
+
try {
|
|
2799
|
+
args = JSON.parse(argsJson);
|
|
2800
|
+
} catch (error) {
|
|
2801
|
+
console.error(formatError("Invalid JSON arguments"));
|
|
2802
|
+
return;
|
|
994
2803
|
}
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
"\u2717 Could not parse GitHub repository information from remote URL."
|
|
2804
|
+
} else {
|
|
2805
|
+
const tools = session.tools;
|
|
2806
|
+
const tool = tools.find((t) => t.name === toolName);
|
|
2807
|
+
if (tool?.inputSchema?.required && tool.inputSchema.required.length > 0) {
|
|
2808
|
+
console.error(
|
|
2809
|
+
formatError(
|
|
2810
|
+
"This tool requires arguments. Provide them as a JSON string."
|
|
1003
2811
|
)
|
|
1004
2812
|
);
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
console.log(import_chalk2.default.white("GitHub repository detected:"));
|
|
1008
|
-
console.log(
|
|
1009
|
-
import_chalk2.default.gray(` Repository: `) + import_chalk2.default.cyan(`${gitInfo.owner}/${gitInfo.repo}`)
|
|
1010
|
-
);
|
|
1011
|
-
console.log(
|
|
1012
|
-
import_chalk2.default.gray(` Branch: `) + import_chalk2.default.cyan(gitInfo.branch || "main")
|
|
1013
|
-
);
|
|
1014
|
-
if (gitInfo.commitSha) {
|
|
1015
|
-
console.log(
|
|
1016
|
-
import_chalk2.default.gray(` Commit: `) + import_chalk2.default.gray(gitInfo.commitSha.substring(0, 7))
|
|
1017
|
-
);
|
|
1018
|
-
}
|
|
1019
|
-
if (gitInfo.commitMessage) {
|
|
2813
|
+
console.log("");
|
|
2814
|
+
console.log(formatInfo("Example:"));
|
|
1020
2815
|
console.log(
|
|
1021
|
-
|
|
2816
|
+
` npx mcp-use client tools call ${toolName} '{"param": "value"}'`
|
|
1022
2817
|
);
|
|
2818
|
+
console.log("");
|
|
2819
|
+
console.log(formatInfo("Tool schema:"));
|
|
2820
|
+
console.log(formatSchema(tool.inputSchema));
|
|
2821
|
+
return;
|
|
1023
2822
|
}
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
2823
|
+
}
|
|
2824
|
+
console.error(formatInfo(`Calling tool '${toolName}'...`));
|
|
2825
|
+
const callResult = await session.callTool(toolName, args, {
|
|
2826
|
+
timeout: options?.timeout
|
|
2827
|
+
});
|
|
2828
|
+
if (options?.json) {
|
|
2829
|
+
console.log(formatJson(callResult));
|
|
2830
|
+
} else {
|
|
2831
|
+
console.log(formatToolCall(callResult));
|
|
2832
|
+
}
|
|
2833
|
+
} catch (error) {
|
|
2834
|
+
console.error(formatError(`Failed to call tool: ${error.message}`));
|
|
2835
|
+
process.exit(1);
|
|
2836
|
+
}
|
|
2837
|
+
}
|
|
2838
|
+
async function listResourcesCommand(options) {
|
|
2839
|
+
try {
|
|
2840
|
+
const result = await getOrRestoreSession(options.session || null);
|
|
2841
|
+
if (!result) return;
|
|
2842
|
+
const { session } = result;
|
|
2843
|
+
const resourcesResult = await session.listAllResources();
|
|
2844
|
+
const resources = resourcesResult.resources;
|
|
2845
|
+
if (options.json) {
|
|
2846
|
+
console.log(formatJson(resources));
|
|
2847
|
+
return;
|
|
2848
|
+
}
|
|
2849
|
+
if (resources.length === 0) {
|
|
2850
|
+
console.log(formatInfo("No resources available"));
|
|
2851
|
+
return;
|
|
2852
|
+
}
|
|
2853
|
+
console.log(formatHeader(`Available Resources (${resources.length}):`));
|
|
2854
|
+
console.log("");
|
|
2855
|
+
const tableData = resources.map((resource) => ({
|
|
2856
|
+
uri: resource.uri,
|
|
2857
|
+
name: resource.name || source_default.gray("(no name)"),
|
|
2858
|
+
type: resource.mimeType || source_default.gray("unknown")
|
|
2859
|
+
}));
|
|
2860
|
+
console.log(
|
|
2861
|
+
formatTable(tableData, [
|
|
2862
|
+
{ key: "uri", header: "URI", width: 40 },
|
|
2863
|
+
{ key: "name", header: "Name", width: 20 },
|
|
2864
|
+
{ key: "type", header: "Type", width: 15 }
|
|
2865
|
+
])
|
|
2866
|
+
);
|
|
2867
|
+
} catch (error) {
|
|
2868
|
+
console.error(formatError(`Failed to list resources: ${error.message}`));
|
|
2869
|
+
process.exit(1);
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
async function readResourceCommand(uri, options) {
|
|
2873
|
+
try {
|
|
2874
|
+
const result = await getOrRestoreSession(options.session || null);
|
|
2875
|
+
if (!result) return;
|
|
2876
|
+
const { session } = result;
|
|
2877
|
+
console.error(formatInfo(`Reading resource: ${uri}`));
|
|
2878
|
+
const resource = await session.readResource(uri);
|
|
2879
|
+
if (options.json) {
|
|
2880
|
+
console.log(formatJson(resource));
|
|
2881
|
+
} else {
|
|
2882
|
+
console.log(formatResourceContent(resource));
|
|
2883
|
+
}
|
|
2884
|
+
} catch (error) {
|
|
2885
|
+
console.error(formatError(`Failed to read resource: ${error.message}`));
|
|
2886
|
+
process.exit(1);
|
|
2887
|
+
}
|
|
2888
|
+
}
|
|
2889
|
+
async function subscribeResourceCommand(uri, options) {
|
|
2890
|
+
try {
|
|
2891
|
+
const result = await getOrRestoreSession(options.session || null);
|
|
2892
|
+
if (!result) return;
|
|
2893
|
+
const { session } = result;
|
|
2894
|
+
await session.subscribeToResource(uri);
|
|
2895
|
+
console.log(formatSuccess(`Subscribed to resource: ${uri}`));
|
|
2896
|
+
session.on("notification", async (notification) => {
|
|
2897
|
+
if (notification.method === "notifications/resources/updated") {
|
|
2898
|
+
console.log("");
|
|
2899
|
+
console.log(formatInfo("Resource updated:"));
|
|
2900
|
+
console.log(formatJson(notification.params));
|
|
1049
2901
|
}
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
2902
|
+
});
|
|
2903
|
+
console.log(formatInfo("Listening for updates... (Press Ctrl+C to stop)"));
|
|
2904
|
+
await new Promise(() => {
|
|
2905
|
+
});
|
|
2906
|
+
} catch (error) {
|
|
2907
|
+
console.error(
|
|
2908
|
+
formatError(`Failed to subscribe to resource: ${error.message}`)
|
|
2909
|
+
);
|
|
2910
|
+
process.exit(1);
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
async function unsubscribeResourceCommand(uri, options) {
|
|
2914
|
+
try {
|
|
2915
|
+
const result = await getOrRestoreSession(options.session || null);
|
|
2916
|
+
if (!result) return;
|
|
2917
|
+
const { session } = result;
|
|
2918
|
+
await session.unsubscribeFromResource(uri);
|
|
2919
|
+
console.log(formatSuccess(`Unsubscribed from resource: ${uri}`));
|
|
2920
|
+
} catch (error) {
|
|
2921
|
+
console.error(
|
|
2922
|
+
formatError(`Failed to unsubscribe from resource: ${error.message}`)
|
|
2923
|
+
);
|
|
2924
|
+
process.exit(1);
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
async function listPromptsCommand(options) {
|
|
2928
|
+
try {
|
|
2929
|
+
const result = await getOrRestoreSession(options.session || null);
|
|
2930
|
+
if (!result) return;
|
|
2931
|
+
const { session } = result;
|
|
2932
|
+
const promptsResult = await session.listPrompts();
|
|
2933
|
+
const prompts = promptsResult.prompts;
|
|
2934
|
+
if (options.json) {
|
|
2935
|
+
console.log(formatJson(prompts));
|
|
2936
|
+
return;
|
|
2937
|
+
}
|
|
2938
|
+
if (prompts.length === 0) {
|
|
2939
|
+
console.log(formatInfo("No prompts available"));
|
|
2940
|
+
return;
|
|
2941
|
+
}
|
|
2942
|
+
console.log(formatHeader(`Available Prompts (${prompts.length}):`));
|
|
2943
|
+
console.log("");
|
|
2944
|
+
const tableData = prompts.map((prompt2) => ({
|
|
2945
|
+
name: source_default.bold(prompt2.name),
|
|
2946
|
+
description: prompt2.description || source_default.gray("No description")
|
|
2947
|
+
}));
|
|
2948
|
+
console.log(
|
|
2949
|
+
formatTable(tableData, [
|
|
2950
|
+
{ key: "name", header: "Prompt", width: 25 },
|
|
2951
|
+
{ key: "description", header: "Description", width: 50 }
|
|
2952
|
+
])
|
|
2953
|
+
);
|
|
2954
|
+
} catch (error) {
|
|
2955
|
+
console.error(formatError(`Failed to list prompts: ${error.message}`));
|
|
2956
|
+
process.exit(1);
|
|
2957
|
+
}
|
|
2958
|
+
}
|
|
2959
|
+
async function getPromptCommand(promptName, argsJson, options) {
|
|
2960
|
+
try {
|
|
2961
|
+
const result = await getOrRestoreSession(options?.session || null);
|
|
2962
|
+
if (!result) return;
|
|
2963
|
+
const { session } = result;
|
|
2964
|
+
let args = {};
|
|
2965
|
+
if (argsJson) {
|
|
2966
|
+
try {
|
|
2967
|
+
args = JSON.parse(argsJson);
|
|
2968
|
+
} catch (error) {
|
|
2969
|
+
console.error(formatError("Invalid JSON arguments"));
|
|
2970
|
+
return;
|
|
1075
2971
|
}
|
|
2972
|
+
}
|
|
2973
|
+
console.error(formatInfo(`Getting prompt '${promptName}'...`));
|
|
2974
|
+
const prompt2 = await session.getPrompt(promptName, args);
|
|
2975
|
+
if (options?.json) {
|
|
2976
|
+
console.log(formatJson(prompt2));
|
|
1076
2977
|
} else {
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
);
|
|
1081
|
-
|
|
1082
|
-
console.log(
|
|
1083
|
-
import_chalk2.default.yellow(
|
|
1084
|
-
"\u26A0\uFE0F This is not a GitHub repository or no remote is configured."
|
|
1085
|
-
)
|
|
1086
|
-
);
|
|
1087
|
-
console.log(import_chalk2.default.white("Deploying from local source code instead..."));
|
|
2978
|
+
console.log(formatHeader(`Prompt: ${promptName}`));
|
|
2979
|
+
console.log("");
|
|
2980
|
+
if (prompt2.description) {
|
|
2981
|
+
console.log(prompt2.description);
|
|
2982
|
+
console.log("");
|
|
1088
2983
|
}
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
const buildCommand = await detectBuildCommand(cwd);
|
|
1094
|
-
const startCommand = await detectStartCommand(cwd);
|
|
1095
|
-
console.log(import_chalk2.default.white("Deployment configuration:"));
|
|
1096
|
-
console.log(import_chalk2.default.gray(` Name: `) + import_chalk2.default.cyan(projectName));
|
|
1097
|
-
console.log(import_chalk2.default.gray(` Runtime: `) + import_chalk2.default.cyan(runtime));
|
|
1098
|
-
console.log(import_chalk2.default.gray(` Port: `) + import_chalk2.default.cyan(port));
|
|
1099
|
-
if (buildCommand) {
|
|
1100
|
-
console.log(import_chalk2.default.gray(` Build command: `) + import_chalk2.default.cyan(buildCommand));
|
|
2984
|
+
if (prompt2.messages) {
|
|
2985
|
+
console.log(formatHeader("Messages:"));
|
|
2986
|
+
console.log("");
|
|
2987
|
+
console.log(formatPromptMessages(prompt2.messages));
|
|
1101
2988
|
}
|
|
1102
|
-
|
|
1103
|
-
|
|
2989
|
+
}
|
|
2990
|
+
} catch (error) {
|
|
2991
|
+
console.error(formatError(`Failed to get prompt: ${error.message}`));
|
|
2992
|
+
process.exit(1);
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
async function interactiveCommand(options) {
|
|
2996
|
+
try {
|
|
2997
|
+
const result = await getOrRestoreSession(options.session || null);
|
|
2998
|
+
if (!result) return;
|
|
2999
|
+
const { name: sessionName, session } = result;
|
|
3000
|
+
console.log(formatHeader("MCP Interactive Mode"));
|
|
3001
|
+
console.log("");
|
|
3002
|
+
console.log(formatInfo(`Connected to: ${sessionName}`));
|
|
3003
|
+
console.log("");
|
|
3004
|
+
console.log(source_default.gray("Commands:"));
|
|
3005
|
+
console.log(source_default.gray(" tools list - List available tools"));
|
|
3006
|
+
console.log(
|
|
3007
|
+
source_default.gray(
|
|
3008
|
+
" tools call <name> - Call a tool (will prompt for args)"
|
|
3009
|
+
)
|
|
3010
|
+
);
|
|
3011
|
+
console.log(source_default.gray(" tools describe <name> - Show tool details"));
|
|
3012
|
+
console.log(
|
|
3013
|
+
source_default.gray(" resources list - List available resources")
|
|
3014
|
+
);
|
|
3015
|
+
console.log(source_default.gray(" resources read <uri> - Read a resource"));
|
|
3016
|
+
console.log(
|
|
3017
|
+
source_default.gray(" prompts list - List available prompts")
|
|
3018
|
+
);
|
|
3019
|
+
console.log(source_default.gray(" prompts get <name> - Get a prompt"));
|
|
3020
|
+
console.log(source_default.gray(" sessions list - List all sessions"));
|
|
3021
|
+
console.log(
|
|
3022
|
+
source_default.gray(" sessions switch <name> - Switch to another session")
|
|
3023
|
+
);
|
|
3024
|
+
console.log(
|
|
3025
|
+
source_default.gray(" exit, quit - Exit interactive mode")
|
|
3026
|
+
);
|
|
3027
|
+
console.log("");
|
|
3028
|
+
const rl = createInterface({
|
|
3029
|
+
input: process.stdin,
|
|
3030
|
+
output: process.stdout,
|
|
3031
|
+
prompt: source_default.cyan("mcp> ")
|
|
3032
|
+
});
|
|
3033
|
+
rl.prompt();
|
|
3034
|
+
rl.on("line", async (line) => {
|
|
3035
|
+
const trimmed = line.trim();
|
|
3036
|
+
if (!trimmed) {
|
|
3037
|
+
rl.prompt();
|
|
3038
|
+
return;
|
|
1104
3039
|
}
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
"y"
|
|
1109
|
-
);
|
|
1110
|
-
if (!shouldDeploy) {
|
|
1111
|
-
console.log(import_chalk2.default.gray("Deployment cancelled."));
|
|
3040
|
+
if (trimmed === "exit" || trimmed === "quit") {
|
|
3041
|
+
console.log(formatInfo("Goodbye!"));
|
|
3042
|
+
rl.close();
|
|
1112
3043
|
process.exit(0);
|
|
1113
3044
|
}
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
const
|
|
1117
|
-
const
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
3045
|
+
const parts = trimmed.split(" ");
|
|
3046
|
+
const scope = parts[0];
|
|
3047
|
+
const command = parts[1];
|
|
3048
|
+
const arg = parts[2];
|
|
3049
|
+
try {
|
|
3050
|
+
if (scope === "tools") {
|
|
3051
|
+
if (command === "list") {
|
|
3052
|
+
const tools = await session.listTools();
|
|
3053
|
+
console.log(
|
|
3054
|
+
formatInfo(
|
|
3055
|
+
`Available tools: ${tools.map((t) => t.name).join(", ")}`
|
|
3056
|
+
)
|
|
3057
|
+
);
|
|
3058
|
+
} else if (command === "call" && arg) {
|
|
3059
|
+
rl.question(
|
|
3060
|
+
"Arguments (JSON, or press Enter for none): ",
|
|
3061
|
+
async (argsInput) => {
|
|
3062
|
+
try {
|
|
3063
|
+
const args = argsInput.trim() ? JSON.parse(argsInput) : {};
|
|
3064
|
+
const result2 = await session.callTool(arg, args);
|
|
3065
|
+
console.log(formatToolCall(result2));
|
|
3066
|
+
} catch (error) {
|
|
3067
|
+
console.error(formatError(error.message));
|
|
3068
|
+
}
|
|
3069
|
+
rl.prompt();
|
|
3070
|
+
}
|
|
3071
|
+
);
|
|
3072
|
+
return;
|
|
3073
|
+
} else if (command === "describe" && arg) {
|
|
3074
|
+
const tools = session.tools;
|
|
3075
|
+
const tool = tools.find((t) => t.name === arg);
|
|
3076
|
+
if (tool) {
|
|
3077
|
+
console.log(formatHeader(`Tool: ${tool.name}`));
|
|
3078
|
+
if (tool.description) console.log(tool.description);
|
|
3079
|
+
if (tool.inputSchema) {
|
|
3080
|
+
console.log("");
|
|
3081
|
+
console.log(formatSchema(tool.inputSchema));
|
|
3082
|
+
}
|
|
3083
|
+
} else {
|
|
3084
|
+
console.error(formatError(`Tool '${arg}' not found`));
|
|
3085
|
+
}
|
|
3086
|
+
} else {
|
|
3087
|
+
console.error(
|
|
3088
|
+
formatError(
|
|
3089
|
+
"Invalid command. Try: tools list, tools call <name>, tools describe <name>"
|
|
3090
|
+
)
|
|
3091
|
+
);
|
|
3092
|
+
}
|
|
3093
|
+
} else if (scope === "resources") {
|
|
3094
|
+
if (command === "list") {
|
|
3095
|
+
const result2 = await session.listAllResources();
|
|
3096
|
+
const resources = result2.resources;
|
|
3097
|
+
console.log(
|
|
3098
|
+
formatInfo(
|
|
3099
|
+
`Available resources: ${resources.map((r) => r.uri).join(", ")}`
|
|
3100
|
+
)
|
|
3101
|
+
);
|
|
3102
|
+
} else if (command === "read" && arg) {
|
|
3103
|
+
const resource = await session.readResource(arg);
|
|
3104
|
+
console.log(formatResourceContent(resource));
|
|
3105
|
+
} else {
|
|
3106
|
+
console.error(
|
|
3107
|
+
formatError(
|
|
3108
|
+
"Invalid command. Try: resources list, resources read <uri>"
|
|
3109
|
+
)
|
|
3110
|
+
);
|
|
3111
|
+
}
|
|
3112
|
+
} else if (scope === "prompts") {
|
|
3113
|
+
if (command === "list") {
|
|
3114
|
+
const result2 = await session.listPrompts();
|
|
3115
|
+
const prompts = result2.prompts;
|
|
3116
|
+
console.log(
|
|
3117
|
+
formatInfo(
|
|
3118
|
+
`Available prompts: ${prompts.map((p) => p.name).join(", ")}`
|
|
3119
|
+
)
|
|
3120
|
+
);
|
|
3121
|
+
} else if (command === "get" && arg) {
|
|
3122
|
+
rl.question(
|
|
3123
|
+
"Arguments (JSON, or press Enter for none): ",
|
|
3124
|
+
async (argsInput) => {
|
|
3125
|
+
try {
|
|
3126
|
+
const args = argsInput.trim() ? JSON.parse(argsInput) : {};
|
|
3127
|
+
const prompt2 = await session.getPrompt(arg, args);
|
|
3128
|
+
console.log(formatPromptMessages(prompt2.messages));
|
|
3129
|
+
} catch (error) {
|
|
3130
|
+
console.error(formatError(error.message));
|
|
3131
|
+
}
|
|
3132
|
+
rl.prompt();
|
|
3133
|
+
}
|
|
3134
|
+
);
|
|
3135
|
+
return;
|
|
3136
|
+
} else {
|
|
3137
|
+
console.error(
|
|
3138
|
+
formatError(
|
|
3139
|
+
"Invalid command. Try: prompts list, prompts get <name>"
|
|
3140
|
+
)
|
|
3141
|
+
);
|
|
3142
|
+
}
|
|
3143
|
+
} else if (scope === "sessions") {
|
|
3144
|
+
if (command === "list") {
|
|
3145
|
+
await listSessionsCommand();
|
|
3146
|
+
} else if (command === "switch" && arg) {
|
|
3147
|
+
console.log(
|
|
3148
|
+
formatWarning(
|
|
3149
|
+
"Session switching in interactive mode will be available in a future version"
|
|
3150
|
+
)
|
|
3151
|
+
);
|
|
3152
|
+
} else {
|
|
3153
|
+
console.error(formatError("Invalid command. Try: sessions list"));
|
|
3154
|
+
}
|
|
3155
|
+
} else {
|
|
3156
|
+
console.error(
|
|
3157
|
+
formatError(
|
|
3158
|
+
"Unknown command. Type a valid scope: tools, resources, prompts, sessions"
|
|
3159
|
+
)
|
|
3160
|
+
);
|
|
3161
|
+
}
|
|
3162
|
+
} catch (error) {
|
|
3163
|
+
console.error(formatError(error.message));
|
|
1157
3164
|
}
|
|
1158
|
-
|
|
3165
|
+
rl.prompt();
|
|
3166
|
+
});
|
|
3167
|
+
rl.on("close", () => {
|
|
3168
|
+
console.log("");
|
|
3169
|
+
console.log(formatInfo("Goodbye!"));
|
|
3170
|
+
process.exit(0);
|
|
3171
|
+
});
|
|
1159
3172
|
} catch (error) {
|
|
1160
3173
|
console.error(
|
|
1161
|
-
|
|
1162
|
-
import_chalk2.default.red(error instanceof Error ? error.message : "Unknown error")
|
|
3174
|
+
formatError(`Failed to start interactive mode: ${error.message}`)
|
|
1163
3175
|
);
|
|
1164
3176
|
process.exit(1);
|
|
1165
3177
|
}
|
|
1166
3178
|
}
|
|
3179
|
+
function createClientCommand() {
|
|
3180
|
+
const clientCommand = new Command("client").description(
|
|
3181
|
+
"Interactive MCP client for terminal usage"
|
|
3182
|
+
);
|
|
3183
|
+
clientCommand.command("connect <url>").description("Connect to an MCP server").option("--name <name>", "Session name").option("--stdio", "Use stdio connector instead of HTTP").option("--auth <token>", "Authentication token").action(connectCommand);
|
|
3184
|
+
clientCommand.command("disconnect [session]").description("Disconnect from a session").option("--all", "Disconnect all sessions").action(disconnectCommand);
|
|
3185
|
+
const sessionsCommand = new Command("sessions").description(
|
|
3186
|
+
"Manage CLI sessions"
|
|
3187
|
+
);
|
|
3188
|
+
sessionsCommand.command("list").description("List all saved sessions").action(listSessionsCommand);
|
|
3189
|
+
sessionsCommand.command("switch <name>").description("Switch to a different session").action(switchSessionCommand);
|
|
3190
|
+
clientCommand.addCommand(sessionsCommand);
|
|
3191
|
+
const toolsCommand = new Command("tools").description(
|
|
3192
|
+
"Interact with MCP tools"
|
|
3193
|
+
);
|
|
3194
|
+
toolsCommand.command("list").description("List available tools").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(listToolsCommand);
|
|
3195
|
+
toolsCommand.command("call <name> [args]").description("Call a tool with arguments (JSON string)").option("--session <name>", "Use specific session").option("--timeout <ms>", "Request timeout in milliseconds", parseInt).option("--json", "Output as JSON").action(callToolCommand);
|
|
3196
|
+
toolsCommand.command("describe <name>").description("Show tool details and schema").option("--session <name>", "Use specific session").action(describeToolCommand);
|
|
3197
|
+
clientCommand.addCommand(toolsCommand);
|
|
3198
|
+
const resourcesCommand = new Command("resources").description(
|
|
3199
|
+
"Interact with MCP resources"
|
|
3200
|
+
);
|
|
3201
|
+
resourcesCommand.command("list").description("List available resources").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(listResourcesCommand);
|
|
3202
|
+
resourcesCommand.command("read <uri>").description("Read a resource by URI").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(readResourceCommand);
|
|
3203
|
+
resourcesCommand.command("subscribe <uri>").description("Subscribe to resource updates").option("--session <name>", "Use specific session").action(subscribeResourceCommand);
|
|
3204
|
+
resourcesCommand.command("unsubscribe <uri>").description("Unsubscribe from resource updates").option("--session <name>", "Use specific session").action(unsubscribeResourceCommand);
|
|
3205
|
+
clientCommand.addCommand(resourcesCommand);
|
|
3206
|
+
const promptsCommand = new Command("prompts").description(
|
|
3207
|
+
"Interact with MCP prompts"
|
|
3208
|
+
);
|
|
3209
|
+
promptsCommand.command("list").description("List available prompts").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(listPromptsCommand);
|
|
3210
|
+
promptsCommand.command("get <name> [args]").description("Get a prompt with arguments (JSON string)").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(getPromptCommand);
|
|
3211
|
+
clientCommand.addCommand(promptsCommand);
|
|
3212
|
+
clientCommand.command("interactive").description("Start interactive REPL mode").option("--session <name>", "Use specific session").action(interactiveCommand);
|
|
3213
|
+
return clientCommand;
|
|
3214
|
+
}
|
|
1167
3215
|
|
|
1168
3216
|
// src/index.ts
|
|
1169
|
-
var program = new
|
|
1170
|
-
var packageContent =
|
|
1171
|
-
|
|
3217
|
+
var program = new Command2();
|
|
3218
|
+
var packageContent = readFileSync(
|
|
3219
|
+
path5.join(__dirname, "../package.json"),
|
|
1172
3220
|
"utf-8"
|
|
1173
3221
|
);
|
|
1174
3222
|
var packageJson = JSON.parse(packageContent);
|
|
@@ -1208,12 +3256,12 @@ async function waitForServer(port, host = "localhost", maxAttempts = 30) {
|
|
|
1208
3256
|
}
|
|
1209
3257
|
return false;
|
|
1210
3258
|
}
|
|
1211
|
-
function runCommand(command, args, cwd,
|
|
1212
|
-
const proc =
|
|
3259
|
+
function runCommand(command, args, cwd, env2, filterStderr = false) {
|
|
3260
|
+
const proc = spawn(command, args, {
|
|
1213
3261
|
cwd,
|
|
1214
3262
|
stdio: filterStderr ? ["inherit", "inherit", "pipe"] : "inherit",
|
|
1215
3263
|
shell: false,
|
|
1216
|
-
env:
|
|
3264
|
+
env: env2 ? { ...process.env, ...env2 } : process.env
|
|
1217
3265
|
});
|
|
1218
3266
|
if (filterStderr && proc.stderr) {
|
|
1219
3267
|
proc.stderr.on("data", (data) => {
|
|
@@ -1237,12 +3285,12 @@ function runCommand(command, args, cwd, env, filterStderr = false) {
|
|
|
1237
3285
|
}
|
|
1238
3286
|
async function startTunnel(port, subdomain) {
|
|
1239
3287
|
return new Promise((resolve, reject) => {
|
|
1240
|
-
console.log(
|
|
3288
|
+
console.log(source_default.gray(`Starting tunnel for port ${port}...`));
|
|
1241
3289
|
const tunnelArgs = ["--yes", "@mcp-use/tunnel", String(port)];
|
|
1242
3290
|
if (subdomain) {
|
|
1243
3291
|
tunnelArgs.push("--subdomain", subdomain);
|
|
1244
3292
|
}
|
|
1245
|
-
const proc =
|
|
3293
|
+
const proc = spawn("npx", tunnelArgs, {
|
|
1246
3294
|
stdio: ["ignore", "pipe", "pipe"],
|
|
1247
3295
|
shell: false
|
|
1248
3296
|
});
|
|
@@ -1262,7 +3310,7 @@ async function startTunnel(port, subdomain) {
|
|
|
1262
3310
|
let extractedSubdomain = subdomainMatch ? subdomainMatch[1] : fullDomain.split(".")[0];
|
|
1263
3311
|
if (!/^[a-z0-9-]+$/i.test(extractedSubdomain)) {
|
|
1264
3312
|
console.warn(
|
|
1265
|
-
|
|
3313
|
+
source_default.yellow(
|
|
1266
3314
|
`Warning: Extracted subdomain "${extractedSubdomain}" does not match expected format.`
|
|
1267
3315
|
)
|
|
1268
3316
|
);
|
|
@@ -1270,7 +3318,7 @@ async function startTunnel(port, subdomain) {
|
|
|
1270
3318
|
}
|
|
1271
3319
|
resolved = true;
|
|
1272
3320
|
clearTimeout(setupTimeout);
|
|
1273
|
-
console.log(
|
|
3321
|
+
console.log(source_default.green.bold(`\u2713 Tunnel established: ${url}/mcp`));
|
|
1274
3322
|
resolve({ url, subdomain: extractedSubdomain, process: proc });
|
|
1275
3323
|
}
|
|
1276
3324
|
});
|
|
@@ -1307,7 +3355,7 @@ async function findServerFile(projectPath) {
|
|
|
1307
3355
|
const candidates = ["index.ts", "src/index.ts", "server.ts", "src/server.ts"];
|
|
1308
3356
|
for (const candidate of candidates) {
|
|
1309
3357
|
try {
|
|
1310
|
-
await
|
|
3358
|
+
await access(path5.join(projectPath, candidate));
|
|
1311
3359
|
return candidate;
|
|
1312
3360
|
} catch {
|
|
1313
3361
|
continue;
|
|
@@ -1316,21 +3364,21 @@ async function findServerFile(projectPath) {
|
|
|
1316
3364
|
throw new Error("No server file found");
|
|
1317
3365
|
}
|
|
1318
3366
|
async function buildWidgets(projectPath) {
|
|
1319
|
-
const { promises:
|
|
3367
|
+
const { promises: fs9 } = await import("fs");
|
|
1320
3368
|
const { build } = await import("vite");
|
|
1321
|
-
const resourcesDir =
|
|
3369
|
+
const resourcesDir = path5.join(projectPath, "resources");
|
|
1322
3370
|
const mcpUrl = process.env.MCP_URL;
|
|
1323
3371
|
try {
|
|
1324
|
-
await
|
|
3372
|
+
await access(resourcesDir);
|
|
1325
3373
|
} catch {
|
|
1326
3374
|
console.log(
|
|
1327
|
-
|
|
3375
|
+
source_default.gray("No resources/ directory found - skipping widget build")
|
|
1328
3376
|
);
|
|
1329
3377
|
return [];
|
|
1330
3378
|
}
|
|
1331
3379
|
const entries = [];
|
|
1332
3380
|
try {
|
|
1333
|
-
const files = await
|
|
3381
|
+
const files = await fs9.readdir(resourcesDir, { withFileTypes: true });
|
|
1334
3382
|
for (const dirent of files) {
|
|
1335
3383
|
if (dirent.name.startsWith("._") || dirent.name.startsWith(".DS_Store")) {
|
|
1336
3384
|
continue;
|
|
@@ -1338,12 +3386,12 @@ async function buildWidgets(projectPath) {
|
|
|
1338
3386
|
if (dirent.isFile() && (dirent.name.endsWith(".tsx") || dirent.name.endsWith(".ts"))) {
|
|
1339
3387
|
entries.push({
|
|
1340
3388
|
name: dirent.name.replace(/\.tsx?$/, ""),
|
|
1341
|
-
path:
|
|
3389
|
+
path: path5.join(resourcesDir, dirent.name)
|
|
1342
3390
|
});
|
|
1343
3391
|
} else if (dirent.isDirectory()) {
|
|
1344
|
-
const widgetPath =
|
|
3392
|
+
const widgetPath = path5.join(resourcesDir, dirent.name, "widget.tsx");
|
|
1345
3393
|
try {
|
|
1346
|
-
await
|
|
3394
|
+
await fs9.access(widgetPath);
|
|
1347
3395
|
entries.push({
|
|
1348
3396
|
name: dirent.name,
|
|
1349
3397
|
path: widgetPath
|
|
@@ -1353,30 +3401,30 @@ async function buildWidgets(projectPath) {
|
|
|
1353
3401
|
}
|
|
1354
3402
|
}
|
|
1355
3403
|
} catch (error) {
|
|
1356
|
-
console.log(
|
|
3404
|
+
console.log(source_default.gray("No widgets found in resources/ directory"));
|
|
1357
3405
|
return [];
|
|
1358
3406
|
}
|
|
1359
3407
|
if (entries.length === 0) {
|
|
1360
|
-
console.log(
|
|
3408
|
+
console.log(source_default.gray("No widgets found in resources/ directory"));
|
|
1361
3409
|
return [];
|
|
1362
3410
|
}
|
|
1363
|
-
console.log(
|
|
3411
|
+
console.log(source_default.gray(`Building ${entries.length} widget(s)...`));
|
|
1364
3412
|
const react = (await import("@vitejs/plugin-react")).default;
|
|
1365
3413
|
const tailwindcss = (await import("@tailwindcss/vite")).default;
|
|
1366
3414
|
const builtWidgets = [];
|
|
1367
3415
|
for (const entry of entries) {
|
|
1368
3416
|
const widgetName = entry.name;
|
|
1369
3417
|
const entryPath = entry.path;
|
|
1370
|
-
console.log(
|
|
1371
|
-
const tempDir =
|
|
1372
|
-
await
|
|
1373
|
-
const relativeResourcesPath =
|
|
3418
|
+
console.log(source_default.gray(` - Building ${widgetName}...`));
|
|
3419
|
+
const tempDir = path5.join(projectPath, ".mcp-use", widgetName);
|
|
3420
|
+
await fs9.mkdir(tempDir, { recursive: true });
|
|
3421
|
+
const relativeResourcesPath = path5.relative(tempDir, resourcesDir).replace(/\\/g, "/");
|
|
1374
3422
|
const cssContent = `@import "tailwindcss";
|
|
1375
3423
|
|
|
1376
3424
|
/* Configure Tailwind to scan the resources directory */
|
|
1377
3425
|
@source "${relativeResourcesPath}";
|
|
1378
3426
|
`;
|
|
1379
|
-
await
|
|
3427
|
+
await fs9.writeFile(path5.join(tempDir, "styles.css"), cssContent, "utf8");
|
|
1380
3428
|
const entryContent = `import React from 'react'
|
|
1381
3429
|
import { createRoot } from 'react-dom/client'
|
|
1382
3430
|
import './styles.css'
|
|
@@ -1400,9 +3448,9 @@ if (container && Component) {
|
|
|
1400
3448
|
<script type="module" src="/entry.tsx"></script>
|
|
1401
3449
|
</body>
|
|
1402
3450
|
</html>`;
|
|
1403
|
-
await
|
|
1404
|
-
await
|
|
1405
|
-
const outDir =
|
|
3451
|
+
await fs9.writeFile(path5.join(tempDir, "entry.tsx"), entryContent, "utf8");
|
|
3452
|
+
await fs9.writeFile(path5.join(tempDir, "index.html"), htmlContent, "utf8");
|
|
3453
|
+
const outDir = path5.join(
|
|
1406
3454
|
projectPath,
|
|
1407
3455
|
"dist",
|
|
1408
3456
|
"resources",
|
|
@@ -1412,12 +3460,12 @@ if (container && Component) {
|
|
|
1412
3460
|
const baseUrl = mcpUrl ? `${mcpUrl}/${widgetName}/` : `/mcp-use/widgets/${widgetName}/`;
|
|
1413
3461
|
let widgetMetadata = {};
|
|
1414
3462
|
try {
|
|
1415
|
-
const metadataTempDir =
|
|
3463
|
+
const metadataTempDir = path5.join(
|
|
1416
3464
|
projectPath,
|
|
1417
3465
|
".mcp-use",
|
|
1418
3466
|
`${widgetName}-metadata`
|
|
1419
3467
|
);
|
|
1420
|
-
await
|
|
3468
|
+
await fs9.mkdir(metadataTempDir, { recursive: true });
|
|
1421
3469
|
const { createServer: createServer2 } = await import("vite");
|
|
1422
3470
|
const nodeStubsPlugin = {
|
|
1423
3471
|
name: "node-stubs",
|
|
@@ -1447,7 +3495,7 @@ export default PostHog;
|
|
|
1447
3495
|
};
|
|
1448
3496
|
const metadataServer = await createServer2({
|
|
1449
3497
|
root: metadataTempDir,
|
|
1450
|
-
cacheDir:
|
|
3498
|
+
cacheDir: path5.join(metadataTempDir, ".vite-cache"),
|
|
1451
3499
|
plugins: [nodeStubsPlugin, tailwindcss(), react()],
|
|
1452
3500
|
resolve: {
|
|
1453
3501
|
alias: {
|
|
@@ -1507,12 +3555,12 @@ export default PostHog;
|
|
|
1507
3555
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1508
3556
|
} catch (error) {
|
|
1509
3557
|
console.warn(
|
|
1510
|
-
|
|
3558
|
+
source_default.yellow(` \u26A0 Could not extract metadata for ${widgetName}`)
|
|
1511
3559
|
);
|
|
1512
3560
|
} finally {
|
|
1513
3561
|
await metadataServer.close();
|
|
1514
3562
|
try {
|
|
1515
|
-
await
|
|
3563
|
+
await fs9.rm(metadataTempDir, { recursive: true, force: true });
|
|
1516
3564
|
} catch {
|
|
1517
3565
|
}
|
|
1518
3566
|
}
|
|
@@ -1543,15 +3591,15 @@ export default PostHog;
|
|
|
1543
3591
|
outDir,
|
|
1544
3592
|
emptyOutDir: true,
|
|
1545
3593
|
rollupOptions: {
|
|
1546
|
-
input:
|
|
3594
|
+
input: path5.join(tempDir, "index.html")
|
|
1547
3595
|
}
|
|
1548
3596
|
}
|
|
1549
3597
|
});
|
|
1550
3598
|
const mcpServerUrl = process.env.MCP_SERVER_URL;
|
|
1551
3599
|
if (mcpServerUrl) {
|
|
1552
3600
|
try {
|
|
1553
|
-
const htmlPath =
|
|
1554
|
-
let html = await
|
|
3601
|
+
const htmlPath = path5.join(outDir, "index.html");
|
|
3602
|
+
let html = await fs9.readFile(htmlPath, "utf8");
|
|
1555
3603
|
const injectionScript = `<script>window.__getFile = (filename) => { return "${mcpUrl}/${widgetName}/"+filename }; window.__mcpPublicUrl = "${mcpServerUrl}/mcp-use/public"; window.__mcpPublicAssetsUrl = "${mcpUrl}/public";</script>`;
|
|
1556
3604
|
if (!html.includes("window.__mcpPublicUrl")) {
|
|
1557
3605
|
html = html.replace(
|
|
@@ -1572,13 +3620,13 @@ export default PostHog;
|
|
|
1572
3620
|
<base href="${mcpServerUrl}">`
|
|
1573
3621
|
);
|
|
1574
3622
|
}
|
|
1575
|
-
await
|
|
3623
|
+
await fs9.writeFile(htmlPath, html, "utf8");
|
|
1576
3624
|
console.log(
|
|
1577
|
-
|
|
3625
|
+
source_default.gray(` \u2192 Injected MCP_SERVER_URL into ${widgetName}`)
|
|
1578
3626
|
);
|
|
1579
3627
|
} catch (error) {
|
|
1580
3628
|
console.warn(
|
|
1581
|
-
|
|
3629
|
+
source_default.yellow(
|
|
1582
3630
|
` \u26A0 Failed to post-process HTML for ${widgetName}:`,
|
|
1583
3631
|
error
|
|
1584
3632
|
)
|
|
@@ -1589,36 +3637,36 @@ export default PostHog;
|
|
|
1589
3637
|
name: widgetName,
|
|
1590
3638
|
metadata: widgetMetadata
|
|
1591
3639
|
});
|
|
1592
|
-
console.log(
|
|
3640
|
+
console.log(source_default.green(` \u2713 Built ${widgetName}`));
|
|
1593
3641
|
} catch (error) {
|
|
1594
|
-
console.error(
|
|
3642
|
+
console.error(source_default.red(` \u2717 Failed to build ${widgetName}:`), error);
|
|
1595
3643
|
}
|
|
1596
3644
|
}
|
|
1597
3645
|
return builtWidgets;
|
|
1598
3646
|
}
|
|
1599
3647
|
program.command("build").description("Build TypeScript and MCP UI widgets").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--with-inspector", "Include inspector in production build").action(async (options) => {
|
|
1600
3648
|
try {
|
|
1601
|
-
const projectPath =
|
|
1602
|
-
const { promises:
|
|
1603
|
-
console.log(
|
|
3649
|
+
const projectPath = path5.resolve(options.path);
|
|
3650
|
+
const { promises: fs9 } = await import("fs");
|
|
3651
|
+
console.log(source_default.cyan.bold(`mcp-use v${packageJson.version}`));
|
|
1604
3652
|
const builtWidgets = await buildWidgets(projectPath);
|
|
1605
|
-
console.log(
|
|
3653
|
+
console.log(source_default.gray("Building TypeScript..."));
|
|
1606
3654
|
await runCommand("npx", ["tsc"], projectPath);
|
|
1607
|
-
console.log(
|
|
1608
|
-
const publicDir =
|
|
3655
|
+
console.log(source_default.green("\u2713 TypeScript build complete!"));
|
|
3656
|
+
const publicDir = path5.join(projectPath, "public");
|
|
1609
3657
|
try {
|
|
1610
|
-
await
|
|
1611
|
-
console.log(
|
|
1612
|
-
await
|
|
3658
|
+
await fs9.access(publicDir);
|
|
3659
|
+
console.log(source_default.gray("Copying public assets..."));
|
|
3660
|
+
await fs9.cp(publicDir, path5.join(projectPath, "dist", "public"), {
|
|
1613
3661
|
recursive: true
|
|
1614
3662
|
});
|
|
1615
|
-
console.log(
|
|
3663
|
+
console.log(source_default.green("\u2713 Public assets copied"));
|
|
1616
3664
|
} catch {
|
|
1617
3665
|
}
|
|
1618
|
-
const manifestPath =
|
|
3666
|
+
const manifestPath = path5.join(projectPath, "dist", "mcp-use.json");
|
|
1619
3667
|
let existingManifest = {};
|
|
1620
3668
|
try {
|
|
1621
|
-
const existingContent = await
|
|
3669
|
+
const existingContent = await fs9.readFile(manifestPath, "utf-8");
|
|
1622
3670
|
existingManifest = JSON.parse(existingContent);
|
|
1623
3671
|
} catch {
|
|
1624
3672
|
}
|
|
@@ -1638,41 +3686,41 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
|
|
|
1638
3686
|
buildId,
|
|
1639
3687
|
widgets: widgetsData
|
|
1640
3688
|
};
|
|
1641
|
-
await
|
|
1642
|
-
await
|
|
3689
|
+
await fs9.mkdir(path5.dirname(manifestPath), { recursive: true });
|
|
3690
|
+
await fs9.writeFile(
|
|
1643
3691
|
manifestPath,
|
|
1644
3692
|
JSON.stringify(manifest, null, 2),
|
|
1645
3693
|
"utf8"
|
|
1646
3694
|
);
|
|
1647
|
-
console.log(
|
|
1648
|
-
console.log(
|
|
3695
|
+
console.log(source_default.green("\u2713 Build manifest created"));
|
|
3696
|
+
console.log(source_default.green.bold(`
|
|
1649
3697
|
\u2713 Build complete!`));
|
|
1650
3698
|
if (builtWidgets.length > 0) {
|
|
1651
|
-
console.log(
|
|
3699
|
+
console.log(source_default.gray(` ${builtWidgets.length} widget(s) built`));
|
|
1652
3700
|
}
|
|
1653
3701
|
if (options.withInspector) {
|
|
1654
|
-
console.log(
|
|
3702
|
+
console.log(source_default.gray(" Inspector included"));
|
|
1655
3703
|
}
|
|
1656
3704
|
} catch (error) {
|
|
1657
|
-
console.error(
|
|
3705
|
+
console.error(source_default.red("Build failed:"), error);
|
|
1658
3706
|
process.exit(1);
|
|
1659
3707
|
}
|
|
1660
3708
|
});
|
|
1661
3709
|
program.command("dev").description("Run development server with auto-reload and inspector").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--port <port>", "Server port", "3000").option("--host <host>", "Server host", "localhost").option("--no-open", "Do not auto-open inspector").action(async (options) => {
|
|
1662
3710
|
try {
|
|
1663
|
-
const projectPath =
|
|
3711
|
+
const projectPath = path5.resolve(options.path);
|
|
1664
3712
|
let port = parseInt(options.port, 10);
|
|
1665
3713
|
const host = options.host;
|
|
1666
|
-
console.log(
|
|
3714
|
+
console.log(source_default.cyan.bold(`mcp-use v${packageJson.version}`));
|
|
1667
3715
|
if (!await isPortAvailable(port, host)) {
|
|
1668
|
-
console.log(
|
|
3716
|
+
console.log(source_default.yellow.bold(`\u26A0\uFE0F Port ${port} is already in use`));
|
|
1669
3717
|
const availablePort = await findAvailablePort2(port, host);
|
|
1670
|
-
console.log(
|
|
3718
|
+
console.log(source_default.green.bold(`\u2713 Using port ${availablePort} instead`));
|
|
1671
3719
|
port = availablePort;
|
|
1672
3720
|
}
|
|
1673
3721
|
const serverFile = await findServerFile(projectPath);
|
|
1674
3722
|
const processes = [];
|
|
1675
|
-
const
|
|
3723
|
+
const env2 = {
|
|
1676
3724
|
PORT: String(port),
|
|
1677
3725
|
HOST: host,
|
|
1678
3726
|
NODE_ENV: "development"
|
|
@@ -1681,7 +3729,7 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
1681
3729
|
"npx",
|
|
1682
3730
|
["tsx", "watch", serverFile],
|
|
1683
3731
|
projectPath,
|
|
1684
|
-
|
|
3732
|
+
env2,
|
|
1685
3733
|
true
|
|
1686
3734
|
);
|
|
1687
3735
|
processes.push(serverCommand.process);
|
|
@@ -1692,17 +3740,17 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
1692
3740
|
const mcpEndpoint = `http://${host}:${port}/mcp`;
|
|
1693
3741
|
const inspectorUrl = `http://${host}:${port}/inspector?autoConnect=${encodeURIComponent(mcpEndpoint)}`;
|
|
1694
3742
|
const readyTime = Date.now() - startTime;
|
|
1695
|
-
console.log(
|
|
1696
|
-
console.log(
|
|
1697
|
-
console.log(
|
|
1698
|
-
console.log(
|
|
1699
|
-
console.log(
|
|
3743
|
+
console.log(source_default.green.bold(`\u2713 Ready in ${readyTime}ms`));
|
|
3744
|
+
console.log(source_default.whiteBright(`Local: http://${host}:${port}`));
|
|
3745
|
+
console.log(source_default.whiteBright(`Network: http://${host}:${port}`));
|
|
3746
|
+
console.log(source_default.whiteBright(`MCP: ${mcpEndpoint}`));
|
|
3747
|
+
console.log(source_default.whiteBright(`Inspector: ${inspectorUrl}
|
|
1700
3748
|
`));
|
|
1701
|
-
await (
|
|
3749
|
+
await open_default(inspectorUrl);
|
|
1702
3750
|
}
|
|
1703
3751
|
}
|
|
1704
3752
|
const cleanup = () => {
|
|
1705
|
-
console.log(
|
|
3753
|
+
console.log(source_default.gray("\n\nShutting down..."));
|
|
1706
3754
|
const processesToKill = processes.length;
|
|
1707
3755
|
let killedCount = 0;
|
|
1708
3756
|
const checkAndExit = () => {
|
|
@@ -1733,13 +3781,13 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
1733
3781
|
await new Promise(() => {
|
|
1734
3782
|
});
|
|
1735
3783
|
} catch (error) {
|
|
1736
|
-
console.error(
|
|
3784
|
+
console.error(source_default.red("Dev mode failed:"), error);
|
|
1737
3785
|
process.exit(1);
|
|
1738
3786
|
}
|
|
1739
3787
|
});
|
|
1740
3788
|
program.command("start").description("Start production server").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--port <port>", "Server port", "3000").option("--tunnel", "Expose server through a tunnel").action(async (options) => {
|
|
1741
3789
|
try {
|
|
1742
|
-
const projectPath =
|
|
3790
|
+
const projectPath = path5.resolve(options.path);
|
|
1743
3791
|
const port = parseInt(options.port, 10);
|
|
1744
3792
|
console.log(
|
|
1745
3793
|
`\x1B[36m\x1B[1mmcp-use\x1B[0m \x1B[90mVersion: ${packageJson.version}\x1B[0m
|
|
@@ -1750,20 +3798,20 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
1750
3798
|
let tunnelSubdomain = void 0;
|
|
1751
3799
|
if (options.tunnel) {
|
|
1752
3800
|
try {
|
|
1753
|
-
const manifestPath =
|
|
3801
|
+
const manifestPath = path5.join(projectPath, "dist", "mcp-use.json");
|
|
1754
3802
|
let existingSubdomain;
|
|
1755
3803
|
try {
|
|
1756
|
-
const manifestContent = await (
|
|
3804
|
+
const manifestContent = await readFile2(manifestPath, "utf-8");
|
|
1757
3805
|
const manifest = JSON.parse(manifestContent);
|
|
1758
3806
|
existingSubdomain = manifest.tunnel?.subdomain;
|
|
1759
3807
|
if (existingSubdomain) {
|
|
1760
3808
|
console.log(
|
|
1761
|
-
|
|
3809
|
+
source_default.gray(`Found existing subdomain: ${existingSubdomain}`)
|
|
1762
3810
|
);
|
|
1763
3811
|
}
|
|
1764
3812
|
} catch (error) {
|
|
1765
3813
|
console.debug(
|
|
1766
|
-
|
|
3814
|
+
source_default.gray(
|
|
1767
3815
|
`Debug: Failed to read or parse mcp-use.json: ${error instanceof Error ? error.message : String(error)}`
|
|
1768
3816
|
)
|
|
1769
3817
|
);
|
|
@@ -1776,7 +3824,7 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
1776
3824
|
try {
|
|
1777
3825
|
let manifest = {};
|
|
1778
3826
|
try {
|
|
1779
|
-
const manifestContent = await (
|
|
3827
|
+
const manifestContent = await readFile2(manifestPath, "utf-8");
|
|
1780
3828
|
manifest = JSON.parse(manifestContent);
|
|
1781
3829
|
} catch {
|
|
1782
3830
|
}
|
|
@@ -1784,44 +3832,44 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
1784
3832
|
manifest.tunnel = {};
|
|
1785
3833
|
}
|
|
1786
3834
|
manifest.tunnel.subdomain = subdomain;
|
|
1787
|
-
await (
|
|
1788
|
-
await (
|
|
3835
|
+
await mkdir2(path5.dirname(manifestPath), { recursive: true });
|
|
3836
|
+
await writeFile2(
|
|
1789
3837
|
manifestPath,
|
|
1790
3838
|
JSON.stringify(manifest, null, 2),
|
|
1791
3839
|
"utf-8"
|
|
1792
3840
|
);
|
|
1793
3841
|
} catch (error) {
|
|
1794
3842
|
console.warn(
|
|
1795
|
-
|
|
3843
|
+
source_default.yellow(
|
|
1796
3844
|
`\u26A0\uFE0F Failed to save subdomain to mcp-use.json: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
1797
3845
|
)
|
|
1798
3846
|
);
|
|
1799
3847
|
}
|
|
1800
3848
|
} catch (error) {
|
|
1801
|
-
console.error(
|
|
3849
|
+
console.error(source_default.red("Failed to start tunnel:"), error);
|
|
1802
3850
|
process.exit(1);
|
|
1803
3851
|
}
|
|
1804
3852
|
}
|
|
1805
3853
|
let serverFile = "dist/index.js";
|
|
1806
3854
|
try {
|
|
1807
|
-
await
|
|
3855
|
+
await access(path5.join(projectPath, serverFile));
|
|
1808
3856
|
} catch {
|
|
1809
3857
|
serverFile = "dist/server.js";
|
|
1810
3858
|
}
|
|
1811
3859
|
console.log("Starting production server...");
|
|
1812
|
-
const
|
|
3860
|
+
const env2 = {
|
|
1813
3861
|
...process.env,
|
|
1814
3862
|
PORT: String(port),
|
|
1815
3863
|
NODE_ENV: "production"
|
|
1816
3864
|
};
|
|
1817
3865
|
if (mcpUrl) {
|
|
1818
|
-
|
|
1819
|
-
console.log(
|
|
3866
|
+
env2.MCP_URL = mcpUrl;
|
|
3867
|
+
console.log(source_default.whiteBright(`Tunnel: ${mcpUrl}/mcp`));
|
|
1820
3868
|
}
|
|
1821
|
-
const serverProc =
|
|
3869
|
+
const serverProc = spawn("node", [serverFile], {
|
|
1822
3870
|
cwd: projectPath,
|
|
1823
3871
|
stdio: "inherit",
|
|
1824
|
-
env
|
|
3872
|
+
env: env2
|
|
1825
3873
|
});
|
|
1826
3874
|
let cleanupInProgress = false;
|
|
1827
3875
|
const cleanup = async () => {
|
|
@@ -1829,7 +3877,7 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
1829
3877
|
return;
|
|
1830
3878
|
}
|
|
1831
3879
|
cleanupInProgress = true;
|
|
1832
|
-
console.log(
|
|
3880
|
+
console.log(source_default.gray("\n\nShutting down..."));
|
|
1833
3881
|
if (tunnelProcess && typeof tunnelProcess.markShutdown === "function") {
|
|
1834
3882
|
tunnelProcess.markShutdown();
|
|
1835
3883
|
}
|
|
@@ -1899,4 +3947,6 @@ program.command("deploy").description("Deploy MCP server to mcp-use cloud").opti
|
|
|
1899
3947
|
fromSource: options.fromSource
|
|
1900
3948
|
});
|
|
1901
3949
|
});
|
|
3950
|
+
program.addCommand(createClientCommand());
|
|
1902
3951
|
program.parse();
|
|
3952
|
+
//# sourceMappingURL=index.js.map
|