#
tokens: 44541/50000 7/263 files (page 7/13)
lines: off (toggle) GitHub
raw markdown copy
This is page 7 of 13. Use http://codebase.md/justinpbarnett/unity-mcp?page={x} to view the full context.

# Directory Structure

```
├── .claude
│   ├── prompts
│   │   ├── nl-unity-suite-nl.md
│   │   └── nl-unity-suite-t.md
│   └── settings.json
├── .github
│   ├── scripts
│   │   └── mark_skipped.py
│   └── workflows
│       ├── bump-version.yml
│       ├── claude-nl-suite.yml
│       ├── github-repo-stats.yml
│       └── unity-tests.yml
├── .gitignore
├── deploy-dev.bat
├── docs
│   ├── CURSOR_HELP.md
│   ├── CUSTOM_TOOLS.md
│   ├── README-DEV-zh.md
│   ├── README-DEV.md
│   ├── screenshots
│   │   ├── v5_01_uninstall.png
│   │   ├── v5_02_install.png
│   │   ├── v5_03_open_mcp_window.png
│   │   ├── v5_04_rebuild_mcp_server.png
│   │   ├── v5_05_rebuild_success.png
│   │   ├── v6_2_create_python_tools_asset.png
│   │   ├── v6_2_python_tools_asset.png
│   │   ├── v6_new_ui_asset_store_version.png
│   │   ├── v6_new_ui_dark.png
│   │   └── v6_new_ui_light.png
│   ├── TELEMETRY.md
│   ├── v5_MIGRATION.md
│   └── v6_NEW_UI_CHANGES.md
├── LICENSE
├── logo.png
├── mcp_source.py
├── MCPForUnity
│   ├── Editor
│   │   ├── AssemblyInfo.cs
│   │   ├── AssemblyInfo.cs.meta
│   │   ├── Data
│   │   │   ├── DefaultServerConfig.cs
│   │   │   ├── DefaultServerConfig.cs.meta
│   │   │   ├── McpClients.cs
│   │   │   ├── McpClients.cs.meta
│   │   │   ├── PythonToolsAsset.cs
│   │   │   └── PythonToolsAsset.cs.meta
│   │   ├── Data.meta
│   │   ├── Dependencies
│   │   │   ├── DependencyManager.cs
│   │   │   ├── DependencyManager.cs.meta
│   │   │   ├── Models
│   │   │   │   ├── DependencyCheckResult.cs
│   │   │   │   ├── DependencyCheckResult.cs.meta
│   │   │   │   ├── DependencyStatus.cs
│   │   │   │   └── DependencyStatus.cs.meta
│   │   │   ├── Models.meta
│   │   │   ├── PlatformDetectors
│   │   │   │   ├── IPlatformDetector.cs
│   │   │   │   ├── IPlatformDetector.cs.meta
│   │   │   │   ├── LinuxPlatformDetector.cs
│   │   │   │   ├── LinuxPlatformDetector.cs.meta
│   │   │   │   ├── MacOSPlatformDetector.cs
│   │   │   │   ├── MacOSPlatformDetector.cs.meta
│   │   │   │   ├── PlatformDetectorBase.cs
│   │   │   │   ├── PlatformDetectorBase.cs.meta
│   │   │   │   ├── WindowsPlatformDetector.cs
│   │   │   │   └── WindowsPlatformDetector.cs.meta
│   │   │   └── PlatformDetectors.meta
│   │   ├── Dependencies.meta
│   │   ├── External
│   │   │   ├── Tommy.cs
│   │   │   └── Tommy.cs.meta
│   │   ├── External.meta
│   │   ├── Helpers
│   │   │   ├── AssetPathUtility.cs
│   │   │   ├── AssetPathUtility.cs.meta
│   │   │   ├── CodexConfigHelper.cs
│   │   │   ├── CodexConfigHelper.cs.meta
│   │   │   ├── ConfigJsonBuilder.cs
│   │   │   ├── ConfigJsonBuilder.cs.meta
│   │   │   ├── ExecPath.cs
│   │   │   ├── ExecPath.cs.meta
│   │   │   ├── GameObjectSerializer.cs
│   │   │   ├── GameObjectSerializer.cs.meta
│   │   │   ├── McpConfigFileHelper.cs
│   │   │   ├── McpConfigFileHelper.cs.meta
│   │   │   ├── McpConfigurationHelper.cs
│   │   │   ├── McpConfigurationHelper.cs.meta
│   │   │   ├── McpLog.cs
│   │   │   ├── McpLog.cs.meta
│   │   │   ├── McpPathResolver.cs
│   │   │   ├── McpPathResolver.cs.meta
│   │   │   ├── PackageDetector.cs
│   │   │   ├── PackageDetector.cs.meta
│   │   │   ├── PackageInstaller.cs
│   │   │   ├── PackageInstaller.cs.meta
│   │   │   ├── PortManager.cs
│   │   │   ├── PortManager.cs.meta
│   │   │   ├── PythonToolSyncProcessor.cs
│   │   │   ├── PythonToolSyncProcessor.cs.meta
│   │   │   ├── Response.cs
│   │   │   ├── Response.cs.meta
│   │   │   ├── ServerInstaller.cs
│   │   │   ├── ServerInstaller.cs.meta
│   │   │   ├── ServerPathResolver.cs
│   │   │   ├── ServerPathResolver.cs.meta
│   │   │   ├── TelemetryHelper.cs
│   │   │   ├── TelemetryHelper.cs.meta
│   │   │   ├── Vector3Helper.cs
│   │   │   └── Vector3Helper.cs.meta
│   │   ├── Helpers.meta
│   │   ├── Importers
│   │   │   ├── PythonFileImporter.cs
│   │   │   └── PythonFileImporter.cs.meta
│   │   ├── Importers.meta
│   │   ├── MCPForUnity.Editor.asmdef
│   │   ├── MCPForUnity.Editor.asmdef.meta
│   │   ├── MCPForUnityBridge.cs
│   │   ├── MCPForUnityBridge.cs.meta
│   │   ├── Models
│   │   │   ├── Command.cs
│   │   │   ├── Command.cs.meta
│   │   │   ├── McpClient.cs
│   │   │   ├── McpClient.cs.meta
│   │   │   ├── McpConfig.cs
│   │   │   ├── McpConfig.cs.meta
│   │   │   ├── MCPConfigServer.cs
│   │   │   ├── MCPConfigServer.cs.meta
│   │   │   ├── MCPConfigServers.cs
│   │   │   ├── MCPConfigServers.cs.meta
│   │   │   ├── McpStatus.cs
│   │   │   ├── McpStatus.cs.meta
│   │   │   ├── McpTypes.cs
│   │   │   ├── McpTypes.cs.meta
│   │   │   ├── ServerConfig.cs
│   │   │   └── ServerConfig.cs.meta
│   │   ├── Models.meta
│   │   ├── Resources
│   │   │   ├── McpForUnityResourceAttribute.cs
│   │   │   ├── McpForUnityResourceAttribute.cs.meta
│   │   │   ├── MenuItems
│   │   │   │   ├── GetMenuItems.cs
│   │   │   │   └── GetMenuItems.cs.meta
│   │   │   ├── MenuItems.meta
│   │   │   ├── Tests
│   │   │   │   ├── GetTests.cs
│   │   │   │   └── GetTests.cs.meta
│   │   │   └── Tests.meta
│   │   ├── Resources.meta
│   │   ├── Services
│   │   │   ├── BridgeControlService.cs
│   │   │   ├── BridgeControlService.cs.meta
│   │   │   ├── ClientConfigurationService.cs
│   │   │   ├── ClientConfigurationService.cs.meta
│   │   │   ├── IBridgeControlService.cs
│   │   │   ├── IBridgeControlService.cs.meta
│   │   │   ├── IClientConfigurationService.cs
│   │   │   ├── IClientConfigurationService.cs.meta
│   │   │   ├── IPackageUpdateService.cs
│   │   │   ├── IPackageUpdateService.cs.meta
│   │   │   ├── IPathResolverService.cs
│   │   │   ├── IPathResolverService.cs.meta
│   │   │   ├── IPythonToolRegistryService.cs
│   │   │   ├── IPythonToolRegistryService.cs.meta
│   │   │   ├── ITestRunnerService.cs
│   │   │   ├── ITestRunnerService.cs.meta
│   │   │   ├── IToolSyncService.cs
│   │   │   ├── IToolSyncService.cs.meta
│   │   │   ├── MCPServiceLocator.cs
│   │   │   ├── MCPServiceLocator.cs.meta
│   │   │   ├── PackageUpdateService.cs
│   │   │   ├── PackageUpdateService.cs.meta
│   │   │   ├── PathResolverService.cs
│   │   │   ├── PathResolverService.cs.meta
│   │   │   ├── PythonToolRegistryService.cs
│   │   │   ├── PythonToolRegistryService.cs.meta
│   │   │   ├── TestRunnerService.cs
│   │   │   ├── TestRunnerService.cs.meta
│   │   │   ├── ToolSyncService.cs
│   │   │   └── ToolSyncService.cs.meta
│   │   ├── Services.meta
│   │   ├── Setup
│   │   │   ├── SetupWizard.cs
│   │   │   ├── SetupWizard.cs.meta
│   │   │   ├── SetupWizardWindow.cs
│   │   │   └── SetupWizardWindow.cs.meta
│   │   ├── Setup.meta
│   │   ├── Tools
│   │   │   ├── CommandRegistry.cs
│   │   │   ├── CommandRegistry.cs.meta
│   │   │   ├── ExecuteMenuItem.cs
│   │   │   ├── ExecuteMenuItem.cs.meta
│   │   │   ├── ManageAsset.cs
│   │   │   ├── ManageAsset.cs.meta
│   │   │   ├── ManageEditor.cs
│   │   │   ├── ManageEditor.cs.meta
│   │   │   ├── ManageGameObject.cs
│   │   │   ├── ManageGameObject.cs.meta
│   │   │   ├── ManageScene.cs
│   │   │   ├── ManageScene.cs.meta
│   │   │   ├── ManageScript.cs
│   │   │   ├── ManageScript.cs.meta
│   │   │   ├── ManageShader.cs
│   │   │   ├── ManageShader.cs.meta
│   │   │   ├── McpForUnityToolAttribute.cs
│   │   │   ├── McpForUnityToolAttribute.cs.meta
│   │   │   ├── Prefabs
│   │   │   │   ├── ManagePrefabs.cs
│   │   │   │   └── ManagePrefabs.cs.meta
│   │   │   ├── Prefabs.meta
│   │   │   ├── ReadConsole.cs
│   │   │   ├── ReadConsole.cs.meta
│   │   │   ├── RunTests.cs
│   │   │   └── RunTests.cs.meta
│   │   ├── Tools.meta
│   │   ├── Windows
│   │   │   ├── ManualConfigEditorWindow.cs
│   │   │   ├── ManualConfigEditorWindow.cs.meta
│   │   │   ├── MCPForUnityEditorWindow.cs
│   │   │   ├── MCPForUnityEditorWindow.cs.meta
│   │   │   ├── MCPForUnityEditorWindowNew.cs
│   │   │   ├── MCPForUnityEditorWindowNew.cs.meta
│   │   │   ├── MCPForUnityEditorWindowNew.uss
│   │   │   ├── MCPForUnityEditorWindowNew.uss.meta
│   │   │   ├── MCPForUnityEditorWindowNew.uxml
│   │   │   ├── MCPForUnityEditorWindowNew.uxml.meta
│   │   │   ├── VSCodeManualSetupWindow.cs
│   │   │   └── VSCodeManualSetupWindow.cs.meta
│   │   └── Windows.meta
│   ├── Editor.meta
│   ├── package.json
│   ├── package.json.meta
│   ├── README.md
│   ├── README.md.meta
│   ├── Runtime
│   │   ├── MCPForUnity.Runtime.asmdef
│   │   ├── MCPForUnity.Runtime.asmdef.meta
│   │   ├── Serialization
│   │   │   ├── UnityTypeConverters.cs
│   │   │   └── UnityTypeConverters.cs.meta
│   │   └── Serialization.meta
│   ├── Runtime.meta
│   └── UnityMcpServer~
│       └── src
│           ├── __init__.py
│           ├── config.py
│           ├── Dockerfile
│           ├── models.py
│           ├── module_discovery.py
│           ├── port_discovery.py
│           ├── pyproject.toml
│           ├── pyrightconfig.json
│           ├── registry
│           │   ├── __init__.py
│           │   ├── resource_registry.py
│           │   └── tool_registry.py
│           ├── reload_sentinel.py
│           ├── resources
│           │   ├── __init__.py
│           │   ├── menu_items.py
│           │   └── tests.py
│           ├── server_version.txt
│           ├── server.py
│           ├── telemetry_decorator.py
│           ├── telemetry.py
│           ├── test_telemetry.py
│           ├── tools
│           │   ├── __init__.py
│           │   ├── execute_menu_item.py
│           │   ├── manage_asset.py
│           │   ├── manage_editor.py
│           │   ├── manage_gameobject.py
│           │   ├── manage_prefabs.py
│           │   ├── manage_scene.py
│           │   ├── manage_script.py
│           │   ├── manage_shader.py
│           │   ├── read_console.py
│           │   ├── resource_tools.py
│           │   ├── run_tests.py
│           │   └── script_apply_edits.py
│           ├── unity_connection.py
│           └── uv.lock
├── prune_tool_results.py
├── README-zh.md
├── README.md
├── restore-dev.bat
├── scripts
│   └── validate-nlt-coverage.sh
├── test_unity_socket_framing.py
├── TestProjects
│   └── UnityMCPTests
│       ├── .gitignore
│       ├── Assets
│       │   ├── Editor.meta
│       │   ├── Scenes
│       │   │   ├── SampleScene.unity
│       │   │   └── SampleScene.unity.meta
│       │   ├── Scenes.meta
│       │   ├── Scripts
│       │   │   ├── Hello.cs
│       │   │   ├── Hello.cs.meta
│       │   │   ├── LongUnityScriptClaudeTest.cs
│       │   │   ├── LongUnityScriptClaudeTest.cs.meta
│       │   │   ├── TestAsmdef
│       │   │   │   ├── CustomComponent.cs
│       │   │   │   ├── CustomComponent.cs.meta
│       │   │   │   ├── TestAsmdef.asmdef
│       │   │   │   └── TestAsmdef.asmdef.meta
│       │   │   └── TestAsmdef.meta
│       │   ├── Scripts.meta
│       │   ├── Tests
│       │   │   ├── EditMode
│       │   │   │   ├── Data
│       │   │   │   │   ├── PythonToolsAssetTests.cs
│       │   │   │   │   └── PythonToolsAssetTests.cs.meta
│       │   │   │   ├── Data.meta
│       │   │   │   ├── Helpers
│       │   │   │   │   ├── CodexConfigHelperTests.cs
│       │   │   │   │   ├── CodexConfigHelperTests.cs.meta
│       │   │   │   │   ├── WriteToConfigTests.cs
│       │   │   │   │   └── WriteToConfigTests.cs.meta
│       │   │   │   ├── Helpers.meta
│       │   │   │   ├── MCPForUnityTests.Editor.asmdef
│       │   │   │   ├── MCPForUnityTests.Editor.asmdef.meta
│       │   │   │   ├── Resources
│       │   │   │   │   ├── GetMenuItemsTests.cs
│       │   │   │   │   └── GetMenuItemsTests.cs.meta
│       │   │   │   ├── Resources.meta
│       │   │   │   ├── Services
│       │   │   │   │   ├── PackageUpdateServiceTests.cs
│       │   │   │   │   ├── PackageUpdateServiceTests.cs.meta
│       │   │   │   │   ├── PythonToolRegistryServiceTests.cs
│       │   │   │   │   ├── PythonToolRegistryServiceTests.cs.meta
│       │   │   │   │   ├── ToolSyncServiceTests.cs
│       │   │   │   │   └── ToolSyncServiceTests.cs.meta
│       │   │   │   ├── Services.meta
│       │   │   │   ├── Tools
│       │   │   │   │   ├── AIPropertyMatchingTests.cs
│       │   │   │   │   ├── AIPropertyMatchingTests.cs.meta
│       │   │   │   │   ├── CommandRegistryTests.cs
│       │   │   │   │   ├── CommandRegistryTests.cs.meta
│       │   │   │   │   ├── ComponentResolverTests.cs
│       │   │   │   │   ├── ComponentResolverTests.cs.meta
│       │   │   │   │   ├── ExecuteMenuItemTests.cs
│       │   │   │   │   ├── ExecuteMenuItemTests.cs.meta
│       │   │   │   │   ├── ManageGameObjectTests.cs
│       │   │   │   │   ├── ManageGameObjectTests.cs.meta
│       │   │   │   │   ├── ManagePrefabsTests.cs
│       │   │   │   │   ├── ManagePrefabsTests.cs.meta
│       │   │   │   │   ├── ManageScriptValidationTests.cs
│       │   │   │   │   └── ManageScriptValidationTests.cs.meta
│       │   │   │   ├── Tools.meta
│       │   │   │   ├── Windows
│       │   │   │   │   ├── ManualConfigJsonBuilderTests.cs
│       │   │   │   │   └── ManualConfigJsonBuilderTests.cs.meta
│       │   │   │   └── Windows.meta
│       │   │   └── EditMode.meta
│       │   └── Tests.meta
│       ├── Packages
│       │   └── manifest.json
│       └── ProjectSettings
│           ├── Packages
│           │   └── com.unity.testtools.codecoverage
│           │       └── Settings.json
│           └── ProjectVersion.txt
├── tests
│   ├── conftest.py
│   ├── test_edit_normalization_and_noop.py
│   ├── test_edit_strict_and_warnings.py
│   ├── test_find_in_file_minimal.py
│   ├── test_get_sha.py
│   ├── test_improved_anchor_matching.py
│   ├── test_logging_stdout.py
│   ├── test_manage_script_uri.py
│   ├── test_read_console_truncate.py
│   ├── test_read_resource_minimal.py
│   ├── test_resources_api.py
│   ├── test_script_editing.py
│   ├── test_script_tools.py
│   ├── test_telemetry_endpoint_validation.py
│   ├── test_telemetry_queue_worker.py
│   ├── test_telemetry_subaction.py
│   ├── test_transport_framing.py
│   └── test_validate_script_summary.py
├── tools
│   └── stress_mcp.py
└── UnityMcpBridge
    ├── Editor
    │   ├── AssemblyInfo.cs
    │   ├── AssemblyInfo.cs.meta
    │   ├── Data
    │   │   ├── DefaultServerConfig.cs
    │   │   ├── DefaultServerConfig.cs.meta
    │   │   ├── McpClients.cs
    │   │   └── McpClients.cs.meta
    │   ├── Data.meta
    │   ├── Dependencies
    │   │   ├── DependencyManager.cs
    │   │   ├── DependencyManager.cs.meta
    │   │   ├── Models
    │   │   │   ├── DependencyCheckResult.cs
    │   │   │   ├── DependencyCheckResult.cs.meta
    │   │   │   ├── DependencyStatus.cs
    │   │   │   └── DependencyStatus.cs.meta
    │   │   ├── Models.meta
    │   │   ├── PlatformDetectors
    │   │   │   ├── IPlatformDetector.cs
    │   │   │   ├── IPlatformDetector.cs.meta
    │   │   │   ├── LinuxPlatformDetector.cs
    │   │   │   ├── LinuxPlatformDetector.cs.meta
    │   │   │   ├── MacOSPlatformDetector.cs
    │   │   │   ├── MacOSPlatformDetector.cs.meta
    │   │   │   ├── PlatformDetectorBase.cs
    │   │   │   ├── PlatformDetectorBase.cs.meta
    │   │   │   ├── WindowsPlatformDetector.cs
    │   │   │   └── WindowsPlatformDetector.cs.meta
    │   │   └── PlatformDetectors.meta
    │   ├── Dependencies.meta
    │   ├── External
    │   │   ├── Tommy.cs
    │   │   └── Tommy.cs.meta
    │   ├── External.meta
    │   ├── Helpers
    │   │   ├── AssetPathUtility.cs
    │   │   ├── AssetPathUtility.cs.meta
    │   │   ├── CodexConfigHelper.cs
    │   │   ├── CodexConfigHelper.cs.meta
    │   │   ├── ConfigJsonBuilder.cs
    │   │   ├── ConfigJsonBuilder.cs.meta
    │   │   ├── ExecPath.cs
    │   │   ├── ExecPath.cs.meta
    │   │   ├── GameObjectSerializer.cs
    │   │   ├── GameObjectSerializer.cs.meta
    │   │   ├── McpConfigFileHelper.cs
    │   │   ├── McpConfigFileHelper.cs.meta
    │   │   ├── McpConfigurationHelper.cs
    │   │   ├── McpConfigurationHelper.cs.meta
    │   │   ├── McpLog.cs
    │   │   ├── McpLog.cs.meta
    │   │   ├── McpPathResolver.cs
    │   │   ├── McpPathResolver.cs.meta
    │   │   ├── PackageDetector.cs
    │   │   ├── PackageDetector.cs.meta
    │   │   ├── PackageInstaller.cs
    │   │   ├── PackageInstaller.cs.meta
    │   │   ├── PortManager.cs
    │   │   ├── PortManager.cs.meta
    │   │   ├── Response.cs
    │   │   ├── Response.cs.meta
    │   │   ├── ServerInstaller.cs
    │   │   ├── ServerInstaller.cs.meta
    │   │   ├── ServerPathResolver.cs
    │   │   ├── ServerPathResolver.cs.meta
    │   │   ├── TelemetryHelper.cs
    │   │   ├── TelemetryHelper.cs.meta
    │   │   ├── Vector3Helper.cs
    │   │   └── Vector3Helper.cs.meta
    │   ├── Helpers.meta
    │   ├── MCPForUnity.Editor.asmdef
    │   ├── MCPForUnity.Editor.asmdef.meta
    │   ├── MCPForUnityBridge.cs
    │   ├── MCPForUnityBridge.cs.meta
    │   ├── Models
    │   │   ├── Command.cs
    │   │   ├── Command.cs.meta
    │   │   ├── McpClient.cs
    │   │   ├── McpClient.cs.meta
    │   │   ├── McpConfig.cs
    │   │   ├── McpConfig.cs.meta
    │   │   ├── MCPConfigServer.cs
    │   │   ├── MCPConfigServer.cs.meta
    │   │   ├── MCPConfigServers.cs
    │   │   ├── MCPConfigServers.cs.meta
    │   │   ├── McpStatus.cs
    │   │   ├── McpStatus.cs.meta
    │   │   ├── McpTypes.cs
    │   │   ├── McpTypes.cs.meta
    │   │   ├── ServerConfig.cs
    │   │   └── ServerConfig.cs.meta
    │   ├── Models.meta
    │   ├── Setup
    │   │   ├── SetupWizard.cs
    │   │   ├── SetupWizard.cs.meta
    │   │   ├── SetupWizardWindow.cs
    │   │   └── SetupWizardWindow.cs.meta
    │   ├── Setup.meta
    │   ├── Tools
    │   │   ├── CommandRegistry.cs
    │   │   ├── CommandRegistry.cs.meta
    │   │   ├── ManageAsset.cs
    │   │   ├── ManageAsset.cs.meta
    │   │   ├── ManageEditor.cs
    │   │   ├── ManageEditor.cs.meta
    │   │   ├── ManageGameObject.cs
    │   │   ├── ManageGameObject.cs.meta
    │   │   ├── ManageScene.cs
    │   │   ├── ManageScene.cs.meta
    │   │   ├── ManageScript.cs
    │   │   ├── ManageScript.cs.meta
    │   │   ├── ManageShader.cs
    │   │   ├── ManageShader.cs.meta
    │   │   ├── McpForUnityToolAttribute.cs
    │   │   ├── McpForUnityToolAttribute.cs.meta
    │   │   ├── MenuItems
    │   │   │   ├── ManageMenuItem.cs
    │   │   │   ├── ManageMenuItem.cs.meta
    │   │   │   ├── MenuItemExecutor.cs
    │   │   │   ├── MenuItemExecutor.cs.meta
    │   │   │   ├── MenuItemsReader.cs
    │   │   │   └── MenuItemsReader.cs.meta
    │   │   ├── MenuItems.meta
    │   │   ├── Prefabs
    │   │   │   ├── ManagePrefabs.cs
    │   │   │   └── ManagePrefabs.cs.meta
    │   │   ├── Prefabs.meta
    │   │   ├── ReadConsole.cs
    │   │   └── ReadConsole.cs.meta
    │   ├── Tools.meta
    │   ├── Windows
    │   │   ├── ManualConfigEditorWindow.cs
    │   │   ├── ManualConfigEditorWindow.cs.meta
    │   │   ├── MCPForUnityEditorWindow.cs
    │   │   ├── MCPForUnityEditorWindow.cs.meta
    │   │   ├── VSCodeManualSetupWindow.cs
    │   │   └── VSCodeManualSetupWindow.cs.meta
    │   └── Windows.meta
    ├── Editor.meta
    ├── package.json
    ├── package.json.meta
    ├── README.md
    ├── README.md.meta
    ├── Runtime
    │   ├── MCPForUnity.Runtime.asmdef
    │   ├── MCPForUnity.Runtime.asmdef.meta
    │   ├── Serialization
    │   │   ├── UnityTypeConverters.cs
    │   │   └── UnityTypeConverters.cs.meta
    │   └── Serialization.meta
    ├── Runtime.meta
    └── UnityMcpServer~
        └── src
            ├── __init__.py
            ├── config.py
            ├── Dockerfile
            ├── port_discovery.py
            ├── pyproject.toml
            ├── pyrightconfig.json
            ├── registry
            │   ├── __init__.py
            │   └── tool_registry.py
            ├── reload_sentinel.py
            ├── server_version.txt
            ├── server.py
            ├── telemetry_decorator.py
            ├── telemetry.py
            ├── test_telemetry.py
            ├── tools
            │   ├── __init__.py
            │   ├── manage_asset.py
            │   ├── manage_editor.py
            │   ├── manage_gameobject.py
            │   ├── manage_menu_item.py
            │   ├── manage_prefabs.py
            │   ├── manage_scene.py
            │   ├── manage_script.py
            │   ├── manage_shader.py
            │   ├── read_console.py
            │   ├── resource_tools.py
            │   └── script_apply_edits.py
            ├── unity_connection.py
            └── uv.lock
```

