From 85c0f69369531feabae67555c49556b3c251d159 Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Tue, 16 Dec 2025 10:28:01 +0100
Subject: [PATCH 01/17] Configuration validation and UX improvements
---
.../Permissions/MCPObjects.PermissionSet.al | 8 +-
.../Codeunits/MCPConfig.Codeunit.al | 9 ++
.../MCPConfigImplementation.Codeunit.al | 91 +++++++++++++++++++
.../MCPConfigMissingObject.Codeunit.al | 36 ++++++++
.../MCPConfigMissingParent.Codeunit.al | 32 +++++++
.../Enums/MCPConfigWarningType.Enum.al | 32 +++++++
.../Interfaces/MCPConfigWarning.Interface.al | 15 +++
.../Configuration/Pages/MCPConfigCard.Page.al | 61 ++++++++++++-
.../Pages/MCPConfigToolList.Page.al | 17 ++--
.../Pages/MCPConfigWarningList.Page.al | 68 ++++++++++++++
.../Pages/MCPSystemToolList.Page.al | 53 +++++++++++
.../Tables/MCPConfigWarning.Table.al | 49 ++++++++++
.../Tables/MCPSystemTool.Table.al | 39 ++++++++
13 files changed, 496 insertions(+), 14 deletions(-)
create mode 100644 src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al
create mode 100644 src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
create mode 100644 src/System Application/App/MCP/src/Configuration/Enums/MCPConfigWarningType.Enum.al
create mode 100644 src/System Application/App/MCP/src/Configuration/Interfaces/MCPConfigWarning.Interface.al
create mode 100644 src/System Application/App/MCP/src/Configuration/Pages/MCPConfigWarningList.Page.al
create mode 100644 src/System Application/App/MCP/src/Configuration/Pages/MCPSystemToolList.Page.al
create mode 100644 src/System Application/App/MCP/src/Configuration/Tables/MCPConfigWarning.Table.al
create mode 100644 src/System Application/App/MCP/src/Configuration/Tables/MCPSystemTool.Table.al
diff --git a/src/System Application/App/MCP/Permissions/MCPObjects.PermissionSet.al b/src/System Application/App/MCP/Permissions/MCPObjects.PermissionSet.al
index 3dc10cd3ae..829225add0 100644
--- a/src/System Application/App/MCP/Permissions/MCPObjects.PermissionSet.al
+++ b/src/System Application/App/MCP/Permissions/MCPObjects.PermissionSet.al
@@ -13,12 +13,18 @@ permissionset 8350 "MCP - Objects"
Permissions = codeunit "MCP Config" = X,
codeunit "MCP Config Implementation" = X,
+ codeunit "MCP Config Missing Object" = X,
+ codeunit "MCP Config Missing Parent" = X,
page "MCP API Config Tool Lookup" = X,
page "MCP API Publisher Lookup" = X,
page "MCP Config Card" = X,
page "MCP Config List" = X,
page "MCP Config Tool List" = X,
+ page "MCP Config Warning List" = X,
page "MCP Copy Config" = X,
+ page "MCP System Tool List" = X,
page "MCP Tools By API Group" = X,
- table "MCP API Publisher Group" = X;
+ table "MCP API Publisher Group" = X,
+ table "MCP Config Warning" = X,
+ table "MCP System Tool" = X;
}
\ No newline at end of file
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfig.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfig.Codeunit.al
index f615c9bbcd..b246456ca5 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfig.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfig.Codeunit.al
@@ -98,6 +98,15 @@ codeunit 8350 "MCP Config"
MCPConfigImplementation.EnableDiscoverReadOnlyObjects(ConfigId, Enable);
end;
+ ///
+ /// Validates the specified MCP configuration and displays any warnings found, such as missing objects or missing parent objects.
+ ///
+ /// The SystemId (GUID) of the configuration to validate.
+ procedure ValidateConfiguration(ConfigId: Guid)
+ begin
+ MCPConfigImplementation.ValidateConfiguration(ConfigId, false);
+ end;
+
///
/// Creates a new API tool for the specified configuration and API page.
///
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
index 4a748d2855..29a0782187 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
@@ -33,6 +33,8 @@ codeunit 8351 "MCP Config Implementation"
DeletedConfigurationLbl: Label 'Deleted MCP configuration %1', Comment = '%1 - configuration ID', Locked = true;
SettingConfigurationEnableDynamicToolModeLbl: Label 'Setting MCP configuration %1 EnableDynamicToolMode to %2', Comment = '%1 - configuration ID, %2 - enable dynamic tool mode', Locked = true;
SettingConfigurationDiscoverReadOnlyObjectsLbl: Label 'Setting MCP configuration %1 DiscoverReadOnlyObjects to %2', Comment = '%1 - configuration ID, %2 - allow read-only API discovery', Locked = true;
+ InvalidConfigurationWarningLbl: Label 'The configuration is invalid and may not work as expected. Do you want to review warnings before activating?';
+ ConfigValidLbl: Label 'No warnings found. The configuration is valid.';
#region Configurations
internal procedure GetConfigurationIdByName(Name: Text[100]): Guid
@@ -230,6 +232,77 @@ codeunit 8351 "MCP Config Implementation"
begin
exit(MCPConfiguration.Name = '');
end;
+
+ internal procedure IsConfigurationActive(ConfigId: Guid): Boolean
+ var
+ MCPConfiguration: Record "MCP Configuration";
+ begin
+ if MCPConfiguration.GetBySystemId(ConfigId) then
+ exit(MCPConfiguration.Active);
+ exit(false);
+ end;
+
+ internal procedure ValidateConfiguration(ConfigId: Guid; OnActivate: Boolean)
+ var
+ MCPConfigurationTool: Record "MCP Configuration Tool";
+ AllObj: Record AllObj;
+ MCPConfigurationWarning: Record "MCP Config Warning";
+ MCPConfigWarningType: Enum "MCP Config Warning Type";
+ begin
+ // Check for missing objects
+ MCPConfigurationTool.SetRange(ID, ConfigId);
+ if MCPConfigurationTool.FindSet() then
+ repeat
+ AllObj.SetRange("Object Type", AllObj."Object Type"::Page);
+ AllObj.SetRange("Object ID", MCPConfigurationTool."Object ID");
+ if AllObj.IsEmpty() then begin
+ MCPConfigurationWarning."Config Id" := ConfigId;
+ MCPConfigurationWarning."Tool Id" := MCPConfigurationTool.SystemId;
+ MCPConfigurationWarning."Warning Type" := MCPConfigWarningType::"Missing Object";
+ MCPConfigurationWarning.Insert();
+ end;
+ until MCPConfigurationTool.Next() = 0;
+
+ // Check for missing parent objects
+ // TODO: Implement after platform support for parent-child relationships of API pages
+
+ // Raise warning if any issues found
+ if MCPConfigurationWarning.IsEmpty() then begin
+ if not OnActivate then
+ Message(ConfigValidLbl);
+ exit;
+ end;
+
+ if OnActivate then
+ if not Confirm(InvalidConfigurationWarningLbl) then
+ exit;
+
+ Page.Run(Page::"MCP Config Warning List", MCPConfigurationWarning);
+ end;
+
+ internal procedure GetWarningMessage(MCPConfigWarning: Record "MCP Config Warning"): Text
+ var
+ IMCPConfigWarning: Interface "MCP Config Warning";
+ begin
+ IMCPConfigWarning := MCPConfigWarning."Warning Type";
+ exit(IMCPConfigWarning.WarningMessage(MCPConfigWarning));
+ end;
+
+ internal procedure GetRecommendedAction(MCPConfigWarning: Record "MCP Config Warning"): Text
+ var
+ IMCPConfigWarning: Interface "MCP Config Warning";
+ begin
+ IMCPConfigWarning := MCPConfigWarning."Warning Type";
+ exit(IMCPConfigWarning.RecommendedAction(MCPConfigWarning));
+ end;
+
+ internal procedure ApplyRecommendedAction(MCPConfigWarning: Record "MCP Config Warning")
+ var
+ IMCPConfigWarning: Interface "MCP Config Warning";
+ begin
+ IMCPConfigWarning := MCPConfigWarning."Warning Type";
+ IMCPConfigWarning.ApplyRecommendedAction(MCPConfigWarning);
+ end;
#endregion
#region Tools
@@ -493,6 +566,24 @@ codeunit 8351 "MCP Config Implementation"
exit(CopyStr(AllObjWithCaption."Object Name", 1, 100));
exit('');
end;
+
+ internal procedure LoadSystemTools(var MCPSystemTool: Record "MCP System Tool")
+ begin
+ // TODO: Replace after platform API to retrieve system tools is available
+ MCPSystemTool.Reset();
+ MCPSystemTool.DeleteAll();
+
+ InsertSystemTool(MCPSystemTool, 'bc_action_describe', 'Describes a Business Central action, providing details about its parameters and usage.');
+ InsertSystemTool(MCPSystemTool, 'bc_action_invoke', 'Invokes a Business Central action with the specified parameters.');
+ InsertSystemTool(MCPSystemTool, 'bc_action_search', 'Searches for available Business Central actions based on the provided criteria.');
+ end;
+
+ local procedure InsertSystemTool(var MCPSystemTool: Record "MCP System Tool"; ToolName: Text[100]; ToolDescription: Text[250])
+ begin
+ MCPSystemTool."Tool Name" := ToolName;
+ MCPSystemTool."Tool Description" := ToolDescription;
+ MCPSystemTool.Insert();
+ end;
#endregion
#if not CLEAN28
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al
new file mode 100644
index 0000000000..8541755ea6
--- /dev/null
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al
@@ -0,0 +1,36 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace System.MCP;
+
+codeunit 8353 "MCP Config Missing Object" implements "MCP Config Warning"
+{
+ Access = Internal;
+ InherentEntitlements = X;
+ InherentPermissions = X;
+
+ var
+ MCPConfigurationTool: Record "MCP Configuration Tool";
+ MissingObjectWarningLbl: Label '%1 %2 referenced by this configuration no longer exists in the system.', Comment = '%1=Object type, %2=Object Id';
+ MissingObjectFixLbl: Label 'Remove this tool from the configuration.';
+
+ procedure WarningMessage(MCPConfigWarning: Record "MCP Config Warning"): Text
+ begin
+ if MCPConfigurationTool.GetBySystemId(MCPConfigWarning."Tool Id") then
+ exit(StrSubstNo(MissingObjectWarningLbl, MCPConfigurationTool."Object Type", MCPConfigurationTool."Object Id"));
+ end;
+
+ procedure RecommendedAction(MCPConfigWarning: Record "MCP Config Warning"): Text
+ begin
+ exit(MissingObjectFixLbl);
+ end;
+
+ procedure ApplyRecommendedAction(var MCPConfigWarning: Record "MCP Config Warning")
+ begin
+ if MCPConfigurationTool.GetBySystemId(MCPConfigWarning."Tool Id") then
+ MCPConfigurationTool.Delete();
+ MCPConfigWarning.Delete();
+ end;
+}
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
new file mode 100644
index 0000000000..8032e72727
--- /dev/null
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
@@ -0,0 +1,32 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace System.MCP;
+
+codeunit 8354 "MCP Config Missing Parent" implements "MCP Config Warning"
+{
+ Access = Internal;
+ InherentEntitlements = X;
+ InherentPermissions = X;
+
+ var
+ MissingParentWarningLbl: Label 'This API page has a parent page that is not included in the configuration.';
+ MissingParentFixLbl: Label 'Add the parent API pages to the configuration.';
+
+ procedure WarningMessage(MCPConfigWarning: Record "MCP Config Warning"): Text
+ begin
+ exit(MissingParentWarningLbl); // TODO: Enhance message with specific parent details.
+ end;
+
+ procedure RecommendedAction(MCPConfigWarning: Record "MCP Config Warning"): Text
+ begin
+ exit(MissingParentFixLbl);
+ end;
+
+ procedure ApplyRecommendedAction(var MCPConfigWarning: Record "MCP Config Warning")
+ begin
+ // TODO: Implement logic to add the parent API page to the configuration.
+ end;
+}
diff --git a/src/System Application/App/MCP/src/Configuration/Enums/MCPConfigWarningType.Enum.al b/src/System Application/App/MCP/src/Configuration/Enums/MCPConfigWarningType.Enum.al
new file mode 100644
index 0000000000..521fd4ce9b
--- /dev/null
+++ b/src/System Application/App/MCP/src/Configuration/Enums/MCPConfigWarningType.Enum.al
@@ -0,0 +1,32 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace System.MCP;
+
+///
+/// Enum that defines the types of MCP configuration warnings.
+///
+enum 8350 "MCP Config Warning Type" implements "MCP Config Warning"
+{
+ Access = Internal;
+ Extensible = false;
+
+ ///
+ /// Warning type for when an object referenced by a tool is missing.
+ ///
+ value(0; "Missing Object")
+ {
+ Caption = 'Missing Object';
+ Implementation = "MCP Config Warning" = "MCP Config Missing Object";
+ }
+ ///
+ /// Warning type for when a parent object is missing for a child API page.
+ ///
+ value(1; "Missing Parent Object")
+ {
+ Caption = 'Missing Parent Object';
+ Implementation = "MCP Config Warning" = "MCP Config Missing Parent";
+ }
+}
diff --git a/src/System Application/App/MCP/src/Configuration/Interfaces/MCPConfigWarning.Interface.al b/src/System Application/App/MCP/src/Configuration/Interfaces/MCPConfigWarning.Interface.al
new file mode 100644
index 0000000000..fd01a35203
--- /dev/null
+++ b/src/System Application/App/MCP/src/Configuration/Interfaces/MCPConfigWarning.Interface.al
@@ -0,0 +1,15 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace System.MCP;
+
+interface "MCP Config Warning"
+{
+ Access = Internal;
+
+ procedure WarningMessage(MCPConfigWarning: Record "MCP Config Warning"): Text;
+ procedure RecommendedAction(MCPConfigWarning: Record "MCP Config Warning"): Text;
+ procedure ApplyRecommendedAction(var MCPConfigWarning: Record "MCP Config Warning");
+}
diff --git a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
index f20bf177e1..99dc876b82 100644
--- a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
+++ b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
@@ -26,11 +26,11 @@ page 8351 "MCP Config Card"
Caption = 'General';
field(Name; Rec.Name)
{
- Editable = not IsDefault;
+ Editable = not IsDefault and not Rec.Active;
}
field(Description; Rec.Description)
{
- Editable = not IsDefault;
+ Editable = not IsDefault and not Rec.Active;
MultiLine = true;
}
field(Active; Rec.Active)
@@ -40,11 +40,14 @@ page 8351 "MCP Config Card"
trigger OnValidate()
begin
Session.LogMessage('0000QE6', StrSubstNo(SettingConfigurationActiveLbl, Rec.SystemId, Rec.Active), Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::ExtensionPublisher, 'Category', MCPConfigImplementation.GetTelemetryCategory());
+
+ if Rec.Active then
+ MCPConfigImplementation.ValidateConfiguration(Rec.SystemId, true);
end;
}
field(EnableDynamicToolMode; Rec.EnableDynamicToolMode)
{
- Editable = not IsDefault;
+ Editable = not IsDefault and not Rec.Active;
trigger OnValidate()
begin
@@ -52,11 +55,14 @@ page 8351 "MCP Config Card"
if not Rec.EnableDynamicToolMode then
Rec.DiscoverReadOnlyObjects := false;
+
+ GetToolModeDescription();
+ CurrPage.Update();
end;
}
field(DiscoverReadOnlyObjects; Rec.DiscoverReadOnlyObjects)
{
- Editable = not IsDefault and Rec.EnableDynamicToolMode;
+ Editable = not IsDefault and Rec.EnableDynamicToolMode and Rec.Active;
trigger OnValidate()
begin
@@ -65,6 +71,8 @@ page 8351 "MCP Config Card"
}
field(AllowProdChanges; Rec.AllowProdChanges)
{
+ Editable = not IsDefault and not Rec.Active;
+
trigger OnValidate()
begin
if not Rec.AllowProdChanges then
@@ -74,12 +82,33 @@ page 8351 "MCP Config Card"
end;
}
}
+ group(Control2)
+ {
+ Caption = 'Tool Modes';
+ ShowCaption = false;
+
+ field(ToolMode; ToolModeLbl)
+ {
+ ApplicationArea = All;
+ Editable = false;
+ Caption = 'Tool Mode';
+ ShowCaption = false;
+ MultiLine = true;
+ }
+ }
+ part(SystemToolList; "MCP System Tool List")
+ {
+ ApplicationArea = All;
+ Visible = not IsDefault and Rec.EnableDynamicToolMode;
+ Editable = false;
+ }
part(ToolList; "MCP Config Tool List")
{
ApplicationArea = All;
SubPageLink = ID = field(SystemId);
UpdatePropagation = Both;
Visible = not IsDefault;
+ Editable = not Rec.Active;
}
}
}
@@ -100,15 +129,31 @@ page 8351 "MCP Config Card"
end;
}
}
+ area(Processing)
+ {
+ action(Validate)
+ {
+ Caption = 'Validate';
+ ToolTip = 'Validates the MCP configuration to ensure all settings and tools are correctly configured.';
+ Image = ValidateEmailLoggingSetup;
+
+ trigger OnAction()
+ begin
+ MCPConfigImplementation.ValidateConfiguration(Rec.SystemId, false);
+ end;
+ }
+ }
area(Promoted)
{
actionref(Promoted_Copy; Copy) { }
+ actionref(Promoted_Validate; Validate) { }
}
}
trigger OnAfterGetRecord()
begin
IsDefault := MCPConfigImplementation.IsDefaultConfiguration(Rec);
+ GetToolModeDescription();
end;
var
@@ -118,4 +163,12 @@ page 8351 "MCP Config Card"
SettingConfigurationEnableDynamicToolModeLbl: Label 'Setting MCP configuration %1 EnableDynamicToolMode to %2', Comment = '%1 - configuration ID, %2 - enable dynamic tool mode', Locked = true;
SettingConfigurationAllowProdChangesLbl: Label 'Setting MCP configuration %1 AllowProdChanges to %2', Comment = '%1 - configuration ID, %2 - allow production changes', Locked = true;
SettingConfigurationDiscoverReadOnlyObjectsLbl: Label 'Setting MCP configuration %1 DiscoverReadOnlyObjects to %2', Comment = '%1 - configuration ID, %2 - allow read-only API discovery', Locked = true;
+ ToolModeLbl: Text;
+ StaticToolModeLbl: Label 'In Static Tool Mode, objects in the available tools will be directly exposed to clients. You can manage these tools by adding, modifying, or removing them from the configuration.', Locked = true;
+ DynamicToolModeLbl: Label 'In Dynamic Tool Mode, only system tools will be exposed to clients. Objects within the available tools can be discovered, described and invoked dynamically using system tools. You can enable dynamic discovery of any read-only object outside of the available tools using Discover Additional Objects setting.', Locked = true;
+
+ local procedure GetToolModeDescription(): Text
+ begin
+ ToolModeLbl := Rec.EnableDynamicToolMode ? DynamicToolModeLbl : StaticToolModeLbl;
+ end;
}
\ No newline at end of file
diff --git a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigToolList.Page.al b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigToolList.Page.al
index d385bce2df..2ced63473d 100644
--- a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigToolList.Page.al
+++ b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigToolList.Page.al
@@ -5,7 +5,6 @@
namespace System.MCP;
-using System.Environment;
using System.Reflection;
page 8352 "MCP Config Tool List"
@@ -65,19 +64,19 @@ page 8352 "MCP Config Tool List"
field("Allow Read"; Rec."Allow Read") { }
field("Allow Create"; Rec."Allow Create")
{
- Editable = AllowCreateEditable and (IsSandbox or AllowCreateUpdateDeleteTools);
+ Editable = AllowCreateEditable and AllowCreateUpdateDeleteTools;
}
field("Allow Modify"; Rec."Allow Modify")
{
- Editable = AllowModifyEditable and (IsSandbox or AllowCreateUpdateDeleteTools);
+ Editable = AllowModifyEditable and AllowCreateUpdateDeleteTools;
}
field("Allow Delete"; Rec."Allow Delete")
{
- Editable = AllowDeleteEditable and (IsSandbox or AllowCreateUpdateDeleteTools);
+ Editable = AllowDeleteEditable and AllowCreateUpdateDeleteTools;
}
field("Allow Bound Actions"; Rec."Allow Bound Actions")
{
- Editable = IsSandbox or AllowCreateUpdateDeleteTools;
+ Editable = AllowCreateUpdateDeleteTools;
}
}
}
@@ -92,6 +91,7 @@ page 8352 "MCP Config Tool List"
Caption = 'Add Tools by API Group';
Image = NewResourceGroup;
ToolTip = 'Adds tools to the configuration by API publisher and group.';
+ Enabled = not IsConfigActive;
trigger OnAction()
begin
@@ -104,6 +104,7 @@ page 8352 "MCP Config Tool List"
Caption = 'Add All Standard APIs as Tools';
Image = ResourceGroup;
ToolTip = 'Adds tools for all standard API v2.0 to the configuration.';
+ Enabled = not IsConfigActive;
trigger OnAction()
begin
@@ -127,11 +128,9 @@ page 8352 "MCP Config Tool List"
end;
trigger OnOpenPage()
- var
- EnvironmentInformation: Codeunit "Environment Information";
begin
- IsSandbox := EnvironmentInformation.IsSandbox();
GetAllowCreateUpdateDeleteTools();
+ IsConfigActive := MCPConfigImplementation.IsConfigurationActive(Rec.ID);
end;
trigger OnNewRecord(BelowxRec: Boolean)
@@ -142,11 +141,11 @@ page 8352 "MCP Config Tool List"
var
MCPConfig: Codeunit "MCP Config";
MCPConfigImplementation: Codeunit "MCP Config Implementation";
- IsSandbox: Boolean;
AllowCreateEditable: Boolean;
AllowModifyEditable: Boolean;
AllowDeleteEditable: Boolean;
AllowCreateUpdateDeleteTools: Boolean;
+ IsConfigActive: Boolean;
local procedure SetPermissions()
var
diff --git a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigWarningList.Page.al b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigWarningList.Page.al
new file mode 100644
index 0000000000..58fad927e9
--- /dev/null
+++ b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigWarningList.Page.al
@@ -0,0 +1,68 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace System.MCP;
+
+page 8358 "MCP Config Warning List"
+{
+ ApplicationArea = All;
+ PageType = List;
+ SourceTable = "MCP Config Warning";
+ SourceTableTemporary = true;
+ Caption = 'MCP Configuration Warnings';
+ Extensible = false;
+ InherentEntitlements = X;
+ InherentPermissions = X;
+ Editable = false;
+ InsertAllowed = false;
+ ModifyAllowed = false;
+ DeleteAllowed = false;
+
+ layout
+ {
+ area(Content)
+ {
+ repeater(Control1)
+ {
+ field("Warning Message"; MCPConfigImplementation.GetWarningMessage(Rec))
+ {
+ Caption = 'Warning Message';
+ ToolTip = 'Specifies the warning message.';
+ }
+ field("Recommended Action"; MCPConfigImplementation.GetRecommendedAction(Rec))
+ {
+ Caption = 'Recommended Action';
+ ToolTip = 'Specifies the recommended action for the warning.';
+ }
+ }
+ }
+ }
+
+ actions
+ {
+ area(Processing)
+ {
+ action(Fix)
+ {
+ ApplicationArea = All;
+ Caption = 'Apply Recommended Action';
+ ToolTip = 'Applies the recommended action for the selected warning.';
+ Image = ApprovalSetup;
+
+ trigger OnAction()
+ begin
+ MCPConfigImplementation.ApplyRecommendedAction(Rec);
+ end;
+ }
+ }
+ area(Promoted)
+ {
+ actionref(Promoted_Fix; Fix) { }
+ }
+ }
+
+ var
+ MCPConfigImplementation: Codeunit "MCP Config Implementation";
+}
diff --git a/src/System Application/App/MCP/src/Configuration/Pages/MCPSystemToolList.Page.al b/src/System Application/App/MCP/src/Configuration/Pages/MCPSystemToolList.Page.al
new file mode 100644
index 0000000000..ac50326ab8
--- /dev/null
+++ b/src/System Application/App/MCP/src/Configuration/Pages/MCPSystemToolList.Page.al
@@ -0,0 +1,53 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace System.MCP;
+
+page 8357 "MCP System Tool List"
+{
+ Caption = 'System Tools';
+ ApplicationArea = All;
+ PageType = ListPart;
+ SourceTable = "MCP System Tool";
+ SourceTableTemporary = true;
+ Editable = false;
+ InsertAllowed = false;
+ ModifyAllowed = false;
+ DeleteAllowed = false;
+ Extensible = false;
+ InherentEntitlements = X;
+ InherentPermissions = X;
+
+ layout
+ {
+ area(Content)
+ {
+ repeater(Control1)
+ {
+ ShowCaption = false;
+ field("Tool Name"; Rec."Tool Name") { }
+ field("Tool Description"; Rec."Tool Description") { }
+ }
+ }
+ }
+
+ trigger OnOpenPage()
+ begin
+ LoadSystemTools();
+ end;
+
+ var
+ MCPConfigImplementation: Codeunit "MCP Config Implementation";
+ IsLoaded: Boolean;
+
+ local procedure LoadSystemTools()
+ begin
+ if IsLoaded then
+ exit;
+
+ IsLoaded := true;
+ MCPConfigImplementation.LoadSystemTools(Rec);
+ end;
+}
\ No newline at end of file
diff --git a/src/System Application/App/MCP/src/Configuration/Tables/MCPConfigWarning.Table.al b/src/System Application/App/MCP/src/Configuration/Tables/MCPConfigWarning.Table.al
new file mode 100644
index 0000000000..8982f309c2
--- /dev/null
+++ b/src/System Application/App/MCP/src/Configuration/Tables/MCPConfigWarning.Table.al
@@ -0,0 +1,49 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace System.MCP;
+
+table 8352 "MCP Config Warning"
+{
+ Access = Internal;
+ DataClassification = SystemMetadata;
+ TableType = Temporary;
+ Caption = 'MCP Configuration Warning';
+
+ fields
+ {
+ field(1; "Entry No."; Integer)
+ {
+ Caption = 'Entry No.';
+ AutoIncrement = true;
+ }
+ field(2; "Config Id"; Guid)
+ {
+ Caption = 'Config Id';
+ ToolTip = 'Specifies the ID of the MCP configuration.';
+ }
+ field(3; "Tool Id"; Guid)
+ {
+ Caption = 'Tool Id';
+ ToolTip = 'Specifies the ID of the tool that has a warning.';
+ }
+ field(4; "Warning Type"; Enum "MCP Config Warning Type")
+ {
+ Caption = 'Warning Type';
+ ToolTip = 'Specifies the type of warning.';
+ }
+ }
+
+ keys
+ {
+ key(Key1; "Entry No.")
+ {
+ Clustered = true;
+ }
+ key(Key2; "Config Id", "Tool Id")
+ {
+ }
+ }
+}
diff --git a/src/System Application/App/MCP/src/Configuration/Tables/MCPSystemTool.Table.al b/src/System Application/App/MCP/src/Configuration/Tables/MCPSystemTool.Table.al
new file mode 100644
index 0000000000..0dbbec0af8
--- /dev/null
+++ b/src/System Application/App/MCP/src/Configuration/Tables/MCPSystemTool.Table.al
@@ -0,0 +1,39 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace System.MCP;
+
+table 8351 "MCP System Tool"
+{
+ Access = Internal;
+ DataClassification = SystemMetadata;
+ TableType = Temporary;
+
+ fields
+ {
+ field(1; "Tool Name"; Text[100])
+ {
+ Caption = 'Tool Name';
+ ToolTip = 'Specifies the name of the system tool.';
+ }
+ field(2; "Tool Description"; Text[250])
+ {
+ Caption = 'Tool Description';
+ ToolTip = 'Specifies the description of the system tool.';
+ }
+ }
+
+ keys
+ {
+ key(Key1; "Tool Name")
+ {
+ Clustered = true;
+ }
+ }
+
+ fieldgroups
+ {
+ }
+}
\ No newline at end of file
From 4cdb287b6f954b76d18a44f73a779c7134d825a4 Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Tue, 16 Dec 2025 10:31:05 +0100
Subject: [PATCH 02/17] Configuration validation and UX improvements
---
.../src/Configuration/Enums/MCPConfigWarningType.Enum.al | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/src/System Application/App/MCP/src/Configuration/Enums/MCPConfigWarningType.Enum.al b/src/System Application/App/MCP/src/Configuration/Enums/MCPConfigWarningType.Enum.al
index 521fd4ce9b..d1cd50cd55 100644
--- a/src/System Application/App/MCP/src/Configuration/Enums/MCPConfigWarningType.Enum.al
+++ b/src/System Application/App/MCP/src/Configuration/Enums/MCPConfigWarningType.Enum.al
@@ -5,25 +5,16 @@
namespace System.MCP;
-///
-/// Enum that defines the types of MCP configuration warnings.
-///
enum 8350 "MCP Config Warning Type" implements "MCP Config Warning"
{
Access = Internal;
Extensible = false;
- ///
- /// Warning type for when an object referenced by a tool is missing.
- ///
value(0; "Missing Object")
{
Caption = 'Missing Object';
Implementation = "MCP Config Warning" = "MCP Config Missing Object";
}
- ///
- /// Warning type for when a parent object is missing for a child API page.
- ///
value(1; "Missing Parent Object")
{
Caption = 'Missing Parent Object';
From c24e47f6e56e1da9a726d5cc4b7dc05f2236fb20 Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Tue, 16 Dec 2025 17:10:42 +0100
Subject: [PATCH 03/17] Configuration validation and UX improvements
---
.../Codeunits/MCPConfig.Codeunit.al | 19 +++++--
.../MCPConfigImplementation.Codeunit.al | 55 ++++++++++++++-----
.../Enums/MCPConfigWarningType.Enum.al | 2 +-
.../Configuration/Pages/MCPConfigCard.Page.al | 9 ++-
.../Pages/MCPConfigWarningList.Page.al | 7 ++-
.../Tables/MCPConfigWarning.Table.al | 4 +-
.../Test/MCP/src/MCPConfigTest.Codeunit.al | 54 ++++++++++++++++++
7 files changed, 124 insertions(+), 26 deletions(-)
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfig.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfig.Codeunit.al
index b246456ca5..b2e613ca66 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfig.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfig.Codeunit.al
@@ -99,12 +99,23 @@ codeunit 8350 "MCP Config"
end;
///
- /// Validates the specified MCP configuration and displays any warnings found, such as missing objects or missing parent objects.
+ /// Finds warnings for the specified MCP configuration, such as missing objects or missing parent objects.
///
- /// The SystemId (GUID) of the configuration to validate.
- procedure ValidateConfiguration(ConfigId: Guid)
+ /// The SystemId (GUID) of the configuration to find warnings for.
+ /// A temporary record variable to hold the found warnings.
+ /// True if any warnings were found; otherwise, false.
+ procedure FindWarningsForConfiguration(ConfigId: Guid; var MCPConfigWarning: Record "MCP Config Warning"): Boolean
begin
- MCPConfigImplementation.ValidateConfiguration(ConfigId, false);
+ exit(MCPConfigImplementation.FindWarningsForConfiguration(ConfigId, MCPConfigWarning));
+ end;
+
+ ///
+ /// Applies the recommended action for the specified warning.
+ ///
+ /// The warning record to apply the recommended action for.
+ procedure ApplyRecommendedAction(var MCPConfigWarning: Record "MCP Config Warning")
+ begin
+ MCPConfigImplementation.ApplyRecommendedAction(MCPConfigWarning);
end;
///
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
index 29a0782187..7b34eee788 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
@@ -242,13 +242,37 @@ codeunit 8351 "MCP Config Implementation"
exit(false);
end;
- internal procedure ValidateConfiguration(ConfigId: Guid; OnActivate: Boolean)
+ internal procedure ValidateConfiguration(var MCPConfiguration: Record "MCP Configuration"; OnActivate: Boolean)
+ var
+ MCPConfigurationWarning: Record "MCP Config Warning";
+ begin
+ // Raise warning if any issues found
+ if not FindWarningsForConfiguration(MCPConfiguration.SystemId, MCPConfigurationWarning) then begin
+ if not OnActivate then
+ Message(ConfigValidLbl);
+ exit;
+ end;
+
+ if OnActivate then
+ if not Confirm(InvalidConfigurationWarningLbl) then
+ exit;
+
+ MCPConfiguration.Active := false;
+ Page.Run(Page::"MCP Config Warning List", MCPConfigurationWarning);
+ end;
+
+ internal procedure FindWarningsForConfiguration(ConfigId: Guid; var MCPConfigurationWarning: Record "MCP Config Warning"): Boolean
var
MCPConfigurationTool: Record "MCP Configuration Tool";
AllObj: Record AllObj;
- MCPConfigurationWarning: Record "MCP Config Warning";
MCPConfigWarningType: Enum "MCP Config Warning Type";
+ EntryNo: Integer;
begin
+ if MCPConfigurationWarning.FindLast() then
+ EntryNo := MCPConfigurationWarning."Entry No." + 1
+ else
+ EntryNo := 1;
+
// Check for missing objects
MCPConfigurationTool.SetRange(ID, ConfigId);
if MCPConfigurationTool.FindSet() then
@@ -256,28 +280,19 @@ codeunit 8351 "MCP Config Implementation"
AllObj.SetRange("Object Type", AllObj."Object Type"::Page);
AllObj.SetRange("Object ID", MCPConfigurationTool."Object ID");
if AllObj.IsEmpty() then begin
+ MCPConfigurationWarning."Entry No." := EntryNo;
MCPConfigurationWarning."Config Id" := ConfigId;
MCPConfigurationWarning."Tool Id" := MCPConfigurationTool.SystemId;
MCPConfigurationWarning."Warning Type" := MCPConfigWarningType::"Missing Object";
MCPConfigurationWarning.Insert();
+ EntryNo += 1;
end;
until MCPConfigurationTool.Next() = 0;
// Check for missing parent objects
// TODO: Implement after platform support for parent-child relationships of API pages
- // Raise warning if any issues found
- if MCPConfigurationWarning.IsEmpty() then begin
- if not OnActivate then
- Message(ConfigValidLbl);
- exit;
- end;
-
- if OnActivate then
- if not Confirm(InvalidConfigurationWarningLbl) then
- exit;
-
- Page.Run(Page::"MCP Config Warning List", MCPConfigurationWarning);
+ exit(not MCPConfigurationWarning.IsEmpty());
end;
internal procedure GetWarningMessage(MCPConfigWarning: Record "MCP Config Warning"): Text
@@ -296,7 +311,17 @@ codeunit 8351 "MCP Config Implementation"
exit(IMCPConfigWarning.RecommendedAction(MCPConfigWarning));
end;
- internal procedure ApplyRecommendedAction(MCPConfigWarning: Record "MCP Config Warning")
+ internal procedure ApplyRecommendedActions(var MCPConfigWarning: Record "MCP Config Warning")
+ begin
+ if not MCPConfigWarning.FindSet() then
+ exit;
+
+ repeat
+ ApplyRecommendedAction(MCPConfigWarning);
+ until MCPConfigWarning.Next() = 0;
+ end;
+
+ internal procedure ApplyRecommendedAction(var MCPConfigWarning: Record "MCP Config Warning")
var
IMCPConfigWarning: Interface "MCP Config Warning";
begin
diff --git a/src/System Application/App/MCP/src/Configuration/Enums/MCPConfigWarningType.Enum.al b/src/System Application/App/MCP/src/Configuration/Enums/MCPConfigWarningType.Enum.al
index d1cd50cd55..cdb4db31e2 100644
--- a/src/System Application/App/MCP/src/Configuration/Enums/MCPConfigWarningType.Enum.al
+++ b/src/System Application/App/MCP/src/Configuration/Enums/MCPConfigWarningType.Enum.al
@@ -7,7 +7,7 @@ namespace System.MCP;
enum 8350 "MCP Config Warning Type" implements "MCP Config Warning"
{
- Access = Internal;
+ Access = Public;
Extensible = false;
value(0; "Missing Object")
diff --git a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
index 99dc876b82..903d953786 100644
--- a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
+++ b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
@@ -42,7 +42,7 @@ page 8351 "MCP Config Card"
Session.LogMessage('0000QE6', StrSubstNo(SettingConfigurationActiveLbl, Rec.SystemId, Rec.Active), Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::ExtensionPublisher, 'Category', MCPConfigImplementation.GetTelemetryCategory());
if Rec.Active then
- MCPConfigImplementation.ValidateConfiguration(Rec.SystemId, true);
+ MCPConfigImplementation.ValidateConfiguration(Rec, true);
end;
}
field(EnableDynamicToolMode; Rec.EnableDynamicToolMode)
@@ -139,7 +139,7 @@ page 8351 "MCP Config Card"
trigger OnAction()
begin
- MCPConfigImplementation.ValidateConfiguration(Rec.SystemId, false);
+ MCPConfigImplementation.ValidateConfiguration(Rec, false);
end;
}
}
@@ -156,6 +156,11 @@ page 8351 "MCP Config Card"
GetToolModeDescription();
end;
+ trigger OnNewRecord(BelowxRec: Boolean)
+ begin
+ ToolModeLbl := StaticToolModeLbl;
+ end;
+
var
MCPConfigImplementation: Codeunit "MCP Config Implementation";
IsDefault: Boolean;
diff --git a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigWarningList.Page.al b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigWarningList.Page.al
index 58fad927e9..08221b1300 100644
--- a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigWarningList.Page.al
+++ b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigWarningList.Page.al
@@ -48,12 +48,15 @@ page 8358 "MCP Config Warning List"
{
ApplicationArea = All;
Caption = 'Apply Recommended Action';
- ToolTip = 'Applies the recommended action for the selected warning.';
+ ToolTip = 'Applies the recommended action for the selected warnings.';
Image = ApprovalSetup;
trigger OnAction()
begin
- MCPConfigImplementation.ApplyRecommendedAction(Rec);
+ SetSelectionFilter(Rec);
+ MCPConfigImplementation.ApplyRecommendedActions(Rec);
+ Rec.Reset();
+ Rec.FindSet();
end;
}
}
diff --git a/src/System Application/App/MCP/src/Configuration/Tables/MCPConfigWarning.Table.al b/src/System Application/App/MCP/src/Configuration/Tables/MCPConfigWarning.Table.al
index 8982f309c2..0ec7176558 100644
--- a/src/System Application/App/MCP/src/Configuration/Tables/MCPConfigWarning.Table.al
+++ b/src/System Application/App/MCP/src/Configuration/Tables/MCPConfigWarning.Table.al
@@ -7,7 +7,8 @@ namespace System.MCP;
table 8352 "MCP Config Warning"
{
- Access = Internal;
+ Access = Public;
+ Extensible = false;
DataClassification = SystemMetadata;
TableType = Temporary;
Caption = 'MCP Configuration Warning';
@@ -17,7 +18,6 @@ table 8352 "MCP Config Warning"
field(1; "Entry No."; Integer)
{
Caption = 'Entry No.';
- AutoIncrement = true;
}
field(2; "Config Id"; Guid)
{
diff --git a/src/System Application/Test/MCP/src/MCPConfigTest.Codeunit.al b/src/System Application/Test/MCP/src/MCPConfigTest.Codeunit.al
index dd7f0b16d0..afc6be67ed 100644
--- a/src/System Application/Test/MCP/src/MCPConfigTest.Codeunit.al
+++ b/src/System Application/Test/MCP/src/MCPConfigTest.Codeunit.al
@@ -578,6 +578,60 @@ codeunit 130130 "MCP Config Test"
Assert.IsFalse(MCPConfigurationTool."Allow Bound Actions", 'Allow Bound Actions is not false');
end;
+ [Test]
+ procedure TestFindWarningsForConfiguration()
+ var
+ MCPConfigurationTool: Record "MCP Configuration Tool";
+ MCPConfigWarning: Record "MCP Config Warning";
+ ConfigId: Guid;
+ ToolId: Guid;
+ begin
+ // [GIVEN] Configuration and tool with non-existing object is created
+ ConfigId := CreateMCPConfig(false, false, true, false);
+ ToolId := CreateMCPConfigTool(ConfigId);
+ MCPConfigurationTool.GetBySystemId(ToolId);
+ MCPConfigurationTool.Rename(MCPConfigurationTool.ID, MCPConfigurationTool."Object Type", -1); // non-existing object
+ Commit();
+
+ // [WHEN] Find warnings for configuration is called
+ MCPConfig.FindWarningsForConfiguration(ConfigId, MCPConfigWarning);
+
+ // [THEN] Warning is created for the tool with non-existing object
+ Assert.RecordCount(MCPConfigWarning, 1);
+ MCPConfigWarning.FindFirst();
+ Assert.AreEqual(MCPConfigWarning."Warning Type"::"Missing Object", MCPConfigWarning."Warning Type", 'Warning Type mismatch');
+ Assert.AreEqual(ToolId, MCPConfigWarning."Tool Id", 'Configuration Tool Id mismatch');
+ end;
+
+ [Test]
+ procedure TestApplyRecommendedAction()
+ var
+ MCPConfigurationTool: Record "MCP Configuration Tool";
+ MCPConfigWarning: Record "MCP Config Warning";
+ ConfigId: Guid;
+ ToolId: Guid;
+ begin
+ // [GIVEN] Configuration and tool with non-existing object is created
+ ConfigId := CreateMCPConfig(false, false, true, false);
+ ToolId := CreateMCPConfigTool(ConfigId);
+ MCPConfigurationTool.GetBySystemId(ToolId);
+ MCPConfigurationTool.Rename(MCPConfigurationTool.ID, MCPConfigurationTool."Object Type", -1); // non-existing object
+ Commit();
+
+ // [WHEN] Find warnings for configuration is called
+ MCPConfig.FindWarningsForConfiguration(ConfigId, MCPConfigWarning);
+
+ // [WHEN] Apply recommended action is called
+ MCPConfig.ApplyRecommendedAction(MCPConfigWarning);
+
+ // [THEN] Warning is resolved after applying the recommended action
+ Assert.RecordCount(MCPConfigWarning, 0);
+
+ // [THEN] Configuration tool is deleted
+ MCPConfigurationTool.SetRange(SystemId, ToolId);
+ Assert.RecordIsEmpty(MCPConfigurationTool);
+ end;
+
local procedure CreateMCPConfig(Active: Boolean; DynamicToolMode: Boolean; AllowCreateUpdateDeleteTools: Boolean; DiscoverReadOnlyObjects: Boolean): Guid
var
MCPConfiguration: Record "MCP Configuration";
From 4e7b464cce9166fc8974d97989e4f71e6f1f4838 Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Wed, 17 Dec 2025 21:31:50 +0100
Subject: [PATCH 04/17] Configuration validation and UX improvements
---
.../MCPConfigImplementation.Codeunit.al | 28 ++++++-------------
.../MCPConfigMissingObject.Codeunit.al | 21 ++++++++++++++
.../MCPConfigMissingParent.Codeunit.al | 6 ++++
.../Interfaces/MCPConfigWarning.Interface.al | 1 +
.../Pages/MCPConfigWarningList.Page.al | 3 +-
5 files changed, 38 insertions(+), 21 deletions(-)
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
index 7b34eee788..4ff0b6457a 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
@@ -263,9 +263,10 @@ codeunit 8351 "MCP Config Implementation"
internal procedure FindWarningsForConfiguration(ConfigId: Guid; var MCPConfigurationWarning: Record "MCP Config Warning"): Boolean
var
- MCPConfigurationTool: Record "MCP Configuration Tool";
- AllObj: Record AllObj;
+ IMCPConfigWarning: Interface "MCP Config Warning";
MCPConfigWarningType: Enum "MCP Config Warning Type";
+ WarningImplementations: List of [Integer];
+ WarningImplementation: Integer;
EntryNo: Integer;
begin
if MCPConfigurationWarning.FindLast() then
@@ -273,24 +274,11 @@ codeunit 8351 "MCP Config Implementation"
else
EntryNo := 1;
- // Check for missing objects
- MCPConfigurationTool.SetRange(ID, ConfigId);
- if MCPConfigurationTool.FindSet() then
- repeat
- AllObj.SetRange("Object Type", AllObj."Object Type"::Page);
- AllObj.SetRange("Object ID", MCPConfigurationTool."Object ID");
- if AllObj.IsEmpty() then begin
- MCPConfigurationWarning."Entry No." := EntryNo;
- MCPConfigurationWarning."Config Id" := ConfigId;
- MCPConfigurationWarning."Tool Id" := MCPConfigurationTool.SystemId;
- MCPConfigurationWarning."Warning Type" := MCPConfigWarningType::"Missing Object";
- MCPConfigurationWarning.Insert();
- EntryNo += 1;
- end;
- until MCPConfigurationTool.Next() = 0;
-
- // Check for missing parent objects
- // TODO: Implement after platform support for parent-child relationships of API pages
+ WarningImplementations := MCPConfigWarningType.Ordinals();
+ foreach WarningImplementation in WarningImplementations do begin
+ IMCPConfigWarning := "MCP Config Warning Type".FromInteger(WarningImplementation);
+ IMCPConfigWarning.CheckForWarnings(ConfigId, MCPConfigurationWarning, EntryNo);
+ end;
exit(not MCPConfigurationWarning.IsEmpty());
end;
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al
index 8541755ea6..c14c41157c 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al
@@ -4,6 +4,7 @@
// ------------------------------------------------------------------------------------------------
namespace System.MCP;
+using System.Reflection;
codeunit 8353 "MCP Config Missing Object" implements "MCP Config Warning"
{
@@ -16,6 +17,26 @@ codeunit 8353 "MCP Config Missing Object" implements "MCP Config Warning"
MissingObjectWarningLbl: Label '%1 %2 referenced by this configuration no longer exists in the system.', Comment = '%1=Object type, %2=Object Id';
MissingObjectFixLbl: Label 'Remove this tool from the configuration.';
+ procedure CheckForWarnings(ConfigId: Guid; var MCPConfigWarning: Record "MCP Config Warning"; var EntryNo: Integer)
+ var
+ AllObj: Record AllObj;
+ begin
+ MCPConfigurationTool.SetRange(ID, ConfigId);
+ if MCPConfigurationTool.FindSet() then
+ repeat
+ AllObj.SetRange("Object Type", AllObj."Object Type"::Page);
+ AllObj.SetRange("Object ID", MCPConfigurationTool."Object ID");
+ if AllObj.IsEmpty() then begin
+ MCPConfigWarning."Entry No." := EntryNo;
+ MCPConfigWarning."Config Id" := ConfigId;
+ MCPConfigWarning."Tool Id" := MCPConfigurationTool.SystemId;
+ MCPConfigWarning."Warning Type" := MCPConfigWarning."Warning Type"::"Missing Object";
+ MCPConfigWarning.Insert();
+ EntryNo += 1;
+ end;
+ until MCPConfigurationTool.Next() = 0;
+ end;
+
procedure WarningMessage(MCPConfigWarning: Record "MCP Config Warning"): Text
begin
if MCPConfigurationTool.GetBySystemId(MCPConfigWarning."Tool Id") then
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
index 8032e72727..f44b0ad45f 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
@@ -15,6 +15,12 @@ codeunit 8354 "MCP Config Missing Parent" implements "MCP Config Warning"
MissingParentWarningLbl: Label 'This API page has a parent page that is not included in the configuration.';
MissingParentFixLbl: Label 'Add the parent API pages to the configuration.';
+ procedure CheckForWarnings(ConfigId: Guid; var MCPConfigWarning: Record "MCP Config Warning"; var EntryNo: Integer)
+ begin
+ EntryNo += 0;
+ // TODO: Implement after platform support for parent-child relationships of API pages
+ end;
+
procedure WarningMessage(MCPConfigWarning: Record "MCP Config Warning"): Text
begin
exit(MissingParentWarningLbl); // TODO: Enhance message with specific parent details.
diff --git a/src/System Application/App/MCP/src/Configuration/Interfaces/MCPConfigWarning.Interface.al b/src/System Application/App/MCP/src/Configuration/Interfaces/MCPConfigWarning.Interface.al
index fd01a35203..72e8c78dc7 100644
--- a/src/System Application/App/MCP/src/Configuration/Interfaces/MCPConfigWarning.Interface.al
+++ b/src/System Application/App/MCP/src/Configuration/Interfaces/MCPConfigWarning.Interface.al
@@ -9,6 +9,7 @@ interface "MCP Config Warning"
{
Access = Internal;
+ procedure CheckForWarnings(ConfigId: Guid; var MCPConfigWarning: Record "MCP Config Warning"; var EntryNo: Integer);
procedure WarningMessage(MCPConfigWarning: Record "MCP Config Warning"): Text;
procedure RecommendedAction(MCPConfigWarning: Record "MCP Config Warning"): Text;
procedure ApplyRecommendedAction(var MCPConfigWarning: Record "MCP Config Warning");
diff --git a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigWarningList.Page.al b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigWarningList.Page.al
index 08221b1300..e8a8397776 100644
--- a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigWarningList.Page.al
+++ b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigWarningList.Page.al
@@ -56,7 +56,8 @@ page 8358 "MCP Config Warning List"
SetSelectionFilter(Rec);
MCPConfigImplementation.ApplyRecommendedActions(Rec);
Rec.Reset();
- Rec.FindSet();
+ if not Rec.IsEmpty() then
+ Rec.FindSet();
end;
}
}
From 19d00c811e933534efbadc603d1ce43cc33db9c1 Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Thu, 18 Dec 2025 14:49:15 +0100
Subject: [PATCH 05/17] Configuration validation and UX improvements
---
.../App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
index 903d953786..7b2a93c201 100644
--- a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
+++ b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
@@ -15,7 +15,7 @@ page 8351 "MCP Config Card"
InherentEntitlements = X;
InherentPermissions = X;
AboutTitle = 'About model context protocol (MCP) server configuration';
- AboutText = 'Manage how MCP configurations are set up. Specify which APIs are available as tools, control data access permissions, and enable dynamic discovery of tools. You can also duplicate existing configurations to quickly create new setups.';
+ AboutText = 'Manage how MCP configurations are set up. Specify which APIs are available as tools, control data access permissions, and enable dynamic discovery of tools. You can also duplicate existing configurations to quickly create new setups. Configurations are read-only when activated to ensure stability.';
layout
{
From a1d955b5a40d25aa728ca67e5211eb6caec27c73 Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Tue, 23 Dec 2025 09:24:50 +0100
Subject: [PATCH 06/17] Apply suggestions from code review
---
.../Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al
index c14c41157c..124bad3fa9 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al
@@ -4,6 +4,7 @@
// ------------------------------------------------------------------------------------------------
namespace System.MCP;
+
using System.Reflection;
codeunit 8353 "MCP Config Missing Object" implements "MCP Config Warning"
From 5b88e6cc1fff6e323066d2e727046cdd3396622d Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Wed, 7 Jan 2026 13:22:23 +0100
Subject: [PATCH 07/17] Update
---
.../MCPConfigImplementation.Codeunit.al | 22 ++++-
.../MCPConfigMissingParent.Codeunit.al | 86 +++++++++++++++++--
.../Tables/MCPConfigWarning.Table.al | 5 ++
3 files changed, 104 insertions(+), 9 deletions(-)
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
index 4ff0b6457a..44cc613729 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
@@ -581,14 +581,28 @@ codeunit 8351 "MCP Config Implementation"
end;
internal procedure LoadSystemTools(var MCPSystemTool: Record "MCP System Tool")
+ var
+ // MCPUtilities: Codeunit "MCP Utilities";
+ SystemTools: Dictionary of [Text, Text];
+ ToolName: Text;
begin
- // TODO: Replace after platform API to retrieve system tools is available
MCPSystemTool.Reset();
MCPSystemTool.DeleteAll();
- InsertSystemTool(MCPSystemTool, 'bc_action_describe', 'Describes a Business Central action, providing details about its parameters and usage.');
- InsertSystemTool(MCPSystemTool, 'bc_action_invoke', 'Invokes a Business Central action with the specified parameters.');
- InsertSystemTool(MCPSystemTool, 'bc_action_search', 'Searches for available Business Central actions based on the provided criteria.');
+ // SystemTools := MCPUtilities.GetSystemToolsInDynamicMode(); TODO
+ SystemTools := GetSystemTools();
+ foreach ToolName in SystemTools.Keys() do
+ InsertSystemTool(MCPSystemTool, CopyStr(ToolName, 1, MaxStrLen(MCPSystemTool."Tool Name")), CopyStr(SystemTools.Get(ToolName), 1, MaxStrLen(MCPSystemTool."Tool Description")));
+ end;
+
+ local procedure GetSystemTools(): Dictionary of [Text, Text]
+ var
+ SystemTools: Dictionary of [Text, Text];
+ begin
+ SystemTools.Add('bc_action_search', 'Searches for available Business Central actions based on the provided criteria.');
+ SystemTools.Add('bc_action_describe', 'Describes a Business Central action, providing details about its parameters and usage.');
+ SystemTools.Add('bc_action_invoke', 'Invokes a Business Central action with the specified parameters.');
+ exit(SystemTools);
end;
local procedure InsertSystemTool(var MCPSystemTool: Record "MCP System Tool"; ToolName: Text[100]; ToolDescription: Text[250])
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
index f44b0ad45f..55705ecd13 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
@@ -5,6 +5,8 @@
namespace System.MCP;
+using System.Reflection;
+
codeunit 8354 "MCP Config Missing Parent" implements "MCP Config Warning"
{
Access = Internal;
@@ -12,18 +14,66 @@ codeunit 8354 "MCP Config Missing Parent" implements "MCP Config Warning"
InherentPermissions = X;
var
- MissingParentWarningLbl: Label 'This API page has a parent page that is not included in the configuration.';
+ MissingParentWarningLbl: Label 'This API page is missing parent page(s): %1', Comment = '%1 = comma-separated list of missing parent page IDs';
MissingParentFixLbl: Label 'Add the parent API pages to the configuration.';
procedure CheckForWarnings(ConfigId: Guid; var MCPConfigWarning: Record "MCP Config Warning"; var EntryNo: Integer)
+ var
+ MCPConfigurationTool: Record "MCP Configuration Tool";
+ PageMetadata: Record "Page Metadata";
+ // MCPUtilities: Codeunit "MCP Utilities";
+ PageIdVersions: Dictionary of [Integer, Text];
+ ParentMCPTools: Dictionary of [Integer, List of [Integer]];
+ ParentPageIds: List of [Integer];
+ MissingParentIds: List of [Integer];
+ PageId: Integer;
+ ParentPageId: Integer;
+ MissingParentsText: Text;
begin
- EntryNo += 0;
- // TODO: Implement after platform support for parent-child relationships of API pages
+ // Build dictionary of page IDs and API versions from configuration tools
+ MCPConfigurationTool.SetRange(ID, ConfigId);
+ MCPConfigurationTool.SetRange("Object Type", MCPConfigurationTool."Object Type"::Page);
+ if not MCPConfigurationTool.FindSet() then
+ exit;
+
+ repeat
+ if PageMetadata.Get(MCPConfigurationTool."Object ID") then
+ PageIdVersions.Add(MCPConfigurationTool."Object ID", PageMetadata.APIVersion);
+ until MCPConfigurationTool.Next() = 0;
+
+ // Get parent mappings from platform
+ // ParentMCPTools := MCPUtilities.GetParentMCPTools(PageIdVersions); TODO
+
+ // Check each page with parents for missing parent tools
+ foreach PageId in ParentMCPTools.Keys() do begin
+ ParentPageIds := ParentMCPTools.Get(PageId);
+ Clear(MissingParentIds);
+
+ // Check if each parent exists in the configuration
+ foreach ParentPageId in ParentPageIds do
+ if not PageIdVersions.ContainsKey(ParentPageId) then
+ MissingParentIds.Add(ParentPageId);
+
+ // Create warning if there are missing parents
+ if MissingParentIds.Count() > 0 then begin
+ // Get the tool record to retrieve its SystemId
+ MCPConfigurationTool.Get(ConfigId, MCPConfigurationTool."Object Type"::Page, PageId);
+
+ MissingParentsText := FormatPageIdList(MissingParentIds);
+ MCPConfigWarning."Entry No." := EntryNo;
+ MCPConfigWarning."Config Id" := ConfigId;
+ MCPConfigWarning."Tool Id" := MCPConfigurationTool.SystemId;
+ MCPConfigWarning."Warning Type" := MCPConfigWarning."Warning Type"::"Missing Parent Object";
+ MCPConfigWarning."Additional Info" := CopyStr(MissingParentsText, 1, MaxStrLen(MCPConfigWarning."Additional Info"));
+ MCPConfigWarning.Insert();
+ EntryNo += 1;
+ end;
+ end;
end;
procedure WarningMessage(MCPConfigWarning: Record "MCP Config Warning"): Text
begin
- exit(MissingParentWarningLbl); // TODO: Enhance message with specific parent details.
+ exit(StrSubstNo(MissingParentWarningLbl, MCPConfigWarning."Additional Info"));
end;
procedure RecommendedAction(MCPConfigWarning: Record "MCP Config Warning"): Text
@@ -32,7 +82,33 @@ codeunit 8354 "MCP Config Missing Parent" implements "MCP Config Warning"
end;
procedure ApplyRecommendedAction(var MCPConfigWarning: Record "MCP Config Warning")
+ var
+ MCPConfigImplementation: Codeunit "MCP Config Implementation";
+ PageIdList: List of [Text];
+ PageIdText: Text;
+ PageId: Integer;
+ begin
+ if MCPConfigWarning."Additional Info" = '' then
+ exit;
+
+ // Parse comma-separated page IDs and add each as a tool
+ PageIdList := MCPConfigWarning."Additional Info".Split(',');
+ foreach PageIdText in PageIdList do
+ if Evaluate(PageId, PageIdText.Trim()) then
+ MCPConfigImplementation.CreateAPITool(MCPConfigWarning."Config Id", PageId, false);
+
+ MCPConfigWarning.Delete();
+ end;
+
+ local procedure FormatPageIdList(PageIds: List of [Integer]): Text
+ var
+ PageId: Integer;
+ Result: TextBuilder;
begin
- // TODO: Implement logic to add the parent API page to the configuration.
+ foreach PageId in PageIds do begin
+ Result.Append(Format(PageId));
+ Result.Append(', ');
+ end;
+ exit(Result.ToText().TrimEnd(', '));
end;
}
diff --git a/src/System Application/App/MCP/src/Configuration/Tables/MCPConfigWarning.Table.al b/src/System Application/App/MCP/src/Configuration/Tables/MCPConfigWarning.Table.al
index 0ec7176558..218f256873 100644
--- a/src/System Application/App/MCP/src/Configuration/Tables/MCPConfigWarning.Table.al
+++ b/src/System Application/App/MCP/src/Configuration/Tables/MCPConfigWarning.Table.al
@@ -34,6 +34,11 @@ table 8352 "MCP Config Warning"
Caption = 'Warning Type';
ToolTip = 'Specifies the type of warning.';
}
+ field(5; "Additional Info"; Text[2048])
+ {
+ Caption = 'Additional Info';
+ ToolTip = 'Specifies additional information about the warning, such as missing parent page IDs.';
+ }
}
keys
From 939560ef6f2e593a85f080476a08d39084b37ccc Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Wed, 7 Jan 2026 15:56:36 +0100
Subject: [PATCH 08/17] Update
---
.../App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
index 7b2a93c201..8a56074d3a 100644
--- a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
+++ b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
@@ -62,7 +62,7 @@ page 8351 "MCP Config Card"
}
field(DiscoverReadOnlyObjects; Rec.DiscoverReadOnlyObjects)
{
- Editable = not IsDefault and Rec.EnableDynamicToolMode and Rec.Active;
+ Editable = not IsDefault and Rec.EnableDynamicToolMode and not Rec.Active;
trigger OnValidate()
begin
From 5b68dd33a9c4465511171a1e28a7a37278588354 Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Mon, 12 Jan 2026 17:14:28 +0100
Subject: [PATCH 09/17] Update
---
.../Codeunits/MCPConfigImplementation.Codeunit.al | 15 ++-------------
.../Codeunits/MCPConfigMissingParent.Codeunit.al | 4 ++--
2 files changed, 4 insertions(+), 15 deletions(-)
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
index 44cc613729..d66e999296 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
@@ -582,29 +582,18 @@ codeunit 8351 "MCP Config Implementation"
internal procedure LoadSystemTools(var MCPSystemTool: Record "MCP System Tool")
var
- // MCPUtilities: Codeunit "MCP Utilities";
+ MCPUtilities: Codeunit "MCP Utilities";
SystemTools: Dictionary of [Text, Text];
ToolName: Text;
begin
MCPSystemTool.Reset();
MCPSystemTool.DeleteAll();
- // SystemTools := MCPUtilities.GetSystemToolsInDynamicMode(); TODO
- SystemTools := GetSystemTools();
+ SystemTools := MCPUtilities.GetSystemToolsInDynamicMode();
foreach ToolName in SystemTools.Keys() do
InsertSystemTool(MCPSystemTool, CopyStr(ToolName, 1, MaxStrLen(MCPSystemTool."Tool Name")), CopyStr(SystemTools.Get(ToolName), 1, MaxStrLen(MCPSystemTool."Tool Description")));
end;
- local procedure GetSystemTools(): Dictionary of [Text, Text]
- var
- SystemTools: Dictionary of [Text, Text];
- begin
- SystemTools.Add('bc_action_search', 'Searches for available Business Central actions based on the provided criteria.');
- SystemTools.Add('bc_action_describe', 'Describes a Business Central action, providing details about its parameters and usage.');
- SystemTools.Add('bc_action_invoke', 'Invokes a Business Central action with the specified parameters.');
- exit(SystemTools);
- end;
-
local procedure InsertSystemTool(var MCPSystemTool: Record "MCP System Tool"; ToolName: Text[100]; ToolDescription: Text[250])
begin
MCPSystemTool."Tool Name" := ToolName;
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
index 55705ecd13..25972d927b 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
@@ -21,7 +21,7 @@ codeunit 8354 "MCP Config Missing Parent" implements "MCP Config Warning"
var
MCPConfigurationTool: Record "MCP Configuration Tool";
PageMetadata: Record "Page Metadata";
- // MCPUtilities: Codeunit "MCP Utilities";
+ MCPUtilities: Codeunit "MCP Utilities";
PageIdVersions: Dictionary of [Integer, Text];
ParentMCPTools: Dictionary of [Integer, List of [Integer]];
ParentPageIds: List of [Integer];
@@ -42,7 +42,7 @@ codeunit 8354 "MCP Config Missing Parent" implements "MCP Config Warning"
until MCPConfigurationTool.Next() = 0;
// Get parent mappings from platform
- // ParentMCPTools := MCPUtilities.GetParentMCPTools(PageIdVersions); TODO
+ ParentMCPTools := MCPUtilities.GetParentMCPTools(PageIdVersions);
// Check each page with parents for missing parent tools
foreach PageId in ParentMCPTools.Keys() do begin
From 9c42225cfb73124a0f1917e4e3ed57a86e1c9eb5 Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Tue, 13 Jan 2026 13:32:40 +0100
Subject: [PATCH 10/17] Update
---
.../Codeunits/MCPConfigImplementation.Codeunit.al | 2 +-
.../Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
index d66e999296..2cb22f8b23 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigImplementation.Codeunit.al
@@ -553,7 +553,7 @@ codeunit 8351 "MCP Config Implementation"
until PageMetadata.Next() = 0;
end;
- local procedure CheckAPIToolExists(ConfigId: Guid; PageId: Integer): Boolean
+ internal procedure CheckAPIToolExists(ConfigId: Guid; PageId: Integer): Boolean
var
MCPConfigurationTool: Record "MCP Configuration Tool";
begin
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
index 25972d927b..d8b2f7fca6 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
@@ -95,7 +95,8 @@ codeunit 8354 "MCP Config Missing Parent" implements "MCP Config Warning"
PageIdList := MCPConfigWarning."Additional Info".Split(',');
foreach PageIdText in PageIdList do
if Evaluate(PageId, PageIdText.Trim()) then
- MCPConfigImplementation.CreateAPITool(MCPConfigWarning."Config Id", PageId, false);
+ if not MCPConfigImplementation.CheckAPIToolExists(MCPConfigWarning."Config Id", PageId) then
+ MCPConfigImplementation.CreateAPITool(MCPConfigWarning."Config Id", PageId, false);
MCPConfigWarning.Delete();
end;
From 393277e5163faaeecc79aa1776f3ae73951d68d5 Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Thu, 15 Jan 2026 14:18:31 +0100
Subject: [PATCH 11/17] Update
---
.../Codeunits/MCPConfigMissingObject.Codeunit.al | 2 +-
.../App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al
index 124bad3fa9..a31c6acc3f 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingObject.Codeunit.al
@@ -15,7 +15,7 @@ codeunit 8353 "MCP Config Missing Object" implements "MCP Config Warning"
var
MCPConfigurationTool: Record "MCP Configuration Tool";
- MissingObjectWarningLbl: Label '%1 %2 referenced by this configuration no longer exists in the system.', Comment = '%1=Object type, %2=Object Id';
+ MissingObjectWarningLbl: Label '%1 (%2) referenced by this configuration no longer exists in the system.', Comment = '%1=Object type, %2=Object Id';
MissingObjectFixLbl: Label 'Remove this tool from the configuration.';
procedure CheckForWarnings(ConfigId: Guid; var MCPConfigWarning: Record "MCP Config Warning"; var EntryNo: Integer)
diff --git a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
index 8a56074d3a..b14cf43ea3 100644
--- a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
+++ b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
@@ -169,8 +169,8 @@ page 8351 "MCP Config Card"
SettingConfigurationAllowProdChangesLbl: Label 'Setting MCP configuration %1 AllowProdChanges to %2', Comment = '%1 - configuration ID, %2 - allow production changes', Locked = true;
SettingConfigurationDiscoverReadOnlyObjectsLbl: Label 'Setting MCP configuration %1 DiscoverReadOnlyObjects to %2', Comment = '%1 - configuration ID, %2 - allow read-only API discovery', Locked = true;
ToolModeLbl: Text;
- StaticToolModeLbl: Label 'In Static Tool Mode, objects in the available tools will be directly exposed to clients. You can manage these tools by adding, modifying, or removing them from the configuration.', Locked = true;
- DynamicToolModeLbl: Label 'In Dynamic Tool Mode, only system tools will be exposed to clients. Objects within the available tools can be discovered, described and invoked dynamically using system tools. You can enable dynamic discovery of any read-only object outside of the available tools using Discover Additional Objects setting.', Locked = true;
+ StaticToolModeLbl: Label 'In Static Tool Mode, objects in the available tools will be directly exposed to clients. You can manage these tools by adding, modifying, or removing them from the configuration.';
+ DynamicToolModeLbl: Label 'In Dynamic Tool Mode, only system tools will be exposed to clients. Objects within the available tools can be discovered, described and invoked dynamically using system tools. You can enable dynamic discovery of any read-only object outside of the available tools using Discover Additional Objects setting.';
local procedure GetToolModeDescription(): Text
begin
From 519d0bbb14cf52e77276f38f44226215da612042 Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Thu, 15 Jan 2026 16:57:13 +0100
Subject: [PATCH 12/17] Add new warning type for no read yes modify tools
---
.../Permissions/MCPObjects.PermissionSet.al | 1 +
.../MCPConfigMissingParent.Codeunit.al | 4 +-
.../MCPConfigMissingReadTool.Codeunit.al | 54 +++++++++
.../Enums/MCPConfigWarningType.Enum.al | 5 +
.../Test/MCP/src/MCPConfigTest.Codeunit.al | 112 +++++++++++++++++-
5 files changed, 172 insertions(+), 4 deletions(-)
create mode 100644 src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingReadTool.Codeunit.al
diff --git a/src/System Application/App/MCP/Permissions/MCPObjects.PermissionSet.al b/src/System Application/App/MCP/Permissions/MCPObjects.PermissionSet.al
index 829225add0..a2679771ce 100644
--- a/src/System Application/App/MCP/Permissions/MCPObjects.PermissionSet.al
+++ b/src/System Application/App/MCP/Permissions/MCPObjects.PermissionSet.al
@@ -15,6 +15,7 @@ permissionset 8350 "MCP - Objects"
codeunit "MCP Config Implementation" = X,
codeunit "MCP Config Missing Object" = X,
codeunit "MCP Config Missing Parent" = X,
+ codeunit "MCP Config Missing Read Tool" = X,
page "MCP API Config Tool Lookup" = X,
page "MCP API Publisher Lookup" = X,
page "MCP Config Card" = X,
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
index d8b2f7fca6..8a84f627ff 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
@@ -21,7 +21,7 @@ codeunit 8354 "MCP Config Missing Parent" implements "MCP Config Warning"
var
MCPConfigurationTool: Record "MCP Configuration Tool";
PageMetadata: Record "Page Metadata";
- MCPUtilities: Codeunit "MCP Utilities";
+ // MCPUtilities: Codeunit "MCP Utilities";
PageIdVersions: Dictionary of [Integer, Text];
ParentMCPTools: Dictionary of [Integer, List of [Integer]];
ParentPageIds: List of [Integer];
@@ -42,7 +42,7 @@ codeunit 8354 "MCP Config Missing Parent" implements "MCP Config Warning"
until MCPConfigurationTool.Next() = 0;
// Get parent mappings from platform
- ParentMCPTools := MCPUtilities.GetParentMCPTools(PageIdVersions);
+ // ParentMCPTools := MCPUtilities.GetParentMCPTools(PageIdVersions);
// Check each page with parents for missing parent tools
foreach PageId in ParentMCPTools.Keys() do begin
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingReadTool.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingReadTool.Codeunit.al
new file mode 100644
index 0000000000..d3aa5961de
--- /dev/null
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingReadTool.Codeunit.al
@@ -0,0 +1,54 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace System.MCP;
+
+codeunit 8355 "MCP Config Missing Read Tool" implements "MCP Config Warning"
+{
+ Access = Internal;
+ InherentEntitlements = X;
+ InherentPermissions = X;
+
+ var
+ MCPConfigurationTool: Record "MCP Configuration Tool";
+ MissingReadToolWarningLbl: Label '%1 (%2) has Allow Modify enabled but Allow Read is disabled.', Comment = '%1=Object type, %2=Object Id';
+ MissingReadToolFixLbl: Label 'Enable Allow Read for this tool.';
+
+ procedure CheckForWarnings(ConfigId: Guid; var MCPConfigWarning: Record "MCP Config Warning"; var EntryNo: Integer)
+ begin
+ MCPConfigurationTool.SetRange(ID, ConfigId);
+ MCPConfigurationTool.SetRange("Allow Modify", true);
+ MCPConfigurationTool.SetRange("Allow Read", false);
+ if MCPConfigurationTool.FindSet() then
+ repeat
+ MCPConfigWarning."Entry No." := EntryNo;
+ MCPConfigWarning."Config Id" := ConfigId;
+ MCPConfigWarning."Tool Id" := MCPConfigurationTool.SystemId;
+ MCPConfigWarning."Warning Type" := MCPConfigWarning."Warning Type"::"Missing Read Tool";
+ MCPConfigWarning.Insert();
+ EntryNo += 1;
+ until MCPConfigurationTool.Next() = 0;
+ end;
+
+ procedure WarningMessage(MCPConfigWarning: Record "MCP Config Warning"): Text
+ begin
+ if MCPConfigurationTool.GetBySystemId(MCPConfigWarning."Tool Id") then
+ exit(StrSubstNo(MissingReadToolWarningLbl, MCPConfigurationTool."Object Type", MCPConfigurationTool."Object ID"));
+ end;
+
+ procedure RecommendedAction(MCPConfigWarning: Record "MCP Config Warning"): Text
+ begin
+ exit(MissingReadToolFixLbl);
+ end;
+
+ procedure ApplyRecommendedAction(var MCPConfigWarning: Record "MCP Config Warning")
+ begin
+ if MCPConfigurationTool.GetBySystemId(MCPConfigWarning."Tool Id") then begin
+ MCPConfigurationTool."Allow Read" := true;
+ MCPConfigurationTool.Modify();
+ end;
+ MCPConfigWarning.Delete();
+ end;
+}
diff --git a/src/System Application/App/MCP/src/Configuration/Enums/MCPConfigWarningType.Enum.al b/src/System Application/App/MCP/src/Configuration/Enums/MCPConfigWarningType.Enum.al
index cdb4db31e2..7fa0432bac 100644
--- a/src/System Application/App/MCP/src/Configuration/Enums/MCPConfigWarningType.Enum.al
+++ b/src/System Application/App/MCP/src/Configuration/Enums/MCPConfigWarningType.Enum.al
@@ -20,4 +20,9 @@ enum 8350 "MCP Config Warning Type" implements "MCP Config Warning"
Caption = 'Missing Parent Object';
Implementation = "MCP Config Warning" = "MCP Config Missing Parent";
}
+ value(2; "Missing Read Tool")
+ {
+ Caption = 'Missing Read Tool';
+ Implementation = "MCP Config Warning" = "MCP Config Missing Read Tool";
+ }
}
diff --git a/src/System Application/Test/MCP/src/MCPConfigTest.Codeunit.al b/src/System Application/Test/MCP/src/MCPConfigTest.Codeunit.al
index afc6be67ed..67165a86da 100644
--- a/src/System Application/Test/MCP/src/MCPConfigTest.Codeunit.al
+++ b/src/System Application/Test/MCP/src/MCPConfigTest.Codeunit.al
@@ -579,7 +579,7 @@ codeunit 130130 "MCP Config Test"
end;
[Test]
- procedure TestFindWarningsForConfiguration()
+ procedure TestFindMissingObjectWarningsForConfiguration()
var
MCPConfigurationTool: Record "MCP Configuration Tool";
MCPConfigWarning: Record "MCP Config Warning";
@@ -604,7 +604,7 @@ codeunit 130130 "MCP Config Test"
end;
[Test]
- procedure TestApplyRecommendedAction()
+ procedure TestApplyMissingObjectRecommendedAction()
var
MCPConfigurationTool: Record "MCP Configuration Tool";
MCPConfigWarning: Record "MCP Config Warning";
@@ -632,6 +632,114 @@ codeunit 130130 "MCP Config Test"
Assert.RecordIsEmpty(MCPConfigurationTool);
end;
+ [Test]
+ procedure TestFindMissingReadToolWarningsForConfiguration()
+ var
+ MCPConfigurationTool: Record "MCP Configuration Tool";
+ MCPConfigWarning: Record "MCP Config Warning";
+ ConfigId: Guid;
+ ToolId: Guid;
+ begin
+ // [GIVEN] Configuration and tool with Allow Modify enabled but Allow Read disabled
+ ConfigId := CreateMCPConfig(false, false, true, false);
+ ToolId := CreateMCPConfigTool(ConfigId);
+ MCPConfigurationTool.GetBySystemId(ToolId);
+ MCPConfigurationTool."Allow Read" := false;
+ MCPConfigurationTool."Allow Modify" := true;
+ MCPConfigurationTool.Modify();
+ Commit();
+
+ // [WHEN] Find warnings for configuration is called
+ MCPConfig.FindWarningsForConfiguration(ConfigId, MCPConfigWarning);
+
+ // [THEN] Warning is created for the tool with missing read permission
+ Assert.RecordCount(MCPConfigWarning, 1);
+ MCPConfigWarning.FindFirst();
+ Assert.AreEqual(MCPConfigWarning."Warning Type"::"Missing Read Tool", MCPConfigWarning."Warning Type", 'Warning Type mismatch');
+ Assert.AreEqual(ToolId, MCPConfigWarning."Tool Id", 'Configuration Tool Id mismatch');
+ end;
+
+ [Test]
+ procedure TestApplyMissingReadToolRecommendedAction()
+ var
+ MCPConfigurationTool: Record "MCP Configuration Tool";
+ MCPConfigWarning: Record "MCP Config Warning";
+ ConfigId: Guid;
+ ToolId: Guid;
+ begin
+ // [GIVEN] Configuration and tool with Allow Modify enabled but Allow Read disabled
+ ConfigId := CreateMCPConfig(false, false, true, false);
+ ToolId := CreateMCPConfigTool(ConfigId);
+ MCPConfigurationTool.GetBySystemId(ToolId);
+ MCPConfigurationTool."Allow Read" := false;
+ MCPConfigurationTool."Allow Modify" := true;
+ MCPConfigurationTool.Modify();
+ Commit();
+
+ // [WHEN] Find warnings for configuration is called
+ MCPConfig.FindWarningsForConfiguration(ConfigId, MCPConfigWarning);
+
+ // [WHEN] Apply recommended action is called
+ MCPConfig.ApplyRecommendedAction(MCPConfigWarning);
+
+ // [THEN] Warning is resolved after applying the recommended action
+ Assert.RecordCount(MCPConfigWarning, 0);
+
+ // [THEN] Configuration tool has Allow Read enabled
+ MCPConfigurationTool.GetBySystemId(ToolId);
+ Assert.IsTrue(MCPConfigurationTool."Allow Read", 'Allow Read should be true after applying recommended action');
+ end;
+
+ [Test]
+ procedure TestNoMissingReadToolWarningWhenReadEnabled()
+ var
+ MCPConfigurationTool: Record "MCP Configuration Tool";
+ MCPConfigWarning: Record "MCP Config Warning";
+ ConfigId: Guid;
+ ToolId: Guid;
+ begin
+ // [GIVEN] Configuration and tool with both Allow Modify and Allow Read enabled
+ ConfigId := CreateMCPConfig(false, false, true, false);
+ ToolId := CreateMCPConfigTool(ConfigId);
+ MCPConfigurationTool.GetBySystemId(ToolId);
+ MCPConfigurationTool."Allow Read" := true;
+ MCPConfigurationTool."Allow Modify" := true;
+ MCPConfigurationTool.Modify();
+ Commit();
+
+ // [WHEN] Find warnings for configuration is called
+ MCPConfig.FindWarningsForConfiguration(ConfigId, MCPConfigWarning);
+
+ // [THEN] No Missing Read Tool warning is created
+ MCPConfigWarning.SetRange("Warning Type", MCPConfigWarning."Warning Type"::"Missing Read Tool");
+ Assert.RecordIsEmpty(MCPConfigWarning);
+ end;
+
+ [Test]
+ procedure TestNoMissingReadToolWarningWhenModifyDisabled()
+ var
+ MCPConfigurationTool: Record "MCP Configuration Tool";
+ MCPConfigWarning: Record "MCP Config Warning";
+ ConfigId: Guid;
+ ToolId: Guid;
+ begin
+ // [GIVEN] Configuration and tool with Allow Modify disabled
+ ConfigId := CreateMCPConfig(false, false, true, false);
+ ToolId := CreateMCPConfigTool(ConfigId);
+ MCPConfigurationTool.GetBySystemId(ToolId);
+ MCPConfigurationTool."Allow Read" := false;
+ MCPConfigurationTool."Allow Modify" := false;
+ MCPConfigurationTool.Modify();
+ Commit();
+
+ // [WHEN] Find warnings for configuration is called
+ MCPConfig.FindWarningsForConfiguration(ConfigId, MCPConfigWarning);
+
+ // [THEN] No Missing Read Tool warning is created
+ MCPConfigWarning.SetRange("Warning Type", MCPConfigWarning."Warning Type"::"Missing Read Tool");
+ Assert.RecordIsEmpty(MCPConfigWarning);
+ end;
+
local procedure CreateMCPConfig(Active: Boolean; DynamicToolMode: Boolean; AllowCreateUpdateDeleteTools: Boolean; DiscoverReadOnlyObjects: Boolean): Guid
var
MCPConfiguration: Record "MCP Configuration";
From 395a1e318118f7059bc4ea8bcaecbc7ccf95a99b Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Thu, 15 Jan 2026 16:58:57 +0100
Subject: [PATCH 13/17] Add new warning type for no read yes modify tools
---
.../Codeunits/MCPConfigMissingParent.Codeunit.al | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
index 8a84f627ff..d8b2f7fca6 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
@@ -21,7 +21,7 @@ codeunit 8354 "MCP Config Missing Parent" implements "MCP Config Warning"
var
MCPConfigurationTool: Record "MCP Configuration Tool";
PageMetadata: Record "Page Metadata";
- // MCPUtilities: Codeunit "MCP Utilities";
+ MCPUtilities: Codeunit "MCP Utilities";
PageIdVersions: Dictionary of [Integer, Text];
ParentMCPTools: Dictionary of [Integer, List of [Integer]];
ParentPageIds: List of [Integer];
@@ -42,7 +42,7 @@ codeunit 8354 "MCP Config Missing Parent" implements "MCP Config Warning"
until MCPConfigurationTool.Next() = 0;
// Get parent mappings from platform
- // ParentMCPTools := MCPUtilities.GetParentMCPTools(PageIdVersions);
+ ParentMCPTools := MCPUtilities.GetParentMCPTools(PageIdVersions);
// Check each page with parents for missing parent tools
foreach PageId in ParentMCPTools.Keys() do begin
From 1cd153fb453133aa7c75f1cbee37646a0936d789 Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Fri, 16 Jan 2026 11:22:28 +0100
Subject: [PATCH 14/17] Update
---
.../App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
index 8438b86669..a304705e76 100644
--- a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
+++ b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigCard.Page.al
@@ -39,7 +39,6 @@ page 8351 "MCP Config Card"
trigger OnValidate()
begin
-
if Rec.Active then
MCPConfigImplementation.ValidateConfiguration(Rec, true);
end;
From e04fe9515a01f701daa76908be6d91659645ecf8 Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Fri, 16 Jan 2026 14:05:49 +0100
Subject: [PATCH 15/17] Add MCP Config Warning permission to PermissionSet
---
.../App/MCP/Permissions/MCPObjects.PermissionSet.al | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/System Application/App/MCP/Permissions/MCPObjects.PermissionSet.al b/src/System Application/App/MCP/Permissions/MCPObjects.PermissionSet.al
index 59d535626c..d3f26d1af5 100644
--- a/src/System Application/App/MCP/Permissions/MCPObjects.PermissionSet.al
+++ b/src/System Application/App/MCP/Permissions/MCPObjects.PermissionSet.al
@@ -14,6 +14,7 @@ permissionset 8350 "MCP - Objects"
Permissions = table "MCP API Publisher Group" = X,
table "MCP Configuration" = X,
table "MCP Configuration Tool" = X,
+ table "MCP Config Warning" = X,
table "MCP Entra Application" = X,
table "MCP System Tool" = X;
-}
\ No newline at end of file
+}
From 0e9d7294a2683013bfddb5a93ad7f8b93b5a82a9 Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Thu, 22 Jan 2026 23:05:30 +0100
Subject: [PATCH 16/17] Update
---
.../Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
index d8b2f7fca6..e0856d1cb4 100644
--- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
+++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPConfigMissingParent.Codeunit.al
@@ -38,7 +38,8 @@ codeunit 8354 "MCP Config Missing Parent" implements "MCP Config Warning"
repeat
if PageMetadata.Get(MCPConfigurationTool."Object ID") then
- PageIdVersions.Add(MCPConfigurationTool."Object ID", PageMetadata.APIVersion);
+ if PageMetadata.PageType = PageMetadata.PageType::API then
+ PageIdVersions.Add(MCPConfigurationTool."Object ID", PageMetadata.APIVersion);
until MCPConfigurationTool.Next() = 0;
// Get parent mappings from platform
From c33da5e6c3aa0dcdb089a4fe283f945be9d53cd3 Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Thu, 22 Jan 2026 23:31:04 +0100
Subject: [PATCH 17/17] Update
---
.../Test/MCP/src/MCPConfigTest.Codeunit.al | 36 ++++++++++++++-----
1 file changed, 28 insertions(+), 8 deletions(-)
diff --git a/src/System Application/Test/MCP/src/MCPConfigTest.Codeunit.al b/src/System Application/Test/MCP/src/MCPConfigTest.Codeunit.al
index 67165a86da..c7b10b1191 100644
--- a/src/System Application/Test/MCP/src/MCPConfigTest.Codeunit.al
+++ b/src/System Application/Test/MCP/src/MCPConfigTest.Codeunit.al
@@ -597,10 +597,11 @@ codeunit 130130 "MCP Config Test"
MCPConfig.FindWarningsForConfiguration(ConfigId, MCPConfigWarning);
// [THEN] Warning is created for the tool with non-existing object
+#pragma warning disable AA0210
+ MCPConfigWarning.SetRange("Warning Type", MCPConfigWarning."Warning Type"::"Missing Object");
+#pragma warning restore AA0210
+ MCPConfigWarning.SetRange("Tool Id", ToolId);
Assert.RecordCount(MCPConfigWarning, 1);
- MCPConfigWarning.FindFirst();
- Assert.AreEqual(MCPConfigWarning."Warning Type"::"Missing Object", MCPConfigWarning."Warning Type", 'Warning Type mismatch');
- Assert.AreEqual(ToolId, MCPConfigWarning."Tool Id", 'Configuration Tool Id mismatch');
end;
[Test]
@@ -622,10 +623,19 @@ codeunit 130130 "MCP Config Test"
MCPConfig.FindWarningsForConfiguration(ConfigId, MCPConfigWarning);
// [WHEN] Apply recommended action is called
+#pragma warning disable AA0210
+ MCPConfigWarning.SetRange("Warning Type", MCPConfigWarning."Warning Type"::"Missing Object");
+#pragma warning restore AA0210
+ MCPConfigWarning.SetRange("Tool Id", ToolId);
+ MCPConfigWarning.FindFirst();
MCPConfig.ApplyRecommendedAction(MCPConfigWarning);
// [THEN] Warning is resolved after applying the recommended action
- Assert.RecordCount(MCPConfigWarning, 0);
+#pragma warning disable AA0210
+ MCPConfigWarning.SetRange("Warning Type", MCPConfigWarning."Warning Type"::"Missing Object");
+#pragma warning restore AA0210
+ MCPConfigWarning.SetRange("Tool Id", ToolId);
+ Assert.RecordIsEmpty(MCPConfigWarning);
// [THEN] Configuration tool is deleted
MCPConfigurationTool.SetRange(SystemId, ToolId);
@@ -653,10 +663,11 @@ codeunit 130130 "MCP Config Test"
MCPConfig.FindWarningsForConfiguration(ConfigId, MCPConfigWarning);
// [THEN] Warning is created for the tool with missing read permission
+#pragma warning disable AA0210
+ MCPConfigWarning.SetRange("Warning Type", MCPConfigWarning."Warning Type"::"Missing Read Tool");
+#pragma warning restore AA0210
+ MCPConfigWarning.SetRange("Tool Id", ToolId);
Assert.RecordCount(MCPConfigWarning, 1);
- MCPConfigWarning.FindFirst();
- Assert.AreEqual(MCPConfigWarning."Warning Type"::"Missing Read Tool", MCPConfigWarning."Warning Type", 'Warning Type mismatch');
- Assert.AreEqual(ToolId, MCPConfigWarning."Tool Id", 'Configuration Tool Id mismatch');
end;
[Test]
@@ -680,10 +691,19 @@ codeunit 130130 "MCP Config Test"
MCPConfig.FindWarningsForConfiguration(ConfigId, MCPConfigWarning);
// [WHEN] Apply recommended action is called
+#pragma warning disable AA0210
+ MCPConfigWarning.SetRange("Warning Type", MCPConfigWarning."Warning Type"::"Missing Read Tool");
+#pragma warning restore AA0210
+ MCPConfigWarning.SetRange("Tool Id", ToolId);
+ MCPConfigWarning.FindFirst();
MCPConfig.ApplyRecommendedAction(MCPConfigWarning);
// [THEN] Warning is resolved after applying the recommended action
- Assert.RecordCount(MCPConfigWarning, 0);
+#pragma warning disable AA0210
+ MCPConfigWarning.SetRange("Warning Type", MCPConfigWarning."Warning Type"::"Missing Read Tool");
+#pragma warning restore AA0210
+ MCPConfigWarning.SetRange("Tool Id", ToolId);
+ Assert.RecordIsEmpty(MCPConfigWarning);
// [THEN] Configuration tool has Allow Read enabled
MCPConfigurationTool.GetBySystemId(ToolId);