diff --git a/MCPForUnity/Editor/Constants/EditorPrefKeys.cs b/MCPForUnity/Editor/Constants/EditorPrefKeys.cs
index c5dab7c41..3cbdad172 100644
--- a/MCPForUnity/Editor/Constants/EditorPrefKeys.cs
+++ b/MCPForUnity/Editor/Constants/EditorPrefKeys.cs
@@ -66,5 +66,7 @@ internal static class EditorPrefKeys
internal const string ApiKey = "MCPForUnity.ApiKey";
internal const string BatchExecuteMaxCommands = "MCPForUnity.BatchExecute.MaxCommands";
+ internal const string GatewayJobLogging = "MCPForUnity.Gateway.JobLogging";
+ internal const string GatewayJobLogPath = "MCPForUnity.Gateway.JobLogPath";
}
}
diff --git a/MCPForUnity/Editor/Helpers/AssetPathUtility.cs b/MCPForUnity/Editor/Helpers/AssetPathUtility.cs
index c648c19e4..03df03f17 100644
--- a/MCPForUnity/Editor/Helpers/AssetPathUtility.cs
+++ b/MCPForUnity/Editor/Helpers/AssetPathUtility.cs
@@ -103,6 +103,14 @@ public static string GetMcpPackageRootPath()
{
try
{
+ // WSL workaround: when the package lives on a WSL UNC path and Unity
+ // runs on Windows, UXML/USS files cannot be parsed from the UNC path.
+ // UIAssetSync copies them to Assets/MCPForUnityUI/ on domain reload.
+ if (UIAssetSync.NeedsSync())
+ {
+ return UIAssetSync.SyncedBasePath;
+ }
+
// Try Package Manager first (registry and local installs)
var packageInfo = PackageInfo.FindForAssembly(typeof(AssetPathUtility).Assembly);
if (packageInfo != null && !string.IsNullOrEmpty(packageInfo.assetPath))
diff --git a/MCPForUnity/Editor/Helpers/UIAssetSync.cs b/MCPForUnity/Editor/Helpers/UIAssetSync.cs
new file mode 100644
index 000000000..d3dba17b8
--- /dev/null
+++ b/MCPForUnity/Editor/Helpers/UIAssetSync.cs
@@ -0,0 +1,121 @@
+using UnityEditor;
+using UnityEngine;
+using System.IO;
+
+namespace MCPForUnity.Editor.Helpers
+{
+ ///
+ /// Automatically copies UXML and USS files from WSL package directories to a local
+ /// Assets/MCPForUnityUI/ folder on every domain reload, preserving directory structure.
+ ///
+ ///
+ ///
+ /// Problem: Unity's UXML/USS importer on Windows cannot properly parse files
+ /// when packages live on a WSL2 filesystem (UNC paths like \\wsl$\...). The
+ /// VisualTreeAsset loads but CloneTree produces an empty tree.
+ ///
+ ///
+ /// Solution: On startup, this class copies all UI asset files to
+ /// Assets/MCPForUnityUI/ and
+ /// returns this fallback path when WSL is detected.
+ ///
+ ///
+ [InitializeOnLoad]
+ static class UIAssetSync
+ {
+ /// Destination folder under the Unity project for synced UI assets.
+ internal const string SyncedBasePath = "Assets/MCPForUnityUI";
+
+ ///
+ /// Relative paths from package root to UXML and USS files that need syncing.
+ ///
+ private static readonly string[] k_UIAssetPaths =
+ {
+ "Editor/Windows/MCPForUnityEditorWindow.uxml",
+ "Editor/Windows/MCPForUnityEditorWindow.uss",
+ "Editor/Windows/MCPSetupWindow.uxml",
+ "Editor/Windows/MCPSetupWindow.uss",
+ "Editor/Windows/EditorPrefs/EditorPrefItem.uxml",
+ "Editor/Windows/EditorPrefs/EditorPrefsWindow.uxml",
+ "Editor/Windows/EditorPrefs/EditorPrefsWindow.uss",
+ "Editor/Windows/Components/Common.uss",
+ "Editor/Windows/Components/Connection/McpConnectionSection.uxml",
+ "Editor/Windows/Components/ClientConfig/McpClientConfigSection.uxml",
+ "Editor/Windows/Components/Validation/McpValidationSection.uxml",
+ "Editor/Windows/Components/Advanced/McpAdvancedSection.uxml",
+ "Editor/Windows/Components/Tools/McpToolsSection.uxml",
+ "Editor/Windows/Components/Resources/McpResourcesSection.uxml",
+ "Editor/Windows/Components/Queue/McpQueueSection.uxml",
+ "Editor/Windows/Components/Queue/McpQueueSection.uss",
+ };
+
+ static UIAssetSync()
+ {
+ if (!NeedsSync())
+ return;
+
+ string packageRoot = GetPackagePhysicalRoot();
+ if (string.IsNullOrEmpty(packageRoot))
+ return;
+
+ bool anyUpdated = false;
+
+ foreach (string relativePath in k_UIAssetPaths)
+ {
+ string sourcePath = Path.Combine(packageRoot, relativePath);
+ if (!File.Exists(sourcePath))
+ continue;
+
+ string sourceContent = File.ReadAllText(sourcePath);
+
+ string destPath = Path.GetFullPath(Path.Combine(SyncedBasePath, relativePath));
+ string destDir = Path.GetDirectoryName(destPath);
+
+ if (!string.IsNullOrEmpty(destDir) && !Directory.Exists(destDir))
+ Directory.CreateDirectory(destDir);
+
+ if (File.Exists(destPath) && File.ReadAllText(destPath) == sourceContent)
+ continue;
+
+ File.WriteAllText(destPath, sourceContent);
+ Debug.Log($"[UIAssetSync] Updated {relativePath}");
+ anyUpdated = true;
+ }
+
+ if (anyUpdated)
+ AssetDatabase.Refresh();
+ }
+
+ ///
+ /// Returns true when the MCP package lives on a WSL UNC path and Unity runs on Windows.
+ ///
+ internal static bool NeedsSync()
+ {
+ if (Application.platform != RuntimePlatform.WindowsEditor)
+ return false;
+
+ string packageRoot = GetPackagePhysicalRoot();
+ if (string.IsNullOrEmpty(packageRoot))
+ return false;
+
+ return packageRoot.StartsWith(@"\\wsl", System.StringComparison.OrdinalIgnoreCase);
+ }
+
+ ///
+ /// Gets the physical (filesystem) root path of the MCP package.
+ ///
+ private static string GetPackagePhysicalRoot()
+ {
+ var packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssembly(
+ typeof(UIAssetSync).Assembly);
+ if (packageInfo != null && !string.IsNullOrEmpty(packageInfo.resolvedPath))
+ return packageInfo.resolvedPath;
+
+ // Fallback: resolve the virtual asset path
+ if (packageInfo != null && !string.IsNullOrEmpty(packageInfo.assetPath))
+ return Path.GetFullPath(packageInfo.assetPath);
+
+ return null;
+ }
+ }
+}
diff --git a/MCPForUnity/Editor/Helpers/UIAssetSync.cs.meta b/MCPForUnity/Editor/Helpers/UIAssetSync.cs.meta
new file mode 100644
index 000000000..382ba1f25
--- /dev/null
+++ b/MCPForUnity/Editor/Helpers/UIAssetSync.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: f23b4c1bd875357488d70068da564267
\ No newline at end of file
diff --git a/MCPForUnity/Editor/Tools/BatchExecute.cs b/MCPForUnity/Editor/Tools/BatchExecute.cs
index aca4a1994..eed6759ba 100644
--- a/MCPForUnity/Editor/Tools/BatchExecute.cs
+++ b/MCPForUnity/Editor/Tools/BatchExecute.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
using MCPForUnity.Editor.Constants;
using MCPForUnity.Editor.Helpers;
@@ -51,6 +52,14 @@ public static async Task