Skip to content

Commit 8759166

Browse files
committed
feat: add Lightning Component Generation tool with customizable templates and output directory
1 parent b9920d5 commit 8759166

File tree

4 files changed

+116
-2
lines changed

4 files changed

+116
-2
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.3.2] - 2025-08-31
9+
10+
### Added
11+
12+
- **Lightning Component Generation**: New tool for generating Lightning Web Components (LWC) and Aura components
13+
- `generate_component` - Generate Lightning component bundles with metadata
14+
- Supports both LWC and Aura component types
15+
- Configurable templates (default, analyticsDashboard, analyticsDashboardWithStep)
16+
- Custom output directory support with default fallback to current directory
17+
- Respects READ_ONLY permissions
18+
819
## [1.3.1] - 2025-08-21
920

1021
### Fixed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@advanced-communities/salesforce-mcp-server",
3-
"version": "1.3.1",
3+
"version": "1.3.2",
44
"description": "MCP server enabling AI assistants to interact with Salesforce orgs through the Salesforce CLI",
55
"main": "./src/index.ts",
66
"scripts": {

src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { registerScannerTools } from "./tools/scanner.js";
1212
import { registerPackageTools } from "./tools/package.js";
1313
import { registerSchemaTools } from "./tools/schema.js";
1414
import { registerSearchTools } from "./tools/search.js";
15+
import { registerLightningTools } from "./tools/lightning.js";
1516
import { permissions } from "./config/permissions.js";
1617

1718
/**
@@ -23,7 +24,7 @@ function buildServerDescription(): string {
2324
const allowedOrgs = permissions.getAllowedOrgs();
2425
const permissionInfo = [];
2526

26-
let description = `Salesforce MCP Server v1.3.0 - AI-powered Salesforce automation via CLI integration\n`;
27+
let description = `Salesforce MCP Server v1.3.2 - AI-powered Salesforce automation via CLI integration\n`;
2728
description += `Capabilities: Apex execution, SOQL queries, org management, code testing & coverage\n`;
2829

2930
if (readOnlyMode) {
@@ -65,6 +66,7 @@ registerScannerTools(server);
6566
registerPackageTools(server);
6667
registerSchemaTools(server);
6768
registerSearchTools(server);
69+
registerLightningTools(server);
6870

6971
async function main() {
7072
const transport = new StdioServerTransport();

src/tools/lightning.ts

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import { z } from "zod";
2+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3+
import { getConnection } from "../shared/connection.js";
4+
import { permissions } from "../config/permissions.js";
5+
import { executeSfCommand, executeSfCommandRaw } from "../utils/sfCommand.js";
6+
7+
const generateComponent = async (
8+
name: string,
9+
template: string,
10+
outputDirectory: string,
11+
type: string,
12+
) => {
13+
let sfCommand = `sf lightning generate component --name ${name} --json `;
14+
15+
if (template && template.length > 0) {
16+
sfCommand += `--template ${template} `;
17+
}
18+
19+
if (outputDirectory && outputDirectory.length > 0) {
20+
sfCommand += `--output-dir ${outputDirectory} `;
21+
}
22+
23+
if (type && type.length > 0) {
24+
sfCommand += `--type ${type}`;
25+
}
26+
27+
try {
28+
const result = await executeSfCommand(sfCommand);
29+
return result;
30+
} catch (error) {
31+
throw error;
32+
}
33+
};
34+
35+
export const registerLightningTools = (server: McpServer) => {
36+
server.tool(
37+
"generate_component",
38+
"",
39+
{
40+
input: z.object({
41+
name: z
42+
.string()
43+
.describe(
44+
"Name of the generated Lightning Component. The name can be up to 40 characters and must start with a letter.",
45+
),
46+
template: z
47+
.string()
48+
.optional()
49+
.describe(
50+
"Template to use for file creation. Supplied parameter values or default values are filled into a copy of the template. Permissible values are: default, analyticsDashboard, analyticsDashboardWithStep. Default value: default",
51+
),
52+
outputDirectory: z
53+
.string()
54+
.optional()
55+
.describe(
56+
"Directory for saving the created files. The location can be an absolute path or relative to the current working directory. The default is the current directory. Default value: .",
57+
),
58+
type: z
59+
.string()
60+
.optional()
61+
.describe(
62+
"Type of the component bundle. Permissible values are: aura, lwc (lightning web component). Default value: aura",
63+
),
64+
}),
65+
},
66+
async ({ input }) => {
67+
const { name, template, outputDirectory, type } = input;
68+
const DEFAULT_OUTPUT = ".";
69+
if (permissions.isReadOnly()) {
70+
return {
71+
content: [
72+
{
73+
type: "text",
74+
text: JSON.stringify({
75+
success: false,
76+
compiled: false,
77+
compileProblem:
78+
"Operation not allowed: Cannot generate components in READ_ONLY mode",
79+
}),
80+
},
81+
],
82+
};
83+
}
84+
85+
const result = await generateComponent(
86+
name,
87+
template || "",
88+
outputDirectory || DEFAULT_OUTPUT,
89+
type || "",
90+
);
91+
return {
92+
content: [
93+
{
94+
type: "text",
95+
text: JSON.stringify(result),
96+
},
97+
],
98+
};
99+
},
100+
);
101+
};

0 commit comments

Comments
 (0)