@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.
Files changed (73) hide show
  1. package/lib/index.d.ts +1 -1
  2. package/lib/index.js +7 -5
  3. package/lib/main-server-provider.d.ts +7 -0
  4. package/lib/main-server-provider.js +31 -0
  5. package/lib/registry.d.ts +3 -29
  6. package/lib/registry.js +9 -113
  7. package/lib/scripts/build-index.js +1 -1
  8. package/lib/services.d.ts +12 -0
  9. package/lib/services.js +34 -0
  10. package/lib/sf-mcp-server.d.ts +12 -7
  11. package/lib/sf-mcp-server.js +6 -21
  12. package/lib/telemetry.d.ts +2 -1
  13. package/lib/tools/sf-enable-tools.d.ts +23 -0
  14. package/lib/tools/sf-enable-tools.js +77 -0
  15. package/lib/tools/sf-list-tools.d.ts +8 -0
  16. package/lib/{modules/platform-cli → tools}/sf-list-tools.js +33 -9
  17. package/lib/tools/sf-suggest-cli-command.d.ts +25 -0
  18. package/lib/{modules/platform-cli → tools}/sf-suggest-cli-command.js +46 -18
  19. package/lib/utils/assets.d.ts +21 -0
  20. package/lib/{assets.js → utils/assets.js} +23 -33
  21. package/lib/{shared → utils}/auth.d.ts +3 -8
  22. package/lib/{shared → utils}/auth.js +2 -42
  23. package/lib/utils/registry-utils.d.ts +4 -0
  24. package/lib/utils/registry-utils.js +87 -0
  25. package/lib/{modules/platform-cli/utils → utils}/tools.js +1 -1
  26. package/lib/utils/types.d.ts +5 -0
  27. package/package.json +8 -4
  28. package/README.md +0 -263
  29. package/lib/assets.d.ts +0 -44
  30. package/lib/modules/platform-cli/index.d.ts +0 -16
  31. package/lib/modules/platform-cli/index.js +0 -32
  32. package/lib/modules/platform-cli/sf-assign-permission-set.d.ts +0 -20
  33. package/lib/modules/platform-cli/sf-assign-permission-set.js +0 -89
  34. package/lib/modules/platform-cli/sf-create-org-snapshot.d.ts +0 -23
  35. package/lib/modules/platform-cli/sf-create-org-snapshot.js +0 -88
  36. package/lib/modules/platform-cli/sf-create-scratch-org.d.ts +0 -50
  37. package/lib/modules/platform-cli/sf-create-scratch-org.js +0 -132
  38. package/lib/modules/platform-cli/sf-delete-org.d.ts +0 -14
  39. package/lib/modules/platform-cli/sf-delete-org.js +0 -65
  40. package/lib/modules/platform-cli/sf-deploy-metadata.d.ts +0 -27
  41. package/lib/modules/platform-cli/sf-deploy-metadata.js +0 -164
  42. package/lib/modules/platform-cli/sf-enable-tools.d.ts +0 -2
  43. package/lib/modules/platform-cli/sf-enable-tools.js +0 -42
  44. package/lib/modules/platform-cli/sf-get-username.d.ts +0 -17
  45. package/lib/modules/platform-cli/sf-get-username.js +0 -109
  46. package/lib/modules/platform-cli/sf-list-all-orgs.d.ts +0 -11
  47. package/lib/modules/platform-cli/sf-list-all-orgs.js +0 -59
  48. package/lib/modules/platform-cli/sf-list-tools.d.ts +0 -2
  49. package/lib/modules/platform-cli/sf-org-open.d.ts +0 -17
  50. package/lib/modules/platform-cli/sf-org-open.js +0 -57
  51. package/lib/modules/platform-cli/sf-query-org.d.ts +0 -20
  52. package/lib/modules/platform-cli/sf-query-org.js +0 -66
  53. package/lib/modules/platform-cli/sf-resume.d.ts +0 -20
  54. package/lib/modules/platform-cli/sf-resume.js +0 -149
  55. package/lib/modules/platform-cli/sf-retrieve-metadata.d.ts +0 -2
  56. package/lib/modules/platform-cli/sf-retrieve-metadata.js +0 -128
  57. package/lib/modules/platform-cli/sf-suggest-cli-command.d.ts +0 -5
  58. package/lib/modules/platform-cli/sf-test-agents.d.ts +0 -21
  59. package/lib/modules/platform-cli/sf-test-agents.js +0 -84
  60. package/lib/modules/platform-cli/sf-test-apex.d.ts +0 -40
  61. package/lib/modules/platform-cli/sf-test-apex.js +0 -132
  62. package/lib/shared/params.d.ts +0 -5
  63. package/lib/shared/params.js +0 -46
  64. package/lib/shared/types.d.ts +0 -33
  65. package/lib/shared/utils.d.ts +0 -11
  66. package/lib/shared/utils.js +0 -71
  67. package/lib/tsconfig.tsbuildinfo +0 -1
  68. /package/lib/{shared → utils}/cache.d.ts +0 -0
  69. /package/lib/{shared → utils}/cache.js +0 -0
  70. /package/lib/{shared → utils}/rate-limiter.d.ts +0 -0
  71. /package/lib/{shared → utils}/rate-limiter.js +0 -0
  72. /package/lib/{modules/platform-cli/utils → utils}/tools.d.ts +0 -0
  73. /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
@@ -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>;
@@ -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
@@ -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
- };
@@ -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;
@@ -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