# Files

--------------------------------------------------------------------------------
/UnityMcpBridge/Editor/Tools/ManageEditor.cs:
--------------------------------------------------------------------------------

```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using Newtonsoft.Json.Linq;
using UnityEditor;
using UnityEditorInternal; // Required for tag management
using UnityEditor.SceneManagement;
using UnityEngine;
using MCPForUnity.Editor.Helpers;

namespace MCPForUnity.Editor.Tools
{
    /// <summary>
    /// Handles operations related to controlling and querying the Unity Editor state,
    /// including managing Tags and Layers.
    /// </summary>
    [McpForUnityTool("manage_editor")]
    public static class ManageEditor
    {
        // Constant for starting user layer index
        private const int FirstUserLayerIndex = 8;

        // Constant for total layer count
        private const int TotalLayerCount = 32;

        /// <summary>
        /// Main handler for editor management actions.
        /// </summary>
        public static object HandleCommand(JObject @params)
        {
            string action = @params["action"]?.ToString().ToLower();
            // Parameters for specific actions
            string tagName = @params["tagName"]?.ToString();
            string layerName = @params["layerName"]?.ToString();
            bool waitForCompletion = @params["waitForCompletion"]?.ToObject<bool>() ?? false; // Example - not used everywhere

            if (string.IsNullOrEmpty(action))
            {
                return Response.Error("Action parameter is required.");
            }

            // Route action
            switch (action)
            {
                // Play Mode Control
                case "play":
                    try
                    {
                        if (!EditorApplication.isPlaying)
                        {
                            EditorApplication.isPlaying = true;
                            return Response.Success("Entered play mode.");
                        }
                        return Response.Success("Already in play mode.");
                    }
                    catch (Exception e)
                    {
                        return Response.Error($"Error entering play mode: {e.Message}");
                    }
                case "pause":
                    try
                    {
                        if (EditorApplication.isPlaying)
                        {
                            EditorApplication.isPaused = !EditorApplication.isPaused;
                            return Response.Success(
                                EditorApplication.isPaused ? "Game paused." : "Game resumed."
                            );
                        }
                        return Response.Error("Cannot pause/resume: Not in play mode.");
                    }
                    catch (Exception e)
                    {
                        return Response.Error($"Error pausing/resuming game: {e.Message}");
                    }
                case "stop":
                    try
                    {
                        if (EditorApplication.isPlaying)
                        {
                            EditorApplication.isPlaying = false;
                            return Response.Success("Exited play mode.");
                        }
                        return Response.Success("Already stopped (not in play mode).");
                    }
                    catch (Exception e)
                    {
                        return Response.Error($"Error stopping play mode: {e.Message}");
                    }

                // Editor State/Info
                case "get_state":
                    return GetEditorState();
                case "get_project_root":
                    return GetProjectRoot();
                case "get_windows":
                    return GetEditorWindows();
                case "get_active_tool":
                    return GetActiveTool();
                case "get_selection":
                    return GetSelection();
                case "get_prefab_stage":
                    return GetPrefabStageInfo();
                case "set_active_tool":
                    string toolName = @params["toolName"]?.ToString();
                    if (string.IsNullOrEmpty(toolName))
                        return Response.Error("'toolName' parameter required for set_active_tool.");
                    return SetActiveTool(toolName);

                // Tag Management
                case "add_tag":
                    if (string.IsNullOrEmpty(tagName))
                        return Response.Error("'tagName' parameter required for add_tag.");
                    return AddTag(tagName);
                case "remove_tag":
                    if (string.IsNullOrEmpty(tagName))
                        return Response.Error("'tagName' parameter required for remove_tag.");
                    return RemoveTag(tagName);
                case "get_tags":
                    return GetTags(); // Helper to list current tags

                // Layer Management
                case "add_layer":
                    if (string.IsNullOrEmpty(layerName))
                        return Response.Error("'layerName' parameter required for add_layer.");
                    return AddLayer(layerName);
                case "remove_layer":
                    if (string.IsNullOrEmpty(layerName))
                        return Response.Error("'layerName' parameter required for remove_layer.");
                    return RemoveLayer(layerName);
                case "get_layers":
                    return GetLayers(); // Helper to list current layers

                // --- Settings (Example) ---
                // case "set_resolution":
                //     int? width = @params["width"]?.ToObject<int?>();
                //     int? height = @params["height"]?.ToObject<int?>();
                //     if (!width.HasValue || !height.HasValue) return Response.Error("'width' and 'height' parameters required.");
                //     return SetGameViewResolution(width.Value, height.Value);
                // case "set_quality":
                //     // Handle string name or int index
                //     return SetQualityLevel(@params["qualityLevel"]);

                default:
                    return Response.Error(
                        $"Unknown action: '{action}'. Supported actions include play, pause, stop, get_state, get_project_root, get_windows, get_active_tool, get_selection, get_prefab_stage, set_active_tool, add_tag, remove_tag, get_tags, add_layer, remove_layer, get_layers."
                    );
            }
        }

        // --- Editor State/Info Methods ---
        private static object GetEditorState()
        {
            try
            {
                var state = new
                {
                    isPlaying = EditorApplication.isPlaying,
                    isPaused = EditorApplication.isPaused,
                    isCompiling = EditorApplication.isCompiling,
                    isUpdating = EditorApplication.isUpdating,
                    applicationPath = EditorApplication.applicationPath,
                    applicationContentsPath = EditorApplication.applicationContentsPath,
                    timeSinceStartup = EditorApplication.timeSinceStartup,
                };
                return Response.Success("Retrieved editor state.", state);
            }
            catch (Exception e)
            {
                return Response.Error($"Error getting editor state: {e.Message}");
            }
        }

        private static object GetProjectRoot()
        {
            try
            {
                // Application.dataPath points to <Project>/Assets
                string assetsPath = Application.dataPath.Replace('\\', '/');
                string projectRoot = Directory.GetParent(assetsPath)?.FullName.Replace('\\', '/');
                if (string.IsNullOrEmpty(projectRoot))
                {
                    return Response.Error("Could not determine project root from Application.dataPath");
                }
                return Response.Success("Project root resolved.", new { projectRoot });
            }
            catch (Exception e)
            {
                return Response.Error($"Error getting project root: {e.Message}");
            }
        }

        private static object GetEditorWindows()
        {
            try
            {
                // Get all types deriving from EditorWindow
                var windowTypes = AppDomain
                    .CurrentDomain.GetAssemblies()
                    .SelectMany(assembly => assembly.GetTypes())
                    .Where(type => type.IsSubclassOf(typeof(EditorWindow)))
                    .ToList();

                var openWindows = new List<object>();

                // Find currently open instances
                // Resources.FindObjectsOfTypeAll seems more reliable than GetWindow for finding *all* open windows
                EditorWindow[] allWindows = Resources.FindObjectsOfTypeAll<EditorWindow>();

                foreach (EditorWindow window in allWindows)
                {
                    if (window == null)
                        continue; // Skip potentially destroyed windows

                    try
                    {
                        openWindows.Add(
                            new
                            {
                                title = window.titleContent.text,
                                typeName = window.GetType().FullName,
                                isFocused = EditorWindow.focusedWindow == window,
                                position = new
                                {
                                    x = window.position.x,
                                    y = window.position.y,
                                    width = window.position.width,
                                    height = window.position.height,
                                },
                                instanceID = window.GetInstanceID(),
                            }
                        );
                    }
                    catch (Exception ex)
                    {
                        Debug.LogWarning(
                            $"Could not get info for window {window.GetType().Name}: {ex.Message}"
                        );
                    }
                }

                return Response.Success("Retrieved list of open editor windows.", openWindows);
            }
            catch (Exception e)
            {
                return Response.Error($"Error getting editor windows: {e.Message}");
            }
        }

        private static object GetPrefabStageInfo()
        {
            try
            {
                PrefabStage stage = PrefabStageUtility.GetCurrentPrefabStage();
                if (stage == null)
                {
                    return Response.Success
                    ("No prefab stage is currently open.", new { isOpen = false });
                }

                return Response.Success(
                    "Prefab stage info retrieved.",
                    new
                    {
                        isOpen = true,
                        assetPath = stage.assetPath,
                        prefabRootName = stage.prefabContentsRoot != null ? stage.prefabContentsRoot.name : null,
                        mode = stage.mode.ToString(),
                        isDirty = stage.scene.isDirty
                    }
                );
            }
            catch (Exception e)
            {
                return Response.Error($"Error getting prefab stage info: {e.Message}");
            }
        }

        private static object GetActiveTool()
        {
            try
            {
                Tool currentTool = UnityEditor.Tools.current;
                string toolName = currentTool.ToString(); // Enum to string
                bool customToolActive = UnityEditor.Tools.current == Tool.Custom; // Check if a custom tool is active
                string activeToolName = customToolActive
                    ? EditorTools.GetActiveToolName()
                    : toolName; // Get custom name if needed

                var toolInfo = new
                {
                    activeTool = activeToolName,
                    isCustom = customToolActive,
                    pivotMode = UnityEditor.Tools.pivotMode.ToString(),
                    pivotRotation = UnityEditor.Tools.pivotRotation.ToString(),
                    handleRotation = UnityEditor.Tools.handleRotation.eulerAngles, // Euler for simplicity
                    handlePosition = UnityEditor.Tools.handlePosition,
                };

                return Response.Success("Retrieved active tool information.", toolInfo);
            }
            catch (Exception e)
            {
                return Response.Error($"Error getting active tool: {e.Message}");
            }
        }

        private static object SetActiveTool(string toolName)
        {
            try
            {
                Tool targetTool;
                if (Enum.TryParse<Tool>(toolName, true, out targetTool)) // Case-insensitive parse
                {
                    // Check if it's a valid built-in tool
                    if (targetTool != Tool.None && targetTool <= Tool.Custom) // Tool.Custom is the last standard tool
                    {
                        UnityEditor.Tools.current = targetTool;
                        return Response.Success($"Set active tool to '{targetTool}'.");
                    }
                    else
                    {
                        return Response.Error(
                            $"Cannot directly set tool to '{toolName}'. It might be None, Custom, or invalid."
                        );
                    }
                }
                else
                {
                    // Potentially try activating a custom tool by name here if needed
                    // This often requires specific editor scripting knowledge for that tool.
                    return Response.Error(
                        $"Could not parse '{toolName}' as a standard Unity Tool (View, Move, Rotate, Scale, Rect, Transform, Custom)."
                    );
                }
            }
            catch (Exception e)
            {
                return Response.Error($"Error setting active tool: {e.Message}");
            }
        }

        private static object GetSelection()
        {
            try
            {
                var selectionInfo = new
                {
                    activeObject = Selection.activeObject?.name,
                    activeGameObject = Selection.activeGameObject?.name,
                    activeTransform = Selection.activeTransform?.name,
                    activeInstanceID = Selection.activeInstanceID,
                    count = Selection.count,
                    objects = Selection
                        .objects.Select(obj => new
                        {
                            name = obj?.name,
                            type = obj?.GetType().FullName,
                            instanceID = obj?.GetInstanceID(),
                        })
                        .ToList(),
                    gameObjects = Selection
                        .gameObjects.Select(go => new
                        {
                            name = go?.name,
                            instanceID = go?.GetInstanceID(),
                        })
                        .ToList(),
                    assetGUIDs = Selection.assetGUIDs, // GUIDs for selected assets in Project view
                };

                return Response.Success("Retrieved current selection details.", selectionInfo);
            }
            catch (Exception e)
            {
                return Response.Error($"Error getting selection: {e.Message}");
            }
        }

        // --- Tag Management Methods ---

        private static object AddTag(string tagName)
        {
            if (string.IsNullOrWhiteSpace(tagName))
                return Response.Error("Tag name cannot be empty or whitespace.");

            // Check if tag already exists
            if (InternalEditorUtility.tags.Contains(tagName))
            {
                return Response.Error($"Tag '{tagName}' already exists.");
            }

            try
            {
                // Add the tag using the internal utility
                InternalEditorUtility.AddTag(tagName);
                // Force save assets to ensure the change persists in the TagManager asset
                AssetDatabase.SaveAssets();
                return Response.Success($"Tag '{tagName}' added successfully.");
            }
            catch (Exception e)
            {
                return Response.Error($"Failed to add tag '{tagName}': {e.Message}");
            }
        }

        private static object RemoveTag(string tagName)
        {
            if (string.IsNullOrWhiteSpace(tagName))
                return Response.Error("Tag name cannot be empty or whitespace.");
            if (tagName.Equals("Untagged", StringComparison.OrdinalIgnoreCase))
                return Response.Error("Cannot remove the built-in 'Untagged' tag.");

            // Check if tag exists before attempting removal
            if (!InternalEditorUtility.tags.Contains(tagName))
            {
                return Response.Error($"Tag '{tagName}' does not exist.");
            }

            try
            {
                // Remove the tag using the internal utility
                InternalEditorUtility.RemoveTag(tagName);
                // Force save assets
                AssetDatabase.SaveAssets();
                return Response.Success($"Tag '{tagName}' removed successfully.");
            }
            catch (Exception e)
            {
                // Catch potential issues if the tag is somehow in use or removal fails
                return Response.Error($"Failed to remove tag '{tagName}': {e.Message}");
            }
        }

        private static object GetTags()
        {
            try
            {
                string[] tags = InternalEditorUtility.tags;
                return Response.Success("Retrieved current tags.", tags);
            }
            catch (Exception e)
            {
                return Response.Error($"Failed to retrieve tags: {e.Message}");
            }
        }

        // --- Layer Management Methods ---

        private static object AddLayer(string layerName)
        {
            if (string.IsNullOrWhiteSpace(layerName))
                return Response.Error("Layer name cannot be empty or whitespace.");

            // Access the TagManager asset
            SerializedObject tagManager = GetTagManager();
            if (tagManager == null)
                return Response.Error("Could not access TagManager asset.");

            SerializedProperty layersProp = tagManager.FindProperty("layers");
            if (layersProp == null || !layersProp.isArray)
                return Response.Error("Could not find 'layers' property in TagManager.");

            // Check if layer name already exists (case-insensitive check recommended)
            for (int i = 0; i < TotalLayerCount; i++)
            {
                SerializedProperty layerSP = layersProp.GetArrayElementAtIndex(i);
                if (
                    layerSP != null
                    && layerName.Equals(layerSP.stringValue, StringComparison.OrdinalIgnoreCase)
                )
                {
                    return Response.Error($"Layer '{layerName}' already exists at index {i}.");
                }
            }

            // Find the first empty user layer slot (indices 8 to 31)
            int firstEmptyUserLayer = -1;
            for (int i = FirstUserLayerIndex; i < TotalLayerCount; i++)
            {
                SerializedProperty layerSP = layersProp.GetArrayElementAtIndex(i);
                if (layerSP != null && string.IsNullOrEmpty(layerSP.stringValue))
                {
                    firstEmptyUserLayer = i;
                    break;
                }
            }

            if (firstEmptyUserLayer == -1)
            {
                return Response.Error("No empty User Layer slots available (8-31 are full).");
            }

            // Assign the name to the found slot
            try
            {
                SerializedProperty targetLayerSP = layersProp.GetArrayElementAtIndex(
                    firstEmptyUserLayer
                );
                targetLayerSP.stringValue = layerName;
                // Apply the changes to the TagManager asset
                tagManager.ApplyModifiedProperties();
                // Save assets to make sure it's written to disk
                AssetDatabase.SaveAssets();
                return Response.Success(
                    $"Layer '{layerName}' added successfully to slot {firstEmptyUserLayer}."
                );
            }
            catch (Exception e)
            {
                return Response.Error($"Failed to add layer '{layerName}': {e.Message}");
            }
        }

        private static object RemoveLayer(string layerName)
        {
            if (string.IsNullOrWhiteSpace(layerName))
                return Response.Error("Layer name cannot be empty or whitespace.");

            // Access the TagManager asset
            SerializedObject tagManager = GetTagManager();
            if (tagManager == null)
                return Response.Error("Could not access TagManager asset.");

            SerializedProperty layersProp = tagManager.FindProperty("layers");
            if (layersProp == null || !layersProp.isArray)
                return Response.Error("Could not find 'layers' property in TagManager.");

            // Find the layer by name (must be user layer)
            int layerIndexToRemove = -1;
            for (int i = FirstUserLayerIndex; i < TotalLayerCount; i++) // Start from user layers
            {
                SerializedProperty layerSP = layersProp.GetArrayElementAtIndex(i);
                // Case-insensitive comparison is safer
                if (
                    layerSP != null
                    && layerName.Equals(layerSP.stringValue, StringComparison.OrdinalIgnoreCase)
                )
                {
                    layerIndexToRemove = i;
                    break;
                }
            }

            if (layerIndexToRemove == -1)
            {
                return Response.Error($"User layer '{layerName}' not found.");
            }

            // Clear the name for that index
            try
            {
                SerializedProperty targetLayerSP = layersProp.GetArrayElementAtIndex(
                    layerIndexToRemove
                );
                targetLayerSP.stringValue = string.Empty; // Set to empty string to remove
                // Apply the changes
                tagManager.ApplyModifiedProperties();
                // Save assets
                AssetDatabase.SaveAssets();
                return Response.Success(
                    $"Layer '{layerName}' (slot {layerIndexToRemove}) removed successfully."
                );
            }
            catch (Exception e)
            {
                return Response.Error($"Failed to remove layer '{layerName}': {e.Message}");
            }
        }

        private static object GetLayers()
        {
            try
            {
                var layers = new Dictionary<int, string>();
                for (int i = 0; i < TotalLayerCount; i++)
                {
                    string layerName = LayerMask.LayerToName(i);
                    if (!string.IsNullOrEmpty(layerName)) // Only include layers that have names
                    {
                        layers.Add(i, layerName);
                    }
                }
                return Response.Success("Retrieved current named layers.", layers);
            }
            catch (Exception e)
            {
                return Response.Error($"Failed to retrieve layers: {e.Message}");
            }
        }

        // --- Helper Methods ---

        /// <summary>
        /// Gets the SerializedObject for the TagManager asset.
        /// </summary>
        private static SerializedObject GetTagManager()
        {
            try
            {
                // Load the TagManager asset from the ProjectSettings folder
                UnityEngine.Object[] tagManagerAssets = AssetDatabase.LoadAllAssetsAtPath(
                    "ProjectSettings/TagManager.asset"
                );
                if (tagManagerAssets == null || tagManagerAssets.Length == 0)
                {
                    Debug.LogError("[ManageEditor] TagManager.asset not found in ProjectSettings.");
                    return null;
                }
                // The first object in the asset file should be the TagManager
                return new SerializedObject(tagManagerAssets[0]);
            }
            catch (Exception e)
            {
                Debug.LogError($"[ManageEditor] Error accessing TagManager.asset: {e.Message}");
                return null;
            }
        }

        // --- Example Implementations for Settings ---
        /*
        private static object SetGameViewResolution(int width, int height) { ... }
        private static object SetQualityLevel(JToken qualityLevelToken) { ... }
        */
    }

    // Helper class to get custom tool names (remains the same)
    internal static class EditorTools
    {
        public static string GetActiveToolName()
        {
            // This is a placeholder. Real implementation depends on how custom tools
            // are registered and tracked in the specific Unity project setup.
            // It might involve checking static variables, calling methods on specific tool managers, etc.
            if (UnityEditor.Tools.current == Tool.Custom)
            {
                // Example: Check a known custom tool manager
                // if (MyCustomToolManager.IsActive) return MyCustomToolManager.ActiveToolName;
                return "Unknown Custom Tool";
            }
            return UnityEditor.Tools.current.ToString();
        }
    }
}

```

--------------------------------------------------------------------------------
/MCPForUnity/Editor/Tools/ManageEditor.cs:
--------------------------------------------------------------------------------

