create-mcp-use-app 0.12.3 → 0.13.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 (3) hide show
  1. package/README.md +11 -2
  2. package/dist/index.js +164 -3
  3. package/package.json +4 -2
package/README.md CHANGED
@@ -40,7 +40,6 @@ Create a new MCP application in seconds:
40
40
  ```bash
41
41
  npx create-mcp-use-app my-mcp-server
42
42
  cd my-mcp-server
43
- npm run dev
44
43
  ```
45
44
 
46
45
  That's it! Your MCP server is running at `http://localhost:3000` with the inspector automatically opened in your browser.
@@ -96,6 +95,8 @@ You'll be prompted for:
96
95
  - Project name
97
96
  - Project template
98
97
  - Package manager preference
98
+ - Install dependencies (Y/n)
99
+ - Skills installation (Claude Code, Cursor, Both, or None)
99
100
 
100
101
  ### Direct Mode
101
102
 
@@ -122,8 +123,16 @@ npx create-mcp-use-app my-project --npm
122
123
  npx create-mcp-use-app my-project --yarn
123
124
  npx create-mcp-use-app my-project --pnpm
124
125
 
125
- # Install deps automatically
126
+ # Install deps automatically (or --no-install to skip and skip prompt)
126
127
  npx create-mcp-use-app my-project --install
128
+ npx create-mcp-use-app my-project --no-install
129
+
130
+ # Skills presets for Claude Code / Cursor (omit to prompt)
131
+ npx create-mcp-use-app my-project --skills
132
+ npx create-mcp-use-app my-project --no-skills
133
+
134
+ # List all available templates
135
+ npx create-mcp-use-app --list-templates
127
136
  ```
128
137
 
129
138
  ---
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ import TextInput from "ink-text-input";
9
9
  import { spawn, spawnSync } from "child_process";
10
10
  import {
11
11
  copyFileSync,
12
+ cpSync,
12
13
  existsSync,
13
14
  mkdirSync,
14
15
  mkdtempSync,
@@ -19,9 +20,12 @@ import {
19
20
  } from "fs";
20
21
  import { tmpdir } from "os";
21
22
  import { dirname, join, resolve } from "path";
23
+ import { Readable } from "stream";
24
+ import { pipeline } from "stream/promises";
22
25
  import { fileURLToPath } from "url";
23
26
  import ora from "ora";
24
27
  import React, { useState } from "react";
28
+ import { extract } from "tar";
25
29
  var __filename = fileURLToPath(import.meta.url);
26
30
  var __dirname = dirname(__filename);
27
31
  function runPackageManager(packageManager, args, cwd) {
@@ -88,6 +92,81 @@ function getInstallArgs(packageManager) {
88
92
  return ["install"];
89
93
  }
90
94
  }
95
+ function sendInstallTelemetryEvent(agents, skills) {
96
+ const TELEMETRY_URL = "https://add-skill.vercel.sh/t";
97
+ const SOURCE_REPO = "mcp-use/mcp-use";
98
+ const telemetryData = {
99
+ event: "install",
100
+ source: SOURCE_REPO,
101
+ skills,
102
+ agents,
103
+ sourceType: "github"
104
+ };
105
+ try {
106
+ const params = new URLSearchParams();
107
+ for (const [key, value] of Object.entries(telemetryData)) {
108
+ if (value !== void 0 && value !== null) {
109
+ params.set(key, String(value));
110
+ }
111
+ }
112
+ fetch(`${TELEMETRY_URL}?${params.toString()}`).catch(() => {
113
+ });
114
+ } catch {
115
+ }
116
+ }
117
+ async function addSkillsToProject(projectPath) {
118
+ const REPO_OWNER = "mcp-use";
119
+ const REPO_NAME = "mcp-use";
120
+ const REPO_COMMIT = "main";
121
+ const tarballUrl = `https://codeload.github.com/${REPO_OWNER}/${REPO_NAME}/tar.gz/${REPO_COMMIT}`;
122
+ const tempDir = mkdtempSync(join(tmpdir(), "mcp-use-skills-"));
123
+ try {
124
+ const response = await fetch(tarballUrl);
125
+ if (!response.ok) {
126
+ throw new Error(`Failed to download tarball: ${response.statusText}`);
127
+ }
128
+ await pipeline(
129
+ Readable.fromWeb(response.body),
130
+ extract({
131
+ cwd: tempDir,
132
+ filter: (path) => path.includes("/skills/"),
133
+ strip: 1
134
+ // Removes 'mcp-use-{commit}/' prefix
135
+ })
136
+ );
137
+ const skillsPath = join(tempDir, "skills");
138
+ if (!existsSync(skillsPath)) {
139
+ throw new Error("Skills folder not found in tarball");
140
+ }
141
+ const presets = ["cursor", "claude-code", "codex"];
142
+ const presetFolders = {
143
+ cursor: ".cursor",
144
+ "claude-code": ".claude",
145
+ codex: ".agent"
146
+ };
147
+ for (const preset of presets) {
148
+ const folderName = presetFolders[preset];
149
+ const outputPath = join(projectPath, folderName, "skills");
150
+ cpSync(skillsPath, outputPath, { recursive: true });
151
+ }
152
+ const skillNames = readdirSync(skillsPath, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
153
+ sendInstallTelemetryEvent(presets.join(","), skillNames.join(","));
154
+ } catch (error) {
155
+ console.log(
156
+ chalk.yellow(
157
+ "\u26A0\uFE0F Failed to download skills from GitHub. Continuing without skills..."
158
+ )
159
+ );
160
+ console.log(
161
+ chalk.yellow(
162
+ ` Error: ${error instanceof Error ? error.message : String(error)}`
163
+ )
164
+ );
165
+ return;
166
+ } finally {
167
+ rmSync(tempDir, { recursive: true, force: true });
168
+ }
169
+ }
91
170
  var program = new Command();
