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 d6ae1dc9eb..416e92dbf6 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 @@ -78,6 +78,25 @@ codeunit 8350 "MCP Config" exit(MCPConfigImplementation.CopyConfiguration(SourceConfigId, NewName, NewDescription)); end; + /// + /// Sets the specified MCP configuration as the default configuration. + /// When no configuration is specified by a connection, the default configuration will be used. + /// Only active configurations can be set as default. + /// + /// The SystemId (GUID) of the configuration to set as default. + procedure SetAsDefaultConfiguration(ConfigId: Guid) + begin + MCPConfigImplementation.SetAsDefaultConfiguration(ConfigId); + end; + + /// + /// Clears the current default configuration designation and restores the system default. + /// + procedure ClearDefaultConfiguration() + begin + MCPConfigImplementation.ClearDefaultConfiguration(); + end; + /// /// Enables dynamic tool mode for the specified configuration. /// 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 ad6fc4ecfe..c834c6a624 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 @@ -28,6 +28,8 @@ codeunit 8351 "MCP Config Implementation" InvalidPageTypeErr: Label 'Only API pages are supported.'; InvalidAPIVersionErr: Label 'Only API v2.0 pages are supported.'; DefaultMCPConfigurationDescriptionLbl: Label 'Default MCP configuration'; + DesignatedDefaultCannotBeDeactivatedErr: Label 'The designated default configuration cannot be deactivated. Clear the default designation first.'; + ConfigurationMustBeActiveErr: Label 'Only active configurations can be set as the default.'; DynamicToolModeRequiredErr: Label 'Dynamic tool mode needs to be enabled to discover read-only objects.'; VersionNotValidErr: Label 'The API version is not valid for the selected tool.'; MCPConfigurationCreatedLbl: Label 'MCP Configuration created', Locked = true; @@ -38,6 +40,7 @@ codeunit 8351 "MCP Config Implementation" MCPConfigurationAuditDeletedLbl: Label 'MCP Configuration %1 deleted by user %2 in company %3', Comment = '%1 - configuration name, %2 - user security ID, %3 - company name', 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.'; + MCPDefaultConfigDesignatedLbl: Label 'MCP default configuration designated', Locked = true; ConnectionStringLbl: Label '%1 Connection String', Comment = '%1 - configuration name'; MCPUrlProdLbl: Label 'https://mcp.businesscentral.dynamics.com', Locked = true; MCPUrlTIELbl: Label 'https://mcp.businesscentral.dynamics-tie.com', Locked = true; @@ -55,6 +58,7 @@ codeunit 8351 "MCP Config Implementation" JsonFilterTxt: Label 'JSON Files (*.json)|*.json'; InvalidJsonErr: Label 'The selected file is not a valid configuration file.'; ConfigNameExistsMsg: Label 'A configuration with the name ''%1'' already exists. Please provide a different name.', Comment = '%1 = configuration name'; + ConfigurationNotFoundErr: Label 'The MCP configuration was not found.'; MCPServerFeedbackConfirmQst: Label 'We noticed you no longer have any active configurations. Could you share what made you decide to stop using the MCP server? Your feedback helps us improve the experience.'; MCPServerFeedbackQst: Label 'What could we do to improve the MCP server experience?'; NoActiveConfigsFeedbackTxt: Label 'No active configs feedback triggered', Locked = true; @@ -88,11 +92,14 @@ codeunit 8351 "MCP Config Implementation" MCPConfiguration: Record "MCP Configuration"; begin if not MCPConfiguration.GetBySystemId(ConfigId) then - exit; + Error(ConfigurationNotFoundErr); if not Active and IsDefaultConfiguration(MCPConfiguration) then Error(DefaultConfigCannotBeDeactivatedErr); + if not Active and IsDesignatedDefaultConfiguration(MCPConfiguration) then + Error(DesignatedDefaultCannotBeDeactivatedErr); + MCPConfiguration.Active := Active; MCPConfiguration.Modify(); @@ -104,7 +111,7 @@ codeunit 8351 "MCP Config Implementation" xMCPConfiguration: Record "MCP Configuration"; begin if not MCPConfiguration.GetBySystemId(ConfigId) then - exit; + Error(ConfigurationNotFoundErr); xMCPConfiguration := MCPConfiguration; @@ -135,11 +142,14 @@ codeunit 8351 "MCP Config Implementation" MCPConfiguration: Record "MCP Configuration"; begin if not MCPConfiguration.GetBySystemId(ConfigId) then - exit; + Error(ConfigurationNotFoundErr); if IsDefaultConfiguration(MCPConfiguration) then Error(DefaultConfigCannotBeDeletedErr); + if IsDesignatedDefaultConfiguration(MCPConfiguration) then + MarkSystemDefaultAsDefault(); + LogConfigurationDeleted(MCPConfiguration); MCPConfiguration.Delete(); end; @@ -166,11 +176,12 @@ codeunit 8351 "MCP Config Implementation" NewMCPConfiguration: Record "MCP Configuration"; begin if not SourceMCPConfiguration.GetBySystemId(SourceConfigId) then - exit; + Error(ConfigurationNotFoundErr); NewMCPConfiguration.Copy(SourceMCPConfiguration); NewMCPConfiguration.Name := NewName; NewMCPConfiguration.Description := NewDescription; + NewMCPConfiguration.Default := false; NewMCPConfiguration.Insert(); CopyTools(SourceMCPConfiguration, NewMCPConfiguration); @@ -201,7 +212,7 @@ codeunit 8351 "MCP Config Implementation" xMCPConfiguration: Record "MCP Configuration"; begin if not MCPConfiguration.GetBySystemId(ConfigId) then - exit; + Error(ConfigurationNotFoundErr); xMCPConfiguration := MCPConfiguration; @@ -221,7 +232,7 @@ codeunit 8351 "MCP Config Implementation" xMCPConfiguration: Record "MCP Configuration"; begin if not MCPConfiguration.GetBySystemId(ConfigId) then - exit; + Error(ConfigurationNotFoundErr); xMCPConfiguration := MCPConfiguration; @@ -241,7 +252,7 @@ codeunit 8351 "MCP Config Implementation" MCPConfiguration: Record "MCP Configuration"; begin if not MCPConfiguration.GetBySystemId(ConfigId) then - exit; + Error(ConfigurationNotFoundErr); if not MCPConfiguration.AllowProdChanges then Error(CreateUpdateDeleteNotAllowedErr); @@ -260,6 +271,7 @@ codeunit 8351 "MCP Config Implementation" MCPConfiguration.EnableDynamicToolMode := true; MCPConfiguration.DiscoverReadOnlyObjects := true; MCPConfiguration.AllowProdChanges := true; + MCPConfiguration.Default := true; MCPConfiguration.Insert(); end; @@ -268,6 +280,57 @@ codeunit 8351 "MCP Config Implementation" exit(MCPConfiguration.Name = ''); end; + internal procedure IsDesignatedDefaultConfiguration(MCPConfiguration: Record "MCP Configuration"): Boolean + begin + exit(MCPConfiguration.Default); + end; + + internal procedure SetAsDefaultConfiguration(ConfigId: Guid) + var + MCPConfiguration: Record "MCP Configuration"; + PreviousDefault: Record "MCP Configuration"; + begin + if not MCPConfiguration.GetBySystemId(ConfigId) then + Error(ConfigurationNotFoundErr); + + if not MCPConfiguration.Active then + Error(ConfigurationMustBeActiveErr); + + PreviousDefault.SetRange(Default, true); + PreviousDefault.ModifyAll(Default, false); + + MCPConfiguration.Default := true; + MCPConfiguration.Modify(); + + Session.LogMessage('0000R0R', MCPDefaultConfigDesignatedLbl, Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::All, GetDimensions(MCPConfiguration)); + end; + + internal procedure ClearDefaultConfiguration() + var + MCPConfiguration: Record "MCP Configuration"; + SystemDefault: Record "MCP Configuration"; + begin + MCPConfiguration.SetRange(Default, true); + MCPConfiguration.SetFilter(Name, '<>%1', ''); + MCPConfiguration.ModifyAll(Default, false); + + if SystemDefault.Get('') then begin + SystemDefault.Default := true; + SystemDefault.Modify(); + end; + end; + + local procedure MarkSystemDefaultAsDefault() + var + SystemDefault: Record "MCP Configuration"; + begin + if not SystemDefault.Get('') then + exit; + + SystemDefault.Default := true; + SystemDefault.Modify(); + end; + internal procedure IsConfigurationActive(ConfigId: Guid): Boolean var MCPConfiguration: Record "MCP Configuration"; @@ -361,7 +424,7 @@ codeunit 8351 "MCP Config Implementation" PageMetadata: Record "Page Metadata"; begin if not MCPConfiguration.GetBySystemId(ConfigId) then - exit; + Error(ConfigurationNotFoundErr); if IsDefaultConfiguration(MCPConfiguration) then Error(ToolsCannotBeAddedToDefaultConfigErr); @@ -917,7 +980,7 @@ codeunit 8351 "MCP Config Implementation" OutputText: Text; begin if not MCPConfiguration.GetBySystemId(ConfigId) then - exit; + Error(ConfigurationNotFoundErr); ConfigJson.Add('name', MCPConfiguration.Name); ConfigJson.Add('description', MCPConfiguration.Description); @@ -1081,6 +1144,7 @@ codeunit 8351 "MCP Config Implementation" Dimensions.Add('Category', GetTelemetryCategory()); Dimensions.Add('MCPConfigurationName', MCPConfiguration.Name); Dimensions.Add('Active', Format(MCPConfiguration.Active)); + Dimensions.Add('IsDesignatedDefault', Format(MCPConfiguration.Default)); Dimensions.Add('UnblockEditTools', Format(MCPConfiguration.AllowProdChanges)); Dimensions.Add('DynamicToolMode', Format(MCPConfiguration.EnableDynamicToolMode)); Dimensions.Add('DiscoverReadOnlyObjects', Format(MCPConfiguration.DiscoverReadOnlyObjects)); diff --git a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPUpgrade.Codeunit.al b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPUpgrade.Codeunit.al index 262339d0b4..d47b6b8e7a 100644 --- a/src/System Application/App/MCP/src/Configuration/Codeunits/MCPUpgrade.Codeunit.al +++ b/src/System Application/App/MCP/src/Configuration/Codeunits/MCPUpgrade.Codeunit.al @@ -17,6 +17,7 @@ codeunit 8356 "MCP Upgrade" trigger OnUpgradePerDatabase() begin UpgradeMCPAPIToolVersion(); + UpgradeMCPSystemDefaultAsDefault(); end; internal procedure UpgradeMCPAPIToolVersion() @@ -45,14 +46,36 @@ codeunit 8356 "MCP Upgrade" UpgradeTag.SetUpgradeTag(GetMCPAPIToolVersionUpgradeTag()); end; + internal procedure UpgradeMCPSystemDefaultAsDefault() + var + MCPConfiguration: Record "MCP Configuration"; + UpgradeTag: Codeunit "Upgrade Tag"; + begin + if UpgradeTag.HasDatabaseUpgradeTag(GetMCPSystemDefaultAsDefaultUpgradeTag()) then + exit; + + if MCPConfiguration.Get('') then begin + MCPConfiguration.Default := true; + MCPConfiguration.Modify(); + end; + + UpgradeTag.SetUpgradeTag(GetMCPSystemDefaultAsDefaultUpgradeTag()); + end; + [EventSubscriber(ObjectType::Codeunit, Codeunit::"Upgrade Tag", OnGetPerDatabaseUpgradeTags, '', false, false)] local procedure RegisterUpgradeTags(var PerDatabaseUpgradeTags: List of [Code[250]]) begin PerDatabaseUpgradeTags.Add(GetMCPAPIToolVersionUpgradeTag()); + PerDatabaseUpgradeTags.Add(GetMCPSystemDefaultAsDefaultUpgradeTag()); end; local procedure GetMCPAPIToolVersionUpgradeTag(): Text[250] begin exit('MS-619475-MCPAPIToolVersion-20260126'); end; + + local procedure GetMCPSystemDefaultAsDefaultUpgradeTag(): Text[250] + begin + exit('MS-612454-MCPSystemDefaultAsDefault-20260216'); + end; } \ No newline at end of file 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 f81781e7f1..530c6169e8 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 @@ -37,9 +37,18 @@ page 8351 "MCP Config Card" trigger OnValidate() begin if Rec.Active then - MCPConfigImplementation.ValidateConfiguration(Rec, true); + MCPConfigImplementation.ValidateConfiguration(Rec, true) + else + if Rec.Default then + Error(DesignatedDefaultCannotBeDeactivatedErr); end; } + field(Default; Rec.Default) + { + Caption = 'Default'; + ToolTip = 'Specifies whether this configuration is the default. The default configuration is used when no configuration is specified by a connection.'; + Editable = false; + } field(EnableDynamicToolMode; Rec.EnableDynamicToolMode) { ToolTip = 'Specifies whether to enable dynamic tool mode for this MCP configuration. When enabled, clients can search for tools within the configuration dynamically.'; @@ -156,11 +165,43 @@ page 8351 "MCP Config Card" end; } } + action(SetAsDefault) + { + Caption = 'Set as Default'; + ToolTip = 'Set this configuration as the default. It will be used when no configuration is specified by a connection.'; + Image = Approve; + AccessByPermission = tabledata "MCP Configuration" = M; + Visible = not IsDefault; + Enabled = not Rec.Default; + + trigger OnAction() + begin + MCPConfigImplementation.SetAsDefaultConfiguration(Rec.SystemId); + CurrPage.Update(false); + end; + } + action(ClearDefault) + { + Caption = 'Clear Default'; + ToolTip = 'Remove the default designation from this configuration. The system will revert to built-in default settings.'; + Image = Undo; + AccessByPermission = tabledata "MCP Configuration" = M; + Visible = not IsDefault; + Enabled = Rec.Default; + + trigger OnAction() + begin + MCPConfigImplementation.ClearDefaultConfiguration(); + CurrPage.Update(false); + end; + } } area(Promoted) { actionref(Promoted_Copy; Copy) { } actionref(Promoted_Validate; Validate) { } + actionref(Promoted_SetAsDefault; SetAsDefault) { } + actionref(Promoted_ClearDefault; ClearDefault) { } group(Promoted_Advanced) { Caption = 'Advanced'; @@ -202,6 +243,7 @@ page 8351 "MCP Config Card" 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.'; 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.'; + DesignatedDefaultCannotBeDeactivatedErr: Label 'The designated default configuration cannot be deactivated. Clear the default designation first.'; local procedure GetToolModeDescription(): Text begin diff --git a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigList.Page.al b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigList.Page.al index e79b041404..0e49953daa 100644 --- a/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigList.Page.al +++ b/src/System Application/App/MCP/src/Configuration/Pages/MCPConfigList.Page.al @@ -40,6 +40,11 @@ page 8350 "MCP Config List" { ToolTip = 'Specifies whether the MCP configuration is active.'; } + field(Default; Rec.Default) + { + ToolTip = 'Specifies whether this configuration is the default. The default configuration is used when no configuration is specified by a connection.'; + Editable = false; + } field(EnableDynamicToolMode; Rec.EnableDynamicToolMode) { ToolTip = 'Specifies whether to enable dynamic tool mode for this MCP configuration. When enabled, clients can search for tools within the configuration dynamically.'; @@ -76,7 +81,7 @@ page 8350 "MCP Config List" { Caption = 'Give Feedback'; ToolTip = 'Share your feedback about the MCP server experience.'; - Image = Questionaire; + Image = Comment; trigger OnAction() begin @@ -132,11 +137,47 @@ page 8350 "MCP Config List" CurrPage.Update(false); end; } + action(SetAsDefault) + { + Caption = 'Set as Default'; + ToolTip = 'Set this configuration as the default. It will be used when no configuration is specified by a connection.'; + Image = Approve; + AccessByPermission = tabledata "MCP Configuration" = M; + Scope = Repeater; + Enabled = not Rec.Default; + + trigger OnAction() + var + MCPConfigImplementation: Codeunit "MCP Config Implementation"; + begin + MCPConfigImplementation.SetAsDefaultConfiguration(Rec.SystemId); + CurrPage.Update(false); + end; + } + action(ClearDefault) + { + Caption = 'Clear Default'; + ToolTip = 'Remove the default designation from this configuration. The system will revert to built-in default settings.'; + Image = Undo; + AccessByPermission = tabledata "MCP Configuration" = M; + Scope = Repeater; + Enabled = Rec.Default; + + trigger OnAction() + var + MCPConfigImplementation: Codeunit "MCP Config Implementation"; + begin + MCPConfigImplementation.ClearDefaultConfiguration(); + CurrPage.Update(false); + end; + } } } area(Promoted) { actionref(Promoted_Copy; Copy) { } + actionref(Promoted_SetAsDefault; SetAsDefault) { } + actionref(Promoted_ClearDefault; ClearDefault) { } actionref(Promoted_GiveFeedback; GiveFeedback) { } group(Promoted_Advanced) { diff --git a/src/System Application/Test/MCP/src/MCPConfigTest.Codeunit.al b/src/System Application/Test/MCP/src/MCPConfigTest.Codeunit.al index dbb8fa2633..2445095346 100644 --- a/src/System Application/Test/MCP/src/MCPConfigTest.Codeunit.al +++ b/src/System Application/Test/MCP/src/MCPConfigTest.Codeunit.al @@ -914,6 +914,149 @@ codeunit 130130 "MCP Config Test" Assert.IsTrue(ConnectionString.Contains('/mcp'), 'On-prem URL should contain /mcp suffix'); end; + [Test] + procedure TestSetAsDefaultConfiguration() + var + MCPConfiguration: Record "MCP Configuration"; + SystemDefault: Record "MCP Configuration"; + ConfigId: Guid; + begin + // [GIVEN] An active configuration + EnsureSystemDefaultExists(); + ConfigId := CreateMCPConfig(true, false, false, false); + + // [WHEN] Set as default is called + MCPConfig.SetAsDefaultConfiguration(ConfigId); + + // [THEN] Configuration is marked as default + MCPConfiguration.GetBySystemId(ConfigId); + Assert.IsTrue(MCPConfiguration.Default, 'Configuration should be marked as default'); + + // [THEN] System default is no longer marked as default + SystemDefault.Get(''); + Assert.IsFalse(SystemDefault.Default, 'System default should not be marked as default'); + end; + + [Test] + procedure TestClearDefaultConfiguration() + var + MCPConfiguration: Record "MCP Configuration"; + SystemDefault: Record "MCP Configuration"; + ConfigId: Guid; + begin + // [GIVEN] A configuration that has been set as default + EnsureSystemDefaultExists(); + ConfigId := CreateMCPConfig(true, false, false, false); + MCPConfig.SetAsDefaultConfiguration(ConfigId); + + // [WHEN] Clear default is called + MCPConfig.ClearDefaultConfiguration(); + + // [THEN] Configuration is no longer marked as default + MCPConfiguration.GetBySystemId(ConfigId); + Assert.IsFalse(MCPConfiguration.Default, 'Configuration should not be marked as default'); + + // [THEN] System default is re-marked as default + SystemDefault.Get(''); + Assert.IsTrue(SystemDefault.Default, 'System default should be re-marked as default'); + end; + + [Test] + procedure TestOnlyOneDefaultConfiguration() + var + MCPConfiguration1: Record "MCP Configuration"; + MCPConfiguration2: Record "MCP Configuration"; + ConfigId1: Guid; + ConfigId2: Guid; + begin + // [GIVEN] Two active configurations + EnsureSystemDefaultExists(); + ConfigId1 := CreateMCPConfig(true, true, true, true); + ConfigId2 := CreateMCPConfig(true, false, false, false); + + // [WHEN] First is set as default, then second + MCPConfig.SetAsDefaultConfiguration(ConfigId1); + MCPConfig.SetAsDefaultConfiguration(ConfigId2); + + // [THEN] Only the second configuration is marked as default + MCPConfiguration1.GetBySystemId(ConfigId1); + MCPConfiguration2.GetBySystemId(ConfigId2); + Assert.IsFalse(MCPConfiguration1.Default, 'First config should no longer be default'); + Assert.IsTrue(MCPConfiguration2.Default, 'Second config should be default'); + end; + + [Test] + procedure TestCopyConfigurationDoesNotCopyDefault() + var + MCPConfiguration: Record "MCP Configuration"; + ConfigId: Guid; + CopiedConfigId: Guid; + begin + // [GIVEN] A default configuration + EnsureSystemDefaultExists(); + ConfigId := CreateMCPConfig(true, true, true, true); + MCPConfig.SetAsDefaultConfiguration(ConfigId); + + // [WHEN] Configuration is copied + CopiedConfigId := MCPConfig.CopyConfiguration(ConfigId, CopyStr(Format(CreateGuid()), 1, 100), 'Copied'); + + // [THEN] Copied configuration is not marked as default + MCPConfiguration.GetBySystemId(CopiedConfigId); + Assert.IsFalse(MCPConfiguration.Default, 'Copied config should not be default'); + end; + + [Test] + procedure TestCannotSetInactiveConfigurationAsDefault() + var + ConfigId: Guid; + begin + // [GIVEN] An inactive configuration + EnsureSystemDefaultExists(); + ConfigId := CreateMCPConfig(false, false, true, false); + + // [WHEN] Set as default is called + asserterror MCPConfig.SetAsDefaultConfiguration(ConfigId); + + // [THEN] Error is raised + Assert.ExpectedError('Only active configurations can be set as the default.'); + end; + + [Test] + procedure TestCannotDeactivateDesignatedDefault() + var + ConfigId: Guid; + begin + // [GIVEN] A configuration set as default + EnsureSystemDefaultExists(); + ConfigId := CreateMCPConfig(true, true, true, true); + MCPConfig.SetAsDefaultConfiguration(ConfigId); + + // [WHEN] Deactivate is called + asserterror MCPConfig.ActivateConfiguration(ConfigId, false); + + // [THEN] Error is raised + Assert.ExpectedError('The designated default configuration cannot be deactivated.'); + end; + + [Test] + procedure TestDeleteDesignatedDefaultRestoresSystemDefault() + var + SystemDefault: Record "MCP Configuration"; + ConfigId: Guid; + begin + // [GIVEN] A configuration set as default + EnsureSystemDefaultExists(); + ConfigId := CreateMCPConfig(true, false, false, false); + MCPConfig.SetAsDefaultConfiguration(ConfigId); + + // [WHEN] The designated default is deleted + MCPConfig.DeleteConfiguration(ConfigId); + + // [THEN] System default is re-marked as default + SystemDefault.Get(''); + Assert.IsTrue(SystemDefault.Default, 'System default should be re-marked as default'); + end; + local procedure CreateMCPConfig(Active: Boolean; DynamicToolMode: Boolean; AllowCreateUpdateDeleteTools: Boolean; DiscoverReadOnlyObjects: Boolean): Guid var MCPConfiguration: Record "MCP Configuration"; @@ -945,6 +1088,22 @@ codeunit 130130 "MCP Config Test" exit(MCPConfigurationTool.SystemId); end; + local procedure EnsureSystemDefaultExists() + var + MCPConfiguration: Record "MCP Configuration"; + begin + if MCPConfiguration.Get('') then + exit; + MCPConfiguration.Name := ''; + MCPConfiguration.Description := 'Default MCP configuration'; + MCPConfiguration.Active := true; + MCPConfiguration.EnableDynamicToolMode := true; + MCPConfiguration.DiscoverReadOnlyObjects := true; + MCPConfiguration.AllowProdChanges := true; + MCPConfiguration.Default := true; + MCPConfiguration.Insert(); + end; + [ModalPageHandler] procedure LookupAPIToolsOKHandler(var MCPAPIConfigToolLookup: TestPage "MCP API Config Tool Lookup") begin