```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using Newtonsoft.Json.Linq;
using UnityEditor;
using UnityEditorInternal; // Required for tag management
using UnityEditor.SceneManagement;
using UnityEngine;
using MCPForUnity.Editor.Helpers;

namespace MCPForUnity.Editor.Tools
{
    /// <summary>
    /// Handles operations related to controlling and querying the Unity Editor state,
    /// including managing Tags and Layers.
    /// </summary>
    [McpForUnityTool("manage_editor")]
    public static class ManageEditor
    {
        // Constant for starting user layer index
        private const int FirstUserLayerIndex = 8;

        // Constant for total layer count
        private const int TotalLayerCount = 32;

        /// <summary>
        /// Main handler for editor management actions.
        /// </summary>
        public static object HandleCommand(JObject @params)
        {
            string action = @params["action"]?.ToString().ToLower();
            // Parameters for specific actions
            string tagName = @params["tagName"]?.ToString();
            string layerName = @params["layerName"]?.ToString();
            bool waitForCompletion = @params["waitForCompletion"]?.ToObject<bool>() ?? false; // Example - not used everywhere

            if (string.IsNullOrEmpty(action))
            {
                return Response.Error("Action parameter is required.");
            }

            // Route action
            switch (action)
            {
                // Play Mode Control
                case "play":
                    try
                    {
                        if (!EditorApplication.isPlaying)
                        {
                            EditorApplication.isPlaying = true;
                            return Response.Success("Entered play mode.");
                        }
                        return Response.Success("Already in play mode.");
                    }
                    catch (Exception e)
                    {
                        return Response.Error($"Error entering play mode: {e.Message}");
                    }
                case "pause":
                    try
                    {
                        if (EditorApplication.isPlaying)
                        {
                            EditorApplication.isPaused = !EditorApplication.isPaused;
                            return Response.Success(
                                EditorApplication.isPaused ? "Game paused." : "Game resumed."
                            );
                        }
                        return Response.Error("Cannot pause/resume: Not in play mode.");
                    }
                    catch (Exception e)
                    {
                        return Response.Error($"Error pausing/resuming game: {e.Message}");
                    }
                case "stop":
                    try
                    {
                        if (EditorApplication.isPlaying)
                        {
                            EditorApplication.isPlaying = false;
                            return Response.Success("Exited play mode.");
                        }
                        return Response.Success("Already stopped (not in play mode).");
                    }
                    catch (Exception e)
                    {
                        return Response.Error($"Error stopping play mode: {e.Message}");
                    }

                // Editor State/Info
                case "get_state":
                    return GetEditorState();
                case "get_project_root":
                    return GetProjectRoot();
                case "get_windows":
                    return GetEditorWindows();
                case "get_active_tool":
                    return GetActiveTool();
                case "get_selection":
                    return GetSelection();
                case "get_prefab_stage":
                    return GetPrefabStageInfo();
                case "set_active_tool":
                    string toolName = @params["toolName"]?.ToString();
                    if (string.IsNullOrEmpty(toolName))
                        return Response.Error("'toolName' parameter required for set_active_tool.");
                    return SetActiveTool(toolName);

                // Tag Management
                case "add_tag":
                    if (string.IsNullOrEmpty(tagName))
                        return Response.Error("'tagName' parameter required for add_tag.");
                    return AddTag(tagName);
                case "remove_tag":
                    if (string.IsNullOrEmpty(tagName))
                        return Response.Error("'tagName' parameter required for remove_tag.");
                    return RemoveTag(tagName);
                case "get_tags":
                    return GetTags(); // Helper to list current tags

                // Layer Management
                case "add_layer":
                    if (string.IsNullOrEmpty(layerName))
                        return Response.Error("'layerName' parameter required for add_layer.");
                    return AddLayer(layerName);
                case "remove_layer":
                    if (string.IsNullOrEmpty(layerName))
                        return Response.Error("'layerName' parameter required for remove_layer.");
                    return RemoveLayer(layerName);
                case "get_layers":
                    return GetLayers(); // Helper to list current layers

                // --- Settings (Example) ---
                // case "set_resolution":
                //     int? width = @params["width"]?.ToObject<int?>();
                //     int? height = @params["height"]?.ToObject<int?>();
                //     if (!width.HasValue || !height.HasValue) return Response.Error("'width' and 'height' parameters required.");
                //     return SetGameViewResolution(width.Value, height.Value);
                // case "set_quality":
                //     // Handle string name or int index
                //     return SetQualityLevel(@params["qualityLevel"]);

                default:
                    return Response.Error(
                        $"Unknown action: '{action}'. Supported actions include play, pause, stop, get_state, get_project_root, get_windows, get_active_tool, get_selection, get_prefab_stage, set_active_tool, add_tag, remove_tag, get_tags, add_layer, remove_layer, get_layers."
                    );
            }
        }

        // --- Editor State/Info Methods ---
        private static object GetEditorState()
        {
            try
            {
                var state = new
                {
                    isPlaying = EditorApplication.isPlaying,
                    isPaused = EditorApplication.isPaused,
                    isCompiling = EditorApplication.isCompiling,
                    isUpdating = EditorApplication.isUpdating,
                    applicationPath = EditorApplication.applicationPath,
                    applicationContentsPath = EditorApplication.applicationContentsPath,
                    timeSinceStartup = EditorApplication.timeSinceStartup,
                };
                return Response.Success("Retrieved editor state.", state);
            }
            catch (Exception e)
            {
                return Response.Error($"Error getting editor state: {e.Message}");
            }
        }

        private static object GetProjectRoot()
        {
            try
            {
                // Application.dataPath points to <Project>/Assets
                string assetsPath = Application.dataPath.Replace('\\', '/');
                string projectRoot = Directory.GetParent(assetsPath)?.FullName.Replace('\\', '/');
                if (string.IsNullOrEmpty(projectRoot))
                {
                    return Response.Error("Could not determine project root from Application.dataPath");
                }
                return Response.Success("Project root resolved.", new { projectRoot });
            }
            catch (Exception e)
            {
                return Response.Error($"Error getting project root: {e.Message}");
            }
        }

        private static object GetEditorWindows()
        {
            try
            {
                // Get all types deriving from EditorWindow
                var windowTypes = AppDomain
                    .CurrentDomain.GetAssemblies()
                    .SelectMany(assembly => assembly.GetTypes())
                    .Where(type => type.IsSubclassOf(typeof(EditorWindow)))
                    .ToList();

                var openWindows = new List<object>();

                // Find currently open instances
                // Resources.FindObjectsOfTypeAll seems more reliable than GetWindow for finding *all* open windows
                EditorWindow[] allWindows = UnityEngine.Resources.FindObjectsOfTypeAll<EditorWindow>();

                foreach (EditorWindow window in allWindows)
                {
                    if (window == null)
                        continue; // Skip potentially destroyed windows

                    try
                    {
                        openWindows.Add(
                            new
                            {
                                title = window.titleContent.text,
                                typeName = window.GetType().FullName,
                                isFocused = EditorWindow.focusedWindow == window,
                                position = new
                                {
                                    x = window.position.x,
                                    y = window.position.y,
                                    width = window.position.width,
                                    height = window.position.height,
                                },
                                instanceID = window.GetInstanceID(),
                            }
                        );
                    }
                    catch (Exception ex)
                    {
                        Debug.LogWarning(
                            $"Could not get info for window {window.GetType().Name}: {ex.Message}"
                        );
                    }
                }

                return Response.Success("Retrieved list of open editor windows.", openWindows);
            }
            catch (Exception e)
            {
                return Response.Error($"Error getting editor windows: {e.Message}");
            }
        }

        private static object GetPrefabStageInfo()
        {
            try
            {
                PrefabStage stage = PrefabStageUtility.GetCurrentPrefabStage();
                if (stage == null)
                {
                    return Response.Success
                    ("No prefab stage is currently open.", new { isOpen = false });
                }

                return Response.Success(
                    "Prefab stage info retrieved.",
                    new
                    {
                        isOpen = true,
                        assetPath = stage.assetPath,
                        prefabRootName = stage.prefabContentsRoot != null ? stage.prefabContentsRoot.name : null,
                        mode = stage.mode.ToString(),
                        isDirty = stage.scene.isDirty
                    }
                );
            }
            catch (Exception e)
            {
                return Response.Error($"Error getting prefab stage info: {e.Message}");
            }
        }

        private static object GetActiveTool()
        {
            try
            {
                Tool currentTool = UnityEditor.Tools.current;
                string toolName = currentTool.ToString(); // Enum to string
                bool customToolActive = UnityEditor.Tools.current == Tool.Custom; // Check if a custom tool is active
                string activeToolName = customToolActive
                    ? EditorTools.GetActiveToolName()
                    : toolName; // Get custom name if needed

                var toolInfo = new
                {
                    activeTool = activeToolName,
                    isCustom = customToolActive,
                    pivotMode = UnityEditor.Tools.pivotMode.ToString(),
                    pivotRotation = UnityEditor.Tools.pivotRotation.ToString(),
                    handleRotation = UnityEditor.Tools.handleRotation.eulerAngles, // Euler for simplicity
                    handlePosition = UnityEditor.Tools.handlePosition,
                };

                return Response.Success("Retrieved active tool information.", toolInfo);
            }
            catch (Exception e)
            {
                return Response.Error($"Error getting active tool: {e.Message}");
            }
        }

        private static object SetActiveTool(string toolName)
        {
            try
            {
                Tool targetTool;
                if (Enum.TryParse<Tool>(toolName, true, out targetTool)) // Case-insensitive parse
                {
                    // Check if it's a valid built-in tool
                    if (targetTool != Tool.None && targetTool <= Tool.Custom) // Tool.Custom is the last standard tool
                    {
                        UnityEditor.Tools.current = targetTool;
                        return Response.Success($"Set active tool to '{targetTool}'.");
                    }
                    else
                    {
                        return Response.Error(
                            $"Cannot directly set tool to '{toolName}'. It might be None, Custom, or invalid."
                        );
                    }
                }
                else
                {
                    // Potentially try activating a custom tool by name here if needed
                    // This often requires specific editor scripting knowledge for that tool.
                    return Response.Error(
                        $"Could not parse '{toolName}' as a standard Unity Tool (View, Move, Rotate, Scale, Rect, Transform, Custom)."
                    );
                }
            }
            catch (Exception e)
            {
                return Response.Error($"Error setting active tool: {e.Message}");
            }
        }

        private static object GetSelection()
        {
            try
            {
                var selectionInfo = new
                {
                    activeObject = Selection.activeObject?.name,
                    activeGameObject = Selection.activeGameObject?.name,
                    activeTransform = Selection.activeTransform?.name,
                    activeInstanceID = Selection.activeInstanceID,
                    count = Selection.count,
                    objects = Selection
                        .objects.Select(obj => new
                        {
                            name = obj?.name,
                            type = obj?.GetType().FullName,
                            instanceID = obj?.GetInstanceID(),
                        })
                        .ToList(),
                    gameObjects = Selection
                        .gameObjects.Select(go => new
                        {
                            name = go?.name,
                            instanceID = go?.GetInstanceID(),
                        })
                        .ToList(),
                    assetGUIDs = Selection.assetGUIDs, // GUIDs for selected assets in Project view
                };

                return Response.Success("Retrieved current selection details.", selectionInfo);
            }
            catch (Exception e)
            {
                return Response.Error($"Error getting selection: {e.Message}");
            }
        }

        // --- Tag Management Methods ---

        private static object AddTag(string tagName)
        {
            if (string.IsNullOrWhiteSpace(tagName))
                return Response.Error("Tag name cannot be empty or whitespace.");

            // Check if tag already exists
            if (InternalEditorUtility.tags.Contains(tagName))
            {
                return Response.Error($"Tag '{tagName}' already exists.");
            }

            try
            {
                // Add the tag using the internal utility
                InternalEditorUtility.AddTag(tagName);
                // Force save assets to ensure the change persists in the TagManager asset
                AssetDatabase.SaveAssets();
                return Response.Success($"Tag '{tagName}' added successfully.");
            }
            catch (Exception e)
            {
                return Response.Error($"Failed to add tag '{tagName}': {e.Message}");
            }
        }

        private static object RemoveTag(string tagName)
        {
            if (string.IsNullOrWhiteSpace(tagName))
                return Response.Error("Tag name cannot be empty or whitespace.");
            if (tagName.Equals("Untagged", StringComparison.OrdinalIgnoreCase))
                return Response.Error("Cannot remove the built-in 'Untagged' tag.");

            // Check if tag exists before attempting removal
            if (!InternalEditorUtility.tags.Contains(tagName))
            {
                return Response.Error($"Tag '{tagName}' does not exist.");
            }

            try
            {
                // Remove the tag using the internal utility
                InternalEditorUtility.RemoveTag(tagName);
                // Force save assets
                AssetDatabase.SaveAssets();
                return Response.Success($"Tag '{tagName}' removed successfully.");
            }
            catch (Exception e)
            {
                // Catch potential issues if the tag is somehow in use or removal fails
                return Response.Error($"Failed to remove tag '{tagName}': {e.Message}");
            }
        }

        private static object GetTags()
        {
            try
            {
                string[] tags = InternalEditorUtility.tags;
                return Response.Success("Retrieved current tags.", tags);
            }
            catch (Exception e)
            {
                return Response.Error($"Failed to retrieve tags: {e.Message}");
            }
        }

        // --- Layer Management Methods ---

        private static object AddLayer(string layerName)
        {
            if (string.IsNullOrWhiteSpace(layerName))
                return Response.Error("Layer name cannot be empty or whitespace.");

            // Access the TagManager asset
            SerializedObject tagManager = GetTagManager();
            if (tagManager == null)
                return Response.Error("Could not access TagManager asset.");

            SerializedProperty layersProp = tagManager.FindProperty("layers");
            if (layersProp == null || !layersProp.isArray)
                return Response.Error("Could not find 'layers' property in TagManager.");

            // Check if layer name already exists (case-insensitive check recommended)
            for (int i = 0; i < TotalLayerCount; i++)
            {
                SerializedProperty layerSP = layersProp.GetArrayElementAtIndex(i);
                if (
                    layerSP != null
                    && layerName.Equals(layerSP.stringValue, StringComparison.OrdinalIgnoreCase)
                )
                {
                    return Response.Error($"Layer '{layerName}' already exists at index {i}.");
                }
            }

            // Find the first empty user layer slot (indices 8 to 31)
            int firstEmptyUserLayer = -1;
            for (int i = FirstUserLayerIndex; i < TotalLayerCount; i++)
            {
                SerializedProperty layerSP = layersProp.GetArrayElementAtIndex(i);
                if (layerSP != null && string.IsNullOrEmpty(layerSP.stringValue))
                {
                    firstEmptyUserLayer = i;
                    break;
                }
            }

            if (firstEmptyUserLayer == -1)
            {
                return Response.Error("No empty User Layer slots available (8-31 are full).");
            }

            // Assign the name to the found slot
            try
            {
                SerializedProperty targetLayerSP = layersProp.GetArrayElementAtIndex(
                    firstEmptyUserLayer
                );
                targetLayerSP.stringValue = layerName;
                // Apply the changes to the TagManager asset
                tagManager.ApplyModifiedProperties();
                // Save assets to make sure it's written to disk
                AssetDatabase.SaveAssets();
                return Response.Success(
                    $"Layer '{layerName}' added successfully to slot {firstEmptyUserLayer}."
                );
            }
            catch (Exception e)
            {
                return Response.Error($"Failed to add layer '{layerName}': {e.Message}");
            }
        }

        private static object RemoveLayer(string layerName)
        {
            if (string.IsNullOrWhiteSpace(layerName))
                return Response.Error("Layer name cannot be empty or whitespace.");

            // Access the TagManager asset
            SerializedObject tagManager = GetTagManager();
            if (tagManager == null)
                return Response.Error("Could not access TagManager asset.");

            SerializedProperty layersProp = tagManager.FindProperty("layers");
            if (layersProp == null || !layersProp.isArray)
                return Response.Error("Could not find 'layers' property in TagManager.");

            // Find the layer by name (must be user layer)
            int layerIndexToRemove = -1;
            for (int i = FirstUserLayerIndex; i < TotalLayerCount; i++) // Start from user layers
            {
                SerializedProperty layerSP = layersProp.GetArrayElementAtIndex(i);
                // Case-insensitive comparison is safer
                if (
                    layerSP != null
                    && layerName.Equals(layerSP.stringValue, StringComparison.OrdinalIgnoreCase)
                )
                {
                    layerIndexToRemove = i;
                    break;
                }
            }

            if (layerIndexToRemove == -1)
            {
                return Response.Error($"User layer '{layerName}' not found.");
            }

            // Clear the name for that index
            try
            {
                SerializedProperty targetLayerSP = layersProp.GetArrayElementAtIndex(
                    layerIndexToRemove
                );
                targetLayerSP.stringValue = string.Empty; // Set to empty string to remove
                // Apply the changes
                tagManager.ApplyModifiedProperties();
                // Save assets
                AssetDatabase.SaveAssets();
                return Response.Success(
                    $"Layer '{layerName}' (slot {layerIndexToRemove}) removed successfully."
                );
            }
            catch (Exception e)
            {
                return Response.Error($"Failed to remove layer '{layerName}': {e.Message}");
            }
        }

        private static object GetLayers()
        {
            try
            {
                var layers = new Dictionary<int, string>();
                for (int i = 0; i < TotalLayerCount; i++)
                {
                    string layerName = LayerMask.LayerToName(i);
                    if (!string.IsNullOrEmpty(layerName)) // Only include layers that have names
                    {
                        layers.Add(i, layerName);
                    }
                }
                return Response.Success("Retrieved current named layers.", layers);
            }
            catch (Exception e)
            {
                return Response.Error($"Failed to retrieve layers: {e.Message}");
            }
        }

        // --- Helper Methods ---

        /// <summary>
        /// Gets the SerializedObject for the TagManager asset.
        /// </summary>
        private static SerializedObject GetTagManager()
        {
            try
            {
                // Load the TagManager asset from the ProjectSettings folder
                UnityEngine.Object[] tagManagerAssets = AssetDatabase.LoadAllAssetsAtPath(
                    "ProjectSettings/TagManager.asset"
                );
                if (tagManagerAssets == null || tagManagerAssets.Length == 0)
                {
                    Debug.LogError("[ManageEditor] TagManager.asset not found in ProjectSettings.");
                    return null;
                }
                // The first object in the asset file should be the TagManager
                return new SerializedObject(tagManagerAssets[0]);
            }
            catch (Exception e)
            {
                Debug.LogError($"[ManageEditor] Error accessing TagManager.asset: {e.Message}");
                return null;
            }
        }

        // --- Example Implementations for Settings ---
        /*
        private static object SetGameViewResolution(int width, int height) { ... }
        private static object SetQualityLevel(JToken qualityLevelToken) { ... }
        */
    }

    // Helper class to get custom tool names (remains the same)
    internal static class EditorTools
    {
        public static string GetActiveToolName()
        {
            // This is a placeholder. Real implementation depends on how custom tools
            // are registered and tracked in the specific Unity project setup.
            // It might involve checking static variables, calling methods on specific tool managers, etc.
            if (UnityEditor.Tools.current == Tool.Custom)
            {
                // Example: Check a known custom tool manager
                // if (MyCustomToolManager.IsActive) return MyCustomToolManager.ActiveToolName;
                return "Unknown Custom Tool";
            }
            return UnityEditor.Tools.current.ToString();
        }
    }
}

```

--------------------------------------------------------------------------------
/MCPForUnity/Editor/Setup/SetupWizardWindow.cs:
--------------------------------------------------------------------------------

