@agiflowai/scaffold-mcp 0.6.0 → 1.0.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 (30) hide show
  1. package/README.md +11 -71
  2. package/dist/ScaffoldConfigLoader-CI0T6zdG.js +142 -0
  3. package/dist/{ScaffoldConfigLoader-DzcV5a_c.cjs → ScaffoldConfigLoader-DQMCLVGD.cjs} +1 -1
  4. package/dist/ScaffoldConfigLoader-DhthV6xq.js +3 -0
  5. package/dist/{ScaffoldService-BgFWAOLQ.cjs → ScaffoldService-B-L4gwHt.cjs} +6 -0
  6. package/dist/ScaffoldService-Cx4ZonaT.cjs +3 -0
  7. package/dist/ScaffoldService-DVsusUh5.js +3 -0
  8. package/dist/ScaffoldService-QgQKHMM-.js +290 -0
  9. package/dist/TemplateService-BZRt3NI8.cjs +3 -0
  10. package/dist/TemplateService-CiZJA06s.js +79 -0
  11. package/dist/TemplateService-DropYdp8.js +3 -0
  12. package/dist/VariableReplacementService-B3qARIC9.js +66 -0
  13. package/dist/{VariableReplacementService-YUpL5nAC.cjs → VariableReplacementService-BrJ1PdKm.cjs} +1 -1
  14. package/dist/VariableReplacementService-D8C-IsP-.js +3 -0
  15. package/dist/cli.cjs +1363 -0
  16. package/dist/cli.d.cts +1 -0
  17. package/dist/cli.d.ts +1 -0
  18. package/dist/cli.js +1355 -0
  19. package/dist/index.cjs +32 -3336
  20. package/dist/index.d.cts +798 -0
  21. package/dist/index.d.ts +799 -0
  22. package/dist/index.js +7 -0
  23. package/dist/stdio-Cz5aRdvr.cjs +2210 -0
  24. package/dist/stdio-Dmpwju2k.js +2074 -0
  25. package/package.json +17 -4
  26. package/dist/ScaffoldService-BvD9WvRi.cjs +0 -3
  27. package/dist/TemplateService-B5EZjPB0.cjs +0 -3
  28. /package/dist/{ScaffoldConfigLoader-1Pcv9cxm.cjs → ScaffoldConfigLoader-BrmvENTo.cjs} +0 -0
  29. /package/dist/{TemplateService-_KpkoLfZ.cjs → TemplateService-DRubcvS9.cjs} +0 -0
  30. /package/dist/{VariableReplacementService-ClshNY_C.cjs → VariableReplacementService-BL84vnKk.cjs} +0 -0
