salesforce-metadata-mcp 2.1.2 → 2.1.4
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.
- package/AGENTFORCE.md +287 -65
- package/CHANGELOG.md +101 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -0
- package/dist/index.js.map +1 -1
- package/dist/schemas/index.js +76 -27
- package/dist/services/deployment.js +99 -0
- package/dist/services/salesforce.js +401 -18
- package/dist/tools/agentforce.js +255 -43
- package/package.json +1 -1
package/dist/schemas/index.js
CHANGED
|
@@ -858,37 +858,86 @@ export const CreateExperiencePageSchema = z.object({
|
|
|
858
858
|
}).strict();
|
|
859
859
|
// ─── AGENTFORCE ───────────────────────────────────────────────────────────────
|
|
860
860
|
export const CreateAgentSchema = z.object({
|
|
861
|
-
agentName: z.string().min(1).max(80).regex(/^[A-Za-z][A-Za-z0-9_]*$/).describe("Agent API name, e.g. '
|
|
862
|
-
label: z.string().min(1).max(255).describe("Agent display
|
|
863
|
-
description: z.string().max(1000).optional().describe("Agent description
|
|
864
|
-
type: z.enum(["
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
tone: z.enum(["Formal", "Neutral", "Casual"]).default("Neutral").describe("Communication tone"),
|
|
868
|
-
instructions: z.string().max(10000).optional().describe("System-level instructions for the agent"),
|
|
861
|
+
agentName: z.string().min(1).max(80).regex(/^[A-Za-z][A-Za-z0-9_]*$/).describe("Agent API name, e.g. 'CRM_Record_Creator'. IMMUTABLE after creation."),
|
|
862
|
+
label: z.string().min(1).max(255).describe("Agent display label, e.g. 'CRM Record Creator'"),
|
|
863
|
+
description: z.string().max(1000).optional().describe("Agent description"),
|
|
864
|
+
type: z.enum(["EinsteinCopilot", "ExternalCopilot"]).default("EinsteinCopilot").describe("Bot type: 'EinsteinCopilot' for internal employee agents (shown in Lightning sidebar), 'ExternalCopilot' for customer-facing Agentforce Service Agents. CANNOT be changed after creation."),
|
|
865
|
+
systemPrompt: z.string().max(32000).optional().describe("Custom system prompt to override the agent's default behavior and persona. Injected into the agent's context before every conversation."),
|
|
866
|
+
openingMessage: z.string().max(2000).optional().describe("Welcome message shown to users when they first open the agent (set as welcomeMessage on the Bot)."),
|
|
869
867
|
}).strict();
|
|
870
868
|
export const CreateAgentTopicSchema = z.object({
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
869
|
+
topicName: z.string().min(1).max(80).regex(/^[A-Za-z][A-Za-z0-9_]*$/).describe("Topic API name, e.g. 'Create_Account_Topic'. Used as the GenAiPlugin developer name."),
|
|
870
|
+
label: z.string().min(1).max(255).describe("Topic display label, e.g. 'Create Account Topic'"),
|
|
871
|
+
description: z.string().min(1).max(5000).describe("Routing description — the LLM uses this to decide which topic handles a user request. Be specific, e.g. 'Use this topic when the user wants to create, add, or make a new Account or company record'"),
|
|
872
|
+
scope: z.string().min(1).max(5000).describe("What this topic covers in detail, e.g. 'Create new Account records with company name, industry, phone, and website'"),
|
|
873
|
+
instructions: z.array(z.string().max(2000)).optional().describe("Ordered step-by-step instructions for the agent, e.g. ['Ask the user for the account name', 'Call the Create Account action', 'Confirm success to the user']"),
|
|
874
|
+
actions: z.array(z.string().max(80)).optional().describe("Action API names (GenAiFunction developer names) to associate, e.g. ['Create_Account']. Create actions first with sf_create_agent_action."),
|
|
875
|
+
escalationEnabled: z.boolean().optional().describe("Whether this topic can escalate to a human agent (sets canEscalate on GenAiPlugin). Default: false."),
|
|
876
|
+
fallbackTopic: z.string().max(80).optional().describe("API name of another GenAiPlugin topic to fall back to if this topic cannot handle the request."),
|
|
878
877
|
}).strict();
|
|
878
|
+
const AgentParamSchema = z.object({
|
|
879
|
+
name: z.string().max(80).describe("Parameter API name matching the flow variable name, e.g. 'AccountName'"),
|
|
880
|
+
label: z.string().max(255).describe("Human-readable label, e.g. 'Account Name'"),
|
|
881
|
+
description: z.string().max(1000).optional().describe("Description shown to the LLM, e.g. 'The name of the company or organization'"),
|
|
882
|
+
type: z.enum(["Text", "Number", "Currency", "Boolean", "Date", "DateTime", "TextArea"]).default("Text").describe("Data type — must match the flow variable type: 'Currency'/'Number' for numeric fields, 'Date' for date fields, 'Boolean' for checkboxes, 'Text' for everything else"),
|
|
883
|
+
required: z.boolean().default(true).describe("Whether this input is required"),
|
|
884
|
+
});
|
|
879
885
|
export const CreateAgentActionSchema = z.object({
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
886
|
+
actionName: z.string().min(1).max(80).regex(/^[A-Za-z][A-Za-z0-9_]*$/).describe("Action API name (GenAiFunction developer name), e.g. 'Create_Account'. Used to reference this action from topics."),
|
|
887
|
+
label: z.string().min(1).max(255).describe("Action display label, e.g. 'Create Account'"),
|
|
888
|
+
description: z.string().min(1).max(5000).describe("What this action does — the LLM uses this to decide when to invoke it. Be specific, e.g. 'Creates a new Account record in Salesforce with the given company name, industry, phone, and website'"),
|
|
889
|
+
invocationTargetType: z.enum(["Flow", "ApexClass"]).default("Flow").describe("Type of backend to invoke: 'Flow' for AutoLaunchedFlow (most common), 'ApexClass' for an Apex class implementing InvocableMethod."),
|
|
890
|
+
flowApiName: z.string().max(255).optional().describe("API name of the AutoLaunchedFlow to invoke (required when invocationTargetType is Flow). Must be Active with runInMode=SystemModeWithoutSharing."),
|
|
891
|
+
apexClassName: z.string().max(255).optional().describe("API name of the Apex class to invoke (required when invocationTargetType is ApexClass). Class must have an @InvocableMethod."),
|
|
892
|
+
inputs: z.array(AgentParamSchema).optional().describe("Input parameters. Each becomes a parameter the LLM collects from the user. Type MUST match the flow variable / Apex param type."),
|
|
893
|
+
outputs: z.array(AgentParamSchema.omit({ required: true })).optional().describe("Output parameters returned to the agent after execution, e.g. the created record ID"),
|
|
894
|
+
}).strict();
|
|
895
|
+
export const CreateAgentPlannerSchema = z.object({
|
|
896
|
+
plannerName: z.string().min(1).max(80).regex(/^[A-Za-z][A-Za-z0-9_]*$/).describe("Planner API name, e.g. 'CRM_Creator_Planner'. NOTE: Names are permanently reserved even after deletion — use a unique name."),
|
|
897
|
+
label: z.string().min(1).max(255).describe("Planner display label, e.g. 'CRM Creator Planner'"),
|
|
898
|
+
description: z.string().max(1000).optional().describe("Planner description"),
|
|
899
|
+
topicNames: z.array(z.string().min(1).max(80)).min(1).describe("Topic API names (GenAiPlugin developer names) to include, e.g. ['Create_Account_Topic', 'Create_Lead_Topic']. Topics must already exist."),
|
|
900
|
+
dataLibraryName: z.string().max(80).optional().describe("API name of a Data Library (Knowledge Base) to attach to this planner for Knowledge-grounded agents."),
|
|
901
|
+
}).strict();
|
|
902
|
+
export const GetAgentSchema = z.object({
|
|
903
|
+
agentApiName: z.string().min(1).max(80).describe("Agent API name, e.g. 'CRM_Record_Creator'"),
|
|
904
|
+
}).strict();
|
|
905
|
+
export const UpdateAgentTopicSchema = z.object({
|
|
906
|
+
agentApiName: z.string().min(1).max(80).describe("API name of the agent that owns this topic. The agent is automatically deactivated before the update and reactivated after."),
|
|
907
|
+
topicName: z.string().min(1).max(80).regex(/^[A-Za-z][A-Za-z0-9_]*$/).describe("Topic API name to update (GenAiPlugin developer name)"),
|
|
908
|
+
label: z.string().min(1).max(255).describe("Updated topic display label"),
|
|
909
|
+
description: z.string().min(1).max(5000).describe("Updated routing description"),
|
|
910
|
+
scope: z.string().min(1).max(5000).describe("Updated scope"),
|
|
911
|
+
instructions: z.array(z.string().max(2000)).optional().describe("Updated step-by-step instructions (replaces existing)"),
|
|
912
|
+
actions: z.array(z.string().max(80)).optional().describe("Updated action API names (replaces existing)"),
|
|
913
|
+
escalationEnabled: z.boolean().optional().describe("Whether this topic can escalate to a human agent"),
|
|
914
|
+
fallbackTopic: z.string().max(80).optional().describe("API name of fallback topic"),
|
|
915
|
+
}).strict();
|
|
916
|
+
export const UpdateAgentActionSchema = z.object({
|
|
917
|
+
actionName: z.string().min(1).max(80).regex(/^[A-Za-z][A-Za-z0-9_]*$/).describe("Action API name to update (GenAiFunction developer name)"),
|
|
918
|
+
label: z.string().min(1).max(255).describe("Updated action display label"),
|
|
919
|
+
description: z.string().min(1).max(5000).describe("Updated action description"),
|
|
920
|
+
invocationTargetType: z.enum(["Flow", "ApexClass"]).default("Flow").describe("Type of backend to invoke"),
|
|
921
|
+
flowApiName: z.string().max(255).optional().describe("API name of the AutoLaunchedFlow (required if invocationTargetType is Flow)"),
|
|
922
|
+
apexClassName: z.string().max(255).optional().describe("API name of the Apex class (required if invocationTargetType is ApexClass)"),
|
|
923
|
+
inputs: z.array(AgentParamSchema).optional().describe("Updated input parameters (replaces existing)"),
|
|
924
|
+
outputs: z.array(AgentParamSchema.omit({ required: true })).optional().describe("Updated output parameters (replaces existing)"),
|
|
925
|
+
}).strict();
|
|
926
|
+
export const DeleteAgentSchema = z.object({
|
|
927
|
+
agentApiName: z.string().min(1).max(80).describe("API name of the agent to delete, e.g. 'CRM_Record_Creator'"),
|
|
928
|
+
deleteTopics: z.boolean().default(false).describe("If true, also deletes the agent's GenAiPlugin topics (identified via its GenAiPlannerBundle)"),
|
|
929
|
+
deleteActions: z.boolean().default(false).describe("If true, also deletes the GenAiFunction actions referenced by the agent's topics"),
|
|
930
|
+
}).strict();
|
|
931
|
+
export const ListAgentsSchema = z.object({}).strict();
|
|
932
|
+
export const TestAgentSchema = z.object({
|
|
933
|
+
agentApiName: z.string().min(1).max(80).describe("API name of the agent to test, e.g. 'CRM_Record_Creator'"),
|
|
934
|
+
message: z.string().min(1).max(5000).describe("Test message to send to the agent, e.g. 'Create an account called Acme Corp'"),
|
|
935
|
+
orgUrl: z.string().url().optional().describe("Override the Agentforce bootstrap URL (defaults to SF_INSTANCE_URL). Required only if your My Domain URL differs from the instance URL."),
|
|
936
|
+
}).strict();
|
|
937
|
+
export const GetAgentLogsSchema = z.object({
|
|
938
|
+
agentApiName: z.string().max(80).optional().describe("Filter logs by agent API name (optional — omit to see all agent activity in the org)"),
|
|
939
|
+
limit: z.number().int().min(1).max(200).default(20).describe("Maximum number of log entries to return (default: 20)"),
|
|
940
|
+
hoursBack: z.number().min(0.1).max(24).default(1).describe("How many hours back to look (default: 1 hour)"),
|
|
892
941
|
}).strict();
|
|
893
942
|
// ─── MCP SERVER MANAGEMENT ───────────────────────────────────────────────────
|
|
894
943
|
export const CreateMcpServerSchema = z.object({
|
|
@@ -64,6 +64,105 @@ export async function buildStaticResourceZip(resourceName, content, contentType,
|
|
|
64
64
|
const buffer = await zip.generateAsync({ type: "nodebuffer" });
|
|
65
65
|
return buffer.toString("base64");
|
|
66
66
|
}
|
|
67
|
+
export async function buildGenAiActionZip(params, apiVersion) {
|
|
68
|
+
const zip = new JSZip();
|
|
69
|
+
const functionName = params.actionName;
|
|
70
|
+
const packageXml = buildPackageXml([{ name: "GenAiFunction", members: [functionName] }], apiVersion);
|
|
71
|
+
zip.file("package.xml", packageXml);
|
|
72
|
+
// Build mappingAttributes XML
|
|
73
|
+
const inputsXml = (params.inputs ?? []).map(inp => `
|
|
74
|
+
<mappingAttributes>
|
|
75
|
+
<description>${escapeXml(inp.description ?? inp.label)}</description>
|
|
76
|
+
<label>${escapeXml(inp.label)}</label>
|
|
77
|
+
<name>${escapeXml(inp.name)}</name>
|
|
78
|
+
<parameterName>${escapeXml(inp.name)}</parameterName>
|
|
79
|
+
<parameterType>input</parameterType>
|
|
80
|
+
</mappingAttributes>`).join("\n");
|
|
81
|
+
const outputsXml = (params.outputs ?? []).map(out => `
|
|
82
|
+
<mappingAttributes>
|
|
83
|
+
<description>${escapeXml(out.description ?? out.label)}</description>
|
|
84
|
+
<label>${escapeXml(out.label)}</label>
|
|
85
|
+
<name>${escapeXml(out.name)}</name>
|
|
86
|
+
<parameterName>${escapeXml(out.name)}</parameterName>
|
|
87
|
+
<parameterType>output</parameterType>
|
|
88
|
+
</mappingAttributes>`).join("\n");
|
|
89
|
+
const isApex = params.invocationTargetType === "ApexClass";
|
|
90
|
+
const invocationTarget = isApex ? (params.apexClassName ?? "") : (params.flowApiName ?? "");
|
|
91
|
+
const invocationTargetType = isApex ? "apexClass" : "flow";
|
|
92
|
+
const functionXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
93
|
+
<GenAiFunction xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
94
|
+
<description>${escapeXml(params.description)}</description>
|
|
95
|
+
<invocationTarget>${escapeXml(invocationTarget)}</invocationTarget>
|
|
96
|
+
<invocationTargetType>${invocationTargetType}</invocationTargetType>
|
|
97
|
+
<isConfirmationRequired>false</isConfirmationRequired>
|
|
98
|
+
<masterLabel>${escapeXml(params.label)}</masterLabel>
|
|
99
|
+
${inputsXml}
|
|
100
|
+
${outputsXml}
|
|
101
|
+
</GenAiFunction>`;
|
|
102
|
+
zip.file(`genAiFunctions/${functionName}/${functionName}.genAiFunction-meta.xml`, functionXml);
|
|
103
|
+
// Build input schema JSON
|
|
104
|
+
const inputSchemaProps = {};
|
|
105
|
+
const requiredInputs = [];
|
|
106
|
+
for (const inp of (params.inputs ?? [])) {
|
|
107
|
+
inputSchemaProps[inp.name] = {
|
|
108
|
+
"title": inp.label,
|
|
109
|
+
"description": inp.description ?? inp.label,
|
|
110
|
+
"lightning:type": lightningTypeFor(inp.type ?? "Text"),
|
|
111
|
+
"lightning:isPII": false,
|
|
112
|
+
"copilotAction:isUserInput": true
|
|
113
|
+
};
|
|
114
|
+
if (inp.required !== false) {
|
|
115
|
+
requiredInputs.push(inp.name);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const inputSchema = {
|
|
119
|
+
"required": requiredInputs.length > 0 ? requiredInputs : undefined,
|
|
120
|
+
"unevaluatedProperties": false,
|
|
121
|
+
"properties": inputSchemaProps,
|
|
122
|
+
"lightning:type": "lightning__objectType"
|
|
123
|
+
};
|
|
124
|
+
if (!inputSchema.required) {
|
|
125
|
+
delete inputSchema.required;
|
|
126
|
+
}
|
|
127
|
+
zip.file(`genAiFunctions/${functionName}/input/schema.json`, JSON.stringify(inputSchema, null, 2));
|
|
128
|
+
// Build output schema JSON
|
|
129
|
+
const outputSchemaProps = {};
|
|
130
|
+
for (const out of (params.outputs ?? [])) {
|
|
131
|
+
outputSchemaProps[out.name] = {
|
|
132
|
+
"title": out.label,
|
|
133
|
+
"description": out.description ?? out.label,
|
|
134
|
+
"lightning:type": lightningTypeFor(out.type ?? "Text"),
|
|
135
|
+
"lightning:isPII": false,
|
|
136
|
+
"copilotAction:isDisplayable": true,
|
|
137
|
+
"copilotAction:isUsedByPlanner": true
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const outputSchema = {
|
|
141
|
+
"unevaluatedProperties": false,
|
|
142
|
+
"properties": outputSchemaProps,
|
|
143
|
+
"lightning:type": "lightning__objectType"
|
|
144
|
+
};
|
|
145
|
+
zip.file(`genAiFunctions/${functionName}/output/schema.json`, JSON.stringify(outputSchema, null, 2));
|
|
146
|
+
const buffer = await zip.generateAsync({ type: "nodebuffer" });
|
|
147
|
+
return buffer.toString("base64");
|
|
148
|
+
}
|
|
149
|
+
function escapeXml(s) {
|
|
150
|
+
return String(s ?? "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
151
|
+
}
|
|
152
|
+
function lightningTypeFor(sfType) {
|
|
153
|
+
const t = sfType.toLowerCase();
|
|
154
|
+
if (t === "currency" || t === "number" || t === "double" || t === "integer" || t === "percent")
|
|
155
|
+
return "lightning__numberType";
|
|
156
|
+
if (t === "boolean" || t === "checkbox")
|
|
157
|
+
return "lightning__booleanType";
|
|
158
|
+
if (t === "date")
|
|
159
|
+
return "lightning__dateType";
|
|
160
|
+
if (t === "datetime")
|
|
161
|
+
return "lightning__dateTimeType";
|
|
162
|
+
if (t === "textarea" || t === "longtextarea" || t === "richtext")
|
|
163
|
+
return "lightning__textAreaType";
|
|
164
|
+
return "lightning__textType";
|
|
165
|
+
}
|
|
67
166
|
export async function buildGenericDeployZip(components, apiVersion) {
|
|
68
167
|
const zip = new JSZip();
|
|
69
168
|
const typeMap = new Map();
|