Skip to content

Commit dbbcfaf

Browse files
committed
fix cli
1 parent 9045e17 commit dbbcfaf

File tree

3 files changed

+82
-17
lines changed

3 files changed

+82
-17
lines changed

packages/create-mcp-use-app/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,11 @@
4646
},
4747
"dependencies": {
4848
"commander": "^11.0.0",
49-
"prompts": "^2.4.2",
5049
"chalk": "^5.3.0",
5150
"fs-extra": "^11.2.0"
5251
},
5352
"devDependencies": {
5453
"@types/node": "^20.0.0",
55-
"@types/prompts": "^2.4.9",
5654
"@types/fs-extra": "^11.0.4",
5755
"typescript": "^5.0.0",
5856
"vitest": "^1.0.0"

packages/create-mcp-use-app/src/index.ts

Lines changed: 78 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { execSync } from 'node:child_process'
44
import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs'
55
import { dirname, join, resolve } from 'node:path'
66
import { fileURLToPath } from 'node:url'
7+
import { createInterface } from 'node:readline'
78
import { Command } from 'commander'
89

910
const __filename = fileURLToPath(import.meta.url)
@@ -15,14 +16,29 @@ program
1516
.name('create-mcp-use-app')
1617
.description('Create a new MCP server project')
1718
.version('0.1.0')
18-
.argument('<project-name>', 'Name of the MCP server project')
19-
.option('-t, --template <template>', 'Template to use', 'basic')
19+
.argument('[project-name]', 'Name of the MCP server project')
20+
.option('-t, --template <template>', 'Template to use', 'ui')
2021
.option('--no-install', 'Skip installing dependencies')
21-
.action(async (projectName: string, options: { template: string, install: boolean }) => {
22+
.action(async (projectName: string | undefined, options: { template: string, install: boolean }) => {
2223
try {
24+
// If no project name provided, prompt for it
25+
if (!projectName) {
26+
console.log('🎯 Welcome to create-mcp-use-app!')
27+
console.log('')
28+
29+
const promptedName = await promptForProjectName()
30+
31+
if (!promptedName) {
32+
console.log('❌ Project creation cancelled.')
33+
process.exit(0)
34+
}
35+
36+
projectName = promptedName
37+
}
38+
2339
console.log(`🚀 Creating MCP server "${projectName}"...`)
2440

25-
const projectPath = resolve(process.cwd(), projectName)
41+
const projectPath = resolve(process.cwd(), projectName!)
2642

2743
// Check if directory already exists
2844
if (existsSync(projectPath)) {
@@ -37,7 +53,7 @@ program
3753
await copyTemplate(projectPath, options.template)
3854

3955
// Update package.json with project name
40-
updatePackageJson(projectPath, projectName)
56+
updatePackageJson(projectPath, projectName!)
4157

4258
// Install dependencies if requested
4359
if (options.install) {
@@ -60,14 +76,26 @@ program
6076
console.log('')
6177
console.log('📁 Project structure:')
6278
console.log(` ${projectName}/`)
63-
console.log(' ├── src/')
64-
console.log(' │ └── server.ts')
65-
console.log(' ├── package.json')
66-
console.log(' ├── tsconfig.json')
67-
console.log(' └── README.md')
79+
if (options.template === 'ui') {
80+
console.log(' ├── src/')
81+
console.log(' │ └── server.ts')
82+
console.log(' ├── resources/')
83+
console.log(' │ ├── data-visualization.tsx')
84+
console.log(' │ ├── kanban-board.tsx')
85+
console.log(' │ └── todo-list.tsx')
86+
console.log(' ├── package.json')
87+
console.log(' ├── tsconfig.json')
88+
console.log(' └── README.md')
89+
} else {
90+
console.log(' ├── src/')
91+
console.log(' │ └── server.ts')
92+
console.log(' ├── package.json')
93+
console.log(' ├── tsconfig.json')
94+
console.log(' └── README.md')
95+
}
6896
console.log('')
6997
console.log('🚀 To get started:')
70-
console.log(` cd ${projectName}`)
98+
console.log(` cd ${projectName!}`)
7199
if (!options.install) {
72100
console.log(' npm install')
73101
}
@@ -87,6 +115,7 @@ async function copyTemplate(projectPath: string, template: string) {
87115
if (!existsSync(templatePath)) {
88116
console.error(`❌ Template "${template}" not found!`)
89117
console.log('Available templates: basic, filesystem, api, ui')
118+
console.log('💡 Tip: Use "ui" template for React components and modern UI features')
90119
process.exit(1)
91120
}
92121

@@ -120,5 +149,43 @@ function updatePackageJson(projectPath: string, projectName: string) {
120149
writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))
121150
}
122151

152+
function promptForProjectName(): Promise<string | null> {
153+
return new Promise((resolvePromise) => {
154+
const rl = createInterface({
155+
input: process.stdin,
156+
output: process.stdout
157+
})
158+
159+
const askForName = () => {
160+
rl.question('What is your project name? ', (answer) => {
161+
const trimmed = answer.trim()
162+
163+
if (!trimmed) {
164+
console.log('❌ Project name is required')
165+
askForName()
166+
return
167+
}
168+
169+
if (!/^[a-zA-Z0-9-_]+$/.test(trimmed)) {
170+
console.log('❌ Project name can only contain letters, numbers, hyphens, and underscores')
171+
askForName()
172+
return
173+
}
174+
175+
if (existsSync(join(process.cwd(), trimmed))) {
176+
console.log(`❌ Directory "${trimmed}" already exists! Please choose a different name.`)
177+
askForName()
178+
return
179+
}
180+
181+
rl.close()
182+
resolvePromise(trimmed)
183+
})
184+
}
185+
186+
askForName()
187+
})
188+
}
189+
123190
program.parse()
124191

pnpm-lock.yaml

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)