Skip to content

Commit b5389c3

Browse files
committed
fix: Fix for miss configuration on Claude Code MCP auto config as reported in issue #63
1 parent ac4a46a commit b5389c3

File tree

1 file changed

+84
-31
lines changed

1 file changed

+84
-31
lines changed

Editor/Utils/McpUtils.cs

Lines changed: 84 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -186,36 +186,17 @@ private static bool AddToConfigFile(string configFilePath, bool useTabsIndentati
186186

187187
// Generate fresh MCP config JSON
188188
string mcpConfigJson = GenerateMcpConfigJson(useTabsIndentation);
189-
190-
// Parse the MCP config JSON
191-
JObject mcpConfig = JObject.Parse(mcpConfigJson);
192189

193190
try
194191
{
192+
// Parse the MCP config JSON
193+
JObject mcpConfig = JObject.Parse(mcpConfigJson);
194+
195195
// Check if the file exists
196196
if (File.Exists(configFilePath))
197197
{
198-
// Read the existing config
199-
string existingConfigJson = File.ReadAllText(configFilePath);
200-
JObject existingConfig = string.IsNullOrEmpty(existingConfigJson) ? new JObject() : JObject.Parse(existingConfigJson);
201-
202-
// Merge the mcpServers from our config into the existing config
203-
if (mcpConfig["mcpServers"] != null && mcpConfig["mcpServers"] is JObject mcpServers)
198+
if (TryMergeMcpServers(configFilePath, mcpConfig, productName))
204199
{
205-
// Create mcpServers object if it doesn't exist
206-
if (existingConfig["mcpServers"] == null)
207-
{
208-
existingConfig["mcpServers"] = new JObject();
209-
}
210-
211-
// Add or update the mcp-unity server config
212-
if (mcpServers["mcp-unity"] != null)
213-
{
214-
((JObject)existingConfig["mcpServers"])["mcp-unity"] = mcpServers["mcp-unity"];
215-
}
216-
217-
// Write the updated config back to the file
218-
File.WriteAllText(configFilePath, existingConfig.ToString(Formatting.Indented));
219200
return true;
220201
}
221202
}
@@ -337,24 +318,28 @@ private static string GetCursorConfigPath()
337318
/// <returns>The path to the Claude Code config file</returns>
338319
private static string GetClaudeCodeConfigPath()
339320
{
340-
string basePath;
321+
// Returns the absolute path to the global Claude configuration file.
322+
// Windows: %USERPROFILE%\.claude.json
323+
// macOS/Linux: $HOME/.claude.json
324+
string homeDir;
325+
341326
if (Application.platform == RuntimePlatform.WindowsEditor)
342327
{
343-
// Windows: %USERPROFILE%\.claude-code\mcp.json
344-
basePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".claude-code");
328+
// Windows: %USERPROFILE%\.claude.json
329+
homeDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
345330
}
346331
else if (Application.platform == RuntimePlatform.OSXEditor)
347332
{
348-
// macOS: ~/.claude-code/mcp.json
349-
string homeDir = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
350-
basePath = Path.Combine(homeDir, ".claude-code");
333+
// macOS: ~/.claude.json
334+
homeDir = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
351335
}
352336
else
353337
{
354-
Debug.LogError("Unsupported platform for Claude Code MCP config");
338+
Debug.LogError("Unsupported platform for Claude configuration path resolution");
355339
return null;
356340
}
357-
return Path.Combine(basePath, "mcp.json");
341+
342+
return Path.Combine(homeDir, ".claude.json");
358343
}
359344

360345
/// <summary>
@@ -445,5 +430,73 @@ public static void RunNpmCommand(string arguments, string workingDirectory)
445430
Debug.LogError($"[MCP Unity] Exception while running npm {arguments} in {workingDirectory}. Error: {ex.Message}");
446431
}
447432
}
433+
434+
/// <summary>
435+
/// Returns the appropriate config JObject for merging MCP server settings,
436+
/// with special handling for "Claude Code":
437+
/// - For most products, returns the root config object.
438+
/// - For "Claude Code", returns the project-specific config under "projects/[serverPathParent]".
439+
/// Throws a MissingMemberException if the expected project entry does not exist.
440+
/// </summary>
441+
private static JObject GetMcpServersConfig(JObject existingConfig, string productName)
442+
{
443+
// For most products, use the root config object.
444+
if (productName != "Claude Code")
445+
{
446+
return existingConfig;
447+
}
448+
449+
// For Claude Code, use the project-specific config.
450+
if (existingConfig["projects"] == null)
451+
{
452+
throw new MissingMemberException("Claude Code config error: Could not find 'projects' entry in existing config.");
453+
}
454+
455+
string serverPath = GetServerPath();
456+
string serverPathParent = Path.GetDirectoryName(serverPath)?.Replace("\\", "/");
457+
var projectConfig = existingConfig["projects"][serverPathParent];
458+
459+
if (projectConfig == null)
460+
{
461+
throw new MissingMemberException(
462+
$"Claude Code config error: Could not find project entry for parent directory '{serverPathParent}' in existing config."
463+
);
464+
}
465+
466+
return (JObject)projectConfig;
467+
}
468+
469+
/// <summary>
470+
/// Helper to merge mcpServers from mcpConfig into the existing config file.
471+
/// </summary>
472+
private static bool TryMergeMcpServers(string configFilePath, JObject mcpConfig, string productName)
473+
{
474+
// Read the existing config
475+
string existingConfigJson = File.ReadAllText(configFilePath);
476+
JObject existingConfig = string.IsNullOrEmpty(existingConfigJson) ? new JObject() : JObject.Parse(existingConfigJson);
477+
JObject mcpServersConfig = GetMcpServersConfig(existingConfig, productName);
478+
479+
// Merge the mcpServers from our config into the existing config
480+
if (mcpConfig["mcpServers"] != null && mcpConfig["mcpServers"] is JObject mcpServers)
481+
{
482+
// Create mcpServers object if it doesn't exist
483+
if (mcpServersConfig["mcpServers"] == null)
484+
{
485+
mcpServersConfig["mcpServers"] = new JObject();
486+
}
487+
488+
// Add or update the mcp-unity server config
489+
if (mcpServers["mcp-unity"] != null)
490+
{
491+
((JObject)mcpServersConfig["mcpServers"])["mcp-unity"] = mcpServers["mcp-unity"];
492+
}
493+
494+
// Write the updated config back to the file
495+
File.WriteAllText(configFilePath, existingConfig.ToString(Formatting.Indented));
496+
return true;
497+
}
498+
499+
return false;
500+
}
448501
}
449502
}

0 commit comments

Comments
 (0)