```csharp
using System;
using System.Linq;
using MCPForUnity.Editor.Data;
using MCPForUnity.Editor.Dependencies;
using MCPForUnity.Editor.Dependencies.Models;
using MCPForUnity.Editor.Helpers;
using MCPForUnity.Editor.Models;
using UnityEditor;
using UnityEngine;

namespace MCPForUnity.Editor.Setup
{
    /// <summary>
    /// Setup wizard window for guiding users through dependency installation
    /// </summary>
    public class SetupWizardWindow : EditorWindow
    {
        private DependencyCheckResult _dependencyResult;
        private Vector2 _scrollPosition;
        private int _currentStep = 0;
        private McpClients _mcpClients;
        private int _selectedClientIndex = 0;

        private readonly string[] _stepTitles = {
            "Setup",
            "Configure",
            "Complete"
        };

        public static void ShowWindow(DependencyCheckResult dependencyResult = null)
        {
            var window = GetWindow<SetupWizardWindow>("MCP for Unity Setup");
            window.minSize = new Vector2(500, 400);
            window.maxSize = new Vector2(800, 600);
            window._dependencyResult = dependencyResult ?? DependencyManager.CheckAllDependencies();
            window.Show();
        }

        private void OnEnable()
        {
            if (_dependencyResult == null)
            {
                _dependencyResult = DependencyManager.CheckAllDependencies();
            }

            _mcpClients = new McpClients();

            // Check client configurations on startup
            foreach (var client in _mcpClients.clients)
            {
                CheckClientConfiguration(client);
            }
        }

        private void OnGUI()
        {
            DrawHeader();
            DrawProgressBar();

            _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);

            switch (_currentStep)
            {
                case 0: DrawSetupStep(); break;
                case 1: DrawConfigureStep(); break;
                case 2: DrawCompleteStep(); break;
            }

            EditorGUILayout.EndScrollView();

            DrawFooter();
        }

        private void DrawHeader()
        {
            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
            GUILayout.Label("MCP for Unity Setup Wizard", EditorStyles.boldLabel);
            GUILayout.FlexibleSpace();
            GUILayout.Label($"Step {_currentStep + 1} of {_stepTitles.Length}");
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space();

            // Step title
            var titleStyle = new GUIStyle(EditorStyles.largeLabel)
            {
                fontSize = 16,
                fontStyle = FontStyle.Bold
            };
            EditorGUILayout.LabelField(_stepTitles[_currentStep], titleStyle);
            EditorGUILayout.Space();
        }

        private void DrawProgressBar()
        {
            var rect = EditorGUILayout.GetControlRect(false, 4);
            var progress = (_currentStep + 1) / (float)_stepTitles.Length;
            EditorGUI.ProgressBar(rect, progress, "");
            EditorGUILayout.Space();
        }

        private void DrawSetupStep()
        {
            // Welcome section
            DrawSectionTitle("MCP for Unity Setup");

            EditorGUILayout.LabelField(
                "This wizard will help you set up MCP for Unity to connect AI assistants with your Unity Editor.",
                EditorStyles.wordWrappedLabel
            );
            EditorGUILayout.Space();

            // Dependency check section
            EditorGUILayout.BeginHorizontal();
            DrawSectionTitle("System Check", 14);
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Refresh", GUILayout.Width(60), GUILayout.Height(20)))
            {
                _dependencyResult = DependencyManager.CheckAllDependencies();
            }
            EditorGUILayout.EndHorizontal();

            // Show simplified dependency status
            foreach (var dep in _dependencyResult.Dependencies)
            {
                DrawSimpleDependencyStatus(dep);
            }

            // Overall status and installation guidance
            EditorGUILayout.Space();
            if (!_dependencyResult.IsSystemReady)
            {
                // Only show critical warnings when dependencies are actually missing
                EditorGUILayout.HelpBox(
                    "⚠️ Missing Dependencies: MCP for Unity requires Python 3.10+ and UV package manager to function properly.",
                    MessageType.Warning
                );

                EditorGUILayout.Space();
                EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                DrawErrorStatus("Installation Required");

                var recommendations = DependencyManager.GetInstallationRecommendations();
                EditorGUILayout.LabelField(recommendations, EditorStyles.wordWrappedLabel);

                EditorGUILayout.Space();
                if (GUILayout.Button("Open Installation Links", GUILayout.Height(25)))
                {
                    OpenInstallationUrls();
                }
                EditorGUILayout.EndVertical();
            }
            else
            {
                DrawSuccessStatus("System Ready");
                EditorGUILayout.LabelField("All requirements are met. You can proceed to configure your AI clients.", EditorStyles.wordWrappedLabel);
            }
        }



        private void DrawCompleteStep()
        {
            DrawSectionTitle("Setup Complete");

            // Refresh dependency check with caching to avoid heavy operations on every repaint
            if (_dependencyResult == null || (DateTime.UtcNow - _dependencyResult.CheckedAt).TotalSeconds > 2)
            {
                _dependencyResult = DependencyManager.CheckAllDependencies();
            }

            if (_dependencyResult.IsSystemReady)
            {
                DrawSuccessStatus("MCP for Unity Ready!");

                EditorGUILayout.HelpBox(
                    "🎉 MCP for Unity is now set up and ready to use!\n\n" +
                    "• Dependencies verified\n" +
                    "• MCP server ready\n" +
                    "• Client configuration accessible",
                    MessageType.Info
                );

                EditorGUILayout.Space();
                EditorGUILayout.BeginHorizontal();
                if (GUILayout.Button("Documentation", GUILayout.Height(30)))
                {
                    Application.OpenURL("https://github.com/CoplayDev/unity-mcp");
                }
                if (GUILayout.Button("Client Settings", GUILayout.Height(30)))
                {
                    Windows.MCPForUnityEditorWindow.ShowWindow();
                }
                EditorGUILayout.EndHorizontal();
            }
            else
            {
                DrawErrorStatus("Setup Incomplete - Package Non-Functional");

                EditorGUILayout.HelpBox(
                    "🚨 MCP for Unity CANNOT work - dependencies still missing!\n\n" +
                    "Install ALL required dependencies before the package will function.",
                    MessageType.Error
                );

                var missingDeps = _dependencyResult.GetMissingRequired();
                if (missingDeps.Count > 0)
                {
                    EditorGUILayout.Space();
                    EditorGUILayout.LabelField("Still Missing:", EditorStyles.boldLabel);
                    foreach (var dep in missingDeps)
                    {
                        EditorGUILayout.LabelField($"✗ {dep.Name}", EditorStyles.label);
                    }
                }

                EditorGUILayout.Space();
                if (GUILayout.Button("Go Back to Setup", GUILayout.Height(30)))
                {
                    _currentStep = 0;
                }
            }
        }

        // Helper methods for consistent UI components
        private void DrawSectionTitle(string title, int fontSize = 16)
        {
            var titleStyle = new GUIStyle(EditorStyles.boldLabel)
            {
                fontSize = fontSize,
                fontStyle = FontStyle.Bold
            };
            EditorGUILayout.LabelField(title, titleStyle);
            EditorGUILayout.Space();
        }

        private void DrawSuccessStatus(string message)
        {
            var originalColor = GUI.color;
            GUI.color = Color.green;
            EditorGUILayout.LabelField($"✓ {message}", EditorStyles.boldLabel);
            GUI.color = originalColor;
            EditorGUILayout.Space();
        }

        private void DrawErrorStatus(string message)
        {
            var originalColor = GUI.color;
            GUI.color = Color.red;
            EditorGUILayout.LabelField($"✗ {message}", EditorStyles.boldLabel);
            GUI.color = originalColor;
            EditorGUILayout.Space();
        }

        private void DrawSimpleDependencyStatus(DependencyStatus dep)
        {
            EditorGUILayout.BeginHorizontal();

            var statusIcon = dep.IsAvailable ? "✓" : "✗";
            var statusColor = dep.IsAvailable ? Color.green : Color.red;

            var originalColor = GUI.color;
            GUI.color = statusColor;
            GUILayout.Label(statusIcon, GUILayout.Width(20));
            EditorGUILayout.LabelField(dep.Name, EditorStyles.boldLabel);
            GUI.color = originalColor;

            if (!dep.IsAvailable && !string.IsNullOrEmpty(dep.ErrorMessage))
            {
                EditorGUILayout.LabelField($"({dep.ErrorMessage})", EditorStyles.miniLabel);
            }

            EditorGUILayout.EndHorizontal();
        }

        private void DrawConfigureStep()
        {
            DrawSectionTitle("AI Client Configuration");

            // Check dependencies first (with caching to avoid heavy operations on every repaint)
            if (_dependencyResult == null || (DateTime.UtcNow - _dependencyResult.CheckedAt).TotalSeconds > 2)
            {
                _dependencyResult = DependencyManager.CheckAllDependencies();
            }
            if (!_dependencyResult.IsSystemReady)
            {
                DrawErrorStatus("Cannot Configure - System Requirements Not Met");

                EditorGUILayout.HelpBox(
                    "Client configuration requires system dependencies to be installed first. Please complete setup before proceeding.",
                    MessageType.Warning
                );

                if (GUILayout.Button("Go Back to Setup", GUILayout.Height(30)))
                {
                    _currentStep = 0;
                }
                return;
            }

            EditorGUILayout.LabelField(
                "Configure your AI assistants to work with Unity. Select a client below to set it up:",
                EditorStyles.wordWrappedLabel
            );
            EditorGUILayout.Space();

            // Client selection and configuration
            if (_mcpClients.clients.Count > 0)
            {
                // Client selector dropdown
                string[] clientNames = _mcpClients.clients.Select(c => c.name).ToArray();
                EditorGUI.BeginChangeCheck();
                _selectedClientIndex = EditorGUILayout.Popup("Select AI Client:", _selectedClientIndex, clientNames);
                if (EditorGUI.EndChangeCheck())
                {
                    _selectedClientIndex = Mathf.Clamp(_selectedClientIndex, 0, _mcpClients.clients.Count - 1);
                    // Refresh client status when selection changes
                    CheckClientConfiguration(_mcpClients.clients[_selectedClientIndex]);
                }

                EditorGUILayout.Space();

                var selectedClient = _mcpClients.clients[_selectedClientIndex];
                DrawClientConfigurationInWizard(selectedClient);

                EditorGUILayout.Space();

                // Batch configuration option
                EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                EditorGUILayout.LabelField("Quick Setup", EditorStyles.boldLabel);
                EditorGUILayout.LabelField(
                    "Automatically configure all detected AI clients at once:",
                    EditorStyles.wordWrappedLabel
                );
                EditorGUILayout.Space();

                if (GUILayout.Button("Configure All Detected Clients", GUILayout.Height(30)))
                {
                    ConfigureAllClientsInWizard();
                }
                EditorGUILayout.EndVertical();
            }
            else
            {
                EditorGUILayout.HelpBox("No AI clients detected. Make sure you have Claude Code, Cursor, or VSCode installed.", MessageType.Info);
            }

            EditorGUILayout.Space();
            EditorGUILayout.HelpBox(
                "💡 You might need to restart your AI client after configuring.",
                MessageType.Info
            );
        }

        private void DrawFooter()
        {
            EditorGUILayout.Space();
            EditorGUILayout.BeginHorizontal();

            // Back button
            GUI.enabled = _currentStep > 0;
            if (GUILayout.Button("Back", GUILayout.Width(60)))
            {
                _currentStep--;
            }

            GUILayout.FlexibleSpace();

            // Skip button
            if (GUILayout.Button("Skip", GUILayout.Width(60)))
            {
                bool dismiss = EditorUtility.DisplayDialog(
                    "Skip Setup",
                    "⚠️ Skipping setup will leave MCP for Unity non-functional!\n\n" +
                    "You can restart setup from: Window > MCP for Unity > Setup Wizard (Required)",
                    "Skip Anyway",
                    "Cancel"
                );

                if (dismiss)
                {
                    SetupWizard.MarkSetupDismissed();
                    Close();
                }
            }

            // Next/Done button
            GUI.enabled = true;
            string buttonText = _currentStep == _stepTitles.Length - 1 ? "Done" : "Next";

            if (GUILayout.Button(buttonText, GUILayout.Width(80)))
            {
                if (_currentStep == _stepTitles.Length - 1)
                {
                    SetupWizard.MarkSetupCompleted();
                    Close();
                }
                else
                {
                    _currentStep++;
                }
            }

            GUI.enabled = true;
            EditorGUILayout.EndHorizontal();
        }

        private void DrawClientConfigurationInWizard(McpClient client)
        {
            EditorGUILayout.BeginVertical(EditorStyles.helpBox);

            EditorGUILayout.LabelField($"{client.name} Configuration", EditorStyles.boldLabel);
            EditorGUILayout.Space();

            // Show current status
            var statusColor = GetClientStatusColor(client);
            var originalColor = GUI.color;
            GUI.color = statusColor;
            EditorGUILayout.LabelField($"Status: {client.configStatus}", EditorStyles.label);
            GUI.color = originalColor;

            EditorGUILayout.Space();

            // Configuration buttons
            EditorGUILayout.BeginHorizontal();

            if (client.mcpType == McpTypes.ClaudeCode)
            {
                // Special handling for Claude Code
                bool claudeAvailable = !string.IsNullOrEmpty(ExecPath.ResolveClaude());
                if (claudeAvailable)
                {
                    bool isConfigured = client.status == McpStatus.Configured;
                    string buttonText = isConfigured ? "Unregister" : "Register";
                    if (GUILayout.Button($"{buttonText} with Claude Code"))
                    {
                        if (isConfigured)
                        {
                            UnregisterFromClaudeCode(client);
                        }
                        else
                        {
                            RegisterWithClaudeCode(client);
                        }
                    }
                }
                else
                {
                    EditorGUILayout.HelpBox("Claude Code not found. Please install Claude Code first.", MessageType.Warning);
                    if (GUILayout.Button("Open Claude Code Website"))
                    {
                        Application.OpenURL("https://claude.ai/download");
                    }
                }
            }
            else
            {
                // Standard client configuration
                if (GUILayout.Button($"Configure {client.name}"))
                {
                    ConfigureClientInWizard(client);
                }

                if (GUILayout.Button("Manual Setup"))
                {
                    ShowManualSetupInWizard(client);
                }
            }

            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();
        }

        private Color GetClientStatusColor(McpClient client)
        {
            return client.status switch
            {
                McpStatus.Configured => Color.green,
                McpStatus.Running => Color.green,
                McpStatus.Connected => Color.green,
                McpStatus.IncorrectPath => Color.yellow,
                McpStatus.CommunicationError => Color.yellow,
                McpStatus.NoResponse => Color.yellow,
                _ => Color.red
            };
        }

        private void ConfigureClientInWizard(McpClient client)
        {
            try
            {
                string result = PerformClientConfiguration(client);

                EditorUtility.DisplayDialog(
                    $"{client.name} Configuration",
                    result,
                    "OK"
                );

                // Refresh client status
                CheckClientConfiguration(client);
                Repaint();
            }
            catch (System.Exception ex)
            {
                EditorUtility.DisplayDialog(
                    "Configuration Error",
                    $"Failed to configure {client.name}: {ex.Message}",
                    "OK"
                );
            }
        }

        private void ConfigureAllClientsInWizard()
        {
            int successCount = 0;
            int totalCount = _mcpClients.clients.Count;

            foreach (var client in _mcpClients.clients)
            {
                try
                {
                    if (client.mcpType == McpTypes.ClaudeCode)
                    {
                        if (!string.IsNullOrEmpty(ExecPath.ResolveClaude()) && client.status != McpStatus.Configured)
                        {
                            RegisterWithClaudeCode(client);
                            successCount++;
                        }
                        else if (client.status == McpStatus.Configured)
                        {
                            successCount++; // Already configured
                        }
                    }
                    else
                    {
                        string result = PerformClientConfiguration(client);
                        if (result.Contains("success", System.StringComparison.OrdinalIgnoreCase))
                        {
                            successCount++;
                        }
                    }

                    CheckClientConfiguration(client);
                }
                catch (System.Exception ex)
                {
                    McpLog.Error($"Failed to configure {client.name}: {ex.Message}");
                }
            }

            EditorUtility.DisplayDialog(
                "Batch Configuration Complete",
                $"Successfully configured {successCount} out of {totalCount} clients.\n\n" +
                "Restart your AI clients for changes to take effect.",
                "OK"
            );

            Repaint();
        }

        private void RegisterWithClaudeCode(McpClient client)
        {
            try
            {
                string pythonDir = McpPathResolver.FindPackagePythonDirectory();
                string claudePath = ExecPath.ResolveClaude();
                string uvPath = ExecPath.ResolveUv() ?? "uv";

                string args = $"mcp add UnityMCP -- \"{uvPath}\" run --directory \"{pythonDir}\" server.py";

                if (!ExecPath.TryRun(claudePath, args, null, out var stdout, out var stderr, 15000, McpPathResolver.GetPathPrepend()))
                {
                    if ((stdout + stderr).Contains("already exists", System.StringComparison.OrdinalIgnoreCase))
                    {
                        CheckClientConfiguration(client);
                        EditorUtility.DisplayDialog("Claude Code", "MCP for Unity is already registered with Claude Code.", "OK");
                    }
                    else
                    {
                        throw new System.Exception($"Registration failed: {stderr}");
                    }
                }
                else
                {
                    CheckClientConfiguration(client);
                    EditorUtility.DisplayDialog("Claude Code", "Successfully registered MCP for Unity with Claude Code!", "OK");
                }
            }
            catch (System.Exception ex)
            {
                EditorUtility.DisplayDialog("Registration Error", $"Failed to register with Claude Code: {ex.Message}", "OK");
            }
        }

        private void UnregisterFromClaudeCode(McpClient client)
        {
            try
            {
                string claudePath = ExecPath.ResolveClaude();
                if (ExecPath.TryRun(claudePath, "mcp remove UnityMCP", null, out var stdout, out var stderr, 10000, McpPathResolver.GetPathPrepend()))
                {
                    CheckClientConfiguration(client);
                    EditorUtility.DisplayDialog("Claude Code", "Successfully unregistered MCP for Unity from Claude Code.", "OK");
                }
                else
                {
                    throw new System.Exception($"Unregistration failed: {stderr}");
                }
            }
            catch (System.Exception ex)
            {
                EditorUtility.DisplayDialog("Unregistration Error", $"Failed to unregister from Claude Code: {ex.Message}", "OK");
            }
        }

        private string PerformClientConfiguration(McpClient client)
        {
            // This mirrors the logic from MCPForUnityEditorWindow.ConfigureMcpClient
            string configPath = McpConfigurationHelper.GetClientConfigPath(client);
            string pythonDir = McpPathResolver.FindPackagePythonDirectory();

            if (string.IsNullOrEmpty(pythonDir))
            {
                return "Manual configuration required - Python server directory not found.";
            }

            McpConfigurationHelper.EnsureConfigDirectoryExists(configPath);
            return McpConfigurationHelper.WriteMcpConfiguration(pythonDir, configPath, client);
        }

        private void ShowManualSetupInWizard(McpClient client)
        {
            string configPath = McpConfigurationHelper.GetClientConfigPath(client);
            string pythonDir = McpPathResolver.FindPackagePythonDirectory();
            string uvPath = ServerInstaller.FindUvPath();

            if (string.IsNullOrEmpty(uvPath))
            {
                EditorUtility.DisplayDialog("Manual Setup", "UV package manager not found. Please install UV first.", "OK");
                return;
            }

            // Build manual configuration using the sophisticated helper logic
            string result = McpConfigurationHelper.WriteMcpConfiguration(pythonDir, configPath, client);
            string manualConfig;

            if (result == "Configured successfully")
            {
                // Read back the configuration that was written
                try
                {
                    manualConfig = System.IO.File.ReadAllText(configPath);
                }
                catch
                {
                    manualConfig = "Configuration written successfully, but could not read back for display.";
                }
            }
            else
            {
                manualConfig = $"Configuration failed: {result}";
            }

            EditorUtility.DisplayDialog(
                $"Manual Setup - {client.name}",
                $"Configuration file location:\n{configPath}\n\n" +
                $"Configuration result:\n{manualConfig}",
                "OK"
            );
        }

        private void CheckClientConfiguration(McpClient client)
        {
            // Basic status check - could be enhanced to mirror MCPForUnityEditorWindow logic
            try
            {
                string configPath = McpConfigurationHelper.GetClientConfigPath(client);
                if (System.IO.File.Exists(configPath))
                {
                    client.configStatus = "Configured";
                    client.status = McpStatus.Configured;
                }
                else
                {
                    client.configStatus = "Not Configured";
                    client.status = McpStatus.NotConfigured;
                }
            }
            catch
            {
                client.configStatus = "Error";
                client.status = McpStatus.Error;
            }
        }

        private void OpenInstallationUrls()
        {
            var (pythonUrl, uvUrl) = DependencyManager.GetInstallationUrls();

            bool openPython = EditorUtility.DisplayDialog(
                "Open Installation URLs",
                "Open Python installation page?",
                "Yes",
                "No"
            );

            if (openPython)
            {
                Application.OpenURL(pythonUrl);
            }

            bool openUV = EditorUtility.DisplayDialog(
                "Open Installation URLs",
                "Open UV installation page?",
                "Yes",
                "No"
            );

            if (openUV)
            {
                Application.OpenURL(uvUrl);
            }
        }
    }
}

```

--------------------------------------------------------------------------------
/UnityMcpBridge/Editor/Setup/SetupWizardWindow.cs:
--------------------------------------------------------------------------------

