@@ -4,6 +4,7 @@ import { execSync } from 'node:child_process'
44import { copyFileSync , existsSync , mkdirSync , readdirSync , readFileSync , writeFileSync } from 'node:fs'
55import { dirname , join , resolve } from 'node:path'
66import { fileURLToPath } from 'node:url'
7+ import { createInterface } from 'node:readline'
78import { Command } from 'commander'
89
910const __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 - z A - Z 0 - 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+
123190program . parse ( )
124191
0 commit comments