@agiflowai/scaffold-mcp 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,28 +1,41 @@
1
1
  #!/usr/bin/env node
2
- import { ScaffoldService, TemplatesManager } from "./ScaffoldService-CnJ1nj1v.js";
3
- import { ScaffoldConfigLoader } from "./ScaffoldConfigLoader-CI0T6zdG.js";
4
- import { TemplateService } from "./TemplateService-CnxvhRVW.js";
5
- import { VariableReplacementService } from "./VariableReplacementService-Bq0GDhTo.js";
6
- import { Command } from "commander";
7
- import { exec } from "node:child_process";
8
- import * as path$1 from "node:path";
9
- import path from "node:path";
10
- import { promisify } from "node:util";
11
- import * as fs$1 from "fs-extra";
12
- import fs from "fs-extra";
13
- import chalk from "chalk";
14
- import { jsonSchemaToZod } from "@composio/json-schema-to-zod";
15
- import * as yaml$1 from "js-yaml";
16
- import yaml from "js-yaml";
17
- import { z } from "zod";
18
- import { fileURLToPath } from "node:url";
19
- import { Server } from "@modelcontextprotocol/sdk/server/index.js";
20
- import { CallToolRequestSchema, GetPromptRequestSchema, ListPromptsRequestSchema, ListToolsRequestSchema, isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
21
- import { randomUUID } from "node:crypto";
22
- import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
23
- import express from "express";
24
- import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
25
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2
+ const require_chunk = require('./chunk-nOFOJqeH.js');
3
+ const require_ScaffoldConfigLoader = require('./ScaffoldConfigLoader-yDhzLQpC.js');
4
+ const require_ScaffoldService = require('./ScaffoldService-B8-dPa7L.js');
5
+ const require_TemplateService = require('./TemplateService-DvKjDjQE.js');
6
+ const require_VariableReplacementService = require('./VariableReplacementService-DJqXiBC2.js');
7
+ let commander = require("commander");
8
+ commander = require_chunk.__toESM(commander);
9
+ let node_path = require("node:path");
10
+ node_path = require_chunk.__toESM(node_path);
11
+ let fs_extra = require("fs-extra");
12
+ fs_extra = require_chunk.__toESM(fs_extra);
13
+ let chalk = require("chalk");
14
+ chalk = require_chunk.__toESM(chalk);
15
+ let node_child_process = require("node:child_process");
16
+ node_child_process = require_chunk.__toESM(node_child_process);
17
+ let node_util = require("node:util");
18
+ node_util = require_chunk.__toESM(node_util);
19
+ let __composio_json_schema_to_zod = require("@composio/json-schema-to-zod");
20
+ __composio_json_schema_to_zod = require_chunk.__toESM(__composio_json_schema_to_zod);
21
+ let js_yaml = require("js-yaml");
22
+ js_yaml = require_chunk.__toESM(js_yaml);
23
+ let zod = require("zod");
24
+ zod = require_chunk.__toESM(zod);
25
+ let __modelcontextprotocol_sdk_server_index_js = require("@modelcontextprotocol/sdk/server/index.js");
26
+ __modelcontextprotocol_sdk_server_index_js = require_chunk.__toESM(__modelcontextprotocol_sdk_server_index_js);
27
+ let __modelcontextprotocol_sdk_types_js = require("@modelcontextprotocol/sdk/types.js");
28
+ __modelcontextprotocol_sdk_types_js = require_chunk.__toESM(__modelcontextprotocol_sdk_types_js);
29
+ let node_crypto = require("node:crypto");
30
+ node_crypto = require_chunk.__toESM(node_crypto);
31
+ let __modelcontextprotocol_sdk_server_streamableHttp_js = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
32
+ __modelcontextprotocol_sdk_server_streamableHttp_js = require_chunk.__toESM(__modelcontextprotocol_sdk_server_streamableHttp_js);
33
+ let express = require("express");
34
+ express = require_chunk.__toESM(express);
35
+ let __modelcontextprotocol_sdk_server_sse_js = require("@modelcontextprotocol/sdk/server/sse.js");
36
+ __modelcontextprotocol_sdk_server_sse_js = require_chunk.__toESM(__modelcontextprotocol_sdk_server_sse_js);
37
+ let __modelcontextprotocol_sdk_server_stdio_js = require("@modelcontextprotocol/sdk/server/stdio.js");
38
+ __modelcontextprotocol_sdk_server_stdio_js = require_chunk.__toESM(__modelcontextprotocol_sdk_server_stdio_js);
26
39
 
27
40
  //#region src/utils/console.ts
28
41
  /**
@@ -30,34 +43,34 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
30
43
  */
31
44
  const logger = {
32
45
  info: (message) => {
33
- console.log(chalk.cyan(message));
46
+ console.log(chalk.default.cyan(message));
34
47
  },
35
48
  success: (message) => {
36
- console.log(chalk.green(message));
49
+ console.log(chalk.default.green(message));
37
50
  },
38
51
  warning: (message) => {
39
- console.log(chalk.yellow(message));
52
+ console.log(chalk.default.yellow(message));
40
53
  },
41
54
  error: (message, error) => {
42
55
  if (error) {
43
56
  const errorMsg = error instanceof Error ? error.message : error;
44
- console.error(chalk.red(message), errorMsg);
45
- } else console.error(chalk.red(message));
57
+ console.error(chalk.default.red(message), errorMsg);
58
+ } else console.error(chalk.default.red(message));
46
59
  },
47
60
  debug: (message) => {
48
- console.log(chalk.gray(message));
61
+ console.log(chalk.default.gray(message));
49
62
  },
50
63
  header: (message) => {
51
- console.log(chalk.bold.cyan(message));
64
+ console.log(chalk.default.bold.cyan(message));
52
65
  },
53
66
  item: (message) => {
54
- console.log(chalk.gray(` - ${message}`));
67
+ console.log(chalk.default.gray(` - ${message}`));
55
68
  },
56
69
  indent: (message) => {
57
- console.log(chalk.gray(` ${message}`));
70
+ console.log(chalk.default.gray(` ${message}`));
58
71
  },
59
72
  highlight: (message) => {
60
- console.log(chalk.bold.green(message));
73
+ console.log(chalk.default.bold.green(message));
61
74
  },
62
75
  newline: () => {
63
76
  console.log();
@@ -82,7 +95,8 @@ const icons = {
82
95
  download: "=�",
83
96
  upload: "=�",
84
97
  gear: "�",
85
- clipboard: "=�"
98
+ clipboard: "=�",
99
+ skip: "⏭"
86
100
  };
87
101
  /**
88
102
  * Themed message helpers
@@ -135,15 +149,98 @@ const sections = {
135
149
  }
136
150
  };
137
151
 
152
+ //#endregion
153
+ //#region src/utils/git.ts
154
+ const execAsync = (0, node_util.promisify)(node_child_process.exec);
155
+ /**
156
+ * Parse GitHub URL to detect if it's a subdirectory
157
+ * Supports formats:
158
+ * - https://github.com/user/repo
159
+ * - https://github.com/user/repo/tree/branch/path/to/dir
160
+ * - https://github.com/user/repo/tree/main/path/to/dir
161
+ */
162
+ function parseGitHubUrl(url) {
163
+ const treeMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+)$/);
164
+ const blobMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/blob\/([^/]+)\/(.+)$/);
165
+ const rootMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/);
166
+ if (treeMatch || blobMatch) {
167
+ const match = treeMatch || blobMatch;
168
+ return {
169
+ owner: match[1],
170
+ repo: match[2],
171
+ repoUrl: `https://github.com/${match[1]}/${match[2]}.git`,
172
+ branch: match[3],
173
+ subdirectory: match[4],
174
+ isSubdirectory: true
175
+ };
176
+ }
177
+ if (rootMatch) return {
178
+ owner: rootMatch[1],
179
+ repo: rootMatch[2],
180
+ repoUrl: `https://github.com/${rootMatch[1]}/${rootMatch[2]}.git`,
181
+ isSubdirectory: false
182
+ };
183
+ return {
184
+ repoUrl: url,
185
+ isSubdirectory: false
186
+ };
187
+ }
188
+ /**
189
+ * Clone a subdirectory from a git repository using sparse checkout
190
+ */
191
+ async function cloneSubdirectory(repoUrl, branch, subdirectory, targetFolder) {
192
+ const tempFolder = `${targetFolder}.tmp`;
193
+ try {
194
+ await execAsync(`git init "${tempFolder}"`);
195
+ await execAsync(`git -C "${tempFolder}" remote add origin ${repoUrl}`);
196
+ await execAsync(`git -C "${tempFolder}" config core.sparseCheckout true`);
197
+ const sparseCheckoutFile = node_path.default.join(tempFolder, ".git", "info", "sparse-checkout");
198
+ await fs_extra.writeFile(sparseCheckoutFile, `${subdirectory}\n`);
199
+ await execAsync(`git -C "${tempFolder}" pull --depth=1 origin ${branch}`);
200
+ const sourceDir = node_path.default.join(tempFolder, subdirectory);
201
+ if (!await fs_extra.pathExists(sourceDir)) throw new Error(`Subdirectory '${subdirectory}' not found in repository at branch '${branch}'`);
202
+ await fs_extra.move(sourceDir, targetFolder);
203
+ await fs_extra.remove(tempFolder);
204
+ } catch (error) {
205
+ if (await fs_extra.pathExists(tempFolder)) await fs_extra.remove(tempFolder);
206
+ throw error;
207
+ }
208
+ }
209
+ /**
210
+ * Clone entire repository
211
+ */
212
+ async function cloneRepository(repoUrl, targetFolder) {
213
+ await execAsync(`git clone ${repoUrl} "${targetFolder}"`);
214
+ const gitFolder = node_path.default.join(targetFolder, ".git");
215
+ if (await fs_extra.pathExists(gitFolder)) await fs_extra.remove(gitFolder);
216
+ }
217
+ /**
218
+ * Fetch directory listing from GitHub API
219
+ */
220
+ async function fetchGitHubDirectoryContents(owner, repo, path$6, branch = "main") {
221
+ const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path$6}?ref=${branch}`;
222
+ const response = await fetch(url, { headers: {
223
+ Accept: "application/vnd.github.v3+json",
224
+ "User-Agent": "scaffold-mcp"
225
+ } });
226
+ if (!response.ok) throw new Error(`Failed to fetch directory contents: ${response.statusText}`);
227
+ const data = await response.json();
228
+ if (!Array.isArray(data)) throw new Error("Expected directory but got file");
229
+ return data.map((item) => ({
230
+ name: item.name,
231
+ type: item.type,
232
+ path: item.path
233
+ }));
234
+ }
235
+
138
236
  //#endregion
139
237
  //#region src/cli/add.ts
140
- const execAsync = promisify(exec);
141
238
  /**
142
239
  * Add command - add a template to templates folder
143
240
  */
144
- const addCommand = new 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>", "Path to templates folder", "./templates").option("--type <type>", "Template type: boilerplate or scaffold", "boilerplate").action(async (options) => {
241
+ 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>", "Path to templates folder", "./templates").option("--type <type>", "Template type: boilerplate or scaffold", "boilerplate").action(async (options) => {
145
242
  try {
146
- const templatesPath = path.resolve(options.path);
243
+ const templatesPath = node_path.default.resolve(options.path);
147
244
  const templateType = options.type.toLowerCase();
148
245
  const templateName = options.name;
149
246
  const templateUrl = options.url;
@@ -151,25 +248,27 @@ const addCommand = new Command("add").description("Add a template to templates f
151
248
  messages.error("Invalid template type. Use: boilerplate or scaffold");
152
249
  process.exit(1);
153
250
  }
154
- const targetFolder = path.join(templatesPath, `${templateType}s`, templateName);
155
- if (await fs$1.pathExists(targetFolder)) {
251
+ const targetFolder = node_path.default.join(templatesPath, `${templateType}s`, templateName);
252
+ if (await fs_extra.pathExists(targetFolder)) {
156
253
  messages.error(`Template '${templateName}' already exists at ${targetFolder}`);
157
254
  process.exit(1);
158
255
  }
159
256
  logger.info(`${icons.download} Downloading template '${templateName}' from ${templateUrl}...`);
160
- await fs$1.ensureDir(path.dirname(targetFolder));
257
+ await fs_extra.ensureDir(node_path.default.dirname(targetFolder));
258
+ const parsedUrl = parseGitHubUrl(templateUrl);
161
259
  try {
162
- await execAsync(`git clone ${templateUrl} "${targetFolder}"`);
163
- const gitFolder = path.join(targetFolder, ".git");
164
- if (await fs$1.pathExists(gitFolder)) await fs$1.remove(gitFolder);
260
+ if (parsedUrl.isSubdirectory && parsedUrl.branch && parsedUrl.subdirectory) {
261
+ logger.info(`${icons.folder} Detected subdirectory: ${parsedUrl.subdirectory} (branch: ${parsedUrl.branch})`);
262
+ await cloneSubdirectory(parsedUrl.repoUrl, parsedUrl.branch, parsedUrl.subdirectory, targetFolder);
263
+ } else await cloneRepository(parsedUrl.repoUrl, targetFolder);
165
264
  messages.success(`Template '${templateName}' added successfully!`);
166
265
  logger.header(`\n${icons.folder} Template location:`);
167
266
  logger.indent(targetFolder);
168
- const configFiles = [path.join(targetFolder, "boilerplate.yaml"), path.join(targetFolder, "scaffold.yaml")];
267
+ const configFiles = [node_path.default.join(targetFolder, "boilerplate.yaml"), node_path.default.join(targetFolder, "scaffold.yaml")];
169
268
  let hasConfig = false;
170
- for (const configFile of configFiles) if (await fs$1.pathExists(configFile)) {
269
+ for (const configFile of configFiles) if (await fs_extra.pathExists(configFile)) {
171
270
  logger.header(`\n${icons.config} Configuration file found:`);
172
- logger.indent(path.basename(configFile));
271
+ logger.indent(node_path.default.basename(configFile));
173
272
  hasConfig = true;
174
273
  break;
175
274
  }
@@ -194,29 +293,29 @@ const addCommand = new Command("add").description("Add a template to templates f
194
293
  //#endregion
195
294
  //#region src/services/FileSystemService.ts
196
295
  var FileSystemService = class {
197
- async pathExists(path$2) {
198
- return fs.pathExists(path$2);
296
+ async pathExists(path$6) {
297
+ return fs_extra.default.pathExists(path$6);
199
298
  }
200
- async readFile(path$2, encoding = "utf8") {
201
- return fs.readFile(path$2, encoding);
299
+ async readFile(path$6, encoding = "utf8") {
300
+ return fs_extra.default.readFile(path$6, encoding);
202
301
  }
203
- async readJson(path$2) {
204
- return fs.readJson(path$2);
302
+ async readJson(path$6) {
303
+ return fs_extra.default.readJson(path$6);
205
304
  }
206
- async writeFile(path$2, content, encoding = "utf8") {
207
- return fs.writeFile(path$2, content, encoding);
305
+ async writeFile(path$6, content, encoding = "utf8") {
306
+ return fs_extra.default.writeFile(path$6, content, encoding);
208
307
  }
209
- async ensureDir(path$2) {
210
- return fs.ensureDir(path$2);
308
+ async ensureDir(path$6) {
309
+ return fs_extra.default.ensureDir(path$6);
211
310
  }
212
311
  async copy(src, dest) {
213
- return fs.copy(src, dest);
312
+ return fs_extra.default.copy(src, dest);
214
313
  }
215
- async readdir(path$2) {
216
- return fs.readdir(path$2);
314
+ async readdir(path$6) {
315
+ return fs_extra.default.readdir(path$6);
217
316
  }
218
- async stat(path$2) {
219
- return fs.stat(path$2);
317
+ async stat(path$6) {
318
+ return fs_extra.default.stat(path$6);
220
319
  }
221
320
  };
222
321
 
@@ -228,11 +327,11 @@ var BoilerplateService = class {
228
327
  scaffoldService;
229
328
  constructor(templatesPath) {
230
329
  this.templatesPath = templatesPath;
231
- this.templateService = new TemplateService();
330
+ this.templateService = new require_TemplateService.TemplateService();
232
331
  const fileSystemService = new FileSystemService();
233
- const scaffoldConfigLoader = new ScaffoldConfigLoader(fileSystemService, this.templateService);
234
- const variableReplacementService = new VariableReplacementService(fileSystemService, this.templateService);
235
- this.scaffoldService = new ScaffoldService(fileSystemService, scaffoldConfigLoader, variableReplacementService, templatesPath);
332
+ const scaffoldConfigLoader = new require_ScaffoldConfigLoader.ScaffoldConfigLoader(fileSystemService, this.templateService);
333
+ const variableReplacementService = new require_VariableReplacementService.VariableReplacementService(fileSystemService, this.templateService);
334
+ this.scaffoldService = new require_ScaffoldService.ScaffoldService(fileSystemService, scaffoldConfigLoader, variableReplacementService, templatesPath);
236
335
  }
237
336
  /**
238
337
  * Scans all scaffold.yaml files and returns available boilerplates
@@ -241,10 +340,10 @@ var BoilerplateService = class {
241
340
  const boilerplates = [];
242
341
  const templateDirs = await this.discoverTemplateDirectories();
243
342
  for (const templatePath of templateDirs) {
244
- const scaffoldYamlPath = path$1.join(this.templatesPath, templatePath, "scaffold.yaml");
245
- if (fs$1.existsSync(scaffoldYamlPath)) try {
246
- const scaffoldContent = fs$1.readFileSync(scaffoldYamlPath, "utf8");
247
- const scaffoldConfig = yaml$1.load(scaffoldContent);
343
+ const scaffoldYamlPath = node_path.join(this.templatesPath, templatePath, "scaffold.yaml");
344
+ if (fs_extra.existsSync(scaffoldYamlPath)) try {
345
+ const scaffoldContent = fs_extra.readFileSync(scaffoldYamlPath, "utf8");
346
+ const scaffoldConfig = js_yaml.load(scaffoldContent);
248
347
  if (scaffoldConfig.boilerplate) for (const boilerplate of scaffoldConfig.boilerplate) {
249
348
  if (!boilerplate.targetFolder) {
250
349
  console.warn(`Skipping boilerplate '${boilerplate.name}' in ${templatePath}: targetFolder is required in scaffold.yaml`);
@@ -273,15 +372,15 @@ var BoilerplateService = class {
273
372
  async discoverTemplateDirectories() {
274
373
  const templateDirs = [];
275
374
  const findTemplates = (dir, baseDir = "") => {
276
- if (!fs$1.existsSync(dir)) return;
277
- const items = fs$1.readdirSync(dir);
375
+ if (!fs_extra.existsSync(dir)) return;
376
+ const items = fs_extra.readdirSync(dir);
278
377
  const hasPackageJson = items.includes("package.json") || items.includes("package.json.liquid");
279
378
  const hasScaffoldYaml = items.includes("scaffold.yaml");
280
379
  if (hasPackageJson && hasScaffoldYaml) templateDirs.push(baseDir);
281
380
  for (const item of items) {
282
- const itemPath = path$1.join(dir, item);
283
- if (fs$1.statSync(itemPath).isDirectory() && !item.startsWith(".") && item !== "node_modules") {
284
- const newBaseDir = baseDir ? path$1.join(baseDir, item) : item;
381
+ const itemPath = node_path.join(dir, item);
382
+ if (fs_extra.statSync(itemPath).isDirectory() && !item.startsWith(".") && item !== "node_modules") {
383
+ const newBaseDir = baseDir ? node_path.join(baseDir, item) : item;
285
384
  findTemplates(itemPath, newBaseDir);
286
385
  }
287
386
  }
@@ -366,13 +465,13 @@ var BoilerplateService = class {
366
465
  validateBoilerplateVariables(boilerplate, variables) {
367
466
  const errors = [];
368
467
  try {
369
- jsonSchemaToZod(boilerplate.variables_schema).parse(variables);
468
+ (0, __composio_json_schema_to_zod.jsonSchemaToZod)(boilerplate.variables_schema).parse(variables);
370
469
  return {
371
470
  isValid: true,
372
471
  errors: []
373
472
  };
374
473
  } catch (error) {
375
- if (error instanceof z.ZodError) {
474
+ if (error instanceof zod.z.ZodError) {
376
475
  const zodErrors = error.errors.map((err) => {
377
476
  return `${err.path.length > 0 ? err.path.join(".") : "root"}: ${err.message}`;
378
477
  });
@@ -389,11 +488,11 @@ var BoilerplateService = class {
389
488
  * If project.json exists, updates it; otherwise creates a new one
390
489
  */
391
490
  ensureProjectJsonSourceTemplate(targetFolder, projectName, sourceTemplate) {
392
- const projectJsonPath = path$1.join(targetFolder, projectName, "project.json");
491
+ const projectJsonPath = node_path.join(targetFolder, projectName, "project.json");
393
492
  try {
394
493
  let projectJson;
395
- if (fs$1.existsSync(projectJsonPath)) {
396
- const content = fs$1.readFileSync(projectJsonPath, "utf8");
494
+ if (fs_extra.existsSync(projectJsonPath)) {
495
+ const content = fs_extra.readFileSync(projectJsonPath, "utf8");
397
496
  projectJson = JSON.parse(content);
398
497
  } else projectJson = {
399
498
  name: projectName,
@@ -402,7 +501,7 @@ var BoilerplateService = class {
402
501
  projectType: "application"
403
502
  };
404
503
  projectJson.sourceTemplate = sourceTemplate;
405
- fs$1.writeFileSync(projectJsonPath, `${JSON.stringify(projectJson, null, 2)}\n`, "utf8");
504
+ fs_extra.writeFileSync(projectJsonPath, `${JSON.stringify(projectJson, null, 2)}\n`, "utf8");
406
505
  } catch (error) {
407
506
  console.warn(`Failed to update project.json with sourceTemplate: ${error}`);
408
507
  }
@@ -411,14 +510,14 @@ var BoilerplateService = class {
411
510
 
412
511
  //#endregion
413
512
  //#region src/cli/boilerplate.ts
414
- const templatesDir$1 = TemplatesManager.findTemplatesPathSync();
415
513
  /**
416
514
  * Boilerplate CLI command
417
515
  */
418
- const boilerplateCommand = new Command("boilerplate").description("Manage boilerplate templates");
516
+ const boilerplateCommand = new commander.Command("boilerplate").description("Manage boilerplate templates");
419
517
  boilerplateCommand.command("list").description("List all available boilerplate templates").action(async () => {
420
518
  try {
421
- const { boilerplates } = await new BoilerplateService(templatesDir$1).listBoilerplates();
519
+ const templatesDir = await require_ScaffoldService.TemplatesManager.findTemplatesPath();
520
+ const { boilerplates } = await new BoilerplateService(templatesDir).listBoilerplates();
422
521
  if (boilerplates.length === 0) {
423
522
  messages.warning("No boilerplate templates found.");
424
523
  return;
@@ -439,7 +538,8 @@ boilerplateCommand.command("list").description("List all available boilerplate t
439
538
  });
440
539
  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("--verbose", "Enable verbose logging").action(async (boilerplateName, options) => {
441
540
  try {
442
- const boilerplateService = new BoilerplateService(templatesDir$1);
541
+ const templatesDir = await require_ScaffoldService.TemplatesManager.findTemplatesPath();
542
+ const boilerplateService = new BoilerplateService(templatesDir);
443
543
  let variables = {};
444
544
  if (options.vars) try {
445
545
  variables = JSON.parse(options.vars);
@@ -498,7 +598,8 @@ boilerplateCommand.command("create <boilerplateName>").description("Create a new
498
598
  });
499
599
  boilerplateCommand.command("info <boilerplateName>").description("Show detailed information about a boilerplate template").action(async (boilerplateName) => {
500
600
  try {
501
- const bp = await new BoilerplateService(templatesDir$1).getBoilerplate(boilerplateName);
601
+ const templatesDir = await require_ScaffoldService.TemplatesManager.findTemplatesPath();
602
+ const bp = await new BoilerplateService(templatesDir).getBoilerplate(boilerplateName);
502
603
  if (!bp) {
503
604
  messages.error(`Boilerplate '${boilerplateName}' not found.`);
504
605
  process.exit(1);
@@ -522,36 +623,69 @@ boilerplateCommand.command("info <boilerplateName>").description("Show detailed
522
623
  * Find the workspace root by searching upwards for .git folder
523
624
  */
524
625
  async function findWorkspaceRoot(startPath = process.cwd()) {
525
- let currentPath = path.resolve(startPath);
526
- const rootPath = path.parse(currentPath).root;
626
+ let currentPath = node_path.default.resolve(startPath);
627
+ const rootPath = node_path.default.parse(currentPath).root;
527
628
  while (true) {
528
- const gitPath = path.join(currentPath, ".git");
529
- if (await fs$1.pathExists(gitPath)) return currentPath;
629
+ const gitPath = node_path.default.join(currentPath, ".git");
630
+ if (await fs_extra.pathExists(gitPath)) return currentPath;
530
631
  if (currentPath === rootPath) return process.cwd();
531
- currentPath = path.dirname(currentPath);
632
+ currentPath = node_path.default.dirname(currentPath);
633
+ }
634
+ }
635
+ const DEFAULT_TEMPLATE_REPO = {
636
+ owner: "AgiFlow",
637
+ repo: "aicode-toolkit",
638
+ branch: "main",
639
+ path: "templates"
640
+ };
641
+ /**
642
+ * Download templates from GitHub repository
643
+ */
644
+ async function downloadTemplates(templatesPath) {
645
+ try {
646
+ logger.info(`${icons.download} Fetching templates from ${DEFAULT_TEMPLATE_REPO.owner}/${DEFAULT_TEMPLATE_REPO.repo}...`);
647
+ const templateDirs = (await fetchGitHubDirectoryContents(DEFAULT_TEMPLATE_REPO.owner, DEFAULT_TEMPLATE_REPO.repo, DEFAULT_TEMPLATE_REPO.path, DEFAULT_TEMPLATE_REPO.branch)).filter((item) => item.type === "dir");
648
+ if (templateDirs.length === 0) {
649
+ messages.warning("No templates found in repository");
650
+ return;
651
+ }
652
+ logger.info(`${icons.folder} Found ${templateDirs.length} template(s)`);
653
+ for (const template of templateDirs) {
654
+ const targetFolder = node_path.default.join(templatesPath, template.name);
655
+ if (await fs_extra.pathExists(targetFolder)) {
656
+ logger.info(`${icons.skip} Skipping ${template.name} (already exists)`);
657
+ continue;
658
+ }
659
+ logger.info(`${icons.download} Downloading ${template.name}...`);
660
+ const repoUrl = `https://github.com/${DEFAULT_TEMPLATE_REPO.owner}/${DEFAULT_TEMPLATE_REPO.repo}.git`;
661
+ await cloneSubdirectory(repoUrl, DEFAULT_TEMPLATE_REPO.branch, template.path, targetFolder);
662
+ logger.success(`${icons.check} Downloaded ${template.name}`);
663
+ }
664
+ logger.success(`\n${icons.check} All templates downloaded successfully!`);
665
+ } catch (error) {
666
+ throw new Error(`Failed to download templates: ${error.message}`);
532
667
  }
