@salesforce/mcp 0.14.3 → 0.15.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/README.md +8 -7
- package/lib/index.js +3 -0
- package/lib/shared/params.js +1 -1
- package/lib/tools/core/sf-resume.js +29 -1
- package/lib/tools/orgs/index.d.ts +3 -0
- package/lib/tools/orgs/index.js +3 -0
- package/lib/tools/orgs/sf-create-org-snapshot.d.ts +23 -0
- package/lib/tools/orgs/sf-create-org-snapshot.js +88 -0
- package/lib/tools/orgs/sf-create-scratch-org.d.ts +50 -0
- package/lib/tools/orgs/sf-create-scratch-org.js +132 -0
- package/lib/tools/orgs/sf-delete-org.d.ts +14 -0
- package/lib/tools/orgs/sf-delete-org.js +65 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -55,6 +55,7 @@ But you're not limited to using only VS Code and Copilot! You can [configure man
|
|
|
55
55
|
|
|
56
56
|
For the best getting-started experience, make sure that you have a Salesforce DX environment set up on your computer. In particular:
|
|
57
57
|
|
|
58
|
+
- [Install Salesforce CLI](https://developer.salesforce.com/docs/atlas.en-us.sfdx_setup.meta/sfdx_setup/sfdx_setup_intro.htm) on your computer.
|
|
58
59
|
- [Install VS Code](https://code.visualstudio.com/docs) on your computer.
|
|
59
60
|
- [Create a Salesforce DX project](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_ws_create_new.htm) and open it in VS Code. You can also clone an example repo, such as [dreamhouse-lwc](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_intro_sample_repo.htm), which is a ready-to-use DX project that contains a simple Salesforce application, with metadata and test data.
|
|
60
61
|
- [Authorize at least one Salesforce org](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_auth_web_flow.htm) to use with your DX project. You can also create a scratch org.
|
|
@@ -66,7 +67,7 @@ For the best getting-started experience, make sure that you have a Salesforce DX
|
|
|
66
67
|
```json
|
|
67
68
|
{
|
|
68
69
|
"servers": {
|
|
69
|
-
"
|
|
70
|
+
"Salesforce DX": {
|
|
70
71
|
"type": "stdio",
|
|
71
72
|
"command": "npx",
|
|
72
73
|
"args": ["-y", "@salesforce/mcp", "--orgs", "DEFAULT_TARGET_ORG", "--toolsets", "all"]
|
|
@@ -83,7 +84,7 @@ For the best getting-started experience, make sure that you have a Salesforce DX
|
|
|
83
84
|
|
|
84
85
|
TIP: You can also get to the command palette by pressing press Ctrl+Shift+P (Windows or Linux) or Command-Shift-P (macOS).
|
|
85
86
|
|
|
86
|
-
1. Click `
|
|
87
|
+
1. Click `Salesforce DX`, then **Start Server**.
|
|
87
88
|
|
|
88
89
|
Check the Output tab for the server status.
|
|
89
90
|
|
|
@@ -100,7 +101,7 @@ For the best getting-started experience, make sure that you have a Salesforce DX
|
|
|
100
101
|
- Show me all the accounts in the org with alias my-org.
|
|
101
102
|
- Deploy everything in my project to the org with alias my-org.
|
|
102
103
|
|
|
103
|
-
1. To stop, restart, or view the MCP server configuration, run the **MCP: List Servers** command, click `
|
|
104
|
+
1. To stop, restart, or view the MCP server configuration, run the **MCP: List Servers** command, click `Salesforce DX`, then click the appropriate option.
|
|
104
105
|
|
|
105
106
|
## Configure Orgs and Toolsets
|
|
106
107
|
|
|
@@ -124,7 +125,7 @@ This example shows how to specify that the MCP tools run against your default or
|
|
|
124
125
|
```json
|
|
125
126
|
"mcp": {
|
|
126
127
|
"servers": {
|
|
127
|
-
"
|
|
128
|
+
"Salesforce DX": {
|
|
128
129
|
"type": "stdio",
|
|
129
130
|
"command": "npx",
|
|
130
131
|
"args": ["-y", "@salesforce/mcp", "--orgs", "DEFAULT_TARGET_ORG"]
|
|
@@ -165,7 +166,7 @@ This example shows how to enable the `data`, `orgs`, and `metadata` toolsets whe
|
|
|
165
166
|
```json
|
|
166
167
|
"mcp": {
|
|
167
168
|
"servers": {
|
|
168
|
-
"
|
|
169
|
+
"Salesforce DX": {
|
|
169
170
|
"type": "stdio",
|
|
170
171
|
"command": "npx",
|
|
171
172
|
"args": ["-y", "@salesforce/mcp", "--orgs", "DEFAULT_TARGET_ORG", "--toolsets", "data,orgs,metadata"]
|
|
@@ -228,7 +229,7 @@ To configure [Cursor](https://www.cursor.com/) to work with Salesforce DX MCP Se
|
|
|
228
229
|
```json
|
|
229
230
|
{
|
|
230
231
|
"mcpServers": {
|
|
231
|
-
"
|
|
232
|
+
"Salesforce DX": {
|
|
232
233
|
"command": "npx",
|
|
233
234
|
"args": ["-y", "@salesforce/mcp", "--orgs", "DEFAULT_TARGET_ORG", "--toolsets", "all"]
|
|
234
235
|
}
|
|
@@ -243,7 +244,7 @@ To configure [Cline](https://cline.bot), add this snippet to your Cline `cline_m
|
|
|
243
244
|
```json
|
|
244
245
|
{
|
|
245
246
|
"mcpServers": {
|
|
246
|
-
"
|
|
247
|
+
"Salesforce DX": {
|
|
247
248
|
"command": "npx",
|
|
248
249
|
"args": ["-y", "@salesforce/mcp", "--orgs", "DEFAULT_TARGET_ORG", "--toolsets", "all"]
|
|
249
250
|
}
|
package/lib/index.js
CHANGED
|
@@ -210,6 +210,9 @@ You can also use special values to control access to orgs:
|
|
|
210
210
|
this.logToStderr('Registering experimental tools');
|
|
211
211
|
orgs.registerToolOrgOpen(server);
|
|
212
212
|
// Add any experimental tools here
|
|
213
|
+
orgs.registerToolCreateScratchOrg(server);
|
|
214
|
+
orgs.registerToolDeleteOrg(server);
|
|
215
|
+
orgs.registerToolCreateOrgSnapshot(server);
|
|
213
216
|
}
|
|
214
217
|
const transport = new StdioServerTransport();
|
|
215
218
|
await server.connect(transport);
|
package/lib/shared/params.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import { z } from 'zod';
|
|
17
17
|
import { sanitizePath } from './utils.js';
|
|
18
18
|
/*
|
|
19
|
-
* A collection of
|
|
19
|
+
* A collection of reusable Tool parameters
|
|
20
20
|
*/
|
|
21
21
|
export const usernameOrAliasParam = z.string()
|
|
22
22
|
.describe(`The username or alias for the Salesforce org to run this tool against.
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { z } from 'zod';
|
|
17
17
|
import { AgentTester } from '@salesforce/agents';
|
|
18
|
-
import { validateSalesforceId, scratchOrgResume } from '@salesforce/core';
|
|
18
|
+
import { validateSalesforceId, scratchOrgResume, PollingClient } from '@salesforce/core';
|
|
19
19
|
import { Duration } from '@salesforce/kit';
|
|
20
20
|
import { MetadataApiDeploy } from '@salesforce/source-deploy-retrieve';
|
|
21
21
|
import { textResponse } from '../../shared/utils.js';
|
|
@@ -25,6 +25,7 @@ const resumableIdPrefixes = new Map([
|
|
|
25
25
|
['deploy', '0Af'],
|
|
26
26
|
['scratchOrg', '2SR'],
|
|
27
27
|
['agentTest', '4KB'],
|
|
28
|
+
['orgSnapshot', '0Oo'],
|
|
28
29
|
]);
|
|
29
30
|
/*
|
|
30
31
|
* Resume a long running operation that was not completed by another tool.
|
|
@@ -63,6 +64,8 @@ Resume the deployment to my org
|
|
|
63
64
|
Resume scratch org creation
|
|
64
65
|
Resume job 2SR1234567890
|
|
65
66
|
Resume agent tests
|
|
67
|
+
Resume org snapshot with ID 0OoKa000000XZAbKAO
|
|
68
|
+
Report on my org snapshot
|
|
66
69
|
`, resumeParamsSchema.shape, {
|
|
67
70
|
title: 'Resume',
|
|
68
71
|
openWorldHint: false,
|
|
@@ -84,6 +87,8 @@ Resume agent tests
|
|
|
84
87
|
return resumeScratchOrg(jobId, wait);
|
|
85
88
|
case resumableIdPrefixes.get('agentTest'):
|
|
86
89
|
return resumeAgentTest(connection, jobId, wait);
|
|
90
|
+
case resumableIdPrefixes.get('orgSnapshot'):
|
|
91
|
+
return resumeOrgSnapshot(connection, jobId, wait);
|
|
87
92
|
default:
|
|
88
93
|
return textResponse(`The job id: ${jobId} is not resumeable.`, true);
|
|
89
94
|
}
|
|
@@ -99,6 +104,29 @@ async function resumeDeployment(connection, jobId, wait) {
|
|
|
99
104
|
return textResponse(`Resumed deployment failed: ${error instanceof Error ? error.message : 'Unknown error'}`, true);
|
|
100
105
|
}
|
|
101
106
|
}
|
|
107
|
+
async function resumeOrgSnapshot(connection, jobId, wait) {
|
|
108
|
+
try {
|
|
109
|
+
const poller = await PollingClient.create({
|
|
110
|
+
timeout: Duration.minutes(wait),
|
|
111
|
+
frequency: Duration.seconds(30),
|
|
112
|
+
poll: async () => {
|
|
113
|
+
const queryResult = await connection.singleRecordQuery(`SELECT Status, Id, SnapshotName, Description, ExpirationDate, CreatedDate FROM OrgSnapshot WHERE Id = '${jobId}'`);
|
|
114
|
+
if (queryResult.Status !== 'In Progress') {
|
|
115
|
+
// either done or error
|
|
116
|
+
return { completed: true, payload: queryResult };
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
return { completed: false };
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
const result = await poller.subscribe();
|
|
124
|
+
return textResponse(`Org snapshot: ${JSON.stringify(result)}`);
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
return textResponse(`Resumed org snapshot failed: ${error instanceof Error ? error.message : 'Unknown error'}`, true);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
102
130
|
async function resumeScratchOrg(jobId, wait) {
|
|
103
131
|
try {
|
|
104
132
|
const result = await scratchOrgResume(jobId, Duration.minutes(wait));
|
package/lib/tools/orgs/index.js
CHANGED
|
@@ -14,5 +14,8 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
export * from './sf-list-all-orgs.js';
|
|
17
|
+
export * from './sf-delete-org.js';
|
|
18
|
+
export * from './sf-create-scratch-org.js';
|
|
19
|
+
export * from './sf-create-org-snapshot.js';
|
|
17
20
|
export * from './sf-org-open.js';
|
|
18
21
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
export declare const createOrgSnapshotParams: z.ZodObject<{
|
|
4
|
+
directory: z.ZodEffects<z.ZodString, string, string>;
|
|
5
|
+
devHub: z.ZodString;
|
|
6
|
+
sourceOrg: z.ZodString;
|
|
7
|
+
description: z.ZodOptional<z.ZodString>;
|
|
8
|
+
name: z.ZodDefault<z.ZodString>;
|
|
9
|
+
}, "strip", z.ZodTypeAny, {
|
|
10
|
+
name: string;
|
|
11
|
+
directory: string;
|
|
12
|
+
devHub: string;
|
|
13
|
+
sourceOrg: string;
|
|
14
|
+
description?: string | undefined;
|
|
15
|
+
}, {
|
|
16
|
+
directory: string;
|
|
17
|
+
devHub: string;
|
|
18
|
+
sourceOrg: string;
|
|
19
|
+
description?: string | undefined;
|
|
20
|
+
name?: string | undefined;
|
|
21
|
+
}>;
|
|
22
|
+
export type CreateOrgSnapshotOptions = z.infer<typeof createOrgSnapshotParams>;
|
|
23
|
+
export declare const registerToolCreateOrgSnapshot: (server: McpServer) => void;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025, Salesforce, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { z } from 'zod';
|
|
17
|
+
import { Org } from '@salesforce/core';
|
|
18
|
+
import { textResponse } from '../../shared/utils.js';
|
|
19
|
+
import { directoryParam, usernameOrAliasParam } from '../../shared/params.js';
|
|
20
|
+
import { getConnection } from '../../shared/auth.js';
|
|
21
|
+
/*
|
|
22
|
+
* Create a new scratch org snapshot
|
|
23
|
+
*
|
|
24
|
+
* Parameters:
|
|
25
|
+
* - directory: directory to change to before running the command
|
|
26
|
+
* - devHub: Username or alias of the Dev Hub org
|
|
27
|
+
* - sourceOrg: ID or locally authenticated username or alias of scratch org to snapshot.
|
|
28
|
+
* - description: a description given to the snapshot
|
|
29
|
+
* - name: Unique name of snapshot
|
|
30
|
+
* Returns:
|
|
31
|
+
* - textResponse:
|
|
32
|
+
*/
|
|
33
|
+
export const createOrgSnapshotParams = z.object({
|
|
34
|
+
directory: directoryParam,
|
|
35
|
+
devHub: usernameOrAliasParam.describe('The default devhub username, use the #sf-get-username tool to get the default devhub if unsure'),
|
|
36
|
+
sourceOrg: usernameOrAliasParam.describe('The org username or alias to create a snapshot of, use the #sf-get-username tool to get the default target org if unsure'),
|
|
37
|
+
description: z.string().describe(' Description of snapshot.').optional(),
|
|
38
|
+
name: z.string().describe('Unique name of snapshot').max(15).default(Date.now().toString().substring(0, 15)),
|
|
39
|
+
});
|
|
40
|
+
export const registerToolCreateOrgSnapshot = (server) => {
|
|
41
|
+
server.tool('sf-create-org-snapshot', `Creates a new snapshot of an org
|
|
42
|
+
|
|
43
|
+
AGENT INSTRUCTIONS:
|
|
44
|
+
|
|
45
|
+
Example usage:
|
|
46
|
+
Create a snapshot called 07042025
|
|
47
|
+
create a snapshot called 07042025 with the description, "this is a snapshot for commit 5b1a09b1743 - new login flow working"
|
|
48
|
+
create a snapshot of my MyScratch in myDevHub
|
|
49
|
+
`, createOrgSnapshotParams.shape, {
|
|
50
|
+
title: 'Create a new snapshot',
|
|
51
|
+
}, async ({ directory, devHub, description, name, sourceOrg }) => {
|
|
52
|
+
try {
|
|
53
|
+
process.chdir(directory);
|
|
54
|
+
const sourceOrgId = (await Org.create({ aliasOrUsername: sourceOrg })).getOrgId();
|
|
55
|
+
const devHubConnection = await getConnection(devHub);
|
|
56
|
+
const createResponse = await devHubConnection.sobject('OrgSnapshot').create({
|
|
57
|
+
SourceOrg: sourceOrgId,
|
|
58
|
+
Description: description,
|
|
59
|
+
SnapshotName: name,
|
|
60
|
+
Content: 'metadatadata',
|
|
61
|
+
});
|
|
62
|
+
if (createResponse.success === false) {
|
|
63
|
+
return textResponse(`An error while created the org snapshot: ${JSON.stringify(createResponse)}`, true);
|
|
64
|
+
}
|
|
65
|
+
const result = await devHubConnection.singleRecordQuery(`SELECT Id,
|
|
66
|
+
SnapshotName,
|
|
67
|
+
Description,
|
|
68
|
+
Status,
|
|
69
|
+
SourceOrg,
|
|
70
|
+
CreatedDate,
|
|
71
|
+
LastModifiedDate,
|
|
72
|
+
ExpirationDate,
|
|
73
|
+
Error FROM OrgSnapshot WHERE Id = '${createResponse.id}'`);
|
|
74
|
+
return textResponse(`Successfully created the org snapshot: ${JSON.stringify(result)}`);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
const e = error;
|
|
78
|
+
// dev hub does not have snapshot pref enabled
|
|
79
|
+
if (e.name === 'NOT_FOUND') {
|
|
80
|
+
return textResponse("Scratch Org Snapshots isn't enabled for your Dev Hub.", true);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
return textResponse(`Error: ${e.name} : ${e.message}`, true);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=sf-create-org-snapshot.js.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
export declare const createScratchOrgParams: z.ZodObject<{
|
|
4
|
+
directory: z.ZodEffects<z.ZodString, string, string>;
|
|
5
|
+
devHub: z.ZodString;
|
|
6
|
+
duration: z.ZodDefault<z.ZodNumber>;
|
|
7
|
+
edition: z.ZodOptional<z.ZodEnum<["developer", "enterprise", "group", "professional", "partner-developer", "partner-enterprise", "partner-group", "partner-professional"]>>;
|
|
8
|
+
definitionFile: z.ZodDefault<z.ZodString>;
|
|
9
|
+
alias: z.ZodOptional<z.ZodString>;
|
|
10
|
+
async: z.ZodDefault<z.ZodBoolean>;
|
|
11
|
+
setDefault: z.ZodOptional<z.ZodBoolean>;
|
|
12
|
+
snapshot: z.ZodOptional<z.ZodString>;
|
|
13
|
+
sourceOrg: z.ZodOptional<z.ZodString>;
|
|
14
|
+
username: z.ZodOptional<z.ZodString>;
|
|
15
|
+
description: z.ZodOptional<z.ZodString>;
|
|
16
|
+
orgName: z.ZodOptional<z.ZodString>;
|
|
17
|
+
adminEmail: z.ZodOptional<z.ZodString>;
|
|
18
|
+
}, "strip", z.ZodTypeAny, {
|
|
19
|
+
duration: number;
|
|
20
|
+
async: boolean;
|
|
21
|
+
directory: string;
|
|
22
|
+
devHub: string;
|
|
23
|
+
definitionFile: string;
|
|
24
|
+
description?: string | undefined;
|
|
25
|
+
alias?: string | undefined;
|
|
26
|
+
snapshot?: string | undefined;
|
|
27
|
+
setDefault?: boolean | undefined;
|
|
28
|
+
username?: string | undefined;
|
|
29
|
+
edition?: "group" | "enterprise" | "developer" | "professional" | "partner-developer" | "partner-enterprise" | "partner-group" | "partner-professional" | undefined;
|
|
30
|
+
sourceOrg?: string | undefined;
|
|
31
|
+
orgName?: string | undefined;
|
|
32
|
+
adminEmail?: string | undefined;
|
|
33
|
+
}, {
|
|
34
|
+
directory: string;
|
|
35
|
+
devHub: string;
|
|
36
|
+
duration?: number | undefined;
|
|
37
|
+
description?: string | undefined;
|
|
38
|
+
alias?: string | undefined;
|
|
39
|
+
async?: boolean | undefined;
|
|
40
|
+
snapshot?: string | undefined;
|
|
41
|
+
setDefault?: boolean | undefined;
|
|
42
|
+
username?: string | undefined;
|
|
43
|
+
edition?: "group" | "enterprise" | "developer" | "professional" | "partner-developer" | "partner-enterprise" | "partner-group" | "partner-professional" | undefined;
|
|
44
|
+
definitionFile?: string | undefined;
|
|
45
|
+
sourceOrg?: string | undefined;
|
|
46
|
+
orgName?: string | undefined;
|
|
47
|
+
adminEmail?: string | undefined;
|
|
48
|
+
}>;
|
|
49
|
+
export type CreateScratchOrgOptions = z.infer<typeof createScratchOrgParams>;
|
|
50
|
+
export declare const registerToolCreateScratchOrg: (server: McpServer) => void;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025, Salesforce, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { join } from 'node:path';
|
|
17
|
+
import * as fs from 'node:fs';
|
|
18
|
+
import { z } from 'zod';
|
|
19
|
+
import { Org, scratchOrgCreate } from '@salesforce/core';
|
|
20
|
+
import { Duration } from '@salesforce/kit';
|
|
21
|
+
import { textResponse } from '../../shared/utils.js';
|
|
22
|
+
import { directoryParam, usernameOrAliasParam } from '../../shared/params.js';
|
|
23
|
+
/*
|
|
24
|
+
* Create a new scratch org
|
|
25
|
+
*
|
|
26
|
+
* Parameters:
|
|
27
|
+
* - directory: directory to change to before running the command
|
|
28
|
+
* - usernameOrAlias: Username or alias of the Salesforce DevHub org to use to create from
|
|
29
|
+
* - duration: Duration in days of the scratch org to exist, default 7
|
|
30
|
+
* - edition: Edition of the scratch org
|
|
31
|
+
* - definitionFile: path to the scratch org definition file, default config/project-scratch-def.json
|
|
32
|
+
* - alias: Alias to use for the scratch org
|
|
33
|
+
* - async: Wait for the scratch org creation process to finish, default false
|
|
34
|
+
* - setDefault: set the newly created org as default-target-org
|
|
35
|
+
* - snapshot: The snapshot name to use when creating a scratch org
|
|
36
|
+
* - sourceOrg: 15-character ID of the org shape that the new scratch org is based on
|
|
37
|
+
* - username: Username of the scratch org admin user
|
|
38
|
+
* - description: a description given to the scratch org
|
|
39
|
+
* - orgName: Name of the scratch org
|
|
40
|
+
* - adminEmail: Email address that will be applied to the org's admin user.
|
|
41
|
+
* Returns:
|
|
42
|
+
* - textResponse:
|
|
43
|
+
*/
|
|
44
|
+
export const createScratchOrgParams = z.object({
|
|
45
|
+
directory: directoryParam,
|
|
46
|
+
devHub: usernameOrAliasParam.describe('The default devhub username, use the #sf-get-username tool to get the default devhub if unsure'),
|
|
47
|
+
duration: z.number().default(7).describe('number of days before the org expires'),
|
|
48
|
+
edition: z
|
|
49
|
+
.enum([
|
|
50
|
+
'developer',
|
|
51
|
+
'enterprise',
|
|
52
|
+
'group',
|
|
53
|
+
'professional',
|
|
54
|
+
'partner-developer',
|
|
55
|
+
'partner-enterprise',
|
|
56
|
+
'partner-group',
|
|
57
|
+
'partner-professional',
|
|
58
|
+
])
|
|
59
|
+
.optional(),
|
|
60
|
+
definitionFile: z
|
|
61
|
+
.string()
|
|
62
|
+
.default(join('config', 'project-scratch-def.json'))
|
|
63
|
+
.describe('a normalized path to a scratch definition json file'),
|
|
64
|
+
alias: z.string().describe('the alias to be used for the scratch org').optional(),
|
|
65
|
+
async: z
|
|
66
|
+
.boolean()
|
|
67
|
+
.default(false)
|
|
68
|
+
.describe('Whether to wait for the org creation process to finish (false) or just quickly return the ID (true)'),
|
|
69
|
+
setDefault: z
|
|
70
|
+
.boolean()
|
|
71
|
+
.optional()
|
|
72
|
+
.describe('If true, will set the newly created scratch org to be the default-target-org'),
|
|
73
|
+
snapshot: z.string().describe('The snapshot name to use when creating a scratch org').optional(),
|
|
74
|
+
sourceOrg: z
|
|
75
|
+
.string()
|
|
76
|
+
.length(15)
|
|
77
|
+
.describe('15-character ID of the org shape that the new scratch org is based on')
|
|
78
|
+
.optional(),
|
|
79
|
+
username: z.string().describe('Username of the scratch org admin user').optional(),
|
|
80
|
+
description: z.string().describe('a description given to the scratch org').optional(),
|
|
81
|
+
orgName: z.string().describe('Name of the scratch org').optional(),
|
|
82
|
+
adminEmail: z.string().describe("Email address that will be applied to the org's admin user.").optional(),
|
|
83
|
+
});
|
|
84
|
+
export const registerToolCreateScratchOrg = (server) => {
|
|
85
|
+
server.tool('sf-create-scratch-org', `Creates a scratch org with the specified parameters.
|
|
86
|
+
|
|
87
|
+
AGENT INSTRUCTIONS:
|
|
88
|
+
|
|
89
|
+
Example usage:
|
|
90
|
+
Create a scratch org
|
|
91
|
+
create a scratch org with the definition file myDefinition.json that lasts 3 days
|
|
92
|
+
create a scratch org aliased as MyNewOrg and set as default and don't wait for it to finish
|
|
93
|
+
`, createScratchOrgParams.shape, {
|
|
94
|
+
title: 'Create a scratch org',
|
|
95
|
+
}, async ({ directory, devHub, orgName, adminEmail, description, snapshot, sourceOrg, username, edition, setDefault, async, duration, alias, definitionFile, }) => {
|
|
96
|
+
try {
|
|
97
|
+
process.chdir(directory);
|
|
98
|
+
const hubOrProd = await Org.create({ aliasOrUsername: devHub });
|
|
99
|
+
const requestParams = {
|
|
100
|
+
hubOrg: hubOrProd,
|
|
101
|
+
durationDays: duration,
|
|
102
|
+
wait: async ? Duration.minutes(0) : Duration.minutes(10),
|
|
103
|
+
orgConfig: {
|
|
104
|
+
...(definitionFile
|
|
105
|
+
? JSON.parse(await fs.promises.readFile(definitionFile, 'utf-8'))
|
|
106
|
+
: {}),
|
|
107
|
+
...(edition ? { edition } : {}),
|
|
108
|
+
...(snapshot ? { snapshot } : {}),
|
|
109
|
+
...(username ? { username } : {}),
|
|
110
|
+
...(description ? { description } : {}),
|
|
111
|
+
...(orgName ? { orgName } : {}),
|
|
112
|
+
...(sourceOrg ? { sourceOrg } : {}),
|
|
113
|
+
...(adminEmail ? { adminEmail } : {}),
|
|
114
|
+
},
|
|
115
|
+
alias,
|
|
116
|
+
setDefault,
|
|
117
|
+
tracksSource: true,
|
|
118
|
+
};
|
|
119
|
+
const result = await scratchOrgCreate(requestParams);
|
|
120
|
+
if (async) {
|
|
121
|
+
return textResponse(`Successfully enqueued scratch org with job Id: ${JSON.stringify(result.scratchOrgInfo?.Id)} use the #sf-resume tool to resume this operation`);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
return textResponse(`Successfully created scratch org ${JSON.stringify(result)}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
return textResponse(`Failed to create org: ${e instanceof Error ? e.message : 'Unknown error'}`, true);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
//# sourceMappingURL=sf-create-scratch-org.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
export declare const deleteOrgParams: z.ZodObject<{
|
|
4
|
+
directory: z.ZodEffects<z.ZodString, string, string>;
|
|
5
|
+
usernameOrAlias: z.ZodString;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
directory: string;
|
|
8
|
+
usernameOrAlias: string;
|
|
9
|
+
}, {
|
|
10
|
+
directory: string;
|
|
11
|
+
usernameOrAlias: string;
|
|
12
|
+
}>;
|
|
13
|
+
export type DeleteOrgOptions = z.infer<typeof deleteOrgParams>;
|
|
14
|
+
export declare const registerToolDeleteOrg: (server: McpServer) => void;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025, Salesforce, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { z } from 'zod';
|
|
17
|
+
import { AuthRemover, Org } from '@salesforce/core';
|
|
18
|
+
import { textResponse } from '../../shared/utils.js';
|
|
19
|
+
import { directoryParam, usernameOrAliasParam } from '../../shared/params.js';
|
|
20
|
+
/*
|
|
21
|
+
* Delete a locally authorized Salesforce org
|
|
22
|
+
*
|
|
23
|
+
* Parameters:
|
|
24
|
+
* - directory: directory to change to before running the command
|
|
25
|
+
* - usernameOrAlias: Username or alias of the Salesforce org to delete.
|
|
26
|
+
*
|
|
27
|
+
* Returns:
|
|
28
|
+
* - textResponse: Deletion request response
|
|
29
|
+
*/
|
|
30
|
+
export const deleteOrgParams = z.object({
|
|
31
|
+
directory: directoryParam,
|
|
32
|
+
usernameOrAlias: usernameOrAliasParam,
|
|
33
|
+
});
|
|
34
|
+
export const registerToolDeleteOrg = (server) => {
|
|
35
|
+
server.tool('sf-delete-org', `Deletes specified salesforce org.
|
|
36
|
+
|
|
37
|
+
AGENT INSTRUCTIONS:
|
|
38
|
+
ALWAYS confirm with the user before deleting an org
|
|
39
|
+
|
|
40
|
+
Example usage:
|
|
41
|
+
Can you delete my org
|
|
42
|
+
Can you delete MyAliasedOrg
|
|
43
|
+
Can you delete test-fe2n4tc8pgku@example.com
|
|
44
|
+
`, deleteOrgParams.shape, {
|
|
45
|
+
title: 'Delete an Org',
|
|
46
|
+
}, async ({ directory, usernameOrAlias }) => {
|
|
47
|
+
try {
|
|
48
|
+
process.chdir(directory);
|
|
49
|
+
const org = await Org.create({ aliasOrUsername: usernameOrAlias });
|
|
50
|
+
await org.delete();
|
|
51
|
+
return textResponse(`Successfully deleted ${usernameOrAlias}`);
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
if (e instanceof Error && e.name === 'DomainNotFoundError') {
|
|
55
|
+
// the org has expired, so remote operations won't work
|
|
56
|
+
// let's clean up the files locally
|
|
57
|
+
const authRemover = await AuthRemover.create();
|
|
58
|
+
await authRemover.removeAuth(usernameOrAlias);
|
|
59
|
+
return textResponse(`Successfully deleted ${usernameOrAlias}`);
|
|
60
|
+
}
|
|
61
|
+
return textResponse(`Failed to delete org: ${e instanceof Error ? e.message : 'Unknown error'}`, true);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=sf-delete-org.js.map
|