Skip to content

Commit daa105d

Browse files
committed
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
1 parent aa4fc1c commit daa105d

File tree

2 files changed

+60
-11
lines changed

2 files changed

+60
-11
lines changed

UnityMcpBridge/Editor/Data/McpClients.cs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,22 @@ public class McpClients
7070
"Claude",
7171
"claude_desktop_config.json"
7272
),
73-
linuxConfigPath = Path.Combine(
74-
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
75-
".config",
76-
"Claude",
77-
"claude_desktop_config.json"
78-
),
73+
// For macOS, Claude Desktop stores config under ~/Library/Application Support/Claude
74+
// For Linux, it remains under ~/.config/Claude
75+
linuxConfigPath = RuntimeInformation.IsOSPlatform(OSPlatform.OSX)
76+
? Path.Combine(
77+
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
78+
"Library",
79+
"Application Support",
80+
"Claude",
81+
"claude_desktop_config.json"
82+
)
83+
: Path.Combine(
84+
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
85+
".config",
86+
"Claude",
87+
"claude_desktop_config.json"
88+
),
7989
mcpType = McpTypes.ClaudeDesktop,
8090
configStatus = "Not Configured",
8191
},

UnityMcpBridge/Editor/Windows/MCPForUnityEditorWindow.cs

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,13 +1202,52 @@ private string WriteToConfig(string pythonDir, string configPath, McpClient mcpC
12021202
existingRoot = ConfigJsonBuilder.ApplyUnityServerToExistingConfig(existingRoot, uvPath, serverSrc, mcpClient);
12031203

12041204
string mergedJson = JsonConvert.SerializeObject(existingRoot, jsonSettings);
1205+
1206+
// Use a more robust atomic write pattern
12051207
string tmp = configPath + ".tmp";
1206-
// Write UTF-8 without BOM to avoid issues on Windows editors/tools
1207-
System.IO.File.WriteAllText(tmp, mergedJson, new System.Text.UTF8Encoding(false));
1208-
if (System.IO.File.Exists(configPath))
1209-
System.IO.File.Replace(tmp, configPath, null);
1210-
else
1208+
string backup = configPath + ".backup";
1209+
1210+
try
1211+
{
1212+
// Write to temp file first
1213+
System.IO.File.WriteAllText(tmp, mergedJson, new System.Text.UTF8Encoding(false));
1214+
1215+
// Create backup of existing file if it exists
1216+
if (System.IO.File.Exists(configPath))
1217+
{
1218+
System.IO.File.Copy(configPath, backup, true);
1219+
}
1220+
1221+
// Atomic move operation (more reliable than Replace on macOS)
1222+
if (System.IO.File.Exists(configPath))
1223+
{
1224+
System.IO.File.Delete(configPath);
1225+
}
12111226
System.IO.File.Move(tmp, configPath);
1227+
1228+
// Clean up backup
1229+
if (System.IO.File.Exists(backup))
1230+
{
1231+
System.IO.File.Delete(backup);
1232+
}
1233+
}
1234+
catch (Exception ex)
1235+
{
1236+
// Clean up temp file
1237+
try { if (System.IO.File.Exists(tmp)) System.IO.File.Delete(tmp); } catch { }
1238+
// Restore backup if it exists
1239+
try {
1240+
if (System.IO.File.Exists(backup))
1241+
{
1242+
if (System.IO.File.Exists(configPath))
1243+
{
1244+
System.IO.File.Delete(configPath);
1245+
}
1246+
System.IO.File.Move(backup, configPath);
1247+
}
1248+
} catch { }
1249+
throw new Exception($"Failed to write config file '{configPath}': {ex.Message}", ex);
1250+
}
12121251
try
12131252
{
12141253
if (IsValidUv(uvPath)) UnityEditor.EditorPrefs.SetString("MCPForUnity.UvPath", uvPath);

0 commit comments

Comments
 (0)