@salesforce/mcp 0.17.1 → 0.17.2-dev.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/lib/index.d.ts +1 -1
- package/lib/index.js +7 -5
- package/lib/main-server-provider.d.ts +7 -0
- package/lib/main-server-provider.js +31 -0
- package/lib/registry.d.ts +3 -29
- package/lib/registry.js +9 -113
- package/lib/scripts/build-index.js +1 -1
- package/lib/services.d.ts +12 -0
- package/lib/services.js +34 -0
- package/lib/sf-mcp-server.d.ts +12 -7
- package/lib/sf-mcp-server.js +6 -21
- package/lib/telemetry.d.ts +2 -1
- package/lib/tools/sf-enable-tools.d.ts +23 -0
- package/lib/tools/sf-enable-tools.js +77 -0
- package/lib/tools/sf-list-tools.d.ts +8 -0
- package/lib/{modules/platform-cli → tools}/sf-list-tools.js +33 -9
- package/lib/tools/sf-suggest-cli-command.d.ts +25 -0
- package/lib/{modules/platform-cli → tools}/sf-suggest-cli-command.js +46 -18
- package/lib/utils/assets.d.ts +21 -0
- package/lib/{assets.js → utils/assets.js} +23 -33
- package/lib/{shared → utils}/auth.d.ts +3 -8
- package/lib/{shared → utils}/auth.js +2 -42
- package/lib/utils/registry-utils.d.ts +4 -0
- package/lib/utils/registry-utils.js +87 -0
- package/lib/{modules/platform-cli/utils → utils}/tools.js +1 -1
- package/lib/utils/types.d.ts +5 -0
- package/package.json +8 -4
- package/README.md +0 -263
- package/lib/assets.d.ts +0 -44
- package/lib/modules/platform-cli/index.d.ts +0 -16
- package/lib/modules/platform-cli/index.js +0 -32
- package/lib/modules/platform-cli/sf-assign-permission-set.d.ts +0 -20
- package/lib/modules/platform-cli/sf-assign-permission-set.js +0 -89
- package/lib/modules/platform-cli/sf-create-org-snapshot.d.ts +0 -23
- package/lib/modules/platform-cli/sf-create-org-snapshot.js +0 -88
- package/lib/modules/platform-cli/sf-create-scratch-org.d.ts +0 -50
- package/lib/modules/platform-cli/sf-create-scratch-org.js +0 -132
- package/lib/modules/platform-cli/sf-delete-org.d.ts +0 -14
- package/lib/modules/platform-cli/sf-delete-org.js +0 -65
- package/lib/modules/platform-cli/sf-deploy-metadata.d.ts +0 -27
- package/lib/modules/platform-cli/sf-deploy-metadata.js +0 -164
- package/lib/modules/platform-cli/sf-enable-tools.d.ts +0 -2
- package/lib/modules/platform-cli/sf-enable-tools.js +0 -42
- package/lib/modules/platform-cli/sf-get-username.d.ts +0 -17
- package/lib/modules/platform-cli/sf-get-username.js +0 -109
- package/lib/modules/platform-cli/sf-list-all-orgs.d.ts +0 -11
- package/lib/modules/platform-cli/sf-list-all-orgs.js +0 -59
- package/lib/modules/platform-cli/sf-list-tools.d.ts +0 -2
- package/lib/modules/platform-cli/sf-org-open.d.ts +0 -17
- package/lib/modules/platform-cli/sf-org-open.js +0 -57
- package/lib/modules/platform-cli/sf-query-org.d.ts +0 -20
- package/lib/modules/platform-cli/sf-query-org.js +0 -66
- package/lib/modules/platform-cli/sf-resume.d.ts +0 -20
- package/lib/modules/platform-cli/sf-resume.js +0 -149
- package/lib/modules/platform-cli/sf-retrieve-metadata.d.ts +0 -2
- package/lib/modules/platform-cli/sf-retrieve-metadata.js +0 -128
- package/lib/modules/platform-cli/sf-suggest-cli-command.d.ts +0 -5
- package/lib/modules/platform-cli/sf-test-agents.d.ts +0 -21
- package/lib/modules/platform-cli/sf-test-agents.js +0 -84
- package/lib/modules/platform-cli/sf-test-apex.d.ts +0 -40
- package/lib/modules/platform-cli/sf-test-apex.js +0 -132
- package/lib/shared/params.d.ts +0 -5
- package/lib/shared/params.js +0 -46
- package/lib/shared/types.d.ts +0 -33
- package/lib/shared/utils.d.ts +0 -11
- package/lib/shared/utils.js +0 -71
- package/lib/tsconfig.tsbuildinfo +0 -1
- /package/lib/{shared → utils}/cache.d.ts +0 -0
- /package/lib/{shared → utils}/cache.js +0 -0
- /package/lib/{shared → utils}/rate-limiter.d.ts +0 -0
- /package/lib/{shared → utils}/rate-limiter.js +0 -0
- /package/lib/{modules/platform-cli/utils → utils}/tools.d.ts +0 -0
- /package/lib/{shared → utils}/types.js +0 -0
|
@@ -1,132 +0,0 @@
|
|
|
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 { TestService } from '@salesforce/apex-node';
|
|
18
|
-
import { Duration, ensureArray } from '@salesforce/kit';
|
|
19
|
-
import { directoryParam, usernameOrAliasParam } from '../../shared/params.js';
|
|
20
|
-
import { textResponse } from '../../shared/utils.js';
|
|
21
|
-
import { getConnection } from '../../shared/auth.js';
|
|
22
|
-
const runApexTestsParam = z.object({
|
|
23
|
-
testLevel: z.enum(["RunLocalTests" /* TestLevel.RunLocalTests */, "RunAllTestsInOrg" /* TestLevel.RunAllTestsInOrg */, "RunSpecifiedTests" /* TestLevel.RunSpecifiedTests */]).describe(`Apex test level
|
|
24
|
-
|
|
25
|
-
AGENT INSTRUCTIONS
|
|
26
|
-
Choose the correct value based on what tests are meant to be executed in some of these ways:
|
|
27
|
-
|
|
28
|
-
RunLocalTests="Run all tests in the org, except the ones that originate from installed managed and unlocked packages."
|
|
29
|
-
RunAllTestsInOrg="Run all tests in the org, including tests of managed packages"
|
|
30
|
-
RunSpecifiedTests="Run the Apex tests I specify, these will be specified in the classNames parameter"
|
|
31
|
-
`),
|
|
32
|
-
classNames: z
|
|
33
|
-
.array(z.string())
|
|
34
|
-
.describe(`Apex tests classes to run.
|
|
35
|
-
if Running all tests, all tests should be listed
|
|
36
|
-
Run the tests, find apex classes matching the pattern **/classes/*.cls, that include the @isTest decorator in the file and then join their test names together with ','
|
|
37
|
-
`)
|
|
38
|
-
.optional(),
|
|
39
|
-
methodNames: z
|
|
40
|
-
.array(z.string())
|
|
41
|
-
.describe('Specific test method names, functions inside of an apex test class, must be joined with the Apex tests name')
|
|
42
|
-
.optional(),
|
|
43
|
-
async: z
|
|
44
|
-
.boolean()
|
|
45
|
-
.default(false)
|
|
46
|
-
.describe('Weather to wait for the test to finish (false) or enque the Apex tests and return the test run id (true)'),
|
|
47
|
-
suiteName: z.string().describe('a suite of apex test classes to run').optional(),
|
|
48
|
-
testRunId: z.string().default('an id of an in-progress, or completed apex test run').optional(),
|
|
49
|
-
verbose: z
|
|
50
|
-
.boolean()
|
|
51
|
-
.default(false)
|
|
52
|
-
.describe('If a user wants more test information in the context, or information about passing tests'),
|
|
53
|
-
codeCoverage: z
|
|
54
|
-
.boolean()
|
|
55
|
-
.default(false)
|
|
56
|
-
.describe('set to true if a user wants codecoverage calculated by the server'),
|
|
57
|
-
usernameOrAlias: usernameOrAliasParam,
|
|
58
|
-
directory: directoryParam,
|
|
59
|
-
});
|
|
60
|
-
/*
|
|
61
|
-
* Run Apex tests in a Salesforce org.
|
|
62
|
-
*
|
|
63
|
-
* Parameters:
|
|
64
|
-
* - testLevel: 'RunSpecifiedTests', 'RunLocalTests', 'RunAllTestsInOrg', used to specify the specific test-level.
|
|
65
|
-
* - classNames: if testLevel='RunSpecifiedTests', this will be the specified tests to run
|
|
66
|
-
* - usernameOrAlias: Username or alias of the Salesforce org to run tests in.
|
|
67
|
-
* - directory: Directory of the local project.
|
|
68
|
-
*
|
|
69
|
-
* Returns:
|
|
70
|
-
* - textResponse: Test result.
|
|
71
|
-
*/
|
|
72
|
-
export const testApex = (server) => {
|
|
73
|
-
server.tool('sf-test-apex', `Run Apex tests in an org.
|
|
74
|
-
|
|
75
|
-
AGENT INSTRUCTIONS:
|
|
76
|
-
If the user doesn't specify what to test, take context from the currently open file
|
|
77
|
-
This will ONLY run APEX tests, NOT agent tests, lightning tests, flow tests, or any other type of test.
|
|
78
|
-
|
|
79
|
-
this should be chosen when a file in the 'classes' directory is mentioned
|
|
80
|
-
|
|
81
|
-
EXAMPLE USAGE:
|
|
82
|
-
Run tests A, B, C.
|
|
83
|
-
Run the myTestMethod in this file
|
|
84
|
-
Run this test and include success and failures
|
|
85
|
-
Run all tests in the org.
|
|
86
|
-
Test the "mySuite" suite asynchronously. I’ll check results later.
|
|
87
|
-
Run tests for this file and include coverage
|
|
88
|
-
What are the results for 707XXXXXXXXXXXX
|
|
89
|
-
`, runApexTestsParam.shape, {
|
|
90
|
-
title: 'Apex Tests',
|
|
91
|
-
openWorldHint: false,
|
|
92
|
-
}, async ({ testLevel, usernameOrAlias, classNames, directory, methodNames, suiteName, async, testRunId, verbose, codeCoverage, }) => {
|
|
93
|
-
if ((ensureArray(suiteName).length > 1 ||
|
|
94
|
-
ensureArray(methodNames).length > 1 ||
|
|
95
|
-
ensureArray(classNames).length > 1) &&
|
|
96
|
-
testLevel !== "RunSpecifiedTests" /* TestLevel.RunSpecifiedTests */) {
|
|
97
|
-
return textResponse("You can't specify which tests to run without setting testLevel='RunSpecifiedTests'", true);
|
|
98
|
-
}
|
|
99
|
-
if (!usernameOrAlias)
|
|
100
|
-
return textResponse('The usernameOrAlias parameter is required, if the user did not specify one use the #sf-get-username tool', true);
|
|
101
|
-
// needed for org allowlist to work
|
|
102
|
-
process.chdir(directory);
|
|
103
|
-
const connection = await getConnection(usernameOrAlias);
|
|
104
|
-
try {
|
|
105
|
-
const testService = new TestService(connection);
|
|
106
|
-
let result;
|
|
107
|
-
if (testRunId) {
|
|
108
|
-
// we just need to get the test results
|
|
109
|
-
result = await testService.reportAsyncResults(testRunId, codeCoverage);
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
// we need to run tests
|
|
113
|
-
const payload = await testService.buildAsyncPayload(testLevel, methodNames?.join(','), classNames?.join(','), suiteName);
|
|
114
|
-
result = await testService.runTestAsynchronous(payload, codeCoverage, async, undefined, undefined, Duration.minutes(10));
|
|
115
|
-
if (async) {
|
|
116
|
-
return textResponse(`Test Run Id: ${JSON.stringify(result)}`);
|
|
117
|
-
}
|
|
118
|
-
// the user waited for the full results, we know they're TestResult
|
|
119
|
-
result = result;
|
|
120
|
-
}
|
|
121
|
-
if (!verbose) {
|
|
122
|
-
// aka concise, filter out passing tests
|
|
123
|
-
result.tests = result.tests.filter((test) => test.outcome === "Fail" /* ApexTestResultOutcome.Fail */);
|
|
124
|
-
}
|
|
125
|
-
return textResponse(`Test result: ${JSON.stringify(result)}`);
|
|
126
|
-
}
|
|
127
|
-
catch (e) {
|
|
128
|
-
return textResponse(`Failed to run Apex Tests: ${e instanceof Error ? e.message : 'Unknown error'}`, true);
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
};
|
|
132
|
-
//# sourceMappingURL=sf-test-apex.js.map
|
package/lib/shared/params.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
export declare const usernameOrAliasParam: z.ZodString;
|
|
3
|
-
export declare const useToolingApiParam: z.ZodOptional<z.ZodBoolean>;
|
|
4
|
-
export declare const baseAbsolutePathParam: z.ZodEffects<z.ZodString, string, string>;
|
|
5
|
-
export declare const directoryParam: z.ZodEffects<z.ZodString, string, string>;
|
package/lib/shared/params.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
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 { sanitizePath } from './utils.js';
|
|
18
|
-
/*
|
|
19
|
-
* A collection of reusable Tool parameters
|
|
20
|
-
*/
|
|
21
|
-
export const usernameOrAliasParam = z.string()
|
|
22
|
-
.describe(`The username or alias for the Salesforce org to run this tool against.
|
|
23
|
-
|
|
24
|
-
AGENT INSTRUCTIONS:
|
|
25
|
-
If it is not clear what username or alias is, run the #sf-get-username tool.
|
|
26
|
-
NEVER guess or make-up a username or alias, use #sf-get-username if you are not sure.
|
|
27
|
-
DO NOT use #sf-get-username if the user mentions an alias or username, like "for my an-alias org" or "for my test-prgelc2petd9@example.com org".
|
|
28
|
-
|
|
29
|
-
USAGE:
|
|
30
|
-
...for the my-alias org
|
|
31
|
-
...for my 'my-alias' user
|
|
32
|
-
...for alias myAlias
|
|
33
|
-
...for my 'test@example.com' user
|
|
34
|
-
...for the 'test@example.com' org`);
|
|
35
|
-
export const useToolingApiParam = z.boolean().optional().describe('Use Tooling API for the operation');
|
|
36
|
-
export const baseAbsolutePathParam = z
|
|
37
|
-
.string()
|
|
38
|
-
.refine(sanitizePath, 'Invalid path: Must be an absolute path and cannot contain path traversal sequences');
|
|
39
|
-
export const directoryParam = baseAbsolutePathParam.describe(`The directory to run this tool from.
|
|
40
|
-
AGENT INSTRUCTIONS:
|
|
41
|
-
We need to know where the user wants to run this tool from.
|
|
42
|
-
Look at your current Workspace Context to determine this filepath.
|
|
43
|
-
ALWAYS USE A FULL PATH TO THE DIRECTORY.
|
|
44
|
-
Unless the user explicitly asks for a different directory, or a new directory is created from the action of a tool, use this same directory for future tool calls.
|
|
45
|
-
`);
|
|
46
|
-
//# sourceMappingURL=params.js.map
|
package/lib/shared/types.d.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { ConfigInfo } from '@salesforce/core';
|
|
2
|
-
import { type Nullable } from '@salesforce/ts-types';
|
|
3
|
-
import { RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
|
-
export type ConfigInfoWithCache = {
|
|
5
|
-
key: string;
|
|
6
|
-
location?: ConfigInfo['location'];
|
|
7
|
-
value: string;
|
|
8
|
-
cached?: boolean;
|
|
9
|
-
path: string;
|
|
10
|
-
};
|
|
11
|
-
export type SanitizedOrgAuthorization = {
|
|
12
|
-
aliases?: Nullable<string[]>;
|
|
13
|
-
configs?: Nullable<string[]>;
|
|
14
|
-
username?: string;
|
|
15
|
-
instanceUrl?: string;
|
|
16
|
-
isScratchOrg?: boolean;
|
|
17
|
-
isDevHub?: boolean;
|
|
18
|
-
isSandbox?: boolean;
|
|
19
|
-
orgId?: string;
|
|
20
|
-
oauthMethod?: string;
|
|
21
|
-
isExpired?: boolean | 'unknown';
|
|
22
|
-
};
|
|
23
|
-
export type ToolTextResponse = {
|
|
24
|
-
isError: boolean;
|
|
25
|
-
content: Array<{
|
|
26
|
-
type: 'text';
|
|
27
|
-
text: string;
|
|
28
|
-
}>;
|
|
29
|
-
};
|
|
30
|
-
export type ToolInfo = {
|
|
31
|
-
tool: RegisteredTool;
|
|
32
|
-
name: string;
|
|
33
|
-
};
|
package/lib/shared/utils.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { type ToolTextResponse } from './types.js';
|
|
2
|
-
export declare function textResponse(text: string, isError?: boolean): ToolTextResponse;
|
|
3
|
-
/**
|
|
4
|
-
* Gets the enabled toolsets based on user input and validates against available toolsets
|
|
5
|
-
*
|
|
6
|
-
* @param availableToolsets - The list of available toolsets
|
|
7
|
-
* @param toolsetsInput - The comma-separated list of toolsets
|
|
8
|
-
* @returns A Set of enabled toolsets
|
|
9
|
-
*/
|
|
10
|
-
export declare function getEnabledToolsets(availableToolsets: string[], toolsetsInput: string): Set<string>;
|
|
11
|
-
export declare function sanitizePath(projectPath: string): boolean;
|
package/lib/shared/utils.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
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
|
-
/* eslint-disable no-console */
|
|
17
|
-
import path from 'node:path';
|
|
18
|
-
// TODO: break into two helpers? One for errors and one for success?
|
|
19
|
-
export function textResponse(text, isError = false) {
|
|
20
|
-
if (text === '')
|
|
21
|
-
throw new Error('textResponse error: "text" cannot be empty');
|
|
22
|
-
return {
|
|
23
|
-
isError,
|
|
24
|
-
content: [
|
|
25
|
-
{
|
|
26
|
-
type: 'text',
|
|
27
|
-
text,
|
|
28
|
-
},
|
|
29
|
-
],
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Gets the enabled toolsets based on user input and validates against available toolsets
|
|
34
|
-
*
|
|
35
|
-
* @param availableToolsets - The list of available toolsets
|
|
36
|
-
* @param toolsetsInput - The comma-separated list of toolsets
|
|
37
|
-
* @returns A Set of enabled toolsets
|
|
38
|
-
*/
|
|
39
|
-
export function getEnabledToolsets(availableToolsets, toolsetsInput) {
|
|
40
|
-
const availableToolsetsSet = new Set(availableToolsets);
|
|
41
|
-
const passedToolsets = toolsetsInput.split(',').map((toolset) => toolset.trim());
|
|
42
|
-
// Check if any passed toolset is not in the available list
|
|
43
|
-
for (const toolset of passedToolsets) {
|
|
44
|
-
if (!availableToolsetsSet.has(toolset)) {
|
|
45
|
-
console.error(`Passed toolset "${toolset}" is not in the allowed toolset list. Available toolsets are "all (default), ${Array.from(availableToolsetsSet)
|
|
46
|
-
.filter((t) => t !== 'all')
|
|
47
|
-
.join(', ')}"`);
|
|
48
|
-
process.exit(1);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
const enabledToolsets = new Set(passedToolsets.filter((toolset) => availableToolsetsSet.has(toolset)));
|
|
52
|
-
console.error('Enabling toolsets:', Array.from(enabledToolsets).join(', '));
|
|
53
|
-
return enabledToolsets;
|
|
54
|
-
}
|
|
55
|
-
export function sanitizePath(projectPath) {
|
|
56
|
-
// Decode URL-encoded sequences
|
|
57
|
-
const decodedProjectPath = decodeURIComponent(projectPath);
|
|
58
|
-
// Normalize Unicode characters
|
|
59
|
-
const normalizedProjectPath = decodedProjectPath.normalize();
|
|
60
|
-
// Check for various traversal patterns
|
|
61
|
-
const hasTraversal = normalizedProjectPath.includes('..') ||
|
|
62
|
-
normalizedProjectPath.includes('\u2025') || // Unicode horizontal ellipsis
|
|
63
|
-
normalizedProjectPath.includes('\u2026'); // Unicode vertical ellipsis
|
|
64
|
-
// `path.isAbsolute` doesn't cover Windows's drive-relative path:
|
|
65
|
-
// https://github.com/nodejs/node/issues/56766
|
|
66
|
-
//
|
|
67
|
-
// we can assume it's a drive-relative path if it's starts with `\`.
|
|
68
|
-
const isAbsolute = path.isAbsolute(projectPath) && (process.platform === 'win32' ? !projectPath.startsWith('\\') : true);
|
|
69
|
-
return !hasTraversal && isAbsolute;
|
|
70
|
-
}
|
|
71
|
-
//# sourceMappingURL=utils.js.map
|