Fix Claude Desktop config path and atomic write issues

- Fix macOS path for Claude Desktop config: use ~/Library/Application Support/Claude/ instead of ~/.config/Claude/
- Improve atomic write pattern with backup/restore safety
- Replace File.Replace() with File.Move() for better macOS compatibility
- Add proper error handling and cleanup for file operations
- Resolves issue where installer couldn't find Claude Desktop config on macOS
main
David Sarno 2025-08-25 14:51:03 -07:00
parent aa4fc1c0ea
commit daa105da35
2 changed files with 60 additions and 11 deletions

View File

@ -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",
},

View File

@ -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);