```csharp
using System;
using System.Linq;
using MCPForUnity.Editor.Data;
using MCPForUnity.Editor.Dependencies;
using MCPForUnity.Editor.Dependencies.Models;
using MCPForUnity.Editor.Helpers;
using MCPForUnity.Editor.Models;
using UnityEditor;
using UnityEngine;

namespace MCPForUnity.Editor.Setup
{
    /// <summary>
    /// Setup wizard window for guiding users through dependency installation
    /// </summary>
    public class SetupWizardWindow : EditorWindow
    {
        private DependencyCheckResult _dependencyResult;
        private Vector2 _scrollPosition;
        private int _currentStep = 0;
        private McpClients _mcpClients;
        private int _selectedClientIndex = 0;

        private readonly string[] _stepTitles = {
            "Setup",
            "Configure",
            "Complete"
        };

        public static void ShowWindow(DependencyCheckResult dependencyResult = null)
        {
            var window = GetWindow<SetupWizardWindow>("MCP for Unity Setup");
            window.minSize = new Vector2(500, 400);
            window.maxSize = new Vector2(800, 600);
            window._dependencyResult = dependencyResult ?? DependencyManager.CheckAllDependencies();
            window.Show();
        }

        private void OnEnable()
        {
            if (_dependencyResult == null)
            {
                _dependencyResult = DependencyManager.CheckAllDependencies();
            }

            _mcpClients = new McpClients();

            // Check client configurations on startup
            foreach (var client in _mcpClients.clients)
            {
                CheckClientConfiguration(client);
            }
        }

        private void OnGUI()
        {
            DrawHeader();
            DrawProgressBar();

            _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);

            switch (_currentStep)
            {
                case 0: DrawSetupStep(); break;
                case 1: DrawConfigureStep(); break;
                case 2: DrawCompleteStep(); break;
            }

            EditorGUILayout.EndScrollView();

            DrawFooter();
        }

        private void DrawHeader()
        {
            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
            GUILayout.Label("MCP for Unity Setup Wizard", EditorStyles.boldLabel);
            GUILayout.FlexibleSpace();
            GUILayout.Label($"Step {_currentStep + 1} of {_stepTitles.Length}");
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space();

            // Step title
            var titleStyle = new GUIStyle(EditorStyles.largeLabel)
            {
                fontSize = 16,
                fontStyle = FontStyle.Bold
            };
            EditorGUILayout.LabelField(_stepTitles[_currentStep], titleStyle);
            EditorGUILayout.Space();
        }

        private void DrawProgressBar()
        {
            var rect = EditorGUILayout.GetControlRect(false, 4);
            var progress = (_currentStep + 1) / (float)_stepTitles.Length;
            EditorGUI.ProgressBar(rect, progress, "");
            EditorGUILayout.Space();
        }

        private void DrawSetupStep()
        {
            // Welcome section
            DrawSectionTitle("MCP for Unity Setup");

            EditorGUILayout.LabelField(
                "This wizard will help you set up MCP for Unity to connect AI assistants with your Unity Editor.",
                EditorStyles.wordWrappedLabel
            );
            EditorGUILayout.Space();

            // Dependency check section
            EditorGUILayout.BeginHorizontal();
            DrawSectionTitle("System Check", 14);
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Refresh", GUILayout.Width(60), GUILayout.Height(20)))
            {
                _dependencyResult = DependencyManager.CheckAllDependencies();
            }
            EditorGUILayout.EndHorizontal();

            // Show simplified dependency status
            foreach (var dep in _dependencyResult.Dependencies)
            {
                DrawSimpleDependencyStatus(dep);
            }

            // Overall status and installation guidance
            EditorGUILayout.Space();
            if (!_dependencyResult.IsSystemReady)
            {
                // Only show critical warnings when dependencies are actually missing
                EditorGUILayout.HelpBox(
                    "⚠️ Missing Dependencies: MCP for Unity requires Python 3.10+ and UV package manager to function properly.",
                    MessageType.Warning
                );

                EditorGUILayout.Space();
                EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                DrawErrorStatus("Installation Required");

                var recommendations = DependencyManager.GetInstallationRecommendations();
                EditorGUILayout.LabelField(recommendations, EditorStyles.wordWrappedLabel);

                EditorGUILayout.Space();
                if (GUILayout.Button("Open Installation Links", GUILayout.Height(25)))
                {
                    OpenInstallationUrls();
                }
                EditorGUILayout.EndVertical();
            }
            else
            {
                DrawSuccessStatus("System Ready");
                EditorGUILayout.LabelField("All requirements are met. You can proceed to configure your AI clients.", EditorStyles.wordWrappedLabel);
            }
        }



        private void DrawCompleteStep()
        {
            DrawSectionTitle("Setup Complete");

            // Refresh dependency check with caching to avoid heavy operations on every repaint
            if (_dependencyResult == null || (DateTime.UtcNow - _dependencyResult.CheckedAt).TotalSeconds > 2)
            {
                _dependencyResult = DependencyManager.CheckAllDependencies();
            }

            if (_dependencyResult.IsSystemReady)
            {
                DrawSuccessStatus("MCP for Unity Ready!");

                EditorGUILayout.HelpBox(
                    "🎉 MCP for Unity is now set up and ready to use!\n\n" +
                    "• Dependencies verified\n" +
                    "• MCP server ready\n" +
                    "• Client configuration accessible",
                    MessageType.Info
                );

                EditorGUILayout.Space();
                EditorGUILayout.BeginHorizontal();
                if (GUILayout.Button("Documentation", GUILayout.Height(30)))
                {
                    Application.OpenURL("https://github.com/CoplayDev/unity-mcp");
                }
                if (GUILayout.Button("Client Settings", GUILayout.Height(30)))
                {
                    Windows.MCPForUnityEditorWindow.ShowWindow();
                }
                EditorGUILayout.EndHorizontal();
            }
            else
            {
                DrawErrorStatus("Setup Incomplete - Package Non-Functional");

                EditorGUILayout.HelpBox(
                    "🚨 MCP for Unity CANNOT work - dependencies still missing!\n\n" +
                    "Install ALL required dependencies before the package will function.",
                    MessageType.Error
                );

                var missingDeps = _dependencyResult.GetMissingRequired();
                if (missingDeps.Count > 0)
                {
                    EditorGUILayout.Space();
                    EditorGUILayout.LabelField("Still Missing:", EditorStyles.boldLabel);
                    foreach (var dep in missingDeps)
                    {
                        EditorGUILayout.LabelField($"✗ {dep.Name}", EditorStyles.label);
                    }
                }

                EditorGUILayout.Space();
                if (GUILayout.Button("Go Back to Setup", GUILayout.Height(30)))
                {
                    _currentStep = 0;
                }
            }
        }

        // Helper methods for consistent UI components
        private void DrawSectionTitle(string title, int fontSize = 16)
        {
            var titleStyle = new GUIStyle(EditorStyles.boldLabel)
            {
                fontSize = fontSize,
                fontStyle = FontStyle.Bold
            };
            EditorGUILayout.LabelField(title, titleStyle);
            EditorGUILayout.Space();
        }

        private void DrawSuccessStatus(string message)
        {
            var originalColor = GUI.color;
            GUI.color = Color.green;
            EditorGUILayout.LabelField($"✓ {message}", EditorStyles.boldLabel);
            GUI.color = originalColor;
            EditorGUILayout.Space();
        }

        private void DrawErrorStatus(string message)
        {
            var originalColor = GUI.color;
            GUI.color = Color.red;
            EditorGUILayout.LabelField($"✗ {message}", EditorStyles.boldLabel);
            GUI.color = originalColor;
            EditorGUILayout.Space();
        }

        private void DrawSimpleDependencyStatus(DependencyStatus dep)
        {
            EditorGUILayout.BeginHorizontal();

            var statusIcon = dep.IsAvailable ? "✓" : "✗";
            var statusColor = dep.IsAvailable ? Color.green : Color.red;

            var originalColor = GUI.color;
            GUI.color = statusColor;
            GUILayout.Label(statusIcon, GUILayout.Width(20));
            EditorGUILayout.LabelField(dep.Name, EditorStyles.boldLabel);
            GUI.color = originalColor;

            if (!dep.IsAvailable && !string.IsNullOrEmpty(dep.ErrorMessage))
            {
                EditorGUILayout.LabelField($"({dep.ErrorMessage})", EditorStyles.miniLabel);
            }

            EditorGUILayout.EndHorizontal();
        }

        private void DrawConfigureStep()
        {
            DrawSectionTitle("AI Client Configuration");

            // Check dependencies first (with caching to avoid heavy operations on every repaint)
            if (_dependencyResult == null || (DateTime.UtcNow - _dependencyResult.CheckedAt).TotalSeconds > 2)
            {
                _dependencyResult = DependencyManager.CheckAllDependencies();
            }
            if (!_dependencyResult.IsSystemReady)
            {
                DrawErrorStatus("Cannot Configure - System Requirements Not Met");

                EditorGUILayout.HelpBox(
                    "Client configuration requires system dependencies to be installed first. Please complete setup before proceeding.",
                    MessageType.Warning
                );

                if (GUILayout.Button("Go Back to Setup", GUILayout.Height(30)))
                {
                    _currentStep = 0;
                }
                return;
            }

            EditorGUILayout.LabelField(
                "Configure your AI assistants to work with Unity. Select a client below to set it up:",
                EditorStyles.wordWrappedLabel
            );
            EditorGUILayout.Space();

            // Client selection and configuration
            if (_mcpClients.clients.Count > 0)
            {
                // Client selector dropdown
                string[] clientNames = _mcpClients.clients.Select(c => c.name).ToArray();
                EditorGUI.BeginChangeCheck();
                _selectedClientIndex = EditorGUILayout.Popup("Select AI Client:", _selectedClientIndex, clientNames);
                if (EditorGUI.EndChangeCheck())
                {
                    _selectedClientIndex = Mathf.Clamp(_selectedClientIndex, 0, _mcpClients.clients.Count - 1);
                    // Refresh client status when selection changes
                    CheckClientConfiguration(_mcpClients.clients[_selectedClientIndex]);
                }

                EditorGUILayout.Space();

                var selectedClient = _mcpClients.clients[_selectedClientIndex];
                DrawClientConfigurationInWizard(selectedClient);

                EditorGUILayout.Space();

                // Batch configuration option
                EditorGUILayout.BeginVertical(EditorStyles.helpBox);
                EditorGUILayout.LabelField("Quick Setup", EditorStyles.boldLabel);
                EditorGUILayout.LabelField(
                    "Automatically configure all detected AI clients at once:",
                    EditorStyles.wordWrappedLabel
                );
                EditorGUILayout.Space();

                if (GUILayout.Button("Configure All Detected Clients", GUILayout.Height(30)))
                {
                    ConfigureAllClientsInWizard();
                }
                EditorGUILayout.EndVertical();
            }
            else
            {
                EditorGUILayout.HelpBox("No AI clients detected. Make sure you have Claude Code, Cursor, or VSCode installed.", MessageType.Info);
            }

            EditorGUILayout.Space();
            EditorGUILayout.HelpBox(
                "💡 You might need to restart your AI client after configuring.",
                MessageType.Info
            );
        }

        private void DrawFooter()
        {
            EditorGUILayout.Space();
            EditorGUILayout.BeginHorizontal();

            // Back button
            GUI.enabled = _currentStep > 0;
            if (GUILayout.Button("Back", GUILayout.Width(60)))
            {
                _currentStep--;
            }

            GUILayout.FlexibleSpace();

            // Skip button
            if (GUILayout.Button("Skip", GUILayout.Width(60)))
            {
                bool dismiss = EditorUtility.DisplayDialog(
                    "Skip Setup",
                    "⚠️ Skipping setup will leave MCP for Unity non-functional!\n\n" +
                    "You can restart setup from: Window > MCP for Unity > Setup Wizard (Required)",
                    "Skip Anyway",
                    "Cancel"
                );

                if (dismiss)
                {
                    SetupWizard.MarkSetupDismissed();
                    Close();
                }
            }

            // Next/Done button
            GUI.enabled = true;
            string buttonText = _currentStep == _stepTitles.Length - 1 ? "Done" : "Next";

            if (GUILayout.Button(buttonText, GUILayout.Width(80)))
            {
                if (_currentStep == _stepTitles.Length - 1)
                {
                    SetupWizard.MarkSetupCompleted();
                    Close();
                }
                else
                {
                    _currentStep++;
                }
            }

            GUI.enabled = true;
            EditorGUILayout.EndHorizontal();
        }

        private void DrawClientConfigurationInWizard(McpClient client)
        {
            EditorGUILayout.BeginVertical(EditorStyles.helpBox);

            EditorGUILayout.LabelField($"{client.name} Configuration", EditorStyles.boldLabel);
            EditorGUILayout.Space();

            // Show current status
            var statusColor = GetClientStatusColor(client);
            var originalColor = GUI.color;
            GUI.color = statusColor;
            EditorGUILayout.LabelField($"Status: {client.configStatus}", EditorStyles.label);
            GUI.color = originalColor;

            EditorGUILayout.Space();

            // Configuration buttons
            EditorGUILayout.BeginHorizontal();

            if (client.mcpType == McpTypes.ClaudeCode)
            {
                // Special handling for Claude Code
                bool claudeAvailable = !string.IsNullOrEmpty(ExecPath.ResolveClaude());
                if (claudeAvailable)
                {
                    bool isConfigured = client.status == McpStatus.Configured;
                    string buttonText = isConfigured ? "Unregister" : "Register";
                    if (GUILayout.Button($"{buttonText} with Claude Code"))
                    {
                        if (isConfigured)
                        {
                            UnregisterFromClaudeCode(client);
                        }
                        else
                        {
                            RegisterWithClaudeCode(client);
                        }
                    }
                }
                else
                {
                    EditorGUILayout.HelpBox("Claude Code not found. Please install Claude Code first.", MessageType.Warning);
                    if (GUILayout.Button("Open Claude Code Website"))
                    {
                        Application.OpenURL("https://claude.ai/download");
                    }
                }
            }
            else
            {
                // Standard client configuration
                if (GUILayout.Button($"Configure {client.name}"))
                {
                    ConfigureClientInWizard(client);
                }

                if (GUILayout.Button("Manual Setup"))
                {
                    ShowManualSetupInWizard(client);
                }
            }

            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();
        }

        private Color GetClientStatusColor(McpClient client)
        {
            return client.status switch
            {
                McpStatus.Configured => Color.green,
                McpStatus.Running => Color.green,
                McpStatus.Connected => Color.green,
                McpStatus.IncorrectPath => Color.yellow,
                McpStatus.CommunicationError => Color.yellow,
                McpStatus.NoResponse => Color.yellow,
                _ => Color.red
            };
        }

        private void ConfigureClientInWizard(McpClient client)
        {
            try
            {
                string result = PerformClientConfiguration(client);

                EditorUtility.DisplayDialog(
                    $"{client.name} Configuration",
                    result,
                    "OK"
                );

                // Refresh client status
                CheckClientConfiguration(client);
                Repaint();
            }
            catch (System.Exception ex)
            {
                EditorUtility.DisplayDialog(
                    "Configuration Error",
                    $"Failed to configure {client.name}: {ex.Message}",
                    "OK"
                );
            }
        }

        private void ConfigureAllClientsInWizard()
        {
            int successCount = 0;
            int totalCount = _mcpClients.clients.Count;

            foreach (var client in _mcpClients.clients)
            {
                try
                {
                    if (client.mcpType == McpTypes.ClaudeCode)
                    {
                        if (!string.IsNullOrEmpty(ExecPath.ResolveClaude()) && client.status != McpStatus.Configured)
                        {
                            RegisterWithClaudeCode(client);
                            successCount++;
                        }
                        else if (client.status == McpStatus.Configured)
                        {
                            successCount++; // Already configured
                        }
                    }
                    else
                    {
                        string result = PerformClientConfiguration(client);
                        if (result.Contains("success", System.StringComparison.OrdinalIgnoreCase))
                        {
                            successCount++;
                        }
                    }

                    CheckClientConfiguration(client);
                }
                catch (System.Exception ex)
                {
                    McpLog.Error($"Failed to configure {client.name}: {ex.Message}");
                }
            }

            EditorUtility.DisplayDialog(
                "Batch Configuration Complete",
                $"Successfully configured {successCount} out of {totalCount} clients.\n\n" +
                "Restart your AI clients for changes to take effect.",
                "OK"
            );

            Repaint();
        }

        private void RegisterWithClaudeCode(McpClient client)
        {
            try
            {
                string pythonDir = McpPathResolver.FindPackagePythonDirectory();
                string claudePath = ExecPath.ResolveClaude();
                string uvPath = ExecPath.ResolveUv() ?? "uv";

                string args = $"mcp add UnityMCP -- \"{uvPath}\" run --directory \"{pythonDir}\" server.py";

                if (!ExecPath.TryRun(claudePath, args, null, out var stdout, out var stderr, 15000, McpPathResolver.GetPathPrepend()))
                {
                    if ((stdout + stderr).Contains("already exists", System.StringComparison.OrdinalIgnoreCase))
                    {
                        CheckClientConfiguration(client);
                        EditorUtility.DisplayDialog("Claude Code", "MCP for Unity is already registered with Claude Code.", "OK");
                    }
                    else
                    {
                        throw new System.Exception($"Registration failed: {stderr}");
                    }
                }
                else
                {
                    CheckClientConfiguration(client);
                    EditorUtility.DisplayDialog("Claude Code", "Successfully registered MCP for Unity with Claude Code!", "OK");
                }
            }
            catch (System.Exception ex)
            {
                EditorUtility.DisplayDialog("Registration Error", $"Failed to register with Claude Code: {ex.Message}", "OK");
            }
        }

        private void UnregisterFromClaudeCode(McpClient client)
        {
            try
            {
                string claudePath = ExecPath.ResolveClaude();
                if (ExecPath.TryRun(claudePath, "mcp remove UnityMCP", null, out var stdout, out var stderr, 10000, McpPathResolver.GetPathPrepend()))
                {
                    CheckClientConfiguration(client);
                    EditorUtility.DisplayDialog("Claude Code", "Successfully unregistered MCP for Unity from Claude Code.", "OK");
                }
                else
                {
                    throw new System.Exception($"Unregistration failed: {stderr}");
                }
            }
            catch (System.Exception ex)
            {
                EditorUtility.DisplayDialog("Unregistration Error", $"Failed to unregister from Claude Code: {ex.Message}", "OK");
            }
        }

        private string PerformClientConfiguration(McpClient client)
        {
            // This mirrors the logic from MCPForUnityEditorWindow.ConfigureMcpClient
            string configPath = McpConfigurationHelper.GetClientConfigPath(client);
            string pythonDir = McpPathResolver.FindPackagePythonDirectory();

            if (string.IsNullOrEmpty(pythonDir))
            {
                return "Manual configuration required - Python server directory not found.";
            }

            McpConfigurationHelper.EnsureConfigDirectoryExists(configPath);
            // Use TOML writer for Codex; JSON writer for others
            if (client != null && client.mcpType == McpTypes.Codex)
            {
                return McpConfigurationHelper.ConfigureCodexClient(pythonDir, configPath, client);
            }
            else
            {
                return McpConfigurationHelper.WriteMcpConfiguration(pythonDir, configPath, client);
            }
        }

        private void ShowManualSetupInWizard(McpClient client)
        {
            string configPath = McpConfigurationHelper.GetClientConfigPath(client);
            string pythonDir = McpPathResolver.FindPackagePythonDirectory();
            string uvPath = ServerInstaller.FindUvPath();

            if (string.IsNullOrEmpty(uvPath))
            {
                EditorUtility.DisplayDialog("Manual Setup", "UV package manager not found. Please install UV first.", "OK");
                return;
            }

            // Build manual configuration using the sophisticated helper logic
            string result = (client != null && client.mcpType == McpTypes.Codex)
                ? McpConfigurationHelper.ConfigureCodexClient(pythonDir, configPath, client)
                : McpConfigurationHelper.WriteMcpConfiguration(pythonDir, configPath, client);
            string manualConfig;

            if (result == "Configured successfully")
            {
                // Read back the configuration that was written
                try
                {
                    manualConfig = System.IO.File.ReadAllText(configPath);
                }
                catch
                {
                    manualConfig = "Configuration written successfully, but could not read back for display.";
                }
            }
            else
            {
                manualConfig = $"Configuration failed: {result}";
            }

            EditorUtility.DisplayDialog(
                $"Manual Setup - {client.name}",
                $"Configuration file location:\n{configPath}\n\n" +
                $"Configuration result:\n{manualConfig}",
                "OK"
            );
        }

        private void CheckClientConfiguration(McpClient client)
        {
            // Basic status check - could be enhanced to mirror MCPForUnityEditorWindow logic
            try
            {
                string configPath = McpConfigurationHelper.GetClientConfigPath(client);
                if (System.IO.File.Exists(configPath))
                {
                    client.configStatus = "Configured";
                    client.status = McpStatus.Configured;
                }
                else
                {
                    client.configStatus = "Not Configured";
                    client.status = McpStatus.NotConfigured;
                }
            }
            catch
            {
                client.configStatus = "Error";
                client.status = McpStatus.Error;
            }
        }

        private void OpenInstallationUrls()
        {
            var (pythonUrl, uvUrl) = DependencyManager.GetInstallationUrls();

            bool openPython = EditorUtility.DisplayDialog(
                "Open Installation URLs",
                "Open Python installation page?",
                "Yes",
                "No"
            );

            if (openPython)
            {
                Application.OpenURL(pythonUrl);
            }

            bool openUV = EditorUtility.DisplayDialog(
                "Open Installation URLs",
                "Open UV installation page?",
                "Yes",
                "No"
            );

            if (openUV)
            {
                Application.OpenURL(uvUrl);
            }
        }
    }
}

```

--------------------------------------------------------------------------------
/UnityMcpBridge/Editor/Helpers/ServerInstaller.cs:
--------------------------------------------------------------------------------

```csharp
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;

namespace MCPForUnity.Editor.Helpers
{
    public static class ServerInstaller
    {
        private const string RootFolder = "UnityMCP";
        private const string ServerFolder = "UnityMcpServer";
        private const string VersionFileName = "server_version.txt";

        /// <summary>
        /// Ensures the mcp-for-unity-server is installed locally by copying from the embedded package source.
        /// No network calls or Git operations are performed.
        /// </summary>
        public static void EnsureServerInstalled()
        {
            try
            {
                string saveLocation = GetSaveLocation();
                TryCreateMacSymlinkForAppSupport();
                string destRoot = Path.Combine(saveLocation, ServerFolder);
                string destSrc = Path.Combine(destRoot, "src");

                // Detect legacy installs and version state (logs)
                DetectAndLogLegacyInstallStates(destRoot);

                // Resolve embedded source and versions
                if (!TryGetEmbeddedServerSource(out string embeddedSrc))
                {
                    throw new Exception("Could not find embedded UnityMcpServer/src in the package.");
                }
                string embeddedVer = ReadVersionFile(Path.Combine(embeddedSrc, VersionFileName)) ?? "unknown";
                string installedVer = ReadVersionFile(Path.Combine(destSrc, VersionFileName));

                bool destHasServer = File.Exists(Path.Combine(destSrc, "server.py"));
                bool needOverwrite = !destHasServer
                                     || string.IsNullOrEmpty(installedVer)
                                     || (!string.IsNullOrEmpty(embeddedVer) && CompareSemverSafe(installedVer, embeddedVer) < 0);

                // Ensure destination exists
                Directory.CreateDirectory(destRoot);

                if (needOverwrite)
                {
                    // Copy the entire UnityMcpServer folder (parent of src)
                    string embeddedRoot = Path.GetDirectoryName(embeddedSrc) ?? embeddedSrc; // go up from src to UnityMcpServer
                    CopyDirectoryRecursive(embeddedRoot, destRoot);
                    // Write/refresh version file
                    try { File.WriteAllText(Path.Combine(destSrc, VersionFileName), embeddedVer ?? "unknown"); } catch { }
                    McpLog.Info($"Installed/updated server to {destRoot} (version {embeddedVer}).");
                }

                // Cleanup legacy installs that are missing version or older than embedded
                foreach (var legacyRoot in GetLegacyRootsForDetection())
                {
                    try
                    {
                        string legacySrc = Path.Combine(legacyRoot, "src");
                        if (!File.Exists(Path.Combine(legacySrc, "server.py"))) continue;
                        string legacyVer = ReadVersionFile(Path.Combine(legacySrc, VersionFileName));
                        bool legacyOlder = string.IsNullOrEmpty(legacyVer)
                                           || (!string.IsNullOrEmpty(embeddedVer) && CompareSemverSafe(legacyVer, embeddedVer) < 0);
                        if (legacyOlder)
                        {
                            TryKillUvForPath(legacySrc);
                            try
                            {
                                Directory.Delete(legacyRoot, recursive: true);
                                McpLog.Info($"Removed legacy server at '{legacyRoot}'.");
                            }
                            catch (Exception ex)
                            {
                                McpLog.Warn($"Failed to remove legacy server at '{legacyRoot}': {ex.Message}");
                            }
                        }
                    }
                    catch { }
                }

                // Clear overrides that might point at legacy locations
                try
                {
                    EditorPrefs.DeleteKey("MCPForUnity.ServerSrc");
                    EditorPrefs.DeleteKey("MCPForUnity.PythonDirOverride");
                }
                catch { }
                return;
            }
            catch (Exception ex)
            {
                // If a usable server is already present (installed or embedded), don't fail hard—just warn.
                bool hasInstalled = false;
                try { hasInstalled = File.Exists(Path.Combine(GetServerPath(), "server.py")); } catch { }

                if (hasInstalled || TryGetEmbeddedServerSource(out _))
                {
                    McpLog.Warn($"Using existing server; skipped install. Details: {ex.Message}");
                    return;
                }

                McpLog.Error($"Failed to ensure server installation: {ex.Message}");
            }
        }

        public static string GetServerPath()
        {
            return Path.Combine(GetSaveLocation(), ServerFolder, "src");
        }

        /// <summary>
        /// Gets the platform-specific save location for the server.
        /// </summary>
        private static string GetSaveLocation()
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                // Use per-user LocalApplicationData for canonical install location
                var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
                                   ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) ?? string.Empty, "AppData", "Local");
                return Path.Combine(localAppData, RootFolder);
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                var xdg = Environment.GetEnvironmentVariable("XDG_DATA_HOME");
                if (string.IsNullOrEmpty(xdg))
                {
                    xdg = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) ?? string.Empty,
                                       ".local", "share");
                }
                return Path.Combine(xdg, RootFolder);
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                // On macOS, use LocalApplicationData (~/Library/Application Support)
                var localAppSupport = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
                // Unity/Mono may map LocalApplicationData to ~/.local/share on macOS; normalize to Application Support
                bool looksLikeXdg = !string.IsNullOrEmpty(localAppSupport) && localAppSupport.Replace('\\', '/').Contains("/.local/share");
                if (string.IsNullOrEmpty(localAppSupport) || looksLikeXdg)
                {
                    // Fallback: construct from $HOME
                    var home = Environment.GetFolderPath(Environment.SpecialFolder.Personal) ?? string.Empty;
                    localAppSupport = Path.Combine(home, "Library", "Application Support");
                }
                TryCreateMacSymlinkForAppSupport();
                return Path.Combine(localAppSupport, RootFolder);
            }
            throw new Exception("Unsupported operating system.");
        }

        /// <summary>
        /// On macOS, create a no-spaces symlink ~/Library/AppSupport -> ~/Library/Application Support
        /// to mitigate arg parsing and quoting issues in some MCP clients.
        /// Safe to call repeatedly.
        /// </summary>
        private static void TryCreateMacSymlinkForAppSupport()
        {
            try
            {
                if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return;
                string home = Environment.GetFolderPath(Environment.SpecialFolder.Personal) ?? string.Empty;
                if (string.IsNullOrEmpty(home)) return;

                string canonical = Path.Combine(home, "Library", "Application Support");
                string symlink = Path.Combine(home, "Library", "AppSupport");

                // If symlink exists already, nothing to do
                if (Directory.Exists(symlink) || File.Exists(symlink)) return;

                // Create symlink only if canonical exists
                if (!Directory.Exists(canonical)) return;

                // Use 'ln -s' to create a directory symlink (macOS)
                var psi = new System.Diagnostics.ProcessStartInfo
                {
                    FileName = "/bin/ln",
                    Arguments = $"-s \"{canonical}\" \"{symlink}\"",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                };
                using var p = System.Diagnostics.Process.Start(psi);
                p?.WaitForExit(2000);
            }
            catch { /* best-effort */ }
        }

        private static bool IsDirectoryWritable(string path)
        {
            try
            {
                File.Create(Path.Combine(path, "test.txt")).Dispose();
                File.Delete(Path.Combine(path, "test.txt"));
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Checks if the server is installed at the specified location.
        /// </summary>
        private static bool IsServerInstalled(string location)
        {
            return Directory.Exists(location)
                && File.Exists(Path.Combine(location, ServerFolder, "src", "server.py"));
        }

        /// <summary>
        /// Detects legacy installs or older versions and logs findings (no deletion yet).
        /// </summary>
        private static void DetectAndLogLegacyInstallStates(string canonicalRoot)
        {
            try
            {
                string canonicalSrc = Path.Combine(canonicalRoot, "src");
                // Normalize canonical root for comparisons
                string normCanonicalRoot = NormalizePathSafe(canonicalRoot);
                string embeddedSrc = null;
                TryGetEmbeddedServerSource(out embeddedSrc);

                string embeddedVer = ReadVersionFile(Path.Combine(embeddedSrc ?? string.Empty, VersionFileName));
                string installedVer = ReadVersionFile(Path.Combine(canonicalSrc, VersionFileName));

                // Legacy paths (macOS/Linux .config; Windows roaming as example)
                foreach (var legacyRoot in GetLegacyRootsForDetection())
                {
                    // Skip logging for the canonical root itself
                    if (PathsEqualSafe(legacyRoot, normCanonicalRoot))
                        continue;
                    string legacySrc = Path.Combine(legacyRoot, "src");
                    bool hasServer = File.Exists(Path.Combine(legacySrc, "server.py"));
                    string legacyVer = ReadVersionFile(Path.Combine(legacySrc, VersionFileName));

                    if (hasServer)
                    {
                        // Case 1: No version file
                        if (string.IsNullOrEmpty(legacyVer))
                        {
                            McpLog.Info("Detected legacy install without version file at: " + legacyRoot, always: false);
                        }

                        // Case 2: Lives in legacy path
                        McpLog.Info("Detected legacy install path: " + legacyRoot, always: false);

                        // Case 3: Has version but appears older than embedded
                        if (!string.IsNullOrEmpty(embeddedVer) && !string.IsNullOrEmpty(legacyVer) && CompareSemverSafe(legacyVer, embeddedVer) < 0)
                        {
                            McpLog.Info($"Legacy install version {legacyVer} is older than embedded {embeddedVer}", always: false);
                        }
                    }
                }

                // Also log if canonical is missing version (treated as older)
                if (Directory.Exists(canonicalRoot))
                {
                    if (string.IsNullOrEmpty(installedVer))
                    {
                        McpLog.Info("Canonical install missing version file (treat as older). Path: " + canonicalRoot, always: false);
                    }
                    else if (!string.IsNullOrEmpty(embeddedVer) && CompareSemverSafe(installedVer, embeddedVer) < 0)
                    {
                        McpLog.Info($"Canonical install version {installedVer} is older than embedded {embeddedVer}", always: false);
                    }
                }
            }
            catch (Exception ex)
            {
                McpLog.Warn("Detect legacy/version state failed: " + ex.Message);
            }
        }

        private static string NormalizePathSafe(string path)
        {
            try { return string.IsNullOrEmpty(path) ? path : Path.GetFullPath(path.Trim()); }
            catch { return path; }
        }

        private static bool PathsEqualSafe(string a, string b)
        {
            if (string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b)) return false;
            string na = NormalizePathSafe(a);
            string nb = NormalizePathSafe(b);
            try
            {
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    return string.Equals(na, nb, StringComparison.OrdinalIgnoreCase);
                }
                return string.Equals(na, nb, StringComparison.Ordinal);
            }
            catch { return false; }
        }

        private static IEnumerable<string> GetLegacyRootsForDetection()
        {
            var roots = new System.Collections.Generic.List<string>();
            string home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) ?? string.Empty;
            // macOS/Linux legacy
            roots.Add(Path.Combine(home, ".config", "UnityMCP", "UnityMcpServer"));
            roots.Add(Path.Combine(home, ".local", "share", "UnityMCP", "UnityMcpServer"));
            // Windows roaming example
            try
            {
                string roaming = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) ?? string.Empty;
                if (!string.IsNullOrEmpty(roaming))
                    roots.Add(Path.Combine(roaming, "UnityMCP", "UnityMcpServer"));
                // Windows legacy: early installers/dev scripts used %LOCALAPPDATA%\Programs\UnityMCP\UnityMcpServer
                // Detect this location so we can clean up older copies during install/update.
                string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) ?? string.Empty;
                if (!string.IsNullOrEmpty(localAppData))
                    roots.Add(Path.Combine(localAppData, "Programs", "UnityMCP", "UnityMcpServer"));
            }
            catch { }
            return roots;
        }

        private static void TryKillUvForPath(string serverSrcPath)
        {
            try
            {
                if (string.IsNullOrEmpty(serverSrcPath)) return;
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return;

                var psi = new System.Diagnostics.ProcessStartInfo
                {
                    FileName = "/usr/bin/pgrep",
                    Arguments = $"-f \"uv .*--directory {serverSrcPath}\"",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                };
                using var p = System.Diagnostics.Process.Start(psi);
                if (p == null) return;
                string outp = p.StandardOutput.ReadToEnd();
                p.WaitForExit(1500);
                if (p.ExitCode == 0 && !string.IsNullOrEmpty(outp))
                {
                    foreach (var line in outp.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        if (int.TryParse(line.Trim(), out int pid))
                        {
                            try { System.Diagnostics.Process.GetProcessById(pid).Kill(); } catch { }
                        }
                    }
                }
            }
            catch { }
        }

        private static string ReadVersionFile(string path)
        {
            try
            {
                if (string.IsNullOrEmpty(path) || !File.Exists(path)) return null;
                string v = File.ReadAllText(path).Trim();
                return string.IsNullOrEmpty(v) ? null : v;
            }
            catch { return null; }
        }

        private static int CompareSemverSafe(string a, string b)
        {
            try
            {
                if (string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b)) return 0;
                var ap = a.Split('.');
                var bp = b.Split('.');
                for (int i = 0; i < Math.Max(ap.Length, bp.Length); i++)
                {
                    int ai = (i < ap.Length && int.TryParse(ap[i], out var t1)) ? t1 : 0;
                    int bi = (i < bp.Length && int.TryParse(bp[i], out var t2)) ? t2 : 0;
                    if (ai != bi) return ai.CompareTo(bi);
                }
                return 0;
            }
            catch { return 0; }
        }

        /// <summary>
        /// Attempts to locate the embedded UnityMcpServer/src directory inside the installed package
        /// or common development locations.
        /// </summary>
        private static bool TryGetEmbeddedServerSource(out string srcPath)
        {
            return ServerPathResolver.TryFindEmbeddedServerSource(out srcPath);
        }

        private static readonly string[] _skipDirs = { ".venv", "__pycache__", ".pytest_cache", ".mypy_cache", ".git" };
        private static void CopyDirectoryRecursive(string sourceDir, string destinationDir)
        {
            Directory.CreateDirectory(destinationDir);

            foreach (string filePath in Directory.GetFiles(sourceDir))
            {
                string fileName = Path.GetFileName(filePath);
                string destFile = Path.Combine(destinationDir, fileName);
                File.Copy(filePath, destFile, overwrite: true);
            }

            foreach (string dirPath in Directory.GetDirectories(sourceDir))
            {
                string dirName = Path.GetFileName(dirPath);
                foreach (var skip in _skipDirs)
                {
                    if (dirName.Equals(skip, StringComparison.OrdinalIgnoreCase))
                        goto NextDir;
                }
                try { if ((File.GetAttributes(dirPath) & FileAttributes.ReparsePoint) != 0) continue; } catch { }
                string destSubDir = Path.Combine(destinationDir, dirName);
                CopyDirectoryRecursive(dirPath, destSubDir);
            NextDir:;
            }
        }

        public static bool RebuildMcpServer()
        {
            try
            {
                // Find embedded source
                if (!TryGetEmbeddedServerSource(out string embeddedSrc))
                {
                    Debug.LogError("RebuildMcpServer: Could not find embedded server source.");
                    return false;
                }

                string saveLocation = GetSaveLocation();
                string destRoot = Path.Combine(saveLocation, ServerFolder);
                string destSrc = Path.Combine(destRoot, "src");

                // Kill any running uv processes for this server
                TryKillUvForPath(destSrc);

                // Delete the entire installed server directory
                if (Directory.Exists(destRoot))
                {
                    try
                    {
                        Directory.Delete(destRoot, recursive: true);
                        Debug.Log($"<b><color=#2EA3FF>MCP-FOR-UNITY</color></b>: Deleted existing server at {destRoot}");
                    }
                    catch (Exception ex)
                    {
                        Debug.LogError($"Failed to delete existing server: {ex.Message}");
                        return false;
                    }
                }

                // Re-copy from embedded source
                string embeddedRoot = Path.GetDirectoryName(embeddedSrc) ?? embeddedSrc;
                Directory.CreateDirectory(destRoot);
                CopyDirectoryRecursive(embeddedRoot, destRoot);

                // Write version file
                string embeddedVer = ReadVersionFile(Path.Combine(embeddedSrc, VersionFileName)) ?? "unknown";
                try
                {
                    File.WriteAllText(Path.Combine(destSrc, VersionFileName), embeddedVer);
                }
                catch (Exception ex)
                {
                    Debug.LogWarning($"Failed to write version file: {ex.Message}");
                }

                Debug.Log($"<b><color=#2EA3FF>MCP-FOR-UNITY</color></b>: Server rebuilt successfully at {destRoot} (version {embeddedVer})");
                return true;
            }
            catch (Exception ex)
            {
                Debug.LogError($"RebuildMcpServer failed: {ex.Message}");
                return false;
            }
        }

        internal static string FindUvPath()
        {
            // Allow user override via EditorPrefs
            try
            {
                string overridePath = EditorPrefs.GetString("MCPForUnity.UvPath", string.Empty);
                if (!string.IsNullOrEmpty(overridePath) && File.Exists(overridePath))
                {
                    if (ValidateUvBinary(overridePath)) return overridePath;
                }
            }
            catch { }

            string home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) ?? string.Empty;

            // Platform-specific candidate lists
            string[] candidates;
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) ?? string.Empty;
                string programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) ?? string.Empty;
                string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) ?? string.Empty;

                // Fast path: resolve from PATH first
                try
                {
                    var wherePsi = new System.Diagnostics.ProcessStartInfo
                    {
                        FileName = "where",
                        Arguments = "uv.exe",
                        UseShellExecute = false,
                        RedirectStandardOutput = true,
                        RedirectStandardError = true,
                        CreateNoWindow = true
                    };
                    using var wp = System.Diagnostics.Process.Start(wherePsi);
                    string output = wp.StandardOutput.ReadToEnd().Trim();
                    wp.WaitForExit(1500);
                    if (wp.ExitCode == 0 && !string.IsNullOrEmpty(output))
                    {
                        foreach (var line in output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
                        {
                            string path = line.Trim();
                            if (File.Exists(path) && ValidateUvBinary(path)) return path;
                        }
                    }
                }
                catch { }

                // Windows Store (PythonSoftwareFoundation) install location probe
                // Example: %LOCALAPPDATA%\Packages\PythonSoftwareFoundation.Python.3.13_*\LocalCache\local-packages\Python313\Scripts\uv.exe
                try
                {
                    string pkgsRoot = Path.Combine(localAppData, "Packages");
                    if (Directory.Exists(pkgsRoot))
                    {
                        var pythonPkgs = Directory.GetDirectories(pkgsRoot, "PythonSoftwareFoundation.Python.*", SearchOption.TopDirectoryOnly)
                                                 .OrderByDescending(p => p, StringComparer.OrdinalIgnoreCase);
                        foreach (var pkg in pythonPkgs)
                        {
                            string localCache = Path.Combine(pkg, "LocalCache", "local-packages");
                            if (!Directory.Exists(localCache)) continue;
                            var pyRoots = Directory.GetDirectories(localCache, "Python*", SearchOption.TopDirectoryOnly)
                                                   .OrderByDescending(d => d, StringComparer.OrdinalIgnoreCase);
                            foreach (var pyRoot in pyRoots)
                            {
                                string uvExe = Path.Combine(pyRoot, "Scripts", "uv.exe");
                                if (File.Exists(uvExe) && ValidateUvBinary(uvExe)) return uvExe;
                            }
                        }
                    }
                }
                catch { }

                candidates = new[]
                {
                    // Preferred: WinGet Links shims (stable entrypoints)
                    // Per-user shim (LOCALAPPDATA) → machine-wide shim (Program Files\WinGet\Links)
                    Path.Combine(localAppData, "Microsoft", "WinGet", "Links", "uv.exe"),
                    Path.Combine(programFiles, "WinGet", "Links", "uv.exe"),

                    // Common per-user installs
                    Path.Combine(localAppData, @"Programs\Python\Python313\Scripts\uv.exe"),
                    Path.Combine(localAppData, @"Programs\Python\Python312\Scripts\uv.exe"),
                    Path.Combine(localAppData, @"Programs\Python\Python311\Scripts\uv.exe"),
                    Path.Combine(localAppData, @"Programs\Python\Python310\Scripts\uv.exe"),
                    Path.Combine(appData, @"Python\Python313\Scripts\uv.exe"),
                    Path.Combine(appData, @"Python\Python312\Scripts\uv.exe"),
                    Path.Combine(appData, @"Python\Python311\Scripts\uv.exe"),
                    Path.Combine(appData, @"Python\Python310\Scripts\uv.exe"),

                    // Program Files style installs (if a native installer was used)
                    Path.Combine(programFiles, @"uv\uv.exe"),

                    // Try simple name resolution later via PATH
                    "uv.exe",
                    "uv"
                };
            }
            else
            {
                candidates = new[]
                {
                    "/opt/homebrew/bin/uv",
                    "/usr/local/bin/uv",
                    "/usr/bin/uv",
                    "/opt/local/bin/uv",
                    Path.Combine(home, ".local", "bin", "uv"),
                    "/opt/homebrew/opt/uv/bin/uv",
                    // Framework Python installs
                    "/Library/Frameworks/Python.framework/Versions/3.13/bin/uv",
                    "/Library/Frameworks/Python.framework/Versions/3.12/bin/uv",
                    // Fallback to PATH resolution by name
                    "uv"
                };
            }

            foreach (string c in candidates)
            {
                try
                {
                    if (File.Exists(c) && ValidateUvBinary(c)) return c;
                }
                catch { /* ignore */ }
            }

            // Use platform-appropriate which/where to resolve from PATH (non-Windows handled here; Windows tried earlier)
            try
            {
                if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    var whichPsi = new System.Diagnostics.ProcessStartInfo
                    {
                        FileName = "/usr/bin/which",
                        Arguments = "uv",
                        UseShellExecute = false,
                        RedirectStandardOutput = true,
                        RedirectStandardError = true,
                        CreateNoWindow = true
                    };
                    try
                    {
                        // Prepend common user-local and package manager locations so 'which' can see them in Unity's GUI env
                        string homeDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) ?? string.Empty;
                        string prepend = string.Join(":", new[]
                        {
                            System.IO.Path.Combine(homeDir, ".local", "bin"),
                            "/opt/homebrew/bin",
                            "/usr/local/bin",
                            "/usr/bin",
                            "/bin"
                        });
                        string currentPath = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
                        whichPsi.EnvironmentVariables["PATH"] = string.IsNullOrEmpty(currentPath) ? prepend : (prepend + ":" + currentPath);
                    }
                    catch { }
                    using var wp = System.Diagnostics.Process.Start(whichPsi);
                    string output = wp.StandardOutput.ReadToEnd().Trim();
                    wp.WaitForExit(3000);
                    if (wp.ExitCode == 0 && !string.IsNullOrEmpty(output) && File.Exists(output))
                    {
                        if (ValidateUvBinary(output)) return output;
                    }
                }
            }
            catch { }

            // Manual PATH scan
            try
            {
                string pathEnv = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
                string[] parts = pathEnv.Split(Path.PathSeparator);
                foreach (string part in parts)
                {
                    try
                    {
                        // Check both uv and uv.exe
                        string candidateUv = Path.Combine(part, "uv");
                        string candidateUvExe = Path.Combine(part, "uv.exe");
                        if (File.Exists(candidateUv) && ValidateUvBinary(candidateUv)) return candidateUv;
                        if (File.Exists(candidateUvExe) && ValidateUvBinary(candidateUvExe)) return candidateUvExe;
                    }
                    catch { }
                }
            }
            catch { }

            return null;
        }

        private static bool ValidateUvBinary(string uvPath)
        {
            try
            {
                var psi = new System.Diagnostics.ProcessStartInfo
                {
                    FileName = uvPath,
                    Arguments = "--version",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                };
                using var p = System.Diagnostics.Process.Start(psi);
                if (!p.WaitForExit(5000)) { try { p.Kill(); } catch { } return false; }
                if (p.ExitCode == 0)
                {
                    string output = p.StandardOutput.ReadToEnd().Trim();
                    return output.StartsWith("uv ");
                }
            }
            catch { }
            return false;
        }
    }
}

```

