create-mcp-use-app 0.14.17 → 2.0.0-beta.0

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.
Files changed (27) hide show
  1. package/README.md +2 -8
  2. package/dist/ansi.d.ts +9 -0
  3. package/dist/ansi.d.ts.map +1 -0
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1768 -629
  6. package/dist/prompts.d.ts +16 -0
  7. package/dist/prompts.d.ts.map +1 -0
  8. package/dist/templates/blank/index.ts +4 -92
  9. package/dist/templates/blank/package.json +3 -12
  10. package/dist/templates/mcp-apps/index.ts +28 -122
  11. package/dist/templates/mcp-apps/package.json +7 -14
  12. package/dist/templates/mcp-apps/resources/product-search-result/view.tsx +26 -0
  13. package/dist/templates/mcp-apps/src/register.d.ts +7 -0
  14. package/dist/templates/mcp-apps/tsconfig.json +8 -14
  15. package/dist/templates/starter/index.ts +43 -80
  16. package/dist/templates/starter/package.json +5 -18
  17. package/package.json +4 -12
  18. package/dist/templates/mcp-apps/pnpm-workspace.yaml +0 -2
  19. package/dist/templates/mcp-apps/resources/product-search-result/components/Accordion.tsx +0 -35
  20. package/dist/templates/mcp-apps/resources/product-search-result/components/AccordionItem.tsx +0 -32
  21. package/dist/templates/mcp-apps/resources/product-search-result/components/Carousel.tsx +0 -51
  22. package/dist/templates/mcp-apps/resources/product-search-result/components/CarouselItem.tsx +0 -54
  23. package/dist/templates/mcp-apps/resources/product-search-result/components/CarouselSkeleton.tsx +0 -20
  24. package/dist/templates/mcp-apps/resources/product-search-result/hooks/useCarouselAnimation.ts +0 -78
  25. package/dist/templates/mcp-apps/resources/product-search-result/types.ts +0 -20
  26. package/dist/templates/mcp-apps/resources/product-search-result/widget.tsx +0 -288
  27. package/dist/templates/mcp-apps/resources/styles.css +0 -117
package/dist/index.js CHANGED
@@ -1,35 +1,1269 @@
1
1
  #!/usr/bin/env node
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+
28
+ // ../../node_modules/.pnpm/sisteransi@1.0.5/node_modules/sisteransi/src/index.js
29
+ var require_src = __commonJS({
30
+ "../../node_modules/.pnpm/sisteransi@1.0.5/node_modules/sisteransi/src/index.js"(exports, module) {
31
+ "use strict";
32
+ var ESC2 = "\x1B";
33
+ var CSI2 = `${ESC2}[`;
34
+ var beep = "\x07";
35
+ var cursor3 = {
36
+ to(x, y) {
37
+ if (!y) return `${CSI2}${x + 1}G`;
38
+ return `${CSI2}${y + 1};${x + 1}H`;
39
+ },
40
+ move(x, y) {
41
+ let ret = "";
42
+ if (x < 0) ret += `${CSI2}${-x}D`;
43
+ else if (x > 0) ret += `${CSI2}${x}C`;
44
+ if (y < 0) ret += `${CSI2}${-y}A`;
45
+ else if (y > 0) ret += `${CSI2}${y}B`;
46
+ return ret;
47
+ },
48
+ up: (count = 1) => `${CSI2}${count}A`,
49
+ down: (count = 1) => `${CSI2}${count}B`,
50
+ forward: (count = 1) => `${CSI2}${count}C`,
51
+ backward: (count = 1) => `${CSI2}${count}D`,
52
+ nextLine: (count = 1) => `${CSI2}E`.repeat(count),
53
+ prevLine: (count = 1) => `${CSI2}F`.repeat(count),
54
+ left: `${CSI2}G`,
55
+ hide: `${CSI2}?25l`,
56
+ show: `${CSI2}?25h`,
57
+ save: `${ESC2}7`,
58
+ restore: `${ESC2}8`
59
+ };
60
+ var scroll = {
61
+ up: (count = 1) => `${CSI2}S`.repeat(count),
62
+ down: (count = 1) => `${CSI2}T`.repeat(count)
63
+ };
64
+ var erase3 = {
65
+ screen: `${CSI2}2J`,
66
+ up: (count = 1) => `${CSI2}1J`.repeat(count),
67
+ down: (count = 1) => `${CSI2}J`.repeat(count),
68
+ line: `${CSI2}2K`,
69
+ lineEnd: `${CSI2}K`,
70
+ lineStart: `${CSI2}1K`,
71
+ lines(count) {
72
+ let clear = "";
73
+ for (let i2 = 0; i2 < count; i2++)
74
+ clear += this.line + (i2 < count - 1 ? cursor3.up() : "");
75
+ if (count)
76
+ clear += cursor3.left;
77
+ return clear;
78
+ }
79
+ };
80
+ module.exports = { cursor: cursor3, scroll, erase: erase3, beep };
81
+ }
82
+ });
2
83
 
3
- // src/index.tsx
4
- import chalk from "chalk";
5
- import { Command } from "commander";
6
- import { Box, render, Text } from "ink";
7
- import SelectInput from "ink-select-input";
8
- import TextInput from "ink-text-input";
84
+ // src/index.ts
9
85
  import { spawn, spawnSync } from "child_process";
10
86
  import {
11
87
  copyFileSync,
12
88
  cpSync,
13
- existsSync as existsSync2,
89
+ existsSync as existsSync3,
14
90
  mkdirSync,
15
91
  mkdtempSync,
16
- readdirSync as readdirSync2,
92
+ readdirSync as readdirSync3,
17
93
  readFileSync as readFileSync2,
18
94
  rmSync,
19
95
  writeFileSync as writeFileSync2
20
96
  } from "fs";
21
97
  import { tmpdir } from "os";
22
- import { dirname, join as join2 } from "path";
23
- import { Readable } from "stream";
24
- import { pipeline } from "stream/promises";
98
+ import { dirname as dirname2, join as join3 } from "path";
99
+ import { parseArgs } from "util";
25
100
  import { fileURLToPath } from "url";
