From 8542b1fa453c91460551a3706a8069119c73c7cc Mon Sep 17 00:00:00 2001 From: hatayama Date: Sat, 2 May 2026 05:15:40 +0900 Subject: [PATCH 1/5] Always allow third-party tools Third-party tool access no longer needs a separate permission toggle, so remove the editor control and normalize persisted settings to keep custom tools available. Update docs and tests to match the always-on behavior. --- .../Tests/Editor/ToolSettingsSectionTests.cs | 10 ------- Assets/Tests/Editor/ULoopSettingsTests.cs | 25 ++++++++++++---- Packages/src/Editor/Config/ULoopSettings.cs | 24 ++++++++++++--- .../src/Editor/Config/ULoopSettingsData.cs | 2 +- .../src/Editor/Security/McpSecurityChecker.cs | 2 +- Packages/src/Editor/UI/McpEditorModel.cs | 8 ----- Packages/src/Editor/UI/McpEditorWindow.cs | 7 ----- .../Components/ToolSettingsSection.cs | 30 ++++--------------- .../Editor/UI/UIToolkit/McpEditorWindow.uxml | 11 ------- .../Editor/UI/UIToolkit/McpEditorWindowUI.cs | 2 -- Packages/src/README.md | 11 ++----- Packages/src/README_ja.md | 11 ++----- README.md | 11 ++----- README_ja.md | 11 ++----- 14 files changed, 59 insertions(+), 106 deletions(-) diff --git a/Assets/Tests/Editor/ToolSettingsSectionTests.cs b/Assets/Tests/Editor/ToolSettingsSectionTests.cs index f07ba08d8..7dba3180a 100644 --- a/Assets/Tests/Editor/ToolSettingsSectionTests.cs +++ b/Assets/Tests/Editor/ToolSettingsSectionTests.cs @@ -177,14 +177,6 @@ private static VisualElement CreateRootElement() { name = "cli-reference-link" }; - Toggle allowThirdPartyToggle = new Toggle - { - name = "allow-third-party-toggle" - }; - Label allowThirdPartyLabel = new Label - { - name = "allow-third-party-label" - }; Button securityLevelRestrictedButton = new Button { name = "security-level-restricted-button" @@ -202,8 +194,6 @@ private static VisualElement CreateRootElement() name = "tool-settings-info-container" }; - foldout.Add(allowThirdPartyToggle); - foldout.Add(allowThirdPartyLabel); foldout.Add(securityLevelRestrictedButton); foldout.Add(securityLevelFullAccessButton); foldout.Add(securityLevelDescription); diff --git a/Assets/Tests/Editor/ULoopSettingsTests.cs b/Assets/Tests/Editor/ULoopSettingsTests.cs index 5b92fab9b..b1a4aebd8 100644 --- a/Assets/Tests/Editor/ULoopSettingsTests.cs +++ b/Assets/Tests/Editor/ULoopSettingsTests.cs @@ -142,7 +142,7 @@ public void SetAndGet_RoundTrip_ShouldPreserveRemainingValues() { ULoopSettingsData written = new ULoopSettingsData { - allowThirdPartyTools = true, + allowThirdPartyTools = false, dynamicCodeSecurityLevel = (int)DynamicCodeSecurityLevel.Restricted }; ULoopSettings.SaveSettings(written); @@ -150,10 +150,25 @@ public void SetAndGet_RoundTrip_ShouldPreserveRemainingValues() ULoopSettingsData readBack = ULoopSettings.GetSettings(); - Assert.AreEqual(written.allowThirdPartyTools, readBack.allowThirdPartyTools); + Assert.IsTrue(readBack.allowThirdPartyTools); Assert.AreEqual(written.dynamicCodeSecurityLevel, readBack.dynamicCodeSecurityLevel); } + [Test] + public void SetAllowThirdPartyTools_WhenFalse_ShouldKeepThirdPartyToolsAllowed() + { + ULoopSettings.SaveSettings(new ULoopSettingsData + { + allowThirdPartyTools = true, + dynamicCodeSecurityLevel = (int)DynamicCodeSecurityLevel.Restricted + }); + + ULoopSettings.SetAllowThirdPartyTools(false); + + Assert.IsTrue(ULoopSettings.GetAllowThirdPartyTools()); + Assert.IsTrue(ULoopSettings.GetSettings().allowThirdPartyTools); + } + [Test] public void Migration_ShouldPurgeRemainingSecurityFieldsAndPreserveOtherSettings() { @@ -189,7 +204,7 @@ public void GetSettings_WhenBothFilesAbsent_ShouldReturnDefaults() ULoopSettingsData result = ULoopSettings.GetSettings(); - Assert.IsFalse(result.allowThirdPartyTools); + Assert.IsTrue(result.allowThirdPartyTools); Assert.AreEqual((int)DynamicCodeSecurityLevel.Restricted, result.dynamicCodeSecurityLevel); Assert.IsFalse(File.Exists(LegacySettingsFilePath), "Legacy file should not be created when both files are absent"); @@ -211,7 +226,7 @@ public void GetSettings_WhenPrimaryMissingAndBackupExists_ShouldRecoverFromBacku ULoopSettingsData result = ULoopSettings.GetSettings(); Assert.IsTrue(File.Exists(SettingsFilePath), $"{SettingsFilePath} should be recovered from .bak"); - Assert.IsFalse(result.allowThirdPartyTools); + Assert.IsTrue(result.allowThirdPartyTools); Assert.AreEqual((int)DynamicCodeSecurityLevel.FullAccess, result.dynamicCodeSecurityLevel); Assert.IsFalse(File.Exists(SettingsBackupPath), ".bak should be consumed by recovery"); } @@ -234,7 +249,7 @@ public void GetSettings_WhenOldSecurityJsonExists_ShouldRenameToPermissions() Assert.IsTrue(File.Exists(SettingsFilePath), "New settings file should exist after rename"); Assert.IsFalse(File.Exists(OldSettingsFilePath), "Old settings file should be removed after rename"); - Assert.IsFalse(result.allowThirdPartyTools); + Assert.IsTrue(result.allowThirdPartyTools); Assert.AreEqual((int)DynamicCodeSecurityLevel.Restricted, result.dynamicCodeSecurityLevel); } diff --git a/Packages/src/Editor/Config/ULoopSettings.cs b/Packages/src/Editor/Config/ULoopSettings.cs index 055d70d97..e9ebb9f73 100644 --- a/Packages/src/Editor/Config/ULoopSettings.cs +++ b/Packages/src/Editor/Config/ULoopSettings.cs @@ -36,6 +36,7 @@ public static ULoopSettingsData GetSettings() public static void SaveSettings(ULoopSettingsData settings) { Debug.Assert(settings != null, "settings must not be null"); + settings = settings with { allowThirdPartyTools = true }; string directory = Path.GetDirectoryName(SettingsFilePath); if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) @@ -65,13 +66,13 @@ public static void UpdateSettings(Func tra public static bool GetAllowThirdPartyTools() { - return GetSettings().allowThirdPartyTools; + return true; } public static void SetAllowThirdPartyTools(bool value) { ULoopSettingsData settings = GetSettings(); - ULoopSettingsData updated = settings with { allowThirdPartyTools = value }; + ULoopSettingsData updated = settings with { allowThirdPartyTools = true }; SaveSettings(updated); } @@ -159,7 +160,8 @@ private static void LoadSettings() _cachedSettings = JsonUtility.FromJson(json); bool migratedToolToggles = ApplyLegacyToolToggleMigrations(json); bool normalizedDynamicCode = NormalizeLegacyDisabledDynamicCode(); - if (migratedToolToggles || normalizedDynamicCode) + bool normalizedThirdPartyTools = NormalizeThirdPartyToolsAllowed(); + if (migratedToolToggles || normalizedDynamicCode || normalizedThirdPartyTools) { SaveSettings(_cachedSettings); } @@ -227,12 +229,13 @@ private static void MigrateFromLegacySettings() _cachedSettings = new ULoopSettingsData { - allowThirdPartyTools = probe.allowThirdPartyTools, + allowThirdPartyTools = true, dynamicCodeSecurityLevel = probe.dynamicCodeSecurityLevel }; ApplyLegacyToolToggleMigrations(legacyJson); NormalizeLegacyDisabledDynamicCode(); + NormalizeThirdPartyToolsAllowed(); SaveSettings(_cachedSettings); // Re-save legacy file to purge security fields that are no longer in @@ -258,6 +261,19 @@ private static bool NormalizeLegacyDisabledDynamicCode() return true; } + private static bool NormalizeThirdPartyToolsAllowed() + { + Debug.Assert(_cachedSettings != null, "_cachedSettings must not be null"); + + if (_cachedSettings.allowThirdPartyTools) + { + return false; + } + + _cachedSettings = _cachedSettings with { allowThirdPartyTools = true }; + return true; + } + private static bool ApplyLegacyToolToggleMigrations(string json) { if (string.IsNullOrWhiteSpace(json)) diff --git a/Packages/src/Editor/Config/ULoopSettingsData.cs b/Packages/src/Editor/Config/ULoopSettingsData.cs index de03d32a3..760b105b2 100644 --- a/Packages/src/Editor/Config/ULoopSettingsData.cs +++ b/Packages/src/Editor/Config/ULoopSettingsData.cs @@ -9,7 +9,7 @@ namespace io.github.hatayama.uLoopMCP [Serializable] public record ULoopSettingsData { - public bool allowThirdPartyTools = false; + public bool allowThirdPartyTools = true; public int dynamicCodeSecurityLevel = (int)DynamicCodeSecurityLevel.Restricted; } } diff --git a/Packages/src/Editor/Security/McpSecurityChecker.cs b/Packages/src/Editor/Security/McpSecurityChecker.cs index d543a2e46..e47193b54 100644 --- a/Packages/src/Editor/Security/McpSecurityChecker.cs +++ b/Packages/src/Editor/Security/McpSecurityChecker.cs @@ -153,7 +153,7 @@ public static string GetBlockReason(string toolName) case SecuritySettings.None: if (IsThirdPartyTool(toolName)) { - return "Third party tools execution is disabled. Enable 'Allow Third Party Tools' in uLoopMCP Security Settings."; + return $"Tool '{toolName}' is not allowed by security policy."; } return $"Tool '{toolName}' is not allowed by security policy."; diff --git a/Packages/src/Editor/UI/McpEditorModel.cs b/Packages/src/Editor/UI/McpEditorModel.cs index 8e051cb43..874223619 100644 --- a/Packages/src/Editor/UI/McpEditorModel.cs +++ b/Packages/src/Editor/UI/McpEditorModel.cs @@ -209,14 +209,6 @@ public void UpdateToolEnabled(string toolName, bool enabled) ToolSettings.SetToolEnabled(toolName, enabled); } - /// - /// Update AllowThirdPartyTools setting with persistence - /// - public void UpdateAllowThirdPartyTools(bool allow) - { - ULoopSettings.SetAllowThirdPartyTools(allow); - } - public void UpdateShowConfiguration(bool show) { UpdateUIState(ui => new UIState( diff --git a/Packages/src/Editor/UI/McpEditorWindow.cs b/Packages/src/Editor/UI/McpEditorWindow.cs index 83fb2ed0a..483a972bb 100644 --- a/Packages/src/Editor/UI/McpEditorWindow.cs +++ b/Packages/src/Editor/UI/McpEditorWindow.cs @@ -101,7 +101,6 @@ private void SetupViewCallbacks() _view.OnConnectedToolsFoldoutChanged += UpdateShowConnectedTools; _view.OnToolSettingsFoldoutChanged += UpdateShowToolSettings; _view.OnToolToggled += HandleToolToggled; - _view.OnAllowThirdPartyChanged += UpdateAllowThirdPartyTools; _view.OnSecurityLevelChanged += UpdateDynamicCodeSecurityLevel; } @@ -561,12 +560,6 @@ private void UpdateShowConfiguration(bool show) _model.UpdateShowConfiguration(show); } - private void UpdateAllowThirdPartyTools(bool allow) - { - _model.UpdateAllowThirdPartyTools(allow); - RefreshToolSettingsHeader(); - } - private void UpdateDynamicCodeSecurityLevel(DynamicCodeSecurityLevel level) { ULoopSettings.SetDynamicCodeSecurityLevel(level); diff --git a/Packages/src/Editor/UI/UIToolkit/Components/ToolSettingsSection.cs b/Packages/src/Editor/UI/UIToolkit/Components/ToolSettingsSection.cs index f6daae226..3e02542e7 100644 --- a/Packages/src/Editor/UI/UIToolkit/Components/ToolSettingsSection.cs +++ b/Packages/src/Editor/UI/UIToolkit/Components/ToolSettingsSection.cs @@ -16,8 +16,6 @@ public class ToolSettingsSection private const int InlineToolRowLimit = 40; private readonly Foldout _foldout; - private readonly Toggle _allowThirdPartyToggle; - private readonly Label _allowThirdPartyLabel; private readonly Button _securityLevelRestrictedButton; private readonly Button _securityLevelFullAccessButton; private readonly Label _securityLevelDescription; @@ -35,14 +33,11 @@ public class ToolSettingsSection public event Action OnFoldoutChanged; public event Action OnToolToggled; - public event Action OnAllowThirdPartyChanged; public event Action OnSecurityLevelChanged; public ToolSettingsSection(VisualElement root) { _foldout = root.Q("tool-settings-foldout"); - _allowThirdPartyToggle = root.Q("allow-third-party-toggle"); - _allowThirdPartyLabel = root.Q