@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.
- package/README.md +240 -3
- package/lib/index.d.ts +1 -0
- package/lib/index.js +70 -4
- package/lib/shared/auth.d.ts +20 -0
- package/lib/shared/auth.js +186 -0
- package/lib/shared/params.d.ts +5 -0
- package/lib/shared/params.js +48 -0
- package/lib/shared/types.d.ts +34 -0
- package/lib/shared/types.js +17 -0
- package/lib/shared/utils.d.ts +13 -0
- package/lib/shared/utils.js +155 -0
- package/lib/tools/core/index.d.ts +1 -0
- package/lib/tools/core/index.js +17 -0
- package/lib/tools/core/sf-get-username.d.ts +17 -0
- package/lib/tools/core/sf-get-username.js +105 -0
- package/lib/tools/data/index.d.ts +1 -0
- package/lib/tools/data/index.js +17 -0
- package/lib/tools/data/sf-query-org.d.ts +17 -0
- package/lib/tools/data/sf-query-org.js +50 -0
- package/lib/tools/metadata/index.d.ts +2 -0
- package/lib/tools/metadata/index.js +18 -0
- package/lib/tools/metadata/sf-deploy-metadata.d.ts +27 -0
- package/lib/tools/metadata/sf-deploy-metadata.js +150 -0
- package/lib/tools/metadata/sf-retrieve-metadata.d.ts +2 -0
- package/lib/tools/metadata/sf-retrieve-metadata.js +122 -0
- package/lib/tools/orgs/index.d.ts +1 -0
- package/lib/tools/orgs/index.js +17 -0
- package/lib/tools/orgs/sf-list-all-orgs.d.ts +2 -0
- package/lib/tools/orgs/sf-list-all-orgs.js +49 -0
- package/lib/tools/users/index.d.ts +1 -0
- package/lib/tools/users/index.js +17 -0
- package/lib/tools/users/sf-assign-permission-set.d.ts +20 -0
- package/lib/tools/users/sf-assign-permission-set.js +84 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- 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,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
|