92
171
  function renderLogo() {
93
172
  console.log(chalk.cyan("\u259B\u259B\u258C\u259B\u2598\u259B\u258C\u2584\u2596\u258C\u258C\u259B\u2598\u2588\u258C"));
@@ -237,7 +316,7 @@ function listTemplates() {
237
316
  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(
238
317
  "-t, --template <template>",
239
318
  "Template to use (starter, mcp-ui, mcp-apps, blank) or GitHub repo URL (owner/repo or https://github.com/owner/repo)"
240
- ).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(
319
+ ).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(
241
320
  async (projectName, options) => {
242
321
  try {
243
322
  if (options.listTemplates) {
@@ -325,6 +404,16 @@ program.name("create-mcp-use-app").description("Create a new MCP server project"
325
404
  );
326
405
  updatePackageJson(projectPath, sanitizedProjectName);
327
406
  updateIndexTs(projectPath, sanitizedProjectName);
407
+ if (options.template !== void 0) {
408
+ if (options.install === void 0) {
409
+ options.install = false;
410
+ }
411
+ if (options.skills === void 0) {
412
+ options.skills = true;
413
+ }
414
+ }
415
+ console.log("");
416
+ const shouldInstall = options.install !== void 0 ? options.install : await promptForInstall();
328
417
  let usedPackageManager = "npm";
329
418
  if (options.yarn) {
330
419
  usedPackageManager = "yarn";
@@ -341,7 +430,7 @@ program.name("create-mcp-use-app").description("Create a new MCP server project"
341
430
  usedPackageManager = defaultOrder[0];
342
431
  }
343
432
  }
344
- if (options.install === true) {
433
+ if (shouldInstall) {
345
434
  console.log("");
346
435
  console.log(chalk.cyan("\u{1F4E6} Installing dependencies..."));
347
436
  console.log("");
@@ -442,6 +531,22 @@ program.name("create-mcp-use-app").description("Create a new MCP server project"
442
531
  }
443
532
  }
444
533
  console.log("");
534
+ const shouldInstallSkills = options.skills !== void 0 ? options.skills : await promptForSkillsPresets();
535
+ if (shouldInstallSkills) {
536
+ console.log("");
537
+ console.log(chalk.cyan("\u{1F4DA} Installing skills..."));
538
+ try {
539
+ await addSkillsToProject(projectPath);
540
+ console.log(chalk.green("\u2705 Skills installed successfully!"));
541
+ } catch (err) {
542
+ console.log(
543
+ chalk.yellow(
544
+ "\u26A0\uFE0F Skills install failed. Run `npx skills add mcp-use/mcp-use` manually in root directory."
545
+ )
546
+ );
547
+ }
548
+ }
549
+ console.log("");
445
550
  console.log(chalk.green("\u2705 MCP server created successfully!"));
446
551
  if (options.dev) {
447
552
  console.log(
@@ -477,7 +582,7 @@ program.name("create-mcp-use-app").description("Create a new MCP server project"
477
582
  console.log("");
478
583
  console.log(chalk.bold("\u{1F680} To get started:"));
479
584
  console.log(chalk.cyan(` cd ${sanitizedProjectName}`));
480
- if (!options.install) {
585
+ if (!shouldInstall) {
481
586
  console.log(
482
587
  chalk.cyan(` ${getInstallCommand(usedPackageManager)}`)
483
588
  );
@@ -767,6 +872,62 @@ function updateIndexTs(projectPath, projectName) {
767
872
  content = content.replace(/\{\{PROJECT_NAME\}\}/g, projectName);
768
873
  writeFileSync(indexPath, content);
769
874
  }
875
+ function InstallPrompt({ onSubmit }) {
876
+ const [value, setValue] = useState("");
877
+ const handleSubmit = (val) => {
878
+ const trimmed = val.trim().toLowerCase();
879
+ if (trimmed === "" || trimmed === "y" || trimmed === "yes") {
880
+ onSubmit(true);
881
+ } else if (trimmed === "n" || trimmed === "no") {
882
+ onSubmit(false);
883
+ }
884
+ };
885
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, "Install dependencies now? (Y/n)")), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, "\u276F "), /* @__PURE__ */ React.createElement(TextInput, { value, onChange: setValue, onSubmit: handleSubmit })));
886
+ }
887
+ async function promptForInstall() {
888
+ return new Promise((resolve2) => {
889
+ const { unmount } = render(
890
+ /* @__PURE__ */ React.createElement(
891
+ InstallPrompt,
892
+ {
893
+ onSubmit: (install) => {
894
+ unmount();
895
+ resolve2(install);
896
+ }
897
+ }
898
+ )
899
+ );
900
+ });
901
+ }
902
+ function SkillsPresetPrompt({
903
+ onSubmit
904
+ }) {
905
+ const [value, setValue] = useState("");
906
+ const handleSubmit = (val) => {
907
+ const trimmed = val.trim().toLowerCase();
908
+ if (trimmed === "" || trimmed === "y" || trimmed === "yes") {
909
+ onSubmit(true);
910
+ } else if (trimmed === "n" || trimmed === "no") {
911
+ onSubmit(false);
912
+ }
913
+ };
914
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, "Install skills (Recommended)? (Y/n)")), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, "\u276F "), /* @__PURE__ */ React.createElement(TextInput, { value, onChange: setValue, onSubmit: handleSubmit })));
915
+ }
916
+ async function promptForSkillsPresets() {
917
+ return new Promise((resolve2) => {
918
+ const { unmount } = render(
919
+ /* @__PURE__ */ React.createElement(
920
+ SkillsPresetPrompt,
921
+ {
922
+ onSubmit: (presets) => {
923
+ unmount();
924
+ resolve2(presets);
925
+ }
926
+ }
927
+ )
928
+ );
929
+ });
930
+ }
770
931
  function ProjectNameInput({ onSubmit }) {
771
932
  const [value, setValue] = useState("");
772
933
  const [error, setError] = useState("");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-mcp-use-app",
3
- "version": "0.12.3",
3
+ "version": "0.13.0",
4
4
  "type": "module",
5
5
  "description": "Create MCP-Use apps with one command",
6
6
  "author": "mcp-use, Inc.",
@@ -43,10 +43,12 @@
43
43
  "ink-select-input": "^6.2.0",
44
44
  "ink-text-input": "^6.0.0",
45
45
  "ora": "^9.0.0",
46
- "react": "^19.2.3"
46
+ "react": "^19.2.3",
47
+ "tar": "^7.4.3"
47
48
  },
48
49
  "devDependencies": {
49
50
  "@types/fs-extra": "^11.0.4",
51
+ "@types/tar": "^6.1.13",
50
52
  "vitest": "^4.0.17"
51
53
  },
52
54
  "publishConfig": {