forcedotcom / forcedotcom/d360-mcp-server

d360_dmo_field_mapping_add sends unrecognized 'fieldMappings' key, PATCH always fails

Open
#16 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
16
Forks
12
PR merge metrics
No merged PRs in 30d

Description

## Summary

`d360_dmo_field_mapping_add` (PATCH `/ssot/data-model-object-mappings/{mappingName}/field-mappings`) cannot succeed against a live org. The request DTO only has one field, `fieldMappings`, and the real Data Cloud API rejects that key outright.

## Root cause

`FieldMappingAddRequest.java`:

```java
public class FieldMappingAddRequest {
private List fieldMappings;
...
}
```

`MappingTools.addFieldMappings` serializes this straight to the PATCH body via `JsonUtil.toMap(request)`, so the outbound body is always `{"fieldMappings": [...]}`.

## Reproduction

Called via the MCP tool against a live org (Salesforce Data Cloud, API v67.0):

```
POST/PATCH /ssot/data-model-object-mappings/{mappingName}/field-mappings
{"fieldMappings":[{"sourceFieldDeveloperName":"CreatedById__c","targetFieldDeveloperName":"CreatedById__c"}]}
```

Response:

```json
{"errorCode":"JSON_PARSER_ERROR","message":"Unrecognized field \"fieldMappings\" at [line:1, column:19]"}
```

Any other key I tried (`fieldMapping` singular, adding `sourceEntityDeveloperName`/`targetEntityDeveloperName`) is silently dropped by `FieldMappingAddRequest`'s Jackson deserialization (since none of those are declared fields), so those attempts sent an effectively empty body and got a different, equally unhelpful error (`INVALID_INPUT: Source Entity Developer Name in Request Body is missing`).

I confirmed `d360_dmo_mapping_create` (POST `/ssot/data-model-object-mappings`, different endpoint) is correctly implemented — it uses `sourceEntityDeveloperName` / `targetEntityDeveloperName` / `fieldMapping` (singular) and those are exactly what the live API expects. It correctly rejects re-creating a mapping between an already-mapped DLO/DMO pair with `DUPLICATE_DLO_TO_DMO_MAPPING`, so it can't be reused as a workaround for adding fields to an existing mapping either.

## What the real API actually expects for "add fields to an existing mapping"

I captured the network request Salesforce's own Data Cloud Setup UI (the Data Model mapping canvas) sends when adding new field-level mappings to an existing DLO→DMO mapping. It does **not** hit the public `/ssot/data-model-object-mappings/{name}/field-mappings` REST path at all — it calls an internal Aura controller action (`ui.cdp.components.controllers.datastreams.DataModelingController/ACTION$deploy`) with the **entire** target mapping's field list (existing pairs + new ones), not just the delta:

```json
{
"config": {
"dseId": "...",
"category": "Profile",
"dloDeveloperName": "CampaignMember_Home__dll",
"targetRefModel": [{
"refModelName": "ssot__CampaignMember__dlm",
"mappings": [
{"filterApplied": false, "source": "CampaignId__c", "target": "ssot__CampaignId__c"},
... all existing pairs ...,
{"filterApplied": false, "source": "CreatedById__c", "target": "CreatedById__c"}
],
"refModelCategory": "Profile"
}],
"addedAttributes": [],
"addedTargetRefModel": [],
"dataSpaceName": "default"
}
}
```

This suggests the public REST `field-mappings` PATCH sub-resource may not actually support incremental adds the way this tool's docstring implies — worth checking with the Data Cloud API team whether that endpoint is meant to accept a full replacement body instead (in which case `FieldMappingAddRequest` needs `sourceEntityDeveloperName`/`targetEntityDeveloperName` plus the full field list), or whether it's genuinely broken server-side.

## Suggested fix

At minimum, fix the DTO/serialization mismatch. Given the UI's own behavior, it's possible the intended contract is closer to a full-replace than a true incremental PATCH — worth confirming against the actual Data Cloud API spec before just renaming the field.

## Environment

- Server built from source, jar built 2026-09-14
- Salesforce Data Cloud API v67.0
- Reproduced against a live production org

Contributor guide

Open the contributing guide

Research direction

Start with FieldMappingAddRequest.java and MappingTools.addFieldMappings, then inspect how JsonUtil.toMap(request) forms the PATCH body. Compare that output with the Data Cloud v67.0 contract and the captured Setup UI request, and confirm with the Data Cloud API team whether the endpoint expects a full replacement or supports incremental adds. Done means the contract is established and the tool sends a body accepted by the live API.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api, backend-api-design
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.