diff --git a/UnityMcpBridge/Editor/Data/McpClients.cs b/UnityMcpBridge/Editor/Data/McpClients.cs index be21770..7b150b7 100644 --- a/UnityMcpBridge/Editor/Data/McpClients.cs +++ b/UnityMcpBridge/Editor/Data/McpClients.cs @@ -70,12 +70,22 @@ namespace MCPForUnity.Editor.Data "Claude", "claude_desktop_config.json" ), - linuxConfigPath = Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), - ".config", - "Claude", - "claude_desktop_config.json" - ), + // For macOS, Claude Desktop stores config under ~/Library/Application Support/Claude + // For Linux, it remains under ~/.config/Claude + linuxConfigPath = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) + ? Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), + "Library", + "Application Support", + "Claude", + "claude_desktop_config.json" + ) + : Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), + ".config", + "Claude", + "claude_desktop_config.json" + ), mcpType = McpTypes.ClaudeDesktop, configStatus = "Not Configured", }, diff --git a/UnityMcpBridge/Editor/Windows/MCPForUnityEditorWindow.cs b/UnityMcpBridge/Editor/Windows/MCPForUnityEditorWindow.cs index f29a192..12a8303 100644 --- a/UnityMcpBridge/Editor/Windows/MCPForUnityEditorWindow.cs +++ b/UnityMcpBridge/Editor/Windows/MCPForUnityEditorWindow.cs @@ -1202,13 +1202,52 @@ namespace MCPForUnity.Editor.Windows existingRoot = ConfigJsonBuilder.ApplyUnityServerToExistingConfig(existingRoot, uvPath, serverSrc, mcpClient); string mergedJson = JsonConvert.SerializeObject(existingRoot, jsonSettings); + + // Use a more robust atomic write pattern string tmp = configPath + ".tmp"; - // Write UTF-8 without BOM to avoid issues on Windows editors/tools - System.IO.File.WriteAllText(tmp, mergedJson, new System.Text.UTF8Encoding(false)); - if (System.IO.File.Exists(configPath)) - System.IO.File.Replace(tmp, configPath, null); - else + string backup = configPath + ".backup"; + + try + { + // Write to temp file first + System.IO.File.WriteAllText(tmp, mergedJson, new System.Text.UTF8Encoding(false)); + + // Create backup of existing file if it exists + if (System.IO.File.Exists(configPath)) + { + System.IO.File.Copy(configPath, backup, true); + } + + // Atomic move operation (more reliable than Replace on macOS) + if (System.IO.File.Exists(configPath)) + { + System.IO.File.Delete(configPath); + } System.IO.File.Move(tmp, configPath); + + // Clean up backup + if (System.IO.File.Exists(backup)) + { + System.IO.File.Delete(backup); + } + } + catch (Exception ex) + { + // Clean up temp file + try { if (System.IO.File.Exists(tmp)) System.IO.File.Delete(tmp); } catch { } + // Restore backup if it exists + try { + if (System.IO.File.Exists(backup)) + { + if (System.IO.File.Exists(configPath)) + { + System.IO.File.Delete(configPath); + } + System.IO.File.Move(backup, configPath); + } + } catch { } + throw new Exception($"Failed to write config file '{configPath}': {ex.Message}", ex); + } try { if (IsValidUv(uvPath)) UnityEditor.EditorPrefs.SetString("MCPForUnity.UvPath", uvPath);