salesforce-metadata-mcp 2.1.2 → 2.1.3
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 +168 -70
- package/CHANGELOG.md +57 -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 +30 -28
- package/dist/services/deployment.js +96 -0
- package/dist/services/salesforce.js +69 -18
- package/dist/tools/agentforce.js +82 -29
- package/package.json +1 -1
package/AGENTFORCE.md
CHANGED
|
@@ -6,120 +6,218 @@ Complete guide for creating Agentforce agents with `salesforce-metadata-mcp`.
|
|
|
6
6
|
|
|
7
7
|
## Overview
|
|
8
8
|
|
|
9
|
-
Agentforce (Einstein Copilot) agents
|
|
9
|
+
Agentforce (Einstein Copilot) agents are built from these metadata types, which must be created in order:
|
|
10
10
|
|
|
11
|
-
1. **
|
|
12
|
-
2. **
|
|
13
|
-
3. **
|
|
11
|
+
1. **AutoLaunchedFlow** — the action's implementation; must be Active with `runInMode=SystemModeWithoutSharing`
|
|
12
|
+
2. **GenAiFunction** — wraps a flow as an agent action; includes LLM-facing JSON schemas
|
|
13
|
+
3. **GenAiPlugin** (Topic) — groups related actions; defines routing criteria and instructions
|
|
14
|
+
4. **GenAiPlannerBundle** — links topics to the agent's planning engine
|
|
15
|
+
5. **Bot** — the top-level agent referencing the planner bundle
|
|
16
|
+
6. Activate the Bot
|
|
17
|
+
|
|
18
|
+
> **Important:** The agent type (`EinsteinCopilot` for internal employees, `ExternalCopilot` for customer-facing) is **immutable** after creation — choose carefully.
|
|
14
19
|
|
|
15
20
|
---
|
|
16
21
|
|
|
17
|
-
## Step 1: Create the
|
|
22
|
+
## Step 1: Create the Flow
|
|
23
|
+
|
|
24
|
+
The flow must be an AutoLaunchedFlow with `runInMode=SystemModeWithoutSharing` and must be **Active**.
|
|
18
25
|
|
|
19
26
|
```
|
|
20
|
-
Create an
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
27
|
+
Create an AutoLaunchedFlow called Create_Account_Record that:
|
|
28
|
+
- Input variable: AccountName (String, isInput: true)
|
|
29
|
+
- Input variable: Industry (String, isInput: true, isRequired: false)
|
|
30
|
+
- Input variable: Phone (String, isInput: true, isRequired: false)
|
|
31
|
+
- CreateRecords element creating an Account with these fields
|
|
32
|
+
- Output variable: AccountId (String, isOutput: true) — set to the created record ID
|
|
25
33
|
```
|
|
26
34
|
|
|
27
|
-
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Step 2: Create Agent Actions (`sf_create_agent_action`)
|
|
38
|
+
|
|
39
|
+
Each action wraps one flow as a GenAiFunction. The tool automatically generates the required LLM-facing JSON schema files (`input/schema.json`, `output/schema.json`) — without these the LLM cannot invoke the action.
|
|
40
|
+
|
|
28
41
|
```json
|
|
29
42
|
{
|
|
30
|
-
"
|
|
31
|
-
"label": "
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
|
|
43
|
+
"actionName": "Create_Account",
|
|
44
|
+
"label": "Create Account",
|
|
45
|
+
"description": "Creates a new Account record with the provided company details",
|
|
46
|
+
"flowApiName": "Create_Account_Record",
|
|
47
|
+
"inputs": [
|
|
48
|
+
{
|
|
49
|
+
"name": "AccountName",
|
|
50
|
+
"label": "Account Name",
|
|
51
|
+
"description": "The name of the company or organization",
|
|
52
|
+
"type": "Text",
|
|
53
|
+
"required": true
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "Industry",
|
|
57
|
+
"label": "Industry",
|
|
58
|
+
"description": "The industry or business sector",
|
|
59
|
+
"type": "Text",
|
|
60
|
+
"required": false
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "Phone",
|
|
64
|
+
"label": "Phone",
|
|
65
|
+
"description": "The main phone number",
|
|
66
|
+
"type": "Text",
|
|
67
|
+
"required": false
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"outputs": [
|
|
71
|
+
{
|
|
72
|
+
"name": "AccountId",
|
|
73
|
+
"label": "Account ID",
|
|
74
|
+
"description": "The Salesforce ID of the created Account record",
|
|
75
|
+
"type": "Text"
|
|
76
|
+
}
|
|
77
|
+
]
|
|
36
78
|
}
|
|
37
79
|
```
|
|
38
80
|
|
|
81
|
+
> **Type matching:** The `type` field must match the flow variable's data type:
|
|
82
|
+
> - Flow `Currency` field → use `"type": "Currency"` (maps to `lightning__numberType`)
|
|
83
|
+
> - Flow `Date` field → use `"type": "Date"` (maps to `lightning__dateType`)
|
|
84
|
+
> - Flow `Number` field → use `"type": "Number"`
|
|
85
|
+
> - Flow `String`/`Text` field → use `"type": "Text"` (default)
|
|
86
|
+
>
|
|
87
|
+
> Using `"type": "Text"` for a Currency/Number field causes the LLM to send a string value that the flow rejects.
|
|
88
|
+
|
|
39
89
|
---
|
|
40
90
|
|
|
41
|
-
## Step
|
|
91
|
+
## Step 3: Create Topics (`sf_create_agent_topic`)
|
|
42
92
|
|
|
43
|
-
Topics
|
|
93
|
+
Topics define the agent's areas of expertise. Create topics **after** actions — topics reference action API names.
|
|
44
94
|
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"topicName": "Account_Management",
|
|
98
|
+
"label": "Account Management",
|
|
99
|
+
"description": "Handle requests to create, update, or look up Account records in Salesforce CRM",
|
|
100
|
+
"scope": "This topic covers creating new company/account records, updating existing accounts, and looking up account information",
|
|
101
|
+
"instructions": [
|
|
102
|
+
"Collect the required company name from the user",
|
|
103
|
+
"Ask for optional details: industry, phone, website",
|
|
104
|
+
"Use the Create Account action to create the record",
|
|
105
|
+
"Confirm success by sharing the record ID with the user"
|
|
106
|
+
],
|
|
107
|
+
"actions": ["Create_Account"]
|
|
108
|
+
}
|
|
51
109
|
```
|
|
52
110
|
|
|
53
111
|
---
|
|
54
112
|
|
|
55
|
-
## Step
|
|
113
|
+
## Step 4: Create Planner Bundle (`sf_create_agent_planner`)
|
|
114
|
+
|
|
115
|
+
The planner bundle is the **critical link** between the Bot and its topics. Without it, the agent has 0 visible topics and cannot route any requests.
|
|
56
116
|
|
|
57
|
-
|
|
117
|
+
Create the planner **after** all topics exist.
|
|
58
118
|
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"plannerName": "CRM_Agent_Planner",
|
|
122
|
+
"label": "CRM Agent Planner",
|
|
123
|
+
"description": "Routes user requests to the appropriate CRM action topics",
|
|
124
|
+
"topicNames": ["Account_Management", "Lead_Management", "Opportunity_Management"]
|
|
125
|
+
}
|
|
59
126
|
```
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Step 5: Create Agent (`sf_create_agent`)
|
|
131
|
+
|
|
132
|
+
Create the Bot referencing the planner bundle name.
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"agentName": "CRM_Record_Creator",
|
|
137
|
+
"label": "CRM Record Creator",
|
|
138
|
+
"description": "Creates and manages CRM records based on user requests",
|
|
139
|
+
"type": "EinsteinCopilot",
|
|
140
|
+
"plannerName": "CRM_Agent_Planner"
|
|
141
|
+
}
|
|
64
142
|
```
|
|
65
143
|
|
|
144
|
+
Agent types:
|
|
145
|
+
- `EinsteinCopilot` — internal employee-facing agent (shown in Lightning sidebar)
|
|
146
|
+
- `ExternalCopilot` — customer-facing Agentforce Service Agent (for Experience Cloud / messaging)
|
|
147
|
+
|
|
66
148
|
---
|
|
67
149
|
|
|
68
|
-
## Step
|
|
150
|
+
## Step 6: Activate the Agent (`sf_activate_agent`)
|
|
69
151
|
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"agentApiName": "CRM_Record_Creator"
|
|
155
|
+
}
|
|
70
156
|
```
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Deactivating for Changes
|
|
161
|
+
|
|
162
|
+
You must deactivate an agent before modifying its topics, actions, or planner:
|
|
163
|
+
|
|
164
|
+
```json
|
|
165
|
+
{ "agentApiName": "CRM_Record_Creator" }
|
|
76
166
|
```
|
|
77
167
|
|
|
168
|
+
After making changes, re-activate with `sf_activate_agent`.
|
|
169
|
+
|
|
78
170
|
---
|
|
79
171
|
|
|
80
172
|
## End-to-End Example
|
|
81
173
|
|
|
82
|
-
Full
|
|
174
|
+
Full prompt sequence to create a CRM Record Creator agent:
|
|
83
175
|
|
|
84
176
|
```
|
|
85
|
-
1. Create
|
|
86
|
-
-
|
|
87
|
-
-
|
|
88
|
-
-
|
|
89
|
-
|
|
90
|
-
2.
|
|
91
|
-
-
|
|
92
|
-
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
-
|
|
97
|
-
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
-
|
|
177
|
+
1. Create AutoLaunchedFlow "Create_Account_Record":
|
|
178
|
+
- Input: AccountName (String, required), Industry (String), Phone (String)
|
|
179
|
+
- CreateRecords element → Account with those fields
|
|
180
|
+
- Output: AccountId (String)
|
|
181
|
+
|
|
182
|
+
2. Create agent action "Create_Account":
|
|
183
|
+
- flowApiName: Create_Account_Record
|
|
184
|
+
- inputs: AccountName (Text, required), Industry (Text), Phone (Text)
|
|
185
|
+
- outputs: AccountId (Text)
|
|
186
|
+
|
|
187
|
+
3. Create agent topic "Account_Management":
|
|
188
|
+
- description: "Handle requests to create Account records"
|
|
189
|
+
- scope: "Creating new company or organization accounts in Salesforce"
|
|
190
|
+
- instructions: ["Ask for company name", "Collect optional fields", "Call Create Account action", "Confirm the record ID"]
|
|
191
|
+
- actions: ["Create_Account"]
|
|
192
|
+
|
|
193
|
+
4. Create planner "CRM_Agent_Planner":
|
|
194
|
+
- topicNames: ["Account_Management"]
|
|
195
|
+
|
|
196
|
+
5. Create agent "CRM_Record_Creator":
|
|
197
|
+
- type: EinsteinCopilot
|
|
198
|
+
- plannerName: CRM_Agent_Planner
|
|
199
|
+
|
|
200
|
+
6. Activate "CRM_Record_Creator"
|
|
103
201
|
```
|
|
104
202
|
|
|
105
203
|
---
|
|
106
204
|
|
|
107
|
-
##
|
|
205
|
+
## Debugging
|
|
108
206
|
|
|
109
|
-
|
|
207
|
+
If the agent routes correctly but never invokes actions (agent says "I can't do that right now"):
|
|
110
208
|
|
|
111
|
-
1. **
|
|
112
|
-
2. **Open Copilot** in any Salesforce page (the lightning bolt icon)
|
|
113
|
-
3. **Test a prompt:** "Show me all orders for Acme Corp"
|
|
209
|
+
1. **Check schema files exist** — Retrieve the GenAiFunction from your org. If you see `The Input LightningTypeBundle schema for action 'X' could not be found`, the schema files are missing. Use `sf_create_agent_action` to redeploy (it now generates schema files automatically).
|
|
114
210
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
---
|
|
211
|
+
2. **Check type mapping** — If the action is invoked but the flow fails with "field in incorrect format", the `type` in your action inputs doesn't match the flow variable type. A Currency flow variable needs `"type": "Currency"`, not `"type": "Text"`.
|
|
118
212
|
|
|
119
|
-
|
|
213
|
+
3. **Check ConversationDefinitionEventLog** — Run SOQL:
|
|
214
|
+
```sql
|
|
215
|
+
SELECT EventLabel, EventTarget, EventDetails
|
|
216
|
+
FROM ConversationDefinitionEventLog
|
|
217
|
+
WHERE LogDate = TODAY
|
|
218
|
+
ORDER BY EventDate DESC
|
|
219
|
+
LIMIT 50
|
|
220
|
+
```
|
|
221
|
+
Look for `TopicClassificationSuccess` (routing worked) vs `ActionExecuted` (action ran).
|
|
120
222
|
|
|
121
|
-
|
|
122
|
-
- **Use clear action descriptions** — help the agent know when to invoke each action
|
|
123
|
-
- **Start with Flows** — they're easiest to create and debug
|
|
124
|
-
- **Test with narrow prompts first** — gradually expand scope
|
|
125
|
-
- **Use variables consistently** — name them meaningfully for better AI reasoning
|
|
223
|
+
4. **Verify planner exists** — If `TopicClassificationSuccess` never appears, the GenAiPlannerBundle may be missing. Use `sf_create_agent_planner` to create it.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,62 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.1.3] - 2026-05-28
|
|
4
|
+
|
|
5
|
+
### Bug Fixes — Agentforce Action Invocation
|
|
6
|
+
|
|
7
|
+
This release fixes critical bugs that prevented Agentforce agents from invoking actions. Agents would correctly route to topics (TopicClassificationSuccess) but never call actions (no ActionExecuted events).
|
|
8
|
+
|
|
9
|
+
#### Root Cause: Missing GenAiFunction Schema Files
|
|
10
|
+
|
|
11
|
+
`sf_create_agent_action` was deploying GenAiFunction metadata without the required `input/schema.json` and `output/schema.json` bundle files. The Agentforce LLM runtime needs these JSON schemas to construct the tool call specification sent to the LLM. Without them, the LLM cannot invoke actions — it replies with messages like "I can't do that directly right now."
|
|
12
|
+
|
|
13
|
+
**Fix:** `sf_create_agent_action` now deploys a complete zip bundle containing:
|
|
14
|
+
- `genAiFunctions/<Name>/<Name>.genAiFunction-meta.xml`
|
|
15
|
+
- `genAiFunctions/<Name>/input/schema.json` — LLM-facing input parameter schema
|
|
16
|
+
- `genAiFunctions/<Name>/output/schema.json` — LLM-facing output parameter schema
|
|
17
|
+
|
|
18
|
+
Schema files use the correct Salesforce LightningTypeBundle format with `lightning:type`, `lightning:isPII`, `copilotAction:isUserInput`, `copilotAction:isDisplayable`, and `copilotAction:isUsedByPlanner` fields.
|
|
19
|
+
|
|
20
|
+
#### Flow Variable Type Mismatch Fixed
|
|
21
|
+
|
|
22
|
+
Flow variables of type `Currency`, `Number`, `Date`, and `DateTime` must use matching `lightning__numberType` or `lightning__dateType` in the schema, not `lightning__textType`. Using text type caused the LLM to send string values like `"5000"` which Flow rejected with "Amount field provided in incorrect format."
|
|
23
|
+
|
|
24
|
+
**Fix:** Added a `type` field to action parameters (`Text`, `Number`, `Currency`, `Boolean`, `Date`, `DateTime`, `TextArea`) that maps correctly to the corresponding `lightning:type` in the schema.
|
|
25
|
+
|
|
26
|
+
#### `sf_create_agent_topic` Was Creating Wrong Metadata Type
|
|
27
|
+
|
|
28
|
+
The tool was deploying `BotVersion` XML instead of `GenAiPlugin` XML.
|
|
29
|
+
|
|
30
|
+
**Fix:** Replaced `buildBotVersionXml` with `buildGenAiPluginXml` that produces correct `GenAiPlugin` metadata with `pluginType`, `scope`, `canEscalate`, step-by-step `genAiPluginInstructions`, and `genAiFunctions` references.
|
|
31
|
+
|
|
32
|
+
#### Added Missing Tools
|
|
33
|
+
|
|
34
|
+
- `sf_create_agent_planner` — Creates a `GenAiPlannerBundle` that links topics to the agent. This is the critical link between the Bot and its topics. Without it, the agent has 0 visible topics and cannot route any requests. Was missing entirely from v2.0.0.
|
|
35
|
+
- `sf_activate_agent` — Activates an agent via REST API after configuration changes.
|
|
36
|
+
- `sf_deactivate_agent` — Deactivates an agent (required before modifying topics/actions).
|
|
37
|
+
|
|
38
|
+
#### API Version Updated
|
|
39
|
+
|
|
40
|
+
Updated from `62.0` to `66.0` (current Salesforce API version for Agentforce metadata).
|
|
41
|
+
|
|
42
|
+
#### Schema Corrections (`sf_create_agent`)
|
|
43
|
+
|
|
44
|
+
- Removed invalid fields: `persona`, `tone`, `instructions`, `company` (not part of Bot metadata)
|
|
45
|
+
- Fixed `type` enum from `["Default", "EinsteinCopilot"]` to `["EinsteinCopilot", "ExternalCopilot"]`
|
|
46
|
+
- Added `agentTemplate: AiCopilot__AgentforceAgent` to Bot XML (required for proper action invocation wiring)
|
|
47
|
+
|
|
48
|
+
#### Correct Creation Order Now Enforced
|
|
49
|
+
|
|
50
|
+
The tool descriptions now document and enforce the correct metadata creation order:
|
|
51
|
+
1. Create Flows (`sf_create_flow`) — AutoLaunchedFlows with `runInMode=SystemModeWithoutSharing`
|
|
52
|
+
2. Create Actions (`sf_create_agent_action`) — GenAiFunction + schema files
|
|
53
|
+
3. Create Topics (`sf_create_agent_topic`) — GenAiPlugin referencing actions
|
|
54
|
+
4. Create Planner (`sf_create_agent_planner`) — GenAiPlannerBundle linking all topics
|
|
55
|
+
5. Create Agent (`sf_create_agent`) — Bot referencing the planner
|
|
56
|
+
6. Activate Agent (`sf_activate_agent`)
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
3
60
|
## [2.0.0] - 2026-05-22
|
|
4
61
|
|
|
5
62
|
### Major Release — 60+ Tools
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
File without changes
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/schemas/index.js
CHANGED
|
@@ -858,37 +858,39 @@ 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
|
-
company: z.string().max(255).optional().describe("Company name for the agent's context"),
|
|
866
|
-
persona: z.string().max(5000).optional().describe("Agent persona description, e.g. 'A helpful customer service representative'"),
|
|
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."),
|
|
869
865
|
}).strict();
|
|
870
866
|
export const CreateAgentTopicSchema = z.object({
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
867
|
+
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."),
|
|
868
|
+
label: z.string().min(1).max(255).describe("Topic display label, e.g. 'Create Account Topic'"),
|
|
869
|
+
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'"),
|
|
870
|
+
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'"),
|
|
871
|
+
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']"),
|
|
872
|
+
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."),
|
|
873
|
+
}).strict();
|
|
874
|
+
const AgentParamSchema = z.object({
|
|
875
|
+
name: z.string().max(80).describe("Parameter API name matching the flow variable name, e.g. 'AccountName'"),
|
|
876
|
+
label: z.string().max(255).describe("Human-readable label, e.g. 'Account Name'"),
|
|
877
|
+
description: z.string().max(1000).optional().describe("Description shown to the LLM, e.g. 'The name of the company or organization'"),
|
|
878
|
+
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"),
|
|
879
|
+
required: z.boolean().default(true).describe("Whether this input is required"),
|
|
880
|
+
});
|
|
879
881
|
export const CreateAgentActionSchema = z.object({
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
882
|
+
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."),
|
|
883
|
+
label: z.string().min(1).max(255).describe("Action display label, e.g. 'Create Account'"),
|
|
884
|
+
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'"),
|
|
885
|
+
flowApiName: z.string().min(1).max(255).describe("API name of the AutoLaunchedFlow to invoke, e.g. 'Create_Account_Record'. The flow must be Active and have runInMode=SystemModeWithoutSharing."),
|
|
886
|
+
inputs: z.array(AgentParamSchema).optional().describe("Flow input variables. Each input becomes a parameter the LLM collects from the user. Type MUST match the flow variable's data type."),
|
|
887
|
+
outputs: z.array(AgentParamSchema.omit({ required: true })).optional().describe("Flow output variables returned to the agent after execution, e.g. the created record ID"),
|
|
888
|
+
}).strict();
|
|
889
|
+
export const CreateAgentPlannerSchema = z.object({
|
|
890
|
+
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."),
|
|
891
|
+
label: z.string().min(1).max(255).describe("Planner display label, e.g. 'CRM Creator Planner'"),
|
|
892
|
+
description: z.string().max(1000).optional().describe("Planner description"),
|
|
893
|
+
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."),
|
|
892
894
|
}).strict();
|
|
893
895
|
// ─── MCP SERVER MANAGEMENT ───────────────────────────────────────────────────
|
|
894
896
|
export const CreateMcpServerSchema = z.object({
|
|
@@ -64,6 +64,102 @@ 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 functionXml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
90
|
+
<GenAiFunction xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
91
|
+
<description>${escapeXml(params.description)}</description>
|
|
92
|
+
<invocationTarget>${escapeXml(params.flowApiName)}</invocationTarget>
|
|
93
|
+
<invocationTargetType>flow</invocationTargetType>
|
|
94
|
+
<isConfirmationRequired>false</isConfirmationRequired>
|
|
95
|
+
<masterLabel>${escapeXml(params.label)}</masterLabel>
|
|
96
|
+
${inputsXml}
|
|
97
|
+
${outputsXml}
|
|
98
|
+
</GenAiFunction>`;
|
|
99
|
+
zip.file(`genAiFunctions/${functionName}/${functionName}.genAiFunction-meta.xml`, functionXml);
|
|
100
|
+
// Build input schema JSON
|
|
101
|
+
const inputSchemaProps = {};
|
|
102
|
+
const requiredInputs = [];
|
|
103
|
+
for (const inp of (params.inputs ?? [])) {
|
|
104
|
+
inputSchemaProps[inp.name] = {
|
|
105
|
+
"title": inp.label,
|
|
106
|
+
"description": inp.description ?? inp.label,
|
|
107
|
+
"lightning:type": lightningTypeFor(inp.type ?? "Text"),
|
|
108
|
+
"lightning:isPII": false,
|
|
109
|
+
"copilotAction:isUserInput": true
|
|
110
|
+
};
|
|
111
|
+
if (inp.required !== false) {
|
|
112
|
+
requiredInputs.push(inp.name);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const inputSchema = {
|
|
116
|
+
"required": requiredInputs.length > 0 ? requiredInputs : undefined,
|
|
117
|
+
"unevaluatedProperties": false,
|
|
118
|
+
"properties": inputSchemaProps,
|
|
119
|
+
"lightning:type": "lightning__objectType"
|
|
120
|
+
};
|
|
121
|
+
if (!inputSchema.required) {
|
|
122
|
+
delete inputSchema.required;
|
|
123
|
+
}
|
|
124
|
+
zip.file(`genAiFunctions/${functionName}/input/schema.json`, JSON.stringify(inputSchema, null, 2));
|
|
125
|
+
// Build output schema JSON
|
|
126
|
+
const outputSchemaProps = {};
|
|
127
|
+
for (const out of (params.outputs ?? [])) {
|
|
128
|
+
outputSchemaProps[out.name] = {
|
|
129
|
+
"title": out.label,
|
|
130
|
+
"description": out.description ?? out.label,
|
|
131
|
+
"lightning:type": lightningTypeFor(out.type ?? "Text"),
|
|
132
|
+
"lightning:isPII": false,
|
|
133
|
+
"copilotAction:isDisplayable": true,
|
|
134
|
+
"copilotAction:isUsedByPlanner": true
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
const outputSchema = {
|
|
138
|
+
"unevaluatedProperties": false,
|
|
139
|
+
"properties": outputSchemaProps,
|
|
140
|
+
"lightning:type": "lightning__objectType"
|
|
141
|
+
};
|
|
142
|
+
zip.file(`genAiFunctions/${functionName}/output/schema.json`, JSON.stringify(outputSchema, null, 2));
|
|
143
|
+
const buffer = await zip.generateAsync({ type: "nodebuffer" });
|
|
144
|
+
return buffer.toString("base64");
|
|
145
|
+
}
|
|
146
|
+
function escapeXml(s) {
|
|
147
|
+
return String(s ?? "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
148
|
+
}
|
|
149
|
+
function lightningTypeFor(sfType) {
|
|
150
|
+
const t = sfType.toLowerCase();
|
|
151
|
+
if (t === "currency" || t === "number" || t === "double" || t === "integer" || t === "percent")
|
|
152
|
+
return "lightning__numberType";
|
|
153
|
+
if (t === "boolean" || t === "checkbox")
|
|
154
|
+
return "lightning__booleanType";
|
|
155
|
+
if (t === "date")
|
|
156
|
+
return "lightning__dateType";
|
|
157
|
+
if (t === "datetime")
|
|
158
|
+
return "lightning__dateTimeType";
|
|
159
|
+
if (t === "textarea" || t === "longtextarea" || t === "richtext")
|
|
160
|
+
return "lightning__textAreaType";
|
|
161
|
+
return "lightning__textType";
|
|
162
|
+
}
|
|
67
163
|
export async function buildGenericDeployZip(components, apiVersion) {
|
|
68
164
|
const zip = new JSZip();
|
|
69
165
|
const typeMap = new Map();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execSync } from "child_process";
|
|
2
|
-
export const API_VERSION = "
|
|
2
|
+
export const API_VERSION = "66.0";
|
|
3
3
|
// ─── Token cache ──────────────────────────────────────────────────────────────
|
|
4
4
|
let cachedToken = null;
|
|
5
5
|
const TOKEN_TTL_MS = 55 * 60 * 1000;
|
|
@@ -1212,26 +1212,50 @@ function buildBotXml(params) {
|
|
|
1212
1212
|
<met:fullName>${x(params.agentName)}</met:fullName>
|
|
1213
1213
|
<met:label>${x(params.label)}</met:label>
|
|
1214
1214
|
${params.description ? `<met:description>${x(params.description)}</met:description>` : ""}
|
|
1215
|
-
<met:
|
|
1216
|
-
<met:
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
<met:
|
|
1220
|
-
|
|
1215
|
+
<met:agentTemplate>AiCopilot__AgentforceAgent</met:agentTemplate>
|
|
1216
|
+
<met:agentType>EinsteinServiceAgent</met:agentType>
|
|
1217
|
+
<met:botSource>None</met:botSource>
|
|
1218
|
+
<met:logPrivateConversationData>false</met:logPrivateConversationData>
|
|
1219
|
+
<met:richContentEnabled>true</met:richContentEnabled>
|
|
1220
|
+
<met:sessionTimeout>0</met:sessionTimeout>
|
|
1221
|
+
<met:type>${x(params.type ?? "EinsteinCopilot")}</met:type>
|
|
1221
1222
|
</met:metadata>`;
|
|
1222
1223
|
}
|
|
1223
|
-
function
|
|
1224
|
-
const
|
|
1225
|
-
<met:
|
|
1226
|
-
<met:
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1224
|
+
function buildGenAiPluginXml(params) {
|
|
1225
|
+
const instructionsXml = (params.instructions ?? []).map((instr, i) => `
|
|
1226
|
+
<met:genAiPluginInstructions>
|
|
1227
|
+
<met:description>${x(instr)}</met:description>
|
|
1228
|
+
<met:developerName>instruction_${i}</met:developerName>
|
|
1229
|
+
<met:masterLabel>instruction_${i}</met:masterLabel>
|
|
1230
|
+
<met:sortOrder>${i}</met:sortOrder>
|
|
1231
|
+
</met:genAiPluginInstructions>`).join("\n");
|
|
1232
|
+
const functionsXml = (params.actions ?? []).map(a => `
|
|
1233
|
+
<met:genAiFunctions>
|
|
1234
|
+
<met:functionName>${x(a)}</met:functionName>
|
|
1235
|
+
</met:genAiFunctions>`).join("\n");
|
|
1236
|
+
return `<met:metadata xsi:type="met:GenAiPlugin" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
1237
|
+
<met:fullName>${x(params.topicName)}</met:fullName>
|
|
1238
|
+
<met:masterLabel>${x(params.label)}</met:masterLabel>
|
|
1231
1239
|
<met:description>${x(params.description)}</met:description>
|
|
1232
1240
|
<met:scope>${x(params.scope)}</met:scope>
|
|
1233
|
-
|
|
1234
|
-
|
|
1241
|
+
<met:pluginType>Topic</met:pluginType>
|
|
1242
|
+
<met:canEscalate>false</met:canEscalate>
|
|
1243
|
+
<met:language>en_US</met:language>
|
|
1244
|
+
${instructionsXml}
|
|
1245
|
+
${functionsXml}
|
|
1246
|
+
</met:metadata>`;
|
|
1247
|
+
}
|
|
1248
|
+
function buildGenAiPlannerBundleXml(params) {
|
|
1249
|
+
const pluginsXml = params.topicNames.map(t => `
|
|
1250
|
+
<met:genAiPlugins>
|
|
1251
|
+
<met:genAiPluginName>${x(t)}</met:genAiPluginName>
|
|
1252
|
+
</met:genAiPlugins>`).join("\n");
|
|
1253
|
+
return `<met:metadata xsi:type="met:GenAiPlannerBundle" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
1254
|
+
<met:fullName>${x(params.plannerName)}</met:fullName>
|
|
1255
|
+
<met:masterLabel>${x(params.label)}</met:masterLabel>
|
|
1256
|
+
${params.description ? `<met:description>${x(params.description)}</met:description>` : ""}
|
|
1257
|
+
<met:plannerType>AiCopilot__ReAct</met:plannerType>
|
|
1258
|
+
${pluginsXml}
|
|
1235
1259
|
</met:metadata>`;
|
|
1236
1260
|
}
|
|
1237
1261
|
function buildMatchingRuleXml(params) {
|
|
@@ -1474,6 +1498,33 @@ export async function createAgent(auth, params) {
|
|
|
1474
1498
|
return upsertMetadata(auth, buildBotXml(params));
|
|
1475
1499
|
}
|
|
1476
1500
|
export async function createAgentTopic(auth, params) {
|
|
1477
|
-
return upsertMetadata(auth,
|
|
1501
|
+
return upsertMetadata(auth, buildGenAiPluginXml(params));
|
|
1502
|
+
}
|
|
1503
|
+
export async function createAgentPlanner(auth, params) {
|
|
1504
|
+
return upsertMetadata(auth, buildGenAiPlannerBundleXml(params));
|
|
1505
|
+
}
|
|
1506
|
+
export async function activateAgent(auth, agentApiName) {
|
|
1507
|
+
try {
|
|
1508
|
+
const resp = await fetchWithTimeout(`${auth.instanceUrl}/services/data/v${API_VERSION}/connect/einstein/copilot/${agentApiName}/activate`, { method: "POST", headers: { "Authorization": `Bearer ${auth.accessToken}`, "Content-Type": "application/json" } }, 30_000);
|
|
1509
|
+
if (resp.ok)
|
|
1510
|
+
return { success: true, message: `Agent '${agentApiName}' activated successfully.` };
|
|
1511
|
+
const body = await resp.text().catch(() => "");
|
|
1512
|
+
return { success: false, message: `Activation failed (HTTP ${resp.status}): ${body}` };
|
|
1513
|
+
}
|
|
1514
|
+
catch (err) {
|
|
1515
|
+
return { success: false, message: sanitizeError(err instanceof Error ? err.message : String(err)) };
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
export async function deactivateAgent(auth, agentApiName) {
|
|
1519
|
+
try {
|
|
1520
|
+
const resp = await fetchWithTimeout(`${auth.instanceUrl}/services/data/v${API_VERSION}/connect/einstein/copilot/${agentApiName}/deactivate`, { method: "POST", headers: { "Authorization": `Bearer ${auth.accessToken}`, "Content-Type": "application/json" } }, 30_000);
|
|
1521
|
+
if (resp.ok)
|
|
1522
|
+
return { success: true, message: `Agent '${agentApiName}' deactivated successfully.` };
|
|
1523
|
+
const body = await resp.text().catch(() => "");
|
|
1524
|
+
return { success: false, message: `Deactivation failed (HTTP ${resp.status}): ${body}` };
|
|
1525
|
+
}
|
|
1526
|
+
catch (err) {
|
|
1527
|
+
return { success: false, message: sanitizeError(err instanceof Error ? err.message : String(err)) };
|
|
1528
|
+
}
|
|
1478
1529
|
}
|
|
1479
1530
|
//# sourceMappingURL=salesforce.js.map
|
package/dist/tools/agentforce.js
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
|
-
import { CreateAgentSchema, CreateAgentTopicSchema, CreateAgentActionSchema } from "../schemas/index.js";
|
|
2
|
-
import { getAuth, createAgent, createAgentTopic } from "../services/salesforce.js";
|
|
1
|
+
import { CreateAgentSchema, CreateAgentTopicSchema, CreateAgentActionSchema, CreateAgentPlannerSchema } from "../schemas/index.js";
|
|
2
|
+
import { getAuth, createAgent, createAgentTopic, createAgentPlanner, activateAgent, deactivateAgent, API_VERSION } from "../services/salesforce.js";
|
|
3
|
+
import { buildGenAiActionZip, deployZip, pollDeployStatus } from "../services/deployment.js";
|
|
3
4
|
import { resultContent } from "./utils.js";
|
|
4
5
|
export function registerAgentforceTools(server) {
|
|
5
6
|
server.registerTool("sf_create_agent", {
|
|
6
7
|
title: "Create Agentforce Agent",
|
|
7
|
-
description: `Creates an Agentforce Agent (Einstein Copilot) in Salesforce using the Bot metadata type.
|
|
8
|
+
description: `Creates an Agentforce Agent (Einstein Copilot / Service Agent) in Salesforce using the Bot metadata type.
|
|
9
|
+
|
|
10
|
+
IMPORTANT: Follow this exact creation order for a fully working agent:
|
|
11
|
+
1. Create flows (sf_create_flow) — the AutoLaunchedFlows that perform actions
|
|
12
|
+
2. Create agent actions (sf_create_agent_action) — link each flow as a GenAiFunction
|
|
13
|
+
3. Create agent topics (sf_create_agent_topic) — create GenAiPlugin topics referencing the actions
|
|
14
|
+
4. Create agent planner (sf_create_agent_planner) — create GenAiPlannerBundle linking all topics
|
|
15
|
+
5. Create agent (sf_create_agent) — create the Bot referencing the planner
|
|
16
|
+
6. Activate the agent (sf_activate_agent)
|
|
17
|
+
|
|
18
|
+
The agent type is IMMUTABLE after creation — choose carefully (EinsteinCopilot for internal, ExternalCopilot for customer-facing).`,
|
|
8
19
|
inputSchema: CreateAgentSchema,
|
|
9
20
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
10
21
|
}, async (params) => {
|
|
@@ -14,22 +25,20 @@ export function registerAgentforceTools(server) {
|
|
|
14
25
|
label: params.label,
|
|
15
26
|
description: params.description,
|
|
16
27
|
type: params.type,
|
|
17
|
-
company: params.company,
|
|
18
|
-
persona: params.persona,
|
|
19
|
-
tone: params.tone,
|
|
20
|
-
instructions: params.instructions,
|
|
21
28
|
});
|
|
22
29
|
return resultContent(result);
|
|
23
30
|
});
|
|
24
31
|
server.registerTool("sf_create_agent_topic", {
|
|
25
|
-
title: "Create Agentforce Topic",
|
|
26
|
-
description: `Creates a Topic for an Agentforce Agent. Topics define areas of expertise — what types of user requests
|
|
32
|
+
title: "Create Agentforce Topic (GenAiPlugin)",
|
|
33
|
+
description: `Creates a Topic (GenAiPlugin) for an Agentforce Agent. Topics define the agent's areas of expertise — what types of user requests it handles. Each topic has a description (routing criteria), scope (what it covers), step-by-step instructions, and references to agent actions.
|
|
34
|
+
|
|
35
|
+
Create topics AFTER creating agent actions (sf_create_agent_action) since topics reference actions by API name.
|
|
36
|
+
Then create the planner bundle (sf_create_agent_planner) to link all topics to the agent.`,
|
|
27
37
|
inputSchema: CreateAgentTopicSchema,
|
|
28
38
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
29
39
|
}, async (params) => {
|
|
30
40
|
const auth = await getAuth();
|
|
31
41
|
const result = await createAgentTopic(auth, {
|
|
32
|
-
agentName: params.agentName,
|
|
33
42
|
topicName: params.topicName,
|
|
34
43
|
label: params.label,
|
|
35
44
|
description: params.description,
|
|
@@ -40,34 +49,78 @@ export function registerAgentforceTools(server) {
|
|
|
40
49
|
return resultContent(result);
|
|
41
50
|
});
|
|
42
51
|
server.registerTool("sf_create_agent_action", {
|
|
43
|
-
title: "Create Agentforce Action",
|
|
44
|
-
description: `Creates an Agentforce Action linked to a Flow
|
|
52
|
+
title: "Create Agentforce Action (GenAiFunction)",
|
|
53
|
+
description: `Creates an Agentforce Action (GenAiFunction) linked to a Flow. Actions are the concrete steps an agent takes when handling a topic. The LLM invokes actions based on the topic's instructions and the user's request.
|
|
54
|
+
|
|
55
|
+
IMPORTANT: This deploys a complete GenAiFunction bundle including:
|
|
56
|
+
- The GenAiFunction metadata (invocationTarget, invocationTargetType, mappingAttributes)
|
|
57
|
+
- input/schema.json — the LLM-facing JSON schema for input parameters (REQUIRED for action invocation)
|
|
58
|
+
- output/schema.json — the LLM-facing JSON schema for output parameters
|
|
59
|
+
|
|
60
|
+
Without the schema files, the LLM cannot invoke the action. This tool handles all three files automatically.
|
|
61
|
+
|
|
62
|
+
Create actions BEFORE topics (topics reference actions by API name).
|
|
63
|
+
The referenced flow MUST exist and be Active with runInMode=SystemModeWithoutSharing.`,
|
|
45
64
|
inputSchema: CreateAgentActionSchema,
|
|
46
65
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
47
66
|
}, async (params) => {
|
|
48
67
|
const auth = await getAuth();
|
|
49
68
|
try {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
<met:description>${x(params.description)}</met:description>
|
|
61
|
-
<met:type>${x(params.type)}</met:type>
|
|
62
|
-
<met:functionRef>${x(params.reference)}</met:functionRef>
|
|
63
|
-
${inputsXml}
|
|
64
|
-
</met:metadata>`;
|
|
65
|
-
const result = await upsertMetadata(auth, xml);
|
|
69
|
+
const base64Zip = await buildGenAiActionZip({
|
|
70
|
+
actionName: params.actionName,
|
|
71
|
+
label: params.label,
|
|
72
|
+
description: params.description,
|
|
73
|
+
flowApiName: params.flowApiName,
|
|
74
|
+
inputs: params.inputs ?? [],
|
|
75
|
+
outputs: params.outputs ?? [],
|
|
76
|
+
}, API_VERSION);
|
|
77
|
+
const deployId = await deployZip(auth, base64Zip);
|
|
78
|
+
const result = await pollDeployStatus(auth, deployId, 120_000);
|
|
66
79
|
return resultContent(result);
|
|
67
80
|
}
|
|
68
81
|
catch (err) {
|
|
69
82
|
return resultContent({ success: false, message: err instanceof Error ? err.message : String(err) });
|
|
70
83
|
}
|
|
71
84
|
});
|
|
85
|
+
server.registerTool("sf_create_agent_planner", {
|
|
86
|
+
title: "Create Agentforce Planner Bundle (GenAiPlannerBundle)",
|
|
87
|
+
description: `Creates a GenAiPlannerBundle that connects topics to the agent's planning engine.
|
|
88
|
+
|
|
89
|
+
The planner bundle is the CRITICAL link between the Bot and its topics (GenAiPlugins). Without it, the agent will have 0 topics visible and cannot route requests or invoke actions.
|
|
90
|
+
|
|
91
|
+
Create the planner bundle AFTER creating all topics (sf_create_agent_topic) and BEFORE creating the agent (sf_create_agent).
|
|
92
|
+
Then reference this planner's API name when calling sf_create_agent.`,
|
|
93
|
+
inputSchema: CreateAgentPlannerSchema,
|
|
94
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
95
|
+
}, async (params) => {
|
|
96
|
+
const auth = await getAuth();
|
|
97
|
+
const result = await createAgentPlanner(auth, {
|
|
98
|
+
plannerName: params.plannerName,
|
|
99
|
+
label: params.label,
|
|
100
|
+
description: params.description,
|
|
101
|
+
topicNames: params.topicNames,
|
|
102
|
+
});
|
|
103
|
+
return resultContent(result);
|
|
104
|
+
});
|
|
105
|
+
server.registerTool("sf_activate_agent", {
|
|
106
|
+
title: "Activate Agentforce Agent",
|
|
107
|
+
description: `Activates an Agentforce Agent so it is available to users. The agent must be inactive (deactivated) before you can make configuration changes like adding/removing topics or actions. After making changes, re-activate with this tool.`,
|
|
108
|
+
inputSchema: { type: "object", properties: { agentApiName: { type: "string", description: "API name of the agent to activate, e.g. 'CRM_Record_Creator'" } }, required: ["agentApiName"] },
|
|
109
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
110
|
+
}, async (params) => {
|
|
111
|
+
const auth = await getAuth();
|
|
112
|
+
const result = await activateAgent(auth, params.agentApiName);
|
|
113
|
+
return resultContent(result);
|
|
114
|
+
});
|
|
115
|
+
server.registerTool("sf_deactivate_agent", {
|
|
116
|
+
title: "Deactivate Agentforce Agent",
|
|
117
|
+
description: `Deactivates an Agentforce Agent so configuration changes can be made. You must deactivate an agent before modifying its topics, actions, or planner configuration. After making changes, re-activate with sf_activate_agent.`,
|
|
118
|
+
inputSchema: { type: "object", properties: { agentApiName: { type: "string", description: "API name of the agent to deactivate, e.g. 'CRM_Record_Creator'" } }, required: ["agentApiName"] },
|
|
119
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
120
|
+
}, async (params) => {
|
|
121
|
+
const auth = await getAuth();
|
|
122
|
+
const result = await deactivateAgent(auth, params.agentApiName);
|
|
123
|
+
return resultContent(result);
|
|
124
|
+
});
|
|
72
125
|
}
|
|
73
|
-
//# sourceMappingURL=agentforce.js.map
|
|
126
|
+
//# sourceMappingURL=agentforce.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "salesforce-metadata-mcp",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3",
|
|
4
4
|
"description": "The most comprehensive Salesforce metadata and development MCP server: 60+ tools for custom objects, flows, Apex, LWC, Agentforce, deployments, and more",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|