create-mcp-use-app 0.7.4-canary.0 → 0.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +122 -43
- package/dist/templates/starter/package.json +3 -0
- package/package.json +8 -5
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":""}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// src/index.
|
|
3
|
+
// src/index.tsx
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import { Command } from "commander";
|
|
6
|
-
import
|
|
6
|
+
import { render } from "ink";
|
|
7
|
+
import SelectInput from "ink-select-input";
|
|
8
|
+
import TextInput from "ink-text-input";
|
|
7
9
|
import { execSync, spawn } from "child_process";
|
|
8
10
|
import {
|
|
9
11
|
copyFileSync,
|
|
@@ -17,6 +19,8 @@ import {
|
|
|
17
19
|
import { dirname, join, resolve } from "path";
|
|
18
20
|
import { fileURLToPath } from "url";
|
|
19
21
|
import ora from "ora";
|
|
22
|
+
import React, { useState } from "react";
|
|
23
|
+
import { Box, Text } from "ink";
|
|
20
24
|
var __filename = fileURLToPath(import.meta.url);
|
|
21
25
|
var __dirname = dirname(__filename);
|
|
22
26
|
function runPackageManager(packageManager, args, cwd) {
|
|
@@ -231,9 +235,48 @@ function processTemplateFile(filePath, versions, isDevelopment = false, useCanar
|
|
|
231
235
|
}
|
|
232
236
|
return processedContent;
|
|
233
237
|
}
|
|
234
|
-
|
|
238
|
+
function getAvailableTemplates() {
|
|
239
|
+
const templatesDir = join(__dirname, "templates");
|
|
240
|
+
if (!existsSync(templatesDir)) {
|
|
241
|
+
return [];
|
|
242
|
+
}
|
|
243
|
+
return readdirSync(templatesDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name).sort();
|
|
244
|
+
}
|
|
245
|
+
function listTemplates() {
|
|
246
|
+
console.log("");
|
|
247
|
+
renderLogo();
|
|
248
|
+
console.log("");
|
|
249
|
+
console.log(chalk.bold("Available Templates:"));
|
|
250
|
+
console.log("");
|
|
251
|
+
const templatesDir = join(__dirname, "templates");
|
|
252
|
+
const availableTemplates = getAvailableTemplates();
|
|
253
|
+
if (availableTemplates.length === 0) {
|
|
254
|
+
console.log(chalk.red("\u274C No templates found!"));
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
for (const template of availableTemplates) {
|
|
258
|
+
const packageJsonPath = join(templatesDir, template, "package.json");
|
|
259
|
+
let description = "MCP server template";
|
|
260
|
+
if (existsSync(packageJsonPath)) {
|
|
261
|
+
try {
|
|
262
|
+
const packageJson2 = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
263
|
+
description = packageJson2.description || description;
|
|
264
|
+
} catch (error) {
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
console.log(chalk.cyan(` ${template.padEnd(15)}`), chalk.gray(description));
|
|
268
|
+
}
|
|
269
|
+
console.log("");
|
|
270
|
+
console.log(chalk.gray("\u{1F4A1} Use with: npx create-mcp-use-app my-project --template <template>"));
|
|
271
|
+
console.log("");
|
|
272
|
+
}
|
|
273
|
+
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("-t, --template <template>", "Template to use (starter, mcp-ui, apps-sdk)", "starter").option("--list-templates", "List all available templates").option("--install", "Install dependencies after creating project").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(
|
|
235
274
|
async (projectName, options) => {
|
|
236
275
|
try {
|
|
276
|
+
if (options.listTemplates) {
|
|
277
|
+
listTemplates();
|
|
278
|
+
process.exit(0);
|
|
279
|
+
}
|
|
237
280
|
let selectedTemplate = options.template;
|
|
238
281
|
if (!projectName) {
|
|
239
282
|
console.log("");
|
|
@@ -581,58 +624,94 @@ function updatePackageJson(projectPath, projectName) {
|
|
|
581
624
|
packageJsonContent.description = `MCP server: ${projectName}`;
|
|
582
625
|
writeFileSync(packageJsonPath, JSON.stringify(packageJsonContent, null, 2));
|
|
583
626
|
}
|
|
584
|
-
|
|
585
|
-
const
|
|
627
|
+
function ProjectNameInput({ onSubmit }) {
|
|
628
|
+
const [value, setValue] = useState("");
|
|
629
|
+
const [error, setError] = useState("");
|
|
630
|
+
const handleSubmit = (val) => {
|
|
631
|
+
const trimmed = val.trim();
|
|
632
|
+
if (!trimmed) {
|
|
633
|
+
setError("Project name is required");
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
if (!/^[a-zA-Z0-9-_]+$/.test(trimmed)) {
|
|
637
|
+
setError("Project name can only contain letters, numbers, hyphens, and underscores");
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
if (existsSync(join(process.cwd(), trimmed))) {
|
|
641
|
+
setError(`Directory "${trimmed}" already exists! Please choose a different name.`);
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
onSubmit(trimmed);
|
|
645
|
+
};
|
|
646
|
+
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(
|
|
647
|
+
TextInput,
|
|
586
648
|
{
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
validate: (input) => {
|
|
591
|
-
const trimmed = input.trim();
|
|
592
|
-
if (!trimmed) {
|
|
593
|
-
return "Project name is required";
|
|
594
|
-
}
|
|
595
|
-
if (!/^[a-zA-Z0-9-_]+$/.test(trimmed)) {
|
|
596
|
-
return "Project name can only contain letters, numbers, hyphens, and underscores";
|
|
597
|
-
}
|
|
598
|
-
if (existsSync(join(process.cwd(), trimmed))) {
|
|
599
|
-
return `Directory "${trimmed}" already exists! Please choose a different name.`;
|
|
600
|
-
}
|
|
601
|
-
return true;
|
|
602
|
-
}
|
|
649
|
+
value,
|
|
650
|
+
onChange: setValue,
|
|
651
|
+
onSubmit: handleSubmit
|
|
603
652
|
}
|
|
604
|
-
|
|
605
|
-
return projectName;
|
|
653
|
+
)), error && /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "red" }, "\u2716 ", error)));
|
|
606
654
|
}
|
|
607
|
-
async function
|
|
655
|
+
async function promptForProjectName() {
|
|
656
|
+
return new Promise((resolve2) => {
|
|
657
|
+
const { unmount } = render(
|
|
658
|
+
/* @__PURE__ */ React.createElement(
|
|
659
|
+
ProjectNameInput,
|
|
660
|
+
{
|
|
661
|
+
onSubmit: (name) => {
|
|
662
|
+
unmount();
|
|
663
|
+
resolve2(name);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
)
|
|
667
|
+
);
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
function TemplateSelector({ onSelect }) {
|
|
608
671
|
const templatesDir = join(__dirname, "templates");
|
|
672
|
+
if (!existsSync(templatesDir)) {
|
|
673
|
+
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));
|
|
674
|
+
}
|
|
609
675
|
const availableTemplates = readdirSync(templatesDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name).sort();
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
676
|
+
if (availableTemplates.length === 0) {
|
|
677
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { color: "red" }, "\u274C No templates found in: ", templatesDir));
|
|
678
|
+
}
|
|
679
|
+
const items = availableTemplates.map((template) => {
|
|
680
|
+
const packageJsonPath = join(templatesDir, template, "package.json");
|
|
681
|
+
let description = "MCP server template";
|
|
613
682
|
if (existsSync(packageJsonPath)) {
|
|
614
683
|
try {
|
|
615
684
|
const packageJson2 = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
616
|
-
|
|
685
|
+
description = packageJson2.description || description;
|
|
617
686
|
} catch (error) {
|
|
618
|
-
templateDescriptions[template2] = "MCP server template";
|
|
619
687
|
}
|
|
620
|
-
} else {
|
|
621
|
-
templateDescriptions[template2] = "MCP server template";
|
|
622
688
|
}
|
|
623
|
-
|
|
624
|
-
|
|
689
|
+
return {
|
|
690
|
+
label: `${template} - ${description}`,
|
|
691
|
+
value: template
|
|
692
|
+
};
|
|
693
|
+
});
|
|
694
|
+
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(
|
|
695
|
+
SelectInput,
|
|
625
696
|
{
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
message: "Select a template:",
|
|
629
|
-
default: "starter",
|
|
630
|
-
choices: availableTemplates.map((template2) => ({
|
|
631
|
-
name: `${template2} - ${templateDescriptions[template2] || "MCP server template"}`,
|
|
632
|
-
value: template2
|
|
633
|
-
}))
|
|
697
|
+
items,
|
|
698
|
+
onSelect: (item) => onSelect(item.value)
|
|
634
699
|
}
|
|
635
|
-
|
|
636
|
-
|
|
700
|
+
));
|
|
701
|
+
}
|
|
702
|
+
async function promptForTemplate() {
|
|
703
|
+
return new Promise((resolve2) => {
|
|
704
|
+
const { unmount } = render(
|
|
705
|
+
/* @__PURE__ */ React.createElement(
|
|
706
|
+
TemplateSelector,
|
|
707
|
+
{
|
|
708
|
+
onSelect: (template) => {
|
|
709
|
+
unmount();
|
|
710
|
+
resolve2(template);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
)
|
|
714
|
+
);
|
|
715
|
+
});
|
|
637
716
|
}
|
|
638
717
|
program.parse();
|
|
@@ -27,12 +27,15 @@
|
|
|
27
27
|
"deploy": "mcp-use deploy"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"@openai/apps-sdk-ui": "^0.2.0",
|
|
31
|
+
"@tanstack/react-query": "^5.90.11",
|
|
30
32
|
"cors": "^2.8.5",
|
|
31
33
|
"express": "^5.2.0",
|
|
32
34
|
"mcp-use": "workspace:*",
|
|
33
35
|
"node-mocks-http": "^1.17.2",
|
|
34
36
|
"react": "^19.2.0",
|
|
35
37
|
"react-dom": "^19.2.0",
|
|
38
|
+
"react-router": "^7.9.6",
|
|
36
39
|
"react-router-dom": "^7.9.6",
|
|
37
40
|
"tailwindcss": "^4.1.17",
|
|
38
41
|
"zod": "^4.1.13"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-mcp-use-app",
|
|
3
|
-
"version": "0.7.4
|
|
3
|
+
"version": "0.7.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Create MCP-Use apps with one command",
|
|
6
6
|
"author": "mcp-use, Inc.",
|
|
@@ -39,13 +39,16 @@
|
|
|
39
39
|
"chalk": "^5.6.2",
|
|
40
40
|
"commander": "^14.0.2",
|
|
41
41
|
"fs-extra": "^11.3.2",
|
|
42
|
-
"
|
|
43
|
-
"
|
|
42
|
+
"ink": "^6.5.1",
|
|
43
|
+
"ink-select-input": "^6.2.0",
|
|
44
|
+
"ink-text-input": "^6.0.0",
|
|
45
|
+
"ora": "^9.0.0",
|
|
46
|
+
"react": "^19.2.0"
|
|
44
47
|
},
|
|
45
48
|
"devDependencies": {
|
|
46
49
|
"@types/fs-extra": "^11.0.4",
|
|
47
|
-
"@types/inquirer": "^9.0.9",
|
|
48
50
|
"@types/node": "^24.10.1",
|
|
51
|
+
"@types/react": "^19.2.7",
|
|
49
52
|
"typescript": "^5.9.3",
|
|
50
53
|
"vitest": "^4.0.14"
|
|
51
54
|
},
|
|
@@ -53,7 +56,7 @@
|
|
|
53
56
|
"access": "public"
|
|
54
57
|
},
|
|
55
58
|
"scripts": {
|
|
56
|
-
"build": "npm run clean && tsup src/index.
|
|
59
|
+
"build": "npm run clean && tsup src/index.tsx --format esm && tsc --emitDeclarationOnly --declaration && npm run copy-templates",
|
|
57
60
|
"clean": "rm -rf dist tsconfig.tsbuildinfo",
|
|
58
61
|
"copy-templates": "node scripts/copy-templates.js",
|
|
59
62
|
"dev": "tsc --build --watch",
|