feat(salesforce): add Tooling API schema tools (custom field/object) + metadata query#5209
feat(salesforce): add Tooling API schema tools (custom field/object) + metadata query#5209waleedlatif1 wants to merge 4 commits into
Conversation
…+ metadata query Add salesforce_create_custom_field, salesforce_update_custom_field, salesforce_delete_custom_field, salesforce_create_custom_object, and salesforce_tooling_query so the connector can make schema/metadata changes (e.g. create a custom field on Account). Previously the integration only did record CRUD via the REST Data API. Existing `api` OAuth scope covers the Tooling API; metadata creation is profile-permission gated, so no scope change. Also: fix Opportunity closeDate being wrongly required on update_opportunity, make list_reports/list_dashboards descriptions honest (recently-viewed scope), and document run_report's includeDetails default.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryHigh Risk Overview Shared Accuracy fixes: Opportunity Reviewed by Cursor Bugbot for commit 7fa34ad. Configure here. |
Greptile SummaryThis PR adds 5 Salesforce Tooling API tools (
Confidence Score: 5/5Safe to merge — all five new Tooling API tools are correctly implemented, the previously flagged silent label overwrite in update_custom_field is confirmed fixed via read-modify-write, and the accuracy fixes are straightforward description and optionality corrections. The new tools follow established patterns (OAuth, error handling, response transformation), the update path does a proper GET-then-PATCH to preserve unspecified metadata, type-specific defaults are applied only on create, and delete/update correctly handle the 204 No Content response without reading the body. The accuracy fixes are low-risk doc/optionality changes. No functional regressions or logic bugs were found. No files require special attention. The only note is the shared Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User
participant Block as Salesforce Block
participant Tool as Salesforce Tool (directExecution/request)
participant SFAPI as Salesforce Tooling API
Note over Block,SFAPI: Create Custom Field
User->>Block: select "Create Custom Field" op
Block->>Tool: salesforce_create_custom_field
Tool->>SFAPI: POST /tooling/sobjects/CustomField
SFAPI-->>Tool: "{id, success, errors}"
Tool-->>User: "{id, fullName, success, created}"
Note over Block,SFAPI: Update Custom Field (read-modify-write)
User->>Block: select "Update Custom Field" op
Block->>Tool: salesforce_update_custom_field
Tool->>SFAPI: "GET /tooling/sobjects/CustomField/{id}"
SFAPI-->>Tool: existing Metadata
Tool->>SFAPI: "PATCH /tooling/sobjects/CustomField/{id}"
SFAPI-->>Tool: 204 No Content
Tool-->>User: "{id, updated: true}"
Note over Block,SFAPI: Delete Custom Field
User->>Block: select "Delete Custom Field" op
Block->>Tool: salesforce_delete_custom_field
Tool->>SFAPI: "DELETE /tooling/sobjects/CustomField/{fieldId}"
SFAPI-->>Tool: 204 No Content
Tool-->>User: "{id, deleted: true}"
Note over Block,SFAPI: Create Custom Object
User->>Block: select "Create Custom Object" op
Block->>Tool: salesforce_create_custom_object
Tool->>SFAPI: POST /tooling/sobjects/CustomObject
SFAPI-->>Tool: "{id, success, errors}"
Tool-->>User: "{id, fullName, success, created}"
Note over Block,SFAPI: Tooling SOQL Query
User->>Block: select "Run Tooling Query" op
Block->>Tool: salesforce_tooling_query
Tool->>SFAPI: "GET /tooling/query?q=encoded_SOQL"
SFAPI-->>Tool: "{records, totalSize, done, nextRecordsUrl}"
Tool-->>User: "{records, totalSize, done, ...}"
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant User
participant Block as Salesforce Block
participant Tool as Salesforce Tool (directExecution/request)
participant SFAPI as Salesforce Tooling API
Note over Block,SFAPI: Create Custom Field
User->>Block: select "Create Custom Field" op
Block->>Tool: salesforce_create_custom_field
Tool->>SFAPI: POST /tooling/sobjects/CustomField
SFAPI-->>Tool: "{id, success, errors}"
Tool-->>User: "{id, fullName, success, created}"
Note over Block,SFAPI: Update Custom Field (read-modify-write)
User->>Block: select "Update Custom Field" op
Block->>Tool: salesforce_update_custom_field
Tool->>SFAPI: "GET /tooling/sobjects/CustomField/{id}"
SFAPI-->>Tool: existing Metadata
Tool->>SFAPI: "PATCH /tooling/sobjects/CustomField/{id}"
SFAPI-->>Tool: 204 No Content
Tool-->>User: "{id, updated: true}"
Note over Block,SFAPI: Delete Custom Field
User->>Block: select "Delete Custom Field" op
Block->>Tool: salesforce_delete_custom_field
Tool->>SFAPI: "DELETE /tooling/sobjects/CustomField/{fieldId}"
SFAPI-->>Tool: 204 No Content
Tool-->>User: "{id, deleted: true}"
Note over Block,SFAPI: Create Custom Object
User->>Block: select "Create Custom Object" op
Block->>Tool: salesforce_create_custom_object
Tool->>SFAPI: POST /tooling/sobjects/CustomObject
SFAPI-->>Tool: "{id, success, errors}"
Tool-->>User: "{id, fullName, success, created}"
Note over Block,SFAPI: Tooling SOQL Query
User->>Block: select "Run Tooling Query" op
Block->>Tool: salesforce_tooling_query
Tool->>SFAPI: "GET /tooling/query?q=encoded_SOQL"
SFAPI-->>Tool: "{records, totalSize, done, nextRecordsUrl}"
Tool-->>User: "{records, totalSize, done, ...}"
Reviews (5): Last reviewed commit: "improvement(salesforce): scope custom fi..." | Re-trigger Greptile |
…metadata param types - update_custom_field now does a read-modify-write (GET existing Metadata, overlay only provided changes, PATCH) so omitted properties are preserved instead of being reset by the Tooling API's full-metadata PATCH; no more fabricated label or injected create-time defaults on update - fieldType is now optional on update (kept from the existing field unless changed) - widen length/precision/scale/visibleLines param types to number | string to match the tool param configs (type: number)
|
@greptile All review threads addressed in 5ea0e0c:
Please re-review. |
|
@cursor review |
…adata on field type change - custom field update now unions provided picklist values with the field's existing values instead of replacing the whole valueSet (no data loss) - when fieldType changes on update, drop the prior type's type-specific metadata (length/precision/scale/visibleLines/valueSet/defaultValue/unique/ externalId) and backfill the new type's required defaults
|
@greptile Addressed the two follow-ups in 75fa2ff:
Please re-review. |
|
@cursor review |
…er the type update_custom_field no longer changes a field's data type: Salesforce treats a type change as a separate conversion operation, and a stale forwarded fieldType could otherwise trigger an unintended destructive migration. The merge keeps the field's existing type and overlays only the other provided properties, dropping the type-change/stale-metadata-stripping logic entirely.
|
@greptile Note: your Confidence Score footer still references 5ea0e0c — please re-review the latest HEAD (7fa34ad). Since then: picklist values union on update, and update_custom_field no longer changes a field's type (keeps the existing type; type changes are out of scope as a Salesforce conversion operation). |
|
@cursor review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7fa34ad. Configure here.

Summary
salesforce_create_custom_field,salesforce_update_custom_field,salesforce_delete_custom_field,salesforce_create_custom_object,salesforce_tooling_query./sobjects/...), and field creation lives in the Tooling/Metadata API (/tooling/sobjects/CustomField).apiscope already covers the Tooling API. Creating metadata is gated by the user's Salesforce profile permission ("Customize Application"), not by an OAuth scope.create_custom_fieldsupports all common field types (Text, Number, Currency, Percent, Checkbox, Date/Time, Phone, Email, Url, Picklist, MultiselectPicklist, TextArea/LongTextArea/Html) with sensible type-specific defaults; picklist value sets accepted as a comma-separated list.tools/registry.ts, and regenerated integration docs.Accuracy fixes (found during a full per-tool audit of the integration)
closeDatebeing unconditionally required — it was wrongly required onupdate_opportunity(Salesforce treats it as optional on update).list_reports/list_dashboardsdescriptions honest: these endpoints return recently viewed items (≤200), not the full catalog.run_report's deliberateincludeDetailsdefault (Sim defaults totrue; the Salesforce API default isfalse).Type of Change
Testing
Tested manually. Typecheck clean (0 errors), lint clean, docs regenerated. Every Salesforce tool (all 40) was audited against the live Salesforce REST/Tooling/Analytics API docs and verified for tool↔API and block↔tool alignment.
Checklist