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