salesforce_execute_anonymous
Execute anonymous Apex code in Salesforce to test scripts, debug issues, or perform data operations when other tools are unavailable.
Instructions
Execute anonymous Apex code in Salesforce.
Examples:
Execute simple Apex code: { "apexCode": "System.debug('Hello World');" }
Execute Apex code with variables: { "apexCode": "List accounts = [SELECT Id, Name FROM Account LIMIT 5]; for(Account a : accounts) { System.debug(a.Name); }" }
Execute Apex with debug logs: { "apexCode": "System.debug(LoggingLevel.INFO, 'Processing accounts...'); List accounts = [SELECT Id FROM Account LIMIT 10]; System.debug(LoggingLevel.INFO, 'Found ' + accounts.size() + ' accounts');", "logLevel": "DEBUG" }
Notes:
The apexCode parameter is required and must contain valid Apex code
The code is executed in an anonymous context and does not persist
The logLevel parameter is optional (defaults to 'DEBUG')
Execution results include compilation success/failure, execution success/failure, and debug logs
For security reasons, some operations may be restricted based on user permissions
This tool can be used for data operations or updates when there are no other specific tools available
When users request data queries or updates that aren't directly supported by other tools, this tool can be used if the operation is achievable using Apex code
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| apexCode | Yes | Apex code to execute anonymously | |
| logLevel | No | Log level for debug logs (optional, defaults to DEBUG) |
Implementation Reference
- src/tools/executeAnonymous.ts:62-145 (handler)The main handler function that executes anonymous Apex code using Salesforce Tooling API. It validates input, executes the code via conn.tooling.executeAnonymous, formats results including compilation/execution status and debug logs, and returns formatted text response.export async function handleExecuteAnonymous(conn: any, args: ExecuteAnonymousArgs) { try { // Validate inputs if (!args.apexCode || args.apexCode.trim() === '') { throw new Error('apexCode is required and cannot be empty'); } console.error(`Executing anonymous Apex code`); // Set default log level if not provided const logLevel = args.logLevel || 'DEBUG'; // Execute the anonymous Apex code const result = await conn.tooling.executeAnonymous(args.apexCode); // Format the response let responseText = ''; // Add compilation and execution status if (result.compiled) { responseText += `**Compilation:** Success\n`; } else { responseText += `**Compilation:** Failed\n`; responseText += `**Line:** ${result.line}\n`; responseText += `**Column:** ${result.column}\n`; responseText += `**Error:** ${result.compileProblem}\n\n`; } if (result.compiled && result.success) { responseText += `**Execution:** Success\n`; } else if (result.compiled) { responseText += `**Execution:** Failed\n`; responseText += `**Error:** ${result.exceptionMessage}\n`; if (result.exceptionStackTrace) { responseText += `**Stack Trace:**\n\`\`\`\n${result.exceptionStackTrace}\n\`\`\`\n\n`; } } // Get debug logs if available if (result.compiled) { try { // Query for the most recent debug log const logs = await conn.query(` SELECT Id, LogUserId, Operation, Application, Status, LogLength, LastModifiedDate, Request FROM ApexLog ORDER BY LastModifiedDate DESC LIMIT 1 `); if (logs.records.length > 0) { const logId = logs.records[0].Id; // Retrieve the log body const logBody = await conn.tooling.request({ method: 'GET', url: `${conn.instanceUrl}/services/data/v58.0/tooling/sobjects/ApexLog/${logId}/Body` }); responseText += `\n**Debug Log:**\n\`\`\`\n${logBody}\n\`\`\``; } else { responseText += `\n**Debug Log:** No logs available. Ensure debug logs are enabled for your user.`; } } catch (logError) { responseText += `\n**Debug Log:** Unable to retrieve debug logs: ${logError instanceof Error ? logError.message : String(logError)}`; } } return { content: [{ type: "text", text: responseText }] }; } catch (error) { console.error('Error executing anonymous Apex:', error); return { content: [{ type: "text", text: `Error executing anonymous Apex: ${error instanceof Error ? error.message : String(error)}` }], isError: true, }; } }
- src/tools/executeAnonymous.ts:4-49 (schema)Tool schema definition including name, description, and input schema for validating apexCode (required string) and optional logLevel enum.export const EXECUTE_ANONYMOUS: Tool = { name: "salesforce_execute_anonymous", description: `Execute anonymous Apex code in Salesforce. Examples: 1. Execute simple Apex code: { "apexCode": "System.debug('Hello World');" } 2. Execute Apex code with variables: { "apexCode": "List<Account> accounts = [SELECT Id, Name FROM Account LIMIT 5]; for(Account a : accounts) { System.debug(a.Name); }" } 3. Execute Apex with debug logs: { "apexCode": "System.debug(LoggingLevel.INFO, 'Processing accounts...'); List<Account> accounts = [SELECT Id FROM Account LIMIT 10]; System.debug(LoggingLevel.INFO, 'Found ' + accounts.size() + ' accounts');", "logLevel": "DEBUG" } Notes: - The apexCode parameter is required and must contain valid Apex code - The code is executed in an anonymous context and does not persist - The logLevel parameter is optional (defaults to 'DEBUG') - Execution results include compilation success/failure, execution success/failure, and debug logs - For security reasons, some operations may be restricted based on user permissions - This tool can be used for data operations or updates when there are no other specific tools available - When users request data queries or updates that aren't directly supported by other tools, this tool can be used if the operation is achievable using Apex code `, inputSchema: { type: "object", properties: { apexCode: { type: "string", description: "Apex code to execute anonymously" }, logLevel: { type: "string", enum: ["NONE", "ERROR", "WARN", "INFO", "DEBUG", "FINE", "FINER", "FINEST"], description: "Log level for debug logs (optional, defaults to DEBUG)" } }, required: ["apexCode"] } };
- src/index.ts:45-63 (registration)Registers the EXECUTE_ANONYMOUS tool in the list of available tools returned by listTools request.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ SEARCH_OBJECTS, DESCRIBE_OBJECT, QUERY_RECORDS, AGGREGATE_QUERY, DML_RECORDS, MANAGE_OBJECT, MANAGE_FIELD, MANAGE_FIELD_PERMISSIONS, SEARCH_ALL, READ_APEX, WRITE_APEX, READ_APEX_TRIGGER, WRITE_APEX_TRIGGER, EXECUTE_ANONYMOUS, MANAGE_DEBUG_LOGS ], }));
- src/index.ts:288-301 (registration)Switch case in CallToolRequest handler that validates arguments and dispatches to the handleExecuteAnonymous function.case "salesforce_execute_anonymous": { const executeArgs = args as Record<string, unknown>; if (!executeArgs.apexCode) { throw new Error('apexCode is required for executing anonymous Apex'); } // Type check and conversion const validatedArgs: ExecuteAnonymousArgs = { apexCode: executeArgs.apexCode as string, logLevel: executeArgs.logLevel as 'NONE' | 'ERROR' | 'WARN' | 'INFO' | 'DEBUG' | 'FINE' | 'FINER' | 'FINEST' | undefined }; return await handleExecuteAnonymous(conn, validatedArgs); }
- src/tools/executeAnonymous.ts:51-54 (schema)TypeScript interface defining the input arguments for the handler, matching the inputSchema.export interface ExecuteAnonymousArgs { apexCode: string; logLevel?: 'NONE' | 'ERROR' | 'WARN' | 'INFO' | 'DEBUG' | 'FINE' | 'FINER' | 'FINEST'; }