@agiflowai/scaffold-mcp 1.0.0 → 1.0.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.
@@ -1,18 +1,16 @@
1
1
  const require_chunk = require('./chunk-CUT6urMc.cjs');
2
2
  const require_ScaffoldConfigLoader = require('./ScaffoldConfigLoader-BrmvENTo.cjs');
3
- const require_ScaffoldService = require('./ScaffoldService-B-L4gwHt.cjs');
3
+ const require_ScaffoldService = require('./ScaffoldService-BwDmXt83.cjs');
4
4
  const require_TemplateService = require('./TemplateService-DRubcvS9.cjs');
5
- const require_VariableReplacementService = require('./VariableReplacementService-BL84vnKk.cjs');
6
- let node_path = require("node:path");
7
- node_path = require_chunk.__toESM(node_path);
5
+ const require_VariableReplacementService = require('./VariableReplacementService-D0QnWKUW.cjs');
8
6
  let __agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
9
7
  __agiflowai_aicode_utils = require_chunk.__toESM(__agiflowai_aicode_utils);
10
- let fs_extra = require("fs-extra");
11
- fs_extra = require_chunk.__toESM(fs_extra);
12
- let execa = require("execa");
13
- execa = require_chunk.__toESM(execa);
8
+ let node_path = require("node:path");
9
+ node_path = require_chunk.__toESM(node_path);
14
10
  let __composio_json_schema_to_zod = require("@composio/json-schema-to-zod");
15
11
  __composio_json_schema_to_zod = require_chunk.__toESM(__composio_json_schema_to_zod);
12
+ let fs_extra = require("fs-extra");
13
+ fs_extra = require_chunk.__toESM(fs_extra);
16
14
  let js_yaml = require("js-yaml");
17
15
  js_yaml = require_chunk.__toESM(js_yaml);
18
16
  let zod = require("zod");
