@mcp-use/cli 2.2.1 → 2.2.2-canary.1

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/index.js CHANGED
@@ -24,17 +24,1136 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/index.ts
27
- var import_config = require("dotenv/config");
27
+ var import_config4 = require("dotenv/config");
28
28
  var import_commander = require("commander");
29
- var import_node_child_process = require("child_process");
30
- var import_node_fs = require("fs");
29
+ var import_node_child_process3 = require("child_process");
30
+ var import_node_fs3 = require("fs");
31
31
  var import_promises = require("fs/promises");
32
- var import_node_path = __toESM(require("path"));
33
- var import_open = __toESM(require("open"));
32
+ var import_node_path3 = __toESM(require("path"));
33
+ var import_open3 = __toESM(require("open"));
34
+ var import_chalk3 = __toESM(require("chalk"));
35
+
36
+ // src/commands/auth.ts
34
37
  var import_chalk = __toESM(require("chalk"));
38
+ var import_node_http = require("http");
39
+ var import_open = __toESM(require("open"));
40
+
41
+ // src/utils/config.ts
42
+ var import_node_fs = require("fs");
43
+ var import_node_path = __toESM(require("path"));
44
+ var import_node_os = __toESM(require("os"));
45
+ var CONFIG_DIR = import_node_path.default.join(import_node_os.default.homedir(), ".mcp-use");
46
+ var CONFIG_FILE = import_node_path.default.join(CONFIG_DIR, "config.json");
47
+ 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";
48
+ var DEFAULT_WEB_URL = process.env.MCP_WEB_URL ? process.env.MCP_WEB_URL : "https://mcp-use.com";
49
+ async function ensureConfigDir() {
50
+ try {
51
+ await import_node_fs.promises.mkdir(CONFIG_DIR, { recursive: true });
52
+ } catch (error) {
53
+ }
54
+ }
55
+ async function readConfig() {
56
+ try {
57
+ const content = await import_node_fs.promises.readFile(CONFIG_FILE, "utf-8");
58
+ return JSON.parse(content);
59
+ } catch (error) {
60
+ return {};
61
+ }
62
+ }
63
+ async function writeConfig(config) {
64
+ await ensureConfigDir();
65
+ await import_node_fs.promises.writeFile(CONFIG_FILE, JSON.stringify(config, null, 2), "utf-8");
66
+ }
67
+ async function deleteConfig() {
68
+ try {
69
+ await import_node_fs.promises.unlink(CONFIG_FILE);
70
+ } catch (error) {
71
+ }
72
+ }
73
+ async function getApiUrl() {
74
+ const config = await readConfig();
75
+ return config.apiUrl || DEFAULT_API_URL;
76
+ }
77
+ async function getApiKey() {
78
+ const config = await readConfig();
79
+ return config.apiKey || null;
80
+ }
81
+ async function isLoggedIn() {
82
+ const apiKey = await getApiKey();
83
+ return !!apiKey;
84
+ }
85
+ async function getWebUrl() {
86
+ return DEFAULT_WEB_URL;
87
+ }
88
+
89
+ // src/utils/api.ts
90
+ var McpUseAPI = class _McpUseAPI {
91
+ baseUrl;
92
+ apiKey;
93
+ constructor(baseUrl, apiKey) {
94
+ this.baseUrl = baseUrl || "";
95
+ this.apiKey = apiKey;
96
+ }
97
+ /**
98
+ * Initialize API client with config
99
+ */
100
+ static async create() {
101
+ const baseUrl = await getApiUrl();
102
+ const apiKey = await getApiKey();
103
+ return new _McpUseAPI(baseUrl, apiKey ?? void 0);
104
+ }
105
+ /**
106
+ * Make authenticated request
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}`);
124
+ }
125
+ return response.json();
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}`);
143
+ }
144
+ return response.json();
145
+ }
146
+ /**
147
+ * Test authentication
148
+ */
149
+ async testAuth() {
150
+ return this.request("/test-auth");
151
+ }
152
+ /**
153
+ * Create deployment
154
+ */
155
+ async createDeployment(request) {
156
+ return this.request("/deployments", {
157
+ method: "POST",
158
+ body: JSON.stringify(request)
159
+ });
160
+ }
161
+ /**
162
+ * Get deployment by ID
163
+ */
164
+ async getDeployment(deploymentId) {
165
+ return this.request(`/deployments/${deploymentId}`);
166
+ }
167
+ /**
168
+ * Stream deployment logs
169
+ */
170
+ async *streamDeploymentLogs(deploymentId) {
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}`);
179
+ }
180
+ if (!response.body) {
181
+ throw new Error("Response body is null");
182
+ }
183
+ const reader = response.body.getReader();
184
+ const decoder = new TextDecoder();
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();
210
+ }
211
+ }
212
+ /**
213
+ * Create deployment with source code upload
214
+ */
215
+ async createDeploymentWithUpload(request, filePath) {
216
+ const { readFile } = await import("fs/promises");
217
+ const { basename } = await import("path");
218
+ const { stat } = await import("fs/promises");
219
+ const stats = await stat(filePath);
220
+ const maxSize = 2 * 1024 * 1024;
221
+ if (stats.size > maxSize) {
222
+ throw new Error(
223
+ `File size (${(stats.size / 1024 / 1024).toFixed(2)}MB) exceeds maximum of 2MB`
224
+ );
225
+ }
226
+ const fileBuffer = await readFile(filePath);
227
+ const filename = basename(filePath);
228
+ const formData = new FormData();
229
+ const blob = new Blob([fileBuffer], { type: "application/gzip" });
230
+ formData.append("source_file", blob, filename);
231
+ formData.append("name", request.name);
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);
241
+ }
242
+ if (request.source.env && Object.keys(request.source.env).length > 0) {
243
+ formData.append("env", JSON.stringify(request.source.env));
244
+ }
245
+ }
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
+ }
268
+ };
269
+
270
+ // src/commands/auth.ts
271
+ var LOGIN_TIMEOUT = 3e5;
272
+ async function findAvailablePort(startPort = 8765) {
273
+ for (let port = startPort; port < startPort + 100; port++) {
274
+ try {
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
+ }
288
+ }
289
+ throw new Error("No available ports found");
290
+ }
291
+ async function startCallbackServer(port) {
292
+ return new Promise((resolve, reject) => {
293
+ let tokenResolver = null;
294
+ const tokenPromise = new Promise((res) => {
295
+ tokenResolver = res;
296
+ });
297
+ const server = (0, import_node_http.createServer)((req, res) => {
298
+ if (req.url?.startsWith("/callback")) {
299
+ const url = new URL(req.url, `http://localhost:${port}`);
300
+ const token = url.searchParams.get("token");
301
+ if (token && tokenResolver) {
302
+ res.writeHead(200, { "Content-Type": "text/html" });
303
+ res.end(`
304
+ <!DOCTYPE html>
305
+ <html>
306
+ <head>
307
+ <title>Login Successful</title>
308
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
309
+ <style>
310
+ * {
311
+ margin: 0;
312
+ padding: 0;
313
+ box-sizing: border-box;
314
+ }
315
+ body {
316
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
317
+ display: flex;
318
+ justify-content: center;
319
+ align-items: center;
320
+ min-height: 100vh;
321
+ background: #000;
322
+ padding: 1rem;
323
+ }
324
+ .container {
325
+ width: 100%;
326
+ max-width: 28rem;
327
+ padding: 3rem;
328
+ text-align: center;
329
+ -webkit-backdrop-filter: blur(40px);
330
+ border: 1px solid rgba(255, 255, 255, 0.2);
331
+ border-radius: 1.5rem;
332
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
333
+ }
334
+ .icon-container {
335
+ display: inline-flex;
336
+ align-items: center;
337
+ justify-content: center;
338
+ width: 6rem;
339
+ height: 6rem;
340
+ margin-bottom: 2rem;
341
+ background: rgba(255, 255, 255, 0.1);
342
+ backdrop-filter: blur(10px);
343
+ -webkit-backdrop-filter: blur(10px);
344
+ border-radius: 50%;
345
+ }
346
+ .checkmark {
347
+ font-size: 4rem;
348
+ color: #fff;
349
+ line-height: 1;
350
+ animation: scaleIn 0.5s ease-out;
351
+ }
352
+ @keyframes scaleIn {
353
+ from {
354
+ transform: scale(0);
355
+ opacity: 0;
356
+ }
357
+ to {
358
+ transform: scale(1);
359
+ opacity: 1;
360
+ }
361
+ }
362
+ h1 {
363
+ color: #fff;
364
+ margin: 0 0 1rem 0;
365
+ font-size: 2.5rem;
366
+ font-weight: 700;
367
+ letter-spacing: -0.025em;
368
+ }
369
+ p {
370
+ color: rgba(255, 255, 255, 0.8);
371
+ margin: 0 0 2rem 0;
372
+ font-size: 1.125rem;
373
+ line-height: 1.5;
374
+ }
375
+ .spinner {
376
+ display: inline-block;
377
+ width: 2rem;
378
+ height: 2rem;
379
+ border: 3px solid rgba(255, 255, 255, 0.3);
380
+ border-top-color: #fff;
381
+ border-radius: 50%;
382
+ animation: spin 0.8s linear infinite;
383
+ }
384
+ @keyframes spin {
385
+ to { transform: rotate(360deg); }
386
+ }
387
+ .footer {
388
+ margin-top: 2rem;
389
+ color: rgba(255, 255, 255, 0.6);
390
+ font-size: 0.875rem;
391
+ }
392
+ </style>
393
+ </head>
394
+ <body>
395
+ <div class="container">
396
+ <h1>Authentication Successful!</h1>
397
+ <p>You can now close this window and return to the CLI.</p>
398
+ </div>
399
+ </body>
400
+ </html>
401
+ `);
402
+ tokenResolver(token);
403
+ } else {
404
+ res.writeHead(400, { "Content-Type": "text/html" });
405
+ res.end(`
406
+ <!DOCTYPE html>
407
+ <html>
408
+ <head>
409
+ <title>Login Failed</title>
410
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
411
+ <style>
412
+ * {
413
+ margin: 0;
414
+ padding: 0;
415
+ box-sizing: border-box;
416
+ }
417
+ body {
418
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
419
+ display: flex;
420
+ justify-content: center;
421
+ align-items: center;
422
+ min-height: 100vh;
423
+ background: #000;
424
+ padding: 1rem;
425
+ }
426
+ .container {
427
+ width: 100%;
428
+ max-width: 28rem;
429
+ padding: 3rem;
430
+ text-align: center;
431
+ background: rgba(255, 255, 255, 0.1);
432
+ backdrop-filter: blur(40px);
433
+ -webkit-backdrop-filter: blur(40px);
434
+ border: 1px solid rgba(255, 255, 255, 0.2);
435
+ border-radius: 1.5rem;
436
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
437
+ }
438
+ .icon-container {
439
+ display: inline-flex;
440
+ align-items: center;
441
+ justify-content: center;
442
+ width: 6rem;
443
+ height: 6rem;
444
+ margin-bottom: 2rem;
445
+ background: rgba(255, 255, 255, 0.1);
446
+ backdrop-filter: blur(10px);
447
+ -webkit-backdrop-filter: blur(10px);
448
+ border-radius: 50%;
449
+ }
450
+ .cross {
451
+ font-size: 4rem;
452
+ color: #fff;
453
+ line-height: 1;
454
+ }
455
+ h1 {
456
+ color: #fff;
457
+ margin: 0 0 1rem 0;
458
+ font-size: 2.5rem;
459
+ font-weight: 700;
460
+ letter-spacing: -0.025em;
461
+ }
462
+ p {
463
+ color: rgba(255, 255, 255, 0.8);
464
+ margin: 0;
465
+ font-size: 1.125rem;
466
+ line-height: 1.5;
467
+ }
468
+ </style>
469
+ </head>
470
+ <body>
471
+ <div class="container">
472
+ <div class="icon-container">
473
+ <div class="cross">\u2717</div>
474
+ </div>
475
+ <h1>Login Failed</h1>
476
+ <p>No token received. Please try again.</p>
477
+ </div>
478
+ </body>
479
+ </html>
480
+ `);
481
+ }
482
+ }
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()) {
493
+ console.log(
494
+ import_chalk.default.yellow(
495
+ "\u26A0\uFE0F You are already logged in. Run 'mcp-use logout' first if you want to login with a different account."
496
+ )
497
+ );
498
+ return;
499
+ }
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
+ } catch (error) {
550
+ console.error(
551
+ import_chalk.default.red.bold("\n\u2717 Login failed:"),
552
+ import_chalk.default.red(error instanceof Error ? error.message : "Unknown error")
553
+ );
554
+ process.exit(1);
555
+ }
556
+ }
557
+ async function logoutCommand() {
558
+ try {
559
+ if (!await isLoggedIn()) {
560
+ console.log(import_chalk.default.yellow("\u26A0\uFE0F You are not logged in."));
561
+ return;
562
+ }
563
+ console.log(import_chalk.default.cyan.bold("\u{1F513} Logging out...\n"));
564
+ await deleteConfig();
565
+ console.log(import_chalk.default.green.bold("\u2713 Successfully logged out!"));
566
+ console.log(
567
+ import_chalk.default.gray(
568
+ "\nYour local config has been deleted. The API key will remain active until revoked from the web interface."
569
+ )
570
+ );
571
+ } catch (error) {
572
+ console.error(
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);
577
+ }
578
+ }
579
+ async function whoamiCommand() {
580
+ try {
581
+ if (!await isLoggedIn()) {
582
+ console.log(import_chalk.default.yellow("\u26A0\uFE0F You are not logged in."));
583
+ console.log(
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));
597
+ }
598
+ } catch (error) {
599
+ console.error(
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);
604
+ }
605
+ }
606
+
607
+ // src/commands/deploy.ts
608
+ var import_chalk2 = __toESM(require("chalk"));
609
+ var import_node_fs2 = require("fs");
610
+ var import_node_path2 = __toESM(require("path"));
611
+ var import_node_os2 = __toESM(require("os"));
612
+ var import_node_child_process2 = require("child_process");
613
+ var import_node_util2 = require("util");
614
+
615
+ // src/utils/git.ts
616
+ var import_node_child_process = require("child_process");
617
+ var import_node_util = require("util");
618
+ var execAsync = (0, import_node_util.promisify)(import_node_child_process.exec);
619
+ async function gitCommand(command, cwd = process.cwd()) {
620
+ try {
621
+ const { stdout } = await execAsync(command, { cwd });
622
+ return stdout.trim();
623
+ } catch (error) {
624
+ return null;
625
+ }
626
+ }
627
+ async function isGitRepo(cwd = process.cwd()) {
628
+ const result = await gitCommand("git rev-parse --is-inside-work-tree", cwd);
629
+ return result === "true";
630
+ }
631
+ async function getRemoteUrl(cwd = process.cwd()) {
632
+ return gitCommand("git config --get remote.origin.url", cwd);
633
+ }
634
+ function parseGitHubUrl(url) {
635
+ const sshMatch = url.match(/git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/);
636
+ const httpsMatch = url.match(
637
+ /https:\/\/github\.com\/([^/]+)\/(.+?)(?:\.git)?$/
638
+ );
639
+ const match = sshMatch || httpsMatch;
640
+ if (!match) return null;
641
+ return {
642
+ owner: match[1],
643
+ repo: match[2]
644
+ };
645
+ }
646
+ async function getCurrentBranch(cwd = process.cwd()) {
647
+ return gitCommand("git rev-parse --abbrev-ref HEAD", cwd);
648
+ }
649
+ async function getCommitSha(cwd = process.cwd()) {
650
+ return gitCommand("git rev-parse HEAD", cwd);
651
+ }
652
+ async function getCommitMessage(cwd = process.cwd()) {
653
+ return gitCommand("git log -1 --pretty=%B", cwd);
654
+ }
655
+ async function getGitInfo(cwd = process.cwd()) {
656
+ const isRepo = await isGitRepo(cwd);
657
+ if (!isRepo) {
658
+ return { isGitRepo: false };
659
+ }
660
+ const remoteUrl = await getRemoteUrl(cwd);
661
+ const branch = await getCurrentBranch(cwd);
662
+ const commitSha = await getCommitSha(cwd);
663
+ const commitMessage = await getCommitMessage(cwd);
664
+ let owner;
665
+ let repo;
666
+ if (remoteUrl) {
667
+ const parsed = parseGitHubUrl(remoteUrl);
668
+ if (parsed) {
669
+ owner = parsed.owner;
670
+ repo = parsed.repo;
671
+ }
672
+ }
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
+ };
682
+ }
683
+ function isGitHubUrl(url) {
684
+ return url.includes("github.com");
685
+ }
686
+
687
+ // src/commands/deploy.ts
688
+ var import_open2 = __toESM(require("open"));
689
+ var execAsync2 = (0, import_node_util2.promisify)(import_node_child_process2.exec);
690
+ async function isMcpProject(cwd = process.cwd()) {
691
+ try {
692
+ const packageJsonPath = import_node_path2.default.join(cwd, "package.json");
693
+ const content = await import_node_fs2.promises.readFile(packageJsonPath, "utf-8");
694
+ const packageJson2 = JSON.parse(content);
695
+ const hasMcpDeps = packageJson2.dependencies?.["mcp-use"] || packageJson2.dependencies?.["@modelcontextprotocol/sdk"] || packageJson2.devDependencies?.["mcp-use"] || packageJson2.devDependencies?.["@modelcontextprotocol/sdk"];
696
+ const hasMcpScripts = packageJson2.scripts?.mcp || packageJson2.scripts?.["mcp:dev"];
697
+ return !!(hasMcpDeps || hasMcpScripts);
698
+ } catch {
699
+ return false;
700
+ }
701
+ }
702
+ async function getProjectName(cwd = process.cwd()) {
703
+ try {
704
+ const packageJsonPath = import_node_path2.default.join(cwd, "package.json");
705
+ const content = await import_node_fs2.promises.readFile(packageJsonPath, "utf-8");
706
+ const packageJson2 = JSON.parse(content);
707
+ if (packageJson2.name) {
708
+ return packageJson2.name;
709
+ }
710
+ } catch {
711
+ }
712
+ return import_node_path2.default.basename(cwd);
713
+ }
714
+ async function detectBuildCommand(cwd = process.cwd()) {
715
+ try {
716
+ const packageJsonPath = import_node_path2.default.join(cwd, "package.json");
717
+ const content = await import_node_fs2.promises.readFile(packageJsonPath, "utf-8");
718
+ const packageJson2 = JSON.parse(content);
719
+ if (packageJson2.scripts?.build) {
720
+ return "npm run build";
721
+ }
722
+ } catch {
723
+ }
724
+ return void 0;
725
+ }
726
+ async function detectStartCommand(cwd = process.cwd()) {
727
+ try {
728
+ const packageJsonPath = import_node_path2.default.join(cwd, "package.json");
729
+ const content = await import_node_fs2.promises.readFile(packageJsonPath, "utf-8");
730
+ const packageJson2 = JSON.parse(content);
731
+ if (packageJson2.scripts?.start) {
732
+ return "npm start";
733
+ }
734
+ if (packageJson2.main) {
735
+ return `node ${packageJson2.main}`;
736
+ }
737
+ } catch {
738
+ }
739
+ return void 0;
740
+ }
741
+ async function detectRuntime(cwd = process.cwd()) {
742
+ try {
743
+ const pythonFiles = ["requirements.txt", "pyproject.toml", "setup.py"];
744
+ for (const file of pythonFiles) {
745
+ try {
746
+ await import_node_fs2.promises.access(import_node_path2.default.join(cwd, file));
747
+ return "python";
748
+ } catch {
749
+ continue;
750
+ }
751
+ }
752
+ try {
753
+ await import_node_fs2.promises.access(import_node_path2.default.join(cwd, "package.json"));
754
+ return "node";
755
+ } catch {
756
+ }
757
+ } catch {
758
+ }
759
+ return "node";
760
+ }
761
+ async function prompt(question) {
762
+ const readline = await import("readline");
763
+ const rl = readline.createInterface({
764
+ input: process.stdin,
765
+ output: process.stdout
766
+ });
767
+ return new Promise((resolve) => {
768
+ rl.question(question, (answer) => {
769
+ rl.close();
770
+ resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
771
+ });
772
+ });
773
+ }
774
+ async function createTarball(cwd) {
775
+ const tmpDir = import_node_os2.default.tmpdir();
776
+ const tarballPath = import_node_path2.default.join(tmpDir, `mcp-deploy-${Date.now()}.tar.gz`);
777
+ const excludePatterns = [
778
+ "node_modules",
779
+ ".git",
780
+ "dist",
781
+ "build",
782
+ ".next",
783
+ ".venv",
784
+ "__pycache__",
785
+ "*.pyc",
786
+ ".DS_Store",
787
+ ".env",
788
+ ".env.local",
789
+ "*.log"
790
+ ];
791
+ const excludeFlags = excludePatterns.map((pattern) => `--exclude='${pattern}'`).join(" ");
792
+ const command = `tar ${excludeFlags} -czf "${tarballPath}" -C "${cwd}" .`;
793
+ try {
794
+ await execAsync2(command);
795
+ return tarballPath;
796
+ } catch (error) {
797
+ throw new Error(
798
+ `Failed to create tarball: ${error instanceof Error ? error.message : "Unknown error"}`
799
+ );
800
+ }
801
+ }
802
+ function formatFileSize(bytes) {
803
+ if (bytes === 0) return "0 B";
804
+ const k = 1024;
805
+ const sizes = ["B", "KB", "MB", "GB"];
806
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
807
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
808
+ }
809
+ async function displayDeploymentProgress(api, deployment) {
810
+ const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
811
+ let frameIndex = 0;
812
+ let spinnerInterval = null;
813
+ let lastStep = "";
814
+ const startSpinner = (message) => {
815
+ if (spinnerInterval) {
816
+ clearInterval(spinnerInterval);
817
+ }
818
+ process.stdout.write("\r\x1B[K");
819
+ spinnerInterval = setInterval(() => {
820
+ const frame = frames[frameIndex];
821
+ frameIndex = (frameIndex + 1) % frames.length;
822
+ process.stdout.write(
823
+ "\r" + import_chalk2.default.cyan(frame) + " " + import_chalk2.default.gray(message)
824
+ );
825
+ }, 80);
826
+ };
827
+ const stopSpinner = () => {
828
+ if (spinnerInterval) {
829
+ clearInterval(spinnerInterval);
830
+ spinnerInterval = null;
831
+ process.stdout.write("\r\x1B[K");
832
+ }
833
+ };
834
+ console.log();
835
+ startSpinner("Deploying...");
836
+ try {
837
+ for await (const log of api.streamDeploymentLogs(deployment.id)) {
838
+ try {
839
+ const logData = JSON.parse(log);
840
+ if (logData.step && logData.step !== lastStep) {
841
+ lastStep = logData.step;
842
+ const stepMessages = {
843
+ clone: "Preparing source code...",
844
+ analyze: "Analyzing project...",
845
+ build: "Building container image...",
846
+ deploy: "Deploying to cloud..."
847
+ };
848
+ const message = stepMessages[logData.step] || "Deploying...";
849
+ startSpinner(message);
850
+ }
851
+ if (logData.line) {
852
+ stopSpinner();
853
+ const levelColor = logData.level === "error" ? import_chalk2.default.red : logData.level === "warn" ? import_chalk2.default.yellow : import_chalk2.default.gray;
854
+ const stepPrefix = logData.step ? import_chalk2.default.cyan(`[${logData.step}]`) + " " : "";
855
+ console.log(stepPrefix + levelColor(logData.line));
856
+ }
857
+ } catch {
858
+ }
859
+ }
860
+ } catch (error) {
861
+ stopSpinner();
862
+ }
863
+ let checkCount = 0;
864
+ const maxChecks = 60;
865
+ let delay = 3e3;
866
+ const maxDelay = 1e4;
867
+ let lastDisplayedLogLength = 0;
868
+ while (checkCount < maxChecks) {
869
+ const currentDelay = delay;
870
+ await new Promise((resolve) => setTimeout(resolve, currentDelay));
871
+ const finalDeployment = await api.getDeployment(deployment.id);
872
+ if (finalDeployment.buildLogs && finalDeployment.buildLogs.length > lastDisplayedLogLength) {
873
+ const newLogs = finalDeployment.buildLogs.substring(
874
+ lastDisplayedLogLength
875
+ );
876
+ const logLines = newLogs.split("\n").filter((l) => l.trim());
877
+ for (const line of logLines) {
878
+ try {
879
+ const logData = JSON.parse(line);
880
+ if (logData.line) {
881
+ stopSpinner();
882
+ const levelColor = logData.level === "error" ? import_chalk2.default.red : logData.level === "warn" ? import_chalk2.default.yellow : import_chalk2.default.gray;
883
+ const stepPrefix = logData.step ? import_chalk2.default.cyan(`[${logData.step}]`) + " " : "";
884
+ console.log(stepPrefix + levelColor(logData.line));
885
+ }
886
+ } catch {
887
+ }
888
+ }
889
+ lastDisplayedLogLength = finalDeployment.buildLogs.length;
890
+ }
891
+ if (finalDeployment.status === "running") {
892
+ const mcpUrl = `https://${finalDeployment.domain}/mcp`;
893
+ const inspectorUrl = `https://inspector.mcp-use.com/inspect?autoConnect=${encodeURIComponent(mcpUrl)}`;
894
+ console.log(import_chalk2.default.green.bold("\u2713 Deployment successful!\n"));
895
+ console.log(import_chalk2.default.white("\u{1F310} MCP Server URL:"));
896
+ console.log(import_chalk2.default.cyan.bold(` ${mcpUrl}
897
+ `));
898
+ console.log(import_chalk2.default.white("\u{1F50D} Inspector URL:"));
899
+ console.log(import_chalk2.default.cyan.bold(` ${inspectorUrl}
900
+ `));
901
+ if (finalDeployment.customDomain) {
902
+ const customMcpUrl = `https://${finalDeployment.customDomain}/mcp`;
903
+ const customInspectorUrl = `https://inspector.mcp-use.com/inspect?autoConnect=${encodeURIComponent(customMcpUrl)}`;
904
+ console.log(import_chalk2.default.white("\u{1F517} Custom Domain:"));
905
+ console.log(import_chalk2.default.cyan.bold(` ${customMcpUrl}
906
+ `));
907
+ console.log(import_chalk2.default.white("\u{1F50D} Custom Inspector:"));
908
+ console.log(import_chalk2.default.cyan.bold(` ${customInspectorUrl}
909
+ `));
910
+ }
911
+ console.log(
912
+ import_chalk2.default.gray("Deployment ID: ") + import_chalk2.default.white(finalDeployment.id)
913
+ );
914
+ return;
915
+ } else if (finalDeployment.status === "failed") {
916
+ console.log(import_chalk2.default.red.bold("\u2717 Deployment failed\n"));
917
+ if (finalDeployment.error) {
918
+ console.log(import_chalk2.default.red("Error: ") + finalDeployment.error);
919
+ }
920
+ if (finalDeployment.buildLogs) {
921
+ console.log(import_chalk2.default.gray("\nBuild logs:"));
922
+ try {
923
+ const logs = finalDeployment.buildLogs.split("\n").filter((l) => l.trim());
924
+ for (const log of logs) {
925
+ try {
926
+ const logData = JSON.parse(log);
927
+ if (logData.line) {
928
+ console.log(import_chalk2.default.gray(` ${logData.line}`));
929
+ }
930
+ } catch {
931
+ console.log(import_chalk2.default.gray(` ${log}`));
932
+ }
933
+ }
934
+ } catch {
935
+ console.log(import_chalk2.default.gray(finalDeployment.buildLogs));
936
+ }
937
+ }
938
+ process.exit(1);
939
+ } else if (finalDeployment.status === "building") {
940
+ startSpinner("Building and deploying...");
941
+ checkCount++;
942
+ delay = Math.min(delay * 1.2, maxDelay);
943
+ } else {
944
+ console.log(
945
+ import_chalk2.default.yellow("\u26A0\uFE0F Deployment status: ") + finalDeployment.status
946
+ );
947
+ return;
948
+ }
949
+ }
950
+ stopSpinner();
951
+ console.log(import_chalk2.default.yellow("\u26A0\uFE0F Deployment is taking longer than expected."));
952
+ console.log(
953
+ import_chalk2.default.gray("Check status with: ") + import_chalk2.default.white(`mcp-use status ${deployment.id}`)
954
+ );
955
+ }
956
+ async function deployCommand(options) {
957
+ try {
958
+ const cwd = process.cwd();
959
+ if (!await isLoggedIn()) {
960
+ console.log(import_chalk2.default.red("\u2717 You are not logged in."));
961
+ console.log(
962
+ import_chalk2.default.gray("Run " + import_chalk2.default.white("mcp-use login") + " to get started.")
963
+ );
964
+ process.exit(1);
965
+ }
966
+ console.log(import_chalk2.default.cyan.bold("\u{1F680} Deploying to mcp-use cloud...\n"));
967
+ const isMcp = await isMcpProject(cwd);
968
+ if (!isMcp) {
969
+ console.log(
970
+ import_chalk2.default.yellow(
971
+ "\u26A0\uFE0F This doesn't appear to be an MCP server project (no mcp-use or @modelcontextprotocol/sdk dependency found)."
972
+ )
973
+ );
974
+ const shouldContinue = await prompt(
975
+ import_chalk2.default.white("Continue anyway? (y/n): ")
976
+ );
977
+ if (!shouldContinue) {
978
+ console.log(import_chalk2.default.gray("Deployment cancelled."));
979
+ process.exit(0);
980
+ }
981
+ console.log();
982
+ }
983
+ const gitInfo = await getGitInfo(cwd);
984
+ if (!options.fromSource && gitInfo.isGitRepo && gitInfo.remoteUrl && isGitHubUrl(gitInfo.remoteUrl)) {
985
+ if (!gitInfo.owner || !gitInfo.repo) {
986
+ console.log(
987
+ import_chalk2.default.red(
988
+ "\u2717 Could not parse GitHub repository information from remote URL."
989
+ )
990
+ );
991
+ process.exit(1);
992
+ }
993
+ console.log(import_chalk2.default.white("GitHub repository detected:"));
994
+ console.log(
995
+ import_chalk2.default.gray(` Repository: `) + import_chalk2.default.cyan(`${gitInfo.owner}/${gitInfo.repo}`)
996
+ );
997
+ console.log(
998
+ import_chalk2.default.gray(` Branch: `) + import_chalk2.default.cyan(gitInfo.branch || "main")
999
+ );
1000
+ if (gitInfo.commitSha) {
1001
+ console.log(
1002
+ import_chalk2.default.gray(` Commit: `) + import_chalk2.default.gray(gitInfo.commitSha.substring(0, 7))
1003
+ );
1004
+ }
1005
+ if (gitInfo.commitMessage) {
1006
+ console.log(
1007
+ import_chalk2.default.gray(` Message: `) + import_chalk2.default.gray(gitInfo.commitMessage.split("\n")[0])
1008
+ );
1009
+ }
1010
+ console.log();
1011
+ const shouldDeploy = await prompt(
1012
+ import_chalk2.default.white(
1013
+ `Deploy from GitHub repository ${gitInfo.owner}/${gitInfo.repo}? (y/n): `
1014
+ )
1015
+ );
1016
+ if (!shouldDeploy) {
1017
+ console.log(import_chalk2.default.gray("Deployment cancelled."));
1018
+ process.exit(0);
1019
+ }
1020
+ const projectName = options.name || await getProjectName(cwd);
1021
+ const runtime = options.runtime || await detectRuntime(cwd);
1022
+ const port = options.port || 3e3;
1023
+ const buildCommand = await detectBuildCommand(cwd);
1024
+ const startCommand = await detectStartCommand(cwd);
1025
+ console.log();
1026
+ console.log(import_chalk2.default.white("Deployment configuration:"));
1027
+ console.log(import_chalk2.default.gray(` Name: `) + import_chalk2.default.cyan(projectName));
1028
+ console.log(import_chalk2.default.gray(` Runtime: `) + import_chalk2.default.cyan(runtime));
1029
+ console.log(import_chalk2.default.gray(` Port: `) + import_chalk2.default.cyan(port));
1030
+ if (buildCommand) {
1031
+ console.log(import_chalk2.default.gray(` Build command: `) + import_chalk2.default.cyan(buildCommand));
1032
+ }
1033
+ if (startCommand) {
1034
+ console.log(import_chalk2.default.gray(` Start command: `) + import_chalk2.default.cyan(startCommand));
1035
+ }
1036
+ console.log();
1037
+ const deploymentRequest = {
1038
+ name: projectName,
1039
+ source: {
1040
+ type: "github",
1041
+ repo: `${gitInfo.owner}/${gitInfo.repo}`,
1042
+ branch: gitInfo.branch || "main",
1043
+ runtime,
1044
+ port,
1045
+ buildCommand,
1046
+ startCommand
1047
+ },
1048
+ healthCheckPath: "/healthz"
1049
+ };
1050
+ console.log(import_chalk2.default.gray("Creating deployment..."));
1051
+ const api = await McpUseAPI.create();
1052
+ const deployment = await api.createDeployment(deploymentRequest);
1053
+ console.log(
1054
+ import_chalk2.default.green("\u2713 Deployment created: ") + import_chalk2.default.gray(deployment.id)
1055
+ );
1056
+ await displayDeploymentProgress(api, deployment);
1057
+ if (options.open && deployment.domain) {
1058
+ console.log();
1059
+ console.log(import_chalk2.default.gray("Opening deployment in browser..."));
1060
+ await (0, import_open2.default)(`https://${deployment.domain}`);
1061
+ }
1062
+ } else {
1063
+ if (options.fromSource) {
1064
+ console.log(
1065
+ import_chalk2.default.white("\u{1F4E6} Deploying from local source code (--from-source)...")
1066
+ );
1067
+ } else {
1068
+ console.log(
1069
+ import_chalk2.default.yellow(
1070
+ "\u26A0\uFE0F This is not a GitHub repository or no remote is configured."
1071
+ )
1072
+ );
1073
+ console.log(import_chalk2.default.white("Deploying from local source code instead..."));
1074
+ }
1075
+ console.log();
1076
+ const projectName = options.name || await getProjectName(cwd);
1077
+ const runtime = options.runtime || await detectRuntime(cwd);
1078
+ const port = options.port || 3e3;
1079
+ const buildCommand = await detectBuildCommand(cwd);
1080
+ const startCommand = await detectStartCommand(cwd);
1081
+ console.log(import_chalk2.default.white("Deployment configuration:"));
1082
+ console.log(import_chalk2.default.gray(` Name: `) + import_chalk2.default.cyan(projectName));
1083
+ console.log(import_chalk2.default.gray(` Runtime: `) + import_chalk2.default.cyan(runtime));
1084
+ console.log(import_chalk2.default.gray(` Port: `) + import_chalk2.default.cyan(port));
1085
+ if (buildCommand) {
1086
+ console.log(import_chalk2.default.gray(` Build command: `) + import_chalk2.default.cyan(buildCommand));
1087
+ }
1088
+ if (startCommand) {
1089
+ console.log(import_chalk2.default.gray(` Start command: `) + import_chalk2.default.cyan(startCommand));
1090
+ }
1091
+ console.log();
1092
+ const shouldDeploy = await prompt(
1093
+ import_chalk2.default.white("Deploy from local source? (y/n): ")
1094
+ );
1095
+ if (!shouldDeploy) {
1096
+ console.log(import_chalk2.default.gray("Deployment cancelled."));
1097
+ process.exit(0);
1098
+ }
1099
+ console.log();
1100
+ console.log(import_chalk2.default.gray("Packaging source code..."));
1101
+ const tarballPath = await createTarball(cwd);
1102
+ const stats = await import_node_fs2.promises.stat(tarballPath);
1103
+ console.log(
1104
+ import_chalk2.default.green("\u2713 Packaged: ") + import_chalk2.default.gray(formatFileSize(stats.size))
1105
+ );
1106
+ const maxSize = 2 * 1024 * 1024;
1107
+ if (stats.size > maxSize) {
1108
+ console.log(
1109
+ import_chalk2.default.red(
1110
+ `\u2717 File size (${formatFileSize(stats.size)}) exceeds maximum of 2MB`
1111
+ )
1112
+ );
1113
+ await import_node_fs2.promises.unlink(tarballPath);
1114
+ process.exit(1);
1115
+ }
1116
+ const deploymentRequest = {
1117
+ name: projectName,
1118
+ source: {
1119
+ type: "upload",
1120
+ runtime,
1121
+ port,
1122
+ buildCommand,
1123
+ startCommand
1124
+ },
1125
+ healthCheckPath: "/healthz"
1126
+ };
1127
+ console.log(import_chalk2.default.gray("Creating deployment..."));
1128
+ const api = await McpUseAPI.create();
1129
+ const deployment = await api.createDeploymentWithUpload(
1130
+ deploymentRequest,
1131
+ tarballPath
1132
+ );
1133
+ await import_node_fs2.promises.unlink(tarballPath);
1134
+ console.log(
1135
+ import_chalk2.default.green("\u2713 Deployment created: ") + import_chalk2.default.gray(deployment.id)
1136
+ );
1137
+ await displayDeploymentProgress(api, deployment);
1138
+ if (options.open && deployment.domain) {
1139
+ console.log();
1140
+ console.log(import_chalk2.default.gray("Opening deployment in browser..."));
1141
+ await (0, import_open2.default)(`https://${deployment.domain}`);
1142
+ }
1143
+ }
1144
+ } catch (error) {
1145
+ console.error(
1146
+ import_chalk2.default.red.bold("\n\u2717 Deployment failed:"),
1147
+ import_chalk2.default.red(error instanceof Error ? error.message : "Unknown error")
1148
+ );
1149
+ process.exit(1);
1150
+ }
1151
+ }
1152
+
1153
+ // src/index.ts
35
1154
  var program = new import_commander.Command();
