@rohithvemulapally/mcp-server-salesforce 0.0.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 (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +357 -0
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.js +312 -0
  5. package/dist/tools/aggregateQuery.d.ts +18 -0
  6. package/dist/tools/aggregateQuery.js +250 -0
  7. package/dist/tools/describe.d.ts +9 -0
  8. package/dist/tools/describe.js +33 -0
  9. package/dist/tools/dml.d.ts +15 -0
  10. package/dist/tools/dml.js +105 -0
  11. package/dist/tools/executeAnonymous.d.ts +25 -0
  12. package/dist/tools/executeAnonymous.js +130 -0
  13. package/dist/tools/manageDebugLogs.d.ts +30 -0
  14. package/dist/tools/manageDebugLogs.js +424 -0
  15. package/dist/tools/manageField.d.ts +32 -0
  16. package/dist/tools/manageField.js +349 -0
  17. package/dist/tools/manageFieldPermissions.d.ts +17 -0
  18. package/dist/tools/manageFieldPermissions.js +247 -0
  19. package/dist/tools/manageObject.d.ts +20 -0
  20. package/dist/tools/manageObject.js +138 -0
  21. package/dist/tools/metadata.d.ts +9 -0
  22. package/dist/tools/metadata.js +66 -0
  23. package/dist/tools/query.d.ts +16 -0
  24. package/dist/tools/query.js +114 -0
  25. package/dist/tools/readApex.d.ts +26 -0
  26. package/dist/tools/readApex.js +165 -0
  27. package/dist/tools/readApexTrigger.d.ts +26 -0
  28. package/dist/tools/readApexTrigger.js +165 -0
  29. package/dist/tools/search.d.ts +9 -0
  30. package/dist/tools/search.js +45 -0
  31. package/dist/tools/searchAll.d.ts +29 -0
  32. package/dist/tools/searchAll.js +250 -0
  33. package/dist/tools/writeApex.d.ts +27 -0
  34. package/dist/tools/writeApex.js +154 -0
  35. package/dist/tools/writeApexTrigger.d.ts +28 -0
  36. package/dist/tools/writeApexTrigger.js +178 -0
  37. package/dist/types/connection.d.ts +52 -0
  38. package/dist/types/connection.js +21 -0
  39. package/dist/types/metadata.d.ts +43 -0
  40. package/dist/types/metadata.js +1 -0
  41. package/dist/types/salesforce.d.ts +33 -0
  42. package/dist/types/salesforce.js +1 -0
  43. package/dist/utils/connection.d.ts +7 -0
  44. package/dist/utils/connection.js +172 -0
  45. package/dist/utils/errorHandler.d.ts +15 -0
  46. package/dist/utils/errorHandler.js +23 -0
  47. package/package.json +39 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Tapas Mukherjee
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,357 @@
1
+ # Salesforce MCP Server
2
+ [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/tsmztech/mcp-server-salesforce/badge)](https://securityscorecards.dev/viewer/?uri=github.com/tsmztech/mcp-server-salesforce)
3
+
4
+
5
+ An MCP (Model Context Protocol) server implementation that integrates Claude with Salesforce, enabling natural language interactions with your Salesforce data and metadata. This server allows Claude to query, modify, and manage your Salesforce objects and records using everyday language.
6
+
7
+ <a href="https://glama.ai/mcp/servers/kqeniawbr6">
8
+ <img width="380" height="200" src="https://glama.ai/mcp/servers/kqeniawbr6/badge" alt="Salesforce Server MCP server" />
9
+ </a>
10
+
11
+ ## Features
12
+
13
+ * **Object and Field Management**: Create and modify custom objects and fields using natural language
14
+ * **Smart Object Search**: Find Salesforce objects using partial name matches
15
+ * **Detailed Schema Information**: Get comprehensive field and relationship details for any object
16
+ * **Flexible Data Queries**: Query records with relationship support and complex filters
17
+ * **Data Manipulation**: Insert, update, delete, and upsert records with ease
18
+ * **Cross-Object Search**: Search across multiple objects using SOSL
19
+ * **Apex Code Management**: Read, create, and update Apex classes and triggers
20
+ * **Intuitive Error Handling**: Clear feedback with Salesforce-specific error details
21
+ * **Switchable Authentication**: Supports multiple orgs. Easily switch your active Salesforce org based on the default org configured in your VS Code workspace (use Salesforce_CLI authentication for this feature).
22
+
23
+ ## Installation
24
+
25
+ ### Global Installation (npm)
26
+
27
+ ```bash
28
+ npm install -g @tsmztech/mcp-server-salesforce
29
+ ```
30
+
31
+ ### Claude Desktop Quick Installation
32
+
33
+ For easy setup with Claude Desktop, download the pre-configured extension:
34
+
35
+ 1. Download [`salesforce-mcp-extension.dxt`](./claude-desktop/salesforce-mcp-extension.dxt) from the `claude-desktop/` folder
36
+ 2. Open Claude Desktop → Settings → Extensions
37
+ 3. Drag the `.dxt` file into the Extensions window
38
+ 4. Configure your Salesforce credentials when prompted
39
+
40
+ For manual Claude Desktop configuration, see [Usage with Claude Desktop](#usage-with-claude-desktop) below.
41
+
42
+ ## Tools
43
+
44
+ ### salesforce_search_objects
45
+ Search for standard and custom objects:
46
+ * Search by partial name matches
47
+ * Finds both standard and custom objects
48
+ * Example: "Find objects related to Account" will find Account, AccountHistory, etc.
49
+
50
+ ### salesforce_describe_object
51
+ Get detailed object schema information:
52
+ * Field definitions and properties
53
+ * Relationship details
54
+ * Picklist values
55
+ * Example: "Show me all fields in the Account object"
56
+
57
+ ### salesforce_query_records
58
+ Query records with relationship support:
59
+ * Parent-to-child relationships
60
+ * Child-to-parent relationships
61
+ * Complex WHERE conditions
62
+ * Example: "Get all Accounts with their related Contacts"
63
+ * Note: For queries with GROUP BY or aggregate functions, use salesforce_aggregate_query
64
+
65
+ ### salesforce_aggregate_query
66
+ Execute aggregate queries with GROUP BY:
67
+ * GROUP BY single or multiple fields
68
+ * Aggregate functions: COUNT, COUNT_DISTINCT, SUM, AVG, MIN, MAX
69
+ * HAVING clauses for filtering grouped results
70
+ * Date/time grouping functions
71
+ * Example: "Count opportunities by stage" or "Find accounts with more than 10 opportunities"
72
+
73
+ ### salesforce_dml_records
74
+ Perform data operations:
75
+ * Insert new records
76
+ * Update existing records
77
+ * Delete records
78
+ * Upsert using external IDs
79
+ * Example: "Update status of multiple accounts"
80
+
81
+ ### salesforce_manage_object
82
+ Create and modify custom objects:
83
+ * Create new custom objects
84
+ * Update object properties
85
+ * Configure sharing settings
86
+ * Example: "Create a Customer Feedback object"
87
+
88
+ ### salesforce_manage_field
89
+ Manage object fields:
90
+ * Add new custom fields
91
+ * Modify field properties
92
+ * Create relationships
93
+ * Automatically grants Field Level Security to System Administrator by default
94
+ * Use `grantAccessTo` parameter to specify different profiles
95
+ * Example: "Add a Rating picklist field to Account"
96
+
97
+ ### salesforce_manage_field_permissions
98
+ Manage Field Level Security (Field Permissions):
99
+ * Grant or revoke read/edit access to fields for specific profiles
100
+ * View current field permissions
101
+ * Bulk update permissions for multiple profiles
102
+ * Useful for managing permissions after field creation or for existing fields
103
+ * Example: "Grant System Administrator access to Custom_Field__c on Account"
104
+
105
+ ### salesforce_search_all
106
+ Search across multiple objects:
107
+ * SOSL-based search
108
+ * Multiple object support
109
+ * Field snippets
110
+ * Example: "Search for 'cloud' across Accounts and Opportunities"
111
+
112
+ ### salesforce_read_apex
113
+ Read Apex classes:
114
+ * Get full source code of specific classes
115
+ * List classes matching name patterns
116
+ * View class metadata (API version, status, etc.)
117
+ * Support for wildcards (* and ?) in name patterns
118
+ * Example: "Show me the AccountController class" or "Find all classes matching Account*Cont*"
119
+
120
+ ### salesforce_write_apex
121
+ Create and update Apex classes:
122
+ * Create new Apex classes
123
+ * Update existing class implementations
124
+ * Specify API versions
125
+ * Example: "Create a new Apex class for handling account operations"
126
+
127
+ ### salesforce_read_apex_trigger
128
+ Read Apex triggers:
129
+ * Get full source code of specific triggers
130
+ * List triggers matching name patterns
131
+ * View trigger metadata (API version, object, status, etc.)
132
+ * Support for wildcards (* and ?) in name patterns
133
+ * Example: "Show me the AccountTrigger" or "Find all triggers for Contact object"
134
+
135
+ ### salesforce_write_apex_trigger
136
+ Create and update Apex triggers:
137
+ * Create new Apex triggers for specific objects
138
+ * Update existing trigger implementations
139
+ * Specify API versions and event operations
140
+ * Example: "Create a new trigger for the Account object" or "Update the Lead trigger"
141
+
142
+ ### salesforce_execute_anonymous
143
+ Execute anonymous Apex code:
144
+ * Run Apex code without creating a permanent class
145
+ * View debug logs and execution results
146
+ * Useful for data operations not directly supported by other tools
147
+ * Example: "Execute Apex code to calculate account metrics" or "Run a script to update related records"
148
+
149
+ ### salesforce_manage_debug_logs
150
+ Manage debug logs for Salesforce users:
151
+ * Enable debug logs for specific users
152
+ * Disable active debug log configurations
153
+ * Retrieve and view debug logs
154
+ * Configure log levels (NONE, ERROR, WARN, INFO, DEBUG, FINE, FINER, FINEST)
155
+ * Example: "Enable debug logs for user@example.com" or "Retrieve recent logs for an admin user"
156
+
157
+ ## Setup
158
+
159
+ ### Salesforce Authentication
160
+ You can connect to Salesforce using one of three authentication methods:
161
+
162
+ #### 1. Username/Password Authentication (Default)
163
+ 1. Set up your Salesforce credentials
164
+ 2. Get your security token (Reset from Salesforce Settings)
165
+
166
+ #### 2. OAuth 2.0 Client Credentials Flow
167
+ 1. Create a Connected App in Salesforce
168
+ 2. Enable OAuth settings and select "Client Credentials Flow"
169
+ 3. Set appropriate scopes (typically "api" is sufficient)
170
+ 4. Save the Client ID and Client Secret
171
+ 5. **Important**: Note your instance URL (e.g., `https://your-domain.my.salesforce.com`) as it's required for authentication
172
+
173
+ #### 3. Salesforce CLI Authentication (Recommended for local/dev) (contribution by @andrea9293)
174
+ 1. Install and authenticate Salesforce CLI (`sf`).
175
+ 2. Make sure your org is authenticated and accessible via `sf org display --json` in the root of your Salesforce project.
176
+ 3. The server will automatically retrieve the access token and instance url using the CLI.
177
+
178
+
179
+
180
+ ### Usage with Claude Desktop
181
+
182
+
183
+ Add to your `claude_desktop_config.json`:
184
+
185
+
186
+ #### For Salesforce CLI Authentication:
187
+ ```json
188
+ {
189
+ "mcpServers": {
190
+ "salesforce": {
191
+ "command": "npx",
192
+ "args": ["-y", "@tsmztech/mcp-server-salesforce"],
193
+ "env": {
194
+ "SALESFORCE_CONNECTION_TYPE": "Salesforce_CLI"
195
+ }
196
+ }
197
+ }
198
+ }
199
+ ```
200
+
201
+ #### For Username/Password Authentication:
202
+ ```json
203
+ {
204
+ "mcpServers": {
205
+ "salesforce": {
206
+ "command": "npx",
207
+ "args": ["-y", "@tsmztech/mcp-server-salesforce"],
208
+ "env": {
209
+ "SALESFORCE_CONNECTION_TYPE": "User_Password",
210
+ "SALESFORCE_USERNAME": "your_username",
211
+ "SALESFORCE_PASSWORD": "your_password",
212
+ "SALESFORCE_TOKEN": "your_security_token",
213
+ "SALESFORCE_INSTANCE_URL": "org_url" // Optional. Default value: https://login.salesforce.com
214
+ }
215
+ }
216
+ }
217
+ }
218
+ ```
219
+
220
+ #### For OAuth 2.0 Client Credentials Flow:
221
+ ```json
222
+ {
223
+ "mcpServers": {
224
+ "salesforce": {
225
+ "command": "npx",
226
+ "args": ["-y", "@tsmztech/mcp-server-salesforce"],
227
+ "env": {
228
+ "SALESFORCE_CONNECTION_TYPE": "OAuth_2.0_Client_Credentials",
229
+ "SALESFORCE_CLIENT_ID": "your_client_id",
230
+ "SALESFORCE_CLIENT_SECRET": "your_client_secret",
231
+ "SALESFORCE_INSTANCE_URL": "https://your-domain.my.salesforce.com" // REQUIRED: Must be your exact Salesforce instance URL
232
+ }
233
+ }
234
+ }
235
+ }
236
+ ```
237
+
238
+ > **Note**: For OAuth 2.0 Client Credentials Flow, the `SALESFORCE_INSTANCE_URL` must be your exact Salesforce instance URL (e.g., `https://your-domain.my.salesforce.com`). The token endpoint will be constructed as `<instance_url>/services/oauth2/token`.
239
+
240
+ ## Example Usage
241
+
242
+ ### Searching Objects
243
+ ```
244
+ "Find all objects related to Accounts"
245
+ "Show me objects that handle customer service"
246
+ "What objects are available for order management?"
247
+ ```
248
+
249
+ ### Getting Schema Information
250
+ ```
251
+ "What fields are available in the Account object?"
252
+ "Show me the picklist values for Case Status"
253
+ "Describe the relationship fields in Opportunity"
254
+ ```
255
+
256
+ ### Querying Records
257
+ ```
258
+ "Get all Accounts created this month"
259
+ "Show me high-priority Cases with their related Contacts"
260
+ "Find all Opportunities over $100k"
261
+ ```
262
+
263
+ ### Aggregate Queries
264
+ ```
265
+ "Count opportunities by stage"
266
+ "Show me the total revenue by account"
267
+ "Find accounts with more than 10 opportunities"
268
+ "Calculate average deal size by sales rep and quarter"
269
+ "Get the number of cases by priority and status"
270
+ ```
271
+
272
+ ### Managing Custom Objects
273
+ ```
274
+ "Create a Customer Feedback object"
275
+ "Add a Rating field to the Feedback object"
276
+ "Update sharing settings for the Service Request object"
277
+ ```
278
+ Examples with Field Level Security:
279
+ ```
280
+ # Default - grants access to System Administrator automatically
281
+ "Create a Status picklist field on Custom_Object__c"
282
+
283
+ # Custom profiles - grants access to specified profiles
284
+ "Create a Revenue currency field on Account and grant access to Sales User and Marketing User profiles"
285
+ ```
286
+
287
+ ### Managing Field Permissions
288
+ ```
289
+ "Grant System Administrator access to Custom_Field__c on Account"
290
+ "Give read-only access to Rating__c field for Sales User profile"
291
+ "View which profiles have access to the Custom_Field__c"
292
+ "Revoke field access for specific profiles"
293
+ ```
294
+
295
+ ### Searching Across Objects
296
+ ```
297
+ "Search for 'cloud' in Accounts and Opportunities"
298
+ "Find mentions of 'network issue' in Cases and Knowledge Articles"
299
+ "Search for customer name across all relevant objects"
300
+ ```
301
+
302
+ ### Managing Apex Code
303
+ ```
304
+ "Show me all Apex classes with 'Controller' in the name"
305
+ "Get the full code for the AccountService class"
306
+ "Create a new Apex utility class for handling date operations"
307
+ "Update the LeadConverter class to add a new method"
308
+ ```
309
+
310
+ ### Managing Apex Triggers
311
+ ```
312
+ "List all triggers for the Account object"
313
+ "Show me the code for the ContactTrigger"
314
+ "Create a new trigger for the Opportunity object"
315
+ "Update the Case trigger to handle after delete events"
316
+ ```
317
+
318
+ ### Executing Anonymous Apex Code
319
+ ```
320
+ "Execute Apex code to calculate account metrics"
321
+ "Run a script to update related records"
322
+ "Execute a batch job to process large datasets"
323
+ ```
324
+
325
+ ### Managing Debug Logs
326
+ ```
327
+ "Enable debug logs for user@example.com"
328
+ "Retrieve recent logs for an admin user"
329
+ "Disable debug logs for a specific user"
330
+ "Configure log level to DEBUG for a user"
331
+ ```
332
+
333
+ ## Development
334
+
335
+ ### Building from source
336
+ ```bash
337
+ # Clone the repository
338
+ git clone https://github.com/tsmztech/mcp-server-salesforce.git
339
+
340
+ # Navigate to directory
341
+ cd mcp-server-salesforce
342
+
343
+ # Install dependencies
344
+ npm install
345
+
346
+ # Build the project
347
+ npm run build
348
+ ```
349
+
350
+ ## Contributing
351
+ Contributions are welcome! Feel free to submit a Pull Request.
352
+
353
+ ## License
354
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
355
+
356
+ ## Issues and Support
357
+ If you encounter any issues or need support, please file an issue on the [GitHub repository](https://github.com/tsmztech/mcp-server-salesforce/issues).
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,312 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ import * as dotenv from "dotenv";
6
+ import { createSalesforceConnection } from "./utils/connection.js";
7
+ import { SEARCH_OBJECTS, handleSearchObjects } from "./tools/search.js";
8
+ import { DESCRIBE_OBJECT, handleDescribeObject } from "./tools/describe.js";
9
+ import { QUERY_RECORDS, handleQueryRecords } from "./tools/query.js";
10
+ import { AGGREGATE_QUERY, handleAggregateQuery } from "./tools/aggregateQuery.js";
11
+ import { DML_RECORDS, handleDMLRecords } from "./tools/dml.js";
12
+ import { MANAGE_OBJECT, handleManageObject } from "./tools/manageObject.js";
13
+ import { MANAGE_FIELD, handleManageField } from "./tools/manageField.js";
14
+ import { MANAGE_FIELD_PERMISSIONS, handleManageFieldPermissions } from "./tools/manageFieldPermissions.js";
15
+ import { SEARCH_ALL, handleSearchAll } from "./tools/searchAll.js";
16
+ import { READ_APEX, handleReadApex } from "./tools/readApex.js";
17
+ import { WRITE_APEX, handleWriteApex } from "./tools/writeApex.js";
18
+ import { READ_APEX_TRIGGER, handleReadApexTrigger } from "./tools/readApexTrigger.js";
19
+ import { WRITE_APEX_TRIGGER, handleWriteApexTrigger } from "./tools/writeApexTrigger.js";
20
+ import { EXECUTE_ANONYMOUS, handleExecuteAnonymous } from "./tools/executeAnonymous.js";
21
+ import { MANAGE_DEBUG_LOGS, handleManageDebugLogs } from "./tools/manageDebugLogs.js";
22
+ import { METADATA_QUERY, handleMetadataQuery } from "./tools/metadata";
23
+ // Load environment variables (using dotenv 16.x which has no stdout tips)
24
+ // MCP servers require stdout to contain ONLY JSON-RPC messages
25
+ dotenv.config();
26
+ const server = new Server({
27
+ name: "salesforce-mcp-server",
28
+ version: "1.0.0",
29
+ }, {
30
+ capabilities: {
31
+ tools: {},
32
+ },
33
+ });
34
+ // Tool handlers
35
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
36
+ tools: [
37
+ SEARCH_OBJECTS,
38
+ DESCRIBE_OBJECT,
39
+ QUERY_RECORDS,
40
+ AGGREGATE_QUERY,
41
+ DML_RECORDS,
42
+ MANAGE_OBJECT,
43
+ MANAGE_FIELD,
44
+ MANAGE_FIELD_PERMISSIONS,
45
+ SEARCH_ALL,
46
+ READ_APEX,
47
+ WRITE_APEX,
48
+ READ_APEX_TRIGGER,
49
+ WRITE_APEX_TRIGGER,
50
+ EXECUTE_ANONYMOUS,
51
+ MANAGE_DEBUG_LOGS,
52
+ METADATA_QUERY
53
+ ],
54
+ }));
55
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
56
+ try {
57
+ const { name, arguments: args } = request.params;
58
+ if (!args)
59
+ throw new Error('Arguments are required');
60
+ const conn = await createSalesforceConnection();
61
+ switch (name) {
62
+ case "salesforce_search_objects": {
63
+ const { searchPattern } = args;
64
+ if (!searchPattern)
65
+ throw new Error('searchPattern is required');
66
+ return await handleSearchObjects(conn, searchPattern);
67
+ }
68
+ case "salesforce_describe_object": {
69
+ const { objectName } = args;
70
+ if (!objectName)
71
+ throw new Error('objectName is required');
72
+ return await handleDescribeObject(conn, objectName);
73
+ }
74
+ case "salesforce_query_records": {
75
+ const queryArgs = args;
76
+ if (!queryArgs.objectName || !Array.isArray(queryArgs.fields)) {
77
+ throw new Error('objectName and fields array are required for query');
78
+ }
79
+ // Type check and conversion
80
+ const validatedArgs = {
81
+ objectName: queryArgs.objectName,
82
+ fields: queryArgs.fields,
83
+ whereClause: queryArgs.whereClause,
84
+ orderBy: queryArgs.orderBy,
85
+ limit: queryArgs.limit
86
+ };
87
+ return await handleQueryRecords(conn, validatedArgs);
88
+ }
89
+ case "salesforce_aggregate_query": {
90
+ const aggregateArgs = args;
91
+ if (!aggregateArgs.objectName || !Array.isArray(aggregateArgs.selectFields) || !Array.isArray(aggregateArgs.groupByFields)) {
92
+ throw new Error('objectName, selectFields array, and groupByFields array are required for aggregate query');
93
+ }
94
+ // Type check and conversion
95
+ const validatedArgs = {
96
+ objectName: aggregateArgs.objectName,
97
+ selectFields: aggregateArgs.selectFields,
98
+ groupByFields: aggregateArgs.groupByFields,
99
+ whereClause: aggregateArgs.whereClause,
100
+ havingClause: aggregateArgs.havingClause,
101
+ orderBy: aggregateArgs.orderBy,
102
+ limit: aggregateArgs.limit
103
+ };
104
+ return await handleAggregateQuery(conn, validatedArgs);
105
+ }
106
+ case "salesforce_dml_records": {
107
+ const dmlArgs = args;
108
+ if (!dmlArgs.operation || !dmlArgs.objectName || !Array.isArray(dmlArgs.records)) {
109
+ throw new Error('operation, objectName, and records array are required for DML');
110
+ }
111
+ const validatedArgs = {
112
+ operation: dmlArgs.operation,
113
+ objectName: dmlArgs.objectName,
114
+ records: dmlArgs.records,
115
+ externalIdField: dmlArgs.externalIdField
116
+ };
117
+ return await handleDMLRecords(conn, validatedArgs);
118
+ }
119
+ case "salesforce_manage_object": {
120
+ const objectArgs = args;
121
+ if (!objectArgs.operation || !objectArgs.objectName) {
122
+ throw new Error('operation and objectName are required for object management');
123
+ }
124
+ const validatedArgs = {
125
+ operation: objectArgs.operation,
126
+ objectName: objectArgs.objectName,
127
+ label: objectArgs.label,
128
+ pluralLabel: objectArgs.pluralLabel,
129
+ description: objectArgs.description,
130
+ nameFieldLabel: objectArgs.nameFieldLabel,
131
+ nameFieldType: objectArgs.nameFieldType,
132
+ nameFieldFormat: objectArgs.nameFieldFormat,
133
+ sharingModel: objectArgs.sharingModel
134
+ };
135
+ return await handleManageObject(conn, validatedArgs);
136
+ }
137
+ case "salesforce_manage_field": {
138
+ const fieldArgs = args;
139
+ if (!fieldArgs.operation || !fieldArgs.objectName || !fieldArgs.fieldName) {
140
+ throw new Error('operation, objectName, and fieldName are required for field management');
141
+ }
142
+ const validatedArgs = {
143
+ operation: fieldArgs.operation,
144
+ objectName: fieldArgs.objectName,
145
+ fieldName: fieldArgs.fieldName,
146
+ label: fieldArgs.label,
147
+ type: fieldArgs.type,
148
+ required: fieldArgs.required,
149
+ unique: fieldArgs.unique,
150
+ externalId: fieldArgs.externalId,
151
+ length: fieldArgs.length,
152
+ precision: fieldArgs.precision,
153
+ scale: fieldArgs.scale,
154
+ referenceTo: fieldArgs.referenceTo,
155
+ relationshipLabel: fieldArgs.relationshipLabel,
156
+ relationshipName: fieldArgs.relationshipName,
157
+ deleteConstraint: fieldArgs.deleteConstraint,
158
+ picklistValues: fieldArgs.picklistValues,
159
+ description: fieldArgs.description,
160
+ grantAccessTo: fieldArgs.grantAccessTo
161
+ };
162
+ return await handleManageField(conn, validatedArgs);
163
+ }
164
+ case "salesforce_manage_field_permissions": {
165
+ const permArgs = args;
166
+ if (!permArgs.operation || !permArgs.objectName || !permArgs.fieldName) {
167
+ throw new Error('operation, objectName, and fieldName are required for field permissions management');
168
+ }
169
+ const validatedArgs = {
170
+ operation: permArgs.operation,
171
+ objectName: permArgs.objectName,
172
+ fieldName: permArgs.fieldName,
173
+ profileNames: permArgs.profileNames,
174
+ readable: permArgs.readable,
175
+ editable: permArgs.editable
176
+ };
177
+ return await handleManageFieldPermissions(conn, validatedArgs);
178
+ }
179
+ case "salesforce_search_all": {
180
+ const searchArgs = args;
181
+ if (!searchArgs.searchTerm || !Array.isArray(searchArgs.objects)) {
182
+ throw new Error('searchTerm and objects array are required for search');
183
+ }
184
+ // Validate objects array
185
+ const objects = searchArgs.objects;
186
+ if (!objects.every(obj => obj.name && Array.isArray(obj.fields))) {
187
+ throw new Error('Each object must specify name and fields array');
188
+ }
189
+ // Type check and conversion
190
+ const validatedArgs = {
191
+ searchTerm: searchArgs.searchTerm,
192
+ searchIn: searchArgs.searchIn,
193
+ objects: objects.map(obj => ({
194
+ name: obj.name,
195
+ fields: obj.fields,
196
+ where: obj.where,
197
+ orderBy: obj.orderBy,
198
+ limit: obj.limit
199
+ })),
200
+ withClauses: searchArgs.withClauses,
201
+ updateable: searchArgs.updateable,
202
+ viewable: searchArgs.viewable
203
+ };
204
+ return await handleSearchAll(conn, validatedArgs);
205
+ }
206
+ case "salesforce_read_apex": {
207
+ const apexArgs = args;
208
+ // Type check and conversion
209
+ const validatedArgs = {
210
+ className: apexArgs.className,
211
+ namePattern: apexArgs.namePattern,
212
+ includeMetadata: apexArgs.includeMetadata
213
+ };
214
+ return await handleReadApex(conn, validatedArgs);
215
+ }
216
+ case "salesforce_write_apex": {
217
+ const apexArgs = args;
218
+ if (!apexArgs.operation || !apexArgs.className || !apexArgs.body) {
219
+ throw new Error('operation, className, and body are required for writing Apex');
220
+ }
221
+ // Type check and conversion
222
+ const validatedArgs = {
223
+ operation: apexArgs.operation,
224
+ className: apexArgs.className,
225
+ apiVersion: apexArgs.apiVersion,
226
+ body: apexArgs.body
227
+ };
228
+ return await handleWriteApex(conn, validatedArgs);
229
+ }
230
+ case "salesforce_read_apex_trigger": {
231
+ const triggerArgs = args;
232
+ // Type check and conversion
233
+ const validatedArgs = {
234
+ triggerName: triggerArgs.triggerName,
235
+ namePattern: triggerArgs.namePattern,
236
+ includeMetadata: triggerArgs.includeMetadata
237
+ };
238
+ return await handleReadApexTrigger(conn, validatedArgs);
239
+ }
240
+ case "salesforce_write_apex_trigger": {
241
+ const triggerArgs = args;
242
+ if (!triggerArgs.operation || !triggerArgs.triggerName || !triggerArgs.body) {
243
+ throw new Error('operation, triggerName, and body are required for writing Apex trigger');
244
+ }
245
+ // Type check and conversion
246
+ const validatedArgs = {
247
+ operation: triggerArgs.operation,
248
+ triggerName: triggerArgs.triggerName,
249
+ objectName: triggerArgs.objectName,
250
+ apiVersion: triggerArgs.apiVersion,
251
+ body: triggerArgs.body
252
+ };
253
+ return await handleWriteApexTrigger(conn, validatedArgs);
254
+ }
255
+ case "salesforce_metadata_query": {
256
+ return await handleMetadataQuery(conn, args);
257
+ }
258
+ case "salesforce_execute_anonymous": {
259
+ const executeArgs = args;
260
+ if (!executeArgs.apexCode) {
261
+ throw new Error('apexCode is required for executing anonymous Apex');
262
+ }
263
+ // Type check and conversion
264
+ const validatedArgs = {
265
+ apexCode: executeArgs.apexCode,
266
+ logLevel: executeArgs.logLevel
267
+ };
268
+ return await handleExecuteAnonymous(conn, validatedArgs);
269
+ }
270
+ case "salesforce_manage_debug_logs": {
271
+ const debugLogsArgs = args;
272
+ if (!debugLogsArgs.operation || !debugLogsArgs.username) {
273
+ throw new Error('operation and username are required for managing debug logs');
274
+ }
275
+ // Type check and conversion
276
+ const validatedArgs = {
277
+ operation: debugLogsArgs.operation,
278
+ username: debugLogsArgs.username,
279
+ logLevel: debugLogsArgs.logLevel,
280
+ expirationTime: debugLogsArgs.expirationTime,
281
+ limit: debugLogsArgs.limit,
282
+ logId: debugLogsArgs.logId,
283
+ includeBody: debugLogsArgs.includeBody
284
+ };
285
+ return await handleManageDebugLogs(conn, validatedArgs);
286
+ }
287
+ default:
288
+ return {
289
+ content: [{ type: "text", text: `Unknown tool: ${name}` }],
290
+ isError: true,
291
+ };
292
+ }
293
+ }
294
+ catch (error) {
295
+ return {
296
+ content: [{
297
+ type: "text",
298
+ text: `Error: ${error instanceof Error ? error.message : String(error)}`,
299
+ }],
300
+ isError: true,
301
+ };
302
+ }
303
+ });
304
+ async function runServer() {
305
+ const transport = new StdioServerTransport();
306
+ await server.connect(transport);
307
+ console.error("Salesforce MCP Server running on stdio");
308
+ }
309
+ runServer().catch((error) => {
310
+ console.error("Fatal error running server:", error);
311
+ process.exit(1);
312
+ });