@@ -30,158 +28,31 @@ __modelcontextprotocol_sdk_server_sse_js = require_chunk.__toESM(__modelcontextp
30
28
  let __modelcontextprotocol_sdk_server_stdio_js = require("@modelcontextprotocol/sdk/server/stdio.js");
31
29
  __modelcontextprotocol_sdk_server_stdio_js = require_chunk.__toESM(__modelcontextprotocol_sdk_server_stdio_js);
32
30
 
33
- //#region src/utils/git.ts
34
- /**
35
- * Execute a git command safely using execa to prevent command injection
36
- */
37
- async function execGit(args, cwd) {
38
- try {
39
- await (0, execa.execa)("git", args, { cwd });
40
- } catch (error) {
41
- const execaError = error;
42
- throw new Error(`Git command failed: ${execaError.stderr || execaError.message}`);
43
- }
44
- }
45
- /**
46
- * Find the workspace root by searching upwards for .git folder
47
- * Returns null if no .git folder is found (indicating a new project setup is needed)
48
- */
49
- async function findWorkspaceRoot(startPath = process.cwd()) {
50
- let currentPath = node_path.default.resolve(startPath);
51
- const rootPath = node_path.default.parse(currentPath).root;
52
- while (true) {
53
- const gitPath = node_path.default.join(currentPath, ".git");
54
- if (await fs_extra.pathExists(gitPath)) return currentPath;
55
- if (currentPath === rootPath) return null;
56
- currentPath = node_path.default.dirname(currentPath);
57
- }
58
- }
59
- /**
60
- * Parse GitHub URL to detect if it's a subdirectory
61
- * Supports formats:
62
- * - https://github.com/user/repo
63
- * - https://github.com/user/repo/tree/branch/path/to/dir
64
- * - https://github.com/user/repo/tree/main/path/to/dir
65
- */
66
- function parseGitHubUrl(url) {
67
- const treeMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+)$/);
68
- const blobMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/blob\/([^/]+)\/(.+)$/);
69
- const rootMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/);
70
- if (treeMatch || blobMatch) {
71
- const match = treeMatch || blobMatch;
72
- return {
73
- owner: match[1],
74
- repo: match[2],
75
- repoUrl: `https://github.com/${match[1]}/${match[2]}.git`,
76
- branch: match[3],
77
- subdirectory: match[4],
78
- isSubdirectory: true
79
- };
80
- }
81
- if (rootMatch) return {
82
- owner: rootMatch[1],
83
- repo: rootMatch[2],
84
- repoUrl: `https://github.com/${rootMatch[1]}/${rootMatch[2]}.git`,
85
- isSubdirectory: false
86
- };
87
- return {
88
- repoUrl: url,
89
- isSubdirectory: false
90
- };
91
- }
92
- /**
93
- * Clone a subdirectory from a git repository using sparse checkout
94
- */
95
- async function cloneSubdirectory(repoUrl, branch, subdirectory, targetFolder) {
96
- const tempFolder = `${targetFolder}.tmp`;
97
- try {
98
- await execGit(["init", tempFolder]);
99
- await execGit([
100
- "remote",
101
- "add",
102
- "origin",
103
- repoUrl
104
- ], tempFolder);
105
- await execGit([
106
- "config",
107
- "core.sparseCheckout",
108
- "true"
109
- ], tempFolder);
110
- const sparseCheckoutFile = node_path.default.join(tempFolder, ".git", "info", "sparse-checkout");
111
- await fs_extra.writeFile(sparseCheckoutFile, `${subdirectory}\n`);
112
- await execGit([
113
- "pull",
114
- "--depth=1",
115
- "origin",
116
- branch
117
- ], tempFolder);
118
- const sourceDir = node_path.default.join(tempFolder, subdirectory);
119
- if (!await fs_extra.pathExists(sourceDir)) throw new Error(`Subdirectory '${subdirectory}' not found in repository at branch '${branch}'`);
120
- if (await fs_extra.pathExists(targetFolder)) throw new Error(`Target folder already exists: ${targetFolder}`);
121
- await fs_extra.move(sourceDir, targetFolder);
122
- await fs_extra.remove(tempFolder);
123
- } catch (error) {
124
- if (await fs_extra.pathExists(tempFolder)) await fs_extra.remove(tempFolder);
125
- throw error;
126
- }
127
- }
128
- /**
129
- * Clone entire repository
130
- */
131
- async function cloneRepository(repoUrl, targetFolder) {
132
- await execGit([
133
- "clone",
134
- repoUrl,
135
- targetFolder
136
- ]);
137
- const gitFolder = node_path.default.join(targetFolder, ".git");
138
- if (await fs_extra.pathExists(gitFolder)) await fs_extra.remove(gitFolder);
139
- }
140
- /**
141
- * Fetch directory listing from GitHub API
142
- */
143
- async function fetchGitHubDirectoryContents(owner, repo, path$3, branch = "main") {
144
- const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path$3}?ref=${branch}`;
145
- const response = await fetch(url, { headers: {
146
- Accept: "application/vnd.github.v3+json",
147
- "User-Agent": "scaffold-mcp"
148
- } });
149
- if (!response.ok) throw new Error(`Failed to fetch directory contents: ${response.statusText}`);
150
- const data = await response.json();
151
- if (!Array.isArray(data)) throw new Error("Expected directory but got file");
152
- return data.map((item) => ({
153
- name: item.name,
154
- type: item.type,
155
- path: item.path
156
- }));
157
- }
158
-
159
- //#endregion
160
31
  //#region src/services/FileSystemService.ts
161
32
  var FileSystemService = class {
162
- async pathExists(path$3) {
163
- return fs_extra.default.pathExists(path$3);
33
+ async pathExists(path$2) {
34
+ return fs_extra.default.pathExists(path$2);
164
35
  }
165
- async readFile(path$3, encoding = "utf8") {
166
- return fs_extra.default.readFile(path$3, encoding);
36
+ async readFile(path$2, encoding = "utf8") {
37
+ return fs_extra.default.readFile(path$2, encoding);
167
38
  }
168
- async readJson(path$3) {
169
- return fs_extra.default.readJson(path$3);
39
+ async readJson(path$2) {
40
+ return fs_extra.default.readJson(path$2);
170
41
  }
171
- async writeFile(path$3, content, encoding = "utf8") {
172
- return fs_extra.default.writeFile(path$3, content, encoding);
42
+ async writeFile(path$2, content, encoding = "utf8") {
43
+ return fs_extra.default.writeFile(path$2, content, encoding);
173
44
  }
174
- async ensureDir(path$3) {
175
- return fs_extra.default.ensureDir(path$3);
45
+ async ensureDir(path$2) {
46
+ return fs_extra.default.ensureDir(path$2);
176
47
  }
177
48
  async copy(src, dest) {
178
49
  return fs_extra.default.copy(src, dest);
179
50
  }
180
- async readdir(path$3) {
181
- return fs_extra.default.readdir(path$3);
51
+ async readdir(path$2) {
52
+ return fs_extra.default.readdir(path$2);
182
53
  }
183
- async stat(path$3) {
184
- return fs_extra.default.stat(path$3);
54
+ async stat(path$2) {
55
+ return fs_extra.default.stat(path$2);
185
56
  }
186
57
  };
187
58
 
@@ -253,7 +124,28 @@ var BoilerplateService = class {
253
124
  * Executes a specific boilerplate with provided variables
254
125
  */
255
126
  async useBoilerplate(request) {
256
- const { boilerplateName, variables, monolith = false, targetFolderOverride } = request;
127
+ let { boilerplateName, variables, monolith, targetFolderOverride } = request;
128
+ if (monolith === void 0) try {
129
+ const config = await __agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(process.cwd());
130
+ monolith = config.type === "monolith";
131
+ __agiflowai_aicode_utils.log.info(`Auto-detected project type: ${config.type}`);
132
+ } catch (_error) {
133
+ monolith = false;
134
+ __agiflowai_aicode_utils.log.info("No project configuration found, defaulting to monorepo mode");
135
+ }
136
+ if (monolith && !boilerplateName) try {
137
+ boilerplateName = (await __agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(process.cwd())).sourceTemplate;
138
+ __agiflowai_aicode_utils.log.info(`Using boilerplate from toolkit.yaml: ${boilerplateName}`);
139
+ } catch (error) {
140
+ return {
141
+ success: false,
142
+ message: `Failed to read boilerplate name from toolkit.yaml: ${error instanceof Error ? error.message : String(error)}`
143
+ };
144
+ }
145
+ if (!boilerplateName) return {
146
+ success: false,
147
+ message: "Missing required parameter: boilerplateName"
148
+ };
257
149
  const boilerplateList = await this.listBoilerplates();
258
150
  const boilerplate = boilerplateList.boilerplates.find((b) => b.name === boilerplateName);
259
151
  if (!boilerplate) return {
@@ -272,9 +164,10 @@ var BoilerplateService = class {
272
164
  };
273
165
  const folderName = packageName.includes("/") ? packageName.split("/")[1] : packageName;
274
166
  const targetFolder = targetFolderOverride || (monolith ? "." : boilerplate.target_folder);
167
+ const projectNameForPath = monolith ? "" : folderName;
275
168
  try {
276
169
  const result = await this.scaffoldService.useBoilerplate({
277
- projectName: folderName,
170
+ projectName: projectNameForPath,
278
171
  packageName,
279
172
  targetFolder,
280
173
  templateFolder: boilerplate.template_path,
@@ -520,44 +413,28 @@ var BoilerplateGeneratorService = class {
520
413
  var GenerateBoilerplateFileTool = class GenerateBoilerplateFileTool {
521
414
  static TOOL_NAME = "generate-boilerplate-file";
522
415
  boilerplateGeneratorService;
523
- constructor(templatesPath) {
416
+ isMonolith;
417
+ constructor(templatesPath, isMonolith = false) {
524
418
  this.boilerplateGeneratorService = new BoilerplateGeneratorService(templatesPath);
419
+ this.isMonolith = isMonolith;
525
420
  }
526
421
  /**
527
422
  * Get the tool definition for MCP
528
423
  */
529
424
  getDefinition() {
530
- return {
531
- name: GenerateBoilerplateFileTool.TOOL_NAME,
532
- description: `Create or update template files for boilerplates or features in the specified template directory.
533
-
534
- This tool:
535
- - Creates template files with .liquid extension for variable substitution
536
- - Supports creating nested directory structures
537
- - Can create files from source files (copying and converting to templates)
538
- - Validates that the template directory exists
539
- - Works for both boilerplate includes and feature scaffold includes
540
-
541
- IMPORTANT - Always add header comments:
542
- - For code files (*.ts, *.tsx, *.js, *.jsx), ALWAYS include a header parameter with design patterns, coding standards, and things to avoid
543
- - Headers help AI understand and follow established patterns when working with generated code
544
- - Use the header parameter to document the architectural decisions and best practices
545
-
546
- Use this after generate-boilerplate or generate-feature-scaffold to create the actual template files referenced in the includes array.`,
547
- inputSchema: {
548
- type: "object",
549
- properties: {
550
- templateName: {
551
- type: "string",
552
- description: "Name of the template folder (must already exist)"
553
- },
554
- filePath: {
555
- type: "string",
556
- description: "Path of the file to create within the template (e.g., \"package.json\", \"src/app/page.tsx\")"
557
- },
558
- content: {
559
- type: "string",
560
- description: `Content of the template file using Liquid template syntax.
425
+ const properties = {};
426
+ if (!this.isMonolith) properties.templateName = {
427
+ type: "string",
428
+ description: "Name of the template folder (must already exist)"
429
+ };
430
+ Object.assign(properties, {
431
+ filePath: {
432
+ type: "string",
433
+ description: "Path of the file to create within the template (e.g., \"package.json\", \"src/app/page.tsx\")"
434
+ },
435
+ content: {
436
+ type: "string",
437
+ description: `Content of the template file using Liquid template syntax.
561
438
 
562
439
  LIQUID SYNTAX:
563
440
  - Variables: {{ variableName }} - Replaced with actual values
@@ -626,14 +503,14 @@ export function calculateTax(income: number) {
626
503
  const stateRate = 0.05;
627
504
  return income * (federalRate + stateRate);
628
505
  }`
629
- },
630
- sourceFile: {
631
- type: "string",
632
- description: "Optional: Path to a source file to copy and convert to a template"
633
- },
634
- header: {
635
- type: "string",
636
- description: `Optional: Header comment to add at the top of the file to provide AI hints about design patterns, coding standards, and best practices.
506
+ },
507
+ sourceFile: {
508
+ type: "string",
509
+ description: "Optional: Path to a source file to copy and convert to a template"
510
+ },
511
+ header: {
512
+ type: "string",
513
+ description: `Optional: Header comment to add at the top of the file to provide AI hints about design patterns, coding standards, and best practices.
637
514
 
638
515
  Example format for TypeScript/JavaScript files:
639
516
  /**
@@ -653,9 +530,31 @@ Example format for TypeScript/JavaScript files:
653
530
  */
654
531
 
655
532
  The header helps AI understand and follow established patterns when working with generated code.`
656
- }
657
- },
658
- required: ["templateName", "filePath"],
533
+ }
534
+ });
535
+ const required = ["filePath"];
536
+ if (!this.isMonolith) required.unshift("templateName");
537
+ return {
538
+ name: GenerateBoilerplateFileTool.TOOL_NAME,
539
+ description: `Create or update template files for boilerplates or features in the specified template directory.
540
+
541
+ This tool:
542
+ - Creates template files with .liquid extension for variable substitution
543
+ - Supports creating nested directory structures
544
+ - Can create files from source files (copying and converting to templates)
545
+ - Validates that the template directory exists
546
+ - Works for both boilerplate includes and feature scaffold includes
547
+
548
+ IMPORTANT - Always add header comments:
549
+ - For code files (*.ts, *.tsx, *.js, *.jsx), ALWAYS include a header parameter with design patterns, coding standards, and things to avoid
550
+ - Headers help AI understand and follow established patterns when working with generated code
551
+ - Use the header parameter to document the architectural decisions and best practices
552
+
553
+ Use this after generate-boilerplate or generate-feature-scaffold to create the actual template files referenced in the includes array.`,
554
+ inputSchema: {
555
+ type: "object",
556
+ properties,
557
+ required,
659
558
  additionalProperties: false
660
559
  }
661
560
  };
@@ -665,7 +564,29 @@ The header helps AI understand and follow established patterns when working with
665
564
  */
666
565
  async execute(args) {
667
566
  try {
668
- const result = await this.boilerplateGeneratorService.createTemplateFile(args);
567
+ let { templateName } = args;
568
+ if (this.isMonolith && !templateName) try {
569
+ templateName = (await __agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(process.cwd())).sourceTemplate;
570
+ } catch (error) {
571
+ return {
572
+ content: [{
573
+ type: "text",
574
+ text: `Failed to read template name from configuration: ${error instanceof Error ? error.message : String(error)}`
575
+ }],
576
+ isError: true
577
+ };
578
+ }
579
+ if (!templateName) return {
580
+ content: [{
581
+ type: "text",
582
+ text: "Missing required parameter: templateName"
583
+ }],
584
+ isError: true
585
+ };
586
+ const result = await this.boilerplateGeneratorService.createTemplateFile({
587
+ ...args,
588
+ templateName
589
+ });
669
590
  if (!result.success) return {
670
591
  content: [{
671
592
  type: "text",
@@ -703,42 +624,32 @@ The header helps AI understand and follow established patterns when working with
703
624
  var GenerateBoilerplateTool = class GenerateBoilerplateTool {
704
625
  static TOOL_NAME = "generate-boilerplate";
705
626
  boilerplateGeneratorService;
706
- constructor(templatesPath) {
627
+ isMonolith;
628
+ constructor(templatesPath, isMonolith = false) {
707
629
  this.boilerplateGeneratorService = new BoilerplateGeneratorService(templatesPath);
630
+ this.isMonolith = isMonolith;
708
631
  }
709
632
  /**
710
633
  * Get the tool definition for MCP
711
634
  */
712
635
  getDefinition() {
713
- return {
714
- name: GenerateBoilerplateTool.TOOL_NAME,
715
- description: `Add a new boilerplate configuration to a template's scaffold.yaml file.
716
-
717
- This tool:
718
- - Creates or updates scaffold.yaml in the specified template directory
719
- - Adds a boilerplate entry with proper schema following the nextjs-15 pattern
720
- - Validates the boilerplate name doesn't already exist
721
- - Creates the template directory if it doesn't exist
722
-
723
- Use this to add custom boilerplate configurations for frameworks not yet supported or for your specific project needs.`,
724
- inputSchema: {
725
- type: "object",
726
- properties: {
727
- templateName: {
728
- type: "string",
729
- description: "Name of the template folder (kebab-case, e.g., \"my-framework\")"
730
- },
731
- boilerplateName: {
732
- type: "string",
733
- description: "Name of the boilerplate (kebab-case, e.g., \"scaffold-my-app\")"
734
- },
735
- targetFolder: {
736
- type: "string",
737
- description: "Target folder where projects will be created (e.g., \"apps\", \"packages\")"
738
- },
739
- description: {
740
- type: "string",
741
- description: `Detailed description of what this boilerplate creates and its key features.
636
+ const properties = {};
637
+ if (!this.isMonolith) properties.templateName = {
638
+ type: "string",
639
+ description: "Name of the template folder (kebab-case, e.g., \"my-framework\")"
640
+ };
641
+ Object.assign(properties, {
642
+ boilerplateName: {
643
+ type: "string",
644
+ description: "Name of the boilerplate (kebab-case, e.g., \"scaffold-my-app\")"
645
+ },
646
+ targetFolder: {
647
+ type: "string",
648
+ description: "Target folder where projects will be created (e.g., \"apps\", \"packages\")"
649
+ },
650
+ description: {
651
+ type: "string",
652
+ description: `Detailed description of what this boilerplate creates and its key features.
742
653
 
743
654
  STRUCTURE (3-5 sentences in multiple paragraphs):
744
655
  - Paragraph 1: Core technology stack and primary value proposition
@@ -749,10 +660,10 @@ Example: "A modern React SPA template powered by Vite for lightning-fast HMR, fe
749
660
  Perfect for building data-driven dashboards, admin panels, and interactive web applications requiring client-side routing and real-time data synchronization.
750
661
 
751
662
  Includes Agiflow Config Management System integration with systematic environment variable naming (VITE_{CATEGORY}_{SUBCATEGORY}_{PROPERTY}) and auto-generated configuration templates for cloud deployment."`
752
- },
753
- instruction: {
754
- type: "string",
755
- description: `Optional detailed instructions about the generated files, their purposes, and how to work with them.
663
+ },
664
+ instruction: {
665
+ type: "string",
666
+ description: `Optional detailed instructions about the generated files, their purposes, and how to work with them.
756
667
 
757
668
  STRUCTURE (Multi-section guide):
758
669
 
@@ -796,47 +707,47 @@ Design patterns to follow:
796
707
  - Type-safe Routes: Leverage [framework] type inference for params
797
708
  - State Management: Use [library] for server state, [library] for client state
798
709
  [... list key patterns with explanations ...]"`
710
+ },
711
+ variables: {
712
+ type: "array",
713
+ description: "Array of variable definitions for the boilerplate",
714
+ items: {
715
+ type: "object",
716
+ properties: {
717
+ name: {
718
+ type: "string",
719
+ description: "Variable name (camelCase)"
720
+ },
721
+ description: {
722
+ type: "string",
723
+ description: "Variable description"
724
+ },
725
+ type: {
726
+ type: "string",
727
+ enum: [
728
+ "string",
729
+ "number",
730
+ "boolean"
731
+ ],
732
+ description: "Variable type"
733
+ },
734
+ required: {
735
+ type: "boolean",
736
+ description: "Whether this variable is required"
737
+ },
738
+ default: { description: "Optional default value for the variable" }
799
739
  },
800
- variables: {
801
- type: "array",
802
- description: "Array of variable definitions for the boilerplate",
803
- items: {
804
- type: "object",
805
- properties: {
806
- name: {
807
- type: "string",
808
- description: "Variable name (camelCase)"
809
- },
810
- description: {
811
- type: "string",
812
- description: "Variable description"
813
- },
814
- type: {
815
- type: "string",
816
- enum: [
817
- "string",
818
- "number",
819
- "boolean"
820
- ],
821
- description: "Variable type"
822
- },
823
- required: {
824
- type: "boolean",
825
- description: "Whether this variable is required"
826
- },
827
- default: { description: "Optional default value for the variable" }
828
- },
829
- required: [
830
- "name",
831
- "description",
832
- "type",
833
- "required"
834
- ]
835
- }
836
- },
837
- includes: {
838
- type: "array",
839
- description: `Array of specific file paths to include in the boilerplate (highly recommended to list explicitly).
740
+ required: [
741
+ "name",
742
+ "description",
743
+ "type",
744
+ "required"
745
+ ]
746
+ }
747
+ },
748
+ includes: {
749
+ type: "array",
750
+ description: `Array of specific file paths to include in the boilerplate (highly recommended to list explicitly).
840
751
 
841
752
  Examples:
842
753
  - ["package.json", "tsconfig.json", "src/index.ts"] - Explicit file list (recommended)
@@ -850,16 +761,33 @@ Best practices:
850
761
  - Avoid wildcards unless you have a good reason
851
762
 
852
763
  See templates/nextjs-15/scaffold.yaml for a good example of explicit file listing.`,
853
- items: { type: "string" }
854
- }
855
- },
856
- required: [
857
- "templateName",
858
- "boilerplateName",
859
- "description",
860
- "targetFolder",
861
- "variables"
862
- ],
764
+ items: { type: "string" }
765
+ }
766
+ });
767
+ const required = [
768
+ "boilerplateName",
769
+ "description",
770
+ "variables"
771
+ ];
772
+ if (!this.isMonolith) {
773
+ required.unshift("templateName");
774
+ required.push("targetFolder");
775
+ }
776
+ return {
777
+ name: GenerateBoilerplateTool.TOOL_NAME,
778
+ description: `Add a new boilerplate configuration to a template's scaffold.yaml file.
779
+
780
+ This tool:
781
+ - Creates or updates scaffold.yaml in the specified template directory
782
+ - Adds a boilerplate entry with proper schema following the nextjs-15 pattern
783
+ - Validates the boilerplate name doesn't already exist
784
+ - Creates the template directory if it doesn't exist
785
+
786
+ Use this to add custom boilerplate configurations for frameworks not yet supported or for your specific project needs.`,
787
+ inputSchema: {
788
+ type: "object",
789
+ properties,
790
+ required,
863
791
  additionalProperties: false
864
792
  }
865
793
  };
@@ -869,7 +797,38 @@ See templates/nextjs-15/scaffold.yaml for a good example of explicit file listin
869
797
  */
870
798
  async execute(args) {
871
799
  try {
872
- const result = await this.boilerplateGeneratorService.generateBoilerplate(args);
800
+ let { templateName, targetFolder } = args;
801
+ if (this.isMonolith && !templateName) try {
802
+ templateName = (await __agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(process.cwd())).sourceTemplate;
803
+ } catch (error) {
804
+ return {
805
+ content: [{
806
+ type: "text",
807
+ text: `Failed to read template name from configuration: ${error instanceof Error ? error.message : String(error)}`
808
+ }],
809
+ isError: true
810
+ };
811
+ }
812
+ if (this.isMonolith && !targetFolder) targetFolder = ".";
813
+ if (!templateName) return {
814
+ content: [{
815
+ type: "text",
816
+ text: "Missing required parameter: templateName"
817
+ }],
818
+ isError: true
819
+ };
820
+ if (!targetFolder) return {
821
+ content: [{
822
+ type: "text",
823
+ text: "Missing required parameter: targetFolder"
824
+ }],
825
+ isError: true
826
+ };
827
+ const result = await this.boilerplateGeneratorService.generateBoilerplate({
828
+ ...args,
829
+ templateName,
830
+ targetFolder
831
+ });
873
832
  if (!result.success) return {
874
833
  content: [{
875
834
  type: "text",
@@ -1037,38 +996,28 @@ var ScaffoldGeneratorService = class {
1037
996
  var GenerateFeatureScaffoldTool = class GenerateFeatureScaffoldTool {
1038
997
  static TOOL_NAME = "generate-feature-scaffold";
1039
998
  scaffoldGeneratorService;
1040
- constructor(templatesPath) {
999
+ isMonolith;
1000
+ constructor(templatesPath, isMonolith = false) {
1041
1001
  this.scaffoldGeneratorService = new ScaffoldGeneratorService(templatesPath);
1002
+ this.isMonolith = isMonolith;
1042
1003
  }
1043
1004
  /**
1044
1005
  * Get the tool definition for MCP
1045
1006
  */
1046
1007
  getDefinition() {
1047
- return {
1048
- name: GenerateFeatureScaffoldTool.TOOL_NAME,
1049
- description: `Add a new feature scaffold configuration to a template's scaffold.yaml file.
1050
-
1051
- This tool:
1052
- - Creates or updates scaffold.yaml in the specified template directory
1053
- - Adds a feature entry with proper schema following the nextjs-15 pattern
1054
- - Validates the feature name doesn't already exist
1055
- - Creates the template directory if it doesn't exist
1056
-
1057
- Use this to add custom feature scaffolds (pages, components, services, etc.) for frameworks not yet supported or for your specific project needs.`,
1058
- inputSchema: {
1059
- type: "object",
1060
- properties: {
1061
- templateName: {
1062
- type: "string",
1063
- description: "Name of the template folder (kebab-case, e.g., \"nextjs-15\")"
1064
- },
1065
- featureName: {
1066
- type: "string",
1067
- description: "Name of the feature (kebab-case, e.g., \"scaffold-nextjs-page\")"
1068
- },
1069
- description: {
1070
- type: "string",
1071
- description: `Detailed description of what this feature creates and its key capabilities.
1008
+ const properties = {};
1009
+ if (!this.isMonolith) properties.templateName = {
1010
+ type: "string",
1011
+ description: "Name of the template folder (kebab-case, e.g., \"nextjs-15\")"
1012
+ };
1013
+ Object.assign(properties, {
1014
+ featureName: {
1015
+ type: "string",
1016
+ description: "Name of the feature (kebab-case, e.g., \"scaffold-nextjs-page\")"
1017
+ },
1018
+ description: {
1019
+ type: "string",
1020
+ description: `Detailed description of what this feature creates and its key capabilities.
1072
1021
 
1073
1022
  STRUCTURE (2-3 sentences):
1074
1023
  - Sentence 1: What type of code it generates (component, page, service, etc.)
@@ -1076,10 +1025,10 @@ STRUCTURE (2-3 sentences):
1076
1025
  - Sentence 3: Primary use cases or when to use it
1077
1026
 
1078
1027
  Example: "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."`
1079
- },
1080
- instruction: {
1081
- type: "string",
1082
- description: `Optional detailed instructions about the generated files, their purposes, and how to work with them.
1028
+ },
1029
+ instruction: {
1030
+ type: "string",
1031
+ description: `Optional detailed instructions about the generated files, their purposes, and how to work with them.
1083
1032
 
1084
1033
  STRUCTURE (Concise multi-aspect guide):
1085
1034
 
@@ -1090,47 +1039,47 @@ STRUCTURE (Concise multi-aspect guide):
1090
1039
  5. **Testing approach**: How to test the feature
1091
1040
 
1092
1041
  Example: "Services follow a class-based pattern with optional interface separation. The service class implements business logic and can be dependency injected. Place services in src/services/ directory. For services with interfaces, define the interface in src/types/interfaces/ for better separation of concerns. Service names should be PascalCase and end with 'Service' suffix. Write comprehensive unit tests for all public methods."`
1042
+ },
1043
+ variables: {
1044
+ type: "array",
1045
+ description: "Array of variable definitions for the feature",
1046
+ items: {
1047
+ type: "object",
1048
+ properties: {
1049
+ name: {
1050
+ type: "string",
1051
+ description: "Variable name (camelCase)"
1052
+ },
1053
+ description: {
1054
+ type: "string",
1055
+ description: "Variable description"
1056
+ },
1057
+ type: {
1058
+ type: "string",
1059
+ enum: [
1060
+ "string",
1061
+ "number",
1062
+ "boolean"
1063
+ ],
1064
+ description: "Variable type"
1065
+ },
1066
+ required: {
1067
+ type: "boolean",
1068
+ description: "Whether this variable is required"
1069
+ },
1070
+ default: { description: "Optional default value for the variable" }
1093
1071
  },
1094
- variables: {
1095
- type: "array",
1096
- description: "Array of variable definitions for the feature",
1097
- items: {
1098
- type: "object",
1099
- properties: {
1100
- name: {
1101
- type: "string",
1102
- description: "Variable name (camelCase)"
1103
- },
1104
- description: {
1105
- type: "string",
1106
- description: "Variable description"
1107
- },
1108
- type: {
1109
- type: "string",
1110
- enum: [
1111
- "string",
1112
- "number",
1113
- "boolean"
1114
- ],
1115
- description: "Variable type"
1116
- },
1117
- required: {
1118
- type: "boolean",
1119
- description: "Whether this variable is required"
1120
- },
1121
- default: { description: "Optional default value for the variable" }
1122
- },
1123
- required: [
1124
- "name",
1125
- "description",
1126
- "type",
1127
- "required"
1128
- ]
1129
- }
1130
- },
1131
- includes: {
1132
- type: "array",
1133
- description: `Array of specific file paths to include in the feature (highly recommended to list explicitly).
1072
+ required: [
1073
+ "name",
1074
+ "description",
1075
+ "type",
1076
+ "required"
1077
+ ]
1078
+ }
1079
+ },
1080
+ includes: {
1081
+ type: "array",
1082
+ description: `Array of specific file paths to include in the feature (highly recommended to list explicitly).
1134
1083
 
1135
1084
  Supports advanced syntax:
1136
1085
  - Basic: "src/app/page/page.tsx" - Always included
@@ -1151,11 +1100,11 @@ Best practices:
1151
1100
  - Use path mapping with -> when source and target paths differ
1152
1101
  - Use {{ variableName }} in target paths for dynamic file placement
1153
1102
  - Avoid wildcards unless you have a good reason`,
1154
- items: { type: "string" }
1155
- },
1156
- patterns: {
1157
- type: "array",
1158
- description: `Optional array of glob patterns to match existing files that this feature works with.
1103
+ items: { type: "string" }
1104
+ },
1105
+ patterns: {
1106
+ type: "array",
1107
+ description: `Optional array of glob patterns to match existing files that this feature works with.
1159
1108
 
1160
1109
  Used to help identify where this feature can be applied in a project.
1161
1110
 
@@ -1168,15 +1117,30 @@ Best practices:
1168
1117
  - Use glob patterns that match the file types this feature works with
1169
1118
  - Keep patterns specific enough to be meaningful but broad enough to be useful
1170
1119
  - Consider both the feature's output and input files`,
1171
- items: { type: "string" }
1172
- }
1173
- },
1174
- required: [
1175
- "templateName",
1176
- "featureName",
1177
- "description",
1178
- "variables"
1179
- ],
1120
+ items: { type: "string" }
1121
+ }
1122
+ });
1123
+ const required = [
1124
+ "featureName",
1125
+ "description",
1126
+ "variables"
1127
+ ];
1128
+ if (!this.isMonolith) required.unshift("templateName");
1129
+ return {
1130
+ name: GenerateFeatureScaffoldTool.TOOL_NAME,
1131
+ description: `Add a new feature scaffold configuration to a template's scaffold.yaml file.
1132
+
1133
+ This tool:
1134
+ - Creates or updates scaffold.yaml in the specified template directory
1135
+ - Adds a feature entry with proper schema following the nextjs-15 pattern
1136
+ - Validates the feature name doesn't already exist
1137
+ - Creates the template directory if it doesn't exist
1138
+
1139
+ Use this to add custom feature scaffolds (pages, components, services, etc.) for frameworks not yet supported or for your specific project needs.`,
1140
+ inputSchema: {
1141
+ type: "object",
1142
+ properties,
1143
+ required,
1180
1144
  additionalProperties: false
1181
1145
  }
1182
1146
  };
@@ -1186,7 +1150,29 @@ Best practices:
1186
1150
  */
1187
1151
  async execute(args) {
1188
1152
  try {
1189
- const result = await this.scaffoldGeneratorService.generateFeatureScaffold(args);
1153
+ let { templateName } = args;
1154
+ if (this.isMonolith && !templateName) try {
1155
+ templateName = (await __agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(process.cwd())).sourceTemplate;
1156
+ } catch (error) {
1157
+ return {
1158
+ content: [{
1159
+ type: "text",
1160
+ text: `Failed to read template name from configuration: ${error instanceof Error ? error.message : String(error)}`
1161
+ }],
1162
+ isError: true
1163
+ };
1164
+ }
1165
+ if (!templateName) return {
1166
+ content: [{
1167
+ type: "text",
1168
+ text: "Missing required parameter: templateName"
1169
+ }],
1170
+ isError: true
1171
+ };
1172
+ const result = await this.scaffoldGeneratorService.generateFeatureScaffold({
1173
+ ...args,
1174
+ templateName
1175
+ });
1190
1176
  if (!result.success) return {
1191
1177
  content: [{
1192
1178
  type: "text",
@@ -1221,29 +1207,30 @@ Best practices:
1221
1207
  }
1222
1208
  };
1223
1209
 
1210
+ //#endregion
1211
+ //#region src/instructions/tools/list-boilerplates/description.md?raw
1212
+ var description_default$2 = "{% if isMonolith %}\nNot available for monolith projects. Monolith uses a single template defined in `toolkit.yaml`.\n\nUse `list-scaffolding-methods` for available features instead.\n{% else %}\nLists all available project boilerplates for creating new applications, APIs, or packages in the monorepo.\n\nEach boilerplate includes:\n- Complete project template with starter files\n- Variable schema for customization\n- Target directory information (e.g., apps/, packages/)\n- Required and optional configuration options\n\nUse this FIRST when creating new projects to understand available templates and their requirements.\n{% endif %}\n";
1213
+
1224
1214
  //#endregion
1225
1215
  //#region src/tools/ListBoilerplatesTool.ts
1226
1216
  var ListBoilerplatesTool = class ListBoilerplatesTool {
1227
1217
  static TOOL_NAME = "list-boilerplates";
1228
1218
  boilerplateService;
1229
- constructor(templatesPath) {
1219
+ templateService;
1220
+ isMonolith;
1221
+ constructor(templatesPath, isMonolith = false) {
1230
1222
  this.boilerplateService = new BoilerplateService(templatesPath);
1223
+ this.templateService = new require_TemplateService.TemplateService();
1224
+ this.isMonolith = isMonolith;
1231
1225
  }
1232
1226
  /**
1233
1227
  * Get the tool definition for MCP
1234
1228
  */
1235
1229
  getDefinition() {
1230
+ const description = this.templateService.renderString(description_default$2, { isMonolith: this.isMonolith });
1236
1231
  return {
1237
1232
  name: ListBoilerplatesTool.TOOL_NAME,
1238
- description: `Lists all available project boilerplates for creating new applications, APIs, or packages in the monorepo.
1239
-
1240
- Each boilerplate includes:
1241
- - Complete project template with starter files
1242
- - Variable schema for customization
1243
- - Target directory information
1244
- - Required and optional configuration options
1245
-
1246
- Use this FIRST when creating new projects to understand available templates and their requirements.`,
1233
+ description: description.trim(),
1247
1234
  inputSchema: {
1248
1235
  type: "object",
1249
1236
  properties: {},
@@ -1273,6 +1260,10 @@ Use this FIRST when creating new projects to understand available templates and
1273
1260
  }
1274
1261
  };
1275
1262
 
1263
+ //#endregion
1264
+ //#region src/instructions/tools/list-scaffolding-methods/description.md?raw
1265
+ var description_default$1 = "Lists all available scaffolding methods (features) that can be added to an existing project{% if not isMonolith %} or for a specific template{% endif %}.\n\nThis tool:\n{% if isMonolith %}\n- Reads your project's sourceTemplate from toolkit.yaml at workspace root\n{% else %}\n- Reads the project's sourceTemplate from project.json (monorepo) or toolkit.yaml (monolith), OR\n- Directly uses the provided templateName to list available features\n{% endif %}\n- Returns available features for that template type\n- Provides variable schemas for each scaffolding method\n- Shows descriptions of what each method creates\n\nUse this FIRST when adding features to understand:\n- What scaffolding methods are available\n- What variables each method requires\n- What files/features will be generated\n\nExample methods might include:\n- Adding new React routes (for React apps)\n- Creating API endpoints (for backend projects)\n- Adding new components (for frontend projects)\n- Setting up database models (for API projects)\n";
1266
+
1276
1267
  //#endregion
1277
1268
  //#region src/services/ScaffoldingMethodsService.ts
1278
1269
  var ScaffoldingMethodsService = class {
@@ -1285,8 +1276,11 @@ var ScaffoldingMethodsService = class {
1285
1276
  async listScaffoldingMethods(projectPath) {
1286
1277
  const absoluteProjectPath = node_path.default.resolve(projectPath);
1287
1278
  const sourceTemplate = (await __agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(absoluteProjectPath)).sourceTemplate;
1288
- const templatePath = await this.findTemplatePath(sourceTemplate);
1289
- if (!templatePath) throw new Error(`Template not found for sourceTemplate: ${sourceTemplate}`);
1279
+ return this.listScaffoldingMethodsByTemplate(sourceTemplate);
1280
+ }
1281
+ async listScaffoldingMethodsByTemplate(templateName) {
1282
+ const templatePath = await this.findTemplatePath(templateName);
1283
+ if (!templatePath) throw new Error(`Template not found for sourceTemplate: ${templateName}`);
1290
1284
  const fullTemplatePath = node_path.default.join(this.templatesRootPath, templatePath);
1291
1285
  const scaffoldYamlPath = node_path.default.join(fullTemplatePath, "scaffold.yaml");
1292
1286
  if (!await this.fileSystem.pathExists(scaffoldYamlPath)) throw new Error(`scaffold.yaml not found at ${scaffoldYamlPath}`);
@@ -1294,8 +1288,9 @@ var ScaffoldingMethodsService = class {
1294
1288
  const architectConfig = js_yaml.default.load(scaffoldContent);
1295
1289
  const methods = [];
1296
1290
  if (architectConfig.features && Array.isArray(architectConfig.features)) architectConfig.features.forEach((feature) => {
1297
- if (feature.name) methods.push({
1298
- name: feature.name,
1291
+ const featureName = feature.name || `scaffold-${templateName}`;
1292
+ methods.push({
1293
+ name: featureName,
1299
1294
  description: feature.description || "",
1300
1295
  instruction: feature.instruction || "",
1301
1296
  variables_schema: feature.variables_schema || {
@@ -1308,7 +1303,7 @@ var ScaffoldingMethodsService = class {
1308
1303
  });
1309
1304
  });
1310
1305
  return {
1311
- sourceTemplate,
1306
+ sourceTemplate: templateName,
1312
1307
  templatePath,
1313
1308
  methods
1314
1309
  };
@@ -1353,6 +1348,14 @@ var ScaffoldingMethodsService = class {
1353
1348
  return null;
1354
1349
  }
1355
1350
  /**
1351
+ * Resolves the project path, handling both monorepo and monolith cases
1352
+ * Uses ProjectConfigResolver to find the correct workspace/project root
1353
+ */
1354
+ async resolveProjectPath(projectPath) {
1355
+ const absolutePath = node_path.default.resolve(projectPath);
1356
+ return (await __agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(absolutePath)).workspaceRoot || absolutePath;
1357
+ }
1358
+ /**
1356
1359
  * Dynamically discovers all template directories
1357
1360
  * Supports both flat structure (templates/nextjs-15) and nested structure (templates/apps/nextjs-15)
1358
1361
  **/
@@ -1390,21 +1393,21 @@ var ScaffoldingMethodsService = class {
1390
1393
  }
1391
1394
  async useScaffoldMethod(request) {
1392
1395
  const { projectPath, scaffold_feature_name, variables } = request;
1393
- const scaffoldingMethods = await this.listScaffoldingMethods(projectPath);
1396
+ const absoluteProjectPath = await this.resolveProjectPath(projectPath);
1397
+ const scaffoldingMethods = await this.listScaffoldingMethods(absoluteProjectPath);
1394
1398
  const method = scaffoldingMethods.methods.find((m) => m.name === scaffold_feature_name);
1395
1399
  if (!method) {
1396
1400
  const availableMethods = scaffoldingMethods.methods.map((m) => m.name).join(", ");
1397
1401
  throw new Error(`Scaffold method '${scaffold_feature_name}' not found. Available methods: ${availableMethods}`);
1398
1402
  }
1399
- const ScaffoldService$1 = (await Promise.resolve().then(() => require("./ScaffoldService-Cx4ZonaT.cjs"))).ScaffoldService;
1403
+ const ScaffoldService$1 = (await Promise.resolve().then(() => require("./ScaffoldService-B3En_m4t.cjs"))).ScaffoldService;
1400
1404
  const ScaffoldConfigLoader$1 = (await Promise.resolve().then(() => require("./ScaffoldConfigLoader-DQMCLVGD.cjs"))).ScaffoldConfigLoader;
1401
- const VariableReplacementService$1 = (await Promise.resolve().then(() => require("./VariableReplacementService-BrJ1PdKm.cjs"))).VariableReplacementService;
1405
+ const VariableReplacementService$1 = (await Promise.resolve().then(() => require("./VariableReplacementService-CroHkMha.cjs"))).VariableReplacementService;
1402
1406
  const TemplateService$1 = (await Promise.resolve().then(() => require("./TemplateService-BZRt3NI8.cjs"))).TemplateService;
1403
1407
  const templateService = new TemplateService$1();
1404
1408
  const scaffoldConfigLoader = new ScaffoldConfigLoader$1(this.fileSystem, templateService);
1405
1409
  const variableReplacer = new VariableReplacementService$1(this.fileSystem, templateService);
1406
1410
  const scaffoldService = new ScaffoldService$1(this.fileSystem, scaffoldConfigLoader, variableReplacer, this.templatesRootPath);
1407
- const absoluteProjectPath = node_path.default.resolve(projectPath);
1408
1411
  const projectName = node_path.default.basename(absoluteProjectPath);
1409
1412
  const result = await scaffoldService.useFeature({
1410
1413
  projectPath: absoluteProjectPath,
@@ -1437,41 +1440,36 @@ var ListScaffoldingMethodsTool = class ListScaffoldingMethodsTool {
1437
1440
  static TOOL_NAME = "list-scaffolding-methods";
1438
1441
  fileSystemService;
1439
1442
  scaffoldingMethodsService;
1440
- constructor(templatesPath) {
1443
+ templateService;
1444
+ isMonolith;
1445
+ constructor(templatesPath, isMonolith = false) {
1441
1446
  this.fileSystemService = new FileSystemService();
1442
1447
  this.scaffoldingMethodsService = new ScaffoldingMethodsService(this.fileSystemService, templatesPath);
1448
+ this.templateService = new require_TemplateService.TemplateService();
1449
+ this.isMonolith = isMonolith;
1443
1450
  }
1444
1451
  /**
1445
1452
  * Get the tool definition for MCP
1446
1453
  */
1447
1454
  getDefinition() {
1455
+ const description = this.templateService.renderString(description_default$1, { isMonolith: this.isMonolith });
1456
+ const properties = {};
1457
+ if (!this.isMonolith) {
1458
+ properties.projectPath = {
1459
+ type: "string",
1460
+ description: "Absolute path to the project directory (for monorepo: containing project.json; for monolith: workspace root with toolkit.yaml). Either projectPath or templateName is required."
1461
+ };
1462
+ properties.templateName = {
1463
+ type: "string",
1464
+ description: "Name of the template to list scaffolding methods for (e.g., \"nextjs-15\", \"typescript-mcp-package\"). Either projectPath or templateName is required."
1465
+ };
1466
+ }
1448
1467
  return {
1449
1468
  name: ListScaffoldingMethodsTool.TOOL_NAME,
1450
- description: `Lists all available scaffolding methods (features) that can be added to an existing project.
1451
-
1452
- This tool:
1453
- - Reads the project's sourceTemplate from project.json (monorepo) or toolkit.yaml (monolith)
1454
- - Returns available features for that template type
1455
- - Provides variable schemas for each scaffolding method
1456
- - Shows descriptions of what each method creates
1457
-
1458
- Use this FIRST when adding features to existing projects to understand:
1459
- - What scaffolding methods are available
1460
- - What variables each method requires
1461
- - What files/features will be generated
1462
-
1463
- Example methods might include:
1464
- - Adding new React routes (for React apps)
1465
- - Creating API endpoints (for backend projects)
1466
- - Adding new components (for frontend projects)
1467
- - Setting up database models (for API projects)`,
1469
+ description: description.trim(),
1468
1470
  inputSchema: {
1469
1471
  type: "object",
1470
- properties: { projectPath: {
1471
- type: "string",
1472
- description: "Absolute path to the project directory (for monorepo: containing project.json; for monolith: workspace root with toolkit.yaml)"
1473
- } },
1474
- required: ["projectPath"],
1472
+ properties,
1475
1473
  additionalProperties: false
1476
1474
  }
1477
1475
  };
@@ -1481,9 +1479,19 @@ Example methods might include:
1481
1479
  */
1482
1480
  async execute(args) {
1483
1481
  try {
1484
- const { projectPath } = args;
1485
- if (!projectPath) throw new Error("Missing required parameter: projectPath");
1486
- const result = await this.scaffoldingMethodsService.listScaffoldingMethods(projectPath);
1482
+ const { projectPath, templateName } = args;
1483
+ let result;
1484
+ if (this.isMonolith) try {
1485
+ const resolvedTemplateName = (await __agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(process.cwd())).sourceTemplate;
1486
+ result = await this.scaffoldingMethodsService.listScaffoldingMethodsByTemplate(resolvedTemplateName);
1487
+ } catch (error) {
1488
+ throw new Error(`Failed to read template name from configuration: ${error instanceof Error ? error.message : String(error)}`);
1489
+ }
1490
+ else {
1491
+ if (!projectPath && !templateName) throw new Error("Either projectPath or templateName must be provided");
1492
+ if (projectPath) result = await this.scaffoldingMethodsService.listScaffoldingMethods(projectPath);
1493
+ else result = await this.scaffoldingMethodsService.listScaffoldingMethodsByTemplate(templateName);
1494
+ }
1487
1495
  return { content: [{
1488
1496
  type: "text",
1489
1497
  text: JSON.stringify(result, null, 2)
@@ -1500,57 +1508,48 @@ Example methods might include:
1500
1508
  }
1501
1509
  };
1502
1510
 
1511
+ //#endregion
1512
+ //#region src/instructions/tools/use-boilerplate/description.md?raw
1513
+ var description_default = "{% if isMonolith %}\nThis tool is not available for monolith projects.\n\nMonolith projects use a single template specified in `toolkit.yaml` (sourceTemplate field). The template cannot be changed through this tool - it's determined by the workspace configuration.\n\nUse `list-scaffolding-methods` and `use-scaffold-method` to add features to your monolith project instead.\n{% else %}\nCreates a new project from a boilerplate template with the specified variables.\n\n**For Monorepo Projects Only:**\nThis tool creates new sub-projects (apps, packages) in your monorepo. Each project can use a different template.\n\nThis tool will:\n- Generate all necessary files from the selected boilerplate template\n- Replace template variables with provided values\n- Create the project in targetFolder/projectName (e.g., apps/my-new-app)\n- Set up initial configuration files (package.json, tsconfig.json, etc.)\n- Create project.json with sourceTemplate reference\n\nIMPORTANT:\n- Always call `list-boilerplates` first to get the exact variable schema\n- Follow the schema exactly - required fields must be provided\n- Use kebab-case for project names (e.g., \"my-new-app\", not \"MyNewApp\")\n- The tool will validate all variables against the schema before proceeding\n- Each new project can use a different boilerplate template\n{% endif %}\n";
1514
+
1503
1515
  //#endregion
1504
1516
  //#region src/tools/UseBoilerplateTool.ts
1505
1517
  var UseBoilerplateTool = class UseBoilerplateTool {
1506
1518
  static TOOL_NAME = "use-boilerplate";
1507
1519
  boilerplateService;
1508
- constructor(templatesPath) {
1520
+ templateService;
1521
+ isMonolith;
1522
+ constructor(templatesPath, isMonolith = false) {
1509
1523
  this.boilerplateService = new BoilerplateService(templatesPath);
1524
+ this.templateService = new require_TemplateService.TemplateService();
1525
+ this.isMonolith = isMonolith;
1510
1526
  }
1511
1527
  /**
1512
1528
  * Get the tool definition for MCP
1513
1529
  */
1514
1530
  getDefinition() {
1531
+ const description = this.templateService.renderString(description_default, { isMonolith: this.isMonolith });
1532
+ const properties = { variables: {
1533
+ type: "object",
1534
+ description: "Variables object matching the boilerplate's variables_schema exactly"
1535
+ } };
1536
+ if (!this.isMonolith) {
1537
+ properties.boilerplateName = {
1538
+ type: "string",
1539
+ description: "Exact name of the boilerplate to use (from list-boilerplates response)"
1540
+ };
1541
+ properties.targetFolderOverride = {
1542
+ type: "string",
1543
+ description: "Optional override for target folder. If not provided, uses boilerplate targetFolder (monorepo) or workspace root (monolith)"
1544
+ };
1545
+ }
1515
1546
  return {
1516
1547
  name: UseBoilerplateTool.TOOL_NAME,
1517
- description: `Creates a new project from a boilerplate template with the specified variables.
1518
-
1519
- This tool will:
1520
- - Generate all necessary files from the template
1521
- - Replace template variables with provided values
1522
- - Create the project in the appropriate directory (monorepo or monolith)
1523
- - Set up initial configuration files (package.json, tsconfig.json, etc.)
1524
- - Create toolkit.yaml (monolith) or project.json (monorepo) with sourceTemplate
1525
-
1526
- IMPORTANT:
1527
- - Always call \`list-boilerplates\` first to get the exact variable schema
1528
- - Follow the schema exactly - required fields must be provided
1529
- - Use kebab-case for project names (e.g., "my-new-app", not "MyNewApp")
1530
- - The tool will validate all variables against the schema before proceeding
1531
- - For monolith projects, use monolith: true to create at workspace root
1532
- - For monorepo projects, files are created in targetFolder/projectName`,
1548
+ description: description.trim(),
1533
1549
  inputSchema: {
1534
1550
  type: "object",
1535
- properties: {
1536
- boilerplateName: {
1537
- type: "string",
1538
- description: "Exact name of the boilerplate to use (from list-boilerplates response)"
1539
- },
1540
- variables: {
1541
- type: "object",
1542
- description: "Variables object matching the boilerplate's variables_schema exactly"
1543
- },
1544
- monolith: {
1545
- type: "boolean",
1546
- description: "If true, creates project at workspace root with toolkit.yaml. If false or omitted, creates in targetFolder/projectName with project.json (monorepo mode)"
1547
- },
1548
- targetFolderOverride: {
1549
- type: "string",
1550
- description: "Optional override for target folder. If not provided, uses boilerplate targetFolder (monorepo) or workspace root (monolith)"
1551
- }
1552
- },
1553
- required: ["boilerplateName", "variables"],
1551
+ properties,
1552
+ required: this.isMonolith ? ["variables"] : ["boilerplateName", "variables"],
1554
1553
  additionalProperties: false
1555
1554
  }
1556
1555
  };
@@ -1560,14 +1559,12 @@ IMPORTANT:
1560
1559
  */
1561
1560
  async execute(args) {
1562
1561
  try {
1563
- const { boilerplateName, variables, monolith, targetFolderOverride } = args;
1564
- if (!boilerplateName) throw new Error("Missing required parameter: boilerplateName");
1565
- if (!variables) throw new Error("Missing required parameter: variables");
1562
+ const { boilerplateName, variables, targetFolderOverride } = args;
1566
1563
  const request = {
1567
1564
  boilerplateName,
1568
1565
  variables,
1569
- monolith,
1570
- targetFolderOverride
1566
+ targetFolderOverride,
1567
+ monolith: this.isMonolith
1571
1568
  };
1572
1569
  return { content: [{
1573
1570
  type: "text",
@@ -1600,14 +1597,30 @@ var UseScaffoldMethodTool = class UseScaffoldMethodTool {
1600
1597
  static TOOL_NAME = "use-scaffold-method";
1601
1598
  fileSystemService;
1602
1599
  scaffoldingMethodsService;
1603
- constructor(templatesPath) {
1600
+ isMonolith;
1601
+ constructor(templatesPath, isMonolith = false) {
1604
1602
  this.fileSystemService = new FileSystemService();
1605
1603
  this.scaffoldingMethodsService = new ScaffoldingMethodsService(this.fileSystemService, templatesPath);
1604
+ this.isMonolith = isMonolith;
1606
1605
  }
1607
1606
  /**
1608
1607
  * Get the tool definition for MCP
1609
1608
  */
1610
1609
  getDefinition() {
1610
+ const properties = {
1611
+ scaffold_feature_name: {
1612
+ type: "string",
1613
+ description: "Exact name of the scaffold method to use (from list-scaffolding-methods response)"
1614
+ },
1615
+ variables: {
1616
+ type: "object",
1617
+ description: "Variables object matching the scaffold method's variables_schema exactly"
1618
+ }
1619
+ };
1620
+ if (!this.isMonolith) properties.projectPath = {
1621
+ type: "string",
1622
+ description: "Absolute path to the project directory (for monorepo: containing project.json; for monolith: workspace root with toolkit.yaml)"
1623
+ };
1611
1624
  return {
1612
1625
  name: UseScaffoldMethodTool.TOOL_NAME,
1613
1626
  description: `Generates and adds a specific feature to an existing project using a scaffolding method.
@@ -1627,21 +1640,8 @@ IMPORTANT:
1627
1640
  `,
1628
1641
  inputSchema: {
1629
1642
  type: "object",
1630
- properties: {
1631
- projectPath: {
1632
- type: "string",
1633
- description: "Absolute path to the project directory (for monorepo: containing project.json; for monolith: workspace root with toolkit.yaml)"
1634
- },
1635
- scaffold_feature_name: {
1636
- type: "string",
1637
- description: "Exact name of the scaffold method to use (from list-scaffolding-methods response)"
1638
- },
1639
- variables: {
1640
- type: "object",
1641
- description: "Variables object matching the scaffold method's variables_schema exactly"
1642
- }
1643
- },
1644
- required: [
1643
+ properties,
1644
+ required: this.isMonolith ? ["scaffold_feature_name", "variables"] : [
1645
1645
  "projectPath",
1646
1646
  "scaffold_feature_name",
1647
1647
  "variables"
@@ -1656,13 +1656,11 @@ IMPORTANT:
1656
1656
  async execute(args) {
1657
1657
  try {
1658
1658
  const { projectPath, scaffold_feature_name, variables } = args;
1659
- if (!projectPath) throw new Error("Missing required parameter: projectPath");
1660
- if (!scaffold_feature_name) throw new Error("Missing required parameter: scaffold_feature_name");
1661
- if (!variables) throw new Error("Missing required parameter: variables");
1659
+ const resolvedProjectPath = this.isMonolith ? process.cwd() : projectPath;
1662
1660
  return { content: [{
1663
1661
  type: "text",
1664
1662
  text: `${(await this.scaffoldingMethodsService.useScaffoldMethod({
1665
- projectPath,
1663
+ projectPath: resolvedProjectPath,
1666
1664
  scaffold_feature_name,
1667
1665
  variables
1668
1666
  })).message}
@@ -2177,34 +2175,4 @@ Object.defineProperty(exports, 'WriteToFileTool', {
2177
2175
  get: function () {
2178
2176
  return WriteToFileTool;
2179
2177
  }
2180
- });
2181
- Object.defineProperty(exports, 'cloneRepository', {
2182
- enumerable: true,
2183
- get: function () {
2184
- return cloneRepository;
2185
- }
2186
- });
2187
- Object.defineProperty(exports, 'cloneSubdirectory', {
2188
- enumerable: true,
2189
- get: function () {
2190
- return cloneSubdirectory;
2191
- }
2192
- });
2193
- Object.defineProperty(exports, 'fetchGitHubDirectoryContents', {
2194
- enumerable: true,
2195
- get: function () {
2196
- return fetchGitHubDirectoryContents;
2197
- }
2198
- });
2199
- Object.defineProperty(exports, 'findWorkspaceRoot', {
2200
- enumerable: true,
2201
- get: function () {
2202
- return findWorkspaceRoot;
2203
- }
2204
- });
2205
- Object.defineProperty(exports, 'parseGitHubUrl', {
2206
- enumerable: true,
2207
- get: function () {
2208
- return parseGitHubUrl;
2209
- }
2210
2178
  });