36
- var packageContent = (0, import_node_fs.readFileSync)(
37
- import_node_path.default.join(__dirname, "../package.json"),
1155
+ var packageContent = (0, import_node_fs3.readFileSync)(
1156
+ import_node_path3.default.join(__dirname, "../package.json"),
38
1157
  "utf-8"
39
1158
  );
40
1159
  var packageJson = JSON.parse(packageContent);
@@ -48,7 +1167,7 @@ async function isPortAvailable(port, host = "localhost") {
48
1167
  return true;
49
1168
  }
50
1169
  }
51
- async function findAvailablePort(startPort, host = "localhost") {
1170
+ async function findAvailablePort2(startPort, host = "localhost") {
52
1171
  for (let port = startPort; port < startPort + 100; port++) {
53
1172
  if (await isPortAvailable(port, host)) {
54
1173
  return port;
@@ -70,7 +1189,7 @@ async function waitForServer(port, host = "localhost", maxAttempts = 30) {
70
1189
  return false;
71
1190
  }
72
1191
  function runCommand(command, args, cwd, env, filterStderr = false) {
73
- const proc = (0, import_node_child_process.spawn)(command, args, {
1192
+ const proc = (0, import_node_child_process3.spawn)(command, args, {
74
1193
  cwd,
75
1194
  stdio: filterStderr ? ["inherit", "inherit", "pipe"] : "inherit",
76
1195
  shell: false,
@@ -98,8 +1217,8 @@ function runCommand(command, args, cwd, env, filterStderr = false) {
98
1217
  }
99
1218
  async function startTunnel(port) {
100
1219
  return new Promise((resolve, reject) => {
101
- console.log(import_chalk.default.gray(`Starting tunnel for port ${port}...`));
102
- const proc = (0, import_node_child_process.spawn)("npx", ["--yes", "@mcp-use/tunnel", String(port)], {
1220
+ console.log(import_chalk3.default.gray(`Starting tunnel for port ${port}...`));
1221
+ const proc = (0, import_node_child_process3.spawn)("npx", ["--yes", "@mcp-use/tunnel", String(port)], {
103
1222
  stdio: ["ignore", "pipe", "pipe"],
104
1223
  shell: false
105
1224
  });
@@ -113,7 +1232,7 @@ async function startTunnel(port) {
113
1232
  const subdomain = url;
114
1233
  resolved = true;
115
1234
  clearTimeout(setupTimeout);
116
- console.log(import_chalk.default.green.bold(`\u2713 Tunnel established: ${url}/mcp`));
1235
+ console.log(import_chalk3.default.green.bold(`\u2713 Tunnel established: ${url}/mcp`));
117
1236
  resolve({ url, subdomain, process: proc });
118
1237
  }
119
1238
  });
@@ -144,7 +1263,7 @@ async function findServerFile(projectPath) {
144
1263
  const candidates = ["index.ts", "src/index.ts", "server.ts", "src/server.ts"];
145
1264
  for (const candidate of candidates) {
146
1265
  try {
147
- await (0, import_promises.access)(import_node_path.default.join(projectPath, candidate));
1266
+ await (0, import_promises.access)(import_node_path3.default.join(projectPath, candidate));
148
1267
  return candidate;
149
1268
  } catch {
150
1269
  continue;
@@ -153,18 +1272,18 @@ async function findServerFile(projectPath) {
153
1272
  throw new Error("No server file found");
154
1273
  }
155
1274
  async function buildWidgets(projectPath) {
156
- const { promises: fs } = await import("fs");
1275
+ const { promises: fs3 } = await import("fs");
157
1276
  const { build } = await import("vite");
158
- const resourcesDir = import_node_path.default.join(projectPath, "resources");
1277
+ const resourcesDir = import_node_path3.default.join(projectPath, "resources");
159
1278
  const mcpUrl = process.env.MCP_URL;
160
1279
  if (!mcpUrl) {
161
1280
  console.log(
162
- import_chalk.default.yellow(
1281
+ import_chalk3.default.yellow(
163
1282
  "\u26A0\uFE0F MCP_URL not set - using relative paths (widgets may not work correctly)"
164
1283
  )
165
1284
  );
166
1285
  console.log(
167
- import_chalk.default.gray(
1286
+ import_chalk3.default.gray(
168
1287
  " Set MCP_URL environment variable for production builds (e.g., https://myserver.com)"
169
1288
  )
170
1289
  );
@@ -173,39 +1292,39 @@ async function buildWidgets(projectPath) {
173
1292
  await (0, import_promises.access)(resourcesDir);
174
1293
  } catch {
175
1294
  console.log(
176
- import_chalk.default.gray("No resources/ directory found - skipping widget build")
1295
+ import_chalk3.default.gray("No resources/ directory found - skipping widget build")
177
1296
  );
178
1297
  return [];
179
1298
  }
180
1299
  let entries = [];
181
1300
  try {
182
- const files = await fs.readdir(resourcesDir);
183
- entries = files.filter((f) => f.endsWith(".tsx") || f.endsWith(".ts")).map((f) => import_node_path.default.join(resourcesDir, f));
1301
+ const files = await fs3.readdir(resourcesDir);
1302
+ entries = files.filter((f) => f.endsWith(".tsx") || f.endsWith(".ts")).map((f) => import_node_path3.default.join(resourcesDir, f));
184
1303
  } catch (error) {
185
- console.log(import_chalk.default.gray("No widgets found in resources/ directory"));
1304
+ console.log(import_chalk3.default.gray("No widgets found in resources/ directory"));
186
1305
  return [];
187
1306
  }
188
1307
  if (entries.length === 0) {
189
- console.log(import_chalk.default.gray("No widgets found in resources/ directory"));
1308
+ console.log(import_chalk3.default.gray("No widgets found in resources/ directory"));
190
1309
  return [];
191
1310
  }
192
- console.log(import_chalk.default.gray(`Building ${entries.length} widget(s)...`));
1311
+ console.log(import_chalk3.default.gray(`Building ${entries.length} widget(s)...`));
193
1312
  const react = (await import("@vitejs/plugin-react")).default;
194
1313
  const tailwindcss = (await import("@tailwindcss/vite")).default;
195
1314
  const builtWidgets = [];
196
1315
  for (const entry of entries) {
197
- const baseName = import_node_path.default.basename(entry).replace(/\.tsx?$/, "");
1316
+ const baseName = import_node_path3.default.basename(entry).replace(/\.tsx?$/, "");
198
1317
  const widgetName = baseName;
199
- console.log(import_chalk.default.gray(` - Building ${widgetName}...`));
200
- const tempDir = import_node_path.default.join(projectPath, ".mcp-use", widgetName);
201
- await fs.mkdir(tempDir, { recursive: true });
202
- const relativeResourcesPath = import_node_path.default.relative(tempDir, resourcesDir).replace(/\\/g, "/");
1318
+ console.log(import_chalk3.default.gray(` - Building ${widgetName}...`));
1319
+ const tempDir = import_node_path3.default.join(projectPath, ".mcp-use", widgetName);
1320
+ await fs3.mkdir(tempDir, { recursive: true });
1321
+ const relativeResourcesPath = import_node_path3.default.relative(tempDir, resourcesDir).replace(/\\/g, "/");
203
1322
  const cssContent = `@import "tailwindcss";
204
1323
 
205
1324
  /* Configure Tailwind to scan the resources directory */
206
1325
  @source "${relativeResourcesPath}";
207
1326
  `;
208
- await fs.writeFile(import_node_path.default.join(tempDir, "styles.css"), cssContent, "utf8");
1327
+ await fs3.writeFile(import_node_path3.default.join(tempDir, "styles.css"), cssContent, "utf8");
209
1328
  const entryContent = `import React from 'react'
210
1329
  import { createRoot } from 'react-dom/client'
211
1330
  import './styles.css'
@@ -229,9 +1348,9 @@ if (container && Component) {
229
1348
  <script type="module" src="/entry.tsx"></script>
230
1349
  </body>
231
1350
  </html>`;
232
- await fs.writeFile(import_node_path.default.join(tempDir, "entry.tsx"), entryContent, "utf8");
233
- await fs.writeFile(import_node_path.default.join(tempDir, "index.html"), htmlContent, "utf8");
234
- const outDir = import_node_path.default.join(
1351
+ await fs3.writeFile(import_node_path3.default.join(tempDir, "entry.tsx"), entryContent, "utf8");
1352
+ await fs3.writeFile(import_node_path3.default.join(tempDir, "index.html"), htmlContent, "utf8");
1353
+ const outDir = import_node_path3.default.join(
235
1354
  projectPath,
236
1355
  "dist",
237
1356
  "resources",
@@ -241,16 +1360,16 @@ if (container && Component) {
241
1360
  const baseUrl = mcpUrl ? `${mcpUrl}/${widgetName}/` : `/mcp-use/widgets/${widgetName}/`;
242
1361
  let widgetMetadata = {};
243
1362
  try {
244
- const metadataTempDir = import_node_path.default.join(
1363
+ const metadataTempDir = import_node_path3.default.join(
245
1364
  projectPath,
246
1365
  ".mcp-use",
247
1366
  `${widgetName}-metadata`
248
1367
  );
249
- await fs.mkdir(metadataTempDir, { recursive: true });
250
- const { createServer } = await import("vite");
251
- const metadataServer = await createServer({
1368
+ await fs3.mkdir(metadataTempDir, { recursive: true });
1369
+ const { createServer: createServer2 } = await import("vite");
1370
+ const metadataServer = await createServer2({
252
1371
  root: metadataTempDir,
253
- cacheDir: import_node_path.default.join(metadataTempDir, ".vite-cache"),
1372
+ cacheDir: import_node_path3.default.join(metadataTempDir, ".vite-cache"),
254
1373
  plugins: [tailwindcss(), react()],
255
1374
  resolve: {
256
1375
  alias: {
@@ -290,12 +1409,12 @@ if (container && Component) {
290
1409
  await new Promise((resolve) => setTimeout(resolve, 50));
291
1410
  } catch (error) {
292
1411
  console.warn(
293
- import_chalk.default.yellow(` \u26A0 Could not extract metadata for ${widgetName}`)
1412
+ import_chalk3.default.yellow(` \u26A0 Could not extract metadata for ${widgetName}`)
294
1413
  );
295
1414
  } finally {
296
1415
  await metadataServer.close();
297
1416
  try {
298
- await fs.rm(metadataTempDir, { recursive: true, force: true });
1417
+ await fs3.rm(metadataTempDir, { recursive: true, force: true });
299
1418
  } catch {
300
1419
  }
301
1420
  }
@@ -326,7 +1445,7 @@ if (container && Component) {
326
1445
  outDir,
327
1446
  emptyOutDir: true,
328
1447
  rollupOptions: {
329
- input: import_node_path.default.join(tempDir, "index.html")
1448
+ input: import_node_path3.default.join(tempDir, "index.html")
330
1449
  }
331
1450
  }
332
1451
  });
@@ -334,23 +1453,23 @@ if (container && Component) {
334
1453
  name: widgetName,
335
1454
  metadata: widgetMetadata
336
1455
  });
337
- console.log(import_chalk.default.green(` \u2713 Built ${widgetName}`));
1456
+ console.log(import_chalk3.default.green(` \u2713 Built ${widgetName}`));
338
1457
  } catch (error) {
339
- console.error(import_chalk.default.red(` \u2717 Failed to build ${widgetName}:`), error);
1458
+ console.error(import_chalk3.default.red(` \u2717 Failed to build ${widgetName}:`), error);
340
1459
  }
341
1460
  }
342
1461
  return builtWidgets;
343
1462
  }
344
1463
  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) => {
345
1464
  try {
346
- const projectPath = import_node_path.default.resolve(options.path);
347
- const { promises: fs } = await import("fs");
348
- console.log(import_chalk.default.cyan.bold(`mcp-use v${packageJson.version}`));
1465
+ const projectPath = import_node_path3.default.resolve(options.path);
1466
+ const { promises: fs3 } = await import("fs");
1467
+ console.log(import_chalk3.default.cyan.bold(`mcp-use v${packageJson.version}`));
349
1468
  const builtWidgets = await buildWidgets(projectPath);
350
- console.log(import_chalk.default.gray("Building TypeScript..."));
1469
+ console.log(import_chalk3.default.gray("Building TypeScript..."));
351
1470
  await runCommand("npx", ["tsc"], projectPath);
352
- console.log(import_chalk.default.green("\u2713 TypeScript build complete!"));
353
- const manifestPath = import_node_path.default.join(projectPath, "dist", "mcp-use.json");
1471
+ console.log(import_chalk3.default.green("\u2713 TypeScript build complete!"));
1472
+ const manifestPath = import_node_path3.default.join(projectPath, "dist", "mcp-use.json");
354
1473
  const widgetsData = {};
355
1474
  for (const widget of builtWidgets) {
356
1475
  widgetsData[widget.name] = widget.metadata;
@@ -361,36 +1480,36 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
361
1480
  buildTime: (/* @__PURE__ */ new Date()).toISOString(),
362
1481
  widgets: widgetsData
363
1482
  };
364
- await fs.mkdir(import_node_path.default.dirname(manifestPath), { recursive: true });
365
- await fs.writeFile(
1483
+ await fs3.mkdir(import_node_path3.default.dirname(manifestPath), { recursive: true });
1484
+ await fs3.writeFile(
366
1485
  manifestPath,
367
1486
  JSON.stringify(manifest, null, 2),
368
1487
  "utf8"
369
1488
  );
370
- console.log(import_chalk.default.green("\u2713 Build manifest created"));
371
- console.log(import_chalk.default.green.bold(`
1489
+ console.log(import_chalk3.default.green("\u2713 Build manifest created"));
1490
+ console.log(import_chalk3.default.green.bold(`
372
1491
  \u2713 Build complete!`));
373
1492
  if (builtWidgets.length > 0) {
374
- console.log(import_chalk.default.gray(` ${builtWidgets.length} widget(s) built`));
1493
+ console.log(import_chalk3.default.gray(` ${builtWidgets.length} widget(s) built`));
375
1494
  }
376
1495
  if (options.withInspector) {
377
- console.log(import_chalk.default.gray(" Inspector included"));
1496
+ console.log(import_chalk3.default.gray(" Inspector included"));
378
1497
  }
379
1498
  } catch (error) {
380
- console.error(import_chalk.default.red("Build failed:"), error);
1499
+ console.error(import_chalk3.default.red("Build failed:"), error);
381
1500
  process.exit(1);
382
1501
  }
383
1502
  });
384
1503
  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) => {
385
1504
  try {
386
- const projectPath = import_node_path.default.resolve(options.path);
1505
+ const projectPath = import_node_path3.default.resolve(options.path);
387
1506
  let port = parseInt(options.port, 10);
388
1507
  const host = options.host;
389
- console.log(import_chalk.default.cyan.bold(`mcp-use v${packageJson.version}`));
1508
+ console.log(import_chalk3.default.cyan.bold(`mcp-use v${packageJson.version}`));
390
1509
  if (!await isPortAvailable(port, host)) {
391
- console.log(import_chalk.default.yellow.bold(`\u26A0\uFE0F Port ${port} is already in use`));
392
- const availablePort = await findAvailablePort(port, host);
393
- console.log(import_chalk.default.green.bold(`\u2713 Using port ${availablePort} instead`));
1510
+ console.log(import_chalk3.default.yellow.bold(`\u26A0\uFE0F Port ${port} is already in use`));
1511
+ const availablePort = await findAvailablePort2(port, host);
1512
+ console.log(import_chalk3.default.green.bold(`\u2713 Using port ${availablePort} instead`));
394
1513
  port = availablePort;
395
1514
  }
396
1515
  let mcpUrl;
@@ -422,20 +1541,20 @@ program.command("dev").description("Run development server with auto-reload and
422
1541
  inspectorUrl += `&tunnelUrl=${encodeURIComponent(mcpUrl)}`;
423
1542
  }
424
1543
  const readyTime = Date.now() - startTime;
425
- console.log(import_chalk.default.green.bold(`\u2713 Ready in ${readyTime}ms`));
426
- console.log(import_chalk.default.whiteBright(`Local: http://${host}:${port}`));
427
- console.log(import_chalk.default.whiteBright(`Network: http://${host}:${port}`));
1544
+ console.log(import_chalk3.default.green.bold(`\u2713 Ready in ${readyTime}ms`));
1545
+ console.log(import_chalk3.default.whiteBright(`Local: http://${host}:${port}`));
1546
+ console.log(import_chalk3.default.whiteBright(`Network: http://${host}:${port}`));
428
1547
  if (mcpUrl) {
429
- console.log(import_chalk.default.whiteBright(`Tunnel: ${mcpUrl}`));
1548
+ console.log(import_chalk3.default.whiteBright(`Tunnel: ${mcpUrl}`));
430
1549
  }
431
- console.log(import_chalk.default.whiteBright(`MCP: ${mcpEndpoint}`));
432
- console.log(import_chalk.default.whiteBright(`Inspector: ${inspectorUrl}
1550
+ console.log(import_chalk3.default.whiteBright(`MCP: ${mcpEndpoint}`));
1551
+ console.log(import_chalk3.default.whiteBright(`Inspector: ${inspectorUrl}
433
1552
  `));
434
- await (0, import_open.default)(inspectorUrl);
1553
+ await (0, import_open3.default)(inspectorUrl);
435
1554
  }
436
1555
  }
437
1556
  const cleanup = () => {
438
- console.log(import_chalk.default.gray("\n\nShutting down..."));
1557
+ console.log(import_chalk3.default.gray("\n\nShutting down..."));
439
1558
  const processesToKill = processes.length;
440
1559
  let killedCount = 0;
441
1560
  const checkAndExit = () => {
@@ -466,13 +1585,13 @@ program.command("dev").description("Run development server with auto-reload and
466
1585
  await new Promise(() => {
467
1586
  });
468
1587
  } catch (error) {
469
- console.error(import_chalk.default.red("Dev mode failed:"), error);
1588
+ console.error(import_chalk3.default.red("Dev mode failed:"), error);
470
1589
  process.exit(1);
471
1590
  }
472
1591
  });
473
1592
  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) => {
474
1593
  try {
475
- const projectPath = import_node_path.default.resolve(options.path);
1594
+ const projectPath = import_node_path3.default.resolve(options.path);
476
1595
  const port = parseInt(options.port, 10);
477
1596
  console.log(
478
1597
  `\x1B[36m\x1B[1mmcp-use\x1B[0m \x1B[90mVersion: ${packageJson.version}\x1B[0m
@@ -486,13 +1605,13 @@ program.command("start").description("Start production server").option("-p, --pa
486
1605
  mcpUrl = tunnelInfo.subdomain;
487
1606
  tunnelProcess = tunnelInfo.process;
488
1607
  } catch (error) {
489
- console.error(import_chalk.default.red("Failed to start tunnel:"), error);
1608
+ console.error(import_chalk3.default.red("Failed to start tunnel:"), error);
490
1609
  process.exit(1);
491
1610
  }
492
1611
  }
493
1612
  let serverFile = "dist/index.js";
494
1613
  try {
495
- await (0, import_promises.access)(import_node_path.default.join(projectPath, serverFile));
1614
+ await (0, import_promises.access)(import_node_path3.default.join(projectPath, serverFile));
496
1615
  } catch {
497
1616
  serverFile = "dist/server.js";
498
1617
  }
@@ -504,9 +1623,9 @@ program.command("start").description("Start production server").option("-p, --pa
504
1623
  };
505
1624
  if (mcpUrl) {
506
1625
  env.MCP_URL = mcpUrl;
507
- console.log(import_chalk.default.whiteBright(`Tunnel: ${mcpUrl}`));
1626
+ console.log(import_chalk3.default.whiteBright(`Tunnel: ${mcpUrl}`));
508
1627
  }
509
- const serverProc = (0, import_node_child_process.spawn)("node", [serverFile], {
1628
+ const serverProc = (0, import_node_child_process3.spawn)("node", [serverFile], {
510
1629
  cwd: projectPath,
511
1630
  stdio: "inherit",
512
1631
  env
@@ -549,4 +1668,25 @@ program.command("start").description("Start production server").option("-p, --pa
549
1668
  process.exit(1);
550
1669
  }
551
1670
  });
1671
+ program.command("login").description("Login to mcp-use cloud").action(async () => {
1672
+ await loginCommand();
1673
+ });
1674
+ program.command("logout").description("Logout from mcp-use cloud").action(async () => {
1675
+ await logoutCommand();
1676
+ });
1677
+ program.command("whoami").description("Show current user information").action(async () => {
1678
+ await whoamiCommand();
1679
+ });
1680
+ program.command("deploy").description("Deploy MCP server to mcp-use cloud").option("--open", "Open deployment in browser after successful deploy").option("--name <name>", "Custom deployment name").option("--port <port>", "Server port", "3000").option("--runtime <runtime>", "Runtime (node or python)").option(
1681
+ "--from-source",
1682
+ "Deploy from local source code (even for GitHub repos)"
1683
+ ).action(async (options) => {
1684
+ await deployCommand({
1685
+ open: options.open,
1686
+ name: options.name,
1687
+ port: options.port ? parseInt(options.port, 10) : void 0,
1688
+ runtime: options.runtime,
1689
+ fromSource: options.fromSource
1690
+ });
1691
+ });
552
1692
  program.parse();