package/dist/cli.cjs ADDED
@@ -0,0 +1,1363 @@
1
+ #!/usr/bin/env node
2
+ const require_chunk = require('./chunk-CUT6urMc.cjs');
3
+ const require_stdio = require('./stdio-Cz5aRdvr.cjs');
4
+ require('./ScaffoldConfigLoader-BrmvENTo.cjs');
5
+ require('./ScaffoldService-B-L4gwHt.cjs');
6
+ require('./TemplateService-DRubcvS9.cjs');
7
+ require('./VariableReplacementService-BL84vnKk.cjs');
8
+ let commander = require("commander");
9
+ commander = require_chunk.__toESM(commander);
10
+ let node_path = require("node:path");
11
+ node_path = require_chunk.__toESM(node_path);
12
+ let __agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
13
+ __agiflowai_aicode_utils = require_chunk.__toESM(__agiflowai_aicode_utils);
14
+ let fs_extra = require("fs-extra");
15
+ fs_extra = require_chunk.__toESM(fs_extra);
16
+ let execa = require("execa");
17
+ execa = require_chunk.__toESM(execa);
18
+ let __inquirer_prompts = require("@inquirer/prompts");
19
+ __inquirer_prompts = require_chunk.__toESM(__inquirer_prompts);
20
+ let __modelcontextprotocol_sdk_server_index_js = require("@modelcontextprotocol/sdk/server/index.js");
21
+ __modelcontextprotocol_sdk_server_index_js = require_chunk.__toESM(__modelcontextprotocol_sdk_server_index_js);
22
+ let __modelcontextprotocol_sdk_types_js = require("@modelcontextprotocol/sdk/types.js");
23
+ __modelcontextprotocol_sdk_types_js = require_chunk.__toESM(__modelcontextprotocol_sdk_types_js);
24
+
25
+ //#region package.json
26
+ var name = "@agiflowai/scaffold-mcp";
27
+ var description = "MCP server for scaffolding applications with boilerplate templates";
28
+ var version = "0.6.0";
29
+ var license = "AGPL-3.0";
30
+ var author = "AgiflowIO";
31
+ var repository = {
32
+ "type": "git",
33
+ "url": "https://github.com/AgiFlow/aicode-toolkit.git",
34
+ "directory": "packages/scaffold-mcp"
35
+ };
36
+ var homepage = "https://github.com/AgiFlow/aicode-toolkit#readme";
37
+ var bugs = { "url": "https://github.com/AgiFlow/aicode-toolkit/issues" };
38
+ var keywords = [
39
+ "mcp",
40
+ "model-context-protocol",
41
+ "scaffold",
42
+ "boilerplate",
43
+ "template",
44
+ "code-generation",
45
+ "nextjs",
46
+ "react",
47
+ "vite"
48
+ ];
49
+ var bin = { "scaffold-mcp": "./dist/cli.cjs" };
50
+ var main$1 = "./dist/index.cjs";
51
+ var types = "./dist/index.d.cts";
52
+ var module$1 = "./dist/index.js";
53
+ var files = ["dist", "README.md"];
54
+ var scripts = {
55
+ "dev": "node --loader ts-node/esm src/cli.ts",
56
+ "build": "tsdown",
57
+ "test": "vitest --run",
58
+ "typecheck": "tsc --noEmit"
59
+ };
60
+ var dependencies = {
61
+ "@agiflowai/aicode-utils": "workspace:*",
62
+ "@composio/json-schema-to-zod": "0.1.15",
63
+ "@inquirer/prompts": "^7.8.6",
64
+ "@modelcontextprotocol/sdk": "1.19.1",
65
+ "chalk": "5.6.2",
66
+ "commander": "14.0.1",
67
+ "execa": "^9.5.2",
68
+ "express": "^4.21.2",
69
+ "fs-extra": "11.3.2",
70
+ "js-yaml": "4.1.0",
71
+ "liquidjs": "10.21.1",
72
+ "pino": "^10.0.0",
73
+ "pino-pretty": "^13.1.1",
74
+ "zod": "3.25.76"
75
+ };
76
+ var devDependencies = {
77
+ "@types/express": "^5.0.0",
78
+ "@types/fs-extra": "^11.0.4",
79
+ "@types/js-yaml": "^4.0.9",
80
+ "@types/node": "^22.0.0",
81
+ "tsdown": "^0.15.6",
82
+ "typescript": "5.9.3"
83
+ };
84
+ var publishConfig = { "access": "public" };
85
+ var type = "module";
86
+ var exports$1 = {
87
+ ".": {
88
+ "import": "./dist/index.js",
89
+ "require": "./dist/index.cjs"
90
+ },
91
+ "./cli": {
92
+ "import": "./dist/cli.js",
93
+ "require": "./dist/cli.cjs"
94
+ },
95
+ "./package.json": "./package.json"
96
+ };
97
+ var package_default = {
98
+ name,
99
+ description,
100
+ version,
101
+ license,
102
+ author,
103
+ repository,
104
+ homepage,
105
+ bugs,
106
+ keywords,
107
+ bin,
108
+ main: main$1,
109
+ types,
110
+ module: module$1,
111
+ files,
112
+ scripts,
113
+ dependencies,
114
+ devDependencies,
115
+ publishConfig,
116
+ type,
117
+ exports: exports$1
118
+ };
119
+
120
+ //#endregion
121
+ //#region src/commands/add.ts
122
+ /**
123
+ * Add command - add a template to templates folder
124
+ */
125
+ const addCommand = new commander.Command("add").description("Add a template to templates folder").requiredOption("--name <name>", "Template name").requiredOption("--url <url>", "URL of the template repository to download").option("--path <path>", "Override templates folder path (uses toolkit.yaml config by default)").option("--type <type>", "Template type: boilerplate or scaffold", "boilerplate").action(async (options) => {
126
+ try {
127
+ const templatesPath = options.path ? node_path.default.resolve(options.path) : await __agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
128
+ const templateType = options.type.toLowerCase();
129
+ const templateName = options.name;
130
+ const templateUrl = options.url;
131
+ if (templateType !== "boilerplate" && templateType !== "scaffold") {
132
+ __agiflowai_aicode_utils.messages.error("Invalid template type. Use: boilerplate or scaffold");
133
+ process.exit(1);
134
+ }
135
+ const targetFolder = node_path.default.join(templatesPath, `${templateType}s`, templateName);
136
+ if (await fs_extra.pathExists(targetFolder)) {
137
+ __agiflowai_aicode_utils.messages.error(`Template '${templateName}' already exists at ${targetFolder}`);
138
+ process.exit(1);
139
+ }
140
+ __agiflowai_aicode_utils.print.info(`${__agiflowai_aicode_utils.icons.download} Downloading template '${templateName}' from ${templateUrl}...`);
141
+ await fs_extra.ensureDir(node_path.default.dirname(targetFolder));
142
+ const parsedUrl = require_stdio.parseGitHubUrl(templateUrl);
143
+ try {
144
+ if (parsedUrl.isSubdirectory && parsedUrl.branch && parsedUrl.subdirectory) {
145
+ __agiflowai_aicode_utils.print.info(`${__agiflowai_aicode_utils.icons.folder} Detected subdirectory: ${parsedUrl.subdirectory} (branch: ${parsedUrl.branch})`);
146
+ await require_stdio.cloneSubdirectory(parsedUrl.repoUrl, parsedUrl.branch, parsedUrl.subdirectory, targetFolder);
147
+ } else await require_stdio.cloneRepository(parsedUrl.repoUrl, targetFolder);
148
+ __agiflowai_aicode_utils.messages.success(`Template '${templateName}' added successfully!`);
149
+ __agiflowai_aicode_utils.print.header(`\n${__agiflowai_aicode_utils.icons.folder} Template location:`);
150
+ __agiflowai_aicode_utils.print.indent(targetFolder);
151
+ const configFiles = [node_path.default.join(targetFolder, "boilerplate.yaml"), node_path.default.join(targetFolder, "scaffold.yaml")];
152
+ let hasConfig = false;
153
+ for (const configFile of configFiles) if (await fs_extra.pathExists(configFile)) {
154
+ __agiflowai_aicode_utils.print.header(`\n${__agiflowai_aicode_utils.icons.config} Configuration file found:`);
155
+ __agiflowai_aicode_utils.print.indent(node_path.default.basename(configFile));
156
+ hasConfig = true;
157
+ break;
158
+ }
159
+ if (!hasConfig) {
160
+ __agiflowai_aicode_utils.messages.warning("Warning: No configuration file found (boilerplate.yaml or scaffold.yaml)");
161
+ __agiflowai_aicode_utils.print.indent("You may need to create one manually.");
162
+ }
163
+ __agiflowai_aicode_utils.sections.nextSteps([`Review the template in ${targetFolder}`, `Test it with: scaffold-mcp ${templateType} list`]);
164
+ } catch (error) {
165
+ if (error.message.includes("not found") || error.message.includes("command not found")) __agiflowai_aicode_utils.messages.error("git command not found. Please install git first.");
166
+ else if (error.message.includes("Authentication failed")) __agiflowai_aicode_utils.messages.error("Authentication failed. Make sure you have access to the repository.");
167
+ else if (error.message.includes("Repository not found")) __agiflowai_aicode_utils.messages.error("Repository not found. Check the URL and try again.");
168
+ else __agiflowai_aicode_utils.messages.error("Failed to clone repository:", error);
169
+ process.exit(1);
170
+ }
171
+ } catch (error) {
172
+ __agiflowai_aicode_utils.messages.error("Error adding template:", error);
173
+ process.exit(1);
174
+ }
175
+ });
176
+
177
+ //#endregion
178
+ //#region src/commands/boilerplate.ts
179
+ /**
180
+ * Boilerplate CLI command
181
+ */
182
+ const boilerplateCommand = new commander.Command("boilerplate").description("Manage boilerplate templates");
183
+ boilerplateCommand.command("list").description("List all available boilerplate templates").action(async () => {
184
+ try {
185
+ const { boilerplates } = await new require_stdio.BoilerplateService(await __agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath()).listBoilerplates();
186
+ if (boilerplates.length === 0) {
187
+ __agiflowai_aicode_utils.messages.warning("No boilerplate templates found.");
188
+ return;
189
+ }
190
+ __agiflowai_aicode_utils.print.header(`\n${__agiflowai_aicode_utils.icons.package} Available Boilerplate Templates:\n`);
191
+ for (const bp of boilerplates) {
192
+ __agiflowai_aicode_utils.print.highlight(` ${bp.name}`);
193
+ __agiflowai_aicode_utils.print.debug(` ${bp.description}`);
194
+ __agiflowai_aicode_utils.print.debug(` Target: ${bp.target_folder}`);
195
+ const required = typeof bp.variables_schema === "object" && bp.variables_schema !== null && "required" in bp.variables_schema ? bp.variables_schema.required : [];
196
+ if (required && required.length > 0) __agiflowai_aicode_utils.print.debug(` Required: ${required.join(", ")}`);
197
+ __agiflowai_aicode_utils.print.newline();
198
+ }
199
+ } catch (error) {
200
+ __agiflowai_aicode_utils.messages.error("Error listing boilerplates:", error);
201
+ process.exit(1);
202
+ }
203
+ });
204
+ boilerplateCommand.command("create <boilerplateName>").description("Create a new project from a boilerplate template").option("-v, --vars <json>", "JSON string containing variables for the boilerplate").option("-m, --monolith", "Create as monolith project at workspace root with toolkit.yaml (default: false, creates as monorepo with project.json)").option("-t, --target-folder <path>", "Override target folder (defaults to boilerplate targetFolder for monorepo, workspace root for monolith)").option("--verbose", "Enable verbose logging").action(async (boilerplateName, options) => {
205
+ try {
206
+ const boilerplateService = new require_stdio.BoilerplateService(await __agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath());
207
+ let variables = {};
208
+ if (options.vars) try {
209
+ variables = JSON.parse(options.vars);
210
+ } catch (error) {
211
+ __agiflowai_aicode_utils.messages.error("Error parsing variables JSON:", error);
212
+ __agiflowai_aicode_utils.messages.hint("Example: --vars '{\"appName\": \"my-app\", \"description\": \"My application\"}'");
213
+ process.exit(1);
214
+ }
215
+ const boilerplate = await boilerplateService.getBoilerplate(boilerplateName);
216
+ if (!boilerplate) {
217
+ const { boilerplates } = await boilerplateService.listBoilerplates();
218
+ __agiflowai_aicode_utils.messages.error(`Boilerplate '${boilerplateName}' not found.`);
219
+ __agiflowai_aicode_utils.print.warning(`Available boilerplates: ${boilerplates.map((b) => b.name).join(", ")}`);
220
+ process.exit(1);
221
+ }
222
+ const required = typeof boilerplate.variables_schema === "object" && boilerplate.variables_schema !== null && "required" in boilerplate.variables_schema ? boilerplate.variables_schema.required : [];
223
+ const missing = required.filter((key) => !variables[key]);
224
+ if (missing.length > 0) {
225
+ __agiflowai_aicode_utils.messages.error(`Missing required variables: ${missing.join(", ")}`);
226
+ __agiflowai_aicode_utils.messages.hint(`Use --vars with a JSON object containing: ${missing.join(", ")}`);
227
+ const exampleVars = {};
228
+ for (const key of required) if (key === "appName" || key === "packageName") exampleVars[key] = "my-app";
229
+ else if (key === "description") exampleVars[key] = "My application description";
230
+ else exampleVars[key] = `<${key}>`;
231
+ __agiflowai_aicode_utils.print.debug(`Example: scaffold-mcp boilerplate create ${boilerplateName} --vars '${JSON.stringify(exampleVars)}'`);
232
+ process.exit(1);
233
+ }
234
+ if (options.verbose) {
235
+ __agiflowai_aicode_utils.print.info(`${__agiflowai_aicode_utils.icons.wrench} Boilerplate: ${boilerplateName}`);
236
+ __agiflowai_aicode_utils.print.info(`${__agiflowai_aicode_utils.icons.chart} Variables: ${JSON.stringify(variables, null, 2)}`);
237
+ }
238
+ __agiflowai_aicode_utils.messages.loading(`Creating project from boilerplate '${boilerplateName}'...`);
239
+ const result = await boilerplateService.useBoilerplate({
240
+ boilerplateName,
241
+ variables,
242
+ monolith: options.monolith,
243
+ targetFolderOverride: options.targetFolder
244
+ });
245
+ if (result.success) {
246
+ __agiflowai_aicode_utils.messages.success("Project created successfully!");
247
+ __agiflowai_aicode_utils.print.info(result.message);
248
+ if (result.createdFiles && result.createdFiles.length > 0) __agiflowai_aicode_utils.sections.createdFiles(result.createdFiles);
249
+ const projectName = variables.appName || variables.packageName;
250
+ if (projectName) {
251
+ const targetFolder = options.targetFolder || (options.monolith ? "." : boilerplate.target_folder);
252
+ const projectPath = options.monolith ? "." : `${targetFolder}/${projectName}`;
253
+ const steps = projectPath === "." ? ["pnpm install", "pnpm dev"] : [
254
+ `cd ${projectPath}`,
255
+ "pnpm install",
256
+ "pnpm dev"
257
+ ];
258
+ __agiflowai_aicode_utils.sections.nextSteps(steps);
259
+ }
260
+ } else {
261
+ __agiflowai_aicode_utils.messages.error(`Failed to create project: ${result.message}`);
262
+ process.exit(1);
263
+ }
264
+ } catch (error) {
265
+ __agiflowai_aicode_utils.messages.error("Error creating project:", error);
266
+ if (options.verbose) console.error("Stack trace:", error.stack);
267
+ process.exit(1);
268
+ }
269
+ });
270
+ boilerplateCommand.command("info <boilerplateName>").description("Show detailed information about a boilerplate template").action(async (boilerplateName) => {
271
+ try {
272
+ const bp = await new require_stdio.BoilerplateService(await __agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath()).getBoilerplate(boilerplateName);
273
+ if (!bp) {
274
+ __agiflowai_aicode_utils.messages.error(`Boilerplate '${boilerplateName}' not found.`);
275
+ process.exit(1);
276
+ }
277
+ __agiflowai_aicode_utils.print.header(`\n${__agiflowai_aicode_utils.icons.package} Boilerplate: ${bp.name}\n`);
278
+ __agiflowai_aicode_utils.print.debug(`Description: ${bp.description}`);
279
+ __agiflowai_aicode_utils.print.debug(`Template Path: ${bp.template_path}`);
280
+ __agiflowai_aicode_utils.print.debug(`Target Folder: ${bp.target_folder}`);
281
+ __agiflowai_aicode_utils.print.header(`\n${__agiflowai_aicode_utils.icons.config} Variables Schema:`);
282
+ console.log(JSON.stringify(bp.variables_schema, null, 2));
283
+ if (bp.includes && bp.includes.length > 0) __agiflowai_aicode_utils.sections.list(`${__agiflowai_aicode_utils.icons.folder} Included Files:`, bp.includes);
284
+ } catch (error) {
285
+ __agiflowai_aicode_utils.messages.error("Error getting boilerplate info:", error);
286
+ process.exit(1);
287
+ }
288
+ });
289
+
290
+ //#endregion
291
+ //#region src/commands/init.ts
292
+ /**
293
+ * Execute git init safely using execa to prevent command injection
294
+ */
295
+ async function gitInit(projectPath) {
296
+ try {
297
+ await (0, execa.execa)("git", ["init", projectPath]);
298
+ } catch (error) {
299
+ const execaError = error;
300
+ throw new Error(`Git init failed: ${execaError.stderr || execaError.message}`);
301
+ }
302
+ }
303
+ const DEFAULT_TEMPLATE_REPO = {
304
+ owner: "AgiFlow",
305
+ repo: "aicode-toolkit",
306
+ branch: "main",
307
+ path: "templates"
308
+ };
309
+ /**
310
+ * Interactive setup for new projects
311
+ * Prompts user for project details when no .git folder is found
312
+ * @param providedName - Optional project name from CLI argument
313
+ * @param providedProjectType - Optional project type from CLI argument
314
+ */
315
+ async function setupNewProject(providedName, providedProjectType) {
316
+ __agiflowai_aicode_utils.print.header(`\n${__agiflowai_aicode_utils.icons.rocket} New Project Setup`);
317
+ __agiflowai_aicode_utils.print.info("No Git repository detected. Let's set up a new project!\n");
318
+ let projectName;
319
+ const reservedNames = [
320
+ ".",
321
+ "..",
322
+ "CON",
323
+ "PRN",
324
+ "AUX",
325
+ "NUL",
326
+ "COM1",
327
+ "COM2",
328
+ "COM3",
329
+ "COM4",
330
+ "COM5",
331
+ "COM6",
332
+ "COM7",
333
+ "COM8",
334
+ "COM9",
335
+ "LPT1",
336
+ "LPT2",
337
+ "LPT3",
338
+ "LPT4",
339
+ "LPT5",
340
+ "LPT6",
341
+ "LPT7",
342
+ "LPT8",
343
+ "LPT9"
344
+ ];
345
+ const validateProjectName = (value) => {
346
+ const trimmed = value.trim();
347
+ if (!trimmed) return "Project name is required";
348
+ if (!/^[a-zA-Z0-9]/.test(trimmed)) return "Project name must start with a letter or number";
349
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/.test(trimmed)) return "Project name can only contain letters, numbers, hyphens, and underscores";
350
+ if (reservedNames.includes(trimmed.toUpperCase())) return "Project name uses a reserved name";
351
+ return true;
352
+ };
353
+ if (providedName) {
354
+ const trimmedName = providedName.trim();
355
+ const validationResult = validateProjectName(trimmedName);
356
+ if (validationResult !== true) throw new Error(validationResult);
357
+ projectName = trimmedName;
358
+ __agiflowai_aicode_utils.print.info(`Project name: ${projectName}`);
359
+ } else projectName = await (0, __inquirer_prompts.input)({
360
+ message: "Enter your project name:",
361
+ validate: validateProjectName
362
+ });
363
+ let projectType;
364
+ if (providedProjectType) {
365
+ if (providedProjectType !== __agiflowai_aicode_utils.ProjectType.MONOLITH && providedProjectType !== __agiflowai_aicode_utils.ProjectType.MONOREPO) throw new Error(`Invalid project type '${providedProjectType}'. Must be '${__agiflowai_aicode_utils.ProjectType.MONOLITH}' or '${__agiflowai_aicode_utils.ProjectType.MONOREPO}'`);
366
+ projectType = providedProjectType;
367
+ __agiflowai_aicode_utils.print.info(`Project type: ${projectType}`);
368
+ } else projectType = await (0, __inquirer_prompts.select)({
369
+ message: "Select project type:",
370
+ choices: [{
371
+ name: "Monolith - Single application structure",
372
+ value: __agiflowai_aicode_utils.ProjectType.MONOLITH,
373
+ description: "Traditional single-application project structure"
374
+ }, {
375
+ name: "Monorepo - Multiple packages/apps in one repository",
376
+ value: __agiflowai_aicode_utils.ProjectType.MONOREPO,
377
+ description: "Multiple packages managed together (uses workspaces)"
378
+ }]
379
+ });
380
+ const hasExistingRepo = await (0, __inquirer_prompts.confirm)({
381
+ message: "Do you have an existing Git repository you want to use?",
382
+ default: false
383
+ });
384
+ const projectPath = node_path.default.join(process.cwd(), projectName.trim());
385
+ try {
386
+ await fs_extra.mkdir(projectPath, { recursive: false });
387
+ __agiflowai_aicode_utils.print.success(`${__agiflowai_aicode_utils.icons.check} Created project directory: ${projectPath}`);
388
+ } catch (error) {
389
+ if (error.code === "EEXIST") throw new Error(`Directory '${projectName}' already exists. Please choose a different name.`);
390
+ throw error;
391
+ }
392
+ if (hasExistingRepo) {
393
+ const repoUrl = await (0, __inquirer_prompts.input)({
394
+ message: "Enter Git repository URL:",
395
+ validate: (value) => {
396
+ if (!value.trim()) return "Repository URL is required";
397
+ if (!value.match(/^(https?:\/\/|git@)/)) return "Please enter a valid Git repository URL";
398
+ return true;
399
+ }
400
+ });
401
+ __agiflowai_aicode_utils.print.info(`${__agiflowai_aicode_utils.icons.download} Cloning repository...`);
402
+ try {
403
+ const parsed = require_stdio.parseGitHubUrl(repoUrl.trim());
404
+ if (parsed.isSubdirectory && parsed.branch && parsed.subdirectory) await require_stdio.cloneSubdirectory(parsed.repoUrl, parsed.branch, parsed.subdirectory, projectPath);
405
+ else await require_stdio.cloneRepository(parsed.repoUrl, projectPath);
406
+ __agiflowai_aicode_utils.print.success(`${__agiflowai_aicode_utils.icons.check} Repository cloned successfully`);
407
+ } catch (error) {
408
+ await fs_extra.remove(projectPath);
409
+ throw new Error(`Failed to clone repository: ${error.message}`);
410
+ }
411
+ } else if (await (0, __inquirer_prompts.confirm)({
412
+ message: "Initialize a new Git repository?",
413
+ default: true
414
+ })) {
415
+ __agiflowai_aicode_utils.print.info(`${__agiflowai_aicode_utils.icons.rocket} Initializing Git repository...`);
416
+ try {
417
+ await gitInit(projectPath);
418
+ __agiflowai_aicode_utils.print.success(`${__agiflowai_aicode_utils.icons.check} Git repository initialized`);
419
+ } catch (error) {
420
+ __agiflowai_aicode_utils.messages.warning(`Failed to initialize Git: ${error.message}`);
421
+ }
422
+ }
423
+ return {
424
+ projectPath,
425
+ projectType
426
+ };
427
+ }
428
+ /**
429
+ * Download templates from GitHub repository
430
+ */
431
+ async function downloadTemplates(templatesPath) {
432
+ try {
433
+ __agiflowai_aicode_utils.print.info(`${__agiflowai_aicode_utils.icons.download} Fetching templates from ${DEFAULT_TEMPLATE_REPO.owner}/${DEFAULT_TEMPLATE_REPO.repo}...`);
434
+ const templateDirs = (await require_stdio.fetchGitHubDirectoryContents(DEFAULT_TEMPLATE_REPO.owner, DEFAULT_TEMPLATE_REPO.repo, DEFAULT_TEMPLATE_REPO.path, DEFAULT_TEMPLATE_REPO.branch)).filter((item) => item.type === "dir");
435
+ if (templateDirs.length === 0) {
436
+ __agiflowai_aicode_utils.messages.warning("No templates found in repository");
437
+ return;
438
+ }
439
+ __agiflowai_aicode_utils.print.info(`${__agiflowai_aicode_utils.icons.folder} Found ${templateDirs.length} template(s)`);
440
+ for (const template of templateDirs) {
441
+ const targetFolder = node_path.default.join(templatesPath, template.name);
442
+ if (await fs_extra.pathExists(targetFolder)) {
443
+ __agiflowai_aicode_utils.print.info(`${__agiflowai_aicode_utils.icons.skip} Skipping ${template.name} (already exists)`);
444
+ continue;
445
+ }
446
+ __agiflowai_aicode_utils.print.info(`${__agiflowai_aicode_utils.icons.download} Downloading ${template.name}...`);
447
+ await require_stdio.cloneSubdirectory(`https://github.com/${DEFAULT_TEMPLATE_REPO.owner}/${DEFAULT_TEMPLATE_REPO.repo}.git`, DEFAULT_TEMPLATE_REPO.branch, template.path, targetFolder);
448
+ __agiflowai_aicode_utils.print.success(`${__agiflowai_aicode_utils.icons.check} Downloaded ${template.name}`);
449
+ }
450
+ __agiflowai_aicode_utils.print.success(`\n${__agiflowai_aicode_utils.icons.check} All templates downloaded successfully!`);
451
+ } catch (error) {
452
+ throw new Error(`Failed to download templates: ${error.message}`);
453
+ }
454
+ }
455
+ /**
456
+ * Init command - initialize templates folder
457
+ */
458
+ const initCommand = new commander.Command("init").description("Initialize templates folder structure at workspace root or create new project").option("--no-download", "Skip downloading templates from repository").option("--path <path>", "Custom path for templates folder (relative to workspace root)").option("--name <name>", "Project name (for new projects)").option("--project-type <type>", "Project type: monolith or monorepo (for new projects)").action(async (options) => {
459
+ try {
460
+ let workspaceRoot = await require_stdio.findWorkspaceRoot();
461
+ let projectType;
462
+ if (!workspaceRoot) {
463
+ const projectSetup = await setupNewProject(options.name, options.projectType);
464
+ workspaceRoot = projectSetup.projectPath;
465
+ projectType = projectSetup.projectType;
466
+ __agiflowai_aicode_utils.print.info(`\n${__agiflowai_aicode_utils.icons.folder} Project type: ${projectType}`);
467
+ }
468
+ let templatesPath = options.path ? node_path.default.join(workspaceRoot, options.path) : node_path.default.join(workspaceRoot, "templates");
469
+ if (await fs_extra.pathExists(templatesPath)) {
470
+ __agiflowai_aicode_utils.messages.warning(`\n⚠️ Templates folder already exists at: ${templatesPath}`);
471
+ if (await (0, __inquirer_prompts.confirm)({
472
+ message: "Do you want to use a different folder for templates?",
473
+ default: false
474
+ })) {
475
+ const alternateFolder = await (0, __inquirer_prompts.input)({
476
+ message: "Enter alternate folder name for templates:",
477
+ default: "my-templates",
478
+ validate: (value) => {
479
+ if (!value.trim()) return "Folder name is required";
480
+ if (!/^[a-zA-Z0-9_\-/]+$/.test(value)) return "Folder name can only contain letters, numbers, hyphens, underscores, and slashes";
481
+ return true;
482
+ }
483
+ });
484
+ templatesPath = node_path.default.join(workspaceRoot, alternateFolder.trim());
485
+ const toolkitConfig = {
486
+ templatesPath: alternateFolder.trim(),
487
+ projectType
488
+ };
489
+ __agiflowai_aicode_utils.print.info(`\n${__agiflowai_aicode_utils.icons.config} Creating toolkit.yaml with custom templates path...`);
490
+ await __agiflowai_aicode_utils.TemplatesManagerService.writeToolkitConfig(toolkitConfig, workspaceRoot);
491
+ __agiflowai_aicode_utils.print.success(`${__agiflowai_aicode_utils.icons.check} toolkit.yaml created`);
492
+ } else __agiflowai_aicode_utils.print.info(`\n${__agiflowai_aicode_utils.icons.info} Using existing templates folder`);
493
+ }
494
+ __agiflowai_aicode_utils.print.info(`\n${__agiflowai_aicode_utils.icons.rocket} Initializing templates folder at: ${templatesPath}`);
495
+ await fs_extra.ensureDir(templatesPath);
496
+ await fs_extra.writeFile(node_path.default.join(templatesPath, "README.md"), `# Templates
497
+
498
+ This folder contains boilerplate templates and scaffolding methods for your projects.
499
+
500
+ ## Templates
501
+
502
+ Templates are organized by framework/technology and include configuration files (\`scaffold.yaml\`) that define:
503
+ - Boilerplates: Full project starter templates
504
+ - Features: Code scaffolding methods for adding new features to existing projects
505
+
506
+ ## Adding More Templates
507
+
508
+ Use the \`aicode-toolkit\` CLI to add templates from remote repositories:
509
+
510
+ \`\`\`bash
511
+ npx @agiflowai/aicode-toolkit add --name my-template --url https://github.com/user/template
512
+ \`\`\`
513
+
514
+ Or add templates from subdirectories:
515
+
516
+ \`\`\`bash
517
+ npx @agiflowai/aicode-toolkit add --name nextjs-template --url https://github.com/user/repo/tree/main/templates/nextjs
518
+ \`\`\`
519
+
520
+ ## Creating Custom Templates
521
+
522
+ Each template should have a \`scaffold.yaml\` configuration file defining:
523
+ - \`boilerplate\`: Array of boilerplate configurations
524
+ - \`features\`: Array of feature scaffold configurations
525
+
526
+ Template files use Liquid syntax for variable placeholders: \`{{ variableName }}\`
527
+
528
+ See existing templates for examples and documentation for more details.
529
+ `);
530
+ __agiflowai_aicode_utils.print.success(`${__agiflowai_aicode_utils.icons.check} Templates folder created!`);
531
+ if (options.download !== false) await downloadTemplates(templatesPath);
532
+ else __agiflowai_aicode_utils.print.info(`${__agiflowai_aicode_utils.icons.skip} Skipping template download (use --download to enable)`);
533
+ __agiflowai_aicode_utils.print.header(`\n${__agiflowai_aicode_utils.icons.folder} Templates location:`);
534
+ __agiflowai_aicode_utils.print.indent(templatesPath);
535
+ const nextSteps = [];
536
+ if (options.download === false) nextSteps.push(`Add templates: npx @agiflowai/aicode-toolkit add --name <name> --url <url>`);
537
+ else {
538
+ nextSteps.push(`List available boilerplates: scaffold-mcp boilerplate list`);
539
+ nextSteps.push(`Add more templates: npx @agiflowai/aicode-toolkit add --name <name> --url <url>`);
540
+ }
541
+ __agiflowai_aicode_utils.sections.nextSteps(nextSteps);
542
+ } catch (error) {
543
+ __agiflowai_aicode_utils.messages.error(`Error initializing templates folder: ${error.message}`);
544
+ process.exit(1);
545
+ }
546
+ });
547
+
548
+ //#endregion
549
+ //#region src/prompts/GenerateBoilerplatePrompt.ts
550
+ /**
551
+ * Prompt for generating boilerplates
552
+ */
553
+ var GenerateBoilerplatePrompt = class GenerateBoilerplatePrompt {
554
+ static PROMPT_NAME = "generate-boilerplate";
555
+ /**
556
+ * Get the prompt definition for MCP
557
+ */
558
+ getDefinition() {
559
+ return {
560
+ name: GenerateBoilerplatePrompt.PROMPT_NAME,
561
+ description: "Generate a new boilerplate template configuration",
562
+ arguments: [{
563
+ name: "request",
564
+ description: "Describe the boilerplate template you want to create",
565
+ required: false
566
+ }]
567
+ };
568
+ }
569
+ /**
570
+ * Get the prompt messages
571
+ */
572
+ getMessages(args) {
573
+ const userRequest = args?.request || "";
574
+ return [{
575
+ role: "user",
576
+ content: {
577
+ type: "text",
578
+ text: `You are helping create a new boilerplate template configuration using the scaffold-mcp MCP tools.
579
+
580
+ ${userRequest ? `User request: ${userRequest}\n` : ""}
581
+ Your task:
582
+
583
+ 1. **Gather Information**: Ask for any missing details:
584
+ - Framework/technology (e.g., "React Vite", "Express API", "Next.js 15")
585
+ - Template name (kebab-case, e.g., "react-vite", "nextjs-15")
586
+ - Boilerplate name (prefixed with "scaffold-", e.g., "scaffold-vite-app")
587
+ - Target folder (e.g., "apps", "packages")
588
+ - Project type (app, library, service, etc.)
589
+ - Required variables (at minimum: appName or packageName)
590
+ - Files to include in the template
591
+
592
+ 2. **Use MCP Tools** in order:
593
+ - \`generate-boilerplate\` - Creates the boilerplate configuration
594
+ - \`generate-boilerplate-file\` - Creates each template file
595
+ - \`list-boilerplates\` - Verify it appears
596
+ - \`use-boilerplate\` - Test the boilerplate
597
+
598
+ Important:
599
+ - Template naming: Use kebab-case (e.g., "react-vite", "express-api")
600
+ - Boilerplate naming: Prefix with "scaffold-" (e.g., "scaffold-vite-app")
601
+ - Target folder: "apps" for applications, "packages" for libraries
602
+ - Include files explicitly - avoid wildcards
603
+ - Template syntax: use {{ variableName }}
604
+
605
+ **Description Field Guidelines (CRITICAL)**:
606
+ The description should be a comprehensive multi-paragraph overview (3-5 sentences):
607
+ - Paragraph 1: Core technology stack and primary value proposition
608
+ - Paragraph 2: Target use cases and ideal project types
609
+ - Paragraph 3: Key integrations or special features (if applicable)
610
+
611
+ Example:
612
+ "A modern React SPA template powered by Vite for lightning-fast HMR, featuring TanStack Router for type-safe routing and TanStack Query for server state management.
613
+ Perfect for building data-driven dashboards, admin panels, and interactive web applications requiring client-side routing and real-time data synchronization.
614
+
615
+ Includes Agiflow Config Management System integration with systematic environment variable naming (VITE_{CATEGORY}_{SUBCATEGORY}_{PROPERTY}) and auto-generated configuration templates for cloud deployment."
616
+
617
+ **Instruction Field Guidelines (CRITICAL)**:
618
+ The instruction should be a detailed multi-section guide that helps AI understand the codebase:
619
+
620
+ 1. **File purposes** section: List each major file/directory with its purpose
621
+ Format: "- path/to/file: Description of what this file does"
622
+
623
+ 2. **How to use the scaffolded code** section: Step-by-step workflows
624
+ Format: Numbered list with specific examples
625
+ - How to add routes/pages
626
+ - How to fetch data
627
+ - How to handle authentication
628
+ - How to configure environment variables
629
+
630
+ 3. **Design patterns to follow** section: Key architectural decisions
631
+ Format: "- Pattern Name: Explanation and when to use it"
632
+ - Routing patterns
633
+ - State management patterns
634
+ - Data fetching patterns
635
+ - Error handling patterns
636
+ - Performance optimization patterns
637
+
638
+ Example structure:
639
+ "[Framework] application template with [key technologies].
640
+
641
+ File purposes:
642
+ - package.json: NPM package configuration with [framework] and dependencies
643
+ - src/main.tsx: Application entry point with [setup details]
644
+ - src/routes/: Route definitions following [pattern]
645
+ [... list all major files ...]
646
+
647
+ How to use the scaffolded code:
648
+ 1. Routes: Create new routes by [specific instructions with example]
649
+ 2. Data Fetching: Use [specific pattern] for [use case]
650
+ 3. Authentication: Use [specific components/modules] for user management
651
+ [... numbered steps for common tasks ...]
652
+
653
+ Design patterns to follow:
654
+ - File-based Routing: Use directory structure in src/routes/ to define URL paths
655
+ - Type-safe Routes: Leverage [framework] type inference for params
656
+ - State Management: Use [library] for server state, [library] for client state
657
+ [... list key patterns with explanations ...]"
658
+
659
+ Template File Content Guidelines:
660
+ - Keep content MINIMAL and business-agnostic
661
+ - Focus on structure and patterns, not business logic
662
+ - Use placeholder/generic examples only
663
+ - Include essential boilerplate code only
664
+ - Let AI fill in specific logic later
665
+ - Add clear headers with design patterns and coding standards`
666
+ }
667
+ }];
668
+ }
669
+ };
670
+
671
+ //#endregion
672
+ //#region src/prompts/GenerateFeatureScaffoldPrompt.ts
673
+ /**
674
+ * Prompt for generating feature scaffolds
675
+ */
676
+ var GenerateFeatureScaffoldPrompt = class GenerateFeatureScaffoldPrompt {
677
+ static PROMPT_NAME = "generate-feature-scaffold";
678
+ /**
679
+ * Get the prompt definition for MCP
680
+ */
681
+ getDefinition() {
682
+ return {
683
+ name: GenerateFeatureScaffoldPrompt.PROMPT_NAME,
684
+ description: "Generate a new feature scaffold configuration",
685
+ arguments: [{
686
+ name: "request",
687
+ description: "Describe the feature scaffold you want to create",
688
+ required: false
689
+ }]
690
+ };
691
+ }
692
+ /**
693
+ * Get the prompt messages
694
+ */
695
+ getMessages(args) {
696
+ const userRequest = args?.request || "";
697
+ return [{
698
+ role: "user",
699
+ content: {
700
+ type: "text",
701
+ text: `You are helping create a new feature scaffold configuration using the scaffold-mcp MCP tools.
702
+
703
+ ${userRequest ? `User request: ${userRequest}\n` : ""}
704
+ Your task:
705
+
706
+ 1. **Gather Information**: Ask for any missing details:
707
+ - Template name (e.g., "nextjs-15", "react-vite")
708
+ - Feature name (prefixed with "scaffold-", e.g., "scaffold-nextjs-page")
709
+ - Feature type (page, component, service, etc.)
710
+ - Variables needed
711
+ - Files to include
712
+
713
+ 2. **Use MCP Tools** in order:
714
+ - \`generate-feature-scaffold\` - Creates the feature configuration
715
+ - \`generate-boilerplate-file\` - Creates each template file
716
+ - \`list-scaffolding-methods\` - Verify it appears
717
+ - \`use-scaffold-method\` - Test the feature
718
+
719
+ Important:
720
+ - Feature names: prefix with "scaffold-"
721
+ - Conditional includes: use "file.tsx?withLayout=true"
722
+ - Template syntax: use {{ variableName }}
723
+
724
+ **Description Field Guidelines (CRITICAL)**:
725
+ The description should explain what the feature scaffold generates (2-3 sentences):
726
+ - Sentence 1: What type of code it generates (component, page, service, etc.)
727
+ - Sentence 2: Key features or capabilities included
728
+ - Sentence 3: Primary use cases or when to use it
729
+
730
+ Example:
731
+ "Generate a new service class for TypeScript libraries following best practices. Creates a service class with interface, implementation, and unit tests. Perfect for creating reusable service modules with dependency injection patterns."
732
+
733
+ **Instruction Field Guidelines (CRITICAL)**:
734
+ The instruction should provide specific guidance for using the generated feature:
735
+
736
+ 1. **Pattern explanation**: Describe the architectural pattern used
737
+ 2. **File organization**: Where files should be placed
738
+ 3. **Naming conventions**: How to name things (PascalCase, camelCase, etc.)
739
+ 4. **Usage guidelines**: How to use the generated code
740
+ 5. **Testing approach**: How to test the feature
741
+
742
+ Example structure:
743
+ "[Feature type] follow a [pattern name] pattern with [key characteristics].
744
+ [Explanation of how it works and integrates with the project].
745
+ Place [files] in [directory].
746
+ For [features with X], define [Y] in [Z] for better separation of concerns.
747
+ [Feature names] should be [case style] and [suffix/prefix rules].
748
+ Write comprehensive [tests/docs] for all [public methods/exports]."
749
+
750
+ Keep it concise but informative - focus on the patterns and conventions that AI needs to understand to work with the generated code effectively.
751
+
752
+ Template File Content Guidelines:
753
+ - Keep content MINIMAL and business-agnostic
754
+ - Focus on structure and patterns, not business logic
755
+ - Use placeholder/generic examples only
756
+ - Include essential boilerplate code only
757
+ - Let AI fill in specific logic later
758
+ - Add clear headers with design patterns and coding standards`
759
+ }
760
+ }];
761
+ }
762
+ };
763
+
764
+ //#endregion
765
+ //#region src/prompts/ScaffoldApplicationPrompt.ts
766
+ /**
767
+ * Prompt for scaffolding a new application using boilerplate templates
768
+ */
769
+ var ScaffoldApplicationPrompt = class ScaffoldApplicationPrompt {
770
+ static PROMPT_NAME = "scaffold-application";
771
+ /**
772
+ * Get the prompt definition for MCP
773
+ */
774
+ getDefinition() {
775
+ return {
776
+ name: ScaffoldApplicationPrompt.PROMPT_NAME,
777
+ description: "Scaffold a new application from a boilerplate template",
778
+ arguments: [{
779
+ name: "request",
780
+ description: "Describe the application you want to create (optional)",
781
+ required: false
782
+ }]
783
+ };
784
+ }
785
+ /**
786
+ * Get the prompt messages
787
+ */
788
+ getMessages(args) {
789
+ const userRequest = args?.request || "";
790
+ return [{
791
+ role: "user",
792
+ content: {
793
+ type: "text",
794
+ text: `You are helping create a new application using the scaffold-mcp MCP tools.
795
+
796
+ ${userRequest ? `User request: ${userRequest}\n` : ""}
797
+ Your task is to scaffold a new application by following this workflow:
798
+
799
+ ## Step 1: List Available Boilerplates
800
+ Use the \`list-boilerplates\` tool to see all available project templates.
801
+
802
+ **What to look for:**
803
+ - Boilerplate name (e.g., "scaffold-nextjs-app", "scaffold-vite-app")
804
+ - Description of what the boilerplate creates
805
+ - Target folder where projects will be created (e.g., "apps", "packages")
806
+ - Required and optional variables in the variables_schema
807
+
808
+ ## Step 2: Gather Required Information
809
+ Based on the selected boilerplate's variables_schema, collect:
810
+ - **Project name**: Must be kebab-case (e.g., "my-new-app", not "MyNewApp")
811
+ - **Required variables**: All variables marked as required: true
812
+ - **Optional variables**: Variables with required: false (ask user if needed)
813
+
814
+ Common variables:
815
+ - \`appName\` or \`packageName\`: The project name (kebab-case)
816
+ - \`description\`: Brief description of what the project does
817
+ - \`author\`: Author name
818
+
819
+ ## Step 3: Execute the Boilerplate
820
+ Use the \`use-boilerplate\` tool with:
821
+ - \`boilerplateName\`: Exact name from list-boilerplates response
822
+ - \`variables\`: Object matching the variables_schema exactly
823
+
824
+ **Example:**
825
+ \`\`\`json
826
+ {
827
+ "boilerplateName": "scaffold-nextjs-app",
828
+ "variables": {
829
+ "appName": "my-dashboard",
830
+ "description": "Admin dashboard for managing users",
831
+ "author": "John Doe"
832
+ }
833
+ }
834
+ \`\`\`
835
+
836
+ ## Important Guidelines:
837
+ - **Always call \`list-boilerplates\` first** to see available options and their schemas
838
+ - **Use exact variable names** from the schema (case-sensitive)
839
+ - **Provide all required variables** - the tool will fail if any are missing
840
+ - **Use kebab-case for project names** (e.g., "user-dashboard", not "UserDashboard")
841
+ - The tool will create the project in the appropriate directory automatically
842
+ - After creation, inform the user where the project was created
843
+
844
+ ## Step 4: Review and Add Features (If Needed)
845
+ After the boilerplate is created, **consider if additional features are needed**:
846
+ 1. **READ** the generated project structure to understand what was created
847
+ 2. **REVIEW** the user's request to see if they asked for specific features (e.g., "with tool for X", "with prompt for Y")
848
+ 3. **If features are needed**:
849
+ - Use \`list-scaffolding-methods\` with the new project path
850
+ - Use \`use-scaffold-method\` to add tools, services, prompts, etc.
851
+ - **IMPLEMENT** the actual logic in the scaffolded feature files
852
+ - **REGISTER** the features in \`src/server/index.ts\`
853
+ 4. **Install dependencies**: Remind user to run \`pnpm install\`
854
+ 5. **Report** the complete setup including any features added
855
+
856
+ ## Example Workflow:
857
+ 1. Call \`list-boilerplates\` → See available templates
858
+ 2. Ask user which template to use (or infer from request)
859
+ 3. Collect required variables based on schema
860
+ 4. Call \`use-boilerplate\` with boilerplateName and variables
861
+ 5. **Review if user requested specific features (tools, prompts, etc.)**
862
+ 6. **If features needed**: Add them using \`list-scaffolding-methods\` and \`use-scaffold-method\`
863
+ 7. **READ and IMPLEMENT** the scaffolded feature files with actual logic
864
+ 8. Report success and next steps to the user`
865
+ }
866
+ }];
867
+ }
868
+ };
869
+
870
+ //#endregion
871
+ //#region src/prompts/ScaffoldFeaturePrompt.ts
872
+ /**
873
+ * Prompt for scaffolding a new feature in an existing project
874
+ */
875
+ var ScaffoldFeaturePrompt = class ScaffoldFeaturePrompt {
876
+ static PROMPT_NAME = "scaffold-feature";
877
+ /**
878
+ * Get the prompt definition for MCP
879
+ */
880
+ getDefinition() {
881
+ return {
882
+ name: ScaffoldFeaturePrompt.PROMPT_NAME,
883
+ description: "Scaffold a new feature (page, component, service, etc.) in an existing project",
884
+ arguments: [{
885
+ name: "request",
886
+ description: "Describe the feature you want to add (optional)",
887
+ required: false
888
+ }, {
889
+ name: "projectPath",
890
+ description: "Path to the project (e.g., \"apps/my-app\") - optional if can be inferred",
891
+ required: false
892
+ }]
893
+ };
894
+ }
895
+ /**
896
+ * Get the prompt messages
897
+ */
898
+ getMessages(args) {
899
+ const userRequest = args?.request || "";
900
+ const projectPath = args?.projectPath || "";
901
+ return [{
902
+ role: "user",
903
+ content: {
904
+ type: "text",
905
+ text: `You are helping add a new feature to an existing project using the scaffold-mcp MCP tools.
906
+
907
+ ${userRequest ? `User request: ${userRequest}\n` : ""}${projectPath ? `Project path: ${projectPath}\n` : ""}
908
+ Your task is to scaffold a new feature by following this workflow:
909
+
910
+ ## Step 1: Identify the Project
911
+ Determine the project path where the feature will be added:
912
+ - If projectPath is provided, use it
913
+ - Otherwise, ask the user or infer from context (e.g., "apps/my-app", "packages/my-lib")
914
+ - The path should point to a directory containing a \`project.json\` file
915
+
916
+ ## Step 2: List Available Scaffolding Methods
917
+ Use the \`list-scaffolding-methods\` tool with the projectPath.
918
+
919
+ **What to look for:**
920
+ - Feature name (e.g., "scaffold-nextjs-page", "scaffold-react-component")
921
+ - Description of what files/code it generates
922
+ - Required and optional variables in the variables_schema
923
+ - The template type (derived from project's sourceTemplate)
924
+
925
+ **Example:**
926
+ \`\`\`json
927
+ {
928
+ "projectPath": "apps/my-dashboard"
929
+ }
930
+ \`\`\`
931
+
932
+ ## Step 3: Gather Required Information
933
+ Based on the selected scaffolding method's variables_schema, collect:
934
+ - **Feature-specific variables**: Name, path, type, etc.
935
+ - **Required variables**: All variables marked as required: true
936
+ - **Optional variables**: Variables with required: false (ask user if needed)
937
+
938
+ Common variables:
939
+ - \`componentName\` / \`pageName\` / \`serviceName\`: Name in PascalCase
940
+ - \`componentPath\` / \`pagePath\`: Where to place the file (may use kebab-case)
941
+ - Boolean flags: \`withTests\`, \`withLayout\`, \`withStyles\`, etc.
942
+
943
+ ## Step 4: Execute the Scaffolding Method
944
+ Use the \`use-scaffold-method\` tool with:
945
+ - \`projectPath\`: Same path from step 1
946
+ - \`scaffold_feature_name\`: Exact name from list-scaffolding-methods response
947
+ - \`variables\`: Object matching the variables_schema exactly
948
+
949
+ **Example:**
950
+ \`\`\`json
951
+ {
952
+ "projectPath": "apps/my-dashboard",
953
+ "scaffold_feature_name": "scaffold-nextjs-page",
954
+ "variables": {
955
+ "pageName": "UserProfile",
956
+ "pagePath": "user/profile",
957
+ "withLayout": true,
958
+ "withTests": false
959
+ }
960
+ }
961
+ \`\`\`
962
+
963
+ ## Important Guidelines:
964
+ - **Always call \`list-scaffolding-methods\` first** with the projectPath
965
+ - **Use exact variable names** from the schema (case-sensitive)
966
+ - **Provide all required variables** - the tool will fail if any are missing
967
+ - **Follow naming conventions**:
968
+ - Component/Page/Service names: PascalCase (e.g., "UserProfile")
969
+ - File paths: kebab-case or as specified in schema (e.g., "user/profile")
970
+ - **Conditional files**: Files with \`?condition=true\` are only included when the variable is true
971
+ - The tool will create files in the appropriate locations automatically
972
+ - After creation, inform the user what files were created
973
+
974
+ ## Step 5: Review and Implement Generated Files
975
+ After scaffolding completes, **you MUST**:
976
+ 1. **READ** all generated files to understand their structure
977
+ 2. **IMPLEMENT** the actual business logic:
978
+ - Replace TODO comments with real code
979
+ - Replace template placeholders with actual implementation
980
+ - Add the specific functionality described in the user's request
981
+ 3. **REGISTER** the feature in appropriate files:
982
+ - Import and register tools in \`src/server/index.ts\`
983
+ - Export new modules from \`index.ts\` files
984
+ - Update any necessary configuration files
985
+ 4. **TEST** to ensure the implementation works correctly
986
+ 5. **DO NOT SKIP** this step - scaffolded files are templates that need actual code
987
+
988
+ ## Example Workflow:
989
+ 1. Identify project path (provided or ask user)
990
+ 2. Call \`list-scaffolding-methods\` → See available features for this project
991
+ 3. Ask user which feature to add (or infer from request)
992
+ 4. Collect required variables based on schema
993
+ 5. Call \`use-scaffold-method\` with projectPath, scaffold_feature_name, and variables
994
+ 6. **READ the generated files and IMPLEMENT the actual logic**
995
+ 7. **REGISTER the feature in server/index.ts and other config files**
996
+ 8. Report success and list created files with implementation details`
997
+ }
998
+ }];
999
+ }
1000
+ };
1001
+
1002
+ //#endregion
1003
+ //#region src/server/index.ts
1004
+ function createServer(options = {}) {
1005
+ const { adminEnabled = false } = options;
1006
+ const templatesPath = __agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPathSync();
1007
+ const listBoilerplatesTool = new require_stdio.ListBoilerplatesTool(templatesPath);
1008
+ const useBoilerplateTool = new require_stdio.UseBoilerplateTool(templatesPath);
1009
+ const listScaffoldingMethodsTool = new require_stdio.ListScaffoldingMethodsTool(templatesPath);
1010
+ const useScaffoldMethodTool = new require_stdio.UseScaffoldMethodTool(templatesPath);
1011
+ const writeToFileTool = new require_stdio.WriteToFileTool();
1012
+ const generateBoilerplateTool = adminEnabled ? new require_stdio.GenerateBoilerplateTool(templatesPath) : null;
1013
+ const generateBoilerplateFileTool = adminEnabled ? new require_stdio.GenerateBoilerplateFileTool(templatesPath) : null;
1014
+ const generateFeatureScaffoldTool = adminEnabled ? new require_stdio.GenerateFeatureScaffoldTool(templatesPath) : null;
1015
+ const generateBoilerplatePrompt = adminEnabled ? new GenerateBoilerplatePrompt() : null;
1016
+ const generateFeatureScaffoldPrompt = adminEnabled ? new GenerateFeatureScaffoldPrompt() : null;
1017
+ const scaffoldApplicationPrompt = new ScaffoldApplicationPrompt();
1018
+ const scaffoldFeaturePrompt = new ScaffoldFeaturePrompt();
1019
+ const server = new __modelcontextprotocol_sdk_server_index_js.Server({
1020
+ name: "scaffold-mcp",
1021
+ version: "0.4.0"
1022
+ }, {
1023
+ instructions: `Use this MCP server to create new project and adding a new feature (pages, component, services, etc...).
1024
+
1025
+ ## Workflow:
1026
+
1027
+ 1. **Creating New Project**: Use \`list-boilerplates\` → \`use-boilerplate\`
1028
+ 2. **Adding Features**: Use \`list-scaffolding-methods\` → \`use-scaffold-method\`
1029
+
1030
+ ## AI Usage Guidelines:
1031
+
1032
+ - Always call \`list-boilerplates\` first when creating new projects to see available options
1033
+ - Always call \`list-scaffolding-methods\` first when adding features to understand what's available
1034
+ - Follow the exact variable schema provided - validation will fail if required fields are missing
1035
+ - Use kebab-case for project names (e.g., "my-new-app")
1036
+ - The tools automatically handle file placement, imports, and code generation
1037
+ - Check the returned JSON schemas to understand required vs optional variables` + (adminEnabled ? `
1038
+
1039
+ ## Admin Mode (Template Generation):
1040
+
1041
+ When creating custom boilerplate templates for frameworks not yet supported:
1042
+
1043
+ 1. **Create Boilerplate Configuration**: Use \`generate-boilerplate\` to add a new boilerplate entry to a template's scaffold.yaml
1044
+ - Specify template name, boilerplate name, description, target folder, and variable schema
1045
+ - This creates the scaffold.yaml structure following the nextjs-15 pattern
1046
+ - Optional: Add detailed instruction about file purposes and design patterns
1047
+
1048
+ 2. **Create Feature Configuration**: Use \`generate-feature-scaffold\` to add a new feature entry to a template's scaffold.yaml
1049
+ - Specify template name, feature name, generator, description, and variable schema
1050
+ - This creates the scaffold.yaml structure for feature scaffolds (pages, components, etc.)
1051
+ - Optional: Add detailed instruction about file purposes and design patterns
1052
+ - Optional: Specify patterns to match existing files this feature works with
1053
+
1054
+ 3. **Create Template Files**: Use \`generate-boilerplate-file\` to create the actual template files
1055
+ - Create files referenced in the boilerplate's or feature's includes array
1056
+ - Use {{ variableName }} syntax for Liquid variable placeholders
1057
+ - Can copy from existing source files or provide content directly
1058
+ - Files automatically get .liquid extension
1059
+
1060
+ 4. **Test the Template**: Use \`list-boilerplates\`/\`list-scaffolding-methods\` and \`use-boilerplate\`/\`use-scaffold-method\` to verify your template works
1061
+
1062
+ Example workflow for boilerplate:
1063
+ \`\`\`
1064
+ 1. generate-boilerplate { templateName: "react-vite", boilerplateName: "scaffold-vite-app", ... }
1065
+ 2. generate-boilerplate-file { templateName: "react-vite", filePath: "package.json", content: "..." }
1066
+ 3. generate-boilerplate-file { templateName: "react-vite", filePath: "src/App.tsx", content: "..." }
1067
+ 4. list-boilerplates (verify it appears)
1068
+ 5. use-boilerplate { boilerplateName: "scaffold-vite-app", variables: {...} }
1069
+ \`\`\`
1070
+
1071
+ Example workflow for feature:
1072
+ \`\`\`
1073
+ 1. generate-feature-scaffold { templateName: "nextjs-15", featureName: "scaffold-nextjs-component", generator: "componentGenerator.ts", ... }
1074
+ 2. generate-boilerplate-file { templateName: "nextjs-15", filePath: "src/components/Component.tsx", content: "..." }
1075
+ 3. list-scaffolding-methods (verify it appears)
1076
+ 4. use-scaffold-method { scaffoldName: "scaffold-nextjs-component", variables: {...} }
1077
+ \`\`\`` : ""),
1078
+ capabilities: {
1079
+ tools: {},
1080
+ prompts: {}
1081
+ }
1082
+ });
1083
+ server.setRequestHandler(__modelcontextprotocol_sdk_types_js.ListToolsRequestSchema, async () => {
1084
+ const tools = [
1085
+ listBoilerplatesTool.getDefinition(),
1086
+ useBoilerplateTool.getDefinition(),
1087
+ listScaffoldingMethodsTool.getDefinition(),
1088
+ useScaffoldMethodTool.getDefinition(),
1089
+ writeToFileTool.getDefinition()
1090
+ ];
1091
+ if (adminEnabled) {
1092
+ if (generateBoilerplateTool) tools.push(generateBoilerplateTool.getDefinition());
1093
+ if (generateBoilerplateFileTool) tools.push(generateBoilerplateFileTool.getDefinition());
1094
+ if (generateFeatureScaffoldTool) tools.push(generateFeatureScaffoldTool.getDefinition());
1095
+ }
1096
+ return { tools };
1097
+ });
1098
+ server.setRequestHandler(__modelcontextprotocol_sdk_types_js.CallToolRequestSchema, async (request) => {
1099
+ const { name: name$1, arguments: args } = request.params;
1100
+ if (name$1 === require_stdio.ListBoilerplatesTool.TOOL_NAME) return await listBoilerplatesTool.execute(args || {});
1101
+ if (name$1 === require_stdio.UseBoilerplateTool.TOOL_NAME) return await useBoilerplateTool.execute(args || {});
1102
+ if (name$1 === require_stdio.ListScaffoldingMethodsTool.TOOL_NAME) return await listScaffoldingMethodsTool.execute(args || {});
1103
+ if (name$1 === require_stdio.UseScaffoldMethodTool.TOOL_NAME) return await useScaffoldMethodTool.execute(args || {});
1104
+ if (name$1 === require_stdio.WriteToFileTool.TOOL_NAME) return await writeToFileTool.execute(args || {});
1105
+ if (name$1 === require_stdio.GenerateBoilerplateTool.TOOL_NAME) {
1106
+ if (!adminEnabled || !generateBoilerplateTool) throw new Error("Admin tools are not enabled. Use --admin-enable flag to enable.");
1107
+ return await generateBoilerplateTool.execute(args);
1108
+ }
1109
+ if (name$1 === require_stdio.GenerateBoilerplateFileTool.TOOL_NAME) {
1110
+ if (!adminEnabled || !generateBoilerplateFileTool) throw new Error("Admin tools are not enabled. Use --admin-enable flag to enable.");
1111
+ return await generateBoilerplateFileTool.execute(args);
1112
+ }
1113
+ if (name$1 === require_stdio.GenerateFeatureScaffoldTool.TOOL_NAME) {
1114
+ if (!adminEnabled || !generateFeatureScaffoldTool) throw new Error("Admin tools are not enabled. Use --admin-enable flag to enable.");
1115
+ return await generateFeatureScaffoldTool.execute(args);
1116
+ }
1117
+ throw new Error(`Unknown tool: ${name$1}`);
1118
+ });
1119
+ server.setRequestHandler(__modelcontextprotocol_sdk_types_js.ListPromptsRequestSchema, async () => {
1120
+ const prompts = [];
1121
+ prompts.push(scaffoldApplicationPrompt.getDefinition());
1122
+ prompts.push(scaffoldFeaturePrompt.getDefinition());
1123
+ if (adminEnabled) {
1124
+ if (generateBoilerplatePrompt) prompts.push(generateBoilerplatePrompt.getDefinition());
1125
+ if (generateFeatureScaffoldPrompt) prompts.push(generateFeatureScaffoldPrompt.getDefinition());
1126
+ }
1127
+ return { prompts };
1128
+ });
1129
+ server.setRequestHandler(__modelcontextprotocol_sdk_types_js.GetPromptRequestSchema, async (request) => {
1130
+ const { name: name$1, arguments: args } = request.params;
1131
+ if (name$1 === ScaffoldApplicationPrompt.PROMPT_NAME) return { messages: scaffoldApplicationPrompt.getMessages(args) };
1132
+ if (name$1 === ScaffoldFeaturePrompt.PROMPT_NAME) return { messages: scaffoldFeaturePrompt.getMessages(args) };
1133
+ if (name$1 === GenerateBoilerplatePrompt.PROMPT_NAME) {
1134
+ if (!generateBoilerplatePrompt) throw new Error("Prompt not available");
1135
+ return { messages: generateBoilerplatePrompt.getMessages(args) };
1136
+ }
1137
+ if (name$1 === GenerateFeatureScaffoldPrompt.PROMPT_NAME) {
1138
+ if (!generateFeatureScaffoldPrompt) throw new Error("Prompt not available");
1139
+ return { messages: generateFeatureScaffoldPrompt.getMessages(args) };
1140
+ }
1141
+ throw new Error(`Unknown prompt: ${name$1}`);
1142
+ });
1143
+ return server;
1144
+ }
1145
+
1146
+ //#endregion
1147
+ //#region src/transports/types.ts
1148
+ /**
1149
+ * Transport mode types
1150
+ */
1151
+ let TransportMode = /* @__PURE__ */ function(TransportMode$1) {
1152
+ TransportMode$1["STDIO"] = "stdio";
1153
+ TransportMode$1["HTTP"] = "http";
1154
+ TransportMode$1["SSE"] = "sse";
1155
+ TransportMode$1["CLI"] = "cli";
1156
+ return TransportMode$1;
1157
+ }({});
1158
+
1159
+ //#endregion
1160
+ //#region src/commands/mcp-serve.ts
1161
+ /**
1162
+ * Start MCP server with given transport handler
1163
+ */
1164
+ async function startServer(handler) {
1165
+ await handler.start();
1166
+ const shutdown = async (signal) => {
1167
+ console.error(`\nReceived ${signal}, shutting down gracefully...`);
1168
+ try {
1169
+ await handler.stop();
1170
+ process.exit(0);
1171
+ } catch (error) {
1172
+ console.error("Error during shutdown:", error);
1173
+ process.exit(1);
1174
+ }
1175
+ };
1176
+ process.on("SIGINT", () => shutdown("SIGINT"));
1177
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
1178
+ }
1179
+ /**
1180
+ * MCP Serve command
1181
+ */
1182
+ const mcpServeCommand = new commander.Command("mcp-serve").description("Start MCP server with specified transport").option("-t, --type <type>", "Transport type: stdio, http, or sse", "stdio").option("-p, --port <port>", "Port to listen on (http/sse only)", (val) => parseInt(val, 10), 3e3).option("--host <host>", "Host to bind to (http/sse only)", "localhost").option("--admin-enable", "Enable admin tools (generate-boilerplate)", false).action(async (options) => {
1183
+ try {
1184
+ const transportType = options.type.toLowerCase();
1185
+ const serverOptions = { adminEnabled: options.adminEnable };
1186
+ if (transportType === "stdio") await startServer(new require_stdio.StdioTransportHandler(createServer(serverOptions)));
1187
+ else if (transportType === "http") await startServer(new require_stdio.HttpTransportHandler(() => createServer(serverOptions), {
1188
+ mode: TransportMode.HTTP,
1189
+ port: options.port || Number(process.env.MCP_PORT) || 3e3,
1190
+ host: options.host || process.env.MCP_HOST || "localhost"
1191
+ }));
1192
+ else if (transportType === "sse") await startServer(new require_stdio.SseTransportHandler(() => createServer(serverOptions), {
1193
+ mode: TransportMode.SSE,
1194
+ port: options.port || Number(process.env.MCP_PORT) || 3e3,
1195
+ host: options.host || process.env.MCP_HOST || "localhost"
1196
+ }));
1197
+ else {
1198
+ console.error(`Unknown transport type: ${transportType}. Use: stdio, http, or sse`);
1199
+ process.exit(1);
1200
+ }
1201
+ } catch (error) {
1202
+ console.error("Failed to start MCP server:", error);
1203
+ process.exit(1);
1204
+ }
1205
+ });
1206
+
1207
+ //#endregion
1208
+ //#region src/commands/scaffold.ts
1209
+ /**
1210
+ * Scaffold CLI command
1211
+ */
1212
+ const scaffoldCommand = new commander.Command("scaffold").description("Add features to existing projects");
1213
+ scaffoldCommand.command("list <projectPath>").description("List available scaffolding methods for a project").action(async (projectPath) => {
1214
+ try {
1215
+ const absolutePath = node_path.default.resolve(projectPath);
1216
+ if (!await __agiflowai_aicode_utils.ProjectConfigResolver.hasConfiguration(absolutePath)) {
1217
+ __agiflowai_aicode_utils.messages.error(`No project configuration found in ${absolutePath}`);
1218
+ __agiflowai_aicode_utils.messages.hint("For monorepo: ensure project.json exists with sourceTemplate field\nFor monolith: ensure toolkit.yaml exists at workspace root");
1219
+ process.exit(1);
1220
+ }
1221
+ const templatesDir = await __agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
1222
+ const methods = (await new require_stdio.ScaffoldingMethodsService(new require_stdio.FileSystemService(), templatesDir).listScaffoldingMethods(absolutePath)).methods;
1223
+ if (methods.length === 0) {
1224
+ __agiflowai_aicode_utils.messages.warning("No scaffolding methods available for this project.");
1225
+ return;
1226
+ }
1227
+ __agiflowai_aicode_utils.print.header(`\n${__agiflowai_aicode_utils.icons.wrench} Available Scaffolding Methods for ${projectPath}:\n`);
1228
+ for (const method of methods) {
1229
+ __agiflowai_aicode_utils.print.highlight(` ${method.name}`);
1230
+ __agiflowai_aicode_utils.print.debug(` ${method.instruction || method.description || "No description available"}`);
1231
+ if (method.variables_schema.required && method.variables_schema.required.length > 0) __agiflowai_aicode_utils.print.debug(` Required: ${method.variables_schema.required.join(", ")}`);
1232
+ __agiflowai_aicode_utils.print.newline();
1233
+ }
1234
+ } catch (error) {
1235
+ __agiflowai_aicode_utils.messages.error("Error listing scaffolding methods:", error);
1236
+ process.exit(1);
1237
+ }
1238
+ });
1239
+ scaffoldCommand.command("add <featureName>").description("Add a feature to an existing project").option("-p, --project <path>", "Project path", process.cwd()).option("-v, --vars <json>", "JSON string containing variables for the feature").option("--verbose", "Enable verbose logging").action(async (featureName, options) => {
1240
+ try {
1241
+ const projectPath = node_path.default.resolve(options.project);
1242
+ if (!await __agiflowai_aicode_utils.ProjectConfigResolver.hasConfiguration(projectPath)) {
1243
+ __agiflowai_aicode_utils.messages.error(`No project configuration found in ${projectPath}`);
1244
+ __agiflowai_aicode_utils.messages.hint("For monorepo: ensure project.json exists with sourceTemplate field\nFor monolith: ensure toolkit.yaml exists at workspace root");
1245
+ process.exit(1);
1246
+ }
1247
+ let variables = {};
1248
+ if (options.vars) try {
1249
+ variables = JSON.parse(options.vars);
1250
+ } catch (error) {
1251
+ __agiflowai_aicode_utils.messages.error("Error parsing variables JSON:", error);
1252
+ __agiflowai_aicode_utils.messages.hint("Example: --vars '{\"componentName\": \"UserProfile\", \"description\": \"User profile component\"}'");
1253
+ process.exit(1);
1254
+ }
1255
+ const templatesDir = await __agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
1256
+ const scaffoldingMethodsService = new require_stdio.ScaffoldingMethodsService(new require_stdio.FileSystemService(), templatesDir);
1257
+ const methods = (await scaffoldingMethodsService.listScaffoldingMethods(projectPath)).methods;
1258
+ const method = methods.find((m) => m.name === featureName);
1259
+ if (!method) {
1260
+ __agiflowai_aicode_utils.messages.error(`Scaffold method '${featureName}' not found.`);
1261
+ __agiflowai_aicode_utils.print.warning(`Available methods: ${methods.map((m) => m.name).join(", ")}`);
1262
+ __agiflowai_aicode_utils.print.debug(`Run 'scaffold-mcp scaffold list ${options.project}' to see all available methods`);
1263
+ process.exit(1);
1264
+ }
1265
+ const required = typeof method.variables_schema === "object" && method.variables_schema !== null && "required" in method.variables_schema ? method.variables_schema.required : [];
1266
+ const missing = required.filter((key) => !variables[key]);
1267
+ if (missing.length > 0) {
1268
+ __agiflowai_aicode_utils.messages.error(`❌ Missing required variables: ${missing.join(", ")}`);
1269
+ __agiflowai_aicode_utils.messages.hint(`💡 Use --vars with a JSON object containing: ${missing.join(", ")}`);
1270
+ const exampleVars = {};
1271
+ for (const key of required) if (key.includes("Name")) exampleVars[key] = "MyFeature";
1272
+ else if (key === "description") exampleVars[key] = "Feature description";
1273
+ else exampleVars[key] = `<${key}>`;
1274
+ __agiflowai_aicode_utils.print.debug(`Example: scaffold-mcp scaffold add ${featureName} --project ${options.project} --vars '${JSON.stringify(exampleVars)}'`);
1275
+ process.exit(1);
1276
+ }
1277
+ if (options.verbose) {
1278
+ __agiflowai_aicode_utils.print.info(`🔧 Feature: ${featureName}`);
1279
+ __agiflowai_aicode_utils.print.info(`📊 Variables: ${JSON.stringify(variables, null, 2)}`);
1280
+ __agiflowai_aicode_utils.print.info(`📁 Project Path: ${projectPath}`);
1281
+ }
1282
+ __agiflowai_aicode_utils.print.info(`🚀 Adding '${featureName}' to project...`);
1283
+ const result = await scaffoldingMethodsService.useScaffoldMethod({
1284
+ projectPath,
1285
+ scaffold_feature_name: featureName,
1286
+ variables
1287
+ });
1288
+ if (result.success) {
1289
+ __agiflowai_aicode_utils.messages.success("✅ Feature added successfully!");
1290
+ console.log(result.message);
1291
+ if (result.createdFiles && result.createdFiles.length > 0) {
1292
+ __agiflowai_aicode_utils.print.header("\n📁 Created files:");
1293
+ result.createdFiles.forEach((file) => __agiflowai_aicode_utils.print.debug(` - ${file}`));
1294
+ }
1295
+ if (result.warnings && result.warnings.length > 0) {
1296
+ __agiflowai_aicode_utils.messages.warning("\n⚠️ Warnings:");
1297
+ result.warnings.forEach((warning) => __agiflowai_aicode_utils.print.debug(` - ${warning}`));
1298
+ }
1299
+ __agiflowai_aicode_utils.print.header("\n📋 Next steps:");
1300
+ __agiflowai_aicode_utils.print.debug(" - Review the generated files");
1301
+ __agiflowai_aicode_utils.print.debug(" - Update imports if necessary");
1302
+ __agiflowai_aicode_utils.print.debug(" - Run tests to ensure everything works");
1303
+ } else {
1304
+ __agiflowai_aicode_utils.messages.error(`❌ Failed to add feature: ${result.message}`);
1305
+ process.exit(1);
1306
+ }
1307
+ } catch (error) {
1308
+ __agiflowai_aicode_utils.messages.error(`❌ Error adding feature: ${error.message}`);
1309
+ if (options.verbose) console.error("Stack trace:", error.stack);
1310
+ process.exit(1);
1311
+ }
1312
+ });
1313
+ scaffoldCommand.command("info <featureName>").description("Show detailed information about a scaffold method").option("-p, --project <path>", "Project path", process.cwd()).action(async (featureName, options) => {
1314
+ try {
1315
+ const projectPath = node_path.default.resolve(options.project);
1316
+ if (!await __agiflowai_aicode_utils.ProjectConfigResolver.hasConfiguration(projectPath)) {
1317
+ __agiflowai_aicode_utils.messages.error(`No project configuration found in ${projectPath}`);
1318
+ __agiflowai_aicode_utils.messages.hint("For monorepo: ensure project.json exists with sourceTemplate field\nFor monolith: ensure toolkit.yaml exists at workspace root");
1319
+ process.exit(1);
1320
+ }
1321
+ const templatesDir = await __agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
1322
+ const method = (await new require_stdio.ScaffoldingMethodsService(new require_stdio.FileSystemService(), templatesDir).listScaffoldingMethods(projectPath)).methods.find((m) => m.name === featureName);
1323
+ if (!method) {
1324
+ __agiflowai_aicode_utils.messages.error(`❌ Scaffold method '${featureName}' not found.`);
1325
+ process.exit(1);
1326
+ }
1327
+ __agiflowai_aicode_utils.print.header(`\n🔧 Scaffold Method: ${method.name}\n`);
1328
+ __agiflowai_aicode_utils.print.debug(`Description: ${method.description}`);
1329
+ __agiflowai_aicode_utils.print.header("\n📝 Variables Schema:");
1330
+ console.log(JSON.stringify(method.variables_schema, null, 2));
1331
+ const includes = "includes" in method ? method.includes : [];
1332
+ if (includes && includes.length > 0) {
1333
+ __agiflowai_aicode_utils.print.header("\n📁 Files to be created:");
1334
+ includes.forEach((include) => {
1335
+ const parts = include.split(">>");
1336
+ if (parts.length === 2) __agiflowai_aicode_utils.print.debug(` - ${parts[1].trim()}`);
1337
+ else __agiflowai_aicode_utils.print.debug(` - ${include}`);
1338
+ });
1339
+ }
1340
+ } catch (error) {
1341
+ __agiflowai_aicode_utils.messages.error(`❌ Error getting scaffold info: ${error.message}`);
1342
+ process.exit(1);
1343
+ }
1344
+ });
1345
+
1346
+ //#endregion
1347
+ //#region src/cli.ts
1348
+ /**
1349
+ * Main entry point
1350
+ */
1351
+ async function main() {
1352
+ const program = new commander.Command();
1353
+ program.name("scaffold-mcp").description("MCP server for scaffolding applications with boilerplate templates").version(package_default.version);
1354
+ program.addCommand(mcpServeCommand);
1355
+ program.addCommand(boilerplateCommand);
1356
+ program.addCommand(scaffoldCommand);
1357
+ program.addCommand(initCommand);
1358
+ program.addCommand(addCommand);
1359
+ await program.parseAsync(process.argv);
1360
+ }
1361
+ main();
1362
+
1363
+ //#endregion