@salesforce/mcp 0.0.1 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +240 -3
  2. package/lib/index.d.ts +1 -0
  3. package/lib/index.js +70 -4
  4. package/lib/shared/auth.d.ts +20 -0
  5. package/lib/shared/auth.js +186 -0
  6. package/lib/shared/params.d.ts +5 -0
  7. package/lib/shared/params.js +48 -0
  8. package/lib/shared/types.d.ts +34 -0
  9. package/lib/shared/types.js +17 -0
  10. package/lib/shared/utils.d.ts +13 -0
  11. package/lib/shared/utils.js +155 -0
  12. package/lib/tools/core/index.d.ts +1 -0
  13. package/lib/tools/core/index.js +17 -0
  14. package/lib/tools/core/sf-get-username.d.ts +17 -0
  15. package/lib/tools/core/sf-get-username.js +105 -0
  16. package/lib/tools/data/index.d.ts +1 -0
  17. package/lib/tools/data/index.js +17 -0
  18. package/lib/tools/data/sf-query-org.d.ts +17 -0
  19. package/lib/tools/data/sf-query-org.js +50 -0
  20. package/lib/tools/metadata/index.d.ts +2 -0
  21. package/lib/tools/metadata/index.js +18 -0
  22. package/lib/tools/metadata/sf-deploy-metadata.d.ts +27 -0
  23. package/lib/tools/metadata/sf-deploy-metadata.js +150 -0
  24. package/lib/tools/metadata/sf-retrieve-metadata.d.ts +2 -0
  25. package/lib/tools/metadata/sf-retrieve-metadata.js +122 -0
  26. package/lib/tools/orgs/index.d.ts +1 -0
  27. package/lib/tools/orgs/index.js +17 -0
  28. package/lib/tools/orgs/sf-list-all-orgs.d.ts +2 -0
  29. package/lib/tools/orgs/sf-list-all-orgs.js +49 -0
  30. package/lib/tools/users/index.d.ts +1 -0
  31. package/lib/tools/users/index.js +17 -0
  32. package/lib/tools/users/sf-assign-permission-set.d.ts +20 -0
  33. package/lib/tools/users/sf-assign-permission-set.js +84 -0
  34. package/lib/tsconfig.tsbuildinfo +1 -1
  35. package/package.json +15 -8
