Describe the issue
MCP appears to treat a field as read-only based on the table definition, even when the API page explicitly marks the field as editable. Direct API calls through Business Central work correctly and persist the value, but MCP omits the field from its Create/Modify schemas and rejects it as an unknown property. I've attached a full reproduction project and documentation.
Microsoft support told me to reach out to create this ticket this way. TrackingID#2609110010002781
Expected behavior
The MCP should respect the page editability property over the table editability, just like when you call it through the API and on Business Central Pages.
Steps to reproduce
Reproduction objects
The following three AL objects are included:
| File |
Object |
Purpose |
MCPWritableDemo.Table.al |
Table 83707SWL-API MCP Writable Demo |
Stores isolated test records |
MCPWritableDemoAPI.Page.al |
Page 83767SWL-API MCP Writable Demo API |
Exposes the records through a custom API |
MCPDemo.PermissionSet.al |
Permission Set 83700SWL-API MCP Demo |
Grants access to the table and API page |
Table definition
Table 83707 contains two fields used for the comparison:
field(3; "Quantity To Post"; Decimal)
{
Caption = 'Quantity To Post';
}
field(4; "New Bin Code"; Code[20])
{
Caption = 'New Bin Code';
Editable = false;
}
Quantity To Post is editable by default. New Bin Code is explicitly read-only at the table level.
API definition
Page 83767 uses this route metadata:
APIPublisher = plumblineConsultingLLC
APIGroup = mcpRepro
APIVersion = v1.0
EntityName = mcpWritableFieldDemo
EntitySetName = mcpWritableFieldDemos
The relevant API controls are:
field(quantityToPost; Rec."Quantity To Post")
{
}
field(newBinCode; Rec."New Bin Code")
{
Editable = true;
}
This intentionally creates conflicting settings: the source table field is read-only while the API page field explicitly requests editability.
The complete API contract is:
| Property |
Editable |
Purpose |
id |
No |
ImmutableSystemId OData key |
code |
Yes |
Record identifier |
description |
Yes |
Editable text field |
quantityToPost |
Yes |
Editable control field |
newBinCode |
Yes through API |
Table hasEditable = false; API page has Editable = true; direct API write succeeds |
lastModifiedDateTime |
No |
Read-only system timestamp |
Deployment
- Publish the extension to a Business Central sandbox.
- Assign permission set
SWL-API MCP Demo to the MCP user.
- Confirm the API entity appears in the environment's
$metadata document.
- Restart or reconnect the Business Central MCP server to force action discovery.
MCP actions discovered
MCP discovered all expected CRUD actions:
Create_McpWritableFieldDemo_PAG83767
Delete_McpWritableFieldDemo_PAG83767
List_McpWritableFieldDemos_PAG83767
Modify_McpWritableFieldDemo_PAG83767
Generated schemas
The List action exposes all six API properties, including newBinCode:
id, code, description, quantityToPost, newBinCode, lastModifiedDateTime
The generated Create schema contains:
code, description, quantityToPost
The generated Modify schema contains:
id, If-Match, code, description, quantityToPost
MCP omits newBinCode from both write schemas even though the Business Central API accepts and persists the property.
Direct Business Central API control
The following request was sent directly to the custom Business Central API endpoint for Page 83767:
POST <api-base>/api/plumblineConsultingLLC/mcpRepro/v1.0/companies(<company-id>)/mcpWritableFieldDemos
Content-Type: application/json
{
"code": "Test00001-090926",
"description": "Test00001-090926",
"quantityToPost": 7,
"newBinCode": "1-F1"
}
Business Central returned 201 Created, including the persisted value in its response:
{
"code": "TEST00001-090926",
"description": "Test00001-090926",
"quantityToPost": 7,
"newBinCode": "1-F1"
}
This confirms that newBinCode is writable through the published Business Central API. The table-level Editable = false does not prevent the API page's explicit Editable = true override from accepting the value.
Test procedure and results
Compare the same Create operation through MCP
Invoke Create_McpWritableFieldDemo_PAG83767 with all four business properties:
{
"code": "MCP-COMPARE-0909",
"description": "Direct API versus MCP create",
"quantityToPost": 7,
"newBinCode": "1-F1"
}
MCP rejects the request before it reaches Business Central:
The tool Create_McpWritableFieldDemo_PAG83767 threw an McpBadRequestException exception.
Message: Unknown property newBinCode for operation Create_McpWritableFieldDemo_PAG83767.
Use 'bc_actions_describe' to see the valid properties for this action.
A List query for code MCP-COMPARE-0909 returned no record, confirming that MCP created no partial data.
Create
Invoke Create_McpWritableFieldDemo_PAG83767:
{
"code": "MCP-20260909-02",
"description": "Table versus page editability test",
"quantityToPost": 45
}
Result: the record was created successfully. The response included newBinCode with an empty value.
Modify an editable field
Invoke Modify_McpWritableFieldDemo_PAG83767 with the record ID and current @odata.etag:
{
"id": "<record-id>",
"If-Match": "<current-etag>",
"quantityToPost": 20
}
Result: the update succeeded, quantityToPost became 20, and Business Central returned a new etag.
Modify the conflicting-editability field
Invoke the same Modify action with the current ID and etag:
{
"id": "<record-id>",
"If-Match": "<current-etag>",
"newBinCode": "1-H1"
}
Result: MCP rejected the request before it reached Business Central:
The tool Modify_McpWritableFieldDemo_PAG83767 threw an McpBadRequestException exception.
Message: Unknown property newBinCode for operation Modify_McpWritableFieldDemo_PAG83767.
Use 'bc_actions_describe' to see the valid properties for this action.
Verify and clean up
Readback after the rejected request confirmed:
{
"quantityToPost": 20,
"newBinCode": ""
}
The rejected request caused no data mutation. The disposable record was deleted through Delete_McpWritableFieldDemo_PAG83767, and a final List query confirmed that it no longer existed.
Observed behavior
- After correcting permissions, Create, List, Modify of
quantityToPost, and Delete all succeeded, confirming that the MCP user has the required CRUD permissions.
- Direct Business Central OData accepts and persists
newBinCode on Create, returning 201 Created.
- MCP exposes
newBinCode through the List action.
- MCP excludes
newBinCode from Create and Modify despite the direct API proving that the property is writable.
- MCP rejects the same Create property as
Unknown property before the request reaches Business Central.
- Editable properties remain available and can be updated successfully.
- Supplying the omitted
newBinCode property causes MCP request validation to return Unknown property.
- A rejected request does not modify the Business Central record.
- Removing table-level
Editable = false causes MCP to expose and successfully write newBinCode through both Create and Modify.
MCP.zip
Additional context
No response
Describe the issue
MCP appears to treat a field as read-only based on the table definition, even when the API page explicitly marks the field as editable. Direct API calls through Business Central work correctly and persist the value, but MCP omits the field from its Create/Modify schemas and rejects it as an unknown property. I've attached a full reproduction project and documentation.
Microsoft support told me to reach out to create this ticket this way. TrackingID#2609110010002781
Expected behavior
The MCP should respect the page editability property over the table editability, just like when you call it through the API and on Business Central Pages.
Steps to reproduce
Reproduction objects
The following three AL objects are included:
MCPWritableDemo.Table.alSWL-API MCP Writable DemoMCPWritableDemoAPI.Page.alSWL-API MCP Writable Demo APIMCPDemo.PermissionSet.alSWL-API MCP DemoTable definition
Table 83707 contains two fields used for the comparison:
Quantity To Postis editable by default.New Bin Codeis explicitly read-only at the table level.API definition
Page 83767 uses this route metadata:
The relevant API controls are:
This intentionally creates conflicting settings: the source table field is read-only while the API page field explicitly requests editability.
The complete API contract is:
idSystemIdOData keycodedescriptionquantityToPostnewBinCodeEditable = false; API page hasEditable = true; direct API write succeedslastModifiedDateTimeDeployment
SWL-API MCP Demoto the MCP user.$metadatadocument.MCP actions discovered
MCP discovered all expected CRUD actions:
Generated schemas
The List action exposes all six API properties, including
newBinCode:The generated Create schema contains:
The generated Modify schema contains:
MCP omits
newBinCodefrom both write schemas even though the Business Central API accepts and persists the property.Direct Business Central API control
The following request was sent directly to the custom Business Central API endpoint for Page 83767:
Business Central returned
201 Created, including the persisted value in its response:{ "code": "TEST00001-090926", "description": "Test00001-090926", "quantityToPost": 7, "newBinCode": "1-F1" }This confirms that
newBinCodeis writable through the published Business Central API. The table-levelEditable = falsedoes not prevent the API page's explicitEditable = trueoverride from accepting the value.Test procedure and results
Compare the same Create operation through MCP
Invoke
Create_McpWritableFieldDemo_PAG83767with all four business properties:{ "code": "MCP-COMPARE-0909", "description": "Direct API versus MCP create", "quantityToPost": 7, "newBinCode": "1-F1" }MCP rejects the request before it reaches Business Central:
A List query for code
MCP-COMPARE-0909returned no record, confirming that MCP created no partial data.Create
Invoke
Create_McpWritableFieldDemo_PAG83767:{ "code": "MCP-20260909-02", "description": "Table versus page editability test", "quantityToPost": 45 }Result: the record was created successfully. The response included
newBinCodewith an empty value.Modify an editable field
Invoke
Modify_McpWritableFieldDemo_PAG83767with the record ID and current@odata.etag:{ "id": "<record-id>", "If-Match": "<current-etag>", "quantityToPost": 20 }Result: the update succeeded,
quantityToPostbecame 20, and Business Central returned a new etag.Modify the conflicting-editability field
Invoke the same Modify action with the current ID and etag:
{ "id": "<record-id>", "If-Match": "<current-etag>", "newBinCode": "1-H1" }Result: MCP rejected the request before it reached Business Central:
Verify and clean up
Readback after the rejected request confirmed:
{ "quantityToPost": 20, "newBinCode": "" }The rejected request caused no data mutation. The disposable record was deleted through
Delete_McpWritableFieldDemo_PAG83767, and a final List query confirmed that it no longer existed.Observed behavior
quantityToPost, and Delete all succeeded, confirming that the MCP user has the required CRUD permissions.newBinCodeon Create, returning201 Created.newBinCodethrough the List action.newBinCodefrom Create and Modify despite the direct API proving that the property is writable.Unknown propertybefore the request reaches Business Central.newBinCodeproperty causes MCP request validation to returnUnknown property.Editable = falsecauses MCP to expose and successfully writenewBinCodethrough both Create and Modify.MCP.zip
Additional context
No response