salesforce-metadata-mcp 2.7.0 → 2.8.7
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/CHANGELOG.md +274 -0
- package/README.md +6 -3
- package/TOOLS.md +2 -2
- package/dist/schemas/index.d.ts +196 -36
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +81 -13
- package/dist/schemas/index.js.map +1 -1
- package/dist/services/deployment.d.ts +23 -0
- package/dist/services/deployment.d.ts.map +1 -1
- package/dist/services/deployment.js +54 -0
- package/dist/services/deployment.js.map +1 -1
- package/dist/services/salesforce.d.ts +45 -10
- package/dist/services/salesforce.d.ts.map +1 -1
- package/dist/services/salesforce.js +627 -151
- package/dist/services/salesforce.js.map +1 -1
- package/dist/tools/agentforce.d.ts.map +1 -1
- package/dist/tools/agentforce.js +40 -19
- package/dist/tools/agentforce.js.map +1 -1
- package/dist/tools/apex.d.ts.map +1 -1
- package/dist/tools/apex.js +16 -2
- package/dist/tools/apex.js.map +1 -1
- package/dist/tools/automation.js +6 -6
- package/dist/tools/automation.js.map +1 -1
- package/dist/tools/deployment.js +3 -3
- package/dist/tools/deployment.js.map +1 -1
- package/dist/tools/devops.d.ts.map +1 -1
- package/dist/tools/devops.js +16 -2
- package/dist/tools/devops.js.map +1 -1
- package/dist/tools/integrations.d.ts.map +1 -1
- package/dist/tools/integrations.js +27 -2
- package/dist/tools/integrations.js.map +1 -1
- package/dist/tools/objects.js +1 -1
- package/dist/tools/objects.js.map +1 -1
- package/dist/tools/ui.d.ts.map +1 -1
- package/dist/tools/ui.js +8 -8
- package/dist/tools/ui.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,279 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.8.7] - 2026-07-31
|
|
4
|
+
|
|
5
|
+
### Added — `sf_create_external_client_app`, and it closes a gap `sf_create_connected_app` structurally cannot
|
|
6
|
+
|
|
7
|
+
Asked why the previous release reached for a Connected App at all when External Client Apps (ECAs) are
|
|
8
|
+
Salesforce's newer, recommended replacement, the honest answer was: the codebase simply had no ECA
|
|
9
|
+
tool, so the fix used what existed. Built the missing tool instead of leaving that as a permanent
|
|
10
|
+
excuse — and it turns out ECAs solve a real limitation, not just a modernization nicety.
|
|
11
|
+
|
|
12
|
+
`ExternalClientApplication` decomposes into three independent metadata types
|
|
13
|
+
(`ExternalClientApplication`, `ExtlClntAppOauthSettings`, `ExtlClntAppOauthConfigurablePolicies`),
|
|
14
|
+
none of which are documented with a field-level reference on Salesforce's own metadata pages for the
|
|
15
|
+
parts that matter most. Every field below — including the full 36-value OAuth scope enum, which the
|
|
16
|
+
official docs don't list at all — was discovered by deploying deliberately-invalid values against a
|
|
17
|
+
live org and reading Salesforce's own rejection messages (the scope enum came back complete, unprompted,
|
|
18
|
+
in a single error string), then confirmed correct by deploying the real values and reading the records
|
|
19
|
+
back. `sf_create_external_client_app` deploys all three components in one call.
|
|
20
|
+
|
|
21
|
+
**The actual reason to prefer this over `sf_create_connected_app`:** on a classic Connected App,
|
|
22
|
+
Client Credentials Flow's "Run As" user can only ever be picked in Setup UI — confirmed in the
|
|
23
|
+
previous release, and still true, there is no metadata or REST field for it. On an External Client
|
|
24
|
+
App, `ExtlClntAppOauthConfigurablePolicies.clientCredentialsFlowUser` sets it directly, verified live:
|
|
25
|
+
create the app, enable the flow, name the user, done — no human required for that part. The one thing
|
|
26
|
+
that's still Setup-UI-only for *either* app type is viewing the Consumer Key/Secret — Salesforce does
|
|
27
|
+
not expose it via any API, full stop, and the tool's success message says so rather than implying the
|
|
28
|
+
app is immediately usable.
|
|
29
|
+
|
|
30
|
+
**Also fixed the same "cannot fail" defect in `sf_create_connected_app`'s own regression test** — it
|
|
31
|
+
called the underlying function with a wrong parameter name (`appName` instead of `fullName`) and
|
|
32
|
+
omitted the two required fields (`callbackUrls`, `scopes`) entirely, so it always threw internally and
|
|
33
|
+
passed via `orgLimitFallback`'s catch. This is very likely *how* the scope-enum bug fixed in the
|
|
34
|
+
previous release went unnoticed for as long as it did: the one test that should have caught it never
|
|
35
|
+
actually ran the real code path. Fixed with real required parameters; added a matching real test for
|
|
36
|
+
the new tool.
|
|
37
|
+
|
|
38
|
+
Also updated the tool count (221→222) across `package.json`, `server.json`, `README.md`, `TOOLS.md`,
|
|
39
|
+
and `CLAUDE.md`.
|
|
40
|
+
|
|
41
|
+
## [2.8.6] - 2026-07-31
|
|
42
|
+
|
|
43
|
+
### Fixed — `sf_create_connected_app` could never successfully grant any OAuth scope
|
|
44
|
+
|
|
45
|
+
Asked to prove an Agentforce agent can hold a live conversation, the trail led to the connected app
|
|
46
|
+
required for the Agent API's client-credentials flow — and that tool turned out to be broken end to
|
|
47
|
+
end, independent of anything Agentforce-specific. Every scope value in the schema (`api`, `web`,
|
|
48
|
+
`chatter_api`, `offline_access`, ...) is lowercase snake_case, matching the OAuth2 `scope`
|
|
49
|
+
query-parameter convention developers know. The `ConnectedApp` Metadata API's scope enum
|
|
50
|
+
(`ConnectedAppOauthAccessScope`) is a completely different, undocumented set of PascalCase literals
|
|
51
|
+
that has no relationship to that convention — `'api' is not a valid value for the enum
|
|
52
|
+
'ConnectedAppOauthAccessScope'`. Every one of the tool's own scope values was therefore guaranteed to
|
|
53
|
+
fail deployment, 100% of the time, for every caller who ever used it. Fixed with a mapping table where
|
|
54
|
+
each entry was individually verified by deploying it against a live org and reading Salesforce's own
|
|
55
|
+
accept/reject response — not guessed from docs: `api`→`Api`, `web`→`Web`, `full`→`Full`,
|
|
56
|
+
`chatter_api`→`Chatter`, `wave_api`→`Wave`, `eclair_api`→`Eclair`, `content`→`Content`,
|
|
57
|
+
`openid`→`OpenID`, `profile`→`Profile`, `email`→`Email`, `address`→`Address`, `phone`→`Phone`,
|
|
58
|
+
`offline_access`→`RefreshToken`, `custom_permissions`→`CustomPermissions`, `pardot_api`→`Pardot`.
|
|
59
|
+
Also added `chatbot_api`→`Chatbot` (verified live) — needed by any external caller of a Salesforce
|
|
60
|
+
bot/Agentforce agent, previously missing from the enum entirely. `visualforce` has **no** confirmed
|
|
61
|
+
working literal — `Visualforce`, `VisualForce`, `Vf`, and `ViewVisualforce` were all tried and
|
|
62
|
+
rejected; it is passed through unmapped and documented as a known open gap rather than guessed.
|
|
63
|
+
|
|
64
|
+
Also added `enableClientCredentialsFlow`, which sets `isClientCredentialEnabled`/`isAdminApproved` on
|
|
65
|
+
the deployed app (both verified accepted by the Metadata API). This does **not** make Client
|
|
66
|
+
Credentials Flow usable by itself: Salesforce still requires a human in Setup → App Manager → Edit
|
|
67
|
+
Policies to pick the flow's "Run As" user, and the Consumer Secret can only ever be viewed/copied from
|
|
68
|
+
that same Setup UI — neither is exposed by any API, Connect resource, or Tooling endpoint found during
|
|
69
|
+
a deliberate search. The tool's success message now says this explicitly instead of implying the app
|
|
70
|
+
is ready to use.
|
|
71
|
+
|
|
72
|
+
### Fixed — `sf_create_agent_action`'s `label` parameter was required but the code already treated it as optional
|
|
73
|
+
|
|
74
|
+
The handler has always used `params.label ?? params.actionName` as a fallback, but the zod schema
|
|
75
|
+
marked `label` as required — so the fallback code was dead and every caller who reasonably omitted a
|
|
76
|
+
redundant label got a hard validation rejection. Schema now matches the code's actual behavior.
|
|
77
|
+
|
|
78
|
+
### Fixed — `activateAgent`/`deactivateAgent` claimed success on total failure
|
|
79
|
+
|
|
80
|
+
Not wired to any MCP tool (dead code, found during this session), but worth fixing since it embodies a
|
|
81
|
+
pattern already flagged elsewhere in this codebase: its final fallback returned `success: true` even
|
|
82
|
+
when every attempt inside the function had failed. Verified live: the `/connect/einstein/copilot/
|
|
83
|
+
{name}/activate` Connect resource 404s ("resource does not exist"), and both `BotDefinition.Status`
|
|
84
|
+
and `BotVersion.Status` are read-only via REST ("No such column" / "Unable to create/update fields:
|
|
85
|
+
Status... check security settings" — Salesforce's own read-only-field wording, not a permissions gap).
|
|
86
|
+
No working programmatic activation path was found despite testing roughly ten REST/Connect/Tooling
|
|
87
|
+
endpoint candidates. The function now reports failure honestly instead of guessing success; Agent
|
|
88
|
+
activation (Setup → Agent Builder → Activate) appears to be Setup-UI-only as of API v66.0.
|
|
89
|
+
|
|
90
|
+
### Fixed — `test-suite.mjs` had 5 Agentforce/Einstein tests that could never fail (not 3, as
|
|
91
|
+
### previously scoped)
|
|
92
|
+
|
|
93
|
+
`sf_create_einstein_bot`, `sf_create_einstein_prediction`, `sf_create_agent`, `sf_create_agent_topic`,
|
|
94
|
+
and `sf_create_agent_action` were each wrapped in try/catch returning `success: true`, then passed
|
|
95
|
+
through `orgLimitFallback` (which also counts HTTP 500/404/NOT_FOUND as a pass). The agent/topic tests
|
|
96
|
+
imported `createAgent`/`createAgentTopic` from `services/salesforce.js`, which no MCP tool calls —
|
|
97
|
+
`src/tools/agentforce.ts` builds its own XML inline — so they exercised orphaned code while the shipped
|
|
98
|
+
handlers had zero coverage from this suite. The action test hand-rolled `GenAiFunction` XML with a
|
|
99
|
+
`type`/`functionRef` shape that doesn't match what the real tool deploys
|
|
100
|
+
(`invocationTarget`/`invocationTargetType`), aimed at a flow named `NonExistentFlow`. All five removed;
|
|
101
|
+
real, live-org-verified coverage for these five tools plus `sf_create_agent_planner`,
|
|
102
|
+
`sf_create_bot_routing`, and `sf_assign_skill_to_agent` (none of which had any test before) lives in
|
|
103
|
+
`qa-agentforce.mjs` (47 checks) and `qa-agentforce-adjacent.mjs` (11 checks). `test-suite.mjs` is now
|
|
104
|
+
210 tests (was 215); re-run against `demo-org` after the changes above: 206 passed, 3 failed (all
|
|
105
|
+
pre-existing and unrelated — `sf_share_report_folder` field-length validation,
|
|
106
|
+
`sf_delete_scratch_org`/`sf_install_package` both probing intentionally-nonexistent targets), 1 skipped.
|
|
107
|
+
|
|
108
|
+
### Investigated — the Agentforce conversation test is still unproven, now for precisely two reasons
|
|
109
|
+
|
|
110
|
+
Went further than any previous session on both blockers named in the last release:
|
|
111
|
+
|
|
112
|
+
**Custom agent actions (`GenAiFunction`) are conclusively an org licensing ceiling, not a code
|
|
113
|
+
defect.** Beyond re-confirming every `invocationTargetType` is still rejected against a fresh
|
|
114
|
+
confirmed-Active flow, this session found and tried the specific fix: `demo-org` has two relevant
|
|
115
|
+
Permission Set Licenses sitting unused (`Agentforce Service Agent User` — 200 seats, 0 assigned;
|
|
116
|
+
`Agent platform builder` — 5 seats, 0 assigned). Assigning `Agent Platform Builder`'s permission set
|
|
117
|
+
succeeded but changed nothing. Assigning the one that actually gates this
|
|
118
|
+
(`AgentforceServiceAgentUser`, and its `AgentforceServiceAgentBase` companion) was rejected outright by
|
|
119
|
+
Salesforce: *"Ajay Semwal can't be assigned the Agentforce Service Agent User permission set license,
|
|
120
|
+
because Ajay Semwal's user license doesn't support it."* That's a base User License / edition ceiling,
|
|
121
|
+
not a permission set gap — nothing reachable from this MCP server's tools can change it.
|
|
122
|
+
|
|
123
|
+
**A live conversation turn needs a Setup UI session, and none exists in this MCP server by design.**
|
|
124
|
+
The Agent API requires an ACTIVE agent and a connected app's Consumer Key/Secret. Both dead ends above
|
|
125
|
+
converge here: agent activation has no API path (see the `activateAgent` fix above), and Consumer
|
|
126
|
+
Secret can only be viewed once from Setup → App Manager, never via any API. Getting either therefore
|
|
127
|
+
requires a human (or a browser-automation session with its own explicit device-confirmation step) in
|
|
128
|
+
Salesforce Setup — outside what a stdio metadata MCP server does. Recorded as a precise, actionable
|
|
129
|
+
handoff rather than an unexplained skip.
|
|
130
|
+
|
|
131
|
+
**Also tried and reverted:** attempting to pre-stage a working connected app for that eventual Setup UI
|
|
132
|
+
session surfaced a third, unresolved anomaly — connected apps created via `upsertMetadata` (Salesforce's
|
|
133
|
+
own SOAP response says `success: true`) became unretrievable via `readMetadata`/`listMetadataType`/SOQL
|
|
134
|
+
within roughly 10–20 minutes, while apps checked within seconds of creation persisted and deleted
|
|
135
|
+
cleanly. Root cause not identified (not a scope-literal issue — reproduced with the corrected literals
|
|
136
|
+
above). Flagged for follow-up, not fixed; treat any connected app in `demo-org` as unverified until
|
|
137
|
+
checked shortly after creation.
|
|
138
|
+
|
|
139
|
+
**QA housekeeping:** cascade-deleted 15 of the 22 leftover `QA*`-prefixed Agentforce agents (plus their
|
|
140
|
+
topics/planners/actions) accumulated across this and prior sessions, via the previously-unwired
|
|
141
|
+
`deleteAgent` service function. 8 remain — Salesforce's Metadata API delete rejects them with a generic
|
|
142
|
+
internal-server error (`ErrorId ...`, not an application-level error), on both batch and individual
|
|
143
|
+
retry; not something a client-side retry fixes. Today's own flow/Apex test artifacts were left in place
|
|
144
|
+
(flows are Active and must be deactivated before delete; Apex class deletion via this org's Metadata
|
|
145
|
+
API delete path is rejected as "not available for this organization") — low-risk, consistent with this
|
|
146
|
+
project's existing no-teardown QA methodology. The broader "few hundred QA artifacts, no teardown
|
|
147
|
+
suite" backlog noted previously is real, unaddressed, and grew further from this session's full
|
|
148
|
+
`test-suite.mjs` run (required to confirm no regressions) — still a separate, unstarted engineering task.
|
|
149
|
+
|
|
150
|
+
## [2.8.5] - 2026-07-30
|
|
151
|
+
|
|
152
|
+
### Fixed — 8 more bugs, from widening Agentforce QA past the four headline tools
|
|
153
|
+
|
|
154
|
+
Asked whether the v2.8.4 Agentforce testing was thorough, the honest answer was no: 4 of 8 agent-related tools, no runtime assertions, no content-level verification, only 2 of 5 action types, and a parameter (`actionNames`) that shipped without ever being exercised. Closing those gaps found eight more real bugs.
|
|
155
|
+
|
|
156
|
+
**`sf_retrieve_metadata` could never return metadata to anyone.** It started an async retrieve, handed back a job id, and the package contained no tool that calls `checkRetrieveStatus` — while the tool's own description told callers the zip was "available via Metadata API checkRetrieveStatus". Added `pollRetrieveStatus`/`retrieveMetadataAndWait`: the tool now waits for the job, unpacks the zip, and returns each file's path and source. This also unblocked every content-level assertion in the QA suites, which is how several bugs below were confirmed.
|
|
157
|
+
|
|
158
|
+
**`sf_create_einstein_bot` was non-functional — five separate defects, each hidden behind the previous one:**
|
|
159
|
+
- `<defaultLocale>` is not a `Bot` field ("Element defaultLocale invalid at this location").
|
|
160
|
+
- The ML domain element is `<botMlDomain>` with a `<name>` child, not `<mlDomain>` with `<developerName>`.
|
|
161
|
+
- The Bot and its BotVersion were upserted in two separate calls, but a Bot alone is rejected with "Bot needs at least one Bot version" — the sequence could never succeed. The version is now embedded as `<botVersions>` in the same payload.
|
|
162
|
+
- `BotStep` takes `<type>`, not `<conversationStepType>`, and its text belongs in `<botMessages><message>`, not a flat `<botMessage>`.
|
|
163
|
+
- `<isGoalStep>` is not a `BotDialog` field; it is `isPlaceholderDialog`.
|
|
164
|
+
|
|
165
|
+
**`sf_create_einstein_prediction` was also non-functional, and its XML is now correct element-by-element:** `<label>` → `<masterLabel>`; `<predictionType>` → `<type>`, whose `AIPredictionType` enum accepts only `BinaryClassification` and `Regression` (`Classification` and `Numeric` are rejected outright, so the schema's friendly `Classification` alias is now mapped before it reaches the XML); `<developerName>` and `<aiApplicationDeveloperName>` are both required, the latter naming an existing AIApplication; `<predictionField>` is a plain string, not a `fieldName`/`objectName` pair; and `<positiveLabel>`, `<negativeLabel>` and `<active>` are not elements of this type at all. `targetField` was a **required** schema parameter the XML never used — it is the predicted field and now populates `<predictionField>`.
|
|
166
|
+
|
|
167
|
+
**Verification widened, not just repeated:**
|
|
168
|
+
- `qa-agentforce.mjs` grew from 27 to 47 checks: content-level assertions that the deployed Bot really carries `persona` as `<role>`, `company`/`toneType`, the org-valid `agentType`/`type` enums and **no** `systemPrompt`; that the deployed planner carries every requested topic, `AiCopilot__ReAct` and a description; all five action types asserting their own `invocationTargetType` mapping; the previously-untested `actionNames`; planner replace semantics (verified by deploying a second action-free topic, so it no longer depends on actions the org cannot create); and a runtime section asserting the agent→planner link survives into deployed metadata and reading real `BotVersion` status from the org.
|
|
169
|
+
- New `qa-agentforce-adjacent.mjs` covers the four tools nothing had ever driven: `sf_create_einstein_bot`, `sf_create_bot_routing`, `sf_create_einstein_prediction`, `sf_assign_skill_to_agent`. `sf_assign_skill_to_agent` passes fully, including its negative cases.
|
|
170
|
+
|
|
171
|
+
**Results against `demo-org`:** `qa-agentforce.mjs` 30 passed / 1 failed / 16 skipped (the failure a transient `fetch failed`, not a defect); `qa-agentforce-adjacent.mjs` 6 passed / 0 failed / 5 skipped.
|
|
172
|
+
|
|
173
|
+
**Honest limits, unchanged and still not papered over.** No conversation test exists: the Agent API needs an ACTIVE agent plus a connected app with client credentials, and creating a connected app is a change to the org this suite should not make unasked — so "agent answers a real conversation turn" is a recorded skip. `demo-org` cannot create GenAiFunction actions, cannot deploy classic Bots ("You don't have access to bots of type Bot" — it licenses Agentforce agents instead), has no Queue for bot routing, and has no AIApplication for predictions. Those are org boundaries, recorded as skips and never as passes. The corrected Einstein Bot and Prediction XML is therefore structurally verified element-by-element against a live org, but neither has completed a successful end-to-end deploy anywhere.
|
|
174
|
+
|
|
175
|
+
## [2.8.4] - 2026-07-30
|
|
176
|
+
|
|
177
|
+
### Fixed — 6 Agentforce bugs; agent creation was broken end to end
|
|
178
|
+
|
|
179
|
+
Agentforce had three tests in `test-suite.mjs` and none of them could fail. They imported `createAgent`/`createAgentTopic` from `services/salesforce.js`, which **no MCP tool calls** — `src/tools/agentforce.ts` builds its own XML inline, so the tests covered an orphaned parallel implementation. Each was also wrapped in `try/catch` returning `success: true`, with results passed through `orgLimitFallback()`, which counts HTTP 500 / 404 / NOT_FOUND as a pass. `sf_create_agent_action`'s test never called the tool at all — it hand-rolled XML aimed at a flow named `NonExistentFlow`. And `sf_create_agent_planner`, the step without which an agent routes nothing, had no test whatsoever.
|
|
180
|
+
|
|
181
|
+
New `qa-agentforce.mjs` registers the four real tool handlers against a stub server, validates arguments through each tool's own zod schema, invokes the real handler, and verifies results with SOQL. Bugs it found:
|
|
182
|
+
|
|
183
|
+
- **`sf_create_agent_planner` deployed `GenAiPlanner`, a metadata type that no longer exists.** Salesforce superseded it with `GenAiPlannerBundle` and rejects the old type with "Not available for deploy for this API version". Step 4 of 4 therefore failed 100% of the time. Rewritten against the live org: `description`, `masterLabel` and `plannerType` are all required, `AiCopilot__ReAct` is the only accepted `PlannerType` (`ReAct`, `Standard` and `AiCopilot__Standard` are all rejected by the enum), topics belong in `<genAiPlugins><genAiPluginName>`, and `<botName>` is invalid on the bundle entirely.
|
|
184
|
+
- **The agent→planner link was never written, by any tool.** Because `<botName>` isn't valid on the planner, nothing connected the Bot to it — so even a successful planner left the agent inert. The link lives on the Bot, as `<conversationDefinitionPlanners><genAiPlannerName>`, verified accepted against the org. `sf_create_agent` gained an optional `plannerName` to write it; since that tool is idempotent, the sequence is now 5 steps, ending in a second `sf_create_agent` call. Its success message says so explicitly instead of claiming the agent is "fully wired".
|
|
185
|
+
- **`sf_create_agent` broke outright whenever `instructions` was passed.** It emitted `<systemPrompt>` inside `<botVersions>`, which Salesforce rejects: "Element systemPrompt invalid at this location in type BotVersion". Isolated by deploying one agent per optional parameter — minimal, `+description`, `+company`, `+persona` and `+tone` all succeed; only `+instructions` fails. `BotVersion` has no system-prompt field (confirmed by retrieving real Bot/BotVersion metadata from the org), so the parameter was removed and its description now points callers at `sf_create_agent_topic`'s `instructions`, which is where agent guidance actually belongs. CLAUDE.md's field-placement note listed `systemPrompt` as valid and has been corrected.
|
|
186
|
+
- **`sf_create_agent`'s `type` parameter was a no-op whose only two allowed values were both invalid.** It was schema-validated and passed to `buildBotDeployZip`, which ignores it — the XML hardcodes `agentType`/`type`. Its enum offered `Default` and `EinsteinCopilot`, which the code's own comment records as rejected by Salesforce. Removed.
|
|
187
|
+
- **`sf_create_agent_action` required two parameters it never reads.** `agentName` and `topicName` were mandatory while the schema's own descriptions called them "informational only, NOT written to the action XML". A caller correctly reasoning that the action XML doesn't need them got a hard zod rejection. Both are now optional.
|
|
188
|
+
- **`sf_create_agent_action`'s failure message sent callers to re-check a target that was already fine.** "Specify a valid invocationTarget and invocationTargetType" is also what Salesforce returns when custom agent actions aren't enabled in the org at all. The message now says so when it sees that specific error.
|
|
189
|
+
|
|
190
|
+
**Verified against `demo-org`:** agent deploys with every remaining optional field, both removed parameters are now rejected by the strict schema, the planner deploys as a `GenAiPlannerBundle` and appears in `GenAiPlannerDefinition`, a planner naming a nonexistent topic is still rejected, and the agent re-deploys with the planner link and reports it.
|
|
191
|
+
|
|
192
|
+
**Explicitly not fixed, because it is not a defect:** `sf_create_agent_action` cannot create actions in `demo-org`, but the cause is the org, not the tool. Hand-deploying spec-compliant `GenAiFunction` XML outside the suite — flat and bundle layouts, and every documented `invocationTargetType` (`flow`, `apex`, `standardInvocableAction`, `customInvocableAction`, `flowService`, plus capitalised variants) against a confirmed-Active flow, a confirmed-Active `@InvocableMethod` class, and standard invocable actions — was rejected identically every time. An earlier draft of this work called that a product bug; it isn't, and the suite now detects the condition and skips the dependent checks rather than reporting nine false failures. `sf_create_agent_topic` is likewise uninvolved: a zero-action topic deploys clean, and its failures here were downstream of actions that could not be created.
|
|
193
|
+
|
|
194
|
+
Also corrected in this release's own record: an earlier commit claimed `demo-org` had no Agentforce at all, based on a `sf org list metadata-types` call that returned 261 types without `Bot`. The org reports 266 types with `Bot` present — that probe ran while the org was still provisioning.
|
|
195
|
+
|
|
196
|
+
## [2.8.3] - 2026-07-30
|
|
197
|
+
|
|
198
|
+
### Fixed — 10 Flow bugs, found by testing the SOAP builder for the first time
|
|
199
|
+
|
|
200
|
+
v2.8.2 reported "30/30 Flow scenarios passing," and that was true, but it hid a structural gap: `sf_create_flow` builds XML with `buildFlowXml` (SOAP/upsertMetadata) while `sf_create_flow_from_xml` and every existing suite use `buildFlowDeployXml` (ZIP/deploy). These are two independent ~300-line generators, and **no suite had ever exercised the SOAP one**. Neither suite passed `triggerObject`/`triggerType` either — grep returns zero hits — so record-triggered flows, the single most common thing an admin builds, were never tested at all.
|
|
201
|
+
|
|
202
|
+
Wrote `qa-flow-comprehensive.mjs` to close both gaps: 46 flow definitions run through **both** builders, plus runtime verification that creates real records and asserts the flow actually fired. 142 checks. Bugs it found:
|
|
203
|
+
|
|
204
|
+
- **`flowType` was written straight into `<processType>`, so every record-triggered and scheduled flow failed to deploy** — `FlowProcessType` has no `RecordTriggeredFlow` or `ScheduledFlow` member; both are `AutoLaunchedFlow` at the process level, distinguished only by the `<start>` element's `triggerType`. Added `toProcessType()` in both builders.
|
|
205
|
+
- **Scheduled flows had no schedule at all** — the start element only handled record triggers, so a `ScheduledFlow` deployed as a plain autolaunched flow that never ran. Added `<schedule>` with new `scheduleFrequency`/`scheduleStartDate`/`scheduleStartTime` params.
|
|
206
|
+
- **`recordTriggerType` was hardcoded to `CreateAndUpdate`** — create-only and update-only triggers were unreachable. Now a parameter, and omitted entirely for `RecordBeforeDelete`, which Salesforce rejects it on.
|
|
207
|
+
- **No Update Records element existed** — Get/Create/Delete were present but not Update, so the most common admin pattern ("when the Opportunity closes, update its Account") could not be built. Added in both addressing modes, with a guardrail on the `inputReference` + `inputAssignments` combination Salesforce forbids.
|
|
208
|
+
- **No Formula, Constant, or Text Template resources existed.** Added to both builders; constants emit type-correct value tags instead of coercing everything to `stringValue`.
|
|
209
|
+
- **`IsNotNull` was rejected by Salesforce everywhere it appeared** — `FlowComparisonOperator` has no such member ("is not null" is `IsNull` compared against `false`), yet the schema advertises it. Now translated in all six sites that accept an operator. The first fix attempt landed in the SOAP builder only and inverted the boolean without changing the operator name in the ZIP builder; the new suite caught that on its first run, and the filter paths in *both* builders turned out to have the same untranslated operator. All six now share one `nullOperatorXml()` helper so this cannot land one-sided again.
|
|
210
|
+
- **Null checks in `GetRecords`/`UpdateRecords` filters emitted an empty `<stringValue>`** where Salesforce requires a `booleanValue`.
|
|
211
|
+
- **`recordUpdates` emitted `<inputReference>{!$Record}</inputReference>`** — merge syntax belongs in formula and text contexts only; an `inputReference` takes the bare element name, so this resolved to nothing.
|
|
212
|
+
- **A `fieldUpdates` formula was inlined as `<formula>` inside `<inputAssignments><value>`**, but `FlowElementReferenceOrValue` has no `formula` child. It is now hoisted into a real `<formulas>` resource the assignment references by name. New `fieldUpdates.formulaDataType` controls its return type — previously formulas were always `String`, and the field was read by the service but missing from the strict zod schema, so no caller could set it.
|
|
213
|
+
- **Latent ordering bug:** the approval-submit `actionCall` and the `fieldUpdates` `recordUpdate` were emitted outside the type-grouping logic, so combining `submitForApprovalProcessName` with an `ApexAction` or `SendEmailAlert` produced non-contiguous `<actionCalls>`, which MDAPI rejects. Both are now merged into their type groups.
|
|
214
|
+
- The `elements` description still advertised `Wait` and `PlatformEvent`, which v2.5.x removed from the enum — an LLM reading it would emit elements zod rejects.
|
|
215
|
+
|
|
216
|
+
**Final run: 142 passed, 0 failed** against `demo-org` — 10 flow types/structures, 20 record-trigger configurations, 22 variable/resource cases, 68 element cases, 12 connector and guardrail cases, 5 lifecycle (activate/versions/deactivate), and 5 runtime assertions proving before-save stamping, after-save related-record creation, entry-criteria suppression, Loop iteration, and Update Records all actually execute in the org.
|
|
217
|
+
|
|
218
|
+
One suite failure was a test bug, not a product defect, and is recorded as such: the entry-criteria check compared the `Industry` picklist with a bare `=`, which Salesforce rejects in favour of `ISPICKVAL`. The tool passed the caller's formula through verbatim and surfaced Salesforce's real reason — correct behavior, so the test was fixed rather than the code.
|
|
219
|
+
|
|
220
|
+
`server.json`'s description still claimed 219 tools; corrected to 221.
|
|
221
|
+
|
|
222
|
+
## [2.8.2] - 2026-07-30
|
|
223
|
+
|
|
224
|
+
### Fixed — 5 more real bugs found by full regression testing across all 221 tools
|
|
225
|
+
|
|
226
|
+
Ajay asked for thorough regression testing against every tool with edge cases, not just the tools touched in v2.8.0/2.8.1. Ran the repo's full `test-suite.mjs` (215 tests, all 221 tools either directly exercised or reviewed) against `demo-org`, plus the dedicated Flow QA suite (33 scenarios). Found and fixed:
|
|
227
|
+
|
|
228
|
+
- **`sf_create_global_value_set`** — schema didn't enforce or document the required `__gvs` fullName suffix; Salesforce rejects GlobalValueSet without it. Added regex validation matching the existing `__c`/`__mdt` pattern used by other metadata types, plus a description note.
|
|
229
|
+
- **`sf_create_business_process`** — XML included a `<label>` element that doesn't exist in the `BusinessProcess` Metadata API type at all (Salesforce: "label invalid at this location"). Removed it; `label` still feeds the `description` fallback.
|
|
230
|
+
- **`sf_create_dashboard`** — built XML inline without escaping (`ui.ts`), unlike every other metadata builder in the codebase. A `&` in the title broke the deploy outright. Applied the `x()` escaping helper to `fullName`, `title`, `description`, `runningUser`, and component `reportApiName`/`header`/`footer`.
|
|
231
|
+
- **`sf_create_escalation_rule`** — same missing-escaping issue (`automation.ts`) on `formula`, `assignedTo`, `notifyTo`, `template`, `ruleName`. `formula` is especially exposed since Salesforce formulas commonly contain `<`, `>`, `&&`.
|
|
232
|
+
- **`sf_create_field_dependency`** — two-layer bug. (1) Wrapped `controllingField`/`valueSettings` in a `<fieldDependency>` element that doesn't exist on `CustomField` (Salesforce: "fieldDependency invalid at this location") — they belong directly inside `<valueSet>`. (2) Even after that fix, a from-scratch SOAP update carrying only the new dependency info failed with "Could not resolve standard field's name" — Salesforce needs the field's full existing metadata (label, type, current values) present in the same update. Rewrote using the same Tooling-API read-merge-PATCH pattern already proven by `addPicklistValues`, instead of hand-building SOAP XML.
|
|
233
|
+
|
|
234
|
+
Also fixed **`getFreshTokenFromCLI`** (JWT/CLI auth path): didn't check `err.stdout` on a non-zero exit, so a transient CLI hiccup (e.g. an update-nag banner polluting stdout) discarded an otherwise-valid access token. Same root cause as the `execSfCli` fix in 2.8.1, applied to the one auth code path that predates it.
|
|
235
|
+
|
|
236
|
+
**Test coverage added:** `test-suite.mjs` gained a `sf_create_field_dependency` test (previously imported but never exercised) and its `sf_create_global_value_set`/`sf_delete_scratch_org` test data bugs were fixed (wrong fullName suffix, wrong parameter name — test bugs, not product bugs). `sf_update_dashboard`'s test no longer assumes a folder literally named "Dashboards" exists (org-specific sample-data assumption); it now discovers a real Dashboard folder first.
|
|
237
|
+
|
|
238
|
+
**Final confirmation run: 212 passed, 2 expected negative-test outcomes (deleting a nonexistent scratch org / installing a fake package ID — both now correctly surface the real Salesforce rejection reason instead of a generic error, proof the 2.8.1 error-handling fix works), 1 skipped (OmniStudio, not enabled in this org), 215 total.**
|
|
239
|
+
|
|
240
|
+
**Flow QA suite (33 scenarios, `qa-flow-test.mjs`) — fully resolved, zero code bugs found:** Initial run showed 18 passed / 15 failed. Root-caused every failure instead of assuming they were code defects: 11 traced to the test assuming specific Account/Opportunity records ("Apex Technologies", "Opp-Acct1-1") existed in the org — leftover from whatever org this suite was originally built against, absent in `demo-org` (which only has standard DE sample data like "Edge Communications"). Created the missing seed records; those 11 passed immediately with no code changes. 1 (T01) was pure infra flakiness — a Windows `cmd.exe` spawn timeout unrelated to Salesforce, passed clean on retry. The remaining 3 (`PROD_Get_Account_Overview` etc.) test pre-existing production flows this suite never creates — they don't exist in any org this suite would be pointed at fresh, confirmed out of scope. **Final: 30/30 real scenarios passing.** This also means the "Known Bugs Pending Fix" list in CLAUDE.md (Loop elements, cross-variable filters, Decision XML, GetRecords gaps, missing inline-XML support, missing `sf_create_flow_from_xml`) was entirely stale — none of it reproduced. Retired that list in CLAUDE.md with a dated note explaining why, rather than leaving inaccurate bug reports in the project's own docs.
|
|
241
|
+
|
|
242
|
+
Also fixed `qa-flow-test.mjs`'s own test harness bug: hardcoded `--target-org secondorg` in its Apex-verification helper, now reads `SF_ALIAS` with a fallback.
|
|
243
|
+
|
|
244
|
+
## [2.8.1] - 2026-07-29
|
|
245
|
+
|
|
246
|
+
### Fixed — 5 real bugs found by thorough live-org testing of v2.8.0, same day
|
|
247
|
+
|
|
248
|
+
Ajay pointed live testing at a working CLI-authenticated org (`demo-org`) after v2.8.0 shipped without it, then asked for thorough testing before this patch went out. Testing surfaced genuine defects:
|
|
249
|
+
|
|
250
|
+
- **`sf_run_code_scanner` returned 404 against every org** — its Tooling API query path double-prefixed `/services/data/v66.0` (the HTTP client's base URL already includes it). Copied this bug from `sf_scan_apex_antipatterns`.
|
|
251
|
+
- **`sf_scan_apex_antipatterns` has had the identical 404 bug since it shipped in v2.7.0 (2026-07-23)** — it was never tested against a live org before now, so this went undetected for 6 days across two releases. Fixed alongside the copy.
|
|
252
|
+
- **`sf_run_code_scanner`'s Java-fallback was cosmetic, not functional** — restricting `--rule-selector` to Java-free engines doesn't stop `code-analyzer` from still trying to *instantiate* the PMD/CPD/SFGE engines first, so it threw 3 "Critical" `UninstantiableEngineError` pseudo-violations even while the response's own `note` field claimed those engines "were skipped." Fixed by generating a `code-analyzer.yml` that explicitly sets `disable_engine: true` on each when Java isn't detected — verified clean (0 fake violations) against `demo-org`.
|
|
253
|
+
- **Every SF-CLI-wrapping function (`installPackage`, `uninstallPackage`, `createPackage`, `createPackageVersion`, `deleteScratchOrg`, `createNewScratchOrg`) swallowed the actual Salesforce error on failure** — Node's `execSync` puts the CLI's `--json` error payload on `err.stdout`, not `err.message`, so callers only ever saw a generic "Command failed: sf package ..." with no reason. Extracted a shared `execSfCli()` helper that parses `err.stdout` first; verified live by attempting to uninstall `demo-org`'s installed package and correctly receiving the real Salesforce reason ("Unable to delete custom app. Profiles are using this custom app as default...") instead of the useless wrapper text.
|
|
254
|
+
- **`sf_install_package` (pre-existing, not something this session touched originally) hung/force-failed on any package requesting third-party site access** — `sf package install` shows an interactive "Grant access?" confirmation for Remote Site Settings/CSP, which `execSync`'s non-interactive session can never answer, throwing `ExitPromptError`. Fixed by always passing `--no-prompt` (there's no scenario where an MCP tool call can answer an interactive prompt, so this is correct unconditionally, not just a default).
|
|
255
|
+
|
|
256
|
+
**All fixes verified against `demo-org` with real success AND failure paths, not just one or the other:**
|
|
257
|
+
- `sf_run_code_scanner` / `sf_scan_apex_antipatterns`: real findings returned (4 classes scanned, 0 violations, accurate `note`)
|
|
258
|
+
- `sf_uninstall_package`: failure path confirmed — real multi-component Salesforce rejection reason now surfaces correctly
|
|
259
|
+
- `sf_install_package`: **full success path confirmed** — real install against `demo-org` returned `Status: "SUCCESS"` end to end, only possible after the `--no-prompt` fix
|
|
260
|
+
- Broader regression sanity: unrelated, untouched tools (`sf_query_records`, `sf_describe_object`) spot-checked against the same org to confirm the shared auth/HTTP client plumbing wasn't affected
|
|
261
|
+
|
|
262
|
+
**Known remaining gap, documented not hidden:** `createNewScratchOrg`/`deleteScratchOrg`/`createPackage`/`createPackageVersion` could not be exercised live — `demo-org` is not Dev Hub-enabled, and creating one is out of scope for a same-day bug-fix pass. Their `execSfCli` usage is mechanically identical to `installPackage`'s (now proven), so risk is low, but this is explicitly unverified, not silently assumed fine.
|
|
263
|
+
|
|
264
|
+
## [2.8.0] - 2026-07-29
|
|
265
|
+
|
|
266
|
+
### Added — 2 new tools closing gaps found in a fresh competitive scan
|
|
267
|
+
|
|
268
|
+
Re-checked npm competitors (@salesforce/mcp, @tsmztech/mcp-server-salesforce, and two new entrants that surpassed this package's downloads: @alfe.ai/salesforce-mcp and @advanced-communities/salesforce-mcp-server at 41 tools). Found two genuine, well-defined gaps:
|
|
269
|
+
|
|
270
|
+
- `sf_uninstall_package` — package uninstall via the SF CLI, completing the create/install/uninstall package lifecycle (`sf_install_package` existed with no counterpart)
|
|
271
|
+
- `sf_run_code_scanner` — wraps Salesforce Code Analyzer (PMD, SFGE SOQL-injection data-flow analysis, RetireJS, ESLint, regex) for real multi-engine static analysis, complementing the existing lightweight `sf_scan_apex_antipatterns` heuristic. Auto-detects Java on the host; if absent, gracefully restricts to the Java-free engines (eslint, retire-js, regex, flow) and reports this in the response instead of surfacing raw engine-instantiation errors.
|
|
272
|
+
|
|
273
|
+
Tool count: 219 → 221. Verified: clean `tsc` build, mock-server registration count (221, no duplicate names), `sf package uninstall --help`/`sf code-analyzer run --help` flag inspection matches what the code sends, and a local (no-org) dry run of `sf code-analyzer run` confirming the Java-detection fallback path produces valid, parseable output.
|
|
274
|
+
|
|
275
|
+
**Not yet verified against a live org** — `secondorg`'s JWT auth is currently broken (Connected App OAuth scope issue, pre-existing, tracked separately) and the only CLI-authenticated org on this machine is the employer org, which this project's rules forbid using for anything. So neither tool's full org round-trip (`sf_uninstall_package`'s install→uninstall, or `sf_run_code_scanner`'s query→scan against real Apex classes) has been exercised end-to-end yet. Re-run both once `secondorg` auth is fixed, before relying on this release in production.
|
|
276
|
+
|
|
3
277
|
## [2.7.0] - 2026-07-23
|
|
4
278
|
|
|
5
279
|
### Added — 7 new tools closing the "daily developer loop" gap
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
[](https://modelcontextprotocol.io)
|
|
7
7
|
|
|
8
|
-
**The only Salesforce MCP server that builds Agentforce agents, OmniStudio components, and DevOps Center pipelines** — alongside a complete daily developer loop (schema describe, Apex read, debug logs) and
|
|
8
|
+
**The only Salesforce MCP server that builds Agentforce agents, OmniStudio components, and DevOps Center pipelines** — alongside a complete daily developer loop (schema describe, Apex read, debug logs) and 222 tools total for building, configuring, and automating Salesforce orgs directly from Claude or any MCP client.
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -47,7 +47,7 @@ See [SETUP.md](SETUP.md) for all authentication methods and detailed setup instr
|
|
|
47
47
|
|
|
48
48
|
---
|
|
49
49
|
|
|
50
|
-
## Tools —
|
|
50
|
+
## Tools — 222 total
|
|
51
51
|
|
|
52
52
|
Highlights below; see [TOOLS.md](TOOLS.md) for the complete reference with parameters and example prompts.
|
|
53
53
|
|
|
@@ -122,6 +122,8 @@ Highlights below; see [TOOLS.md](TOOLS.md) for the complete reference with param
|
|
|
122
122
|
| `sf_enable_debug_logs` | Turn on Apex debug logging for a user (TraceFlag) |
|
|
123
123
|
| `sf_get_debug_logs` | List recent Apex debug logs |
|
|
124
124
|
| `sf_get_debug_log_body` | Read the full content of a debug log |
|
|
125
|
+
| `sf_scan_apex_antipatterns` | Lightweight heuristic scan for SOQL/DML-in-loop, hardcoded IDs, debug statements |
|
|
126
|
+
| `sf_run_code_scanner` | Multi-engine static analysis (PMD, SFGE SOQL-injection data-flow, RetireJS, ESLint) via Salesforce Code Analyzer |
|
|
125
127
|
|
|
126
128
|
### LWC Development
|
|
127
129
|
| Tool | Description |
|
|
@@ -147,6 +149,7 @@ Highlights below; see [TOOLS.md](TOOLS.md) for the complete reference with param
|
|
|
147
149
|
| Tool | Description |
|
|
148
150
|
|------|-------------|
|
|
149
151
|
| `sf_create_connected_app` | Create OAuth Connected Apps |
|
|
152
|
+
| `sf_create_external_client_app` | Create External Client Apps (OAuth) — Salesforce's newer replacement for Connected Apps; Client Credentials Flow (incl. Run As user) is API-settable here, unlike Connected Apps |
|
|
150
153
|
| `sf_create_external_data_source` | Create External Data Sources for Connect |
|
|
151
154
|
| `sf_create_external_object` | Create External Objects (__x) |
|
|
152
155
|
| `sf_create_remote_site_setting` | Whitelist external URLs for callouts |
|
|
@@ -207,7 +210,7 @@ Highlights below; see [TOOLS.md](TOOLS.md) for the complete reference with param
|
|
|
207
210
|
## Documentation
|
|
208
211
|
|
|
209
212
|
- [SETUP.md](SETUP.md) — Prerequisites, authentication, Claude configuration
|
|
210
|
-
- [TOOLS.md](TOOLS.md) — All
|
|
213
|
+
- [TOOLS.md](TOOLS.md) — All 222 tools with full parameter documentation
|
|
211
214
|
- [AGENTFORCE.md](AGENTFORCE.md) — Agentforce agent creation guide
|
|
212
215
|
- [APEX_LWC.md](APEX_LWC.md) — Apex and LWC development guide
|
|
213
216
|
- [CHANGELOG.md](CHANGELOG.md) — Version history
|
package/TOOLS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Tools Reference
|
|
2
2
|
|
|
3
|
-
Complete documentation for all
|
|
3
|
+
Complete documentation for all 222 tools in `salesforce-metadata-mcp`. (Highlights below cover the most commonly used tools in depth; see the README's full 222-tool table for every tool name.)
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -323,4 +323,4 @@ Reads the current field-level security grants for a field across all Profiles an
|
|
|
323
323
|
|
|
324
324
|
---
|
|
325
325
|
|
|
326
|
-
*For the complete list of all
|
|
326
|
+
*For the complete list of all 222 tools, see [README.md](README.md).*
|