--------------------------------------------------------------------------------
/TestProjects/UnityMCPTests/Assets/Scripts/LongUnityScriptClaudeTest.cs:
--------------------------------------------------------------------------------

```csharp
using UnityEngine;
using System.Collections.Generic;

// Standalone, dependency-free long script for Claude NL/T editing tests.
// Intentionally verbose to simulate a complex gameplay script without external packages.
public class LongUnityScriptClaudeTest : MonoBehaviour
{
    [Header("Core References")]
    public Transform reachOrigin;
    public Animator animator;

    [Header("State")]
    private Transform currentTarget;
    private Transform previousTarget;
    private float lastTargetFoundTime;

    [Header("Held Objects")]
    private readonly List<Transform> heldObjects = new List<Transform>();

    // Accumulators used by padding methods to avoid complete no-ops
    private int padAccumulator = 0;
    private Vector3 padVector = Vector3.zero;


    [Header("Tuning")]
    public float maxReachDistance = 2f;
    public float maxHorizontalDistance = 1.0f;
    public float maxVerticalDistance = 1.0f;

    // Public accessors used by NL tests
    public bool HasTarget() { return currentTarget != null; }
    public Transform GetCurrentTarget() => currentTarget;

    // Simple selection logic (self-contained)
    private Transform FindBestTarget()
    {
        if (reachOrigin == null) return null;
        // Dummy: prefer previously seen target within distance
        if (currentTarget != null && Vector3.Distance(reachOrigin.position, currentTarget.position) <= maxReachDistance)
            return currentTarget;
        return null;
    }

    private void HandleTargetSwitch(Transform next)
    {
        if (next == currentTarget) return;
        previousTarget = currentTarget;
        currentTarget = next;
        lastTargetFoundTime = Time.time;
    }

    private void LateUpdate()
    {
        // Keep file long with harmless per-frame work
        if (currentTarget == null && previousTarget != null)
        {
            // decay previous reference over time
            if (Time.time - lastTargetFoundTime > 0.5f) previousTarget = null;
        }
    }

    // NL tests sometimes add comments above Update() as an anchor
    private void Update()
    {
        if (reachOrigin == null) return;
        var best = FindBestTarget();
        if (best != null) HandleTargetSwitch(best);
    }


    // Dummy reach/hold API (no external deps)
    public void OnObjectHeld(Transform t)
    {
        if (t == null) return;
        if (!heldObjects.Contains(t)) heldObjects.Add(t);
        animator?.SetInteger("objectsHeld", heldObjects.Count);
    }

    public void OnObjectPlaced()
    {
        if (heldObjects.Count == 0) return;
        heldObjects.RemoveAt(heldObjects.Count - 1);
        animator?.SetInteger("objectsHeld", heldObjects.Count);
    }

    // More padding: repetitive blocks with slight variations
    #region Padding Blocks
    private Vector3 AccumulateBlend(Transform t)
    {
        if (t == null || reachOrigin == null) return Vector3.zero;
        Vector3 local = reachOrigin.InverseTransformPoint(t.position);
        float bx = Mathf.Clamp(local.x / Mathf.Max(0.001f, maxHorizontalDistance), -1f, 1f);
        float by = Mathf.Clamp(local.y / Mathf.Max(0.001f, maxVerticalDistance), -1f, 1f);
        return new Vector3(bx, by, 0f);
    }

    private void ApplyBlend(Vector3 blend)
    {
        if (animator == null) return;
        animator.SetFloat("reachX", blend.x);
        animator.SetFloat("reachY", blend.y);
    }

    public void TickBlendOnce()
    {
        var b = AccumulateBlend(currentTarget);
        ApplyBlend(b);
    }

    // A long series of small no-op methods to bulk up the file without adding deps
    private void Step001() { }
    private void Step002() { }
    private void Step003() { }
    private void Step004() { }
    private void Step005() { }
    private void Step006() { }
    private void Step007() { }
    private void Step008() { }
    private void Step009() { }
    private void Step010() { }
    private void Step011() { }
    private void Step012() { }
    private void Step013() { }
    private void Step014() { }
    private void Step015() { }
    private void Step016() { }
    private void Step017() { }
    private void Step018() { }
    private void Step019() { }
    private void Step020() { }
    private void Step021() { }
    private void Step022() { }
    private void Step023() { }
    private void Step024() { }
    private void Step025() { }
    private void Step026() { }
    private void Step027() { }
    private void Step028() { }
    private void Step029() { }
    private void Step030() { }
    private void Step031() { }
    private void Step032() { }
    private void Step033() { }
    private void Step034() { }
    private void Step035() { }
    private void Step036() { }
    private void Step037() { }
    private void Step038() { }
    private void Step039() { }
    private void Step040() { }
    private void Step041() { }
    private void Step042() { }
    private void Step043() { }
    private void Step044() { }
    private void Step045() { }
    private void Step046() { }
    private void Step047() { }
    private void Step048() { }
    private void Step049() { }
    private void Step050() { }
    #endregion
    #region MassivePadding
    private void Pad0051()
    {
    }
    private void Pad0052()
    {
    }
    private void Pad0053()
    {
    }
    private void Pad0054()
    {
    }
    private void Pad0055()
    {
    }
    private void Pad0056()
    {
    }
    private void Pad0057()
    {
    }
    private void Pad0058()
    {
    }
    private void Pad0059()
    {
    }
    private void Pad0060()
    {
    }
    private void Pad0061()
    {
    }
    private void Pad0062()
    {
    }
    private void Pad0063()
    {
    }
    private void Pad0064()
    {
    }
    private void Pad0065()
    {
    }
    private void Pad0066()
    {
    }
    private void Pad0067()
    {
    }
    private void Pad0068()
    {
    }
    private void Pad0069()
    {
    }
    private void Pad0070()
    {
    }
    private void Pad0071()
    {
    }
    private void Pad0072()
    {
    }
    private void Pad0073()
    {
    }
    private void Pad0074()
    {
    }
    private void Pad0075()
    {
    }
    private void Pad0076()
    {
    }
    private void Pad0077()
    {
    }
    private void Pad0078()
    {
    }
    private void Pad0079()
    {
    }
    private void Pad0080()
    {
    }
    private void Pad0081()
    {
    }
    private void Pad0082()
    {
    }
    private void Pad0083()
    {
    }
    private void Pad0084()
    {
    }
    private void Pad0085()
    {
    }
    private void Pad0086()
    {
    }
    private void Pad0087()
    {
    }
    private void Pad0088()
    {
    }
    private void Pad0089()
    {
    }
    private void Pad0090()
    {
    }
    private void Pad0091()
    {
    }
    private void Pad0092()
    {
    }
    private void Pad0093()
    {
    }
    private void Pad0094()
    {
    }
    private void Pad0095()
    {
    }
    private void Pad0096()
    {
    }
    private void Pad0097()
    {
    }
    private void Pad0098()
    {
    }
    private void Pad0099()
    {
    }
    private void Pad0100()
    {
        // lightweight math to give this padding method some substance
        padAccumulator = (padAccumulator * 1664525 + 1013904223 + 100) & 0x7fffffff;
        float t = (padAccumulator % 1000) * 0.001f;
        padVector.x = Mathf.Lerp(padVector.x, t, 0.1f);
        padVector.y = Mathf.Lerp(padVector.y, 1f - t, 0.1f);
        padVector.z = 0f;
    }
    private void Pad0101()
    {
    }
    private void Pad0102()
    {
    }
    private void Pad0103()
    {
    }
    private void Pad0104()
    {
    }
    private void Pad0105()
    {
    }
    private void Pad0106()
    {
    }
    private void Pad0107()
    {
    }
    private void Pad0108()
    {
    }
    private void Pad0109()
    {
    }
    private void Pad0110()
    {
    }
    private void Pad0111()
    {
    }
    private void Pad0112()
    {
    }
    private void Pad0113()
    {
    }
    private void Pad0114()
    {
    }
    private void Pad0115()
    {
    }
    private void Pad0116()
    {
    }
    private void Pad0117()
    {
    }
    private void Pad0118()
    {
    }
    private void Pad0119()
    {
    }
    private void Pad0120()
    {
    }
    private void Pad0121()
    {
    }
    private void Pad0122()
    {
    }
    private void Pad0123()
    {
    }
    private void Pad0124()
    {
    }
    private void Pad0125()
    {
    }
    private void Pad0126()
    {
    }
    private void Pad0127()
    {
    }
    private void Pad0128()
    {
    }
    private void Pad0129()
    {
    }
    private void Pad0130()
    {
    }
    private void Pad0131()
    {
    }
    private void Pad0132()
    {
    }
    private void Pad0133()
    {
    }
    private void Pad0134()
    {
    }
    private void Pad0135()
    {
    }
    private void Pad0136()
    {
    }
    private void Pad0137()
    {
    }
    private void Pad0138()
    {
    }
    private void Pad0139()
    {
    }
    private void Pad0140()
    {
    }
    private void Pad0141()
    {
    }
    private void Pad0142()
    {
    }
    private void Pad0143()
    {
    }
    private void Pad0144()
    {
    }
    private void Pad0145()
    {
    }
    private void Pad0146()
    {
    }
    private void Pad0147()
    {
    }
    private void Pad0148()
    {
    }
    private void Pad0149()
    {
    }
    private void Pad0150()
    {
        // lightweight math to give this padding method some substance
        padAccumulator = (padAccumulator * 1664525 + 1013904223 + 150) & 0x7fffffff;
        float t = (padAccumulator % 1000) * 0.001f;
        padVector.x = Mathf.Lerp(padVector.x, t, 0.1f);
        padVector.y = Mathf.Lerp(padVector.y, 1f - t, 0.1f);
        padVector.z = 0f;
    }
    private void Pad0151()
    {
    }
    private void Pad0152()
    {
    }
    private void Pad0153()
    {
    }
    private void Pad0154()
    {
    }
    private void Pad0155()
    {
    }
    private void Pad0156()
    {
    }
    private void Pad0157()
    {
    }
    private void Pad0158()
    {
    }
    private void Pad0159()
    {
    }
    private void Pad0160()
    {
    }
    private void Pad0161()
    {
    }
    private void Pad0162()
    {
    }
    private void Pad0163()
    {
    }
    private void Pad0164()
    {
    }
    private void Pad0165()
    {
    }
    private void Pad0166()
    {
    }
    private void Pad0167()
    {
    }
    private void Pad0168()
    {
    }
    private void Pad0169()
    {
    }
    private void Pad0170()
    {
    }
    private void Pad0171()
    {
    }
    private void Pad0172()
    {
    }
    private void Pad0173()
    {
    }
    private void Pad0174()
    {
    }
    private void Pad0175()
    {
    }
    private void Pad0176()
    {
    }
    private void Pad0177()
    {
    }
    private void Pad0178()
    {
    }
    private void Pad0179()
    {
    }
    private void Pad0180()
    {
    }
    private void Pad0181()
    {
    }
    private void Pad0182()
    {
    }
    private void Pad0183()
    {
    }
    private void Pad0184()
    {
    }
    private void Pad0185()
    {
    }
    private void Pad0186()
    {
    }
    private void Pad0187()
    {
    }
    private void Pad0188()
    {
    }
    private void Pad0189()
    {
    }
    private void Pad0190()
    {
    }
    private void Pad0191()
    {
    }
    private void Pad0192()
    {
    }
    private void Pad0193()
    {
    }
    private void Pad0194()
    {
    }
    private void Pad0195()
    {
    }
    private void Pad0196()
    {
    }
    private void Pad0197()
    {
    }
    private void Pad0198()
    {
    }
    private void Pad0199()
    {
    }
    private void Pad0200()
    {
        // lightweight math to give this padding method some substance
        padAccumulator = (padAccumulator * 1664525 + 1013904223 + 200) & 0x7fffffff;
        float t = (padAccumulator % 1000) * 0.001f;
        padVector.x = Mathf.Lerp(padVector.x, t, 0.1f);
        padVector.y = Mathf.Lerp(padVector.y, 1f - t, 0.1f);
        padVector.z = 0f;
    }
    private void Pad0201()
    {
    }
    private void Pad0202()
    {
    }
    private void Pad0203()
    {
    }
    private void Pad0204()
    {
    }
    private void Pad0205()
    {
    }
    private void Pad0206()
    {
    }
    private void Pad0207()
    {
    }
    private void Pad0208()
    {
    }
    private void Pad0209()
    {
    }
    private void Pad0210()
    {
    }
    private void Pad0211()
    {
    }
    private void Pad0212()
    {
    }
    private void Pad0213()
    {
    }
    private void Pad0214()
    {
    }
    private void Pad0215()
    {
    }
    private void Pad0216()
    {
    }
    private void Pad0217()
    {
    }
    private void Pad0218()
    {
    }
    private void Pad0219()
    {
    }
    private void Pad0220()
    {
    }
    private void Pad0221()
    {
    }
    private void Pad0222()
    {
    }
    private void Pad0223()
    {
    }
    private void Pad0224()
    {
    }
    private void Pad0225()
    {
    }
    private void Pad0226()
    {
    }
    private void Pad0227()
    {
    }
    private void Pad0228()
    {
    }
    private void Pad0229()
    {
    }
    private void Pad0230()
    {
    }
    private void Pad0231()
    {
    }
    private void Pad0232()
    {
    }
    private void Pad0233()
    {
    }
    private void Pad0234()
    {
    }
    private void Pad0235()
    {
    }
    private void Pad0236()
    {
    }
    private void Pad0237()
    {
    }
    private void Pad0238()
    {
    }
    private void Pad0239()
    {
    }
    private void Pad0240()
    {
    }
    private void Pad0241()
    {
    }
    private void Pad0242()
    {
    }
    private void Pad0243()
    {
    }
    private void Pad0244()
    {
    }
    private void Pad0245()
    {
    }
    private void Pad0246()
    {
    }
    private void Pad0247()
    {
    }
    private void Pad0248()
    {
    }
    private void Pad0249()
    {
    }
    private void Pad0250()
    {
        // lightweight math to give this padding method some substance
        padAccumulator = (padAccumulator * 1664525 + 1013904223 + 250) & 0x7fffffff;
        float t = (padAccumulator % 1000) * 0.001f;
        padVector.x = Mathf.Lerp(padVector.x, t, 0.1f);
        padVector.y = Mathf.Lerp(padVector.y, 1f - t, 0.1f);
        padVector.z = 0f;
    }
    private void Pad0251()
    {
    }
    private void Pad0252()
    {
    }
    private void Pad0253()
    {
    }
    private void Pad0254()
    {
    }
    private void Pad0255()
    {
    }
    private void Pad0256()
    {
    }
    private void Pad0257()
    {
    }
    private void Pad0258()
    {
    }
    private void Pad0259()
    {
    }
    private void Pad0260()
    {
    }
    private void Pad0261()
    {
    }
    private void Pad0262()
    {
    }
    private void Pad0263()
    {
    }
    private void Pad0264()
    {
    }
    private void Pad0265()
    {
    }
    private void Pad0266()
    {
    }
    private void Pad0267()
    {
    }
    private void Pad0268()
    {
    }
    private void Pad0269()
    {
    }
    private void Pad0270()
    {
    }
    private void Pad0271()
    {
    }
    private void Pad0272()
    {
    }
    private void Pad0273()
    {
    }
    private void Pad0274()
    {
    }
    private void Pad0275()
    {
    }
    private void Pad0276()
    {
    }
    private void Pad0277()
    {
    }
    private void Pad0278()
    {
    }
    private void Pad0279()
    {
    }
    private void Pad0280()
    {
    }
    private void Pad0281()
    {
    }
    private void Pad0282()
    {
    }
    private void Pad0283()
    {
    }
    private void Pad0284()
    {
    }
    private void Pad0285()
    {
    }
    private void Pad0286()
    {
    }
    private void Pad0287()
    {
    }
    private void Pad0288()
    {
    }
    private void Pad0289()
    {
    }
    private void Pad0290()
    {
    }
    private void Pad0291()
    {
    }
    private void Pad0292()
    {
    }
    private void Pad0293()
    {
    }
    private void Pad0294()
    {
    }
    private void Pad0295()
    {
    }
    private void Pad0296()
    {
    }
    private void Pad0297()
    {
    }
    private void Pad0298()
    {
    }
    private void Pad0299()
    {
    }
    private void Pad0300()
    {
        // lightweight math to give this padding method some substance
        padAccumulator = (padAccumulator * 1664525 + 1013904223 + 300) & 0x7fffffff;
        float t = (padAccumulator % 1000) * 0.001f;
        padVector.x = Mathf.Lerp(padVector.x, t, 0.1f);
        padVector.y = Mathf.Lerp(padVector.y, 1f - t, 0.1f);
        padVector.z = 0f;
    }
    private void Pad0301()
    {
    }
    private void Pad0302()
    {
    }
    private void Pad0303()
    {
    }
    private void Pad0304()
    {
    }
    private void Pad0305()
    {
    }
    private void Pad0306()
    {
    }
    private void Pad0307()
    {
    }
    private void Pad0308()
    {
    }
    private void Pad0309()
    {
    }
    private void Pad0310()
    {
    }
    private void Pad0311()
    {
    }
    private void Pad0312()
    {
    }
    private void Pad0313()
    {
    }
    private void Pad0314()
    {
    }
    private void Pad0315()
    {
    }
    private void Pad0316()
    {
    }
    private void Pad0317()
    {
    }
    private void Pad0318()
    {
    }
    private void Pad0319()
    {
    }
    private void Pad0320()
    {
    }
    private void Pad0321()
    {
    }
    private void Pad0322()
    {
    }
    private void Pad0323()
    {
    }
    private void Pad0324()
    {
    }
    private void Pad0325()
    {
    }
    private void Pad0326()
    {
    }
    private void Pad0327()
    {
    }
    private void Pad0328()
    {
    }
    private void Pad0329()
    {
    }
    private void Pad0330()
    {
    }
    private void Pad0331()
    {
    }
    private void Pad0332()
    {
    }
    private void Pad0333()
    {
    }
    private void Pad0334()
    {
    }
    private void Pad0335()
    {
    }
    private void Pad0336()
    {
    }
    private void Pad0337()
    {
    }
    private void Pad0338()
    {
    }
    private void Pad0339()
    {
    }
    private void Pad0340()
    {
    }
    private void Pad0341()
    {
    }
    private void Pad0342()
    {
    }
    private void Pad0343()
    {
    }
    private void Pad0344()
    {
    }
    private void Pad0345()
    {
    }
    private void Pad0346()
    {
    }
    private void Pad0347()
    {
    }
    private void Pad0348()
    {
    }
    private void Pad0349()
    {
    }
    private void Pad0350()
    {
        // lightweight math to give this padding method some substance
        padAccumulator = (padAccumulator * 1664525 + 1013904223 + 350) & 0x7fffffff;
        float t = (padAccumulator % 1000) * 0.001f;
        padVector.x = Mathf.Lerp(padVector.x, t, 0.1f);
        padVector.y = Mathf.Lerp(padVector.y, 1f - t, 0.1f);
        padVector.z = 0f;
    }
    private void Pad0351()
    {
    }
    private void Pad0352()
    {
    }
    private void Pad0353()
    {
    }
    private void Pad0354()
    {
    }
    private void Pad0355()
    {
    }
    private void Pad0356()
    {
    }
    private void Pad0357()
    {
    }
    private void Pad0358()
    {
    }
    private void Pad0359()
    {
    }
    private void Pad0360()
    {
    }
    private void Pad0361()
    {
    }
    private void Pad0362()
    {
    }
    private void Pad0363()
    {
    }
    private void Pad0364()
    {
    }
    private void Pad0365()
    {
    }
    private void Pad0366()
    {
    }
    private void Pad0367()
    {
    }
    private void Pad0368()
    {
    }
    private void Pad0369()
    {
    }
    private void Pad0370()
    {
    }
    private void Pad0371()
    {
    }
    private void Pad0372()
    {
    }
    private void Pad0373()
    {
    }
    private void Pad0374()
    {
    }
    private void Pad0375()
    {
    }
    private void Pad0376()
    {
    }
    private void Pad0377()
    {
    }
    private void Pad0378()
    {
    }
    private void Pad0379()
    {
    }
    private void Pad0380()
    {
    }
    private void Pad0381()
    {
    }
    private void Pad0382()
    {
    }
    private void Pad0383()
    {
    }
    private void Pad0384()
    {
    }
    private void Pad0385()
    {
    }
    private void Pad0386()
    {
    }
    private void Pad0387()
    {
    }
    private void Pad0388()
    {
    }
    private void Pad0389()
    {
    }
    private void Pad0390()
    {
    }
    private void Pad0391()
    {
    }
    private void Pad0392()
    {
    }
    private void Pad0393()
    {
    }
    private void Pad0394()
    {
    }
    private void Pad0395()
    {
    }
    private void Pad0396()
    {
    }
    private void Pad0397()
    {
    }
    private void Pad0398()
    {
    }
    private void Pad0399()
    {
    }
    private void Pad0400()
    {
        // lightweight math to give this padding method some substance
        padAccumulator = (padAccumulator * 1664525 + 1013904223 + 400) & 0x7fffffff;
        float t = (padAccumulator % 1000) * 0.001f;
        padVector.x = Mathf.Lerp(padVector.x, t, 0.1f);
        padVector.y = Mathf.Lerp(padVector.y, 1f - t, 0.1f);
        padVector.z = 0f;
    }
    private void Pad0401()
    {
    }
    private void Pad0402()
    {
    }
    private void Pad0403()
    {
    }
    private void Pad0404()
    {
    }
    private void Pad0405()
    {
    }
    private void Pad0406()
    {
    }
    private void Pad0407()
    {
    }
    private void Pad0408()
    {
    }
    private void Pad0409()
    {
    }
    private void Pad0410()
    {
    }
    private void Pad0411()
    {
    }
    private void Pad0412()
    {
    }
    private void Pad0413()
    {
    }
    private void Pad0414()
    {
    }
    private void Pad0415()
    {
    }
    private void Pad0416()
    {
    }
    private void Pad0417()
    {
    }
    private void Pad0418()
    {
    }
    private void Pad0419()
    {
    }
    private void Pad0420()
    {
    }
    private void Pad0421()
    {
    }
    private void Pad0422()
    {
    }
    private void Pad0423()
    {
    }
    private void Pad0424()
    {
    }
    private void Pad0425()
    {
    }
    private void Pad0426()
    {
    }
    private void Pad0427()
    {
    }
    private void Pad0428()
    {
    }
    private void Pad0429()
    {
    }
    private void Pad0430()
    {
    }
    private void Pad0431()
    {
    }
    private void Pad0432()
    {
    }
    private void Pad0433()
    {
    }
    private void Pad0434()
    {
    }
    private void Pad0435()
    {
    }
    private void Pad0436()
    {
    }
    private void Pad0437()
    {
    }
    private void Pad0438()
    {
    }
    private void Pad0439()
    {
    }
    private void Pad0440()
    {
    }
    private void Pad0441()
    {
    }
    private void Pad0442()
    {
    }
    private void Pad0443()
    {
    }
    private void Pad0444()
    {
    }
    private void Pad0445()
    {
    }
    private void Pad0446()
    {
    }
    private void Pad0447()
    {
    }
    private void Pad0448()
    {
    }
    private void Pad0449()
    {
    }
    private void Pad0450()
    {
        // lightweight math to give this padding method some substance
        padAccumulator = (padAccumulator * 1664525 + 1013904223 + 450) & 0x7fffffff;
        float t = (padAccumulator % 1000) * 0.001f;
        padVector.x = Mathf.Lerp(padVector.x, t, 0.1f);
        padVector.y = Mathf.Lerp(padVector.y, 1f - t, 0.1f);
        padVector.z = 0f;
    }
    private void Pad0451()
    {
    }
    private void Pad0452()
    {
    }
    private void Pad0453()
    {
    }
    private void Pad0454()
    {
    }
    private void Pad0455()
    {
    }
    private void Pad0456()
    {
    }
    private void Pad0457()
    {
    }
    private void Pad0458()
    {
    }
    private void Pad0459()
    {
    }
    private void Pad0460()
    {
    }
    private void Pad0461()
    {
    }
    private void Pad0462()
    {
    }
    private void Pad0463()
    {
    }
    private void Pad0464()
    {
    }
    private void Pad0465()
    {
    }
    private void Pad0466()
    {
    }
    private void Pad0467()
    {
    }
    private void Pad0468()
    {
    }
    private void Pad0469()
    {
    }
    private void Pad0470()
    {
    }
    private void Pad0471()
    {
    }
    private void Pad0472()
    {
    }
    private void Pad0473()
    {
    }
    private void Pad0474()
    {
    }
    private void Pad0475()
    {
    }
    private void Pad0476()
    {
    }
    private void Pad0477()
    {
    }
    private void Pad0478()
    {
    }
    private void Pad0479()
    {
    }
    private void Pad0480()
    {
    }
    private void Pad0481()
    {
    }
    private void Pad0482()
    {
    }
    private void Pad0483()
    {
    }
    private void Pad0484()
    {
    }
    private void Pad0485()
    {
    }
    private void Pad0486()
    {
    }
    private void Pad0487()
    {
    }
    private void Pad0488()
    {
    }
    private void Pad0489()
    {
    }
    private void Pad0490()
    {
    }
    private void Pad0491()
    {
    }
    private void Pad0492()
    {
    }
    private void Pad0493()
    {
    }
    private void Pad0494()
    {
    }
    private void Pad0495()
    {
    }
    private void Pad0496()
    {
    }
    private void Pad0497()
    {
    }
    private void Pad0498()
    {
    }
    private void Pad0499()
    {
    }
    private void Pad0500()
    {
        // lightweight math to give this padding method some substance
        padAccumulator = (padAccumulator * 1664525 + 1013904223 + 500) & 0x7fffffff;
        float t = (padAccumulator % 1000) * 0.001f;
        padVector.x = Mathf.Lerp(padVector.x, t, 0.1f);
        padVector.y = Mathf.Lerp(padVector.y, 1f - t, 0.1f);
        padVector.z = 0f;
    }
    private void Pad0501()
    {
    }
    private void Pad0502()
    {
    }
    private void Pad0503()
    {
    }
    private void Pad0504()
    {
    }
    private void Pad0505()
    {
    }
    private void Pad0506()
    {
    }
    private void Pad0507()
    {
    }
    private void Pad0508()
    {
    }
    private void Pad0509()
    {
    }
    private void Pad0510()
    {
    }
    private void Pad0511()
    {
    }
    private void Pad0512()
    {
    }
    private void Pad0513()
    {
    }
    private void Pad0514()
    {
    }
    private void Pad0515()
    {
    }
    private void Pad0516()
    {
    }
    private void Pad0517()
    {
    }
    private void Pad0518()
    {
    }
    private void Pad0519()
    {
    }
    private void Pad0520()
    {
    }
    private void Pad0521()
    {
    }
    private void Pad0522()
    {
    }
    private void Pad0523()
    {
    }
    private void Pad0524()
    {
    }
    private void Pad0525()
    {
    }
    private void Pad0526()
    {
    }
    private void Pad0527()
    {
    }
    private void Pad0528()
    {
    }
    private void Pad0529()
    {
    }
    private void Pad0530()
    {
    }
    private void Pad0531()
    {
    }
    private void Pad0532()
    {
    }
    private void Pad0533()
    {
    }
    private void Pad0534()
    {
    }
    private void Pad0535()
    {
    }
    private void Pad0536()
    {
    }
    private void Pad0537()
    {
    }
    private void Pad0538()
    {
    }
    private void Pad0539()
    {
    }
    private void Pad0540()
    {
    }
    private void Pad0541()
    {
    }
    private void Pad0542()
    {
    }
    private void Pad0543()
    {
    }
    private void Pad0544()
    {
    }
    private void Pad0545()
    {
    }
    private void Pad0546()
    {
    }
    private void Pad0547()
    {
    }
    private void Pad0548()
    {
    }
    private void Pad0549()
    {
    }
    private void Pad0550()
    {
        // lightweight math to give this padding method some substance
        padAccumulator = (padAccumulator * 1664525 + 1013904223 + 550) & 0x7fffffff;
        float t = (padAccumulator % 1000) * 0.001f;
        padVector.x = Mathf.Lerp(padVector.x, t, 0.1f);
        padVector.y = Mathf.Lerp(padVector.y, 1f - t, 0.1f);
        padVector.z = 0f;
    }
    private void Pad0551()
    {
    }
    private void Pad0552()
    {
    }
    private void Pad0553()
    {
    }
    private void Pad0554()
    {
    }
    private void Pad0555()
    {
    }
    private void Pad0556()
    {
    }
    private void Pad0557()
    {
    }
    private void Pad0558()
    {
    }
    private void Pad0559()
    {
    }
    private void Pad0560()
    {
    }
    private void Pad0561()
    {
    }
    private void Pad0562()
    {
    }
    private void Pad0563()
    {
    }
    private void Pad0564()
    {
    }
    private void Pad0565()
    {
    }
    private void Pad0566()
    {
    }
    private void Pad0567()
    {
    }
    private void Pad0568()
    {
    }
    private void Pad0569()
    {
    }
    private void Pad0570()
    {
    }
    private void Pad0571()
    {
    }
    private void Pad0572()
    {
    }
    private void Pad0573()
    {
    }
    private void Pad0574()
    {
    }
    private void Pad0575()
    {
    }
    private void Pad0576()
    {
    }
    private void Pad0577()
    {
    }
    private void Pad0578()
    {
    }
    private void Pad0579()
    {
    }
    private void Pad0580()
    {
    }
    private void Pad0581()
    {
    }
    private void Pad0582()
    {
    }
    private void Pad0583()
    {
    }
    private void Pad0584()
    {
    }
    private void Pad0585()
    {
    }
    private void Pad0586()
    {
    }
    private void Pad0587()
    {
    }
    private void Pad0588()
    {
    }
    private void Pad0589()
    {
    }
    private void Pad0590()
    {
    }
    private void Pad0591()
    {
    }
    private void Pad0592()
    {
    }
    private void Pad0593()
    {
    }
    private void Pad0594()
    {
    }
    private void Pad0595()
    {
    }
    private void Pad0596()
    {
    }
    private void Pad0597()
    {
    }
    private void Pad0598()
    {
    }
    private void Pad0599()
    {
    }
    private void Pad0600()
    {
        // lightweight math to give this padding method some substance
        padAccumulator = (padAccumulator * 1664525 + 1013904223 + 600) & 0x7fffffff;
        float t = (padAccumulator % 1000) * 0.001f;
        padVector.x = Mathf.Lerp(padVector.x, t, 0.1f);
        padVector.y = Mathf.Lerp(padVector.y, 1f - t, 0.1f);
        padVector.z = 0f;
    }
    private void Pad0601()
    {
    }
    private void Pad0602()
    {
    }
    private void Pad0603()
    {
    }
    private void Pad0604()
    {
    }
    private void Pad0605()
    {
    }
    private void Pad0606()
    {
    }
    private void Pad0607()
    {
    }
    private void Pad0608()
    {
    }
    private void Pad0609()
    {
    }
    private void Pad0610()
    {
    }
    private void Pad0611()
    {
    }
    private void Pad0612()
    {
    }
    private void Pad0613()
    {
    }
    private void Pad0614()
    {
    }
    private void Pad0615()
    {
    }
    private void Pad0616()
    {
    }
    private void Pad0617()
    {
    }
    private void Pad0618()
    {
    }
    private void Pad0619()
    {
    }
    private void Pad0620()
    {
    }
    private void Pad0621()
    {
    }
    private void Pad0622()
    {
    }
    private void Pad0623()
    {
    }
    private void Pad0624()
    {
    }
    private void Pad0625()
    {
    }
    private void Pad0626()
    {
    }
    private void Pad0627()
    {
    }
    private void Pad0628()
    {
    }
    private void Pad0629()
    {
    }
    private void Pad0630()
    {
    }
    private void Pad0631()
    {
    }
    private void Pad0632()
    {
    }
    private void Pad0633()
    {
    }
    private void Pad0634()
    {
    }
    private void Pad0635()
    {
    }
    private void Pad0636()
    {
    }
    private void Pad0637()
    {
    }
    private void Pad0638()
    {
    }
    private void Pad0639()
    {
    }
    private void Pad0640()
    {
    }
    private void Pad0641()
    {
    }
    private void Pad0642()
    {
    }
    private void Pad0643()
    {
    }
    private void Pad0644()
    {
    }
    private void Pad0645()
    {
    }
    private void Pad0646()
    {
    }
    private void Pad0647()
    {
    }
    private void Pad0648()
    {
    }
    private void Pad0649()
    {
    }
    private void Pad0650()
    {
        // lightweight math to give this padding method some substance
        padAccumulator = (padAccumulator * 1664525 + 1013904223 + 650) & 0x7fffffff;
        float t = (padAccumulator % 1000) * 0.001f;
        padVector.x = Mathf.Lerp(padVector.x, t, 0.1f);
        padVector.y = Mathf.Lerp(padVector.y, 1f - t, 0.1f);
        padVector.z = 0f;
    }
    #endregion

}

```