@@ -0,0 +1,122 @@
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, SfProject } from '@salesforce/core';
18
+ import { SourceTracking } from '@salesforce/source-tracking';
19
+ import { ComponentSetBuilder } from '@salesforce/source-deploy-retrieve';
20
+ import { ensureString } from '@salesforce/ts-types';
21
+ import { Duration } from '@salesforce/kit';
22
+ import { directoryParam, usernameOrAliasParam } from '../../shared/params.js';
23
+ import { textResponse } from '../../shared/utils.js';
24
+ import { getConnection } from '../../shared/auth.js';
25
+ const retrieveMetadataParams = z.object({
26
+ sourceDir: z
27
+ .array(z.string())
28
+ .describe('Path to the local source files to retrieve. Leave this unset if the user is vague about what to retrieve.')
29
+ .optional(),
30
+ manifest: z.string().describe('Full file path for manifest (XML file) of components to retrieve.').optional(),
31
+ usernameOrAlias: usernameOrAliasParam,
32
+ directory: directoryParam,
33
+ });
34
+ /*
35
+ * Retrieve metadata from an org to your local project.
36
+ *
37
+ * Parameters:
38
+ * - sourceDir: Path to the local source files to retrieve.
39
+ * - manifest: Full file path for manifest (XML file) of components to retrieve.
40
+ * - usernameOrAlias: Username or alias of the Salesforce org to retrieve from.
41
+ * - directory: Directory of the local project.
42
+ *
43
+ * Returns:
44
+ * - textResponse: Retrieve result.
45
+ */
46
+ export const registerToolRetrieveMetadata = (server) => {
47
+ server.tool('sf-retrieve-metadata', `Retrieve metadata from an org to your local project.
48
+
49
+ AGENT INSTRUCTIONS:
50
+ If the user doesn't specify what to retrieve exactly ("retrieve my changes"), leave the "sourceDir" and "manifest" params empty so the tool calculates which files to retrieve.
51
+
52
+ EXAMPLE USAGE:
53
+ Retrieve changes
54
+ Retrieve changes from my org
55
+ Retrieve this file from my org
56
+ Retrieve the metadata in the manifest
57
+ Retrieve X metadata from my org
58
+ `, retrieveMetadataParams.shape, async ({ sourceDir, usernameOrAlias, directory, manifest }) => {
59
+ if (sourceDir && manifest) {
60
+ return textResponse("You can't specify both `sourceDir` and `manifest` parameters.", true);
61
+ }
62
+ // needed for org allowlist to work
63
+ process.chdir(directory);
64
+ const connection = await getConnection(usernameOrAlias);
65
+ const project = await SfProject.resolve(directory);
66
+ const org = await Org.create({ connection });
67
+ if (!sourceDir && !manifest && !(await org.tracksSource())) {
68
+ return textResponse('This org does not have source-tracking enabled or does not support source-tracking. You should specify the files or a manifest to retrieve.', true);
69
+ }
70
+ try {
71
+ const stl = await SourceTracking.create({
72
+ org,
73
+ project,
74
+ subscribeSDREvents: true,
75
+ });
76
+ const componentSet = await buildRetrieveComponentSet(connection, project, stl, sourceDir, manifest);
77
+ if (componentSet.size === 0) {
78
+ // STL found no changes
79
+ return textResponse('No remote changes to retrieve were found.');
80
+ }
81
+ const retrieve = await componentSet.retrieve({
82
+ usernameOrConnection: connection,
83
+ merge: true,
84
+ format: 'source',
85
+ output: project.getDefaultPackage().fullPath,
86
+ });
87
+ // polling freq. is set dynamically by SDR based no the component set size.
88
+ const result = await retrieve.pollStatus({
89
+ timeout: Duration.minutes(10),
90
+ });
91
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
92
+ const { zipFile, ...retrieveResult } = result.response;
93
+ return textResponse(`Retrieve result: ${JSON.stringify(retrieveResult)}`, !retrieveResult.success);
94
+ // }
95
+ }
96
+ catch (error) {
97
+ return textResponse(`Failed to retrieve metadata: ${error instanceof Error ? error.message : 'Unknown error'}`, true);
98
+ }
99
+ });
100
+ };
101
+ async function buildRetrieveComponentSet(connection, project, stl, sourceDir, manifestPath) {
102
+ if (sourceDir || manifestPath) {
103
+ return ComponentSetBuilder.build({
104
+ apiversion: connection.getApiVersion(),
105
+ sourceapiversion: ensureString((await project.resolveProjectConfig()).sourceApiVersion),
106
+ sourcepath: sourceDir,
107
+ ...(manifestPath
108
+ ? {
109
+ manifest: {
110
+ manifestPath,
111
+ directoryPaths: project.getUniquePackageDirectories().map((pDir) => pDir.fullPath),
112
+ },
113
+ }
114
+ : {}),
115
+ projectDir: project.getPath(),
116
+ });
117
+ }
118
+ // No specific metadata requested to retrieve, build component set from STL.
119
+ const cs = await stl.maybeApplyRemoteDeletesToLocal(true);
120
+ return cs.componentSetFromNonDeletes;
121
+ }
122
+ //# sourceMappingURL=sf-retrieve-metadata.js.map
@@ -0,0 +1 @@
1
+ export * from './sf-list-all-orgs.js';
@@ -0,0 +1,17 @@
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
+ export * from './sf-list-all-orgs.js';
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare const registerToolListAllOrgs: (server: McpServer) => void;
@@ -0,0 +1,49 @@
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 { getAllAllowedOrgs } from '../../shared/auth.js';
17
+ import { textResponse } from '../../shared/utils.js';
18
+ /*
19
+ * List all Salesforce orgs
20
+ *
21
+ * Lists all configured Salesforce orgs.
22
+ *
23
+ * Parameters:
24
+ * - None required
25
+ *
26
+ * Returns:
27
+ * - textResponse: List of configured Salesforce orgs
28
+ */
29
+ export const registerToolListAllOrgs = (server) => {
30
+ server.tool('sf-list-all-orgs', `Lists all configured Salesforce orgs.
31
+
32
+ AGENT INSTRUCTIONS:
33
+ DO NOT use this tool to try to determine which org a user wants, use #sf-get-username instead. Only use it if the user explicitly asks for a list of orgs.
34
+
35
+ Example usage:
36
+ Can you list all Salesforce orgs for me
37
+ List all Salesforce orgs
38
+ List all orgs
39
+ `, {}, async () => {
40
+ try {
41
+ const orgs = await getAllAllowedOrgs();
42
+ return textResponse(`List of configured Salesforce orgs:\n\n${JSON.stringify(orgs, null, 2)}`);
43
+ }
44
+ catch (error) {
45
+ return textResponse(`Failed to list orgs: ${error instanceof Error ? error.message : 'Unknown error'}`, true);
46
+ }
47
+ });
48
+ };
49
+ //# sourceMappingURL=sf-list-all-orgs.js.map
@@ -0,0 +1 @@
1
+ export * from './sf-assign-permission-set.js';
@@ -0,0 +1,17 @@
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
+ export * from './sf-assign-permission-set.js';
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,20 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { z } from 'zod';
3
+ export declare const assignPermissionSetParamsSchema: z.ZodObject<{
4
+ permissionSetName: z.ZodString;
5
+ usernameOrAlias: z.ZodString;
6
+ onBehalfOf: z.ZodOptional<z.ZodString>;
7
+ directory: z.ZodEffects<z.ZodString, string, string>;
8
+ }, "strip", z.ZodTypeAny, {
9
+ directory: string;
10
+ usernameOrAlias: string;
11
+ permissionSetName: string;
12
+ onBehalfOf?: string | undefined;
13
+ }, {
14
+ directory: string;
15
+ usernameOrAlias: string;
16
+ permissionSetName: string;
17
+ onBehalfOf?: string | undefined;
18
+ }>;
19
+ export type AssignPermissionSetOptions = z.infer<typeof assignPermissionSetParamsSchema>;
20
+ export declare const registerToolAssignPermissionSet: (server: McpServer) => void;
@@ -0,0 +1,84 @@
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 { Org, StateAggregator, User } from '@salesforce/core';
17
+ import { z } from 'zod';
18
+ import { directoryParam, usernameOrAliasParam } from '../../shared/params.js';
19
+ import { textResponse } from '../../shared/utils.js';
20
+ import { getConnection } from '../../shared/auth.js';
21
+ /*
22
+ * Assign permission set
23
+ *
24
+ * Assign a permission set to one or more org users.
25
+ *
26
+ * Parameters:
27
+ * - permissionSetName: Permission set to assign (required)
28
+ * Example: "Set the permission set MyPermSet", "Set the perm set MyPermSet"
29
+ * - usernameOrAlias: Username or alias for the Salesforce org (required)
30
+ * - onBehalfOf: Username or alias to assign the permission set to (optional)
31
+ * Note: This is only used when "on behalf of" is explicitly mentioned.
32
+ * Otherwise, the permission will be set to the usernameOrAlias user.
33
+ * Example: "Set the permission set MyPermSet on behalf of my-alias"
34
+ *
35
+ * Returns:
36
+ * - textResponse: Permission set assignment result
37
+ */
38
+ export const assignPermissionSetParamsSchema = z.object({
39
+ permissionSetName: z.string().describe(`A single permission set to assign
40
+
41
+ EXAMPLE USAGE:
42
+ Set the permission set MyPermSet
43
+ Set the perm set MyPermSet`),
44
+ usernameOrAlias: usernameOrAliasParam,
45
+ onBehalfOf: z.string().optional()
46
+ .describe(`A single username or alias (other than the usernameOrAlias) to assign the permission set to
47
+
48
+ AGENT INSTRUCTIONS:
49
+ If the user does not specifically say "on behalf of" this will be empty.
50
+ If the user does specifically say "on behalf of", but it is unclear what the target-org is, run the #sf-get-username tool.
51
+ In that case, use the usernameOrAlias parameter as the org to assign the permission set to.
52
+
53
+ USAGE EXAMPLE:
54
+ Assign the permission set MyPermSet.
55
+ Set the permission set MyPermSet on behalf of test-3uyb8kmftiu@example.com.
56
+ Set the permission set MyPermSet on behalf of my-alias.`),
57
+ directory: directoryParam,
58
+ });
59
+ export const registerToolAssignPermissionSet = (server) => {
60
+ server.tool('sf-assign-permission-set', 'Assign a permission set to one or more org users.', assignPermissionSetParamsSchema.shape, async ({ permissionSetName, usernameOrAlias, onBehalfOf, directory }) => {
61
+ try {
62
+ process.chdir(directory);
63
+ // We build the connection from the usernameOrAlias
64
+ const connection = await getConnection(usernameOrAlias);
65
+ // We need to clear the instance so we know we have the most up to date aliases
66
+ // If a user sets an alias after server start up, it was not getting picked up
67
+ StateAggregator.clearInstance();
68
+ // Must NOT be nullish coalescing (??) In case the LLM uses and empty string
69
+ const assignTo = (await StateAggregator.getInstance()).aliases.resolveUsername(onBehalfOf || usernameOrAlias);
70
+ if (!assignTo.includes('@')) {
71
+ return textResponse('Unable to resolve the username for alias. Make sure it is correct', true);
72
+ }
73
+ const org = await Org.create({ connection });
74
+ const user = await User.create({ org });
75
+ const queryResult = await connection.singleRecordQuery(`SELECT Id FROM User WHERE Username='${assignTo}'`);
76
+ await user.assignPermissionSets(queryResult.Id, [permissionSetName]);
77
+ return textResponse(`Assigned ${permissionSetName} to ${assignTo}`);
78
+ }
79
+ catch (error) {
80
+ return textResponse(`Failed to assign permission set: ${error instanceof Error ? error.message : 'Unknown error'}`, true);
81
+ }
82
+ });
83
+ };
84
+ //# sourceMappingURL=sf-assign-permission-set.js.map