533
668
  }
534
669
  /**
535
670
  * Init command - initialize templates folder
536
671
  */
537
- const initCommand = new Command("init").description("Initialize templates folder structure at workspace root").action(async () => {
672
+ const initCommand = new commander.Command("init").description("Initialize templates folder structure at workspace root").option("--no-download", "Skip downloading templates from repository").option("--path <path>", "Custom path for templates folder (relative to workspace root)").action(async (options) => {
538
673
  try {
539
674
  const workspaceRoot = await findWorkspaceRoot();
540
- const templatesPath = path.join(workspaceRoot, "templates");
675
+ const templatesPath = options.path ? node_path.default.join(workspaceRoot, options.path) : node_path.default.join(workspaceRoot, "templates");
541
676
  logger.info(`${icons.rocket} Initializing templates folder at: ${templatesPath}`);
542
- await fs$1.ensureDir(templatesPath);
543
- await fs$1.ensureDir(path.join(templatesPath, "boilerplates"));
544
- await fs$1.ensureDir(path.join(templatesPath, "scaffolds"));
545
- await fs$1.writeFile(path.join(templatesPath, "README.md"), `# Templates
677
+ await fs_extra.ensureDir(templatesPath);
678
+ await fs_extra.writeFile(node_path.default.join(templatesPath, "README.md"), `# Templates
546
679
 
547
680
  This folder contains boilerplate templates and scaffolding methods for your projects.
548
681
 
549
- ## Structure
682
+ ## Templates
550
683
 
551
- - \`boilerplates/\` - Full project boilerplate templates
552
- - \`scaffolds/\` - Feature scaffolding methods for existing projects
684
+ Templates are organized by framework/technology and include configuration files (\`scaffold.yaml\`) that define:
685
+ - Boilerplates: Full project starter templates
686
+ - Features: Code scaffolding methods for adding new features to existing projects
553
687
 
554
- ## Adding Templates
688
+ ## Adding More Templates
555
689
 
556
690
  Use the \`add\` command to add templates from remote repositories:
557
691
 
@@ -559,31 +693,38 @@ Use the \`add\` command to add templates from remote repositories:
559
693
  scaffold-mcp add --name my-template --url https://github.com/user/template
560
694
  \`\`\`
561
695
 
562
- ## Creating Custom Templates
696
+ Or add templates from subdirectories:
563
697
 
564
- ### Boilerplate Template Structure
698
+ \`\`\`bash
699
+ scaffold-mcp add --name nextjs-template --url https://github.com/user/repo/tree/main/templates/nextjs
700
+ \`\`\`
565
701
 
566
- Each boilerplate should have:
567
- - \`boilerplate.yaml\` - Configuration file
568
- - Template files with variable placeholders using Liquid syntax (\`{{ variableName }}\`)
702
+ ## Creating Custom Templates
569
703
 
570
- ### Scaffold Method Structure
704
+ Each template should have a \`scaffold.yaml\` configuration file defining:
705
+ - \`boilerplate\`: Array of boilerplate configurations
706
+ - \`features\`: Array of feature scaffold configurations
571
707
 
572
- Each scaffold method should have:
573
- - \`scaffold.yaml\` - Configuration file
574
- - Template files organized by project type
708
+ Template files use Liquid syntax for variable placeholders: \`{{ variableName }}\`
575
709
 
576
- See documentation for more details on template creation.
710
+ See existing templates for examples and documentation for more details.
577
711
  `);
578
- logger.success(`${icons.check} Templates folder initialized successfully!`);
579
- logger.header(`\n${icons.folder} Created structure:`);
580
- logger.indent(`${templatesPath}/`);
581
- logger.indent(`├── boilerplates/`);
582
- logger.indent(`├── scaffolds/`);
583
- logger.indent(`└── README.md`);
584
- sections.nextSteps([`Add templates using: scaffold-mcp add --name <name> --url <url>`, `Or manually create templates in ${templatesPath}/`]);
712
+ logger.success(`${icons.check} Templates folder created!`);
713
+ if (options.download !== false) await downloadTemplates(templatesPath);
714
+ else logger.info(`${icons.skip} Skipping template download (use --download to enable)`);
715
+ logger.header(`\n${icons.folder} Templates location:`);
716
+ logger.indent(templatesPath);
717
+ const nextSteps = [];
718
+ if (options.download === false) {
719
+ nextSteps.push(`Download templates: scaffold-mcp init --download`);
720
+ nextSteps.push(`Add templates manually: scaffold-mcp add --name <name> --url <url>`);
721
+ } else {
722
+ nextSteps.push(`List available boilerplates: scaffold-mcp boilerplate list`);
723
+ nextSteps.push(`Add more templates: scaffold-mcp add --name <name> --url <url>`);
724
+ }
725
+ sections.nextSteps(nextSteps);
585
726
  } catch (error) {
586
- logger.error(`${icons.cross} Error initializing templates folder:`, error);
727
+ messages.error(`Error initializing templates folder: ${error.message}`);
587
728
  process.exit(1);
588
729
  }
589
730
  });
@@ -1025,7 +1166,7 @@ var BoilerplateGeneratorService = class {
1025
1166
  * Custom YAML dumper that forces literal block style (|) for description and instruction fields
1026
1167
  */
1027
1168
  dumpYamlWithLiteralBlocks(config) {
1028
- const LiteralBlockType = new yaml$1.Type("tag:yaml.org,2002:str", {
1169
+ const LiteralBlockType = new js_yaml.Type("tag:yaml.org,2002:str", {
1029
1170
  kind: "scalar",
1030
1171
  construct: (data) => data,
1031
1172
  represent: (data) => {
@@ -1033,9 +1174,9 @@ var BoilerplateGeneratorService = class {
1033
1174
  },
1034
1175
  defaultStyle: "|"
1035
1176
  });
1036
- const LITERAL_SCHEMA = yaml$1.DEFAULT_SCHEMA.extend([LiteralBlockType]);
1177
+ const LITERAL_SCHEMA = js_yaml.DEFAULT_SCHEMA.extend([LiteralBlockType]);
1037
1178
  const processedConfig = this.processConfigForLiteralBlocks(config);
1038
- return yaml$1.dump(processedConfig, {
1179
+ return js_yaml.dump(processedConfig, {
1039
1180
  schema: LITERAL_SCHEMA,
1040
1181
  indent: 2,
1041
1182
  lineWidth: -1,
@@ -1078,13 +1219,13 @@ var BoilerplateGeneratorService = class {
1078
1219
  */
1079
1220
  async generateBoilerplate(options) {
1080
1221
  const { templateName, boilerplateName, description, instruction, targetFolder, variables, includes = [] } = options;
1081
- const templatePath = path$1.join(this.templatesPath, templateName);
1082
- await fs$1.ensureDir(templatePath);
1083
- const scaffoldYamlPath = path$1.join(templatePath, "scaffold.yaml");
1222
+ const templatePath = node_path.join(this.templatesPath, templateName);
1223
+ await fs_extra.ensureDir(templatePath);
1224
+ const scaffoldYamlPath = node_path.join(templatePath, "scaffold.yaml");
1084
1225
  let scaffoldConfig = {};
1085
- if (await fs$1.pathExists(scaffoldYamlPath)) {
1086
- const yamlContent$1 = await fs$1.readFile(scaffoldYamlPath, "utf-8");
1087
- scaffoldConfig = yaml$1.load(yamlContent$1);
1226
+ if (await fs_extra.pathExists(scaffoldYamlPath)) {
1227
+ const yamlContent$1 = await fs_extra.readFile(scaffoldYamlPath, "utf-8");
1228
+ scaffoldConfig = js_yaml.load(yamlContent$1);
1088
1229
  }
1089
1230
  if (!scaffoldConfig.boilerplate) scaffoldConfig.boilerplate = [];
1090
1231
  if (scaffoldConfig.boilerplate.findIndex((b) => b.name === boilerplateName) !== -1) return {
@@ -1115,7 +1256,7 @@ var BoilerplateGeneratorService = class {
1115
1256
  if (instruction) boilerplateDefinition.instruction = instruction;
1116
1257
  scaffoldConfig.boilerplate.push(boilerplateDefinition);
1117
1258
  const yamlContent = this.dumpYamlWithLiteralBlocks(scaffoldConfig);
1118
- await fs$1.writeFile(scaffoldYamlPath, yamlContent, "utf-8");
1259
+ await fs_extra.writeFile(scaffoldYamlPath, yamlContent, "utf-8");
1119
1260
  return {
1120
1261
  success: true,
1121
1262
  message: `Boilerplate '${boilerplateName}' added to ${scaffoldYamlPath}`,
@@ -1127,43 +1268,43 @@ var BoilerplateGeneratorService = class {
1127
1268
  * List all templates (directories in templates folder)
1128
1269
  */
1129
1270
  async listTemplates() {
1130
- return (await fs$1.readdir(this.templatesPath, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
1271
+ return (await fs_extra.readdir(this.templatesPath, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
1131
1272
  }
1132
1273
  /**
1133
1274
  * Check if a template exists
1134
1275
  */
1135
1276
  async templateExists(templateName) {
1136
- const templatePath = path$1.join(this.templatesPath, templateName);
1137
- return fs$1.pathExists(templatePath);
1277
+ const templatePath = node_path.join(this.templatesPath, templateName);
1278
+ return fs_extra.pathExists(templatePath);
1138
1279
  }
1139
1280
  /**
1140
1281
  * Create or update a template file for a boilerplate
1141
1282
  */
1142
1283
  async createTemplateFile(options) {
1143
1284
  const { templateName, filePath, content, sourceFile, header } = options;
1144
- const templatePath = path$1.join(this.templatesPath, templateName);
1145
- if (!await fs$1.pathExists(templatePath)) return {
1285
+ const templatePath = node_path.join(this.templatesPath, templateName);
1286
+ if (!await fs_extra.pathExists(templatePath)) return {
1146
1287
  success: false,
1147
1288
  message: `Template directory '${templateName}' does not exist at ${templatePath}`
1148
1289
  };
1149
1290
  let fileContent = content || "";
1150
1291
  if (sourceFile) {
1151
- if (!await fs$1.pathExists(sourceFile)) return {
1292
+ if (!await fs_extra.pathExists(sourceFile)) return {
1152
1293
  success: false,
1153
1294
  message: `Source file '${sourceFile}' does not exist`
1154
1295
  };
1155
- fileContent = await fs$1.readFile(sourceFile, "utf-8");
1296
+ fileContent = await fs_extra.readFile(sourceFile, "utf-8");
1156
1297
  }
1157
1298
  if (!fileContent && !sourceFile) return {
1158
1299
  success: false,
1159
1300
  message: "Either content or sourceFile must be provided"
1160
1301
  };
1161
1302
  const templateFilePath = filePath.endsWith(".liquid") ? filePath : `${filePath}.liquid`;
1162
- const fullPath = path$1.join(templatePath, templateFilePath);
1163
- await fs$1.ensureDir(path$1.dirname(fullPath));
1303
+ const fullPath = node_path.join(templatePath, templateFilePath);
1304
+ await fs_extra.ensureDir(node_path.dirname(fullPath));
1164
1305
  let finalContent = fileContent;
1165
1306
  if (header) finalContent = `${header}\n\n${fileContent}`;
1166
- await fs$1.writeFile(fullPath, finalContent, "utf-8");
1307
+ await fs_extra.writeFile(fullPath, finalContent, "utf-8");
1167
1308
  return {
1168
1309
  success: true,
1169
1310
  message: "Template file created successfully",
@@ -1525,7 +1666,7 @@ var ScaffoldGeneratorService = class {
1525
1666
  * Custom YAML dumper that forces literal block style (|) for description and instruction fields
1526
1667
  */
1527
1668
  dumpYamlWithLiteralBlocks(config) {
1528
- const LiteralBlockType = new yaml$1.Type("tag:yaml.org,2002:str", {
1669
+ const LiteralBlockType = new js_yaml.Type("tag:yaml.org,2002:str", {
1529
1670
  kind: "scalar",
1530
1671
  construct: (data) => data,
1531
1672
  represent: (data) => {
@@ -1533,9 +1674,9 @@ var ScaffoldGeneratorService = class {
1533
1674
  },
1534
1675
  defaultStyle: "|"
1535
1676
  });
1536
- const LITERAL_SCHEMA = yaml$1.DEFAULT_SCHEMA.extend([LiteralBlockType]);
1677
+ const LITERAL_SCHEMA = js_yaml.DEFAULT_SCHEMA.extend([LiteralBlockType]);
1537
1678
  const processedConfig = this.processConfigForLiteralBlocks(config);
1538
- return yaml$1.dump(processedConfig, {
1679
+ return js_yaml.dump(processedConfig, {
1539
1680
  schema: LITERAL_SCHEMA,
1540
1681
  indent: 2,
1541
1682
  lineWidth: -1,
@@ -1578,13 +1719,13 @@ var ScaffoldGeneratorService = class {
1578
1719
  */
1579
1720
  async generateFeatureScaffold(options) {
1580
1721
  const { templateName, featureName, description, instruction, variables, includes = [], patterns = [] } = options;
1581
- const templatePath = path$1.join(this.templatesPath, templateName);
1582
- await fs$1.ensureDir(templatePath);
1583
- const scaffoldYamlPath = path$1.join(templatePath, "scaffold.yaml");
1722
+ const templatePath = node_path.join(this.templatesPath, templateName);
1723
+ await fs_extra.ensureDir(templatePath);
1724
+ const scaffoldYamlPath = node_path.join(templatePath, "scaffold.yaml");
1584
1725
  let scaffoldConfig = {};
1585
- if (await fs$1.pathExists(scaffoldYamlPath)) {
1586
- const yamlContent$1 = await fs$1.readFile(scaffoldYamlPath, "utf-8");
1587
- scaffoldConfig = yaml$1.load(yamlContent$1);
1726
+ if (await fs_extra.pathExists(scaffoldYamlPath)) {
1727
+ const yamlContent$1 = await fs_extra.readFile(scaffoldYamlPath, "utf-8");
1728
+ scaffoldConfig = js_yaml.load(yamlContent$1);
1588
1729
  }
1589
1730
  if (!scaffoldConfig.features) scaffoldConfig.features = [];
1590
1731
  if (scaffoldConfig.features.findIndex((f) => f.name === featureName) !== -1) return {
@@ -1615,7 +1756,7 @@ var ScaffoldGeneratorService = class {
1615
1756
  if (patterns && patterns.length > 0) featureDefinition.patterns = patterns;
1616
1757
  scaffoldConfig.features.push(featureDefinition);
1617
1758
  const yamlContent = this.dumpYamlWithLiteralBlocks(scaffoldConfig);
1618
- await fs$1.writeFile(scaffoldYamlPath, yamlContent, "utf-8");
1759
+ await fs_extra.writeFile(scaffoldYamlPath, yamlContent, "utf-8");
1619
1760
  return {
1620
1761
  success: true,
1621
1762
  message: `Feature '${featureName}' added to ${scaffoldYamlPath}`,
@@ -1627,14 +1768,14 @@ var ScaffoldGeneratorService = class {
1627
1768
  * List all templates (directories in templates folder)
1628
1769
  */
1629
1770
  async listTemplates() {
1630
- return (await fs$1.readdir(this.templatesPath, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
1771
+ return (await fs_extra.readdir(this.templatesPath, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
1631
1772
  }
1632
1773
  /**
1633
1774
  * Check if a template exists
1634
1775
  */
1635
1776
  async templateExists(templateName) {
1636
- const templatePath = path$1.join(this.templatesPath, templateName);
1637
- return fs$1.pathExists(templatePath);
1777
+ const templatePath = node_path.join(this.templatesPath, templateName);
1778
+ return fs_extra.pathExists(templatePath);
1638
1779
  }
1639
1780
  };
1640
1781
 
@@ -1759,9 +1900,7 @@ Best practices:
1759
1900
  - Use conditional includes with ?variableName=value for optional files
1760
1901
  - Use path mapping with -> when source and target paths differ
1761
1902
  - Use {{ variableName }} in target paths for dynamic file placement
1762
- - Avoid wildcards unless you have a good reason
1763
-
1764
- See templates/nextjs-15/scaffold.yaml features section for examples.`,
1903
+ - Avoid wildcards unless you have a good reason`,
1765
1904
  items: { type: "string" }
1766
1905
  },
1767
1906
  patterns: {
@@ -1891,22 +2030,22 @@ var ScaffoldingMethodsService = class {
1891
2030
  constructor(fileSystem, templatesRootPath) {
1892
2031
  this.fileSystem = fileSystem;
1893
2032
  this.templatesRootPath = templatesRootPath;
1894
- this.templateService = new TemplateService();
2033
+ this.templateService = new require_TemplateService.TemplateService();
1895
2034
  }
1896
2035
  async listScaffoldingMethods(projectPath) {
1897
- const absoluteProjectPath = path.resolve(projectPath);
1898
- const projectJsonPath = path.join(absoluteProjectPath, "project.json");
2036
+ const absoluteProjectPath = node_path.default.resolve(projectPath);
2037
+ const projectJsonPath = node_path.default.join(absoluteProjectPath, "project.json");
1899
2038
  if (!await this.fileSystem.pathExists(projectJsonPath)) throw new Error(`project.json not found at ${projectJsonPath}`);
1900
2039
  const projectConfig = await this.fileSystem.readJson(projectJsonPath);
1901
2040
  if (!projectConfig.sourceTemplate) throw new Error(`sourceTemplate not specified in project.json at ${projectJsonPath}`);
1902
2041
  const sourceTemplate = projectConfig.sourceTemplate;
1903
2042
  const templatePath = await this.findTemplatePath(sourceTemplate);
1904
2043
  if (!templatePath) throw new Error(`Template not found for sourceTemplate: ${sourceTemplate}`);
1905
- const fullTemplatePath = path.join(this.templatesRootPath, templatePath);
1906
- const scaffoldYamlPath = path.join(fullTemplatePath, "scaffold.yaml");
2044
+ const fullTemplatePath = node_path.default.join(this.templatesRootPath, templatePath);
2045
+ const scaffoldYamlPath = node_path.default.join(fullTemplatePath, "scaffold.yaml");
1907
2046
  if (!await this.fileSystem.pathExists(scaffoldYamlPath)) throw new Error(`scaffold.yaml not found at ${scaffoldYamlPath}`);
1908
2047
  const scaffoldContent = await this.fileSystem.readFile(scaffoldYamlPath, "utf8");
1909
- const architectConfig = yaml.load(scaffoldContent);
2048
+ const architectConfig = js_yaml.default.load(scaffoldContent);
1910
2049
  const methods = [];
1911
2050
  if (architectConfig.features && Array.isArray(architectConfig.features)) architectConfig.features.forEach((feature) => {
1912
2051
  if (feature.name) methods.push({
@@ -1953,11 +2092,11 @@ var ScaffoldingMethodsService = class {
1953
2092
  const templateDirs = await this.discoverTemplateDirs();
1954
2093
  if (templateDirs.includes(sourceTemplate)) return sourceTemplate;
1955
2094
  for (const templateDir of templateDirs) {
1956
- const templatePath = path.join(this.templatesRootPath, templateDir);
1957
- const scaffoldYamlPath = path.join(templatePath, "scaffold.yaml");
2095
+ const templatePath = node_path.default.join(this.templatesRootPath, templateDir);
2096
+ const scaffoldYamlPath = node_path.default.join(templatePath, "scaffold.yaml");
1958
2097
  if (await this.fileSystem.pathExists(scaffoldYamlPath)) try {
1959
2098
  const scaffoldContent = await this.fileSystem.readFile(scaffoldYamlPath, "utf8");
1960
- const architectConfig = yaml.load(scaffoldContent);
2099
+ const architectConfig = js_yaml.default.load(scaffoldContent);
1961
2100
  if (architectConfig.boilerplate && Array.isArray(architectConfig.boilerplate)) {
1962
2101
  for (const boilerplate of architectConfig.boilerplate) if (boilerplate.name?.includes(sourceTemplate)) return templateDir;
1963
2102
  }
@@ -1976,9 +2115,9 @@ var ScaffoldingMethodsService = class {
1976
2115
  try {
1977
2116
  const items = await this.fileSystem.readdir(this.templatesRootPath);
1978
2117
  for (const item of items) {
1979
- const itemPath = path.join(this.templatesRootPath, item);
2118
+ const itemPath = node_path.default.join(this.templatesRootPath, item);
1980
2119
  if (!(await this.fileSystem.stat(itemPath)).isDirectory()) continue;
1981
- const scaffoldYamlPath = path.join(itemPath, "scaffold.yaml");
2120
+ const scaffoldYamlPath = node_path.default.join(itemPath, "scaffold.yaml");
1982
2121
  if (await this.fileSystem.pathExists(scaffoldYamlPath)) {
1983
2122
  templateDirs.push(item);
1984
2123
  continue;
@@ -1986,11 +2125,11 @@ var ScaffoldingMethodsService = class {
1986
2125
  try {
1987
2126
  const subItems = await this.fileSystem.readdir(itemPath);
1988
2127
  for (const subItem of subItems) {
1989
- const subItemPath = path.join(itemPath, subItem);
2128
+ const subItemPath = node_path.default.join(itemPath, subItem);
1990
2129
  if (!(await this.fileSystem.stat(subItemPath)).isDirectory()) continue;
1991
- const subScaffoldYamlPath = path.join(subItemPath, "scaffold.yaml");
2130
+ const subScaffoldYamlPath = node_path.default.join(subItemPath, "scaffold.yaml");
1992
2131
  if (await this.fileSystem.pathExists(subScaffoldYamlPath)) {
1993
- const relativePath = path.join(item, subItem);
2132
+ const relativePath = node_path.default.join(item, subItem);
1994
2133
  templateDirs.push(relativePath);
1995
2134
  }
1996
2135
  }
@@ -2011,16 +2150,16 @@ var ScaffoldingMethodsService = class {
2011
2150
  const availableMethods = scaffoldingMethods.methods.map((m) => m.name).join(", ");
2012
2151
  throw new Error(`Scaffold method '${scaffold_feature_name}' not found. Available methods: ${availableMethods}`);
2013
2152
  }
2014
- const ScaffoldService$1 = (await import("./ScaffoldService-CDhYAUrp.js")).ScaffoldService;
2015
- const ScaffoldConfigLoader$1 = (await import("./ScaffoldConfigLoader-DhthV6xq.js")).ScaffoldConfigLoader;
2016
- const VariableReplacementService$1 = (await import("./VariableReplacementService-CrxFJrqU.js")).VariableReplacementService;
2017
- const TemplateService$1 = (await import("./TemplateService-PmTU3_On.js")).TemplateService;
2153
+ const ScaffoldService$1 = (await Promise.resolve().then(() => require("./ScaffoldService-BXKXXg4M.js"))).ScaffoldService;
2154
+ const ScaffoldConfigLoader$1 = (await Promise.resolve().then(() => require("./ScaffoldConfigLoader-CnVkzUxL.js"))).ScaffoldConfigLoader;
2155
+ const VariableReplacementService$1 = (await Promise.resolve().then(() => require("./VariableReplacementService-_GgLG4Im.js"))).VariableReplacementService;
2156
+ const TemplateService$1 = (await Promise.resolve().then(() => require("./TemplateService-B0ns4TR_.js"))).TemplateService;
2018
2157
  const templateService = new TemplateService$1();
2019
2158
  const scaffoldConfigLoader = new ScaffoldConfigLoader$1(this.fileSystem, templateService);
2020
2159
  const variableReplacer = new VariableReplacementService$1(this.fileSystem, templateService);
2021
2160
  const scaffoldService = new ScaffoldService$1(this.fileSystem, scaffoldConfigLoader, variableReplacer, this.templatesRootPath);
2022
- const absoluteProjectPath = path.resolve(projectPath);
2023
- const projectName = path.basename(absoluteProjectPath);
2161
+ const absoluteProjectPath = node_path.default.resolve(projectPath);
2162
+ const projectName = node_path.default.basename(absoluteProjectPath);
2024
2163
  const result = await scaffoldService.useFeature({
2025
2164
  projectPath: absoluteProjectPath,
2026
2165
  templateFolder: scaffoldingMethods.templatePath,
@@ -2322,8 +2461,8 @@ Parameters:
2322
2461
  const { file_path, content } = args;
2323
2462
  if (!file_path) throw new Error("Missing required parameter: file_path");
2324
2463
  if (content === void 0 || content === null) throw new Error("Missing required parameter: content");
2325
- const resolvedPath = path.isAbsolute(file_path) ? file_path : path.resolve(process.cwd(), file_path);
2326
- const dirPath = path.dirname(resolvedPath);
2464
+ const resolvedPath = node_path.default.isAbsolute(file_path) ? file_path : node_path.default.resolve(process.cwd(), file_path);
2465
+ const dirPath = node_path.default.dirname(resolvedPath);
2327
2466
  await this.fileSystemService.ensureDir(dirPath);
2328
2467
  await this.fileSystemService.writeFile(resolvedPath, content);
2329
2468
  return { content: [{
@@ -2346,7 +2485,7 @@ Parameters:
2346
2485
  //#region src/server/index.ts
2347
2486
  function createServer(options = {}) {
2348
2487
  const { adminEnabled = false } = options;
2349
- const templatesPath = TemplatesManager.findTemplatesPathSync();
2488
+ const templatesPath = require_ScaffoldService.TemplatesManager.findTemplatesPathSync();
2350
2489
  const listBoilerplatesTool = new ListBoilerplatesTool(templatesPath);
2351
2490
  const useBoilerplateTool = new UseBoilerplateTool(templatesPath);
2352
2491
  const listScaffoldingMethodsTool = new ListScaffoldingMethodsTool(templatesPath);
@@ -2359,7 +2498,7 @@ function createServer(options = {}) {
2359
2498
  const generateFeatureScaffoldPrompt = adminEnabled ? new GenerateFeatureScaffoldPrompt() : null;
2360
2499
  const scaffoldApplicationPrompt = new ScaffoldApplicationPrompt();
2361
2500
  const scaffoldFeaturePrompt = new ScaffoldFeaturePrompt();
2362
- const server = new Server({
2501
+ const server = new __modelcontextprotocol_sdk_server_index_js.Server({
2363
2502
  name: "scaffold-mcp",
2364
2503
  version: "1.0.0"
2365
2504
  }, {
@@ -2423,7 +2562,7 @@ Example workflow for feature:
2423
2562
  prompts: {}
2424
2563
  }
2425
2564
  });
2426
- server.setRequestHandler(ListToolsRequestSchema, async () => {
2565
+ server.setRequestHandler(__modelcontextprotocol_sdk_types_js.ListToolsRequestSchema, async () => {
2427
2566
  const listBoilerplateTool = listBoilerplatesTool.getDefinition();
2428
2567
  const useBoilerplateToolDef = useBoilerplateTool.getDefinition();
2429
2568
  const listScaffoldingMethodsToolDef = listScaffoldingMethodsTool.getDefinition();
@@ -2443,7 +2582,7 @@ Example workflow for feature:
2443
2582
  }
2444
2583
  return { tools };
2445
2584
  });
2446
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
2585
+ server.setRequestHandler(__modelcontextprotocol_sdk_types_js.CallToolRequestSchema, async (request) => {
2447
2586
  const { name, arguments: args } = request.params;
2448
2587
  if (name === ListBoilerplatesTool.TOOL_NAME) return await listBoilerplatesTool.execute(args || {});
2449
2588
  if (name === UseBoilerplateTool.TOOL_NAME) return await useBoilerplateTool.execute(args || {});
@@ -2464,7 +2603,7 @@ Example workflow for feature:
2464
2603
  }
2465
2604
  throw new Error(`Unknown tool: ${name}`);
2466
2605
  });
2467
- server.setRequestHandler(ListPromptsRequestSchema, async () => {
2606
+ server.setRequestHandler(__modelcontextprotocol_sdk_types_js.ListPromptsRequestSchema, async () => {
2468
2607
  const prompts = [];
2469
2608
  prompts.push(scaffoldApplicationPrompt.getDefinition());
2470
2609
  prompts.push(scaffoldFeaturePrompt.getDefinition());
@@ -2474,7 +2613,7 @@ Example workflow for feature:
2474
2613
  }
2475
2614
  return { prompts };
2476
2615
  });
2477
- server.setRequestHandler(GetPromptRequestSchema, async (request) => {
2616
+ server.setRequestHandler(__modelcontextprotocol_sdk_types_js.GetPromptRequestSchema, async (request) => {
2478
2617
  const { name, arguments: args } = request.params;
2479
2618
  if (name === ScaffoldApplicationPrompt.PROMPT_NAME) return { messages: scaffoldApplicationPrompt.getMessages(args) };
2480
2619
  if (name === ScaffoldFeaturePrompt.PROMPT_NAME) return { messages: scaffoldFeaturePrompt.getMessages(args) };
@@ -2494,24 +2633,30 @@ Example workflow for feature:
2494
2633
  //#endregion
2495
2634
  //#region src/transports/http.ts
2496
2635
  /**
2497
- * Session manager for HTTP transports
2636
+ * HTTP session manager
2498
2637
  */
2499
- var HttpSessionManager = class {
2500
- transports = /* @__PURE__ */ new Map();
2638
+ var HttpFullSessionManager = class {
2639
+ sessions = /* @__PURE__ */ new Map();
2501
2640
  getSession(sessionId) {
2502
- return this.transports.get(sessionId);
2641
+ return this.sessions.get(sessionId);
2503
2642
  }
2504
- setSession(sessionId, transport) {
2505
- this.transports.set(sessionId, transport);
2643
+ setSession(sessionId, transport, server) {
2644
+ this.sessions.set(sessionId, {
2645
+ transport,
2646
+ server
2647
+ });
2506
2648
  }
2507
2649
  deleteSession(sessionId) {
2508
- this.transports.delete(sessionId);
2650
+ const session = this.sessions.get(sessionId);
2651
+ if (session) session.server.close();
2652
+ this.sessions.delete(sessionId);
2509
2653
  }
2510
2654
  hasSession(sessionId) {
2511
- return this.transports.has(sessionId);
2655
+ return this.sessions.has(sessionId);
2512
2656
  }
2513
2657
  clear() {
2514
- this.transports.clear();
2658
+ for (const session of this.sessions.values()) session.server.close();
2659
+ this.sessions.clear();
2515
2660
  }
2516
2661
  };
2517
2662
  /**
@@ -2519,15 +2664,15 @@ var HttpSessionManager = class {
2519
2664
  * Provides stateful session management with resumability support
2520
2665
  */
2521
2666
  var HttpTransportHandler = class {
2522
- mcpServer;
2667
+ serverFactory;
2523
2668
  app;
2524
2669
  server = null;
2525
2670
  sessionManager;
2526
2671
  config;
2527
- constructor(mcpServer, config) {
2528
- this.mcpServer = mcpServer;
2529
- this.app = express();
2530
- this.sessionManager = new HttpSessionManager();
2672
+ constructor(serverFactory, config) {
2673
+ this.serverFactory = typeof serverFactory === "function" ? serverFactory : () => serverFactory;
2674
+ this.app = (0, express.default)();
2675
+ this.sessionManager = new HttpFullSessionManager();
2531
2676
  this.config = {
2532
2677
  mode: config.mode,
2533
2678
  port: config.port ?? 3e3,
@@ -2537,7 +2682,7 @@ var HttpTransportHandler = class {
2537
2682
  this.setupRoutes();
2538
2683
  }
2539
2684
  setupMiddleware() {
2540
- this.app.use(express.json());
2685
+ this.app.use(express.default.json());
2541
2686
  }
2542
2687
  setupRoutes() {
2543
2688
  this.app.post("/mcp", async (req, res) => {
@@ -2559,18 +2704,20 @@ var HttpTransportHandler = class {
2559
2704
  async handlePostRequest(req, res) {
2560
2705
  const sessionId = req.headers["mcp-session-id"];
2561
2706
  let transport;
2562
- if (sessionId && this.sessionManager.hasSession(sessionId)) transport = this.sessionManager.getSession(sessionId);
2563
- else if (!sessionId && isInitializeRequest(req.body)) {
2564
- transport = new StreamableHTTPServerTransport({
2565
- sessionIdGenerator: () => randomUUID(),
2707
+ if (sessionId && this.sessionManager.hasSession(sessionId)) transport = this.sessionManager.getSession(sessionId).transport;
2708
+ else if (!sessionId && (0, __modelcontextprotocol_sdk_types_js.isInitializeRequest)(req.body)) {
2709
+ const mcpServer = this.serverFactory();
2710
+ transport = new __modelcontextprotocol_sdk_server_streamableHttp_js.StreamableHTTPServerTransport({
2711
+ sessionIdGenerator: () => (0, node_crypto.randomUUID)(),
2712
+ enableJsonResponse: true,
2566
2713
  onsessioninitialized: (sessionId$1) => {
2567
- this.sessionManager.setSession(sessionId$1, transport);
2714
+ this.sessionManager.setSession(sessionId$1, transport, mcpServer);
2568
2715
  }
2569
2716
  });
2570
2717
  transport.onclose = () => {
2571
2718
  if (transport.sessionId) this.sessionManager.deleteSession(transport.sessionId);
2572
2719
  };
2573
- await this.mcpServer.connect(transport);
2720
+ await mcpServer.connect(transport);
2574
2721
  } else {
2575
2722
  res.status(400).json({
2576
2723
  jsonrpc: "2.0",
@@ -2590,7 +2737,7 @@ var HttpTransportHandler = class {
2590
2737
  res.status(400).send("Invalid or missing session ID");
2591
2738
  return;
2592
2739
  }
2593
- await this.sessionManager.getSession(sessionId).handleRequest(req, res);
2740
+ await this.sessionManager.getSession(sessionId).transport.handleRequest(req, res);
2594
2741
  }
2595
2742
  async handleDeleteRequest(req, res) {
2596
2743
  const sessionId = req.headers["mcp-session-id"];
@@ -2598,7 +2745,7 @@ var HttpTransportHandler = class {
2598
2745
  res.status(400).send("Invalid or missing session ID");
2599
2746
  return;
2600
2747
  }
2601
- await this.sessionManager.getSession(sessionId).handleRequest(req, res);
2748
+ await this.sessionManager.getSession(sessionId).transport.handleRequest(req, res);
2602
2749
  this.sessionManager.deleteSession(sessionId);
2603
2750
  }
2604
2751
  async start() {
@@ -2681,7 +2828,7 @@ var SseTransportHandler = class {
2681
2828
  config;
2682
2829
  constructor(serverFactory, config) {
2683
2830
  this.serverFactory = typeof serverFactory === "function" ? serverFactory : () => serverFactory;
2684
- this.app = express();
2831
+ this.app = (0, express.default)();
2685
2832
  this.sessionManager = new SseSessionManager();
2686
2833
  this.config = {
2687
2834
  mode: config.mode,
@@ -2692,7 +2839,7 @@ var SseTransportHandler = class {
2692
2839
  this.setupRoutes();
2693
2840
  }
2694
2841
  setupMiddleware() {
2695
- this.app.use(express.json());
2842
+ this.app.use(express.default.json());
2696
2843
  }
2697
2844
  setupRoutes() {
2698
2845
  this.app.get("/sse", async (req, res) => {
@@ -2711,7 +2858,7 @@ var SseTransportHandler = class {
2711
2858
  async handleSseConnection(_req, res) {
2712
2859
  try {
2713
2860
  const mcpServer = this.serverFactory();
2714
- const transport = new SSEServerTransport("/messages", res);
2861
+ const transport = new __modelcontextprotocol_sdk_server_sse_js.SSEServerTransport("/messages", res);
2715
2862
  this.sessionManager.setSession(transport.sessionId, transport, mcpServer);
2716
2863
  res.on("close", () => {
2717
2864
  this.sessionManager.deleteSession(transport.sessionId);
@@ -2794,7 +2941,7 @@ var StdioTransportHandler = class {
2794
2941
  this.server = server;
2795
2942
  }
2796
2943
  async start() {
2797
- this.transport = new StdioServerTransport();
2944
+ this.transport = new __modelcontextprotocol_sdk_server_stdio_js.StdioServerTransport();
2798
2945
  await this.server.connect(this.transport);
2799
2946
  console.error("Scaffolding MCP server started on stdio");
2800
2947
  }
@@ -2842,7 +2989,7 @@ async function startServer(handler) {
2842
2989
  /**
2843
2990
  * MCP Serve command
2844
2991
  */
2845
- const mcpServeCommand = new 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) => {
2992
+ 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) => {
2846
2993
  try {
2847
2994
  const transportType = options.type.toLowerCase();
2848
2995
  const serverOptions = { adminEnabled: options.adminEnable };
@@ -2851,13 +2998,12 @@ const mcpServeCommand = new Command("mcp-serve").description("Start MCP server w
2851
2998
  const handler = new StdioTransportHandler(server);
2852
2999
  await startServer(handler);
2853
3000
  } else if (transportType === "http") {
2854
- const server = createServer(serverOptions);
2855
3001
  const config = {
2856
3002
  mode: TransportMode.HTTP,
2857
3003
  port: options.port || Number(process.env.MCP_PORT) || 3e3,
2858
3004
  host: options.host || process.env.MCP_HOST || "localhost"
2859
3005
  };
2860
- const handler = new HttpTransportHandler(server, config);
3006
+ const handler = new HttpTransportHandler(() => createServer(serverOptions), config);
2861
3007
  await startServer(handler);
2862
3008
  } else if (transportType === "sse") {
2863
3009
  const config = {
@@ -2879,21 +3025,19 @@ const mcpServeCommand = new Command("mcp-serve").description("Start MCP server w
2879
3025
 
2880
3026
  //#endregion
2881
3027
  //#region src/cli/scaffold.ts
2882
- const __filename = fileURLToPath(import.meta.url);
2883
- const __dirname = path.dirname(__filename);
2884
- const templatesDir = path.resolve(__dirname, "../../../../templates");
2885
3028
  /**
2886
3029
  * Scaffold CLI command
2887
3030
  */
2888
- const scaffoldCommand = new Command("scaffold").description("Add features to existing projects");
3031
+ const scaffoldCommand = new commander.Command("scaffold").description("Add features to existing projects");
2889
3032
  scaffoldCommand.command("list <projectPath>").description("List available scaffolding methods for a project").action(async (projectPath) => {
2890
3033
  try {
2891
- const absolutePath = path.resolve(projectPath);
2892
- if (!fs$1.existsSync(path.join(absolutePath, "project.json"))) {
3034
+ const absolutePath = node_path.default.resolve(projectPath);
3035
+ if (!fs_extra.existsSync(node_path.default.join(absolutePath, "project.json"))) {
2893
3036
  messages.error(`No project.json found in ${absolutePath}`);
2894
3037
  messages.hint("Make sure you are in a valid project directory");
2895
3038
  process.exit(1);
2896
3039
  }
3040
+ const templatesDir = await require_ScaffoldService.TemplatesManager.findTemplatesPath();
2897
3041
  const fileSystemService = new FileSystemService();
2898
3042
  const methods = (await new ScaffoldingMethodsService(fileSystemService, templatesDir).listScaffoldingMethods(absolutePath)).methods;
2899
3043
  if (methods.length === 0) {
@@ -2914,8 +3058,8 @@ scaffoldCommand.command("list <projectPath>").description("List available scaffo
2914
3058
  });
2915
3059
  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) => {
2916
3060
  try {
2917
- const projectPath = path.resolve(options.project);
2918
- if (!fs$1.existsSync(path.join(projectPath, "project.json"))) {
3061
+ const projectPath = node_path.default.resolve(options.project);
3062
+ if (!fs_extra.existsSync(node_path.default.join(projectPath, "project.json"))) {
2919
3063
  messages.error(`No project.json found in ${projectPath}`);
2920
3064
  messages.hint("Make sure you are in a valid project directory");
2921
3065
  process.exit(1);
@@ -2928,6 +3072,7 @@ scaffoldCommand.command("add <featureName>").description("Add a feature to an ex
2928
3072
  messages.hint("Example: --vars '{\"componentName\": \"UserProfile\", \"description\": \"User profile component\"}'");
2929
3073
  process.exit(1);
2930
3074
  }
3075
+ const templatesDir = await require_ScaffoldService.TemplatesManager.findTemplatesPath();
2931
3076
  const fileSystemService = new FileSystemService();
2932
3077
  const scaffoldingMethodsService = new ScaffoldingMethodsService(fileSystemService, templatesDir);
2933
3078
  const methods = (await scaffoldingMethodsService.listScaffoldingMethods(projectPath)).methods;
@@ -2988,11 +3133,12 @@ scaffoldCommand.command("add <featureName>").description("Add a feature to an ex
2988
3133
  });
2989
3134
  scaffoldCommand.command("info <featureName>").description("Show detailed information about a scaffold method").option("-p, --project <path>", "Project path", process.cwd()).action(async (featureName, options) => {
2990
3135
  try {
2991
- const projectPath = path.resolve(options.project);
2992
- if (!fs$1.existsSync(path.join(projectPath, "project.json"))) {
3136
+ const projectPath = node_path.default.resolve(options.project);
3137
+ if (!fs_extra.existsSync(node_path.default.join(projectPath, "project.json"))) {
2993
3138
  messages.error(`❌ No project.json found in ${projectPath}`);
2994
3139
  process.exit(1);
2995
3140
  }
3141
+ const templatesDir = await require_ScaffoldService.TemplatesManager.findTemplatesPath();
2996
3142
  const fileSystemService = new FileSystemService();
2997
3143
  const method = (await new ScaffoldingMethodsService(fileSystemService, templatesDir).listScaffoldingMethods(projectPath)).methods.find((m) => m.name === featureName);
2998
3144
  if (!method) {
@@ -3024,7 +3170,7 @@ scaffoldCommand.command("info <featureName>").description("Show detailed informa
3024
3170
  * Main entry point
3025
3171
  */
3026
3172
  async function main() {
3027
- const program = new Command();
3173
+ const program = new commander.Command();
3028
3174
  program.name("scaffold-mcp").description("MCP server for scaffolding applications with boilerplate templates").version("1.0.0");
3029
3175
  program.addCommand(mcpServeCommand);
3030
3176
  program.addCommand(boilerplateCommand);
@@ -3035,5 +3181,4 @@ async function main() {
3035
3181
  }
3036
3182
  main();
3037
3183
 
3038
- //#endregion
3039
- export { };
3184
+ //#endregion