--------------------------------------------------------------------------------
/MCPForUnity/Editor/Windows/MCPForUnityEditorWindowNew.cs:
--------------------------------------------------------------------------------

```csharp
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using UnityEditor;
using UnityEditor.UIElements; // For Unity 2021 compatibility
using UnityEngine;
using UnityEngine.UIElements;
using MCPForUnity.Editor.Data;
using MCPForUnity.Editor.Helpers;
using MCPForUnity.Editor.Models;
using MCPForUnity.Editor.Services;

namespace MCPForUnity.Editor.Windows
{
    public class MCPForUnityEditorWindowNew : EditorWindow
    {
        // Protocol enum for future HTTP support
        private enum ConnectionProtocol
        {
            Stdio,
            // HTTPStreaming // Future
        }

        // Settings UI Elements
        private Label versionLabel;
        private Toggle debugLogsToggle;
        private EnumField validationLevelField;
        private Label validationDescription;
        private Foldout advancedSettingsFoldout;
        private TextField mcpServerPathOverride;
        private TextField uvPathOverride;
        private Button browsePythonButton;
        private Button clearPythonButton;
        private Button browseUvButton;
        private Button clearUvButton;
        private VisualElement mcpServerPathStatus;
        private VisualElement uvPathStatus;

        // Connection UI Elements
        private EnumField protocolDropdown;
        private TextField unityPortField;
        private TextField serverPortField;
        private VisualElement statusIndicator;
        private Label connectionStatusLabel;
        private Button connectionToggleButton;
        private VisualElement healthIndicator;
        private Label healthStatusLabel;
        private Button testConnectionButton;
        private VisualElement serverStatusBanner;
        private Label serverStatusMessage;
        private Button downloadServerButton;
        private Button rebuildServerButton;

        // Client UI Elements
        private DropdownField clientDropdown;
        private Button configureAllButton;
        private VisualElement clientStatusIndicator;
        private Label clientStatusLabel;
        private Button configureButton;
        private VisualElement claudeCliPathRow;
        private TextField claudeCliPath;
        private Button browseClaudeButton;
        private Foldout manualConfigFoldout;
        private TextField configPathField;
        private Button copyPathButton;
        private Button openFileButton;
        private TextField configJsonField;
        private Button copyJsonButton;
        private Label installationStepsLabel;

        // Data
        private readonly McpClients mcpClients = new();
        private int selectedClientIndex = 0;
        private ValidationLevel currentValidationLevel = ValidationLevel.Standard;

        // Validation levels matching the existing enum
        private enum ValidationLevel
        {
            Basic,
            Standard,
            Comprehensive,
            Strict
        }

        public static void ShowWindow()
        {
            var window = GetWindow<MCPForUnityEditorWindowNew>("MCP For Unity");
            window.minSize = new Vector2(500, 600);
        }
        public void CreateGUI()
        {
            // Determine base path (Package Manager vs Asset Store install)
            string basePath = AssetPathUtility.GetMcpPackageRootPath();

            // Load UXML
            var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(
                $"{basePath}/Editor/Windows/MCPForUnityEditorWindowNew.uxml"
            );

            if (visualTree == null)
            {
                McpLog.Error($"Failed to load UXML at: {basePath}/Editor/Windows/MCPForUnityEditorWindowNew.uxml");
                return;
            }

            visualTree.CloneTree(rootVisualElement);

            // Load USS
            var styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>(
                $"{basePath}/Editor/Windows/MCPForUnityEditorWindowNew.uss"
            );

            if (styleSheet != null)
            {
                rootVisualElement.styleSheets.Add(styleSheet);
            }

            // Cache UI elements
            CacheUIElements();

            // Initialize UI
            InitializeUI();

            // Register callbacks
            RegisterCallbacks();

            // Initial update
            UpdateConnectionStatus();
            UpdateServerStatusBanner();
            UpdateClientStatus();
            UpdatePathOverrides();
            // Technically not required to connect, but if we don't do this, the UI will be blank
            UpdateManualConfiguration();
            UpdateClaudeCliPathVisibility();
        }

        private void OnEnable()
        {
            EditorApplication.update += OnEditorUpdate;
        }

        private void OnDisable()
        {
            EditorApplication.update -= OnEditorUpdate;
        }

        private void OnFocus()
        {
            // Only refresh data if UI is built
            if (rootVisualElement == null || rootVisualElement.childCount == 0)
                return;

            RefreshAllData();
        }

        private void OnEditorUpdate()
        {
            // Only update UI if it's built
            if (rootVisualElement == null || rootVisualElement.childCount == 0)
                return;

            UpdateConnectionStatus();
        }

        private void RefreshAllData()
        {
            // Update connection status
            UpdateConnectionStatus();

            // Auto-verify bridge health if connected
            if (MCPServiceLocator.Bridge.IsRunning)
            {
                VerifyBridgeConnection();
            }

            // Update path overrides
            UpdatePathOverrides();

            // Refresh selected client (may have been configured externally)
            if (selectedClientIndex >= 0 && selectedClientIndex < mcpClients.clients.Count)
            {
                var client = mcpClients.clients[selectedClientIndex];
                MCPServiceLocator.Client.CheckClientStatus(client);
                UpdateClientStatus();
                UpdateManualConfiguration();
                UpdateClaudeCliPathVisibility();
            }
        }

        private void CacheUIElements()
        {
            // Settings
            versionLabel = rootVisualElement.Q<Label>("version-label");
            debugLogsToggle = rootVisualElement.Q<Toggle>("debug-logs-toggle");
            validationLevelField = rootVisualElement.Q<EnumField>("validation-level");
            validationDescription = rootVisualElement.Q<Label>("validation-description");
            advancedSettingsFoldout = rootVisualElement.Q<Foldout>("advanced-settings-foldout");
            mcpServerPathOverride = rootVisualElement.Q<TextField>("python-path-override");
            uvPathOverride = rootVisualElement.Q<TextField>("uv-path-override");
            browsePythonButton = rootVisualElement.Q<Button>("browse-python-button");
            clearPythonButton = rootVisualElement.Q<Button>("clear-python-button");
            browseUvButton = rootVisualElement.Q<Button>("browse-uv-button");
            clearUvButton = rootVisualElement.Q<Button>("clear-uv-button");
            mcpServerPathStatus = rootVisualElement.Q<VisualElement>("mcp-server-path-status");
            uvPathStatus = rootVisualElement.Q<VisualElement>("uv-path-status");

            // Connection
            protocolDropdown = rootVisualElement.Q<EnumField>("protocol-dropdown");
            unityPortField = rootVisualElement.Q<TextField>("unity-port");
            serverPortField = rootVisualElement.Q<TextField>("server-port");
            statusIndicator = rootVisualElement.Q<VisualElement>("status-indicator");
            connectionStatusLabel = rootVisualElement.Q<Label>("connection-status");
            connectionToggleButton = rootVisualElement.Q<Button>("connection-toggle");
            healthIndicator = rootVisualElement.Q<VisualElement>("health-indicator");
            healthStatusLabel = rootVisualElement.Q<Label>("health-status");
            testConnectionButton = rootVisualElement.Q<Button>("test-connection-button");
            serverStatusBanner = rootVisualElement.Q<VisualElement>("server-status-banner");
            serverStatusMessage = rootVisualElement.Q<Label>("server-status-message");
            downloadServerButton = rootVisualElement.Q<Button>("download-server-button");
            rebuildServerButton = rootVisualElement.Q<Button>("rebuild-server-button");

            // Client
            clientDropdown = rootVisualElement.Q<DropdownField>("client-dropdown");
            configureAllButton = rootVisualElement.Q<Button>("configure-all-button");
            clientStatusIndicator = rootVisualElement.Q<VisualElement>("client-status-indicator");
            clientStatusLabel = rootVisualElement.Q<Label>("client-status");
            configureButton = rootVisualElement.Q<Button>("configure-button");
            claudeCliPathRow = rootVisualElement.Q<VisualElement>("claude-cli-path-row");
            claudeCliPath = rootVisualElement.Q<TextField>("claude-cli-path");
            browseClaudeButton = rootVisualElement.Q<Button>("browse-claude-button");
            manualConfigFoldout = rootVisualElement.Q<Foldout>("manual-config-foldout");
            configPathField = rootVisualElement.Q<TextField>("config-path");
            copyPathButton = rootVisualElement.Q<Button>("copy-path-button");
            openFileButton = rootVisualElement.Q<Button>("open-file-button");
            configJsonField = rootVisualElement.Q<TextField>("config-json");
            copyJsonButton = rootVisualElement.Q<Button>("copy-json-button");
            installationStepsLabel = rootVisualElement.Q<Label>("installation-steps");
        }

        private void InitializeUI()
        {
            // Settings Section
            UpdateVersionLabel();
            debugLogsToggle.value = EditorPrefs.GetBool("MCPForUnity.DebugLogs", false);

            validationLevelField.Init(ValidationLevel.Standard);
            int savedLevel = EditorPrefs.GetInt("MCPForUnity.ValidationLevel", 1);
            currentValidationLevel = (ValidationLevel)Mathf.Clamp(savedLevel, 0, 3);
            validationLevelField.value = currentValidationLevel;
            UpdateValidationDescription();

            // Advanced settings starts collapsed
            advancedSettingsFoldout.value = false;

            // Connection Section
            protocolDropdown.Init(ConnectionProtocol.Stdio);
            protocolDropdown.SetEnabled(false); // Disabled for now, only stdio supported

            unityPortField.value = MCPServiceLocator.Bridge.CurrentPort.ToString();
            serverPortField.value = "6500";

            // Client Configuration
            var clientNames = mcpClients.clients.Select(c => c.name).ToList();
            clientDropdown.choices = clientNames;
            if (clientNames.Count > 0)
            {
                clientDropdown.index = 0;
            }

            // Manual config starts collapsed
            manualConfigFoldout.value = false;

            // Claude CLI path row hidden by default
            claudeCliPathRow.style.display = DisplayStyle.None;
        }

        private void RegisterCallbacks()
        {
            // Settings callbacks
            debugLogsToggle.RegisterValueChangedCallback(evt =>
            {
                EditorPrefs.SetBool("MCPForUnity.DebugLogs", evt.newValue);
            });

            validationLevelField.RegisterValueChangedCallback(evt =>
            {
                currentValidationLevel = (ValidationLevel)evt.newValue;
                EditorPrefs.SetInt("MCPForUnity.ValidationLevel", (int)currentValidationLevel);
                UpdateValidationDescription();
            });

            // Advanced settings callbacks
            browsePythonButton.clicked += OnBrowsePythonClicked;
            clearPythonButton.clicked += OnClearPythonClicked;
            browseUvButton.clicked += OnBrowseUvClicked;
            clearUvButton.clicked += OnClearUvClicked;

            // Connection callbacks
            connectionToggleButton.clicked += OnConnectionToggleClicked;
            testConnectionButton.clicked += OnTestConnectionClicked;
            downloadServerButton.clicked += OnDownloadServerClicked;
            rebuildServerButton.clicked += OnRebuildServerClicked;

            // Client callbacks
            clientDropdown.RegisterValueChangedCallback(evt =>
            {
                selectedClientIndex = clientDropdown.index;
                UpdateClientStatus();
                UpdateManualConfiguration();
                UpdateClaudeCliPathVisibility();
            });

            configureAllButton.clicked += OnConfigureAllClientsClicked;
            configureButton.clicked += OnConfigureClicked;
            browseClaudeButton.clicked += OnBrowseClaudeClicked;
            copyPathButton.clicked += OnCopyPathClicked;
            openFileButton.clicked += OnOpenFileClicked;
            copyJsonButton.clicked += OnCopyJsonClicked;
        }

        private void UpdateValidationDescription()
        {
            validationDescription.text = GetValidationLevelDescription((int)currentValidationLevel);
        }

        private string GetValidationLevelDescription(int index)
        {
            return index switch
            {
                0 => "Only basic syntax checks (braces, quotes, comments)",
                1 => "Syntax checks + Unity best practices and warnings",
                2 => "All checks + semantic analysis and performance warnings",
                3 => "Full semantic validation with namespace/type resolution (requires Roslyn)",
                _ => "Standard validation"
            };
        }

        private void UpdateConnectionStatus()
        {
            var bridgeService = MCPServiceLocator.Bridge;
            bool isRunning = bridgeService.IsRunning;

            if (isRunning)
            {
                connectionStatusLabel.text = "Connected";
                statusIndicator.RemoveFromClassList("disconnected");
                statusIndicator.AddToClassList("connected");
                connectionToggleButton.text = "Stop";
            }
            else
            {
                connectionStatusLabel.text = "Disconnected";
                statusIndicator.RemoveFromClassList("connected");
                statusIndicator.AddToClassList("disconnected");
                connectionToggleButton.text = "Start";

                // Reset health status when disconnected
                healthStatusLabel.text = "Unknown";
                healthIndicator.RemoveFromClassList("healthy");
                healthIndicator.RemoveFromClassList("warning");
                healthIndicator.AddToClassList("unknown");
            }

            // Update ports
            unityPortField.value = bridgeService.CurrentPort.ToString();
        }

        private void UpdateClientStatus()
        {
            if (selectedClientIndex < 0 || selectedClientIndex >= mcpClients.clients.Count)
                return;

            var client = mcpClients.clients[selectedClientIndex];
            MCPServiceLocator.Client.CheckClientStatus(client);

            clientStatusLabel.text = client.GetStatusDisplayString();
            
            // Reset inline color style (clear error state from OnConfigureClicked)
            clientStatusLabel.style.color = StyleKeyword.Null;

            // Update status indicator color
            clientStatusIndicator.RemoveFromClassList("configured");
            clientStatusIndicator.RemoveFromClassList("not-configured");
            clientStatusIndicator.RemoveFromClassList("warning");

            switch (client.status)
            {
                case McpStatus.Configured:
                case McpStatus.Running:
                case McpStatus.Connected:
                    clientStatusIndicator.AddToClassList("configured");
                    break;
                case McpStatus.IncorrectPath:
                case McpStatus.CommunicationError:
                case McpStatus.NoResponse:
                    clientStatusIndicator.AddToClassList("warning");
                    break;
                default:
                    clientStatusIndicator.AddToClassList("not-configured");
                    break;
            }

            // Update configure button text for Claude Code
            if (client.mcpType == McpTypes.ClaudeCode)
            {
                bool isConfigured = client.status == McpStatus.Configured;
                configureButton.text = isConfigured ? "Unregister" : "Register";
            }
            else
            {
                configureButton.text = "Configure";
            }
        }

        private void UpdateManualConfiguration()
        {
            if (selectedClientIndex < 0 || selectedClientIndex >= mcpClients.clients.Count)
                return;

            var client = mcpClients.clients[selectedClientIndex];

            // Get config path
            string configPath = MCPServiceLocator.Client.GetConfigPath(client);
            configPathField.value = configPath;

            // Get config JSON
            string configJson = MCPServiceLocator.Client.GenerateConfigJson(client);
            configJsonField.value = configJson;

            // Get installation steps
            string steps = MCPServiceLocator.Client.GetInstallationSteps(client);
            installationStepsLabel.text = steps;
        }

        private void UpdateClaudeCliPathVisibility()
        {
            if (selectedClientIndex < 0 || selectedClientIndex >= mcpClients.clients.Count)
                return;

            var client = mcpClients.clients[selectedClientIndex];

            // Show Claude CLI path only for Claude Code client
            if (client.mcpType == McpTypes.ClaudeCode)
            {
                string claudePath = MCPServiceLocator.Paths.GetClaudeCliPath();
                if (string.IsNullOrEmpty(claudePath))
                {
                    // Show path selector if not found
                    claudeCliPathRow.style.display = DisplayStyle.Flex;
                    claudeCliPath.value = "Not found - click Browse to select";
                }
                else
                {
                    // Show detected path
                    claudeCliPathRow.style.display = DisplayStyle.Flex;
                    claudeCliPath.value = claudePath;
                }
            }
            else
            {
                claudeCliPathRow.style.display = DisplayStyle.None;
            }
        }

        private void UpdatePathOverrides()
        {
            var pathService = MCPServiceLocator.Paths;

            // MCP Server Path
            string mcpServerPath = pathService.GetMcpServerPath();
            if (pathService.HasMcpServerOverride)
            {
                mcpServerPathOverride.value = mcpServerPath ?? "(override set but invalid)";
            }
            else
            {
                mcpServerPathOverride.value = mcpServerPath ?? "(auto-detected)";
            }

            // Update status indicator
            mcpServerPathStatus.RemoveFromClassList("valid");
            mcpServerPathStatus.RemoveFromClassList("invalid");
            if (!string.IsNullOrEmpty(mcpServerPath) && File.Exists(Path.Combine(mcpServerPath, "server.py")))
            {
                mcpServerPathStatus.AddToClassList("valid");
            }
            else
            {
                mcpServerPathStatus.AddToClassList("invalid");
            }

            // UV Path
            string uvPath = pathService.GetUvPath();
            if (pathService.HasUvPathOverride)
            {
                uvPathOverride.value = uvPath ?? "(override set but invalid)";
            }
            else
            {
                uvPathOverride.value = uvPath ?? "(auto-detected)";
            }

            // Update status indicator
            uvPathStatus.RemoveFromClassList("valid");
            uvPathStatus.RemoveFromClassList("invalid");
            if (!string.IsNullOrEmpty(uvPath) && File.Exists(uvPath))
            {
                uvPathStatus.AddToClassList("valid");
            }
            else
            {
                uvPathStatus.AddToClassList("invalid");
            }
        }

        // Button callbacks
        private void OnConnectionToggleClicked()
        {
            var bridgeService = MCPServiceLocator.Bridge;

            if (bridgeService.IsRunning)
            {
                bridgeService.Stop();
            }
            else
            {
                bridgeService.Start();

                // Verify connection after starting (Option C: verify on connect)
                EditorApplication.delayCall += () =>
                {
                    if (bridgeService.IsRunning)
                    {
                        VerifyBridgeConnection();
                    }
                };
            }

            UpdateConnectionStatus();
        }

        private void OnTestConnectionClicked()
        {
            VerifyBridgeConnection();
        }

        private void VerifyBridgeConnection()
        {
            var bridgeService = MCPServiceLocator.Bridge;

            if (!bridgeService.IsRunning)
            {
                healthStatusLabel.text = "Disconnected";
                healthIndicator.RemoveFromClassList("healthy");
                healthIndicator.RemoveFromClassList("warning");
                healthIndicator.AddToClassList("unknown");
                McpLog.Warn("Cannot verify connection: Bridge is not running");
                return;
            }

            var result = bridgeService.Verify(bridgeService.CurrentPort);

            healthIndicator.RemoveFromClassList("healthy");
            healthIndicator.RemoveFromClassList("warning");
            healthIndicator.RemoveFromClassList("unknown");

            if (result.Success && result.PingSucceeded)
            {
                healthStatusLabel.text = "Healthy";
                healthIndicator.AddToClassList("healthy");
                McpLog.Info("Bridge verification successful");
            }
            else if (result.HandshakeValid)
            {
                healthStatusLabel.text = "Ping Failed";
                healthIndicator.AddToClassList("warning");
                McpLog.Warn($"Bridge verification warning: {result.Message}");
            }
            else
            {
                healthStatusLabel.text = "Unhealthy";
                healthIndicator.AddToClassList("warning");
                McpLog.Error($"Bridge verification failed: {result.Message}");
            }
        }

        private void OnDownloadServerClicked()
        {
            if (ServerInstaller.DownloadAndInstallServer())
            {
                UpdateServerStatusBanner();
                UpdatePathOverrides();
                EditorUtility.DisplayDialog(
                    "Download Complete",
                    "Server installed successfully! Start your connection and configure your MCP clients to begin.",
                    "OK"
                );
            }
        }

        private void OnRebuildServerClicked()
        {
            try
            {
                bool success = ServerInstaller.RebuildMcpServer();
                if (success)
                {
                    EditorUtility.DisplayDialog("MCP For Unity", "Server rebuilt successfully.", "OK");
                    UpdateServerStatusBanner();
                    UpdatePathOverrides();
                }
                else
                {
                    EditorUtility.DisplayDialog("MCP For Unity", "Rebuild failed. Please check Console for details.", "OK");
                }
            }
            catch (Exception ex)
            {
                McpLog.Error($"Failed to rebuild server: {ex.Message}");
                EditorUtility.DisplayDialog("MCP For Unity", $"Rebuild failed: {ex.Message}", "OK");
            }
        }

        private void UpdateServerStatusBanner()
        {
            bool hasEmbedded = ServerInstaller.HasEmbeddedServer();
            string installedVer = ServerInstaller.GetInstalledServerVersion();
            string packageVer = AssetPathUtility.GetPackageVersion();

            // Show/hide download vs rebuild buttons
            if (hasEmbedded)
            {
                downloadServerButton.style.display = DisplayStyle.None;
                rebuildServerButton.style.display = DisplayStyle.Flex;
            }
            else
            {
                downloadServerButton.style.display = DisplayStyle.Flex;
                rebuildServerButton.style.display = DisplayStyle.None;
            }

            // Update banner
            if (!hasEmbedded && string.IsNullOrEmpty(installedVer))
            {
                serverStatusMessage.text = "\u26A0 Server not installed. Click 'Download & Install Server' to get started.";
                serverStatusBanner.style.display = DisplayStyle.Flex;
            }
            else if (!hasEmbedded && !string.IsNullOrEmpty(installedVer) && installedVer != packageVer)
            {
                serverStatusMessage.text = $"\u26A0 Server update available (v{installedVer} \u2192 v{packageVer}). Update recommended.";
                serverStatusBanner.style.display = DisplayStyle.Flex;
            }
            else
            {
                serverStatusBanner.style.display = DisplayStyle.None;
            }
        }

        private void OnConfigureAllClientsClicked()
        {
            try
            {
                var summary = MCPServiceLocator.Client.ConfigureAllDetectedClients();

                // Build detailed message
                string message = summary.GetSummaryMessage() + "\n\n";
                foreach (var msg in summary.Messages)
                {
                    message += msg + "\n";
                }

                EditorUtility.DisplayDialog("Configure All Clients", message, "OK");

                // Refresh current client status
                if (selectedClientIndex >= 0 && selectedClientIndex < mcpClients.clients.Count)
                {
                    UpdateClientStatus();
                    UpdateManualConfiguration();
                }
            }
            catch (Exception ex)
            {
                EditorUtility.DisplayDialog("Configuration Failed", ex.Message, "OK");
            }
        }

        private void OnConfigureClicked()
        {
            if (selectedClientIndex < 0 || selectedClientIndex >= mcpClients.clients.Count)
                return;

            var client = mcpClients.clients[selectedClientIndex];

            try
            {
                if (client.mcpType == McpTypes.ClaudeCode)
                {
                    bool isConfigured = client.status == McpStatus.Configured;
                    if (isConfigured)
                    {
                        MCPServiceLocator.Client.UnregisterClaudeCode();
                    }
                    else
                    {
                        MCPServiceLocator.Client.RegisterClaudeCode();
                    }
                }
                else
                {
                    MCPServiceLocator.Client.ConfigureClient(client);
                }

                UpdateClientStatus();
                UpdateManualConfiguration();
            }
            catch (Exception ex)
            {
                clientStatusLabel.text = "Error";
                clientStatusLabel.style.color = Color.red;
                McpLog.Error($"Configuration failed: {ex.Message}");
                EditorUtility.DisplayDialog("Configuration Failed", ex.Message, "OK");
            }
        }

        private void OnBrowsePythonClicked()
        {
            string picked = EditorUtility.OpenFolderPanel("Select MCP Server Directory", Application.dataPath, "");
            if (!string.IsNullOrEmpty(picked))
            {
                try
                {
                    MCPServiceLocator.Paths.SetMcpServerOverride(picked);
                    UpdatePathOverrides();
                    McpLog.Info($"MCP server path override set to: {picked}");
                }
                catch (Exception ex)
                {
                    EditorUtility.DisplayDialog("Invalid Path", ex.Message, "OK");
                }
            }
        }

        private void OnClearPythonClicked()
        {
            MCPServiceLocator.Paths.ClearMcpServerOverride();
            UpdatePathOverrides();
            McpLog.Info("MCP server path override cleared");
        }

        private void OnBrowseUvClicked()
        {
            string suggested = RuntimeInformation.IsOSPlatform(OSPlatform.OSX)
                ? "/opt/homebrew/bin"
                : Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
            string picked = EditorUtility.OpenFilePanel("Select UV Executable", suggested, "");
            if (!string.IsNullOrEmpty(picked))
            {
                try
                {
                    MCPServiceLocator.Paths.SetUvPathOverride(picked);
                    UpdatePathOverrides();
                    McpLog.Info($"UV path override set to: {picked}");
                }
                catch (Exception ex)
                {
                    EditorUtility.DisplayDialog("Invalid Path", ex.Message, "OK");
                }
            }
        }

        private void OnClearUvClicked()
        {
            MCPServiceLocator.Paths.ClearUvPathOverride();
            UpdatePathOverrides();
            McpLog.Info("UV path override cleared");
        }

        private void OnBrowseClaudeClicked()
        {
            string suggested = RuntimeInformation.IsOSPlatform(OSPlatform.OSX)
                ? "/opt/homebrew/bin"
                : Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
            string picked = EditorUtility.OpenFilePanel("Select Claude CLI", suggested, "");
            if (!string.IsNullOrEmpty(picked))
            {
                try
                {
                    MCPServiceLocator.Paths.SetClaudeCliPathOverride(picked);
                    UpdateClaudeCliPathVisibility();
                    UpdateClientStatus();
                    McpLog.Info($"Claude CLI path override set to: {picked}");
                }
                catch (Exception ex)
                {
                    EditorUtility.DisplayDialog("Invalid Path", ex.Message, "OK");
                }
            }
        }

        private void OnCopyPathClicked()
        {
            EditorGUIUtility.systemCopyBuffer = configPathField.value;
            McpLog.Info("Config path copied to clipboard");
        }

        private void OnOpenFileClicked()
        {
            string path = configPathField.value;
            try
            {
                if (!File.Exists(path))
                {
                    EditorUtility.DisplayDialog("Open File", "The configuration file path does not exist.", "OK");
                    return;
                }

                Process.Start(new ProcessStartInfo
                {
                    FileName = path,
                    UseShellExecute = true
                });
            }
            catch (Exception ex)
            {
                McpLog.Error($"Failed to open file: {ex.Message}");
            }
        }

        private void OnCopyJsonClicked()
        {
            EditorGUIUtility.systemCopyBuffer = configJsonField.value;
            McpLog.Info("Configuration copied to clipboard");
        }

        private void UpdateVersionLabel()
        {
            string currentVersion = AssetPathUtility.GetPackageVersion();
            versionLabel.text = $"v{currentVersion}";

            // Check for updates using the service
            var updateCheck = MCPServiceLocator.Updates.CheckForUpdate(currentVersion);

            if (updateCheck.UpdateAvailable && !string.IsNullOrEmpty(updateCheck.LatestVersion))
            {
                // Update available - enhance the label
                versionLabel.text = $"\u2191 v{currentVersion} (Update available: v{updateCheck.LatestVersion})";
                versionLabel.style.color = new Color(1f, 0.7f, 0f); // Orange
                versionLabel.tooltip = $"Version {updateCheck.LatestVersion} is available. Update via Package Manager.\n\nGit URL: https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity";
            }
            else
            {
                versionLabel.style.color = StyleKeyword.Null; // Default color
                versionLabel.tooltip = $"Current version: {currentVersion}";
            }
        }

    }
}

```
Page 7/13FirstPrevNextLast