salesforce_write_apex_trigger
Create or update Apex triggers in Salesforce to automate business logic on database operations.
Instructions
Create or update Apex triggers in Salesforce.
Examples:
Create a new Apex trigger: { "operation": "create", "triggerName": "AccountTrigger", "objectName": "Account", "apiVersion": "58.0", "body": "trigger AccountTrigger on Account (before insert, before update) { /* implementation */ }" }
Update an existing Apex trigger: { "operation": "update", "triggerName": "AccountTrigger", "body": "trigger AccountTrigger on Account (before insert, before update, after update) { /* updated implementation */ }" }
Notes:
The operation must be either 'create' or 'update'
For 'create' operations, triggerName, objectName, and body are required
For 'update' operations, triggerName and body are required
apiVersion is optional for 'create' (defaults to the latest version)
The body must be valid Apex trigger code
The triggerName in the body must match the triggerName parameter
The objectName in the body must match the objectName parameter (for 'create')
Status information is returned after successful operations
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| operation | Yes | Whether to create a new trigger or update an existing one | |
| triggerName | Yes | Name of the Apex trigger to create or update | |
| objectName | No | Name of the Salesforce object the trigger is for (required for 'create') | |
| apiVersion | No | API version for the Apex trigger (e.g., '58.0') | |
| body | Yes | Full body of the Apex trigger |
Implementation Reference
- src/tools/writeApexTrigger.ts:76-206 (handler)Core handler function that validates arguments, performs create/update operations on ApexTriggers using Salesforce Tooling API, and returns formatted success/error responses.export async function handleWriteApexTrigger(conn: any, args: WriteApexTriggerArgs) { try { // Validate inputs if (!args.triggerName) { throw new Error('triggerName is required'); } if (!args.body) { throw new Error('body is required'); } // Check if the trigger name in the body matches the provided triggerName const triggerNameRegex = new RegExp(`\\btrigger\\s+${args.triggerName}\\b`); if (!triggerNameRegex.test(args.body)) { throw new Error(`The trigger name in the body must match the provided triggerName: ${args.triggerName}`); } // Handle create operation if (args.operation === 'create') { console.error(`Creating new Apex trigger: ${args.triggerName}`); // Validate object name for create operation if (!args.objectName) { throw new Error('objectName is required for creating a new trigger'); } // Check if the object name in the body matches the provided objectName const objectNameRegex = new RegExp(`\\bon\\s+${args.objectName}\\b`); if (!objectNameRegex.test(args.body)) { throw new Error(`The object name in the body must match the provided objectName: ${args.objectName}`); } // Check if trigger already exists const existingTrigger = await conn.query(` SELECT Id FROM ApexTrigger WHERE Name = '${args.triggerName}' `); if (existingTrigger.records.length > 0) { throw new Error(`Apex trigger with name '${args.triggerName}' already exists. Use 'update' operation instead.`); } // Create the new trigger using the Tooling API const createResult = await conn.tooling.sobject('ApexTrigger').create({ Name: args.triggerName, TableEnumOrId: args.objectName, Body: args.body, ApiVersion: args.apiVersion || '58.0', // Default to latest if not specified Status: 'Active' }); if (!createResult.success) { throw new Error(`Failed to create Apex trigger: ${createResult.errors.join(', ')}`); } return { content: [{ type: "text", text: `Successfully created Apex trigger: ${args.triggerName}\n\n` + `**ID:** ${createResult.id}\n` + `**Object:** ${args.objectName}\n` + `**API Version:** ${args.apiVersion || '58.0'}\n` + `**Status:** Active` }] }; } // Handle update operation else if (args.operation === 'update') { console.error(`Updating Apex trigger: ${args.triggerName}`); // Find the existing trigger const existingTrigger = await conn.query(` SELECT Id, TableEnumOrId FROM ApexTrigger WHERE Name = '${args.triggerName}' `); if (existingTrigger.records.length === 0) { throw new Error(`No Apex trigger found with name: ${args.triggerName}. Use 'create' operation instead.`); } const triggerId = existingTrigger.records[0].Id; const objectName = existingTrigger.records[0].TableEnumOrId; // Check if the object name in the body matches the existing object const objectNameRegex = new RegExp(`\\bon\\s+${objectName}\\b`); if (!objectNameRegex.test(args.body)) { throw new Error(`The object name in the body must match the existing object: ${objectName}`); } // Update the trigger using the Tooling API const updateResult = await conn.tooling.sobject('ApexTrigger').update({ Id: triggerId, Body: args.body }); if (!updateResult.success) { throw new Error(`Failed to update Apex trigger: ${updateResult.errors.join(', ')}`); } // Get the updated trigger details const updatedTrigger = await conn.query(` SELECT Id, Name, TableEnumOrId, ApiVersion, Status, LastModifiedDate FROM ApexTrigger WHERE Id = '${triggerId}' `); const triggerDetails = updatedTrigger.records[0]; return { content: [{ type: "text", text: `Successfully updated Apex trigger: ${args.triggerName}\n\n` + `**ID:** ${triggerId}\n` + `**Object:** ${triggerDetails.TableEnumOrId}\n` + `**API Version:** ${triggerDetails.ApiVersion}\n` + `**Status:** ${triggerDetails.Status}\n` + `**Last Modified:** ${new Date(triggerDetails.LastModifiedDate).toLocaleString()}` }] }; } else { throw new Error(`Invalid operation: ${args.operation}. Must be 'create' or 'update'.`); } } catch (error) { console.error('Error writing Apex trigger:', error); return { content: [{ type: "text", text: `Error writing Apex trigger: ${error instanceof Error ? error.message : String(error)}` }], isError: true, }; } }
- src/tools/writeApexTrigger.ts:3-60 (schema)Tool schema definition including name, description, and input validation schema for the salesforce_write_apex_trigger tool.export const WRITE_APEX_TRIGGER: Tool = { name: "salesforce_write_apex_trigger", description: `Create or update Apex triggers in Salesforce. Examples: 1. Create a new Apex trigger: { "operation": "create", "triggerName": "AccountTrigger", "objectName": "Account", "apiVersion": "58.0", "body": "trigger AccountTrigger on Account (before insert, before update) { /* implementation */ }" } 2. Update an existing Apex trigger: { "operation": "update", "triggerName": "AccountTrigger", "body": "trigger AccountTrigger on Account (before insert, before update, after update) { /* updated implementation */ }" } Notes: - The operation must be either 'create' or 'update' - For 'create' operations, triggerName, objectName, and body are required - For 'update' operations, triggerName and body are required - apiVersion is optional for 'create' (defaults to the latest version) - The body must be valid Apex trigger code - The triggerName in the body must match the triggerName parameter - The objectName in the body must match the objectName parameter (for 'create') - Status information is returned after successful operations`, inputSchema: { type: "object", properties: { operation: { type: "string", enum: ["create", "update"], description: "Whether to create a new trigger or update an existing one" }, triggerName: { type: "string", description: "Name of the Apex trigger to create or update" }, objectName: { type: "string", description: "Name of the Salesforce object the trigger is for (required for 'create')" }, apiVersion: { type: "string", description: "API version for the Apex trigger (e.g., '58.0')" }, body: { type: "string", description: "Full body of the Apex trigger" } }, required: ["operation", "triggerName", "body"] } };
- src/index.ts:270-286 (registration)Switch case registration in the main tool dispatcher that validates input, casts to WriteApexTriggerArgs, and invokes the handler.case "salesforce_write_apex_trigger": { const triggerArgs = args as Record<string, unknown>; if (!triggerArgs.operation || !triggerArgs.triggerName || !triggerArgs.body) { throw new Error('operation, triggerName, and body are required for writing Apex trigger'); } // Type check and conversion const validatedArgs: WriteApexTriggerArgs = { operation: triggerArgs.operation as 'create' | 'update', triggerName: triggerArgs.triggerName as string, objectName: triggerArgs.objectName as string | undefined, apiVersion: triggerArgs.apiVersion as string | undefined, body: triggerArgs.body as string }; return await handleWriteApexTrigger(conn, validatedArgs); }
- src/index.ts:59-59 (registration)Registration of the tool schema in the listTools handler for tool discovery.WRITE_APEX_TRIGGER,