26
- import ora from "ora";
27
- import React, { useState } from "react";
28
- import { extract } from "tar";
101
+
102
+ // src/ansi.ts
103
+ var wrap = (code) => (text2) => `\x1B[${code}m${text2}\x1B[0m`;
104
+ var bold = wrap("1");
105
+ var red = wrap("31");
106
+ var green = wrap("32");
107
+ var yellow = wrap("33");
108
+ var cyan = wrap("36");
109
+ var gray = wrap("90");
110
+ var white = wrap("37");
111
+ var whiteBold = (text2) => `\x1B[1;37m${text2}\x1B[0m`;
112
+
113
+ // ../../node_modules/.pnpm/@clack+core@1.4.3/node_modules/@clack/core/dist/index.mjs
114
+ import { styleText } from "util";
115
+ import { stdout, stdin } from "process";
116
+ import * as l from "readline";
117
+ import l__default from "readline";
118
+
119
+ // ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
120
+ var getCodePointsLength = /* @__PURE__ */ (() => {
121
+ const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
122
+ return (input) => {
123
+ let surrogatePairsNr = 0;
124
+ SURROGATE_PAIR_RE.lastIndex = 0;
125
+ while (SURROGATE_PAIR_RE.test(input)) {
126
+ surrogatePairsNr += 1;
127
+ }
128
+ return input.length - surrogatePairsNr;
129
+ };
130
+ })();
131
+ var isFullWidth = (x) => {
132
+ return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
133
+ };
134
+ var isWideNotCJKTNotEmoji = (x) => {
135
+ return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
136
+ };
137
+
138
+ // ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
139
+ var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
140
+ var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
141
+ var CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu;
142
+ var TAB_RE = /\t{1,1000}/y;
143
+ var EMOJI_RE = /[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/yu;
144
+ var LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
145
+ var MODIFIER_RE = /\p{M}+/gu;
146
+ var NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
147
+ var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
148
+ const LIMIT = truncationOptions.limit ?? Infinity;
149
+ const ELLIPSIS = truncationOptions.ellipsis ?? "";
150
+ const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
151
+ const ANSI_WIDTH = 0;
152
+ const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
153
+ const TAB_WIDTH = widthOptions.tabWidth ?? 8;
154
+ const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
155
+ const FULL_WIDTH_WIDTH = 2;
156
+ const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
157
+ const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
158
+ const PARSE_BLOCKS = [
159
+ [LATIN_RE, REGULAR_WIDTH],
160
+ [ANSI_RE, ANSI_WIDTH],
161
+ [CONTROL_RE, CONTROL_WIDTH],
162
+ [TAB_RE, TAB_WIDTH],
163
+ [EMOJI_RE, EMOJI_WIDTH],
164
+ [CJKT_WIDE_RE, WIDE_WIDTH]
165
+ ];
166
+ let indexPrev = 0;
167
+ let index = 0;
168
+ let length = input.length;
169
+ let lengthExtra = 0;
170
+ let truncationEnabled = false;
171
+ let truncationIndex = length;
172
+ let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
173
+ let unmatchedStart = 0;
174
+ let unmatchedEnd = 0;
175
+ let width = 0;
176
+ let widthExtra = 0;
177
+ outer: while (true) {
178
+ if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
179
+ const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
180
+ lengthExtra = 0;
181
+ for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
182
+ const codePoint = char.codePointAt(0) || 0;
183
+ if (isFullWidth(codePoint)) {
184
+ widthExtra = FULL_WIDTH_WIDTH;
185
+ } else if (isWideNotCJKTNotEmoji(codePoint)) {
186
+ widthExtra = WIDE_WIDTH;
187
+ } else {
188
+ widthExtra = REGULAR_WIDTH;
189
+ }
190
+ if (width + widthExtra > truncationLimit) {
191
+ truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
192
+ }
193
+ if (width + widthExtra > LIMIT) {
194
+ truncationEnabled = true;
195
+ break outer;
196
+ }
197
+ lengthExtra += char.length;
198
+ width += widthExtra;
199
+ }
200
+ unmatchedStart = unmatchedEnd = 0;
201
+ }
202
+ if (index >= length) {
203
+ break outer;
204
+ }
205
+ for (let i2 = 0, l2 = PARSE_BLOCKS.length; i2 < l2; i2++) {
206
+ const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i2];
207
+ BLOCK_RE.lastIndex = index;
208
+ if (BLOCK_RE.test(input)) {
209
+ lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
210
+ widthExtra = lengthExtra * BLOCK_WIDTH;
211
+ if (width + widthExtra > truncationLimit) {
212
+ truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
213
+ }
214
+ if (width + widthExtra > LIMIT) {
215
+ truncationEnabled = true;
216
+ break outer;
217
+ }
218
+ width += widthExtra;
219
+ unmatchedStart = indexPrev;
220
+ unmatchedEnd = index;
221
+ index = indexPrev = BLOCK_RE.lastIndex;
222
+ continue outer;
223
+ }
224
+ }
225
+ index += 1;
226
+ }
227
+ return {
228
+ width: truncationEnabled ? truncationLimit : width,
229
+ index: truncationEnabled ? truncationIndex : length,
230
+ truncated: truncationEnabled,
231
+ ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
232
+ };
233
+ };
234
+ var dist_default = getStringTruncatedWidth;
235
+
236
+ // ../../node_modules/.pnpm/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
237
+ var NO_TRUNCATION2 = {
238
+ limit: Infinity,
239
+ ellipsis: "",
240
+ ellipsisWidth: 0
241
+ };
242
+ var fastStringWidth = (input, options = {}) => {
243
+ return dist_default(input, NO_TRUNCATION2, options).width;
244
+ };
245
+ var dist_default2 = fastStringWidth;
246
+
247
+ // ../../node_modules/.pnpm/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
248
+ var ESC = "\x1B";
249
+ var CSI = "\x9B";
250
+ var END_CODE = 39;
251
+ var ANSI_ESCAPE_BELL = "\x07";
252
+ var ANSI_CSI = "[";
253
+ var ANSI_OSC = "]";
254
+ var ANSI_SGR_TERMINATOR = "m";
255
+ var ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
256
+ var GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
257
+ var getClosingCode = (openingCode) => {
258
+ if (openingCode >= 30 && openingCode <= 37)
259
+ return 39;
260
+ if (openingCode >= 90 && openingCode <= 97)
261
+ return 39;
262
+ if (openingCode >= 40 && openingCode <= 47)
263
+ return 49;
264
+ if (openingCode >= 100 && openingCode <= 107)
265
+ return 49;
266
+ if (openingCode === 1 || openingCode === 2)
267
+ return 22;
268
+ if (openingCode === 3)
269
+ return 23;
270
+ if (openingCode === 4)
271
+ return 24;
272
+ if (openingCode === 7)
273
+ return 27;
274
+ if (openingCode === 8)
275
+ return 28;
276
+ if (openingCode === 9)
277
+ return 29;
278
+ if (openingCode === 0)
279
+ return 0;
280
+ return void 0;
281
+ };
282
+ var wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
283
+ var wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
284
+ var wrapWord = (rows, word, columns) => {
285
+ const characters = word[Symbol.iterator]();
286
+ let isInsideEscape = false;
287
+ let isInsideLinkEscape = false;
288
+ let lastRow = rows.at(-1);
289
+ let visible = lastRow === void 0 ? 0 : dist_default2(lastRow);
290
+ let currentCharacter = characters.next();
291
+ let nextCharacter = characters.next();
292
+ let rawCharacterIndex = 0;
293
+ while (!currentCharacter.done) {
294
+ const character = currentCharacter.value;
295
+ const characterLength = dist_default2(character);
296
+ if (visible + characterLength <= columns) {
297
+ rows[rows.length - 1] += character;
298
+ } else {
299
+ rows.push(character);
300
+ visible = 0;
301
+ }
302
+ if (character === ESC || character === CSI) {
303
+ isInsideEscape = true;
304
+ isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
305
+ }
306
+ if (isInsideEscape) {
307
+ if (isInsideLinkEscape) {
308
+ if (character === ANSI_ESCAPE_BELL) {
309
+ isInsideEscape = false;
310
+ isInsideLinkEscape = false;
311
+ }
312
+ } else if (character === ANSI_SGR_TERMINATOR) {
313
+ isInsideEscape = false;
314
+ }
315
+ } else {
316
+ visible += characterLength;
317
+ if (visible === columns && !nextCharacter.done) {
318
+ rows.push("");
319
+ visible = 0;
320
+ }
321
+ }
322
+ currentCharacter = nextCharacter;
323
+ nextCharacter = characters.next();
324
+ rawCharacterIndex += character.length;
325
+ }
326
+ lastRow = rows.at(-1);
327
+ if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) {
328
+ rows[rows.length - 2] += rows.pop();
329
+ }
330
+ };
331
+ var stringVisibleTrimSpacesRight = (string) => {
332
+ const words = string.split(" ");
333
+ let last = words.length;
334
+ while (last) {
335
+ if (dist_default2(words[last - 1])) {
336
+ break;
337
+ }
338
+ last--;
339
+ }
340
+ if (last === words.length) {
341
+ return string;
342
+ }
343
+ return words.slice(0, last).join(" ") + words.slice(last).join("");
344
+ };
345
+ var exec = (string, columns, options = {}) => {
346
+ if (options.trim !== false && string.trim() === "") {
347
+ return "";
348
+ }
349
+ let returnValue = "";
350
+ let escapeCode;
351
+ let escapeUrl;
352
+ const words = string.split(" ");
353
+ let rows = [""];
354
+ let rowLength = 0;
355
+ for (let index = 0; index < words.length; index++) {
356
+ const word = words[index];
357
+ if (options.trim !== false) {
358
+ const row = rows.at(-1) ?? "";
359
+ const trimmed = row.trimStart();
360
+ if (row.length !== trimmed.length) {
361
+ rows[rows.length - 1] = trimmed;
362
+ rowLength = dist_default2(trimmed);
363
+ }
364
+ }
365
+ if (index !== 0) {
366
+ if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
367
+ rows.push("");
368
+ rowLength = 0;
369
+ }
370
+ if (rowLength || options.trim === false) {
371
+ rows[rows.length - 1] += " ";
372
+ rowLength++;
373
+ }
374
+ }
375
+ const wordLength = dist_default2(word);
376
+ if (options.hard && wordLength > columns) {
377
+ const remainingColumns = columns - rowLength;
378
+ const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
379
+ const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
380
+ if (breaksStartingNextLine < breaksStartingThisLine) {
381
+ rows.push("");
382
+ }
383
+ wrapWord(rows, word, columns);
384
+ rowLength = dist_default2(rows.at(-1) ?? "");
385
+ continue;
386
+ }
387
+ if (rowLength + wordLength > columns && rowLength && wordLength) {
388
+ if (options.wordWrap === false && rowLength < columns) {
389
+ wrapWord(rows, word, columns);
390
+ rowLength = dist_default2(rows.at(-1) ?? "");
391
+ continue;
392
+ }
393
+ rows.push("");
394
+ rowLength = 0;
395
+ }
396
+ if (rowLength + wordLength > columns && options.wordWrap === false) {
397
+ wrapWord(rows, word, columns);
398
+ rowLength = dist_default2(rows.at(-1) ?? "");
399
+ continue;
400
+ }
401
+ rows[rows.length - 1] += word;
402
+ rowLength += wordLength;
403
+ }
404
+ if (options.trim !== false) {
405
+ rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
406
+ }
407
+ const preString = rows.join("\n");
408
+ let inSurrogate = false;
409
+ for (let i2 = 0; i2 < preString.length; i2++) {
410
+ const character = preString[i2];
411
+ returnValue += character;
412
+ if (!inSurrogate) {
413
+ inSurrogate = character >= "\uD800" && character <= "\uDBFF";
414
+ if (inSurrogate) {
415
+ continue;
416
+ }
417
+ } else {
418
+ inSurrogate = false;
419
+ }
420
+ if (character === ESC || character === CSI) {
421
+ GROUP_REGEX.lastIndex = i2 + 1;
422
+ const groupsResult = GROUP_REGEX.exec(preString);
423
+ const groups = groupsResult?.groups;
424
+ if (groups?.code !== void 0) {
425
+ const code = Number.parseFloat(groups.code);
426
+ escapeCode = code === END_CODE ? void 0 : code;
427
+ } else if (groups?.uri !== void 0) {
428
+ escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
429
+ }
430
+ }
431
+ if (preString[i2 + 1] === "\n") {
432
+ if (escapeUrl) {
433
+ returnValue += wrapAnsiHyperlink("");
434
+ }
435
+ const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
436
+ if (escapeCode && closingCode) {
437
+ returnValue += wrapAnsiCode(closingCode);
438
+ }
439
+ } else if (character === "\n") {
440
+ if (escapeCode && getClosingCode(escapeCode)) {
441
+ returnValue += wrapAnsiCode(escapeCode);
442
+ }
443
+ if (escapeUrl) {
444
+ returnValue += wrapAnsiHyperlink(escapeUrl);
445
+ }
446
+ }
447
+ }
448
+ return returnValue;
449
+ };
450
+ var CRLF_OR_LF = /\r?\n/;
451
+ function wrapAnsi(string, columns, options) {
452
+ return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
453
+ }
454
+
455
+ // ../../node_modules/.pnpm/@clack+core@1.4.3/node_modules/@clack/core/dist/index.mjs
456
+ var import_sisteransi = __toESM(require_src(), 1);
457
+ import { ReadStream } from "tty";
458
+ function findCursor(s, o, l2) {
459
+ if (!l2.some((r2) => !r2.disabled))
460
+ return s;
461
+ const t2 = s + o, n3 = Math.max(l2.length - 1, 0), e = t2 < 0 ? n3 : t2 > n3 ? 0 : t2;
462
+ return l2[e]?.disabled ? findCursor(e, o < 0 ? -1 : 1, l2) : e;
463
+ }
464
+ var a$1 = ["up", "down", "left", "right", "space", "enter", "cancel"];
465
+ var t = [
466
+ "January",
467
+ "February",
468
+ "March",
469
+ "April",
470
+ "May",
471
+ "June",
472
+ "July",
473
+ "August",
474
+ "September",
475
+ "October",
476
+ "November",
477
+ "December"
478
+ ];
479
+ var settings = {
480
+ actions: new Set(a$1),
481
+ aliases: /* @__PURE__ */ new Map([
482
+ // vim support
483
+ ["k", "up"],
484
+ ["j", "down"],
485
+ ["h", "left"],
486
+ ["l", "right"],
487
+ ["", "cancel"],
488
+ // opinionated defaults!
489
+ ["escape", "cancel"]
490
+ ]),
491
+ messages: {
492
+ cancel: "Canceled",
493
+ error: "Something went wrong"
494
+ },
495
+ withGuide: true,
496
+ date: {
497
+ monthNames: [...t],
498
+ messages: {
499
+ required: "Please enter a valid date",
500
+ invalidMonth: "There are only 12 months in a year",
501
+ invalidDay: (n3, e) => `There are only ${n3} days in ${e}`,
502
+ afterMin: (n3) => `Date must be on or after ${n3.toISOString().slice(0, 10)}`,
503
+ beforeMax: (n3) => `Date must be on or before ${n3.toISOString().slice(0, 10)}`
504
+ }
505
+ }
506
+ };
507
+ function isActionKey(n3, e) {
508
+ if (typeof n3 == "string")
509
+ return settings.aliases.get(n3) === e;
510
+ for (const s of n3)
511
+ if (s !== void 0 && isActionKey(s, e))
512
+ return true;
513
+ return false;
514
+ }
515
+ function diffLines(i2, s) {
516
+ if (i2 === s) return;
517
+ const e = i2.split(`
518
+ `), t2 = s.split(`
519
+ `), r2 = Math.max(e.length, t2.length), f = [];
520
+ for (let n3 = 0; n3 < r2; n3++)
521
+ e[n3] !== t2[n3] && f.push(n3);
522
+ return {
523
+ lines: f,
524
+ numLinesBefore: e.length,
525
+ numLinesAfter: t2.length,
526
+ numLines: r2
527
+ };
528
+ }
529
+ var R = globalThis.process.platform.startsWith("win");
530
+ var CANCEL_SYMBOL = /* @__PURE__ */ Symbol("clack:cancel");
531
+ function isCancel(e) {
532
+ return e === CANCEL_SYMBOL;
533
+ }
534
+ function setRawMode(e, r2) {
535
+ const o = e;
536
+ o.isTTY && o.setRawMode(r2);
537
+ }
538
+ function block({
539
+ input: e = stdin,
540
+ output: r2 = stdout,
541
+ overwrite: o = true,
542
+ hideCursor: t2 = true
543
+ } = {}) {
544
+ const s = l.createInterface({
545
+ input: e,
546
+ output: r2,
547
+ prompt: "",
548
+ tabSize: 1
549
+ });
550
+ l.emitKeypressEvents(e, s), e instanceof ReadStream && e.isTTY && e.setRawMode(true);
551
+ const n3 = (f, { name: a2, sequence: p }) => {
552
+ const c2 = String(f);
553
+ if (isActionKey([c2, a2, p], "cancel")) {
554
+ t2 && r2.write(import_sisteransi.cursor.show), process.exit(0);
555
+ return;
556
+ }
557
+ if (!o) return;
558
+ const i2 = a2 === "return" ? 0 : -1, m = a2 === "return" ? -1 : 0;
559
+ l.moveCursor(r2, i2, m, () => {
560
+ l.clearLine(r2, 1, () => {
561
+ e.once("keypress", n3);
562
+ });
563
+ });
564
+ };
565
+ return t2 && r2.write(import_sisteransi.cursor.hide), e.once("keypress", n3), () => {
566
+ e.off("keypress", n3), t2 && r2.write(import_sisteransi.cursor.show), e instanceof ReadStream && e.isTTY && !R && e.setRawMode(false), s.terminal = false, s.close();
567
+ };
568
+ }
569
+ var getColumns = (e) => "columns" in e && typeof e.columns == "number" ? e.columns : 80;
570
+ var getRows = (e) => "rows" in e && typeof e.rows == "number" ? e.rows : 20;
571
+ function wrapTextWithPrefix(e, r2, o, t2 = o, s = o, n3) {
572
+ const f = getColumns(e ?? stdout);
573
+ return wrapAnsi(r2, f - o.length, {
574
+ hard: true,
575
+ trim: false
576
+ }).split(`
577
+ `).map((c2, i2, m) => {
578
+ const d = n3 ? n3(c2, i2) : c2;
579
+ return i2 === 0 ? `${t2}${d}` : i2 === m.length - 1 ? `${s}${d}` : `${o}${d}`;
580
+ }).join(`
581
+ `);
582
+ }
583
+ function runValidation(e, n3) {
584
+ if ("~standard" in e) {
585
+ const a2 = e["~standard"].validate(n3);
586
+ if (a2 instanceof Promise)
587
+ throw new TypeError(
588
+ "Schema validation must be synchronous. Update `validate()` and remove any asynchronous logic."
589
+ );
590
+ return a2.issues?.at(0)?.message;
591
+ }
592
+ return e(n3);
593
+ }
594
+ var V = class {
595
+ input;
596
+ output;
597
+ _abortSignal;
598
+ rl;
599
+ opts;
600
+ _render;
601
+ _track = false;
602
+ _prevFrame = "";
603
+ _subscribers = /* @__PURE__ */ new Map();
604
+ _cursor = 0;
605
+ state = "initial";
606
+ error = "";
607
+ value;
608
+ userInput = "";
609
+ constructor(t2, e = true) {
610
+ const { input: i2 = stdin, output: n3 = stdout, render: s, signal: r2, ...o } = t2;
611
+ this.opts = o, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = s.bind(this), this._track = e, this._abortSignal = r2, this.input = i2, this.output = n3;
612
+ }
613
+ /**
614
+ * Unsubscribe all listeners
615
+ */
616
+ unsubscribe() {
617
+ this._subscribers.clear();
618
+ }
619
+ /**
620
+ * Set a subscriber with opts
621
+ * @param event - The event name
622
+ */
623
+ setSubscriber(t2, e) {
624
+ const i2 = this._subscribers.get(t2) ?? [];
625
+ i2.push(e), this._subscribers.set(t2, i2);
626
+ }
627
+ /**
628
+ * Subscribe to an event
629
+ * @param event - The event name
630
+ * @param cb - The callback
631
+ */
632
+ on(t2, e) {
633
+ this.setSubscriber(t2, { cb: e });
634
+ }
635
+ /**
636
+ * Subscribe to an event once
637
+ * @param event - The event name
638
+ * @param cb - The callback
639
+ */
640
+ once(t2, e) {
641
+ this.setSubscriber(t2, { cb: e, once: true });
642
+ }
643
+ /**
644
+ * Emit an event with data
645
+ * @param event - The event name
646
+ * @param data - The data to pass to the callback
647
+ */
648
+ emit(t2, ...e) {
649
+ const i2 = this._subscribers.get(t2) ?? [], n3 = [];
650
+ for (const s of i2)
651
+ s.cb(...e), s.once && n3.push(() => i2.splice(i2.indexOf(s), 1));
652
+ for (const s of n3)
653
+ s();
654
+ }
655
+ prompt() {
656
+ return new Promise((t2) => {
657
+ if (this._abortSignal) {
658
+ if (this._abortSignal.aborted)
659
+ return this.state = "cancel", this.close(), t2(CANCEL_SYMBOL);
660
+ this._abortSignal.addEventListener(
661
+ "abort",
662
+ () => {
663
+ this.state = "cancel", this.close();
664
+ },
665
+ { once: true }
666
+ );
667
+ }
668
+ this.rl = l__default.createInterface({
669
+ input: this.input,
670
+ tabSize: 2,
671
+ prompt: "",
672
+ escapeCodeTimeout: 50,
673
+ terminal: true
674
+ }), this.rl.prompt(), this.opts.initialUserInput !== void 0 && this._setUserInput(this.opts.initialUserInput, true), this.input.on("keypress", this.onKeypress), setRawMode(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
675
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t2(this.value);
676
+ }), this.once("cancel", () => {
677
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t2(CANCEL_SYMBOL);
678
+ });
679
+ });
680
+ }
681
+ _isActionKey(t2, e) {
682
+ return t2 === " ";
683
+ }
684
+ _shouldSubmit(t2, e) {
685
+ return true;
686
+ }
687
+ _setValue(t2) {
688
+ this.value = t2, this.emit("value", this.value);
689
+ }
690
+ _setUserInput(t2, e) {
691
+ this.userInput = t2 ?? "", this.emit("userInput", this.userInput), e && this._track && this.rl && (this.rl.write(this.userInput), this._cursor = this.rl.cursor);
692
+ }
693
+ _clearUserInput() {
694
+ this.rl?.write(null, { ctrl: true, name: "u" }), this._setUserInput("");
695
+ }
696
+ onKeypress(t2, e) {
697
+ if (this._track && e.name !== "return" && (e.name && this._isActionKey(t2, e) && this.rl?.write(null, { ctrl: true, name: "h" }), this._cursor = this.rl?.cursor ?? 0, this._setUserInput(this.rl?.line)), this.state === "error" && (this.state = "active"), e?.name && (!this._track && settings.aliases.has(e.name) && this.emit("cursor", settings.aliases.get(e.name)), settings.actions.has(e.name) && this.emit("cursor", e.name)), t2 && (t2.toLowerCase() === "y" || t2.toLowerCase() === "n") && this.emit("confirm", t2.toLowerCase() === "y"), this.emit("key", t2, e), e?.name === "return" && this._shouldSubmit(t2, e)) {
698
+ if (this.opts.validate) {
699
+ const i2 = runValidation(this.opts.validate, this.value);
700
+ i2 && (this.error = i2 instanceof Error ? i2.message : i2, this.state = "error", this.rl?.write(this.userInput));
701
+ }
702
+ this.state !== "error" && (this.state = "submit");
703
+ }
704
+ isActionKey([t2, e?.name, e?.sequence], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
705
+ }
706
+ close() {
707
+ this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
708
+ `), setRawMode(this.input, false), this.rl?.close(), this.rl = void 0, this.emit(`${this.state}`, this.value), this.unsubscribe();
709
+ }
710
+ restoreCursor() {
711
+ const t2 = wrapAnsi(this._prevFrame, process.stdout.columns, { hard: true, trim: false }).split(`
712
+ `).length - 1;
713
+ this.output.write(import_sisteransi.cursor.move(-999, t2 * -1));
714
+ }
715
+ render() {
716
+ const t2 = wrapAnsi(this._render(this) ?? "", process.stdout.columns, {
717
+ hard: true,
718
+ trim: false
719
+ });
720
+ if (t2 !== this._prevFrame) {
721
+ if (this.state === "initial")
722
+ this.output.write(import_sisteransi.cursor.hide);
723
+ else {
724
+ const e = diffLines(this._prevFrame, t2), i2 = getRows(this.output);
725
+ if (this.restoreCursor(), e) {
726
+ const n3 = Math.max(0, e.numLinesAfter - i2), s = Math.max(0, e.numLinesBefore - i2);
727
+ let r2 = e.lines.find((o) => o >= n3);
728
+ if (r2 === void 0) {
729
+ this._prevFrame = t2;
730
+ return;
731
+ }
732
+ if (e.lines.length === 1) {
733
+ this.output.write(import_sisteransi.cursor.move(0, r2 - s)), this.output.write(import_sisteransi.erase.lines(1));
734
+ const o = t2.split(`
735
+ `);
736
+ this.output.write(o[r2]), this._prevFrame = t2, this.output.write(import_sisteransi.cursor.move(0, o.length - r2 - 1));
737
+ return;
738
+ } else if (e.lines.length > 1) {
739
+ if (n3 < s)
740
+ r2 = n3;
741
+ else {
742
+ const h2 = r2 - s;
743
+ h2 > 0 && this.output.write(import_sisteransi.cursor.move(0, h2));
744
+ }
745
+ this.output.write(import_sisteransi.erase.down());
746
+ const f = t2.split(`
747
+ `).slice(r2);
748
+ this.output.write(f.join(`
749
+ `)), this._prevFrame = t2;
750
+ return;
751
+ }
752
+ }
753
+ this.output.write(import_sisteransi.erase.down());
754
+ }
755
+ this.output.write(t2), this.state === "initial" && (this.state = "active"), this._prevFrame = t2;
756
+ }
757
+ }
758
+ };
759
+ var r = class extends V {
760
+ get cursor() {
761
+ return this.value ? 0 : 1;
762
+ }
763
+ get _value() {
764
+ return this.cursor === 0;
765
+ }
766
+ constructor(t2) {
767
+ super(t2, false), this.value = !!t2.initialValue, this.on("userInput", () => {
768
+ this.value = this._value;
769
+ }), this.on("confirm", (i2) => {
770
+ this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = i2, this.state = "submit", this.close();
771
+ }), this.on("cursor", () => {
772
+ this.value = !this.value;
773
+ });
774
+ }
775
+ };
776
+ var n$1 = class n extends V {
777
+ options;
778
+ cursor = 0;
779
+ get _selectedValue() {
780
+ return this.options[this.cursor];
781
+ }
782
+ changeValue() {
783
+ const e = this._selectedValue;
784
+ this.value = e === void 0 ? void 0 : e.value;
785
+ }
786
+ constructor(e) {
787
+ super(e, false), this.options = e.options;
788
+ const o = this.options.findIndex(({ value: s }) => s === e.initialValue), t2 = o === -1 ? 0 : o;
789
+ this.cursor = this.options[t2]?.disabled ? findCursor(t2, 1, this.options) : t2, this.changeValue(), this.on("cursor", (s) => {
790
+ switch (s) {
791
+ case "left":
792
+ case "up":
793
+ this.cursor = findCursor(this.cursor, -1, this.options);
794
+ break;
795
+ case "down":
796
+ case "right":
797
+ this.cursor = findCursor(this.cursor, 1, this.options);
798
+ break;
799
+ }
800
+ this.changeValue();
801
+ });
802
+ }
803
+ };
804
+ var n2 = class extends V {
805
+ get userInputWithCursor() {
806
+ if (this.state === "submit")
807
+ return this.userInput;
808
+ const t2 = this.userInput;
809
+ if (this.cursor >= t2.length)
810
+ return `${this.userInput}\u2588`;
811
+ const r2 = t2.slice(0, this.cursor), s = t2.slice(this.cursor, this.cursor + 1), e = t2.slice(this.cursor + 1);
812
+ return `${r2}${styleText("inverse", s)}${e}`;
813
+ }
814
+ get cursor() {
815
+ return this._cursor;
816
+ }
817
+ constructor(t2) {
818
+ super({
819
+ ...t2,
820
+ initialUserInput: t2.initialUserInput ?? t2.initialValue
821
+ }), this.on("userInput", (r2) => {
822
+ this._setValue(r2);
823
+ }), this.on("finalize", () => {
824
+ this.value || (this.value = t2.defaultValue), this.value === void 0 && (this.value = "");
825
+ });
826
+ }
827
+ };
828
+
829
+ // ../../node_modules/.pnpm/@clack+prompts@1.7.0/node_modules/@clack/prompts/dist/index.mjs
830
+ import { styleText as styleText2, stripVTControlCharacters } from "util";
831
+ import process$1 from "process";
832
+ var import_sisteransi2 = __toESM(require_src(), 1);
833
+ import { existsSync, lstatSync, readdirSync } from "fs";
834
+ import { dirname, join } from "path";
835
+ function isUnicodeSupported() {
836
+ if (process$1.platform !== "win32") {
837
+ return process$1.env.TERM !== "linux";
838
+ }
839
+ return Boolean(process$1.env.CI) || Boolean(process$1.env.WT_SESSION) || Boolean(process$1.env.TERMINUS_SUBLIME) || process$1.env.ConEmuTask === "{cmd::Cmder}" || process$1.env.TERM_PROGRAM === "Terminus-Sublime" || process$1.env.TERM_PROGRAM === "vscode" || process$1.env.TERM === "xterm-256color" || process$1.env.TERM === "alacritty" || process$1.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
840
+ }
841
+ var unicode = isUnicodeSupported();
842
+ var isCI = () => process.env.CI === "true";
843
+ var unicodeOr = (o, e) => unicode ? o : e;
844
+ var S_STEP_ACTIVE = unicodeOr("\u25C6", "*");
845
+ var S_STEP_CANCEL = unicodeOr("\u25A0", "x");
846
+ var S_STEP_ERROR = unicodeOr("\u25B2", "x");
847
+ var S_STEP_SUBMIT = unicodeOr("\u25C7", "o");
848
+ var S_BAR_START = unicodeOr("\u250C", "T");
849
+ var S_BAR = unicodeOr("\u2502", "|");
850
+ var S_BAR_END = unicodeOr("\u2514", "\u2014");
851
+ var S_BAR_START_RIGHT = unicodeOr("\u2510", "T");
852
+ var S_BAR_END_RIGHT = unicodeOr("\u2518", "\u2014");
853
+ var S_RADIO_ACTIVE = unicodeOr("\u25CF", ">");
854
+ var S_RADIO_INACTIVE = unicodeOr("\u25CB", " ");
855
+ var S_CHECKBOX_ACTIVE = unicodeOr("\u25FB", "[\u2022]");
856
+ var S_CHECKBOX_SELECTED = unicodeOr("\u25FC", "[+]");
857
+ var S_CHECKBOX_INACTIVE = unicodeOr("\u25FB", "[ ]");
858
+ var S_PASSWORD_MASK = unicodeOr("\u25AA", "\u2022");
859
+ var S_BAR_H = unicodeOr("\u2500", "-");
860
+ var S_CORNER_TOP_RIGHT = unicodeOr("\u256E", "+");
861
+ var S_CONNECT_LEFT = unicodeOr("\u251C", "+");
862
+ var S_CORNER_BOTTOM_RIGHT = unicodeOr("\u256F", "+");
863
+ var S_CORNER_BOTTOM_LEFT = unicodeOr("\u2570", "+");
864
+ var S_CORNER_TOP_LEFT = unicodeOr("\u256D", "+");
865
+ var S_INFO = unicodeOr("\u25CF", "\u2022");
866
+ var S_SUCCESS = unicodeOr("\u25C6", "*");
867
+ var S_WARN = unicodeOr("\u25B2", "!");
868
+ var S_ERROR = unicodeOr("\u25A0", "x");
869
+ var symbol = (o) => {
870
+ switch (o) {
871
+ case "initial":
872
+ case "active":
873
+ return styleText2("cyan", S_STEP_ACTIVE);
874
+ case "cancel":
875
+ return styleText2("red", S_STEP_CANCEL);
876
+ case "error":
877
+ return styleText2("yellow", S_STEP_ERROR);
878
+ case "submit":
879
+ return styleText2("green", S_STEP_SUBMIT);
880
+ }
881
+ };
882
+ var symbolBar = (o) => {
883
+ switch (o) {
884
+ case "initial":
885
+ case "active":
886
+ return styleText2("cyan", S_BAR);
887
+ case "cancel":
888
+ return styleText2("red", S_BAR);
889
+ case "error":
890
+ return styleText2("yellow", S_BAR);
891
+ case "submit":
892
+ return styleText2("green", S_BAR);
893
+ }
894
+ };
895
+ function formatInstructionFooter(o, e) {
896
+ const r2 = [`${e ? `${styleText2("cyan", S_BAR)} ` : ""}${o.join(" \u2022 ")}`];
897
+ return e && r2.push(styleText2("cyan", S_BAR_END)), r2;
898
+ }
899
+ var I = (l2, e, w, p, b, C = false) => {
900
+ let r2 = e, O = 0;
901
+ if (C)
902
+ for (let i2 = p - 1; i2 >= w; i2--) {
903
+ const m = l2[i2];
904
+ if (m && (r2 -= m.length), O++, r2 <= b) break;
905
+ }
906
+ else
907
+ for (let i2 = w; i2 < p; i2++) {
908
+ const m = l2[i2];
909
+ if (m && (r2 -= m.length), O++, r2 <= b) break;
910
+ }
911
+ return { lineCount: r2, removals: O };
912
+ };
913
+ var limitOptions = ({
914
+ cursor: l2,
915
+ options: e,
916
+ style: w,
917
+ output: p = process.stdout,
918
+ maxItems: b = Number.POSITIVE_INFINITY,
919
+ columnPadding: C = 0,
920
+ rowPadding: r2 = 4
921
+ }) => {
922
+ const i2 = getColumns(p) - C, m = getRows(p), M = styleText2("dim", "..."), v = Math.max(m - r2, 0), a2 = Math.max(Math.min(b, v), 5);
923
+ let f = 0;
924
+ l2 >= a2 - 3 && (f = Math.max(
925
+ Math.min(l2 - a2 + 3, e.length - a2),
926
+ 0
927
+ ));
928
+ let d = a2 < e.length && f > 0, c2 = a2 < e.length && f + a2 < e.length;
929
+ const W2 = Math.min(
930
+ f + a2,
931
+ e.length
932
+ ), s = [];
933
+ let g = 0;
934
+ d && g++, c2 && g++;
935
+ const T = f + (d ? 1 : 0), y = W2 - (c2 ? 1 : 0);
936
+ for (let t2 = T; t2 < y; t2++) {
937
+ const n3 = e[t2], o = n3 ? w(n3, t2 === l2) : "", h2 = wrapAnsi(o, i2, {
938
+ hard: true,
939
+ trim: false
940
+ }).split(`
941
+ `);
942
+ s.push(h2), g += h2.length;
943
+ }
944
+ if (g > v) {
945
+ let t2 = 0, n3 = 0, o = g;
946
+ const h2 = l2 - T;
947
+ let u3 = v;
948
+ const L = () => I(s, o, 0, h2, u3), E = () => I(
949
+ s,
950
+ o,
951
+ h2 + 1,
952
+ s.length,
953
+ u3,
954
+ true
955
+ );
956
+ d ? ({ lineCount: o, removals: t2 } = L(), o > u3 && (c2 || (u3 -= 1), { lineCount: o, removals: n3 } = E())) : (c2 || (u3 -= 1), { lineCount: o, removals: n3 } = E(), o > u3 && (u3 -= 1, { lineCount: o, removals: t2 } = L())), t2 > 0 && (d = true, s.splice(0, t2)), n3 > 0 && (c2 = true, s.splice(s.length - n3, n3));
957
+ }
958
+ const x = [];
959
+ d && x.push(M);
960
+ for (const t2 of s)
961
+ for (const n3 of t2)
962
+ x.push(n3);
963
+ return c2 && x.push(M), x;
964
+ };
965
+ var confirm = (i2) => {
966
+ const a2 = i2.active ?? "Yes", s = i2.inactive ?? "No";
967
+ return new r({
968
+ active: a2,
969
+ inactive: s,
970
+ signal: i2.signal,
971
+ input: i2.input,
972
+ output: i2.output,
973
+ initialValue: i2.initialValue ?? true,
974
+ render() {
975
+ const e = i2.withGuide ?? settings.withGuide, u3 = `${symbol(this.state)} `, l2 = e ? `${styleText2("gray", S_BAR)} ` : "", f = wrapTextWithPrefix(
976
+ i2.output,
977
+ i2.message,
978
+ l2,
979
+ u3
980
+ ), o = `${e ? `${styleText2("gray", S_BAR)}
981
+ ` : ""}${f}
982
+ `, c2 = this.value ? a2 : s;
983
+ switch (this.state) {
984
+ case "submit": {
985
+ const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
986
+ return `${o}${r2}${styleText2("dim", c2)}`;
987
+ }
988
+ case "cancel": {
989
+ const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
990
+ return `${o}${r2}${styleText2(["strikethrough", "dim"], c2)}${e ? `
991
+ ${styleText2("gray", S_BAR)}` : ""}`;
992
+ }
993
+ default: {
994
+ const r2 = e ? `${styleText2("cyan", S_BAR)} ` : "", g = e ? styleText2("cyan", S_BAR_END) : "";
995
+ return `${o}${r2}${this.value ? `${styleText2("green", S_RADIO_ACTIVE)} ${a2}` : `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", a2)}`}${i2.vertical ? e ? `
996
+ ${styleText2("cyan", S_BAR)} ` : `
997
+ ` : ` ${styleText2("dim", "/")} `}${this.value ? `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", s)}` : `${styleText2("green", S_RADIO_ACTIVE)} ${s}`}
998
+ ${g}
999
+ `;
1000
+ }
1001
+ }
1002
+ }
1003
+ }).prompt();
1004
+ };
1005
+ var MULTISELECT_INSTRUCTIONS = [
1006
+ `${styleText2("dim", "\u2191/\u2193")} to navigate`,
1007
+ `${styleText2("dim", "Space:")} select`,
1008
+ `${styleText2("dim", "Enter:")} confirm`
1009
+ ];
1010
+ var cancel = (o = "", t2) => {
1011
+ const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_END)} ` : "";
1012
+ i2.write(`${e}${styleText2("red", o)}
1013
+
1014
+ `);
1015
+ };
1016
+ var W = (l2) => styleText2("magenta", l2);
1017
+ var spinner = ({
1018
+ indicator: l2 = "dots",
1019
+ onCancel: h2,
1020
+ output: n3 = process.stdout,
1021
+ cancelMessage: G,
1022
+ errorMessage: O,
1023
+ frames: E = unicode ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"],
1024
+ delay: F = unicode ? 80 : 120,
1025
+ signal: m,
1026
+ ...I2
1027
+ } = {}) => {
1028
+ const u3 = isCI();
1029
+ let M, T, d = false, S = false, s = "", p, w = performance.now();
1030
+ const x = getColumns(n3), k = I2?.styleFrame ?? W, g = (e) => {
1031
+ const r2 = e > 1 ? O ?? settings.messages.error : G ?? settings.messages.cancel;
1032
+ S = e === 1, d && (a2(r2, e), S && typeof h2 == "function" && h2());
1033
+ }, f = () => g(2), i2 = () => g(1), A = () => {
1034
+ process.on("uncaughtExceptionMonitor", f), process.on("unhandledRejection", f), process.on("SIGINT", i2), process.on("SIGTERM", i2), process.on("exit", g), m && m.addEventListener("abort", i2);
1035
+ }, H = () => {
1036
+ process.removeListener("uncaughtExceptionMonitor", f), process.removeListener("unhandledRejection", f), process.removeListener("SIGINT", i2), process.removeListener("SIGTERM", i2), process.removeListener("exit", g), m && m.removeEventListener("abort", i2);
1037
+ }, y = () => {
1038
+ if (p === void 0) return;
1039
+ u3 && n3.write(`
1040
+ `);
1041
+ const r2 = wrapAnsi(p, x, {
1042
+ hard: true,
1043
+ trim: false
1044
+ }).split(`
1045
+ `);
1046
+ r2.length > 1 && n3.write(import_sisteransi2.cursor.up(r2.length - 1)), n3.write(import_sisteransi2.cursor.to(0)), n3.write(import_sisteransi2.erase.down());
1047
+ }, C = (e) => e.replace(/\.+$/, ""), _ = (e) => {
1048
+ const r2 = (performance.now() - e) / 1e3, t2 = Math.floor(r2 / 60), o = Math.floor(r2 % 60);
1049
+ return t2 > 0 ? `[${t2}m ${o}s]` : `[${o}s]`;
1050
+ }, N = I2.withGuide ?? settings.withGuide, P = (e = "") => {
1051
+ d = true, M = block({ output: n3 }), s = C(e), w = performance.now(), N && n3.write(`${styleText2("gray", S_BAR)}
1052
+ `);
1053
+ let r2 = 0, t2 = 0;
1054
+ A(), T = setInterval(() => {
1055
+ if (u3 && s === p)
1056
+ return;
1057
+ y(), p = s;
1058
+ const o = k(E[r2]);
1059
+ let v;
1060
+ if (u3)
1061
+ v = `${o} ${s}...`;
1062
+ else if (l2 === "timer")
1063
+ v = `${o} ${s} ${_(w)}`;
1064
+ else {
1065
+ const B = ".".repeat(Math.floor(t2)).slice(0, 3);
1066
+ v = `${o} ${s}${B}`;
1067
+ }
1068
+ const j = wrapAnsi(v, x, {
1069
+ hard: true,
1070
+ trim: false
1071
+ });
1072
+ n3.write(j), r2 = r2 + 1 < E.length ? r2 + 1 : 0, t2 = t2 < 4 ? t2 + 0.125 : 0;
1073
+ }, F);
1074
+ }, a2 = (e = "", r2 = 0, t2 = false) => {
1075
+ if (!d) return;
1076
+ d = false, clearInterval(T), y();
1077
+ const o = r2 === 0 ? styleText2("green", S_STEP_SUBMIT) : r2 === 1 ? styleText2("red", S_STEP_CANCEL) : styleText2("red", S_STEP_ERROR);
1078
+ s = e ?? s, t2 || (l2 === "timer" ? n3.write(`${o} ${s} ${_(w)}
1079
+ `) : n3.write(`${o} ${s}
1080
+ `)), H(), M();
1081
+ };
1082
+ return {
1083
+ start: P,
1084
+ stop: (e = "") => a2(e, 0),
1085
+ message: (e = "") => {
1086
+ s = C(e ?? s);
1087
+ },
1088
+ cancel: (e = "") => a2(e, 1),
1089
+ error: (e = "") => a2(e, 2),
1090
+ clear: () => a2("", 0, true),
1091
+ get isCancelled() {
1092
+ return S;
1093
+ }
1094
+ };
1095
+ };
1096
+ var u2 = {
1097
+ light: unicodeOr("\u2500", "-"),
1098
+ heavy: unicodeOr("\u2501", "="),
1099
+ block: unicodeOr("\u2588", "#")
1100
+ };
1101
+ var SELECT_INSTRUCTIONS = [
1102
+ `${styleText2("dim", "\u2191/\u2193")} to navigate`,
1103
+ `${styleText2("dim", "Enter:")} confirm`
1104
+ ];
1105
+ var c = (t2, o) => t2.includes(`
1106
+ `) ? t2.split(`
1107
+ `).map((d) => o(d)).join(`
1108
+ `) : o(t2);
1109
+ var select = (t2) => {
1110
+ const o = (n3, m) => {
1111
+ if (n3 === void 0)
1112
+ return "";
1113
+ const s = n3.label ?? String(n3.value);
1114
+ switch (m) {
1115
+ case "disabled":
1116
+ return `${styleText2("gray", S_RADIO_INACTIVE)} ${c(s, (i2) => styleText2("gray", i2))}${n3.hint ? ` ${styleText2("dim", `(${n3.hint ?? "disabled"})`)}` : ""}`;
1117
+ case "selected":
1118
+ return `${c(s, (i2) => styleText2("dim", i2))}`;
1119
+ case "active":
1120
+ return `${styleText2("green", S_RADIO_ACTIVE)} ${s}${n3.hint ? ` ${styleText2("dim", `(${n3.hint})`)}` : ""}`;
1121
+ case "cancelled":
1122
+ return `${c(s, (i2) => styleText2(["strikethrough", "dim"], i2))}`;
1123
+ default:
1124
+ return `${styleText2("dim", S_RADIO_INACTIVE)} ${c(s, (i2) => styleText2("dim", i2))}`;
1125
+ }
1126
+ }, d = t2.showInstructions ?? true;
1127
+ return new n$1({
1128
+ options: t2.options,
1129
+ signal: t2.signal,
1130
+ input: t2.input,
1131
+ output: t2.output,
1132
+ initialValue: t2.initialValue,
1133
+ render() {
1134
+ const n3 = t2.withGuide ?? settings.withGuide, m = `${symbol(this.state)} `, s = `${symbolBar(this.state)} `, i2 = wrapTextWithPrefix(
1135
+ t2.output,
1136
+ t2.message,
1137
+ s,
1138
+ m
1139
+ ), u3 = `${n3 ? `${styleText2("gray", S_BAR)}
1140
+ ` : ""}${i2}
1141
+ `;
1142
+ switch (this.state) {
1143
+ case "submit": {
1144
+ const r2 = n3 ? `${styleText2("gray", S_BAR)} ` : "", a2 = wrapTextWithPrefix(
1145
+ t2.output,
1146
+ o(this.options[this.cursor], "selected"),
1147
+ r2
1148
+ );
1149
+ return `${u3}${a2}`;
1150
+ }
1151
+ case "cancel": {
1152
+ const r2 = n3 ? `${styleText2("gray", S_BAR)} ` : "", a2 = wrapTextWithPrefix(
1153
+ t2.output,
1154
+ o(this.options[this.cursor], "cancelled"),
1155
+ r2
1156
+ );
1157
+ return `${u3}${a2}${n3 ? `
1158
+ ${styleText2("gray", S_BAR)}` : ""}`;
1159
+ }
1160
+ default: {
1161
+ const r2 = n3 ? `${styleText2("cyan", S_BAR)} ` : "", a2 = u3.split(`
1162
+ `).length, p = d ? formatInstructionFooter(SELECT_INSTRUCTIONS, n3) : n3 ? [styleText2("cyan", S_BAR_END)] : [], b = p.join(`
1163
+ `), f = p.length + 1;
1164
+ return `${u3}${r2}${limitOptions({
1165
+ output: t2.output,
1166
+ cursor: this.cursor,
1167
+ options: this.options,
1168
+ maxItems: t2.maxItems,
1169
+ columnPadding: r2.length,
1170
+ rowPadding: a2 + f,
1171
+ style: (g, x) => o(g, g.disabled ? "disabled" : x ? "active" : "inactive")
1172
+ }).join(`
1173
+ ${r2}`)}
1174
+ ${b}
1175
+ `;
1176
+ }
1177
+ }
1178
+ }
1179
+ }).prompt();
1180
+ };
1181
+ var i = `${styleText2("gray", S_BAR)} `;
1182
+ var text = (e) => new n2({
1183
+ validate: e.validate,
1184
+ placeholder: e.placeholder,
1185
+ defaultValue: e.defaultValue,
1186
+ initialValue: e.initialValue,
1187
+ output: e.output,
1188
+ signal: e.signal,
1189
+ input: e.input,
1190
+ render() {
1191
+ const i2 = e?.withGuide ?? settings.withGuide, s = `${`${i2 ? `${styleText2("gray", S_BAR)}
1192
+ ` : ""}${symbol(this.state)} `}${e.message}
1193
+ `, c2 = e.placeholder && e.placeholder.length > 0 ? (
1194
+ // biome-ignore lint/style/noNonNullAssertion: guarded by placeholder.length > 0
1195
+ styleText2("inverse", e.placeholder[0]) + styleText2("dim", e.placeholder.slice(1))
1196
+ ) : styleText2(["inverse", "hidden"], "_"), o = this.userInput ? this.userInputWithCursor : c2, l2 = this.value ?? "";
1197
+ switch (this.state) {
1198
+ case "error": {
1199
+ const n3 = this.error ? ` ${styleText2("yellow", this.error)}` : "", r2 = i2 ? `${styleText2("yellow", S_BAR)} ` : "", d = i2 ? styleText2("yellow", S_BAR_END) : "";
1200
+ return `${s.trim()}
1201
+ ${r2}${o}
1202
+ ${d}${n3}
1203
+ `;
1204
+ }
1205
+ case "submit": {
1206
+ const n3 = l2 ? ` ${styleText2("dim", l2)}` : "", r2 = i2 ? styleText2("gray", S_BAR) : "";
1207
+ return `${s}${r2}${n3}`;
1208
+ }
1209
+ case "cancel": {
1210
+ const n3 = l2 ? ` ${styleText2(["strikethrough", "dim"], l2)}` : "", r2 = i2 ? styleText2("gray", S_BAR) : "";
1211
+ return `${s}${r2}${n3}${l2.trim() ? `
1212
+ ${r2}` : ""}`;
1213
+ }
1214
+ default: {
1215
+ const n3 = i2 ? `${styleText2("cyan", S_BAR)} ` : "", r2 = i2 ? styleText2("cyan", S_BAR_END) : "";
1216
+ return `${s}${n3}${o}
1217
+ ${r2}
1218
+ `;
1219
+ }
1220
+ }
1221
+ }
1222
+ }).prompt();
1223
+
1224
+ // src/prompts.ts
1225
+ function isInteractive() {
1226
+ return process.stdin.isTTY === true;
1227
+ }
1228
+ function handleCancel(value) {
1229
+ if (isCancel(value)) {
1230
+ cancel("Operation cancelled");
1231
+ process.exit(0);
1232
+ }
1233
+ return value;
1234
+ }
1235
+ async function promptText(message, options = {}) {
1236
+ const result = await text({
1237
+ message,
1238
+ defaultValue: options.defaultValue,
1239
+ placeholder: options.defaultValue,
1240
+ validate: options.validate ? (value) => options.validate(value ?? "") : void 0
1241
+ });
1242
+ return handleCancel(result);
1243
+ }
1244
+ async function promptConfirm(message, initialValue = true) {
1245
+ const result = await confirm({ message, initialValue });
1246
+ return handleCancel(result);
1247
+ }
1248
+ async function promptSelect(message, items, defaultIndex = 0) {
1249
+ if (items.length === 0) {
1250
+ throw new Error("No items to select");
1251
+ }
1252
+ const result = await select({
1253
+ message,
1254
+ options: items.map((item) => ({
1255
+ value: item.value,
1256
+ label: item.label
1257
+ })),
1258
+ initialValue: items[defaultIndex]?.value
1259
+ });
1260
+ return handleCancel(result);
1261
+ }
1262
+ var spinner2 = spinner;
29
1263
 
30
1264
  // src/utils.ts
31
- import { existsSync, readdirSync, readFileSync, writeFileSync } from "fs";
32
- import { basename, join, resolve } from "path";
1265
+ import { existsSync as existsSync2, readdirSync as readdirSync2, readFileSync, writeFileSync } from "fs";
1266
+ import { basename, join as join2, resolve } from "path";
33
1267
  var SAFE_DIR_ENTRIES = /* @__PURE__ */ new Set([
34
1268
  ".claude",
35
1269
  ".cursor",
@@ -60,7 +1294,7 @@ function isSafeEntry(name) {
60
1294
  return SAFE_DIR_ENTRIES.has(name);
61
1295
  }
62
1296
  function findUnsafeEntries(dir) {
63
- return readdirSync(dir).filter((entry) => !isSafeEntry(entry)).sort();
1297
+ return readdirSync2(dir).filter((entry) => !isSafeEntry(entry)).sort();
64
1298
  }
65
1299
  function sanitizePackageName(raw) {
66
1300
  return raw.toLowerCase().replace(/[^a-z0-9_.-]/g, "-").replace(/^[.-]+/, "").replace(/[.-]+$/, "") || "my-app";
@@ -84,15 +1318,15 @@ function deriveProjectInfo(rawName, cwd) {
84
1318
  };
85
1319
  }
86
1320
  function updatePackageJson(projectPath, projectName) {
87
- const packageJsonPath = join(projectPath, "package.json");
1321
+ const packageJsonPath = join2(projectPath, "package.json");
88
1322
  const packageJsonContent = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
89
1323
  packageJsonContent.name = projectName;
90
1324
  packageJsonContent.description = `MCP server: ${projectName}`;
91
1325
  writeFileSync(packageJsonPath, JSON.stringify(packageJsonContent, null, 2));
92
1326
  }
93
1327
  function updateIndexTs(projectPath, projectName) {
94
- const indexPath = join(projectPath, "index.ts");
95
- if (!existsSync(indexPath)) {
1328
+ const indexPath = join2(projectPath, "index.ts");
1329
+ if (!existsSync2(indexPath)) {
96
1330
  return;
97
1331
  }
98
1332
  let content = readFileSync(indexPath, "utf-8");
@@ -100,9 +1334,45 @@ function updateIndexTs(projectPath, projectName) {
100
1334
  writeFileSync(indexPath, content);
101
1335
  }
102
1336
 
103
- // src/index.tsx
1337
+ // src/index.ts
104
1338
  var __filename = fileURLToPath(import.meta.url);
105
- var __dirname = dirname(__filename);
1339
+ var __dirname = dirname2(__filename);
1340
+ function parseCli(argv) {
1341
+ const { values, positionals } = parseArgs({
1342
+ args: argv,
1343
+ options: {
1344
+ template: { type: "string", short: "t" },
1345
+ "list-templates": { type: "boolean" },
1346
+ install: { type: "boolean" },
1347
+ skills: { type: "boolean" },
1348
+ dev: { type: "boolean" },
1349
+ canary: { type: "boolean" },
1350
+ yarn: { type: "boolean" },
1351
+ npm: { type: "boolean" },
1352
+ pnpm: { type: "boolean" },
1353
+ help: { type: "boolean", short: "h" },
1354
+ version: { type: "boolean", short: "V" }
1355
+ },
1356
+ allowPositionals: true,
1357
+ strict: false
1358
+ });
1359
+ const install = argv.includes("--install") ? true : argv.includes("--no-install") ? false : values.install;
1360
+ const skills = argv.includes("--skills") ? true : argv.includes("--no-skills") ? false : values.skills;
1361
+ return {
1362
+ projectName: positionals[0],
1363
+ options: {
1364
+ template: values.template,
1365
+ listTemplates: values["list-templates"],
1366
+ install,
1367
+ skills,
1368
+ dev: values.dev,
1369
+ canary: values.canary,
1370
+ yarn: values.yarn,
1371
+ npm: values.npm,
1372
+ pnpm: values.pnpm
1373
+ }
1374
+ };
1375
+ }
106
1376
  function runPackageManager(packageManager, args, cwd) {
107
1377
  return new Promise((resolve2, reject) => {
108
1378
  const child = spawn(packageManager, args, {
@@ -131,9 +1401,11 @@ function detectPackageManager() {
131
1401
  const userAgent = process.env.npm_config_user_agent || "";
132
1402
  if (userAgent.includes("yarn")) {
133
1403
  return "yarn";
134
- } else if (userAgent.includes("pnpm")) {
1404
+ }
1405
+ if (userAgent.includes("pnpm")) {
135
1406
  return "pnpm";
136
- } else if (userAgent.includes("npm")) {
1407
+ }
1408
+ if (userAgent.includes("npm")) {
137
1409
  return "npm";
138
1410
  }
139
1411
  return null;
@@ -144,7 +1416,6 @@ function getDevCommand(packageManager) {
144
1416
  return "yarn dev";
145
1417
  case "pnpm":
146
1418
  return "pnpm dev";
147
- case "npm":
148
1419
  default:
149
1420
  return "npm run dev";
150
1421
  }
@@ -155,7 +1426,6 @@ function getInstallCommand(packageManager) {
155
1426
  return "yarn";
156
1427
  case "pnpm":
157
1428
  return "pnpm install";
158
- case "npm":
159
1429
  default:
160
1430
  return "npm install";
161
1431
  }
@@ -166,7 +1436,6 @@ function getInstallArgs(packageManager) {
166
1436
  return ["install"];
167
1437
  case "pnpm":
168
1438
  return ["install"];
169
- case "npm":
170
1439
  default:
171
1440
  return ["install"];
172
1441
  }
@@ -193,112 +1462,92 @@ function sendInstallTelemetryEvent(agents, skills) {
193
1462
  } catch {
194
1463
  }
195
1464
  }
196
- async function addSkillsToProject(projectPath) {
197
- const REPO_OWNER = "mcp-use";
198
- const REPO_NAME = "mcp-use";
199
- const REPO_COMMIT = "main";
200
- const tarballUrl = `https://codeload.github.com/${REPO_OWNER}/${REPO_NAME}/tar.gz/${REPO_COMMIT}`;
201
- const tempDir = mkdtempSync(join2(tmpdir(), "mcp-use-skills-"));
1465
+ var SKILLS_REPO = "https://github.com/mcp-use/mcp-use.git";
1466
+ var SKILLS_SPARSE_PATH = "skills/mcp-apps-builder";
1467
+ var SKILLS_AGENT_DIRS = [".cursor", ".claude", ".agent"];
1468
+ var SKILLS_MANUAL_INSTALL_CMD = "npx --yes skills add mcp-use/mcp-use --yes --skill mcp-apps-builder -a cursor -a claude-code -a codex";
1469
+ function isGitAvailable() {
1470
+ const result = spawnSync("git", ["--version"], {
1471
+ stdio: "ignore",
1472
+ shell: false
1473
+ });
1474
+ return result.status === 0 && !result.error;
1475
+ }
1476
+ function warnSkillsInstallFailed(missingGit) {
1477
+ const reason = missingGit ? "Failed to install skills: git is not installed or not in PATH." : "Failed to install skills.";
1478
+ console.log(yellow(`\u26A0\uFE0F ${reason}`));
1479
+ console.log(yellow(` Run manually: ${SKILLS_MANUAL_INSTALL_CMD}`));
1480
+ }
1481
+ async function installSkills(projectPath) {
1482
+ const tempDir = mkdtempSync(join3(tmpdir(), "mcp-use-skills-"));
1483
+ const repoDir = join3(tempDir, "repo");
202
1484
  try {
203
- const response = await fetch(tarballUrl);
204
- if (!response.ok) {
205
- throw new Error(`Failed to download tarball: ${response.statusText}`);
1485
+ const clone = spawnSync(
1486
+ "git",
1487
+ [
1488
+ "clone",
1489
+ "--depth",
1490
+ "1",
1491
+ "--filter=blob:none",
1492
+ "--sparse",
1493
+ "--single-branch",
1494
+ SKILLS_REPO,
1495
+ repoDir
1496
+ ],
1497
+ { stdio: "ignore", shell: false }
1498
+ );
1499
+ if (clone.status !== 0 || clone.error) {
1500
+ throw new Error("git clone failed");
206
1501
  }
207
- await pipeline(
208
- Readable.fromWeb(response.body),
209
- extract({
210
- cwd: tempDir,
211
- filter: (path) => path.includes("/skills/mcp-apps-builder/"),
212
- strip: 1
213
- // Removes 'mcp-use-{commit}/' prefix
214
- })
1502
+ const checkout = spawnSync(
1503
+ "git",
1504
+ ["sparse-checkout", "set", SKILLS_SPARSE_PATH],
1505
+ { cwd: repoDir, stdio: "ignore", shell: false }
215
1506
  );
216
- const skillsPath = join2(tempDir, "skills");
217
- if (!existsSync2(skillsPath)) {
218
- throw new Error("Skills folder not found in tarball");
1507
+ if (checkout.status !== 0 || checkout.error) {
1508
+ throw new Error("git sparse-checkout failed");
219
1509
  }
220
- const presets = ["cursor", "claude-code", "codex"];
221
- const presetFolders = {
222
- cursor: ".cursor",
223
- "claude-code": ".claude",
224
- codex: ".agent"
225
- };
226
- for (const preset of presets) {
227
- const folderName = presetFolders[preset];
228
- const outputPath = join2(projectPath, folderName, "skills");
229
- cpSync(skillsPath, outputPath, { recursive: true });
1510
+ const skillSrc = join3(repoDir, SKILLS_SPARSE_PATH);
1511
+ if (!existsSync3(skillSrc)) {
1512
+ throw new Error("mcp-apps-builder skill not found in repository");
230
1513
  }
231
- const skillNames = readdirSync2(skillsPath, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
232
- sendInstallTelemetryEvent(presets.join(","), skillNames.join(","));
233
- } catch (error) {
234
- console.log(
235
- chalk.yellow(
236
- "\u26A0\uFE0F Failed to download skills from GitHub. Continuing without skills..."
237
- )
238
- );
239
- console.log(
240
- chalk.yellow(
241
- ` Error: ${error instanceof Error ? error.message : String(error)}`
242
- )
243
- );
244
- return;
1514
+ for (const agentDir of SKILLS_AGENT_DIRS) {
1515
+ const dest = join3(projectPath, agentDir, "skills", "mcp-apps-builder");
1516
+ mkdirSync(dirname2(dest), { recursive: true });
1517
+ cpSync(skillSrc, dest, { recursive: true });
1518
+ }
1519
+ sendInstallTelemetryEvent("cursor,claude-code,codex", "mcp-apps-builder");
245
1520
  } finally {
246
1521
  rmSync(tempDir, { recursive: true, force: true });
247
1522
  }
248
1523
  }
249
- var program = new Command();
250
1524
  function renderLogo() {
251
- console.log(
252
- chalk.white.bold(
253
- " \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557"
254
- )
255
- );
256
- console.log(
257
- chalk.white.bold(
258
- " \u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D"
259
- )
260
- );
261
- console.log(
262
- chalk.white.bold(
263
- " \u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2501\u2501\u2501\u2501 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 "
264
- )
265
- );
266
- console.log(
267
- chalk.white.bold(
268
- " \u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2501\u2501\u2501\u2501 \u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u255D "
269
- )
270
- );
271
- console.log(
272
- chalk.white.bold(
273
- " \u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557"
274
- )
275
- );
276
- console.log(
277
- chalk.white.bold(
278
- " \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"
279
- )
280
- );
1525
+ const lines = [
1526
+ " \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557",
1527
+ " \u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D",
1528
+ " \u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2501\u2501\u2501\u2501 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 ",
1529
+ " \u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2501\u2501\u2501\u2501 \u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u255D ",
1530
+ " \u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557",
1531
+ " \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"
1532
+ ];
1533
+ for (const line of lines) {
1534
+ console.log(whiteBold(line));
1535
+ }
281
1536
  console.log("");
282
- console.log(chalk.gray.bold(" by Manufact"));
1537
+ console.log(gray(bold(" by Manufact")));
283
1538
  }
284
1539
  var packageJson = JSON.parse(
285
- readFileSync2(join2(__dirname, "../package.json"), "utf-8")
1540
+ readFileSync2(join3(__dirname, "../package.json"), "utf-8")
286
1541
  );
287
1542
  function getCurrentPackageVersions(isDevelopment = false, useCanary = false) {
288
1543
  const versions = {};
289
1544
  try {
290
1545
  if (isDevelopment) {
291
1546
  versions["mcp-use"] = "workspace:*";
292
- versions["@mcp-use/cli"] = "workspace:*";
293
- versions["@mcp-use/inspector"] = "workspace:*";
294
1547
  } else if (useCanary) {
295
1548
  versions["mcp-use"] = "canary";
296
- versions["@mcp-use/cli"] = "canary";
297
- versions["@mcp-use/inspector"] = "canary";
298
1549
  } else {
299
1550
  versions["mcp-use"] = "latest";
300
- versions["@mcp-use/cli"] = "latest";
301
- versions["@mcp-use/inspector"] = "latest";
302
1551
  }
303
1552
  } catch (error) {
304
1553
  if (process.env.NODE_ENV === "development") {
@@ -330,14 +1579,6 @@ function processTemplateFile(filePath, versions, isDevelopment = false, useCanar
330
1579
  /"mcp-use": "\^[^"]+"/,
331
1580
  '"mcp-use": "workspace:*"'
332
1581
  );
333
- processedContent = processedContent.replace(
334
- /"@mcp-use\/cli": "\^[^"]+"/,
335
- '"@mcp-use/cli": "workspace:*"'
336
- );
337
- processedContent = processedContent.replace(
338
- /"@mcp-use\/inspector": "\^[^"]+"/,
339
- '"@mcp-use/inspector": "workspace:*"'
340
- );
341
1582
  } else if (useCanary) {
342
1583
  processedContent = processedContent.replace(
343
1584
  /"mcp-use": "workspace:\*"/,
@@ -347,362 +1588,55 @@ function processTemplateFile(filePath, versions, isDevelopment = false, useCanar
347
1588
  /"mcp-use": "\^[^"]+"/,
348
1589
  `"mcp-use": "canary"`
349
1590
  );
350
- processedContent = processedContent.replace(
351
- /"@mcp-use\/cli": "workspace:\*"/,
352
- `"@mcp-use/cli": "canary"`
353
- );
354
- processedContent = processedContent.replace(
355
- /"@mcp-use\/cli": "\^[^"]+"/,
356
- `"@mcp-use/cli": "canary"`
357
- );
358
- processedContent = processedContent.replace(
359
- /"@mcp-use\/inspector": "workspace:\*"/,
360
- `"@mcp-use/inspector": "canary"`
361
- );
362
- processedContent = processedContent.replace(
363
- /"@mcp-use\/inspector": "\^[^"]+"/,
364
- `"@mcp-use/inspector": "canary"`
365
- );
366
1591
  } else {
367
1592
  processedContent = processedContent.replace(
368
1593
  /"mcp-use": "workspace:\*"/,
369
1594
  `"mcp-use": "${versions["mcp-use"] || "latest"}"`
370
1595
  );
371
- processedContent = processedContent.replace(
372
- /"@mcp-use\/cli": "workspace:\*"/,
373
- `"@mcp-use/cli": "${versions["@mcp-use/cli"] || "latest"}"`
374
- );
375
- processedContent = processedContent.replace(
376
- /"@mcp-use\/inspector": "workspace:\*"/,
377
- `"@mcp-use/inspector": "${versions["@mcp-use/inspector"] || "latest"}"`
378
- );
379
1596
  }
380
1597
  return processedContent;
381
1598
  }
382
1599
  function getAvailableTemplates() {
383
- const templatesDir = join2(__dirname, "templates");
384
- if (!existsSync2(templatesDir)) {
1600
+ const templatesDir = join3(__dirname, "templates");
1601
+ if (!existsSync3(templatesDir)) {
385
1602
  return [];
386
1603
  }
387
- return readdirSync2(templatesDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name).sort();
1604
+ return readdirSync3(templatesDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name).sort();
388
1605
  }
389
1606
  function listTemplates() {
390
1607
  console.log("");
391
1608
  renderLogo();
392
1609
  console.log("");
393
- console.log(chalk.bold("Available Templates:"));
1610
+ console.log(bold("Available Templates:"));
394
1611
  console.log("");
395
- const templatesDir = join2(__dirname, "templates");
1612
+ const templatesDir = join3(__dirname, "templates");
396
1613
  const availableTemplates = getAvailableTemplates();
397
1614
  if (availableTemplates.length === 0) {
398
- console.log(chalk.red("\u274C No templates found!"));
1615
+ console.log(red("\u274C No templates found!"));
399
1616
  return;
400
1617
  }
401
1618
  for (const template of availableTemplates) {
402
- const packageJsonPath = join2(templatesDir, template, "package.json");
1619
+ const packageJsonPath = join3(templatesDir, template, "package.json");
403
1620
  let description = "MCP server template";
404
- if (existsSync2(packageJsonPath)) {
1621
+ if (existsSync3(packageJsonPath)) {
405
1622
  try {
406
- const packageJson2 = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
407
- description = packageJson2.description || description;
408
- } catch (error) {
1623
+ const templatePackageJson = JSON.parse(
1624
+ readFileSync2(packageJsonPath, "utf-8")
1625
+ );
1626
+ description = templatePackageJson.description || description;
1627
+ } catch {
409
1628
  }
410
1629
  }
411
- console.log(
412
- chalk.cyan(` ${template.padEnd(15)}`),
413
- chalk.gray(description)
414
- );
1630
+ console.log(cyan(` ${template.padEnd(15)}`), gray(description));
415
1631
  }
416
1632
  console.log("");
417
1633
  console.log(
418
- chalk.gray(
1634
+ gray(
419
1635
  "\u{1F4A1} Use with: npx create-mcp-use-app my-project --template <template>"
420
1636
  )
421
1637
  );
422
1638
  console.log("");
423
1639
  }
424
- program.name("create-mcp-use-app").description("Create a new MCP server project").version(packageJson.version).argument("[project-name]", "Name of the MCP server project").option(
425
- "-t, --template <template>",
426
- "Template to use (starter, mcp-ui, mcp-apps, blank) or GitHub repo URL (owner/repo or https://github.com/owner/repo)"
427
- ).option("--list-templates", "List all available templates").option("--install", "Install dependencies after creating project").option("--no-install", "Skip installing dependencies").option("--skills", "Install skills for all agents").option("--no-skills", "Skip installing skills").option("--no-git", "Skip initializing a git repository").option("--dev", "Use workspace dependencies for development").option("--canary", "Use canary versions of packages").option("--yarn", "Use yarn as package manager").option("--npm", "Use npm as package manager").option("--pnpm", "Use pnpm as package manager").action(
428
- async (projectName, options) => {
429
- try {
430
- if (options.listTemplates) {
431
- listTemplates();
432
- process.exit(0);
433
- }
434
- if (options.dev && options.canary) {
435
- console.error(chalk.red("\u274C Cannot use --dev and --canary together"));
436
- console.error(
437
- chalk.yellow(" Please choose only one dependency mode")
438
- );
439
- process.exit(1);
440
- }
441
- let selectedTemplate = options.template;
442
- console.log("");
443
- renderLogo();
444
- console.log("");
445
- if (!projectName) {
446
- projectName = await promptForProjectName();
447
- console.log("");
448
- }
449
- if (!options.template && !selectedTemplate) {
450
- selectedTemplate = await promptForTemplate();
451
- }
452
- if (!selectedTemplate) {
453
- selectedTemplate = "starter";
454
- }
455
- const trimmedProjectName = projectName.trim();
456
- if (!trimmedProjectName) {
457
- console.error(chalk.red("\u274C Project name cannot be empty"));
458
- process.exit(1);
459
- }
460
- const { useCurrentDir, projectPath, displayName, packageName } = deriveProjectInfo(trimmedProjectName, process.cwd());
461
- if (useCurrentDir) {
462
- const unsafeEntries = findUnsafeEntries(projectPath);
463
- if (unsafeEntries.length > 0) {
464
- console.error(
465
- chalk.red(
466
- "\u274C Cannot initialize here \u2014 these entries would clash with the template:"
467
- )
468
- );
469
- for (const entry of unsafeEntries) {
470
- console.error(chalk.red(` \u2022 ${entry}`));
471
- }
472
- console.error("");
473
- console.error(
474
- chalk.yellow(
475
- " Remove these files, or pass a project name to scaffold into a new subdirectory instead."
476
- )
477
- );
478
- process.exit(1);
479
- }
480
- } else {
481
- if (trimmedProjectName.includes("..") || trimmedProjectName.includes("/") || trimmedProjectName.includes("\\")) {
482
- console.error(
483
- chalk.red(
484
- '\u274C Project name cannot contain path separators or ".."'
485
- )
486
- );
487
- console.error(
488
- chalk.yellow(' Use simple names like "my-mcp-server"')
489
- );
490
- process.exit(1);
491
- }
492
- const protectedNames = [
493
- "node_modules",
494
- ".git",
495
- ".env",
496
- "package.json",
497
- "src",
498
- "dist"
499
- ];
500
- if (protectedNames.includes(trimmedProjectName.toLowerCase())) {
501
- console.error(
502
- chalk.red(`\u274C Cannot use protected name "${trimmedProjectName}"`)
503
- );
504
- console.error(
505
- chalk.yellow(" Please choose a different project name")
506
- );
507
- process.exit(1);
508
- }
509
- if (existsSync2(projectPath)) {
510
- console.error(
511
- chalk.red(`\u274C Directory "${trimmedProjectName}" already exists!`)
512
- );
513
- console.error(
514
- chalk.yellow(
515
- " Please choose a different name or remove the existing directory"
516
- )
517
- );
518
- process.exit(1);
519
- }
520
- mkdirSync(projectPath, { recursive: true });
521
- }
522
- console.log(chalk.cyan(`\u{1F680} Creating MCP server "${displayName}"...`));
523
- const validatedTemplate = validateTemplateName(selectedTemplate);
524
- const versions = getCurrentPackageVersions(options.dev, options.canary);
525
- await copyTemplate(
526
- projectPath,
527
- validatedTemplate,
528
- versions,
529
- options.dev,
530
- options.canary
531
- );
532
- updatePackageJson(projectPath, packageName);
533
- updateIndexTs(projectPath, packageName);
534
- if (options.template !== void 0) {
535
- if (options.install === void 0) {
536
- options.install = false;
537
- }
538
- if (options.skills === void 0) {
539
- options.skills = true;
540
- }
541
- }
542
- console.log("");
543
- const shouldInstallSkills = options.skills !== void 0 ? options.skills : await promptForSkillsPresets();
544
- let skillsInstalled = false;
545
- if (shouldInstallSkills) {
546
- console.log("");
547
- console.log(chalk.cyan("\u{1F4DA} Installing skills..."));
548
- try {
549
- await addSkillsToProject(projectPath);
550
- skillsInstalled = true;
551
- console.log(chalk.green("\u2705 Skills installed successfully!"));
552
- } catch (err) {
553
- console.log(
554
- chalk.yellow(
555
- "\u26A0\uFE0F Skills install failed. Run `npx skills add mcp-use/mcp-use` manually in root directory."
556
- )
557
- );
558
- }
559
- }
560
- let usedPackageManager = "npm";
561
- if (options.yarn) {
562
- usedPackageManager = "yarn";
563
- } else if (options.npm) {
564
- usedPackageManager = "npm";
565
- } else if (options.pnpm) {
566
- usedPackageManager = "pnpm";
567
- } else {
568
- const detected = detectPackageManager();
569
- if (detected) {
570
- usedPackageManager = detected;
571
- } else {
572
- const defaultOrder = ["npm", "pnpm", "yarn"];
573
- usedPackageManager = defaultOrder[0];
574
- }
575
- }
576
- console.log("");
577
- const shouldInstall = options.install !== void 0 ? options.install : await promptForInstall(usedPackageManager);
578
- if (shouldInstall) {
579
- console.log("");
580
- console.log(chalk.cyan("\u{1F4E6} Installing dependencies..."));
581
- console.log("");
582
- const isKnownManager = options.yarn || options.npm || options.pnpm || detectPackageManager();
583
- const managersToTry = isKnownManager ? [usedPackageManager] : ["npm", "pnpm", "yarn"];
584
- let installed = false;
585
- for (const pm of managersToTry) {
586
- const spinner = ora(`Installing packages with ${pm}...`).start();
587
- try {
588
- await runPackageManager(pm, getInstallArgs(pm), projectPath);
589
- usedPackageManager = pm;
590
- spinner.succeed(`Packages installed successfully with ${pm}`);
591
- installed = true;
592
- break;
593
- } catch (err) {
594
- const remaining = managersToTry.slice(
595
- managersToTry.indexOf(pm) + 1
596
- );
597
- if (remaining.length > 0) {
598
- spinner.warn(`${pm} not available, trying ${remaining[0]}...`);
599
- } else {
600
- spinner.fail("Package installation failed");
601
- if (err instanceof Error) {
602
- console.error(chalk.red(err.message));
603
- }
604
- }
605
- }
606
- }
607
- if (!installed) {
608
- console.log(
609
- '\u26A0\uFE0F Please run "npm install", "yarn install", or "pnpm install" manually'
610
- );
611
- }
612
- }
613
- console.log("");
614
- console.log(chalk.green("\u2705 MCP server created successfully!"));
615
- if (options.dev) {
616
- console.log(
617
- chalk.yellow("\u{1F527} Development mode: Using workspace dependencies")
618
- );
619
- } else if (options.canary) {
620
- console.log(
621
- chalk.cyan("\u{1F680} Canary mode: Using canary versions of packages")
622
- );
623
- }
624
- console.log("");
625
- console.log(chalk.bold("\u{1F4C1} Project structure:"));
626
- console.log(` ${useCurrentDir ? "." : displayName}/`);
627
- if (skillsInstalled) {
628
- console.log(" \u251C\u2500\u2500 .agent/skills/");
629
- console.log(" \u251C\u2500\u2500 .claude/skills/");
630
- console.log(" \u251C\u2500\u2500 .cursor/skills/");
631
- }
632
- if (validatedTemplate === "blank") {
633
- console.log(" \u251C\u2500\u2500 public/");
634
- console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
635
- console.log(" \u251C\u2500\u2500 package.json");
636
- console.log(" \u251C\u2500\u2500 tsconfig.json");
637
- console.log(" \u2514\u2500\u2500 README.md");
638
- } else if (validatedTemplate === "mcp-apps") {
639
- console.log(" \u251C\u2500\u2500 public/");
640
- console.log(" \u251C\u2500\u2500 resources/");
641
- console.log(" \u2502 \u2514\u2500\u2500 product-search-result/");
642
- console.log(" \u2502 \u2514\u2500\u2500 widget.tsx");
643
- console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
644
- console.log(" \u251C\u2500\u2500 package.json");
645
- console.log(" \u251C\u2500\u2500 tsconfig.json");
646
- console.log(" \u2514\u2500\u2500 README.md");
647
- } else if (validatedTemplate === "starter") {
648
- console.log(" \u251C\u2500\u2500 public/");
649
- console.log(" \u251C\u2500\u2500 resources/");
650
- console.log(" \u2502 \u2514\u2500\u2500 display-weather.tsx");
651
- console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
652
- console.log(" \u251C\u2500\u2500 package.json");
653
- console.log(" \u251C\u2500\u2500 tsconfig.json");
654
- console.log(" \u2514\u2500\u2500 README.md");
655
- } else {
656
- console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
657
- console.log(" \u251C\u2500\u2500 package.json");
658
- console.log(" \u251C\u2500\u2500 tsconfig.json");
659
- console.log(" \u2514\u2500\u2500 README.md");
660
- }
661
- console.log("");
662
- console.log(chalk.bold("\u{1F680} To get started:"));
663
- if (!useCurrentDir) {
664
- console.log(chalk.cyan(` cd ${displayName}`));
665
- }
666
- if (!shouldInstall) {
667
- console.log(
668
- chalk.cyan(` ${getInstallCommand(usedPackageManager)}`)
669
- );
670
- }
671
- console.log(chalk.cyan(` ${getDevCommand(usedPackageManager)}`));
672
- console.log("");
673
- console.log(chalk.bold("\u{1F4E4} To deploy:"));
674
- console.log(
675
- chalk.cyan(
676
- ` ${usedPackageManager === "yarn" ? "yarn" : usedPackageManager === "pnpm" ? "pnpm" : "npm run"} deploy`
677
- )
678
- );
679
- console.log("");
680
- if (options.dev) {
681
- console.log(
682
- chalk.yellow(
683
- "\u{1F4A1} Development mode: Your project uses workspace dependencies"
684
- )
685
- );
686
- console.log(
687
- chalk.yellow(
688
- " Make sure you're in the mcp-use workspace root for development"
689
- )
690
- );
691
- console.log("");
692
- }
693
- console.log(chalk.cyan("\u{1F4DA} Learn more: https://manufact.com/docs"));
694
- console.log(chalk.gray("\u{1F4AC} For feedback and bug reporting visit:"));
695
- console.log(
696
- chalk.gray(
697
- " https://github.com/mcp-use/mcp-use or https://manufact.com"
698
- )
699
- );
700
- } catch (error) {
701
- console.error("\u274C Error creating MCP server:", error);
702
- process.exit(1);
703
- }
704
- }
705
- );
706
1640
  function parseGitHubRepoUrl(url) {
707
1641
  const trimmed = url.trim();
708
1642
  let match = trimmed.match(
@@ -758,17 +1692,16 @@ async function cloneGitHubRepo(repoInfo, tempDir) {
758
1692
  shell: false
759
1693
  });
760
1694
  if (versionCheck.status !== 0 || versionCheck.error) {
1695
+ console.error(red("\u274C Git is not installed or not available in PATH"));
761
1696
  console.error(
762
- chalk.red("\u274C Git is not installed or not available in PATH")
763
- );
764
- console.error(
765
- chalk.yellow(" Please install Git to use GitHub repository templates")
1697
+ yellow(" Please install Git to use GitHub repository templates")
766
1698
  );
767
1699
  process.exit(1);
768
1700
  }
769
1701
  const repoUrl = `https://github.com/${repoInfo.owner}/${repoInfo.repo}.git`;
770
1702
  const branch = repoInfo.branch || "main";
771
- const spinner = ora(`Cloning repository from GitHub...`).start();
1703
+ const s = spinner2();
1704
+ s.start("Cloning repository from GitHub...");
772
1705
  const cloneWithBranch = (branchName) => {
773
1706
  const result = spawnSync(
774
1707
  "git",
@@ -789,33 +1722,33 @@ async function cloneGitHubRepo(repoInfo, tempDir) {
789
1722
  };
790
1723
  const cloneResult = cloneWithBranch(branch);
791
1724
  if (cloneResult.success) {
792
- spinner.succeed("Repository cloned successfully");
1725
+ s.stop("Repository cloned successfully");
793
1726
  return tempDir;
794
1727
  }
795
1728
  if (!repoInfo.branch) {
796
- spinner.text = `Branch "${branch}" not found, trying "main"...`;
1729
+ s.message(`Branch "${branch}" not found, trying "main"...`);
797
1730
  const mainResult = cloneWithBranch("main");
798
1731
  if (mainResult.success) {
799
- spinner.succeed("Repository cloned successfully (using main branch)");
1732
+ s.stop("Repository cloned successfully (using main branch)");
800
1733
  return tempDir;
801
1734
  }
802
- spinner.text = `Branch "main" not found, trying "master"...`;
1735
+ s.message('Branch "main" not found, trying "master"...');
803
1736
  const masterResult = cloneWithBranch("master");
804
1737
  if (masterResult.success) {
805
- spinner.succeed("Repository cloned successfully (using master branch)");
1738
+ s.stop("Repository cloned successfully (using master branch)");
806
1739
  return tempDir;
807
1740
  }
808
1741
  }
809
- spinner.fail("Failed to clone repository");
810
- console.error(chalk.red(`\u274C Error cloning repository: ${repoUrl}`));
1742
+ s.error("Failed to clone repository");
1743
+ console.error(red(`\u274C Error cloning repository: ${repoUrl}`));
811
1744
  if (repoInfo.branch) {
812
- console.error(chalk.yellow(` Branch "${repoInfo.branch}" may not exist`));
1745
+ console.error(yellow(` Branch "${repoInfo.branch}" may not exist`));
813
1746
  }
814
1747
  const errorMessage = cloneResult.error?.message || "Unknown error";
815
1748
  if (errorMessage.includes("not found")) {
816
- console.error(chalk.yellow(` Repository may not exist or is private`));
1749
+ console.error(yellow(" Repository may not exist or is private"));
817
1750
  } else {
818
- console.error(chalk.yellow(` ${errorMessage}`));
1751
+ console.error(yellow(` ${errorMessage}`));
819
1752
  }
820
1753
  throw cloneResult.error || new Error("Failed to clone repository");
821
1754
  }
@@ -826,20 +1759,19 @@ function validateTemplateName(template) {
826
1759
  }
827
1760
  const aliases = {
828
1761
  "apps-sdk": "mcp-apps"
829
- // Silent redirect for backward compatibility
830
1762
  };
831
1763
  const resolvedTemplate = aliases[sanitized] || sanitized;
832
1764
  if (resolvedTemplate.includes("..") || resolvedTemplate.includes("/") || resolvedTemplate.includes("\\")) {
833
- console.error(chalk.red("\u274C Invalid template name"));
1765
+ console.error(red("\u274C Invalid template name"));
834
1766
  console.error(
835
- chalk.yellow(" Template name cannot contain path separators")
1767
+ yellow(" Template name cannot contain path separators")
836
1768
  );
837
1769
  process.exit(1);
838
1770
  }
839
1771
  if (!/^[a-zA-Z0-9_-]+$/.test(resolvedTemplate)) {
840
- console.error(chalk.red("\u274C Invalid template name"));
1772
+ console.error(red("\u274C Invalid template name"));
841
1773
  console.error(
842
- chalk.yellow(
1774
+ yellow(
843
1775
  " Template name can only contain letters, numbers, hyphens, and underscores"
844
1776
  )
845
1777
  );
@@ -850,7 +1782,7 @@ function validateTemplateName(template) {
850
1782
  async function copyTemplate(projectPath, template, versions, isDevelopment = false, useCanary = false) {
851
1783
  const repoInfo = parseGitHubRepoUrl(template);
852
1784
  if (repoInfo) {
853
- const tempDir = mkdtempSync(join2(tmpdir(), "create-mcp-use-app-"));
1785
+ const tempDir = mkdtempSync(join3(tmpdir(), "create-mcp-use-app-"));
854
1786
  try {
855
1787
  await cloneGitHubRepo(repoInfo, tempDir);
856
1788
  copyDirectoryWithProcessing(
@@ -863,7 +1795,7 @@ async function copyTemplate(projectPath, template, versions, isDevelopment = fal
863
1795
  } finally {
864
1796
  try {
865
1797
  rmSync(tempDir, { recursive: true, force: true });
866
- } catch (error) {
1798
+ } catch {
867
1799
  if (process.env.NODE_ENV === "development") {
868
1800
  console.warn(
869
1801
  `Warning: Failed to clean up temp directory: ${tempDir}`
@@ -873,12 +1805,12 @@ async function copyTemplate(projectPath, template, versions, isDevelopment = fal
873
1805
  }
874
1806
  return;
875
1807
  }
876
- const templatePath = join2(__dirname, "templates", template);
877
- if (!existsSync2(templatePath)) {
878
- console.error(chalk.red(`\u274C Template "${template}" not found!`));
879
- const templatesDir = join2(__dirname, "templates");
880
- if (existsSync2(templatesDir)) {
881
- const availableTemplates = readdirSync2(templatesDir, {
1808
+ const templatePath = join3(__dirname, "templates", template);
1809
+ if (!existsSync3(templatePath)) {
1810
+ console.error(red(`\u274C Template "${template}" not found!`));
1811
+ const templatesDir = join3(__dirname, "templates");
1812
+ if (existsSync3(templatesDir)) {
1813
+ const availableTemplates = readdirSync3(templatesDir, {
882
1814
  withFileTypes: true
883
1815
  }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name).sort();
884
1816
  console.log(`Available templates: ${availableTemplates.join(", ")}`);
@@ -905,14 +1837,14 @@ async function copyTemplate(projectPath, template, versions, isDevelopment = fal
905
1837
  );
906
1838
  }
907
1839
  function copyDirectoryWithProcessing(src, dest, versions, isDevelopment, useCanary = false) {
908
- const entries = readdirSync2(src, { withFileTypes: true });
1840
+ const entries = readdirSync3(src, { withFileTypes: true });
909
1841
  for (const entry of entries) {
910
1842
  if (entry.name === ".git") {
911
1843
  continue;
912
1844
  }
913
- const srcPath = join2(src, entry.name);
1845
+ const srcPath = join3(src, entry.name);
914
1846
  const destName = entry.name === "gitignore" ? ".gitignore" : entry.name;
915
- const destPath = join2(dest, destName);
1847
+ const destPath = join3(dest, destName);
916
1848
  if (entry.isDirectory()) {
917
1849
  mkdirSync(destPath, { recursive: true });
918
1850
  copyDirectoryWithProcessing(
@@ -922,187 +1854,394 @@ function copyDirectoryWithProcessing(src, dest, versions, isDevelopment, useCana
922
1854
  isDevelopment,
923
1855
  useCanary
924
1856
  );
1857
+ } else if (entry.name === "package.json" || entry.name.endsWith(".json")) {
1858
+ const processedContent = processTemplateFile(
1859
+ srcPath,
1860
+ versions,
1861
+ isDevelopment,
1862
+ useCanary
1863
+ );
1864
+ writeFileSync2(destPath, processedContent);
925
1865
  } else {
926
- if (entry.name === "package.json" || entry.name.endsWith(".json")) {
927
- const processedContent = processTemplateFile(
928
- srcPath,
929
- versions,
930
- isDevelopment,
931
- useCanary
932
- );
933
- writeFileSync2(destPath, processedContent);
934
- } else {
935
- copyFileSync(srcPath, destPath);
936
- }
1866
+ copyFileSync(srcPath, destPath);
937
1867
  }
938
1868
  }
939
1869
  }
940
- function InstallPrompt({
941
- packageManager,
942
- onSubmit
943
- }) {
944
- const [value, setValue] = useState("");
945
- const handleSubmit = (val) => {
946
- const trimmed = val.trim().toLowerCase();
947
- if (trimmed === "" || trimmed === "y" || trimmed === "yes") {
948
- onSubmit(true);
949
- } else if (trimmed === "n" || trimmed === "no") {
950
- onSubmit(false);
951
- }
952
- };
953
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, "Install dependencies with ", packageManager, "? (Y/n)")), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, "\u276F "), /* @__PURE__ */ React.createElement(TextInput, { value, onChange: setValue, onSubmit: handleSubmit })));
954
- }
955
- async function promptForInstall(packageManager) {
956
- return new Promise((resolve2) => {
957
- const { unmount } = render(
958
- /* @__PURE__ */ React.createElement(
959
- InstallPrompt,
960
- {
961
- packageManager,
962
- onSubmit: (install) => {
963
- unmount();
964
- resolve2(install);
965
- }
966
- }
967
- )
968
- );
969
- });
970
- }
971
- function SkillsPresetPrompt({
972
- onSubmit
973
- }) {
974
- const [value, setValue] = useState("");
975
- const handleSubmit = (val) => {
976
- const trimmed = val.trim().toLowerCase();
977
- if (trimmed === "" || trimmed === "y" || trimmed === "yes") {
978
- onSubmit(true);
979
- } else if (trimmed === "n" || trimmed === "no") {
980
- onSubmit(false);
1870
+ function getTemplateItems() {
1871
+ const templatesDir = join3(__dirname, "templates");
1872
+ const availableTemplates = getAvailableTemplates();
1873
+ return availableTemplates.map((template) => {
1874
+ const packageJsonPath = join3(templatesDir, template, "package.json");
1875
+ let description = "MCP server template";
1876
+ if (existsSync3(packageJsonPath)) {
1877
+ try {
1878
+ const templatePackageJson = JSON.parse(
1879
+ readFileSync2(packageJsonPath, "utf-8")
1880
+ );
1881
+ description = templatePackageJson.description || description;
1882
+ } catch {
1883
+ }
981
1884
  }
982
- };
983
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, "Install AI coding skills for Cursor, Claude Code, and Codex? (Recommended) (Y/n)")), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, "\u276F "), /* @__PURE__ */ React.createElement(TextInput, { value, onChange: setValue, onSubmit: handleSubmit })));
984
- }
985
- async function promptForSkillsPresets() {
986
- return new Promise((resolve2) => {
987
- const { unmount } = render(
988
- /* @__PURE__ */ React.createElement(
989
- SkillsPresetPrompt,
990
- {
991
- onSubmit: (presets) => {
992
- unmount();
993
- resolve2(presets);
994
- }
995
- }
996
- )
997
- );
1885
+ return {
1886
+ label: `${template} - ${description}`,
1887
+ value: template
1888
+ };
998
1889
  });
999
1890
  }
1000
- function ProjectNameInput({ onSubmit }) {
1001
- const [value, setValue] = useState("");
1002
- const [error, setError] = useState("");
1003
- const handleSubmit = (val) => {
1004
- const trimmed = val.trim();
1005
- if (!trimmed) {
1006
- setError("Project name is required");
1007
- return;
1008
- }
1009
- if (trimmed === ".") {
1010
- const unsafeEntries = findUnsafeEntries(process.cwd());
1011
- if (unsafeEntries.length > 0) {
1012
- const list = unsafeEntries.map((entry) => ` \u2022 ${entry}`).join("\n");
1013
- setError(
1014
- `Cannot initialize here \u2014 these entries would clash with the template:
1891
+ async function promptForProjectName() {
1892
+ return promptText("What is your project name?", {
1893
+ validate: (value) => {
1894
+ if (!value) {
1895
+ return "Project name is required";
1896
+ }
1897
+ if (value === ".") {
1898
+ const unsafeEntries = findUnsafeEntries(process.cwd());
1899
+ if (unsafeEntries.length > 0) {
1900
+ const list = unsafeEntries.map((entry) => ` \u2022 ${entry}`).join("\n");
1901
+ return `Cannot initialize here \u2014 these entries would clash with the template:
1015
1902
  ${list}
1016
1903
 
1017
- Remove these files, or pick a project name to scaffold into a subdirectory.`
1018
- );
1019
- return;
1904
+ Remove these files, or pick a project name to scaffold into a subdirectory.`;
1905
+ }
1906
+ return void 0;
1020
1907
  }
1021
- } else {
1022
- if (!/^[a-zA-Z0-9-_]+$/.test(trimmed)) {
1023
- setError(
1024
- "Project name can only contain letters, numbers, hyphens, and underscores"
1025
- );
1026
- return;
1908
+ if (!/^[a-zA-Z0-9-_]+$/.test(value)) {
1909
+ return "Project name can only contain letters, numbers, hyphens, and underscores";
1027
1910
  }
1028
- if (existsSync2(join2(process.cwd(), trimmed))) {
1029
- setError(
1030
- `Directory "${trimmed}" already exists! Please choose a different name.`
1031
- );
1032
- return;
1911
+ if (existsSync3(join3(process.cwd(), value))) {
1912
+ return `Directory "${value}" already exists! Please choose a different name.`;
1033
1913
  }
1914
+ return void 0;
1034
1915
  }
1035
- onSubmit(trimmed);
1036
- };
1037
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, "What is your project name?")), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, "\u276F "), /* @__PURE__ */ React.createElement(TextInput, { value, onChange: setValue, onSubmit: handleSubmit })), error && /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "red" }, "\u2716 ", error)));
1916
+ });
1038
1917
  }
1039
- async function promptForProjectName() {
1040
- return new Promise((resolve2) => {
1041
- const { unmount } = render(
1042
- /* @__PURE__ */ React.createElement(
1043
- ProjectNameInput,
1044
- {
1045
- onSubmit: (name) => {
1046
- unmount();
1047
- resolve2(name);
1048
- }
1049
- }
1050
- )
1918
+ async function promptForTemplate() {
1919
+ const items = getTemplateItems();
1920
+ if (items.length === 0) {
1921
+ console.error(
1922
+ red(`\u274C No templates found in: ${join3(__dirname, "templates")}`)
1051
1923
  );
1052
- });
1924
+ process.exit(1);
1925
+ }
1926
+ const defaultIndex = Math.max(
1927
+ 0,
1928
+ items.findIndex((item) => item.value === "mcp-apps")
1929
+ );
1930
+ return promptSelect("Select a template:", items, defaultIndex);
1053
1931
  }
1054
- function TemplateSelector({
1055
- onSelect
1056
- }) {
1057
- const templatesDir = join2(__dirname, "templates");
1058
- if (!existsSync2(templatesDir)) {
1059
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { color: "red" }, "\u274C Templates directory not found at: ", templatesDir), /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, " __dirname: ", __dirname));
1060
- }
1061
- const availableTemplates = readdirSync2(templatesDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name).sort();
1062
- if (availableTemplates.length === 0) {
1063
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { color: "red" }, "\u274C No templates found in: ", templatesDir));
1932
+ function printHelp() {
1933
+ console.log(`Usage: create-mcp-use-app [project-name] [options]
1934
+
1935
+ Create a new MCP server project.
1936
+
1937
+ Arguments:
1938
+ project-name Name of the MCP server project
1939
+
1940
+ Options:
1941
+ -t, --template <template> Template to use or GitHub repo URL
1942
+ --list-templates List all available templates
1943
+ --install Install dependencies after creating project
1944
+ --no-install Skip installing dependencies
1945
+ --skills Install skills for all agents
1946
+ --no-skills Skip installing skills
1947
+ --no-git Skip initializing a git repository
1948
+ --dev Use workspace dependencies for development
1949
+ --canary Use canary versions of packages
1950
+ --yarn Use yarn as package manager
1951
+ --npm Use npm as package manager
1952
+ --pnpm Use pnpm as package manager
1953
+ -h, --help Display help
1954
+ -V, --version Display version`);
1955
+ }
1956
+ async function main() {
1957
+ const argv = process.argv.slice(2);
1958
+ const { projectName: initialProjectName, options } = parseCli(argv);
1959
+ if (argv.includes("--help") || argv.includes("-h")) {
1960
+ printHelp();
1961
+ return;
1064
1962
  }
1065
- const items = availableTemplates.map((template) => {
1066
- const packageJsonPath = join2(templatesDir, template, "package.json");
1067
- let description = "MCP server template";
1068
- if (existsSync2(packageJsonPath)) {
1963
+ if (argv.includes("--version") || argv.includes("-V")) {
1964
+ console.log(packageJson.version);
1965
+ return;
1966
+ }
1967
+ if (options.listTemplates) {
1968
+ listTemplates();
1969
+ return;
1970
+ }
1971
+ if (options.dev && options.canary) {
1972
+ console.error(red("\u274C Cannot use --dev and --canary together"));
1973
+ console.error(yellow(" Please choose only one dependency mode"));
1974
+ process.exit(1);
1975
+ }
1976
+ let projectName = initialProjectName;
1977
+ let selectedTemplate = options.template;
1978
+ const interactive = isInteractive();
1979
+ console.log("");
1980
+ renderLogo();
1981
+ console.log("");
1982
+ if (!projectName) {
1983
+ if (!interactive) {
1984
+ console.error(
1985
+ red("\u274C Project name is required in non-interactive mode")
1986
+ );
1987
+ process.exit(1);
1988
+ }
1989
+ projectName = await promptForProjectName();
1990
+ console.log("");
1991
+ }
1992
+ if (!selectedTemplate) {
1993
+ if (interactive) {
1994
+ selectedTemplate = await promptForTemplate();
1995
+ } else {
1996
+ selectedTemplate = "starter";
1997
+ }
1998
+ }
1999
+ const trimmedProjectName = projectName.trim();
2000
+ if (!trimmedProjectName) {
2001
+ console.error(red("\u274C Project name cannot be empty"));
2002
+ process.exit(1);
2003
+ }
2004
+ const { useCurrentDir, projectPath, displayName, packageName } = deriveProjectInfo(trimmedProjectName, process.cwd());
2005
+ if (useCurrentDir) {
2006
+ const unsafeEntries = findUnsafeEntries(projectPath);
2007
+ if (unsafeEntries.length > 0) {
2008
+ console.error(
2009
+ red(
2010
+ "\u274C Cannot initialize here \u2014 these entries would clash with the template:"
2011
+ )
2012
+ );
2013
+ for (const entry of unsafeEntries) {
2014
+ console.error(red(` \u2022 ${entry}`));
2015
+ }
2016
+ console.error("");
2017
+ console.error(
2018
+ yellow(
2019
+ " Remove these files, or pass a project name to scaffold into a new subdirectory instead."
2020
+ )
2021
+ );
2022
+ process.exit(1);
2023
+ }
2024
+ } else {
2025
+ if (trimmedProjectName.includes("..") || trimmedProjectName.includes("/") || trimmedProjectName.includes("\\")) {
2026
+ console.error(
2027
+ red('\u274C Project name cannot contain path separators or ".."')
2028
+ );
2029
+ console.error(yellow(' Use simple names like "my-mcp-server"'));
2030
+ process.exit(1);
2031
+ }
2032
+ const protectedNames = [
2033
+ "node_modules",
2034
+ ".git",
2035
+ ".env",
2036
+ "package.json",
2037
+ "src",
2038
+ "dist"
2039
+ ];
2040
+ if (protectedNames.includes(trimmedProjectName.toLowerCase())) {
2041
+ console.error(
2042
+ red(`\u274C Cannot use protected name "${trimmedProjectName}"`)
2043
+ );
2044
+ console.error(yellow(" Please choose a different project name"));
2045
+ process.exit(1);
2046
+ }
2047
+ if (existsSync3(projectPath)) {
2048
+ console.error(
2049
+ red(`\u274C Directory "${trimmedProjectName}" already exists!`)
2050
+ );
2051
+ console.error(
2052
+ yellow(
2053
+ " Please choose a different name or remove the existing directory"
2054
+ )
2055
+ );
2056
+ process.exit(1);
2057
+ }
2058
+ mkdirSync(projectPath, { recursive: true });
2059
+ }
2060
+ console.log(cyan(`\u{1F680} Creating MCP server "${displayName}"...`));
2061
+ const validatedTemplate = validateTemplateName(selectedTemplate);
2062
+ const versions = getCurrentPackageVersions(options.dev, options.canary);
2063
+ await copyTemplate(
2064
+ projectPath,
2065
+ validatedTemplate,
2066
+ versions,
2067
+ options.dev,
2068
+ options.canary
2069
+ );
2070
+ updatePackageJson(projectPath, packageName);
2071
+ updateIndexTs(projectPath, packageName);
2072
+ let install = options.install;
2073
+ let skills = options.skills;
2074
+ if (options.template !== void 0) {
2075
+ if (install === void 0) {
2076
+ install = false;
2077
+ }
2078
+ if (skills === void 0) {
2079
+ skills = true;
2080
+ }
2081
+ } else if (!interactive) {
2082
+ if (install === void 0) {
2083
+ install = false;
2084
+ }
2085
+ if (skills === void 0) {
2086
+ skills = false;
2087
+ }
2088
+ }
2089
+ console.log("");
2090
+ const shouldInstallSkills = skills !== void 0 ? skills : interactive ? await promptConfirm(
2091
+ "Install AI coding skills for Cursor, Claude Code, and Codex? (Recommended)",
2092
+ true
2093
+ ) : false;
2094
+ let skillsInstalled = false;
2095
+ if (shouldInstallSkills) {
2096
+ console.log("");
2097
+ const s = spinner2();
2098
+ s.start("Installing skills...");
2099
+ if (!isGitAvailable()) {
2100
+ s.stop("Skills install skipped");
2101
+ warnSkillsInstallFailed(true);
2102
+ } else {
1069
2103
  try {
1070
- const packageJson2 = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
1071
- description = packageJson2.description || description;
1072
- } catch (error) {
2104
+ await installSkills(projectPath);
2105
+ skillsInstalled = true;
2106
+ s.stop("Skills installed successfully!");
2107
+ } catch {
2108
+ s.stop("Skills install failed");
2109
+ warnSkillsInstallFailed(false);
1073
2110
  }
1074
2111
  }
1075
- return {
1076
- label: `${template} - ${description}`,
1077
- value: template
1078
- };
1079
- });
1080
- const defaultIndex = items.findIndex((item) => item.value === "mcp-apps");
1081
- const initialIndex = defaultIndex >= 0 ? defaultIndex : 0;
1082
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, "Select a template:")), /* @__PURE__ */ React.createElement(
1083
- SelectInput,
1084
- {
1085
- items,
1086
- initialIndex,
1087
- onSelect: (item) => onSelect(item.value),
1088
- indicatorComponent: ({ isSelected }) => /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, isSelected ? "\u276F " : " "),
1089
- itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React.createElement(Text, { color: isSelected ? "cyan" : void 0 }, label)
2112
+ }
2113
+ let usedPackageManager = "npm";
2114
+ if (options.yarn) {
2115
+ usedPackageManager = "yarn";
2116
+ } else if (options.npm) {
2117
+ usedPackageManager = "npm";
2118
+ } else if (options.pnpm) {
2119
+ usedPackageManager = "pnpm";
2120
+ } else {
2121
+ const detected = detectPackageManager();
2122
+ if (detected) {
2123
+ usedPackageManager = detected;
1090
2124
  }
1091
- ));
1092
- }
1093
- async function promptForTemplate() {
1094
- return new Promise((resolve2) => {
1095
- const { unmount } = render(
1096
- /* @__PURE__ */ React.createElement(
1097
- TemplateSelector,
1098
- {
1099
- onSelect: (template) => {
1100
- unmount();
1101
- resolve2(template);
2125
+ }
2126
+ console.log("");
2127
+ const shouldInstall = install !== void 0 ? install : interactive ? await promptConfirm(
2128
+ `Install dependencies with ${usedPackageManager}?`,
2129
+ true
2130
+ ) : false;
2131
+ if (shouldInstall) {
2132
+ console.log("");
2133
+ console.log(cyan("\u{1F4E6} Installing dependencies..."));
2134
+ console.log("");
2135
+ const isKnownManager = options.yarn || options.npm || options.pnpm || detectPackageManager();
2136
+ const managersToTry = isKnownManager ? [usedPackageManager] : ["npm", "pnpm", "yarn"];
2137
+ let installed = false;
2138
+ for (const pm of managersToTry) {
2139
+ const s = spinner2();
2140
+ s.start(`Installing packages with ${pm}...`);
2141
+ try {
2142
+ await runPackageManager(pm, getInstallArgs(pm), projectPath);
2143
+ usedPackageManager = pm;
2144
+ s.stop(`Packages installed successfully with ${pm}`);
2145
+ installed = true;
2146
+ break;
2147
+ } catch (err) {
2148
+ const remaining = managersToTry.slice(managersToTry.indexOf(pm) + 1);
2149
+ if (remaining.length > 0) {
2150
+ s.stop(`${pm} not available, trying ${remaining[0]}...`);
2151
+ } else {
2152
+ s.error("Package installation failed");
2153
+ if (err instanceof Error) {
2154
+ console.error(red(err.message));
1102
2155
  }
1103
2156
  }
2157
+ }
2158
+ }
2159
+ if (!installed) {
2160
+ console.log(
2161
+ '\u26A0\uFE0F Please run "npm install", "yarn install", or "pnpm install" manually'
2162
+ );
2163
+ }
2164
+ }
2165
+ console.log("");
2166
+ console.log(green("\u2705 MCP server created successfully!"));
2167
+ if (options.dev) {
2168
+ console.log(
2169
+ yellow("\u{1F527} Development mode: Using workspace dependencies")
2170
+ );
2171
+ } else if (options.canary) {
2172
+ console.log(cyan("\u{1F680} Canary mode: Using canary versions of packages"));
2173
+ }
2174
+ console.log("");
2175
+ console.log(bold("\u{1F4C1} Project structure:"));
2176
+ console.log(` ${useCurrentDir ? "." : displayName}/`);
2177
+ if (skillsInstalled) {
2178
+ console.log(" \u251C\u2500\u2500 .agent/skills/");
2179
+ console.log(" \u251C\u2500\u2500 .claude/skills/");
2180
+ console.log(" \u251C\u2500\u2500 .cursor/skills/");
2181
+ }
2182
+ if (validatedTemplate === "blank") {
2183
+ console.log(" \u251C\u2500\u2500 public/");
2184
+ console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
2185
+ console.log(" \u251C\u2500\u2500 package.json");
2186
+ console.log(" \u251C\u2500\u2500 tsconfig.json");
2187
+ console.log(" \u2514\u2500\u2500 README.md");
2188
+ } else if (validatedTemplate === "mcp-apps") {
2189
+ console.log(" \u251C\u2500\u2500 resources/");
2190
+ console.log(" \u2502 \u2514\u2500\u2500 product-search-result/");
2191
+ console.log(" \u2502 \u2514\u2500\u2500 view.tsx");
2192
+ console.log(" \u251C\u2500\u2500 src/register.d.ts");
2193
+ console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
2194
+ console.log(" \u251C\u2500\u2500 package.json");
2195
+ console.log(" \u251C\u2500\u2500 tsconfig.json");
2196
+ console.log(" \u2514\u2500\u2500 README.md");
2197
+ } else if (validatedTemplate === "starter") {
2198
+ console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
2199
+ console.log(" \u251C\u2500\u2500 package.json");
2200
+ console.log(" \u251C\u2500\u2500 tsconfig.json");
2201
+ console.log(" \u2514\u2500\u2500 README.md");
2202
+ } else {
2203
+ console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
2204
+ console.log(" \u251C\u2500\u2500 package.json");
2205
+ console.log(" \u251C\u2500\u2500 tsconfig.json");
2206
+ console.log(" \u2514\u2500\u2500 README.md");
2207
+ }
2208
+ console.log("");
2209
+ console.log(bold("\u{1F680} To get started:"));
2210
+ if (!useCurrentDir) {
2211
+ console.log(cyan(` cd ${displayName}`));
2212
+ }
2213
+ if (!shouldInstall) {
2214
+ console.log(cyan(` ${getInstallCommand(usedPackageManager)}`));
2215
+ }
2216
+ console.log(cyan(` ${getDevCommand(usedPackageManager)}`));
2217
+ console.log("");
2218
+ console.log(bold("\u{1F4E4} To deploy:"));
2219
+ console.log(
2220
+ cyan(
2221
+ ` ${usedPackageManager === "yarn" ? "yarn" : usedPackageManager === "pnpm" ? "pnpm" : "npm run"} deploy`
2222
+ )
2223
+ );
2224
+ console.log("");
2225
+ if (options.dev) {
2226
+ console.log(
2227
+ yellow(
2228
+ "\u{1F4A1} Development mode: Your project uses workspace dependencies"
1104
2229
  )
1105
2230
  );
1106
- });
2231
+ console.log(
2232
+ yellow(
2233
+ " Make sure you're in the mcp-use workspace root for development"
2234
+ )
2235
+ );
2236
+ console.log("");
2237
+ }
2238
+ console.log(cyan("\u{1F4DA} Learn more: https://manufact.com/docs"));
2239
+ console.log(gray("\u{1F4AC} For feedback and bug reporting visit:"));
2240
+ console.log(
2241
+ gray(" https://github.com/mcp-use/mcp-use or https://manufact.com")
2242
+ );
1107
2243
  }
1108
- program.parse();
2244
+ main().catch((error) => {
2245
+ console.error("\u274C Error creating MCP server:", error);
2246
+ process.exit(1);
2247
+ });