UNPKG

@advanced-communities/salesforce-mcp-server

Version:

MCP server enabling AI assistants to interact with Salesforce orgs through the Salesforce CLI

114 lines (113 loc) 4.63 kB
import { z } from "zod"; import { permissions } from "../config/permissions.js"; import { executeSfCommand } from "../utils/sfCommand.js"; const deployStart = async (targetOrg, dryRun, manifest, metadata, metadataDirectory, singlePackage, sourceDirectory, tests, testLevel) => { let sfCommand = `sf project deploy start --target-org ${targetOrg} --json `; if (dryRun) { sfCommand += `--dry-run `; } if (manifest && manifest.length > 0) { sfCommand += `--manifest ${manifest} `; } if (metadata && metadata.length > 0) { sfCommand += `--metadata ${metadata} `; } if (metadataDirectory && metadataDirectory.length > 0) { sfCommand += `--metadata-dir ${metadataDirectory} `; } if (singlePackage) { sfCommand += `--single-package `; } if (sourceDirectory && sourceDirectory.length > 0) { sfCommand += `--source-dir ${sourceDirectory} `; } if (tests && tests.length > 0) { sfCommand += `--tests ${tests} `; } if (testLevel && testLevel.length > 0) { sfCommand += `--test-level ${testLevel} `; } try { const result = await executeSfCommand(sfCommand); return result; } catch (error) { throw error; } }; export const registerProjectTools = (server) => { server.tool("deploy_start", "Deploy metadata to Salesforce org with test execution options.", { input: z.object({ targetOrg: z.string().describe("Target org username or alias."), dryRun: z .boolean() .describe("Validate only, don't save changes."), manifest: z .string() .optional() .describe("Package.xml manifest path. Excludes --metadata and --source-dir."), metadata: z .string() .optional() .describe("Component names to deploy. Supports wildcards with quotes."), metadataDirectory: z .string() .optional() .describe("Metadata directory or zip file to deploy."), singlePackage: z .boolean() .optional() .describe("Metadata zip contains single package structure."), sourceDirectory: z .string() .optional() .describe("Local source path to deploy - can be a directory OR a specific file path (e.g., 'force-app/main' or 'force-app/main/default/classes/MyClass.cls'). For single file deployment, provide the exact file path. If you specify this flag, don't specify --metadata or --manifest."), tests: z .string() .optional() .describe("Tests for RunSpecifiedTests level. Quote names with spaces. Separate multiple with spaces or repeat flag."), testLevel: z .string() .optional() .describe("Test level: NoTestRun (dev only), RunSpecifiedTests (75% coverage), RunLocalTests (default prod), RunAllTestsInOrg."), }), }, async ({ input }) => { const { targetOrg, dryRun, manifest, metadata, metadataDirectory, singlePackage, sourceDirectory, tests, testLevel, } = input; if (permissions.isReadOnly()) { return { content: [ { type: "text", text: JSON.stringify({ success: false, compiled: false, compileProblem: "Operation not allowed: Cannot generate components in READ_ONLY mode", }), }, ], }; } if (!permissions.isOrgAllowed(targetOrg)) { return { content: [ { type: "text", text: JSON.stringify({ success: false, message: `Access denied: Org '${targetOrg}' is not in the allowed list`, }), }, ], }; } const result = await deployStart(targetOrg, dryRun, manifest || "", metadata || "", metadataDirectory || "", singlePackage || false, sourceDirectory || "", tests || "", testLevel || ""); return { content: [ { type: "text", text: JSON.stringify(result), }, ], }; }); };