@mcp-use/cli 2.5.6 → 2.6.0-canary.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/client.d.ts +95 -0
- package/dist/commands/client.d.ts.map +1 -0
- package/dist/index.cjs +4087 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +3101 -1029
- 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/git.d.ts.map +1 -1
- 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 -1976
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,1680 @@ 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, 6) + "...";
|
|
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
|
+
try {
|
|
1757
|
+
const parsedUrl = new URL(url);
|
|
1758
|
+
return parsedUrl.hostname === "github.com" || parsedUrl.hostname === "www.github.com";
|
|
1759
|
+
} catch {
|
|
1760
|
+
const sshMatch = url.match(/^git@([^:/]+)[:/]/);
|
|
1761
|
+
if (sshMatch) {
|
|
1762
|
+
const host = sshMatch[1];
|
|
1763
|
+
return host === "github.com" || host === "www.github.com";
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
return false;
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
// src/commands/deploy.ts
|
|
1770
|
+
var execAsync2 = promisify8(exec2);
|
|
1771
|
+
async function isMcpProject(cwd = process.cwd()) {
|
|
1772
|
+
try {
|
|
1773
|
+
const packageJsonPath = path4.join(cwd, "package.json");
|
|
1774
|
+
const content = await fs8.readFile(packageJsonPath, "utf-8");
|
|
1775
|
+
const packageJson2 = JSON.parse(content);
|
|
1776
|
+
const hasMcpDeps = packageJson2.dependencies?.["mcp-use"] || packageJson2.dependencies?.["@modelcontextprotocol/sdk"] || packageJson2.devDependencies?.["mcp-use"] || packageJson2.devDependencies?.["@modelcontextprotocol/sdk"];
|
|
1777
|
+
const hasMcpScripts = packageJson2.scripts?.mcp || packageJson2.scripts?.["mcp:dev"];
|
|
1778
|
+
return !!(hasMcpDeps || hasMcpScripts);
|
|
1779
|
+
} catch {
|
|
1780
|
+
return false;
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
async function getProjectName(cwd = process.cwd()) {
|
|
1784
|
+
try {
|
|
1785
|
+
const packageJsonPath = path4.join(cwd, "package.json");
|
|
1786
|
+
const content = await fs8.readFile(packageJsonPath, "utf-8");
|
|
1787
|
+
const packageJson2 = JSON.parse(content);
|
|
1788
|
+
if (packageJson2.name) {
|
|
1789
|
+
return packageJson2.name;
|
|
1790
|
+
}
|
|
1791
|
+
} catch {
|
|
1792
|
+
}
|
|
1793
|
+
return path4.basename(cwd);
|
|
1794
|
+
}
|
|
1795
|
+
async function detectBuildCommand(cwd = process.cwd()) {
|
|
1796
|
+
try {
|
|
1797
|
+
const packageJsonPath = path4.join(cwd, "package.json");
|
|
1798
|
+
const content = await fs8.readFile(packageJsonPath, "utf-8");
|
|
1799
|
+
const packageJson2 = JSON.parse(content);
|
|
1800
|
+
if (packageJson2.scripts?.build) {
|
|
1801
|
+
return "npm run build";
|
|
1802
|
+
}
|
|
1803
|
+
} catch {
|
|
1804
|
+
}
|
|
1805
|
+
return void 0;
|
|
1806
|
+
}
|
|
1807
|
+
async function detectStartCommand(cwd = process.cwd()) {
|
|
1808
|
+
try {
|
|
1809
|
+
const packageJsonPath = path4.join(cwd, "package.json");
|
|
1810
|
+
const content = await fs8.readFile(packageJsonPath, "utf-8");
|
|
1811
|
+
const packageJson2 = JSON.parse(content);
|
|
1812
|
+
if (packageJson2.scripts?.start) {
|
|
1813
|
+
return "npm start";
|
|
1814
|
+
}
|
|
1815
|
+
if (packageJson2.main) {
|
|
1816
|
+
return `node ${packageJson2.main}`;
|
|
1817
|
+
}
|
|
1818
|
+
} catch {
|
|
1819
|
+
}
|
|
1820
|
+
return void 0;
|
|
1821
|
+
}
|
|
1822
|
+
async function detectRuntime(cwd = process.cwd()) {
|
|
1823
|
+
try {
|
|
1824
|
+
const pythonFiles = ["requirements.txt", "pyproject.toml", "setup.py"];
|
|
1825
|
+
for (const file of pythonFiles) {
|
|
1826
|
+
try {
|
|
1827
|
+
await fs8.access(path4.join(cwd, file));
|
|
1828
|
+
return "python";
|
|
1829
|
+
} catch {
|
|
1830
|
+
continue;
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
try {
|
|
1834
|
+
await fs8.access(path4.join(cwd, "package.json"));
|
|
1835
|
+
return "node";
|
|
1836
|
+
} catch {
|
|
1837
|
+
}
|
|
1838
|
+
} catch {
|
|
1839
|
+
}
|
|
1840
|
+
return "node";
|
|
1841
|
+
}
|
|
1842
|
+
async function prompt(question, defaultValue = "n") {
|
|
1843
|
+
const readline = await import("readline");
|
|
1844
|
+
const rl = readline.createInterface({
|
|
1845
|
+
input: process.stdin,
|
|
1846
|
+
output: process.stdout
|
|
1847
|
+
});
|
|
1848
|
+
const defaultIndicator = defaultValue === "y" ? "Y/n" : "y/N";
|
|
1849
|
+
const questionWithDefault = question.replace(
|
|
1850
|
+
/(\(y\/n\):)/,
|
|
1851
|
+
`(${defaultIndicator}):`
|
|
1852
|
+
);
|
|
1853
|
+
return new Promise((resolve) => {
|
|
1854
|
+
rl.question(questionWithDefault, (answer) => {
|
|
1855
|
+
rl.close();
|
|
1856
|
+
const trimmedAnswer = answer.trim().toLowerCase();
|
|
1857
|
+
if (trimmedAnswer === "") {
|
|
1858
|
+
resolve(defaultValue === "y");
|
|
1859
|
+
} else {
|
|
1860
|
+
resolve(trimmedAnswer === "y" || trimmedAnswer === "yes");
|
|
1861
|
+
}
|
|
1862
|
+
});
|
|
1863
|
+
});
|
|
1864
|
+
}
|
|
1865
|
+
async function createTarball(cwd) {
|
|
1866
|
+
const tmpDir = os4.tmpdir();
|
|
1867
|
+
const tarballPath = path4.join(tmpDir, `mcp-deploy-${Date.now()}.tar.gz`);
|
|
1868
|
+
const excludePatterns = [
|
|
1869
|
+
"node_modules",
|
|
1870
|
+
".git",
|
|
1871
|
+
"dist",
|
|
1872
|
+
"build",
|
|
1873
|
+
".next",
|
|
1874
|
+
".venv",
|
|
1875
|
+
"__pycache__",
|
|
1876
|
+
"*.pyc",
|
|
1877
|
+
".DS_Store",
|
|
1878
|
+
"._*",
|
|
1879
|
+
// macOS resource fork files
|
|
1880
|
+
".mcp-use",
|
|
1881
|
+
// Build artifacts directory
|
|
1882
|
+
".env",
|
|
1883
|
+
".env.local",
|
|
1884
|
+
"*.log"
|
|
1885
|
+
];
|
|
1886
|
+
const excludeFlags = excludePatterns.map((pattern) => `--exclude=${pattern}`).join(" ");
|
|
1887
|
+
const command = `tar ${excludeFlags} -czf "${tarballPath}" -C "${cwd}" . 2>&1 || true`;
|
|
1888
|
+
try {
|
|
1889
|
+
await execAsync2(command);
|
|
1890
|
+
return tarballPath;
|
|
1891
|
+
} catch (error) {
|
|
1892
|
+
throw new Error(
|
|
1893
|
+
`Failed to create tarball: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
1894
|
+
);
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
function formatFileSize(bytes) {
|
|
1898
|
+
if (bytes === 0) return "0 B";
|
|
1899
|
+
const k = 1024;
|
|
1900
|
+
const sizes = ["B", "KB", "MB", "GB"];
|
|
1901
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
1902
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
1903
|
+
}
|
|
1904
|
+
async function displayDeploymentProgress(api, deployment) {
|
|
1905
|
+
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
1906
|
+
let frameIndex = 0;
|
|
1907
|
+
let spinnerInterval = null;
|
|
1908
|
+
let lastStep = "";
|
|
1909
|
+
const startSpinner = (message) => {
|
|
1910
|
+
if (spinnerInterval) {
|
|
1911
|
+
clearInterval(spinnerInterval);
|
|
1912
|
+
}
|
|
1913
|
+
process.stdout.write("\r\x1B[K");
|
|
1914
|
+
spinnerInterval = setInterval(() => {
|
|
1915
|
+
const frame = frames[frameIndex];
|
|
1916
|
+
frameIndex = (frameIndex + 1) % frames.length;
|
|
1917
|
+
process.stdout.write(
|
|
1918
|
+
"\r" + source_default.cyan(frame) + " " + source_default.gray(message)
|
|
1919
|
+
);
|
|
1920
|
+
}, 80);
|
|
1921
|
+
};
|
|
1922
|
+
const stopSpinner = () => {
|
|
1923
|
+
if (spinnerInterval) {
|
|
1924
|
+
clearInterval(spinnerInterval);
|
|
1925
|
+
spinnerInterval = null;
|
|
1926
|
+
process.stdout.write("\r\x1B[K");
|
|
1927
|
+
}
|
|
1928
|
+
};
|
|
1929
|
+
console.log();
|
|
1930
|
+
startSpinner("Deploying...");
|
|
1931
|
+
try {
|
|
1932
|
+
for await (const log of api.streamDeploymentLogs(deployment.id)) {
|
|
1933
|
+
try {
|
|
1934
|
+
const logData = JSON.parse(log);
|
|
1935
|
+
if (logData.step && logData.step !== lastStep) {
|
|
1936
|
+
lastStep = logData.step;
|
|
1937
|
+
const stepMessages = {
|
|
1938
|
+
clone: "Preparing source code...",
|
|
1939
|
+
analyze: "Analyzing project...",
|
|
1940
|
+
build: "Building container image...",
|
|
1941
|
+
deploy: "Deploying to cloud..."
|
|
1942
|
+
};
|
|
1943
|
+
const message = stepMessages[logData.step] || "Deploying...";
|
|
1944
|
+
startSpinner(message);
|
|
1945
|
+
}
|
|
1946
|
+
if (logData.line) {
|
|
1947
|
+
stopSpinner();
|
|
1948
|
+
const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
|
|
1949
|
+
const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
|
|
1950
|
+
console.log(stepPrefix + levelColor(logData.line));
|
|
1951
|
+
}
|
|
1952
|
+
} catch {
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
} catch (error) {
|
|
1956
|
+
stopSpinner();
|
|
1957
|
+
}
|
|
1958
|
+
let checkCount = 0;
|
|
1959
|
+
const maxChecks = 60;
|
|
1960
|
+
let delay = 3e3;
|
|
1961
|
+
const maxDelay = 1e4;
|
|
1962
|
+
let lastDisplayedLogLength = 0;
|
|
1963
|
+
while (checkCount < maxChecks) {
|
|
1964
|
+
const currentDelay = delay;
|
|
1965
|
+
await new Promise((resolve) => setTimeout(resolve, currentDelay));
|
|
1966
|
+
const finalDeployment = await api.getDeployment(deployment.id);
|
|
1967
|
+
if (finalDeployment.buildLogs && finalDeployment.buildLogs.length > lastDisplayedLogLength) {
|
|
1968
|
+
const newLogs = finalDeployment.buildLogs.substring(
|
|
1969
|
+
lastDisplayedLogLength
|
|
1970
|
+
);
|
|
1971
|
+
const logLines = newLogs.split("\n").filter((l) => l.trim());
|
|
1972
|
+
for (const line of logLines) {
|
|
1973
|
+
try {
|
|
1974
|
+
const logData = JSON.parse(line);
|
|
1975
|
+
if (logData.line) {
|
|
1976
|
+
stopSpinner();
|
|
1977
|
+
const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
|
|
1978
|
+
const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
|
|
1979
|
+
console.log(stepPrefix + levelColor(logData.line));
|
|
1980
|
+
}
|
|
1981
|
+
} catch {
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
lastDisplayedLogLength = finalDeployment.buildLogs.length;
|
|
1985
|
+
}
|
|
1986
|
+
if (finalDeployment.status === "running") {
|
|
1987
|
+
const mcpUrl = `https://${finalDeployment.domain}/mcp`;
|
|
1988
|
+
const inspectorUrl = `https://inspector.mcp-use.com/inspector?autoConnect=${encodeURIComponent(mcpUrl)}`;
|
|
1989
|
+
console.log(source_default.green.bold("\u2713 Deployment successful!\n"));
|
|
1990
|
+
console.log(source_default.white("\u{1F310} MCP Server URL:"));
|
|
1991
|
+
console.log(source_default.cyan.bold(` ${mcpUrl}
|
|
1992
|
+
`));
|
|
1993
|
+
console.log(source_default.white("\u{1F50D} Inspector URL:"));
|
|
1994
|
+
console.log(source_default.cyan.bold(` ${inspectorUrl}
|
|
1995
|
+
`));
|
|
1996
|
+
if (finalDeployment.customDomain) {
|
|
1997
|
+
const customMcpUrl = `https://${finalDeployment.customDomain}/mcp`;
|
|
1998
|
+
const customInspectorUrl = `https://inspector.mcp-use.com/inspect?autoConnect=${encodeURIComponent(customMcpUrl)}`;
|
|
1999
|
+
console.log(source_default.white("\u{1F517} Custom Domain:"));
|
|
2000
|
+
console.log(source_default.cyan.bold(` ${customMcpUrl}
|
|
2001
|
+
`));
|
|
2002
|
+
console.log(source_default.white("\u{1F50D} Custom Inspector:"));
|
|
2003
|
+
console.log(source_default.cyan.bold(` ${customInspectorUrl}
|
|
2004
|
+
`));
|
|
2005
|
+
}
|
|
2006
|
+
console.log(
|
|
2007
|
+
source_default.gray("Deployment ID: ") + source_default.white(finalDeployment.id)
|
|
2008
|
+
);
|
|
2009
|
+
return;
|
|
2010
|
+
} else if (finalDeployment.status === "failed") {
|
|
2011
|
+
console.log(source_default.red.bold("\u2717 Deployment failed\n"));
|
|
2012
|
+
if (finalDeployment.error) {
|
|
2013
|
+
console.log(source_default.red("Error: ") + finalDeployment.error);
|
|
2014
|
+
}
|
|
2015
|
+
if (finalDeployment.buildLogs) {
|
|
2016
|
+
console.log(source_default.gray("\nBuild logs:"));
|
|
2017
|
+
try {
|
|
2018
|
+
const logs = finalDeployment.buildLogs.split("\n").filter((l) => l.trim());
|
|
2019
|
+
for (const log of logs) {
|
|
2020
|
+
try {
|
|
2021
|
+
const logData = JSON.parse(log);
|
|
2022
|
+
if (logData.line) {
|
|
2023
|
+
console.log(source_default.gray(` ${logData.line}`));
|
|
2024
|
+
}
|
|
2025
|
+
} catch {
|
|
2026
|
+
console.log(source_default.gray(` ${log}`));
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
} catch {
|
|
2030
|
+
console.log(source_default.gray(finalDeployment.buildLogs));
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
process.exit(1);
|
|
2034
|
+
} else if (finalDeployment.status === "building") {
|
|
2035
|
+
startSpinner("Building and deploying...");
|
|
2036
|
+
checkCount++;
|
|
2037
|
+
delay = Math.min(delay * 1.2, maxDelay);
|
|
2038
|
+
} else {
|
|
2039
|
+
console.log(
|
|
2040
|
+
source_default.yellow("\u26A0\uFE0F Deployment status: ") + finalDeployment.status
|
|
2041
|
+
);
|
|
2042
|
+
return;
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
stopSpinner();
|
|
2046
|
+
console.log(source_default.yellow("\u26A0\uFE0F Deployment is taking longer than expected."));
|
|
2047
|
+
console.log(
|
|
2048
|
+
source_default.gray("Check status with: ") + source_default.white(`mcp-use status ${deployment.id}`)
|
|
2049
|
+
);
|
|
2050
|
+
}
|
|
2051
|
+
async function deployCommand(options) {
|
|
2052
|
+
try {
|
|
2053
|
+
const cwd = process.cwd();
|
|
2054
|
+
if (!await isLoggedIn()) {
|
|
2055
|
+
console.log(source_default.red("\u2717 You are not logged in."));
|
|
2056
|
+
console.log(
|
|
2057
|
+
source_default.gray("Run " + source_default.white("mcp-use login") + " to get started.")
|
|
2058
|
+
);
|
|
2059
|
+
process.exit(1);
|
|
2060
|
+
}
|
|
2061
|
+
console.log(source_default.cyan.bold("\u{1F680} Deploying to mcp-use cloud...\n"));
|
|
2062
|
+
const isMcp = await isMcpProject(cwd);
|
|
2063
|
+
if (!isMcp) {
|
|
2064
|
+
console.log(
|
|
2065
|
+
source_default.yellow(
|
|
2066
|
+
"\u26A0\uFE0F This doesn't appear to be an MCP server project (no mcp-use or @modelcontextprotocol/sdk dependency found)."
|
|
2067
|
+
)
|
|
2068
|
+
);
|
|
2069
|
+
const shouldContinue = await prompt(
|
|
2070
|
+
source_default.white("Continue anyway? (y/n): ")
|
|
2071
|
+
);
|
|
2072
|
+
if (!shouldContinue) {
|
|
2073
|
+
console.log(source_default.gray("Deployment cancelled."));
|
|
2074
|
+
process.exit(0);
|
|
2075
|
+
}
|
|
2076
|
+
console.log();
|
|
2077
|
+
}
|
|
2078
|
+
const gitInfo = await getGitInfo(cwd);
|
|
2079
|
+
if (!options.fromSource && gitInfo.isGitRepo && gitInfo.remoteUrl && isGitHubUrl(gitInfo.remoteUrl)) {
|
|
2080
|
+
if (!gitInfo.owner || !gitInfo.repo) {
|
|
2081
|
+
console.log(
|
|
2082
|
+
source_default.red(
|
|
2083
|
+
"\u2717 Could not parse GitHub repository information from remote URL."
|
|
2084
|
+
)
|
|
2085
|
+
);
|
|
2086
|
+
process.exit(1);
|
|
2087
|
+
}
|
|
2088
|
+
console.log(source_default.white("GitHub repository detected:"));
|
|
2089
|
+
console.log(
|
|
2090
|
+
source_default.gray(` Repository: `) + source_default.cyan(`${gitInfo.owner}/${gitInfo.repo}`)
|
|
2091
|
+
);
|
|
2092
|
+
console.log(
|
|
2093
|
+
source_default.gray(` Branch: `) + source_default.cyan(gitInfo.branch || "main")
|
|
2094
|
+
);
|
|
2095
|
+
if (gitInfo.commitSha) {
|
|
2096
|
+
console.log(
|
|
2097
|
+
source_default.gray(` Commit: `) + source_default.gray(gitInfo.commitSha.substring(0, 7))
|
|
2098
|
+
);
|
|
2099
|
+
}
|
|
2100
|
+
if (gitInfo.commitMessage) {
|
|
2101
|
+
console.log(
|
|
2102
|
+
source_default.gray(` Message: `) + source_default.gray(gitInfo.commitMessage.split("\n")[0])
|
|
2103
|
+
);
|
|
2104
|
+
}
|
|
2105
|
+
console.log();
|
|
2106
|
+
const shouldDeploy = await prompt(
|
|
2107
|
+
source_default.white(
|
|
2108
|
+
`Deploy from GitHub repository ${gitInfo.owner}/${gitInfo.repo}? (y/n): `
|
|
2109
|
+
)
|
|
2110
|
+
);
|
|
2111
|
+
if (!shouldDeploy) {
|
|
2112
|
+
console.log(source_default.gray("Deployment cancelled."));
|
|
2113
|
+
process.exit(0);
|
|
2114
|
+
}
|
|
2115
|
+
const projectName = options.name || await getProjectName(cwd);
|
|
2116
|
+
const runtime = options.runtime || await detectRuntime(cwd);
|
|
2117
|
+
const port = options.port || 3e3;
|
|
2118
|
+
const buildCommand = await detectBuildCommand(cwd);
|
|
2119
|
+
const startCommand = await detectStartCommand(cwd);
|
|
2120
|
+
console.log();
|
|
2121
|
+
console.log(source_default.white("Deployment configuration:"));
|
|
2122
|
+
console.log(source_default.gray(` Name: `) + source_default.cyan(projectName));
|
|
2123
|
+
console.log(source_default.gray(` Runtime: `) + source_default.cyan(runtime));
|
|
2124
|
+
console.log(source_default.gray(` Port: `) + source_default.cyan(port));
|
|
2125
|
+
if (buildCommand) {
|
|
2126
|
+
console.log(source_default.gray(` Build command: `) + source_default.cyan(buildCommand));
|
|
2127
|
+
}
|
|
2128
|
+
if (startCommand) {
|
|
2129
|
+
console.log(source_default.gray(` Start command: `) + source_default.cyan(startCommand));
|
|
2130
|
+
}
|
|
2131
|
+
console.log();
|
|
2132
|
+
const deploymentRequest = {
|
|
2133
|
+
name: projectName,
|
|
2134
|
+
source: {
|
|
2135
|
+
type: "github",
|
|
2136
|
+
repo: `${gitInfo.owner}/${gitInfo.repo}`,
|
|
2137
|
+
branch: gitInfo.branch || "main",
|
|
2138
|
+
runtime,
|
|
2139
|
+
port,
|
|
2140
|
+
buildCommand,
|
|
2141
|
+
startCommand
|
|
2142
|
+
},
|
|
2143
|
+
healthCheckPath: "/healthz"
|
|
2144
|
+
};
|
|
2145
|
+
console.log(source_default.gray("Creating deployment..."));
|
|
2146
|
+
const api = await McpUseAPI.create();
|
|
2147
|
+
const deployment = await api.createDeployment(deploymentRequest);
|
|
2148
|
+
console.log(
|
|
2149
|
+
source_default.green("\u2713 Deployment created: ") + source_default.gray(deployment.id)
|
|
2150
|
+
);
|
|
2151
|
+
await displayDeploymentProgress(api, deployment);
|
|
2152
|
+
if (options.open && deployment.domain) {
|
|
2153
|
+
console.log();
|
|
2154
|
+
console.log(source_default.gray("Opening deployment in browser..."));
|
|
2155
|
+
await open_default(`https://${deployment.domain}`);
|
|
2156
|
+
}
|
|
2157
|
+
} else {
|
|
2158
|
+
if (options.fromSource) {
|
|
2159
|
+
console.log(
|
|
2160
|
+
source_default.white("\u{1F4E6} Deploying from local source code (--from-source)...")
|
|
2161
|
+
);
|
|
2162
|
+
} else {
|
|
2163
|
+
console.log(
|
|
2164
|
+
source_default.yellow(
|
|
2165
|
+
"\u26A0\uFE0F This is not a GitHub repository or no remote is configured."
|
|
2166
|
+
)
|
|
2167
|
+
);
|
|
2168
|
+
console.log(source_default.white("Deploying from local source code instead..."));
|
|
2169
|
+
}
|
|
2170
|
+
console.log();
|
|
2171
|
+
const projectName = options.name || await getProjectName(cwd);
|
|
2172
|
+
const runtime = options.runtime || await detectRuntime(cwd);
|
|
2173
|
+
const port = options.port || 3e3;
|
|
2174
|
+
const buildCommand = await detectBuildCommand(cwd);
|
|
2175
|
+
const startCommand = await detectStartCommand(cwd);
|
|
2176
|
+
console.log(source_default.white("Deployment configuration:"));
|
|
2177
|
+
console.log(source_default.gray(` Name: `) + source_default.cyan(projectName));
|
|
2178
|
+
console.log(source_default.gray(` Runtime: `) + source_default.cyan(runtime));
|
|
2179
|
+
console.log(source_default.gray(` Port: `) + source_default.cyan(port));
|
|
2180
|
+
if (buildCommand) {
|
|
2181
|
+
console.log(source_default.gray(` Build command: `) + source_default.cyan(buildCommand));
|
|
2182
|
+
}
|
|
2183
|
+
if (startCommand) {
|
|
2184
|
+
console.log(source_default.gray(` Start command: `) + source_default.cyan(startCommand));
|
|
2185
|
+
}
|
|
2186
|
+
console.log();
|
|
2187
|
+
const shouldDeploy = await prompt(
|
|
2188
|
+
source_default.white("Deploy from local source? (y/n): "),
|
|
2189
|
+
"y"
|
|
2190
|
+
);
|
|
2191
|
+
if (!shouldDeploy) {
|
|
2192
|
+
console.log(source_default.gray("Deployment cancelled."));
|
|
2193
|
+
process.exit(0);
|
|
2194
|
+
}
|
|
2195
|
+
console.log();
|
|
2196
|
+
console.log(source_default.gray("Packaging source code..."));
|
|
2197
|
+
const tarballPath = await createTarball(cwd);
|
|
2198
|
+
const stats = await fs8.stat(tarballPath);
|
|
493
2199
|
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
|
-
)
|
|
2200
|
+
source_default.green("\u2713 Packaged: ") + source_default.gray(formatFileSize(stats.size))
|
|
497
2201
|
);
|
|
498
|
-
|
|
2202
|
+
const maxSize = 2 * 1024 * 1024;
|
|
2203
|
+
if (stats.size > maxSize) {
|
|
2204
|
+
console.log(
|
|
2205
|
+
source_default.red(
|
|
2206
|
+
`\u2717 File size (${formatFileSize(stats.size)}) exceeds maximum of 2MB`
|
|
2207
|
+
)
|
|
2208
|
+
);
|
|
2209
|
+
await fs8.unlink(tarballPath);
|
|
2210
|
+
process.exit(1);
|
|
2211
|
+
}
|
|
2212
|
+
const deploymentRequest = {
|
|
2213
|
+
name: projectName,
|
|
2214
|
+
source: {
|
|
2215
|
+
type: "upload",
|
|
2216
|
+
runtime,
|
|
2217
|
+
port,
|
|
2218
|
+
buildCommand,
|
|
2219
|
+
startCommand
|
|
2220
|
+
},
|
|
2221
|
+
healthCheckPath: "/healthz"
|
|
2222
|
+
};
|
|
2223
|
+
console.log(source_default.gray("Creating deployment..."));
|
|
2224
|
+
const api = await McpUseAPI.create();
|
|
2225
|
+
const deployment = await api.createDeploymentWithUpload(
|
|
2226
|
+
deploymentRequest,
|
|
2227
|
+
tarballPath
|
|
2228
|
+
);
|
|
2229
|
+
await fs8.unlink(tarballPath);
|
|
2230
|
+
console.log(
|
|
2231
|
+
source_default.green("\u2713 Deployment created: ") + source_default.gray(deployment.id)
|
|
2232
|
+
);
|
|
2233
|
+
await displayDeploymentProgress(api, deployment);
|
|
2234
|
+
if (options.open && deployment.domain) {
|
|
2235
|
+
console.log();
|
|
2236
|
+
console.log(source_default.gray("Opening deployment in browser..."));
|
|
2237
|
+
await open_default(`https://${deployment.domain}`);
|
|
2238
|
+
}
|
|
499
2239
|
}
|
|
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
2240
|
} catch (error) {
|
|
550
2241
|
console.error(
|
|
551
|
-
|
|
552
|
-
|
|
2242
|
+
source_default.red.bold("\n\u2717 Deployment failed:"),
|
|
2243
|
+
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
553
2244
|
);
|
|
554
2245
|
process.exit(1);
|
|
555
2246
|
}
|
|
556
2247
|
}
|
|
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);
|
|
2248
|
+
|
|
2249
|
+
// src/commands/client.ts
|
|
2250
|
+
import { Command } from "commander";
|
|
2251
|
+
import { createInterface } from "readline";
|
|
2252
|
+
import { MCPClient } from "mcp-use/client";
|
|
2253
|
+
|
|
2254
|
+
// src/utils/session-storage.ts
|
|
2255
|
+
import { homedir } from "os";
|
|
2256
|
+
import { join } from "path";
|
|
2257
|
+
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
2258
|
+
import { existsSync } from "fs";
|
|
2259
|
+
var SESSION_FILE_PATH = join(homedir(), ".mcp-use", "cli-sessions.json");
|
|
2260
|
+
async function ensureSessionDir() {
|
|
2261
|
+
const dir = join(homedir(), ".mcp-use");
|
|
2262
|
+
if (!existsSync(dir)) {
|
|
2263
|
+
await mkdir(dir, { recursive: true });
|
|
577
2264
|
}
|
|
578
2265
|
}
|
|
579
|
-
async function
|
|
2266
|
+
async function loadSessions() {
|
|
580
2267
|
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));
|
|
2268
|
+
await ensureSessionDir();
|
|
2269
|
+
if (!existsSync(SESSION_FILE_PATH)) {
|
|
2270
|
+
return { activeSession: null, sessions: {} };
|
|
597
2271
|
}
|
|
2272
|
+
const content = await readFile(SESSION_FILE_PATH, "utf-8");
|
|
2273
|
+
return JSON.parse(content);
|
|
598
2274
|
} 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);
|
|
2275
|
+
return { activeSession: null, sessions: {} };
|
|
604
2276
|
}
|
|
605
2277
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
2278
|
+
async function saveSessions(storage) {
|
|
2279
|
+
await ensureSessionDir();
|
|
2280
|
+
await writeFile(SESSION_FILE_PATH, JSON.stringify(storage, null, 2), "utf-8");
|
|
2281
|
+
}
|
|
2282
|
+
async function saveSession(name, config) {
|
|
2283
|
+
const storage = await loadSessions();
|
|
2284
|
+
storage.sessions[name] = {
|
|
2285
|
+
...config,
|
|
2286
|
+
lastUsed: (/* @__PURE__ */ new Date()).toISOString()
|
|
2287
|
+
};
|
|
2288
|
+
if (!storage.activeSession) {
|
|
2289
|
+
storage.activeSession = name;
|
|
2290
|
+
}
|
|
2291
|
+
await saveSessions(storage);
|
|
2292
|
+
}
|
|
2293
|
+
async function getActiveSession() {
|
|
2294
|
+
const storage = await loadSessions();
|
|
2295
|
+
if (!storage.activeSession || !storage.sessions[storage.activeSession]) {
|
|
624
2296
|
return null;
|
|
625
2297
|
}
|
|
2298
|
+
return {
|
|
2299
|
+
name: storage.activeSession,
|
|
2300
|
+
config: storage.sessions[storage.activeSession]
|
|
2301
|
+
};
|
|
626
2302
|
}
|
|
627
|
-
async function
|
|
628
|
-
const
|
|
629
|
-
return
|
|
2303
|
+
async function getSession(name) {
|
|
2304
|
+
const storage = await loadSessions();
|
|
2305
|
+
return storage.sessions[name] || null;
|
|
630
2306
|
}
|
|
631
|
-
async function
|
|
632
|
-
|
|
2307
|
+
async function setActiveSession(name) {
|
|
2308
|
+
const storage = await loadSessions();
|
|
2309
|
+
if (!storage.sessions[name]) {
|
|
2310
|
+
throw new Error(`Session '${name}' not found`);
|
|
2311
|
+
}
|
|
2312
|
+
storage.activeSession = name;
|
|
2313
|
+
storage.sessions[name].lastUsed = (/* @__PURE__ */ new Date()).toISOString();
|
|
2314
|
+
await saveSessions(storage);
|
|
633
2315
|
}
|
|
634
|
-
function
|
|
635
|
-
const
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
2316
|
+
async function listAllSessions() {
|
|
2317
|
+
const storage = await loadSessions();
|
|
2318
|
+
return Object.entries(storage.sessions).map(([name, config]) => ({
|
|
2319
|
+
name,
|
|
2320
|
+
config,
|
|
2321
|
+
isActive: name === storage.activeSession
|
|
2322
|
+
}));
|
|
2323
|
+
}
|
|
2324
|
+
async function updateSessionInfo(name, serverInfo, capabilities) {
|
|
2325
|
+
const storage = await loadSessions();
|
|
2326
|
+
if (storage.sessions[name]) {
|
|
2327
|
+
storage.sessions[name].serverInfo = serverInfo;
|
|
2328
|
+
storage.sessions[name].capabilities = capabilities;
|
|
2329
|
+
storage.sessions[name].lastUsed = (/* @__PURE__ */ new Date()).toISOString();
|
|
2330
|
+
await saveSessions(storage);
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
|
|
2334
|
+
// src/utils/format.ts
|
|
2335
|
+
function formatTable(data, columns) {
|
|
2336
|
+
if (data.length === 0) {
|
|
2337
|
+
return source_default.gray("No items found");
|
|
2338
|
+
}
|
|
2339
|
+
const widths = columns.map((col) => {
|
|
2340
|
+
const maxDataWidth = Math.max(
|
|
2341
|
+
...data.map((row) => String(row[col.key] || "").length)
|
|
2342
|
+
);
|
|
2343
|
+
const headerWidth = col.header.length;
|
|
2344
|
+
return col.width || Math.max(maxDataWidth, headerWidth, 10);
|
|
2345
|
+
});
|
|
2346
|
+
const createRow = (values, bold = false) => {
|
|
2347
|
+
const cells = values.map((val, i) => {
|
|
2348
|
+
const padded = val.padEnd(widths[i]);
|
|
2349
|
+
return bold ? source_default.bold(padded) : padded;
|
|
2350
|
+
});
|
|
2351
|
+
return `\u2502 ${cells.join(" \u2502 ")} \u2502`;
|
|
644
2352
|
};
|
|
2353
|
+
const separator = (char) => {
|
|
2354
|
+
const parts = widths.map((w) => char.repeat(w + 2));
|
|
2355
|
+
if (char === "\u2500") {
|
|
2356
|
+
return `\u251C${parts.join("\u253C")}\u2524`;
|
|
2357
|
+
}
|
|
2358
|
+
return `\u2514${parts.join("\u2534")}\u2518`;
|
|
2359
|
+
};
|
|
2360
|
+
const lines = [];
|
|
2361
|
+
lines.push(`\u250C${widths.map((w) => "\u2500".repeat(w + 2)).join("\u252C")}\u2510`);
|
|
2362
|
+
lines.push(
|
|
2363
|
+
createRow(
|
|
2364
|
+
columns.map((c) => c.header),
|
|
2365
|
+
true
|
|
2366
|
+
)
|
|
2367
|
+
);
|
|
2368
|
+
lines.push(separator("\u2500"));
|
|
2369
|
+
data.forEach((row) => {
|
|
2370
|
+
lines.push(createRow(columns.map((c) => String(row[c.key] || ""))));
|
|
2371
|
+
});
|
|
2372
|
+
lines.push(separator("\u2500"));
|
|
2373
|
+
return lines.join("\n");
|
|
645
2374
|
}
|
|
646
|
-
|
|
647
|
-
|
|
2375
|
+
function formatJson(data, pretty = true) {
|
|
2376
|
+
if (pretty) {
|
|
2377
|
+
return JSON.stringify(data, null, 2);
|
|
2378
|
+
}
|
|
2379
|
+
return JSON.stringify(data);
|
|
648
2380
|
}
|
|
649
|
-
|
|
650
|
-
|
|
2381
|
+
function formatToolCall(result) {
|
|
2382
|
+
const lines = [];
|
|
2383
|
+
if (result.isError) {
|
|
2384
|
+
lines.push(source_default.red("\u2717 Tool execution failed"));
|
|
2385
|
+
lines.push("");
|
|
2386
|
+
} else {
|
|
2387
|
+
lines.push(source_default.green("\u2713 Tool executed successfully"));
|
|
2388
|
+
lines.push("");
|
|
2389
|
+
}
|
|
2390
|
+
if (result.content && result.content.length > 0) {
|
|
2391
|
+
result.content.forEach((item, index) => {
|
|
2392
|
+
if (result.content.length > 1) {
|
|
2393
|
+
lines.push(source_default.bold(`Content ${index + 1}:`));
|
|
2394
|
+
}
|
|
2395
|
+
if (item.type === "text") {
|
|
2396
|
+
lines.push(item.text);
|
|
2397
|
+
} else if (item.type === "image") {
|
|
2398
|
+
lines.push(source_default.cyan(`[Image: ${item.mimeType || "unknown type"}]`));
|
|
2399
|
+
if (item.data) {
|
|
2400
|
+
lines.push(source_default.gray(`Data: ${item.data.substring(0, 50)}...`));
|
|
2401
|
+
}
|
|
2402
|
+
} else if (item.type === "resource") {
|
|
2403
|
+
lines.push(source_default.cyan(`[Resource]`));
|
|
2404
|
+
if (item.resource?.uri) {
|
|
2405
|
+
lines.push(source_default.gray(`URI: ${item.resource.uri}`));
|
|
2406
|
+
}
|
|
2407
|
+
if (item.resource && "text" in item.resource && item.resource.text) {
|
|
2408
|
+
lines.push(item.resource.text);
|
|
2409
|
+
}
|
|
2410
|
+
} else {
|
|
2411
|
+
lines.push(source_default.gray(`[Unknown content type: ${item.type}]`));
|
|
2412
|
+
}
|
|
2413
|
+
if (index < result.content.length - 1) {
|
|
2414
|
+
lines.push("");
|
|
2415
|
+
}
|
|
2416
|
+
});
|
|
2417
|
+
}
|
|
2418
|
+
return lines.join("\n");
|
|
651
2419
|
}
|
|
652
|
-
|
|
653
|
-
|
|
2420
|
+
function formatResourceContent(content) {
|
|
2421
|
+
if (!content || !content.contents) {
|
|
2422
|
+
return source_default.gray("No content");
|
|
2423
|
+
}
|
|
2424
|
+
const lines = [];
|
|
2425
|
+
content.contents.forEach((item, index) => {
|
|
2426
|
+
if (content.contents.length > 1) {
|
|
2427
|
+
lines.push(source_default.bold(`Content ${index + 1}:`));
|
|
2428
|
+
}
|
|
2429
|
+
if (item.uri) {
|
|
2430
|
+
lines.push(source_default.gray(`URI: ${item.uri}`));
|
|
2431
|
+
}
|
|
2432
|
+
if (item.mimeType) {
|
|
2433
|
+
lines.push(source_default.gray(`Type: ${item.mimeType}`));
|
|
2434
|
+
}
|
|
2435
|
+
if ("text" in item && item.text) {
|
|
2436
|
+
lines.push("");
|
|
2437
|
+
lines.push(item.text);
|
|
2438
|
+
} else if ("blob" in item && item.blob) {
|
|
2439
|
+
lines.push("");
|
|
2440
|
+
lines.push(source_default.cyan(`[Binary data: ${item.blob.length} bytes]`));
|
|
2441
|
+
}
|
|
2442
|
+
if (index < content.contents.length - 1) {
|
|
2443
|
+
lines.push("");
|
|
2444
|
+
lines.push(source_default.gray("\u2500".repeat(50)));
|
|
2445
|
+
lines.push("");
|
|
2446
|
+
}
|
|
2447
|
+
});
|
|
2448
|
+
return lines.join("\n");
|
|
654
2449
|
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
return { isGitRepo: false };
|
|
2450
|
+
function formatSchema(schema, indent = 0) {
|
|
2451
|
+
if (!schema) {
|
|
2452
|
+
return source_default.gray("No schema");
|
|
659
2453
|
}
|
|
660
|
-
const
|
|
661
|
-
const
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
2454
|
+
const lines = [];
|
|
2455
|
+
const pad = " ".repeat(indent);
|
|
2456
|
+
if (schema.type === "object" && schema.properties) {
|
|
2457
|
+
Object.entries(schema.properties).forEach(([key, value]) => {
|
|
2458
|
+
const required = schema.required?.includes(key);
|
|
2459
|
+
const type = value.type || "any";
|
|
2460
|
+
const desc = value.description || "";
|
|
2461
|
+
const keyStr = required ? source_default.bold(key) : key;
|
|
2462
|
+
const typeStr = source_default.cyan(`(${type})`);
|
|
2463
|
+
const requiredStr = required ? source_default.red(" *required") : "";
|
|
2464
|
+
lines.push(`${pad}${keyStr} ${typeStr}${requiredStr}`);
|
|
2465
|
+
if (desc) {
|
|
2466
|
+
lines.push(`${pad} ${source_default.gray(desc)}`);
|
|
2467
|
+
}
|
|
2468
|
+
if (value.type === "object" && value.properties) {
|
|
2469
|
+
lines.push(formatSchema(value, indent + 1));
|
|
2470
|
+
}
|
|
2471
|
+
if (value.type === "array" && value.items) {
|
|
2472
|
+
lines.push(`${pad} ${source_default.gray("Items:")}`);
|
|
2473
|
+
if (value.items.type === "object") {
|
|
2474
|
+
lines.push(formatSchema(value.items, indent + 2));
|
|
2475
|
+
} else {
|
|
2476
|
+
lines.push(
|
|
2477
|
+
`${pad} ${source_default.cyan(`(${value.items.type || "any"})`)}`
|
|
2478
|
+
);
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
});
|
|
2482
|
+
} else {
|
|
2483
|
+
lines.push(`${pad}${source_default.cyan(`Type: ${schema.type || "any"}`)}`);
|
|
2484
|
+
if (schema.description) {
|
|
2485
|
+
lines.push(`${pad}${source_default.gray(schema.description)}`);
|
|
671
2486
|
}
|
|
672
2487
|
}
|
|
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
|
-
};
|
|
2488
|
+
return lines.join("\n");
|
|
682
2489
|
}
|
|
683
|
-
function
|
|
684
|
-
|
|
2490
|
+
function formatError(error) {
|
|
2491
|
+
const message = typeof error === "string" ? error : error.message;
|
|
2492
|
+
return source_default.red(`\u2717 Error: ${message}`);
|
|
685
2493
|
}
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
2494
|
+
function formatSuccess(message) {
|
|
2495
|
+
return source_default.green(`\u2713 ${message}`);
|
|
2496
|
+
}
|
|
2497
|
+
function formatInfo(message) {
|
|
2498
|
+
return source_default.cyan(message);
|
|
2499
|
+
}
|
|
2500
|
+
function formatWarning(message) {
|
|
2501
|
+
return source_default.yellow(`\u26A0 ${message}`);
|
|
2502
|
+
}
|
|
2503
|
+
function formatHeader(text) {
|
|
2504
|
+
return source_default.bold.white(text);
|
|
2505
|
+
}
|
|
2506
|
+
function formatKeyValue(pairs) {
|
|
2507
|
+
const maxKeyLength = Math.max(...Object.keys(pairs).map((k) => k.length), 0);
|
|
2508
|
+
return Object.entries(pairs).map(([key, value]) => {
|
|
2509
|
+
const paddedKey = key.padEnd(maxKeyLength);
|
|
2510
|
+
return ` ${source_default.gray(paddedKey)}: ${value}`;
|
|
2511
|
+
}).join("\n");
|
|
2512
|
+
}
|
|
2513
|
+
function formatPromptMessages(messages) {
|
|
2514
|
+
if (!messages || messages.length === 0) {
|
|
2515
|
+
return source_default.gray("No messages");
|
|
700
2516
|
}
|
|
2517
|
+
const lines = [];
|
|
2518
|
+
messages.forEach((msg, index) => {
|
|
2519
|
+
const role = msg.role || "unknown";
|
|
2520
|
+
const roleStr = role === "user" ? source_default.blue("[User]") : role === "assistant" ? source_default.green("[Assistant]") : source_default.gray(`[${role}]`);
|
|
2521
|
+
lines.push(`${roleStr}`);
|
|
2522
|
+
if (msg.content) {
|
|
2523
|
+
if (typeof msg.content === "string") {
|
|
2524
|
+
lines.push(msg.content);
|
|
2525
|
+
} else if (msg.content.type === "text") {
|
|
2526
|
+
lines.push(msg.content.text);
|
|
2527
|
+
} else if (msg.content.type === "image") {
|
|
2528
|
+
lines.push(source_default.cyan(`[Image: ${msg.content.mimeType}]`));
|
|
2529
|
+
} else if (msg.content.type === "resource") {
|
|
2530
|
+
lines.push(source_default.cyan(`[Resource: ${msg.content.resource?.uri}]`));
|
|
2531
|
+
if (msg.content.resource?.text) {
|
|
2532
|
+
lines.push(msg.content.resource.text);
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
if (index < messages.length - 1) {
|
|
2537
|
+
lines.push("");
|
|
2538
|
+
}
|
|
2539
|
+
});
|
|
2540
|
+
return lines.join("\n");
|
|
701
2541
|
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
2542
|
+
|
|
2543
|
+
// src/commands/client.ts
|
|
2544
|
+
var activeSessions = /* @__PURE__ */ new Map();
|
|
2545
|
+
async function getOrRestoreSession(sessionName) {
|
|
2546
|
+
if (!sessionName) {
|
|
2547
|
+
const active = await getActiveSession();
|
|
2548
|
+
if (!active) {
|
|
2549
|
+
console.error(
|
|
2550
|
+
formatError("No active session. Connect to a server first.")
|
|
2551
|
+
);
|
|
2552
|
+
console.error(
|
|
2553
|
+
formatInfo("Use: npx mcp-use client connect <url> --name <name>")
|
|
2554
|
+
);
|
|
2555
|
+
return null;
|
|
709
2556
|
}
|
|
710
|
-
|
|
2557
|
+
sessionName = active.name;
|
|
2558
|
+
}
|
|
2559
|
+
if (activeSessions.has(sessionName)) {
|
|
2560
|
+
const { session } = activeSessions.get(sessionName);
|
|
2561
|
+
return { name: sessionName, session };
|
|
2562
|
+
}
|
|
2563
|
+
const config = await getSession(sessionName);
|
|
2564
|
+
if (!config) {
|
|
2565
|
+
console.error(formatError(`Session '${sessionName}' not found`));
|
|
2566
|
+
return null;
|
|
711
2567
|
}
|
|
712
|
-
return import_node_path2.default.basename(cwd);
|
|
713
|
-
}
|
|
714
|
-
async function detectBuildCommand(cwd = process.cwd()) {
|
|
715
2568
|
try {
|
|
716
|
-
const
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
2569
|
+
const client = new MCPClient();
|
|
2570
|
+
if (config.type === "http") {
|
|
2571
|
+
client.addServer(sessionName, {
|
|
2572
|
+
url: config.url,
|
|
2573
|
+
headers: config.authToken ? { Authorization: `Bearer ${config.authToken}` } : void 0
|
|
2574
|
+
});
|
|
2575
|
+
} else if (config.type === "stdio") {
|
|
2576
|
+
client.addServer(sessionName, {
|
|
2577
|
+
command: config.command,
|
|
2578
|
+
args: config.args || [],
|
|
2579
|
+
env: config.env
|
|
2580
|
+
});
|
|
2581
|
+
} else {
|
|
2582
|
+
console.error(formatError(`Unknown session type: ${config.type}`));
|
|
2583
|
+
return null;
|
|
721
2584
|
}
|
|
722
|
-
|
|
2585
|
+
const session = await client.createSession(sessionName);
|
|
2586
|
+
activeSessions.set(sessionName, { client, session });
|
|
2587
|
+
console.error(formatInfo(`Reconnected to session '${sessionName}'`));
|
|
2588
|
+
return { name: sessionName, session };
|
|
2589
|
+
} catch (error) {
|
|
2590
|
+
console.error(formatError(`Failed to restore session: ${error.message}`));
|
|
2591
|
+
return null;
|
|
723
2592
|
}
|
|
724
|
-
return void 0;
|
|
725
2593
|
}
|
|
726
|
-
async function
|
|
2594
|
+
async function connectCommand(urlOrCommand, options) {
|
|
727
2595
|
try {
|
|
728
|
-
const
|
|
729
|
-
const
|
|
730
|
-
|
|
731
|
-
if (
|
|
732
|
-
|
|
2596
|
+
const sessionName = options.name || `session-${Date.now()}`;
|
|
2597
|
+
const client = new MCPClient();
|
|
2598
|
+
let session;
|
|
2599
|
+
if (options.stdio) {
|
|
2600
|
+
const parts = urlOrCommand.split(" ");
|
|
2601
|
+
const command = parts[0];
|
|
2602
|
+
const args = parts.slice(1);
|
|
2603
|
+
console.error(
|
|
2604
|
+
formatInfo(`Connecting to stdio server: ${command} ${args.join(" ")}`)
|
|
2605
|
+
);
|
|
2606
|
+
client.addServer(sessionName, {
|
|
2607
|
+
command,
|
|
2608
|
+
args
|
|
2609
|
+
});
|
|
2610
|
+
session = await client.createSession(sessionName);
|
|
2611
|
+
await saveSession(sessionName, {
|
|
2612
|
+
type: "stdio",
|
|
2613
|
+
command,
|
|
2614
|
+
args,
|
|
2615
|
+
lastUsed: (/* @__PURE__ */ new Date()).toISOString()
|
|
2616
|
+
});
|
|
2617
|
+
} else {
|
|
2618
|
+
console.error(formatInfo(`Connecting to ${urlOrCommand}...`));
|
|
2619
|
+
client.addServer(sessionName, {
|
|
2620
|
+
url: urlOrCommand,
|
|
2621
|
+
headers: options.auth ? { Authorization: `Bearer ${options.auth}` } : void 0
|
|
2622
|
+
});
|
|
2623
|
+
session = await client.createSession(sessionName);
|
|
2624
|
+
await saveSession(sessionName, {
|
|
2625
|
+
type: "http",
|
|
2626
|
+
url: urlOrCommand,
|
|
2627
|
+
authToken: options.auth,
|
|
2628
|
+
lastUsed: (/* @__PURE__ */ new Date()).toISOString()
|
|
2629
|
+
});
|
|
733
2630
|
}
|
|
734
|
-
|
|
735
|
-
|
|
2631
|
+
activeSessions.set(sessionName, { client, session });
|
|
2632
|
+
const serverInfo = session.serverInfo;
|
|
2633
|
+
const capabilities = session.serverCapabilities;
|
|
2634
|
+
if (serverInfo) {
|
|
2635
|
+
await updateSessionInfo(sessionName, serverInfo, capabilities);
|
|
736
2636
|
}
|
|
737
|
-
|
|
2637
|
+
console.log(formatSuccess(`Connected to ${sessionName}`));
|
|
2638
|
+
if (serverInfo) {
|
|
2639
|
+
console.log("");
|
|
2640
|
+
console.log(formatHeader("Server Information:"));
|
|
2641
|
+
console.log(
|
|
2642
|
+
formatKeyValue({
|
|
2643
|
+
Name: serverInfo.name,
|
|
2644
|
+
Version: serverInfo.version || "unknown"
|
|
2645
|
+
})
|
|
2646
|
+
);
|
|
2647
|
+
}
|
|
2648
|
+
if (capabilities) {
|
|
2649
|
+
console.log("");
|
|
2650
|
+
console.log(formatHeader("Capabilities:"));
|
|
2651
|
+
const caps = Object.keys(capabilities).join(", ");
|
|
2652
|
+
console.log(` ${caps || "none"}`);
|
|
2653
|
+
}
|
|
2654
|
+
const tools = session.tools;
|
|
2655
|
+
console.log("");
|
|
2656
|
+
console.log(
|
|
2657
|
+
formatInfo(
|
|
2658
|
+
`Available: ${tools.length} tool${tools.length !== 1 ? "s" : ""}`
|
|
2659
|
+
)
|
|
2660
|
+
);
|
|
2661
|
+
} catch (error) {
|
|
2662
|
+
console.error(formatError(`Connection failed: ${error.message}`));
|
|
2663
|
+
process.exit(1);
|
|
738
2664
|
}
|
|
739
|
-
return void 0;
|
|
740
2665
|
}
|
|
741
|
-
async function
|
|
2666
|
+
async function disconnectCommand(sessionName, options) {
|
|
742
2667
|
try {
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
}
|
|
749
|
-
|
|
2668
|
+
if (options?.all) {
|
|
2669
|
+
for (const [name, { client }] of activeSessions.entries()) {
|
|
2670
|
+
await client.closeAllSessions();
|
|
2671
|
+
activeSessions.delete(name);
|
|
2672
|
+
console.log(formatSuccess(`Disconnected from ${name}`));
|
|
2673
|
+
}
|
|
2674
|
+
return;
|
|
2675
|
+
}
|
|
2676
|
+
if (!sessionName) {
|
|
2677
|
+
const active = await getActiveSession();
|
|
2678
|
+
if (!active) {
|
|
2679
|
+
console.error(formatError("No active session to disconnect"));
|
|
2680
|
+
return;
|
|
750
2681
|
}
|
|
2682
|
+
sessionName = active.name;
|
|
751
2683
|
}
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
2684
|
+
const sessionData = activeSessions.get(sessionName);
|
|
2685
|
+
if (sessionData) {
|
|
2686
|
+
await sessionData.client.closeAllSessions();
|
|
2687
|
+
activeSessions.delete(sessionName);
|
|
2688
|
+
console.log(formatSuccess(`Disconnected from ${sessionName}`));
|
|
2689
|
+
} else {
|
|
2690
|
+
console.log(formatInfo(`Session '${sessionName}' is not connected`));
|
|
756
2691
|
}
|
|
757
|
-
} catch {
|
|
2692
|
+
} catch (error) {
|
|
2693
|
+
console.error(formatError(`Failed to disconnect: ${error.message}`));
|
|
2694
|
+
process.exit(1);
|
|
758
2695
|
}
|
|
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
2696
|
}
|
|
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`;
|
|
2697
|
+
async function listSessionsCommand() {
|
|
807
2698
|
try {
|
|
808
|
-
await
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
2699
|
+
const sessions = await listAllSessions();
|
|
2700
|
+
if (sessions.length === 0) {
|
|
2701
|
+
console.log(formatInfo("No saved sessions"));
|
|
2702
|
+
console.log(
|
|
2703
|
+
formatInfo("Connect to a server with: npx mcp-use client connect <url>")
|
|
2704
|
+
);
|
|
2705
|
+
return;
|
|
2706
|
+
}
|
|
2707
|
+
console.log(formatHeader("Saved Sessions:"));
|
|
2708
|
+
console.log("");
|
|
2709
|
+
const tableData = sessions.map((s) => ({
|
|
2710
|
+
name: s.isActive ? source_default.green.bold(`${s.name} *`) : s.name,
|
|
2711
|
+
type: s.config.type,
|
|
2712
|
+
target: s.config.type === "http" ? s.config.url || "" : `${s.config.command} ${(s.config.args || []).join(" ")}`,
|
|
2713
|
+
server: s.config.serverInfo?.name || "unknown",
|
|
2714
|
+
status: activeSessions.has(s.name) ? source_default.green("connected") : source_default.gray("disconnected")
|
|
2715
|
+
}));
|
|
2716
|
+
console.log(
|
|
2717
|
+
formatTable(tableData, [
|
|
2718
|
+
{ key: "name", header: "Name" },
|
|
2719
|
+
{ key: "type", header: "Type" },
|
|
2720
|
+
{ key: "target", header: "Target", width: 40 },
|
|
2721
|
+
{ key: "server", header: "Server" },
|
|
2722
|
+
{ key: "status", header: "Status" }
|
|
2723
|
+
])
|
|
813
2724
|
);
|
|
2725
|
+
console.log("");
|
|
2726
|
+
console.log(source_default.gray("* = active session"));
|
|
2727
|
+
} catch (error) {
|
|
2728
|
+
console.error(formatError(`Failed to list sessions: ${error.message}`));
|
|
2729
|
+
process.exit(1);
|
|
814
2730
|
}
|
|
815
2731
|
}
|
|
816
|
-
function
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
2732
|
+
async function switchSessionCommand(name) {
|
|
2733
|
+
try {
|
|
2734
|
+
await setActiveSession(name);
|
|
2735
|
+
console.log(formatSuccess(`Switched to session '${name}'`));
|
|
2736
|
+
} catch (error) {
|
|
2737
|
+
console.error(formatError(`Failed to switch session: ${error.message}`));
|
|
2738
|
+
process.exit(1);
|
|
2739
|
+
}
|
|
822
2740
|
}
|
|
823
|
-
async function
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
if (
|
|
830
|
-
|
|
2741
|
+
async function listToolsCommand(options) {
|
|
2742
|
+
try {
|
|
2743
|
+
const result = await getOrRestoreSession(options.session || null);
|
|
2744
|
+
if (!result) return;
|
|
2745
|
+
const { session } = result;
|
|
2746
|
+
const tools = await session.listTools();
|
|
2747
|
+
if (options.json) {
|
|
2748
|
+
console.log(formatJson(tools));
|
|
2749
|
+
return;
|
|
831
2750
|
}
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
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");
|
|
2751
|
+
if (tools.length === 0) {
|
|
2752
|
+
console.log(formatInfo("No tools available"));
|
|
2753
|
+
return;
|
|
846
2754
|
}
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
2755
|
+
console.log(formatHeader(`Available Tools (${tools.length}):`));
|
|
2756
|
+
console.log("");
|
|
2757
|
+
const tableData = tools.map((tool) => ({
|
|
2758
|
+
name: source_default.bold(tool.name),
|
|
2759
|
+
description: tool.description || source_default.gray("No description")
|
|
2760
|
+
}));
|
|
2761
|
+
console.log(
|
|
2762
|
+
formatTable(tableData, [
|
|
2763
|
+
{ key: "name", header: "Tool", width: 25 },
|
|
2764
|
+
{ key: "description", header: "Description", width: 50 }
|
|
2765
|
+
])
|
|
2766
|
+
);
|
|
2767
|
+
} catch (error) {
|
|
2768
|
+
console.error(formatError(`Failed to list tools: ${error.message}`));
|
|
2769
|
+
process.exit(1);
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2772
|
+
async function describeToolCommand(toolName, options) {
|
|
850
2773
|
try {
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
}
|
|
2774
|
+
const result = await getOrRestoreSession(options.session || null);
|
|
2775
|
+
if (!result) return;
|
|
2776
|
+
const { session } = result;
|
|
2777
|
+
const tools = session.tools;
|
|
2778
|
+
const tool = tools.find((t) => t.name === toolName);
|
|
2779
|
+
if (!tool) {
|
|
2780
|
+
console.error(formatError(`Tool '${toolName}' not found`));
|
|
2781
|
+
console.log("");
|
|
2782
|
+
console.log(formatInfo("Available tools:"));
|
|
2783
|
+
tools.forEach((t) => console.log(` \u2022 ${t.name}`));
|
|
2784
|
+
return;
|
|
2785
|
+
}
|
|
2786
|
+
console.log(formatHeader(`Tool: ${tool.name}`));
|
|
2787
|
+
console.log("");
|
|
2788
|
+
if (tool.description) {
|
|
2789
|
+
console.log(tool.description);
|
|
2790
|
+
console.log("");
|
|
2791
|
+
}
|
|
2792
|
+
if (tool.inputSchema) {
|
|
2793
|
+
console.log(formatHeader("Input Schema:"));
|
|
2794
|
+
console.log(formatSchema(tool.inputSchema));
|
|
873
2795
|
}
|
|
874
2796
|
} catch (error) {
|
|
875
|
-
|
|
2797
|
+
console.error(formatError(`Failed to describe tool: ${error.message}`));
|
|
2798
|
+
process.exit(1);
|
|
876
2799
|
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
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;
|
|
904
|
-
}
|
|
905
|
-
if (finalDeployment.status === "running") {
|
|
906
|
-
const mcpUrl = `https://${finalDeployment.domain}/mcp`;
|
|
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
|
-
);
|
|
928
|
-
return;
|
|
929
|
-
} else if (finalDeployment.status === "failed") {
|
|
930
|
-
console.log(import_chalk2.default.red.bold("\u2717 Deployment failed\n"));
|
|
931
|
-
if (finalDeployment.error) {
|
|
932
|
-
console.log(import_chalk2.default.red("Error: ") + finalDeployment.error);
|
|
2800
|
+
}
|
|
2801
|
+
async function callToolCommand(toolName, argsJson, options) {
|
|
2802
|
+
try {
|
|
2803
|
+
const result = await getOrRestoreSession(options?.session || null);
|
|
2804
|
+
if (!result) return;
|
|
2805
|
+
const { session } = result;
|
|
2806
|
+
let args = {};
|
|
2807
|
+
if (argsJson) {
|
|
2808
|
+
try {
|
|
2809
|
+
args = JSON.parse(argsJson);
|
|
2810
|
+
} catch (error) {
|
|
2811
|
+
console.error(formatError("Invalid JSON arguments"));
|
|
2812
|
+
return;
|
|
933
2813
|
}
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
2814
|
+
} else {
|
|
2815
|
+
const tools = session.tools;
|
|
2816
|
+
const tool = tools.find((t) => t.name === toolName);
|
|
2817
|
+
if (tool?.inputSchema?.required && tool.inputSchema.required.length > 0) {
|
|
2818
|
+
console.error(
|
|
2819
|
+
formatError(
|
|
2820
|
+
"This tool requires arguments. Provide them as a JSON string."
|
|
2821
|
+
)
|
|
2822
|
+
);
|
|
2823
|
+
console.log("");
|
|
2824
|
+
console.log(formatInfo("Example:"));
|
|
2825
|
+
console.log(
|
|
2826
|
+
` npx mcp-use client tools call ${toolName} '{"param": "value"}'`
|
|
2827
|
+
);
|
|
2828
|
+
console.log("");
|
|
2829
|
+
console.log(formatInfo("Tool schema:"));
|
|
2830
|
+
console.log(formatSchema(tool.inputSchema));
|
|
2831
|
+
return;
|
|
951
2832
|
}
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
2833
|
+
}
|
|
2834
|
+
console.error(formatInfo(`Calling tool '${toolName}'...`));
|
|
2835
|
+
const callResult = await session.callTool(toolName, args, {
|
|
2836
|
+
timeout: options?.timeout
|
|
2837
|
+
});
|
|
2838
|
+
if (options?.json) {
|
|
2839
|
+
console.log(formatJson(callResult));
|
|
957
2840
|
} else {
|
|
958
|
-
console.log(
|
|
959
|
-
|
|
960
|
-
|
|
2841
|
+
console.log(formatToolCall(callResult));
|
|
2842
|
+
}
|
|
2843
|
+
} catch (error) {
|
|
2844
|
+
console.error(formatError(`Failed to call tool: ${error.message}`));
|
|
2845
|
+
process.exit(1);
|
|
2846
|
+
}
|
|
2847
|
+
}
|
|
2848
|
+
async function listResourcesCommand(options) {
|
|
2849
|
+
try {
|
|
2850
|
+
const result = await getOrRestoreSession(options.session || null);
|
|
2851
|
+
if (!result) return;
|
|
2852
|
+
const { session } = result;
|
|
2853
|
+
const resourcesResult = await session.listAllResources();
|
|
2854
|
+
const resources = resourcesResult.resources;
|
|
2855
|
+
if (options.json) {
|
|
2856
|
+
console.log(formatJson(resources));
|
|
961
2857
|
return;
|
|
962
2858
|
}
|
|
2859
|
+
if (resources.length === 0) {
|
|
2860
|
+
console.log(formatInfo("No resources available"));
|
|
2861
|
+
return;
|
|
2862
|
+
}
|
|
2863
|
+
console.log(formatHeader(`Available Resources (${resources.length}):`));
|
|
2864
|
+
console.log("");
|
|
2865
|
+
const tableData = resources.map((resource) => ({
|
|
2866
|
+
uri: resource.uri,
|
|
2867
|
+
name: resource.name || source_default.gray("(no name)"),
|
|
2868
|
+
type: resource.mimeType || source_default.gray("unknown")
|
|
2869
|
+
}));
|
|
2870
|
+
console.log(
|
|
2871
|
+
formatTable(tableData, [
|
|
2872
|
+
{ key: "uri", header: "URI", width: 40 },
|
|
2873
|
+
{ key: "name", header: "Name", width: 20 },
|
|
2874
|
+
{ key: "type", header: "Type", width: 15 }
|
|
2875
|
+
])
|
|
2876
|
+
);
|
|
2877
|
+
} catch (error) {
|
|
2878
|
+
console.error(formatError(`Failed to list resources: ${error.message}`));
|
|
2879
|
+
process.exit(1);
|
|
963
2880
|
}
|
|
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
2881
|
}
|
|
970
|
-
async function
|
|
2882
|
+
async function readResourceCommand(uri, options) {
|
|
971
2883
|
try {
|
|
972
|
-
const
|
|
973
|
-
if (!
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
2884
|
+
const result = await getOrRestoreSession(options.session || null);
|
|
2885
|
+
if (!result) return;
|
|
2886
|
+
const { session } = result;
|
|
2887
|
+
console.error(formatInfo(`Reading resource: ${uri}`));
|
|
2888
|
+
const resource = await session.readResource(uri);
|
|
2889
|
+
if (options.json) {
|
|
2890
|
+
console.log(formatJson(resource));
|
|
2891
|
+
} else {
|
|
2892
|
+
console.log(formatResourceContent(resource));
|
|
979
2893
|
}
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
2894
|
+
} catch (error) {
|
|
2895
|
+
console.error(formatError(`Failed to read resource: ${error.message}`));
|
|
2896
|
+
process.exit(1);
|
|
2897
|
+
}
|
|
2898
|
+
}
|
|
2899
|
+
async function subscribeResourceCommand(uri, options) {
|
|
2900
|
+
try {
|
|
2901
|
+
const result = await getOrRestoreSession(options.session || null);
|
|
2902
|
+
if (!result) return;
|
|
2903
|
+
const { session } = result;
|
|
2904
|
+
await session.subscribeToResource(uri);
|
|
2905
|
+
console.log(formatSuccess(`Subscribed to resource: ${uri}`));
|
|
2906
|
+
session.on("notification", async (notification) => {
|
|
2907
|
+
if (notification.method === "notifications/resources/updated") {
|
|
2908
|
+
console.log("");
|
|
2909
|
+
console.log(formatInfo("Resource updated:"));
|
|
2910
|
+
console.log(formatJson(notification.params));
|
|
994
2911
|
}
|
|
995
|
-
|
|
2912
|
+
});
|
|
2913
|
+
console.log(formatInfo("Listening for updates... (Press Ctrl+C to stop)"));
|
|
2914
|
+
await new Promise(() => {
|
|
2915
|
+
});
|
|
2916
|
+
} catch (error) {
|
|
2917
|
+
console.error(
|
|
2918
|
+
formatError(`Failed to subscribe to resource: ${error.message}`)
|
|
2919
|
+
);
|
|
2920
|
+
process.exit(1);
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
async function unsubscribeResourceCommand(uri, options) {
|
|
2924
|
+
try {
|
|
2925
|
+
const result = await getOrRestoreSession(options.session || null);
|
|
2926
|
+
if (!result) return;
|
|
2927
|
+
const { session } = result;
|
|
2928
|
+
await session.unsubscribeFromResource(uri);
|
|
2929
|
+
console.log(formatSuccess(`Unsubscribed from resource: ${uri}`));
|
|
2930
|
+
} catch (error) {
|
|
2931
|
+
console.error(
|
|
2932
|
+
formatError(`Failed to unsubscribe from resource: ${error.message}`)
|
|
2933
|
+
);
|
|
2934
|
+
process.exit(1);
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
async function listPromptsCommand(options) {
|
|
2938
|
+
try {
|
|
2939
|
+
const result = await getOrRestoreSession(options.session || null);
|
|
2940
|
+
if (!result) return;
|
|
2941
|
+
const { session } = result;
|
|
2942
|
+
const promptsResult = await session.listPrompts();
|
|
2943
|
+
const prompts = promptsResult.prompts;
|
|
2944
|
+
if (options.json) {
|
|
2945
|
+
console.log(formatJson(prompts));
|
|
2946
|
+
return;
|
|
996
2947
|
}
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
)
|
|
1029
|
-
|
|
1030
|
-
if (!shouldDeploy) {
|
|
1031
|
-
console.log(import_chalk2.default.gray("Deployment cancelled."));
|
|
1032
|
-
process.exit(0);
|
|
1033
|
-
}
|
|
1034
|
-
const projectName = options.name || await getProjectName(cwd);
|
|
1035
|
-
const runtime = options.runtime || await detectRuntime(cwd);
|
|
1036
|
-
const port = options.port || 3e3;
|
|
1037
|
-
const buildCommand = await detectBuildCommand(cwd);
|
|
1038
|
-
const startCommand = await detectStartCommand(cwd);
|
|
1039
|
-
console.log();
|
|
1040
|
-
console.log(import_chalk2.default.white("Deployment configuration:"));
|
|
1041
|
-
console.log(import_chalk2.default.gray(` Name: `) + import_chalk2.default.cyan(projectName));
|
|
1042
|
-
console.log(import_chalk2.default.gray(` Runtime: `) + import_chalk2.default.cyan(runtime));
|
|
1043
|
-
console.log(import_chalk2.default.gray(` Port: `) + import_chalk2.default.cyan(port));
|
|
1044
|
-
if (buildCommand) {
|
|
1045
|
-
console.log(import_chalk2.default.gray(` Build command: `) + import_chalk2.default.cyan(buildCommand));
|
|
1046
|
-
}
|
|
1047
|
-
if (startCommand) {
|
|
1048
|
-
console.log(import_chalk2.default.gray(` Start command: `) + import_chalk2.default.cyan(startCommand));
|
|
1049
|
-
}
|
|
1050
|
-
console.log();
|
|
1051
|
-
const deploymentRequest = {
|
|
1052
|
-
name: projectName,
|
|
1053
|
-
source: {
|
|
1054
|
-
type: "github",
|
|
1055
|
-
repo: `${gitInfo.owner}/${gitInfo.repo}`,
|
|
1056
|
-
branch: gitInfo.branch || "main",
|
|
1057
|
-
runtime,
|
|
1058
|
-
port,
|
|
1059
|
-
buildCommand,
|
|
1060
|
-
startCommand
|
|
1061
|
-
},
|
|
1062
|
-
healthCheckPath: "/healthz"
|
|
1063
|
-
};
|
|
1064
|
-
console.log(import_chalk2.default.gray("Creating deployment..."));
|
|
1065
|
-
const api = await McpUseAPI.create();
|
|
1066
|
-
const deployment = await api.createDeployment(deploymentRequest);
|
|
1067
|
-
console.log(
|
|
1068
|
-
import_chalk2.default.green("\u2713 Deployment created: ") + import_chalk2.default.gray(deployment.id)
|
|
1069
|
-
);
|
|
1070
|
-
await displayDeploymentProgress(api, deployment);
|
|
1071
|
-
if (options.open && deployment.domain) {
|
|
1072
|
-
console.log();
|
|
1073
|
-
console.log(import_chalk2.default.gray("Opening deployment in browser..."));
|
|
1074
|
-
await (0, import_open2.default)(`https://${deployment.domain}`);
|
|
2948
|
+
if (prompts.length === 0) {
|
|
2949
|
+
console.log(formatInfo("No prompts available"));
|
|
2950
|
+
return;
|
|
2951
|
+
}
|
|
2952
|
+
console.log(formatHeader(`Available Prompts (${prompts.length}):`));
|
|
2953
|
+
console.log("");
|
|
2954
|
+
const tableData = prompts.map((prompt2) => ({
|
|
2955
|
+
name: source_default.bold(prompt2.name),
|
|
2956
|
+
description: prompt2.description || source_default.gray("No description")
|
|
2957
|
+
}));
|
|
2958
|
+
console.log(
|
|
2959
|
+
formatTable(tableData, [
|
|
2960
|
+
{ key: "name", header: "Prompt", width: 25 },
|
|
2961
|
+
{ key: "description", header: "Description", width: 50 }
|
|
2962
|
+
])
|
|
2963
|
+
);
|
|
2964
|
+
} catch (error) {
|
|
2965
|
+
console.error(formatError(`Failed to list prompts: ${error.message}`));
|
|
2966
|
+
process.exit(1);
|
|
2967
|
+
}
|
|
2968
|
+
}
|
|
2969
|
+
async function getPromptCommand(promptName, argsJson, options) {
|
|
2970
|
+
try {
|
|
2971
|
+
const result = await getOrRestoreSession(options?.session || null);
|
|
2972
|
+
if (!result) return;
|
|
2973
|
+
const { session } = result;
|
|
2974
|
+
let args = {};
|
|
2975
|
+
if (argsJson) {
|
|
2976
|
+
try {
|
|
2977
|
+
args = JSON.parse(argsJson);
|
|
2978
|
+
} catch (error) {
|
|
2979
|
+
console.error(formatError("Invalid JSON arguments"));
|
|
2980
|
+
return;
|
|
1075
2981
|
}
|
|
2982
|
+
}
|
|
2983
|
+
console.error(formatInfo(`Getting prompt '${promptName}'...`));
|
|
2984
|
+
const prompt2 = await session.getPrompt(promptName, args);
|
|
2985
|
+
if (options?.json) {
|
|
2986
|
+
console.log(formatJson(prompt2));
|
|
1076
2987
|
} 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..."));
|
|
2988
|
+
console.log(formatHeader(`Prompt: ${promptName}`));
|
|
2989
|
+
console.log("");
|
|
2990
|
+
if (prompt2.description) {
|
|
2991
|
+
console.log(prompt2.description);
|
|
2992
|
+
console.log("");
|
|
1088
2993
|
}
|
|
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));
|
|
2994
|
+
if (prompt2.messages) {
|
|
2995
|
+
console.log(formatHeader("Messages:"));
|
|
2996
|
+
console.log("");
|
|
2997
|
+
console.log(formatPromptMessages(prompt2.messages));
|
|
1101
2998
|
}
|
|
1102
|
-
|
|
1103
|
-
|
|
2999
|
+
}
|
|
3000
|
+
} catch (error) {
|
|
3001
|
+
console.error(formatError(`Failed to get prompt: ${error.message}`));
|
|
3002
|
+
process.exit(1);
|
|
3003
|
+
}
|
|
3004
|
+
}
|
|
3005
|
+
async function interactiveCommand(options) {
|
|
3006
|
+
try {
|
|
3007
|
+
const result = await getOrRestoreSession(options.session || null);
|
|
3008
|
+
if (!result) return;
|
|
3009
|
+
const { name: sessionName, session } = result;
|
|
3010
|
+
console.log(formatHeader("MCP Interactive Mode"));
|
|
3011
|
+
console.log("");
|
|
3012
|
+
console.log(formatInfo(`Connected to: ${sessionName}`));
|
|
3013
|
+
console.log("");
|
|
3014
|
+
console.log(source_default.gray("Commands:"));
|
|
3015
|
+
console.log(source_default.gray(" tools list - List available tools"));
|
|
3016
|
+
console.log(
|
|
3017
|
+
source_default.gray(
|
|
3018
|
+
" tools call <name> - Call a tool (will prompt for args)"
|
|
3019
|
+
)
|
|
3020
|
+
);
|
|
3021
|
+
console.log(source_default.gray(" tools describe <name> - Show tool details"));
|
|
3022
|
+
console.log(
|
|
3023
|
+
source_default.gray(" resources list - List available resources")
|
|
3024
|
+
);
|
|
3025
|
+
console.log(source_default.gray(" resources read <uri> - Read a resource"));
|
|
3026
|
+
console.log(
|
|
3027
|
+
source_default.gray(" prompts list - List available prompts")
|
|
3028
|
+
);
|
|
3029
|
+
console.log(source_default.gray(" prompts get <name> - Get a prompt"));
|
|
3030
|
+
console.log(source_default.gray(" sessions list - List all sessions"));
|
|
3031
|
+
console.log(
|
|
3032
|
+
source_default.gray(" sessions switch <name> - Switch to another session")
|
|
3033
|
+
);
|
|
3034
|
+
console.log(
|
|
3035
|
+
source_default.gray(" exit, quit - Exit interactive mode")
|
|
3036
|
+
);
|
|
3037
|
+
console.log("");
|
|
3038
|
+
const rl = createInterface({
|
|
3039
|
+
input: process.stdin,
|
|
3040
|
+
output: process.stdout,
|
|
3041
|
+
prompt: source_default.cyan("mcp> ")
|
|
3042
|
+
});
|
|
3043
|
+
rl.prompt();
|
|
3044
|
+
rl.on("line", async (line) => {
|
|
3045
|
+
const trimmed = line.trim();
|
|
3046
|
+
if (!trimmed) {
|
|
3047
|
+
rl.prompt();
|
|
3048
|
+
return;
|
|
1104
3049
|
}
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
"y"
|
|
1109
|
-
);
|
|
1110
|
-
if (!shouldDeploy) {
|
|
1111
|
-
console.log(import_chalk2.default.gray("Deployment cancelled."));
|
|
3050
|
+
if (trimmed === "exit" || trimmed === "quit") {
|
|
3051
|
+
console.log(formatInfo("Goodbye!"));
|
|
3052
|
+
rl.close();
|
|
1112
3053
|
process.exit(0);
|
|
1113
3054
|
}
|
|
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
|
-
|
|
3055
|
+
const parts = trimmed.split(" ");
|
|
3056
|
+
const scope = parts[0];
|
|
3057
|
+
const command = parts[1];
|
|
3058
|
+
const arg = parts[2];
|
|
3059
|
+
try {
|
|
3060
|
+
if (scope === "tools") {
|
|
3061
|
+
if (command === "list") {
|
|
3062
|
+
const tools = await session.listTools();
|
|
3063
|
+
console.log(
|
|
3064
|
+
formatInfo(
|
|
3065
|
+
`Available tools: ${tools.map((t) => t.name).join(", ")}`
|
|
3066
|
+
)
|
|
3067
|
+
);
|
|
3068
|
+
} else if (command === "call" && arg) {
|
|
3069
|
+
rl.question(
|
|
3070
|
+
"Arguments (JSON, or press Enter for none): ",
|
|
3071
|
+
async (argsInput) => {
|
|
3072
|
+
try {
|
|
3073
|
+
const args = argsInput.trim() ? JSON.parse(argsInput) : {};
|
|
3074
|
+
const result2 = await session.callTool(arg, args);
|
|
3075
|
+
console.log(formatToolCall(result2));
|
|
3076
|
+
} catch (error) {
|
|
3077
|
+
console.error(formatError(error.message));
|
|
3078
|
+
}
|
|
3079
|
+
rl.prompt();
|
|
3080
|
+
}
|
|
3081
|
+
);
|
|
3082
|
+
return;
|
|
3083
|
+
} else if (command === "describe" && arg) {
|
|
3084
|
+
const tools = session.tools;
|
|
3085
|
+
const tool = tools.find((t) => t.name === arg);
|
|
3086
|
+
if (tool) {
|
|
3087
|
+
console.log(formatHeader(`Tool: ${tool.name}`));
|
|
3088
|
+
if (tool.description) console.log(tool.description);
|
|
3089
|
+
if (tool.inputSchema) {
|
|
3090
|
+
console.log("");
|
|
3091
|
+
console.log(formatSchema(tool.inputSchema));
|
|
3092
|
+
}
|
|
3093
|
+
} else {
|
|
3094
|
+
console.error(formatError(`Tool '${arg}' not found`));
|
|
3095
|
+
}
|
|
3096
|
+
} else {
|
|
3097
|
+
console.error(
|
|
3098
|
+
formatError(
|
|
3099
|
+
"Invalid command. Try: tools list, tools call <name>, tools describe <name>"
|
|
3100
|
+
)
|
|
3101
|
+
);
|
|
3102
|
+
}
|
|
3103
|
+
} else if (scope === "resources") {
|
|
3104
|
+
if (command === "list") {
|
|
3105
|
+
const result2 = await session.listAllResources();
|
|
3106
|
+
const resources = result2.resources;
|
|
3107
|
+
console.log(
|
|
3108
|
+
formatInfo(
|
|
3109
|
+
`Available resources: ${resources.map((r) => r.uri).join(", ")}`
|
|
3110
|
+
)
|
|
3111
|
+
);
|
|
3112
|
+
} else if (command === "read" && arg) {
|
|
3113
|
+
const resource = await session.readResource(arg);
|
|
3114
|
+
console.log(formatResourceContent(resource));
|
|
3115
|
+
} else {
|
|
3116
|
+
console.error(
|
|
3117
|
+
formatError(
|
|
3118
|
+
"Invalid command. Try: resources list, resources read <uri>"
|
|
3119
|
+
)
|
|
3120
|
+
);
|
|
3121
|
+
}
|
|
3122
|
+
} else if (scope === "prompts") {
|
|
3123
|
+
if (command === "list") {
|
|
3124
|
+
const result2 = await session.listPrompts();
|
|
3125
|
+
const prompts = result2.prompts;
|
|
3126
|
+
console.log(
|
|
3127
|
+
formatInfo(
|
|
3128
|
+
`Available prompts: ${prompts.map((p) => p.name).join(", ")}`
|
|
3129
|
+
)
|
|
3130
|
+
);
|
|
3131
|
+
} else if (command === "get" && arg) {
|
|
3132
|
+
rl.question(
|
|
3133
|
+
"Arguments (JSON, or press Enter for none): ",
|
|
3134
|
+
async (argsInput) => {
|
|
3135
|
+
try {
|
|
3136
|
+
const args = argsInput.trim() ? JSON.parse(argsInput) : {};
|
|
3137
|
+
const prompt2 = await session.getPrompt(arg, args);
|
|
3138
|
+
console.log(formatPromptMessages(prompt2.messages));
|
|
3139
|
+
} catch (error) {
|
|
3140
|
+
console.error(formatError(error.message));
|
|
3141
|
+
}
|
|
3142
|
+
rl.prompt();
|
|
3143
|
+
}
|
|
3144
|
+
);
|
|
3145
|
+
return;
|
|
3146
|
+
} else {
|
|
3147
|
+
console.error(
|
|
3148
|
+
formatError(
|
|
3149
|
+
"Invalid command. Try: prompts list, prompts get <name>"
|
|
3150
|
+
)
|
|
3151
|
+
);
|
|
3152
|
+
}
|
|
3153
|
+
} else if (scope === "sessions") {
|
|
3154
|
+
if (command === "list") {
|
|
3155
|
+
await listSessionsCommand();
|
|
3156
|
+
} else if (command === "switch" && arg) {
|
|
3157
|
+
console.log(
|
|
3158
|
+
formatWarning(
|
|
3159
|
+
"Session switching in interactive mode will be available in a future version"
|
|
3160
|
+
)
|
|
3161
|
+
);
|
|
3162
|
+
} else {
|
|
3163
|
+
console.error(formatError("Invalid command. Try: sessions list"));
|
|
3164
|
+
}
|
|
3165
|
+
} else {
|
|
3166
|
+
console.error(
|
|
3167
|
+
formatError(
|
|
3168
|
+
"Unknown command. Type a valid scope: tools, resources, prompts, sessions"
|
|
3169
|
+
)
|
|
3170
|
+
);
|
|
3171
|
+
}
|
|
3172
|
+
} catch (error) {
|
|
3173
|
+
console.error(formatError(error.message));
|
|
1157
3174
|
}
|
|
1158
|
-
|
|
3175
|
+
rl.prompt();
|
|
3176
|
+
});
|
|
3177
|
+
rl.on("close", () => {
|
|
3178
|
+
console.log("");
|
|
3179
|
+
console.log(formatInfo("Goodbye!"));
|
|
3180
|
+
process.exit(0);
|
|
3181
|
+
});
|
|
1159
3182
|
} catch (error) {
|
|
1160
3183
|
console.error(
|
|
1161
|
-
|
|
1162
|
-
import_chalk2.default.red(error instanceof Error ? error.message : "Unknown error")
|
|
3184
|
+
formatError(`Failed to start interactive mode: ${error.message}`)
|
|
1163
3185
|
);
|
|
1164
3186
|
process.exit(1);
|
|
1165
3187
|
}
|
|
1166
3188
|
}
|
|
3189
|
+
function createClientCommand() {
|
|
3190
|
+
const clientCommand = new Command("client").description(
|
|
3191
|
+
"Interactive MCP client for terminal usage"
|
|
3192
|
+
);
|
|
3193
|
+
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);
|
|
3194
|
+
clientCommand.command("disconnect [session]").description("Disconnect from a session").option("--all", "Disconnect all sessions").action(disconnectCommand);
|
|
3195
|
+
const sessionsCommand = new Command("sessions").description(
|
|
3196
|
+
"Manage CLI sessions"
|
|
3197
|
+
);
|
|
3198
|
+
sessionsCommand.command("list").description("List all saved sessions").action(listSessionsCommand);
|
|
3199
|
+
sessionsCommand.command("switch <name>").description("Switch to a different session").action(switchSessionCommand);
|
|
3200
|
+
clientCommand.addCommand(sessionsCommand);
|
|
3201
|
+
const toolsCommand = new Command("tools").description(
|
|
3202
|
+
"Interact with MCP tools"
|
|
3203
|
+
);
|
|
3204
|
+
toolsCommand.command("list").description("List available tools").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(listToolsCommand);
|
|
3205
|
+
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);
|
|
3206
|
+
toolsCommand.command("describe <name>").description("Show tool details and schema").option("--session <name>", "Use specific session").action(describeToolCommand);
|
|
3207
|
+
clientCommand.addCommand(toolsCommand);
|
|
3208
|
+
const resourcesCommand = new Command("resources").description(
|
|
3209
|
+
"Interact with MCP resources"
|
|
3210
|
+
);
|
|
3211
|
+
resourcesCommand.command("list").description("List available resources").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(listResourcesCommand);
|
|
3212
|
+
resourcesCommand.command("read <uri>").description("Read a resource by URI").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(readResourceCommand);
|
|
3213
|
+
resourcesCommand.command("subscribe <uri>").description("Subscribe to resource updates").option("--session <name>", "Use specific session").action(subscribeResourceCommand);
|
|
3214
|
+
resourcesCommand.command("unsubscribe <uri>").description("Unsubscribe from resource updates").option("--session <name>", "Use specific session").action(unsubscribeResourceCommand);
|
|
3215
|
+
clientCommand.addCommand(resourcesCommand);
|
|
3216
|
+
const promptsCommand = new Command("prompts").description(
|
|
3217
|
+
"Interact with MCP prompts"
|
|
3218
|
+
);
|
|
3219
|
+
promptsCommand.command("list").description("List available prompts").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(listPromptsCommand);
|
|
3220
|
+
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);
|
|
3221
|
+
clientCommand.addCommand(promptsCommand);
|
|
3222
|
+
clientCommand.command("interactive").description("Start interactive REPL mode").option("--session <name>", "Use specific session").action(interactiveCommand);
|
|
3223
|
+
return clientCommand;
|
|
3224
|
+
}
|
|
1167
3225
|
|
|
1168
3226
|
// src/index.ts
|
|
1169
|
-
var program = new
|
|
1170
|
-
var packageContent =
|
|
1171
|
-
|
|
3227
|
+
var program = new Command2();
|
|
3228
|
+
var packageContent = readFileSync(
|
|
3229
|
+
path5.join(__dirname, "../package.json"),
|
|
1172
3230
|
"utf-8"
|
|
1173
3231
|
);
|
|
1174
3232
|
var packageJson = JSON.parse(packageContent);
|
|
@@ -1208,12 +3266,12 @@ async function waitForServer(port, host = "localhost", maxAttempts = 30) {
|
|
|
1208
3266
|
}
|
|
1209
3267
|
return false;
|
|
1210
3268
|
}
|
|
1211
|
-
function runCommand(command, args, cwd,
|
|
1212
|
-
const proc =
|
|
3269
|
+
function runCommand(command, args, cwd, env2, filterStderr = false) {
|
|
3270
|
+
const proc = spawn(command, args, {
|
|
1213
3271
|
cwd,
|
|
1214
3272
|
stdio: filterStderr ? ["inherit", "inherit", "pipe"] : "inherit",
|
|
1215
3273
|
shell: false,
|
|
1216
|
-
env:
|
|
3274
|
+
env: env2 ? { ...process.env, ...env2 } : process.env
|
|
1217
3275
|
});
|
|
1218
3276
|
if (filterStderr && proc.stderr) {
|
|
1219
3277
|
proc.stderr.on("data", (data) => {
|
|
@@ -1237,12 +3295,12 @@ function runCommand(command, args, cwd, env, filterStderr = false) {
|
|
|
1237
3295
|
}
|
|
1238
3296
|
async function startTunnel(port, subdomain) {
|
|
1239
3297
|
return new Promise((resolve, reject) => {
|
|
1240
|
-
console.log(
|
|
3298
|
+
console.log(source_default.gray(`Starting tunnel for port ${port}...`));
|
|
1241
3299
|
const tunnelArgs = ["--yes", "@mcp-use/tunnel", String(port)];
|
|
1242
3300
|
if (subdomain) {
|
|
1243
3301
|
tunnelArgs.push("--subdomain", subdomain);
|
|
1244
3302
|
}
|
|
1245
|
-
const proc =
|
|
3303
|
+
const proc = spawn("npx", tunnelArgs, {
|
|
1246
3304
|
stdio: ["ignore", "pipe", "pipe"],
|
|
1247
3305
|
shell: false
|
|
1248
3306
|
});
|
|
@@ -1262,7 +3320,7 @@ async function startTunnel(port, subdomain) {
|
|
|
1262
3320
|
let extractedSubdomain = subdomainMatch ? subdomainMatch[1] : fullDomain.split(".")[0];
|
|
1263
3321
|
if (!/^[a-z0-9-]+$/i.test(extractedSubdomain)) {
|
|
1264
3322
|
console.warn(
|
|
1265
|
-
|
|
3323
|
+
source_default.yellow(
|
|
1266
3324
|
`Warning: Extracted subdomain "${extractedSubdomain}" does not match expected format.`
|
|
1267
3325
|
)
|
|
1268
3326
|
);
|
|
@@ -1270,7 +3328,7 @@ async function startTunnel(port, subdomain) {
|
|
|
1270
3328
|
}
|
|
1271
3329
|
resolved = true;
|
|
1272
3330
|
clearTimeout(setupTimeout);
|
|
1273
|
-
console.log(
|
|
3331
|
+
console.log(source_default.green.bold(`\u2713 Tunnel established: ${url}/mcp`));
|
|
1274
3332
|
resolve({ url, subdomain: extractedSubdomain, process: proc });
|
|
1275
3333
|
}
|
|
1276
3334
|
});
|
|
@@ -1307,7 +3365,7 @@ async function findServerFile(projectPath) {
|
|
|
1307
3365
|
const candidates = ["index.ts", "src/index.ts", "server.ts", "src/server.ts"];
|
|
1308
3366
|
for (const candidate of candidates) {
|
|
1309
3367
|
try {
|
|
1310
|
-
await
|
|
3368
|
+
await access(path5.join(projectPath, candidate));
|
|
1311
3369
|
return candidate;
|
|
1312
3370
|
} catch {
|
|
1313
3371
|
continue;
|
|
@@ -1316,21 +3374,21 @@ async function findServerFile(projectPath) {
|
|
|
1316
3374
|
throw new Error("No server file found");
|
|
1317
3375
|
}
|
|
1318
3376
|
async function buildWidgets(projectPath) {
|
|
1319
|
-
const { promises:
|
|
3377
|
+
const { promises: fs9 } = await import("fs");
|
|
1320
3378
|
const { build } = await import("vite");
|
|
1321
|
-
const resourcesDir =
|
|
3379
|
+
const resourcesDir = path5.join(projectPath, "resources");
|
|
1322
3380
|
const mcpUrl = process.env.MCP_URL;
|
|
1323
3381
|
try {
|
|
1324
|
-
await
|
|
3382
|
+
await access(resourcesDir);
|
|
1325
3383
|
} catch {
|
|
1326
3384
|
console.log(
|
|
1327
|
-
|
|
3385
|
+
source_default.gray("No resources/ directory found - skipping widget build")
|
|
1328
3386
|
);
|
|
1329
3387
|
return [];
|
|
1330
3388
|
}
|
|
1331
3389
|
const entries = [];
|
|
1332
3390
|
try {
|
|
1333
|
-
const files = await
|
|
3391
|
+
const files = await fs9.readdir(resourcesDir, { withFileTypes: true });
|
|
1334
3392
|
for (const dirent of files) {
|
|
1335
3393
|
if (dirent.name.startsWith("._") || dirent.name.startsWith(".DS_Store")) {
|
|
1336
3394
|
continue;
|
|
@@ -1338,12 +3396,12 @@ async function buildWidgets(projectPath) {
|
|
|
1338
3396
|
if (dirent.isFile() && (dirent.name.endsWith(".tsx") || dirent.name.endsWith(".ts"))) {
|
|
1339
3397
|
entries.push({
|
|
1340
3398
|
name: dirent.name.replace(/\.tsx?$/, ""),
|
|
1341
|
-
path:
|
|
3399
|
+
path: path5.join(resourcesDir, dirent.name)
|
|
1342
3400
|
});
|
|
1343
3401
|
} else if (dirent.isDirectory()) {
|
|
1344
|
-
const widgetPath =
|
|
3402
|
+
const widgetPath = path5.join(resourcesDir, dirent.name, "widget.tsx");
|
|
1345
3403
|
try {
|
|
1346
|
-
await
|
|
3404
|
+
await fs9.access(widgetPath);
|
|
1347
3405
|
entries.push({
|
|
1348
3406
|
name: dirent.name,
|
|
1349
3407
|
path: widgetPath
|
|
@@ -1353,30 +3411,41 @@ async function buildWidgets(projectPath) {
|
|
|
1353
3411
|
}
|
|
1354
3412
|
}
|
|
1355
3413
|
} catch (error) {
|
|
1356
|
-
console.log(
|
|
3414
|
+
console.log(source_default.gray("No widgets found in resources/ directory"));
|
|
1357
3415
|
return [];
|
|
1358
3416
|
}
|
|
1359
3417
|
if (entries.length === 0) {
|
|
1360
|
-
console.log(
|
|
3418
|
+
console.log(source_default.gray("No widgets found in resources/ directory"));
|
|
1361
3419
|
return [];
|
|
1362
3420
|
}
|
|
1363
|
-
console.log(
|
|
3421
|
+
console.log(source_default.gray(`Building ${entries.length} widget(s)...`));
|
|
1364
3422
|
const react = (await import("@vitejs/plugin-react")).default;
|
|
1365
3423
|
const tailwindcss = (await import("@tailwindcss/vite")).default;
|
|
3424
|
+
const packageJsonPath = path5.join(projectPath, "package.json");
|
|
3425
|
+
let favicon = "";
|
|
3426
|
+
try {
|
|
3427
|
+
const pkgContent = await fs9.readFile(packageJsonPath, "utf-8");
|
|
3428
|
+
const pkg = JSON.parse(pkgContent);
|
|
3429
|
+
favicon = pkg.mcpUse?.favicon || "";
|
|
3430
|
+
} catch {
|
|
3431
|
+
}
|
|
1366
3432
|
const builtWidgets = [];
|
|
1367
3433
|
for (const entry of entries) {
|
|
1368
3434
|
const widgetName = entry.name;
|
|
1369
3435
|
const entryPath = entry.path;
|
|
1370
|
-
console.log(
|
|
1371
|
-
const tempDir =
|
|
1372
|
-
await
|
|
1373
|
-
const relativeResourcesPath =
|
|
3436
|
+
console.log(source_default.gray(` - Building ${widgetName}...`));
|
|
3437
|
+
const tempDir = path5.join(projectPath, ".mcp-use", widgetName);
|
|
3438
|
+
await fs9.mkdir(tempDir, { recursive: true });
|
|
3439
|
+
const relativeResourcesPath = path5.relative(tempDir, resourcesDir).replace(/\\/g, "/");
|
|
3440
|
+
const mcpUsePath = path5.join(projectPath, "node_modules", "mcp-use");
|
|
3441
|
+
const relativeMcpUsePath = path5.relative(tempDir, mcpUsePath).replace(/\\/g, "/");
|
|
1374
3442
|
const cssContent = `@import "tailwindcss";
|
|
1375
3443
|
|
|
1376
|
-
/* Configure Tailwind to scan the resources directory */
|
|
3444
|
+
/* Configure Tailwind to scan the resources directory and mcp-use package */
|
|
1377
3445
|
@source "${relativeResourcesPath}";
|
|
3446
|
+
@source "${relativeMcpUsePath}/**/*.{ts,tsx,js,jsx}";
|
|
1378
3447
|
`;
|
|
1379
|
-
await
|
|
3448
|
+
await fs9.writeFile(path5.join(tempDir, "styles.css"), cssContent, "utf8");
|
|
1380
3449
|
const entryContent = `import React from 'react'
|
|
1381
3450
|
import { createRoot } from 'react-dom/client'
|
|
1382
3451
|
import './styles.css'
|
|
@@ -1393,16 +3462,17 @@ if (container && Component) {
|
|
|
1393
3462
|
<head>
|
|
1394
3463
|
<meta charset="UTF-8" />
|
|
1395
3464
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
1396
|
-
<title>${widgetName} Widget</title
|
|
3465
|
+
<title>${widgetName} Widget</title>${favicon ? `
|
|
3466
|
+
<link rel="icon" href="/mcp-use/public/${favicon}" />` : ""}
|
|
1397
3467
|
</head>
|
|
1398
3468
|
<body>
|
|
1399
3469
|
<div id="widget-root"></div>
|
|
1400
3470
|
<script type="module" src="/entry.tsx"></script>
|
|
1401
3471
|
</body>
|
|
1402
3472
|
</html>`;
|
|
1403
|
-
await
|
|
1404
|
-
await
|
|
1405
|
-
const outDir =
|
|
3473
|
+
await fs9.writeFile(path5.join(tempDir, "entry.tsx"), entryContent, "utf8");
|
|
3474
|
+
await fs9.writeFile(path5.join(tempDir, "index.html"), htmlContent, "utf8");
|
|
3475
|
+
const outDir = path5.join(
|
|
1406
3476
|
projectPath,
|
|
1407
3477
|
"dist",
|
|
1408
3478
|
"resources",
|
|
@@ -1412,12 +3482,12 @@ if (container && Component) {
|
|
|
1412
3482
|
const baseUrl = mcpUrl ? `${mcpUrl}/${widgetName}/` : `/mcp-use/widgets/${widgetName}/`;
|
|
1413
3483
|
let widgetMetadata = {};
|
|
1414
3484
|
try {
|
|
1415
|
-
const metadataTempDir =
|
|
3485
|
+
const metadataTempDir = path5.join(
|
|
1416
3486
|
projectPath,
|
|
1417
3487
|
".mcp-use",
|
|
1418
3488
|
`${widgetName}-metadata`
|
|
1419
3489
|
);
|
|
1420
|
-
await
|
|
3490
|
+
await fs9.mkdir(metadataTempDir, { recursive: true });
|
|
1421
3491
|
const { createServer: createServer2 } = await import("vite");
|
|
1422
3492
|
const nodeStubsPlugin = {
|
|
1423
3493
|
name: "node-stubs",
|
|
@@ -1447,7 +3517,7 @@ export default PostHog;
|
|
|
1447
3517
|
};
|
|
1448
3518
|
const metadataServer = await createServer2({
|
|
1449
3519
|
root: metadataTempDir,
|
|
1450
|
-
cacheDir:
|
|
3520
|
+
cacheDir: path5.join(metadataTempDir, ".vite-cache"),
|
|
1451
3521
|
plugins: [nodeStubsPlugin, tailwindcss(), react()],
|
|
1452
3522
|
resolve: {
|
|
1453
3523
|
alias: {
|
|
@@ -1507,12 +3577,12 @@ export default PostHog;
|
|
|
1507
3577
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1508
3578
|
} catch (error) {
|
|
1509
3579
|
console.warn(
|
|
1510
|
-
|
|
3580
|
+
source_default.yellow(` \u26A0 Could not extract metadata for ${widgetName}`)
|
|
1511
3581
|
);
|
|
1512
3582
|
} finally {
|
|
1513
3583
|
await metadataServer.close();
|
|
1514
3584
|
try {
|
|
1515
|
-
await
|
|
3585
|
+
await fs9.rm(metadataTempDir, { recursive: true, force: true });
|
|
1516
3586
|
} catch {
|
|
1517
3587
|
}
|
|
1518
3588
|
}
|
|
@@ -1635,7 +3705,7 @@ export default {
|
|
|
1635
3705
|
outDir,
|
|
1636
3706
|
emptyOutDir: true,
|
|
1637
3707
|
rollupOptions: {
|
|
1638
|
-
input:
|
|
3708
|
+
input: path5.join(tempDir, "index.html"),
|
|
1639
3709
|
external: (id) => {
|
|
1640
3710
|
return false;
|
|
1641
3711
|
}
|
|
@@ -1645,8 +3715,8 @@ export default {
|
|
|
1645
3715
|
const mcpServerUrl = process.env.MCP_SERVER_URL;
|
|
1646
3716
|
if (mcpServerUrl) {
|
|
1647
3717
|
try {
|
|
1648
|
-
const htmlPath =
|
|
1649
|
-
let html = await
|
|
3718
|
+
const htmlPath = path5.join(outDir, "index.html");
|
|
3719
|
+
let html = await fs9.readFile(htmlPath, "utf8");
|
|
1650
3720
|
const injectionScript = `<script>window.__getFile = (filename) => { return "${mcpUrl}/${widgetName}/"+filename }; window.__mcpPublicUrl = "${mcpServerUrl}/mcp-use/public"; window.__mcpPublicAssetsUrl = "${mcpUrl}/public";</script>`;
|
|
1651
3721
|
if (!html.includes("window.__mcpPublicUrl")) {
|
|
1652
3722
|
html = html.replace(
|
|
@@ -1667,13 +3737,13 @@ export default {
|
|
|
1667
3737
|
<base href="${mcpServerUrl}">`
|
|
1668
3738
|
);
|
|
1669
3739
|
}
|
|
1670
|
-
await
|
|
3740
|
+
await fs9.writeFile(htmlPath, html, "utf8");
|
|
1671
3741
|
console.log(
|
|
1672
|
-
|
|
3742
|
+
source_default.gray(` \u2192 Injected MCP_SERVER_URL into ${widgetName}`)
|
|
1673
3743
|
);
|
|
1674
3744
|
} catch (error) {
|
|
1675
3745
|
console.warn(
|
|
1676
|
-
|
|
3746
|
+
source_default.yellow(
|
|
1677
3747
|
` \u26A0 Failed to post-process HTML for ${widgetName}:`,
|
|
1678
3748
|
error
|
|
1679
3749
|
)
|
|
@@ -1684,36 +3754,36 @@ export default {
|
|
|
1684
3754
|
name: widgetName,
|
|
1685
3755
|
metadata: widgetMetadata
|
|
1686
3756
|
});
|
|
1687
|
-
console.log(
|
|
3757
|
+
console.log(source_default.green(` \u2713 Built ${widgetName}`));
|
|
1688
3758
|
} catch (error) {
|
|
1689
|
-
console.error(
|
|
3759
|
+
console.error(source_default.red(` \u2717 Failed to build ${widgetName}:`), error);
|
|
1690
3760
|
}
|
|
1691
3761
|
}
|
|
1692
3762
|
return builtWidgets;
|
|
1693
3763
|
}
|
|
1694
3764
|
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) => {
|
|
1695
3765
|
try {
|
|
1696
|
-
const projectPath =
|
|
1697
|
-
const { promises:
|
|
1698
|
-
console.log(
|
|
3766
|
+
const projectPath = path5.resolve(options.path);
|
|
3767
|
+
const { promises: fs9 } = await import("fs");
|
|
3768
|
+
console.log(source_default.cyan.bold(`mcp-use v${packageJson.version}`));
|
|
1699
3769
|
const builtWidgets = await buildWidgets(projectPath);
|
|
1700
|
-
console.log(
|
|
3770
|
+
console.log(source_default.gray("Building TypeScript..."));
|
|
1701
3771
|
await runCommand("npx", ["tsc"], projectPath);
|
|
1702
|
-
console.log(
|
|
1703
|
-
const publicDir =
|
|
3772
|
+
console.log(source_default.green("\u2713 TypeScript build complete!"));
|
|
3773
|
+
const publicDir = path5.join(projectPath, "public");
|
|
1704
3774
|
try {
|
|
1705
|
-
await
|
|
1706
|
-
console.log(
|
|
1707
|
-
await
|
|
3775
|
+
await fs9.access(publicDir);
|
|
3776
|
+
console.log(source_default.gray("Copying public assets..."));
|
|
3777
|
+
await fs9.cp(publicDir, path5.join(projectPath, "dist", "public"), {
|
|
1708
3778
|
recursive: true
|
|
1709
3779
|
});
|
|
1710
|
-
console.log(
|
|
3780
|
+
console.log(source_default.green("\u2713 Public assets copied"));
|
|
1711
3781
|
} catch {
|
|
1712
3782
|
}
|
|
1713
|
-
const manifestPath =
|
|
3783
|
+
const manifestPath = path5.join(projectPath, "dist", "mcp-use.json");
|
|
1714
3784
|
let existingManifest = {};
|
|
1715
3785
|
try {
|
|
1716
|
-
const existingContent = await
|
|
3786
|
+
const existingContent = await fs9.readFile(manifestPath, "utf-8");
|
|
1717
3787
|
existingManifest = JSON.parse(existingContent);
|
|
1718
3788
|
} catch {
|
|
1719
3789
|
}
|
|
@@ -1733,41 +3803,41 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
|
|
|
1733
3803
|
buildId,
|
|
1734
3804
|
widgets: widgetsData
|
|
1735
3805
|
};
|
|
1736
|
-
await
|
|
1737
|
-
await
|
|
3806
|
+
await fs9.mkdir(path5.dirname(manifestPath), { recursive: true });
|
|
3807
|
+
await fs9.writeFile(
|
|
1738
3808
|
manifestPath,
|
|
1739
3809
|
JSON.stringify(manifest, null, 2),
|
|
1740
3810
|
"utf8"
|
|
1741
3811
|
);
|
|
1742
|
-
console.log(
|
|
1743
|
-
console.log(
|
|
3812
|
+
console.log(source_default.green("\u2713 Build manifest created"));
|
|
3813
|
+
console.log(source_default.green.bold(`
|
|
1744
3814
|
\u2713 Build complete!`));
|
|
1745
3815
|
if (builtWidgets.length > 0) {
|
|
1746
|
-
console.log(
|
|
3816
|
+
console.log(source_default.gray(` ${builtWidgets.length} widget(s) built`));
|
|
1747
3817
|
}
|
|
1748
3818
|
if (options.withInspector) {
|
|
1749
|
-
console.log(
|
|
3819
|
+
console.log(source_default.gray(" Inspector included"));
|
|
1750
3820
|
}
|
|
1751
3821
|
} catch (error) {
|
|
1752
|
-
console.error(
|
|
3822
|
+
console.error(source_default.red("Build failed:"), error);
|
|
1753
3823
|
process.exit(1);
|
|
1754
3824
|
}
|
|
1755
3825
|
});
|
|
1756
3826
|
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) => {
|
|
1757
3827
|
try {
|
|
1758
|
-
const projectPath =
|
|
3828
|
+
const projectPath = path5.resolve(options.path);
|
|
1759
3829
|
let port = parseInt(options.port, 10);
|
|
1760
3830
|
const host = options.host;
|
|
1761
|
-
console.log(
|
|
3831
|
+
console.log(source_default.cyan.bold(`mcp-use v${packageJson.version}`));
|
|
1762
3832
|
if (!await isPortAvailable(port, host)) {
|
|
1763
|
-
console.log(
|
|
3833
|
+
console.log(source_default.yellow.bold(`\u26A0\uFE0F Port ${port} is already in use`));
|
|
1764
3834
|
const availablePort = await findAvailablePort2(port, host);
|
|
1765
|
-
console.log(
|
|
3835
|
+
console.log(source_default.green.bold(`\u2713 Using port ${availablePort} instead`));
|
|
1766
3836
|
port = availablePort;
|
|
1767
3837
|
}
|
|
1768
3838
|
const serverFile = await findServerFile(projectPath);
|
|
1769
3839
|
const processes = [];
|
|
1770
|
-
const
|
|
3840
|
+
const env2 = {
|
|
1771
3841
|
PORT: String(port),
|
|
1772
3842
|
HOST: host,
|
|
1773
3843
|
NODE_ENV: "development"
|
|
@@ -1776,7 +3846,7 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
1776
3846
|
"npx",
|
|
1777
3847
|
["tsx", "watch", serverFile],
|
|
1778
3848
|
projectPath,
|
|
1779
|
-
|
|
3849
|
+
env2,
|
|
1780
3850
|
true
|
|
1781
3851
|
);
|
|
1782
3852
|
processes.push(serverCommand.process);
|
|
@@ -1787,17 +3857,17 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
1787
3857
|
const mcpEndpoint = `http://${host}:${port}/mcp`;
|
|
1788
3858
|
const inspectorUrl = `http://${host}:${port}/inspector?autoConnect=${encodeURIComponent(mcpEndpoint)}`;
|
|
1789
3859
|
const readyTime = Date.now() - startTime;
|
|
1790
|
-
console.log(
|
|
1791
|
-
console.log(
|
|
1792
|
-
console.log(
|
|
1793
|
-
console.log(
|
|
1794
|
-
console.log(
|
|
3860
|
+
console.log(source_default.green.bold(`\u2713 Ready in ${readyTime}ms`));
|
|
3861
|
+
console.log(source_default.whiteBright(`Local: http://${host}:${port}`));
|
|
3862
|
+
console.log(source_default.whiteBright(`Network: http://${host}:${port}`));
|
|
3863
|
+
console.log(source_default.whiteBright(`MCP: ${mcpEndpoint}`));
|
|
3864
|
+
console.log(source_default.whiteBright(`Inspector: ${inspectorUrl}
|
|
1795
3865
|
`));
|
|
1796
|
-
await (
|
|
3866
|
+
await open_default(inspectorUrl);
|
|
1797
3867
|
}
|
|
1798
3868
|
}
|
|
1799
3869
|
const cleanup = () => {
|
|
1800
|
-
console.log(
|
|
3870
|
+
console.log(source_default.gray("\n\nShutting down..."));
|
|
1801
3871
|
const processesToKill = processes.length;
|
|
1802
3872
|
let killedCount = 0;
|
|
1803
3873
|
const checkAndExit = () => {
|
|
@@ -1828,13 +3898,13 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
1828
3898
|
await new Promise(() => {
|
|
1829
3899
|
});
|
|
1830
3900
|
} catch (error) {
|
|
1831
|
-
console.error(
|
|
3901
|
+
console.error(source_default.red("Dev mode failed:"), error);
|
|
1832
3902
|
process.exit(1);
|
|
1833
3903
|
}
|
|
1834
3904
|
});
|
|
1835
3905
|
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) => {
|
|
1836
3906
|
try {
|
|
1837
|
-
const projectPath =
|
|
3907
|
+
const projectPath = path5.resolve(options.path);
|
|
1838
3908
|
const port = parseInt(options.port, 10);
|
|
1839
3909
|
console.log(
|
|
1840
3910
|
`\x1B[36m\x1B[1mmcp-use\x1B[0m \x1B[90mVersion: ${packageJson.version}\x1B[0m
|
|
@@ -1845,20 +3915,20 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
1845
3915
|
let tunnelSubdomain = void 0;
|
|
1846
3916
|
if (options.tunnel) {
|
|
1847
3917
|
try {
|
|
1848
|
-
const manifestPath =
|
|
3918
|
+
const manifestPath = path5.join(projectPath, "dist", "mcp-use.json");
|
|
1849
3919
|
let existingSubdomain;
|
|
1850
3920
|
try {
|
|
1851
|
-
const manifestContent = await (
|
|
3921
|
+
const manifestContent = await readFile2(manifestPath, "utf-8");
|
|
1852
3922
|
const manifest = JSON.parse(manifestContent);
|
|
1853
3923
|
existingSubdomain = manifest.tunnel?.subdomain;
|
|
1854
3924
|
if (existingSubdomain) {
|
|
1855
3925
|
console.log(
|
|
1856
|
-
|
|
3926
|
+
source_default.gray(`Found existing subdomain: ${existingSubdomain}`)
|
|
1857
3927
|
);
|
|
1858
3928
|
}
|
|
1859
3929
|
} catch (error) {
|
|
1860
3930
|
console.debug(
|
|
1861
|
-
|
|
3931
|
+
source_default.gray(
|
|
1862
3932
|
`Debug: Failed to read or parse mcp-use.json: ${error instanceof Error ? error.message : String(error)}`
|
|
1863
3933
|
)
|
|
1864
3934
|
);
|
|
@@ -1871,7 +3941,7 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
1871
3941
|
try {
|
|
1872
3942
|
let manifest = {};
|
|
1873
3943
|
try {
|
|
1874
|
-
const manifestContent = await (
|
|
3944
|
+
const manifestContent = await readFile2(manifestPath, "utf-8");
|
|
1875
3945
|
manifest = JSON.parse(manifestContent);
|
|
1876
3946
|
} catch {
|
|
1877
3947
|
}
|
|
@@ -1879,44 +3949,44 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
1879
3949
|
manifest.tunnel = {};
|
|
1880
3950
|
}
|
|
1881
3951
|
manifest.tunnel.subdomain = subdomain;
|
|
1882
|
-
await (
|
|
1883
|
-
await (
|
|
3952
|
+
await mkdir2(path5.dirname(manifestPath), { recursive: true });
|
|
3953
|
+
await writeFile2(
|
|
1884
3954
|
manifestPath,
|
|
1885
3955
|
JSON.stringify(manifest, null, 2),
|
|
1886
3956
|
"utf-8"
|
|
1887
3957
|
);
|
|
1888
3958
|
} catch (error) {
|
|
1889
3959
|
console.warn(
|
|
1890
|
-
|
|
3960
|
+
source_default.yellow(
|
|
1891
3961
|
`\u26A0\uFE0F Failed to save subdomain to mcp-use.json: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
1892
3962
|
)
|
|
1893
3963
|
);
|
|
1894
3964
|
}
|
|
1895
3965
|
} catch (error) {
|
|
1896
|
-
console.error(
|
|
3966
|
+
console.error(source_default.red("Failed to start tunnel:"), error);
|
|
1897
3967
|
process.exit(1);
|
|
1898
3968
|
}
|
|
1899
3969
|
}
|
|
1900
3970
|
let serverFile = "dist/index.js";
|
|
1901
3971
|
try {
|
|
1902
|
-
await
|
|
3972
|
+
await access(path5.join(projectPath, serverFile));
|
|
1903
3973
|
} catch {
|
|
1904
3974
|
serverFile = "dist/server.js";
|
|
1905
3975
|
}
|
|
1906
3976
|
console.log("Starting production server...");
|
|
1907
|
-
const
|
|
3977
|
+
const env2 = {
|
|
1908
3978
|
...process.env,
|
|
1909
3979
|
PORT: String(port),
|
|
1910
3980
|
NODE_ENV: "production"
|
|
1911
3981
|
};
|
|
1912
3982
|
if (mcpUrl) {
|
|
1913
|
-
|
|
1914
|
-
console.log(
|
|
3983
|
+
env2.MCP_URL = mcpUrl;
|
|
3984
|
+
console.log(source_default.whiteBright(`Tunnel: ${mcpUrl}/mcp`));
|
|
1915
3985
|
}
|
|
1916
|
-
const serverProc =
|
|
3986
|
+
const serverProc = spawn("node", [serverFile], {
|
|
1917
3987
|
cwd: projectPath,
|
|
1918
3988
|
stdio: "inherit",
|
|
1919
|
-
env
|
|
3989
|
+
env: env2
|
|
1920
3990
|
});
|
|
1921
3991
|
let cleanupInProgress = false;
|
|
1922
3992
|
const cleanup = async () => {
|
|
@@ -1924,7 +3994,7 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
1924
3994
|
return;
|
|
1925
3995
|
}
|
|
1926
3996
|
cleanupInProgress = true;
|
|
1927
|
-
console.log(
|
|
3997
|
+
console.log(source_default.gray("\n\nShutting down..."));
|
|
1928
3998
|
if (tunnelProcess && typeof tunnelProcess.markShutdown === "function") {
|
|
1929
3999
|
tunnelProcess.markShutdown();
|
|
1930
4000
|
}
|
|
@@ -1994,4 +4064,6 @@ program.command("deploy").description("Deploy MCP server to mcp-use cloud").opti
|
|
|
1994
4064
|
fromSource: options.fromSource
|
|
1995
4065
|
});
|
|
1996
4066
|
});
|
|
4067
|
+
program.addCommand(createClientCommand());
|
|
1997
4068
|
program.parse();
|
|
4069
|
+
//# sourceMappingURL=index.js.map
|