Skip to content

Commit c48798a

Browse files
authored
Merge branch 'CoplayDev:main' into feat/code-insiders-autoconfig
2 parents 6414759 + 0c2934a commit c48798a

File tree

25 files changed

+838
-152
lines changed

25 files changed

+838
-152
lines changed

MCPForUnity/Editor/Clients/Configurators/ClaudeDesktopConfigurator.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@ namespace MCPForUnity.Editor.Clients.Configurators
99
{
1010
public class ClaudeDesktopConfigurator : JsonFileMcpConfigurator
1111
{
12+
public const string ClientName = "Claude Desktop";
13+
1214
public ClaudeDesktopConfigurator() : base(new McpClient
1315
{
14-
name = "Claude Desktop",
16+
name = ClientName,
1517
windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Claude", "claude_desktop_config.json"),
1618
macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support", "Claude", "claude_desktop_config.json"),
1719
linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config", "Claude", "claude_desktop_config.json"),
18-
SupportsHttpTransport = false
20+
SupportsHttpTransport = false,
21+
StripEnvWhenNotRequired = true
1922
})
2023
{ }
2124

MCPForUnity/Editor/Helpers/ConfigJsonBuilder.cs

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
35
using MCPForUnity.Editor.Constants;
6+
using MCPForUnity.Editor.Clients.Configurators;
47
using MCPForUnity.Editor.Helpers;
58
using MCPForUnity.Editor.Models;
69
using Newtonsoft.Json;
710
using Newtonsoft.Json.Linq;
811
using UnityEditor;
12+
using UnityEngine;
913

1014
namespace MCPForUnity.Editor.Helpers
1115
{
@@ -77,27 +81,26 @@ private static void PopulateUnityNode(JObject unity, string uvPath, McpClient cl
7781
// Stdio mode: Use uvx command
7882
var (uvxPath, fromUrl, packageName) = AssetPathUtility.GetUvxCommandParts();
7983

80-
unity["command"] = uvxPath;
84+
var toolArgs = BuildUvxArgs(fromUrl, packageName);
8185

82-
var args = new List<string> { packageName };
83-
if (!string.IsNullOrEmpty(fromUrl))
86+
if (ShouldUseWindowsCmdShim(client))
8487
{
85-
args.Insert(0, fromUrl);
86-
args.Insert(0, "--from");
87-
}
88+
unity["command"] = ResolveCmdPath();
8889

89-
args.Add("--transport");
90-
args.Add("stdio");
90+
var cmdArgs = new List<string> { "/c", uvxPath };
91+
cmdArgs.AddRange(toolArgs);
9192

92-
unity["args"] = JArray.FromObject(args.ToArray());
93+
unity["args"] = JArray.FromObject(cmdArgs.ToArray());
94+
}
95+
else
96+
{
97+
unity["command"] = uvxPath;
98+
unity["args"] = JArray.FromObject(toolArgs.ToArray());
99+
}
93100

94101
// Remove url/serverUrl if they exist from previous config
95102
if (unity["url"] != null) unity.Remove("url");
96103
if (unity["serverUrl"] != null) unity.Remove("serverUrl");
97-
foreach (var prop in urlPropsToRemove)
98-
{
99-
if (unity[prop] != null) unity.Remove(prop);
100-
}
101104

102105
if (isVSCode)
103106
{
@@ -145,5 +148,44 @@ private static JObject EnsureObject(JObject parent, string name)
145148
parent[name] = created;
146149
return created;
147150
}
151+
152+
private static IList<string> BuildUvxArgs(string fromUrl, string packageName)
153+
{
154+
var args = new List<string> { packageName };
155+
156+
if (!string.IsNullOrEmpty(fromUrl))
157+
{
158+
args.Insert(0, fromUrl);
159+
args.Insert(0, "--from");
160+
}
161+
162+
args.Add("--transport");
163+
args.Add("stdio");
164+
165+
return args;
166+
}
167+
168+
private static bool ShouldUseWindowsCmdShim(McpClient client)
169+
{
170+
if (client == null)
171+
{
172+
return false;
173+
}
174+
175+
return Application.platform == RuntimePlatform.WindowsEditor &&
176+
string.Equals(client.name, ClaudeDesktopConfigurator.ClientName, StringComparison.OrdinalIgnoreCase);
177+
}
178+
179+
private static string ResolveCmdPath()
180+
{
181+
var comSpec = Environment.GetEnvironmentVariable("ComSpec");
182+
if (!string.IsNullOrEmpty(comSpec) && File.Exists(comSpec))
183+
{
184+
return comSpec;
185+
}
186+
187+
string system32Cmd = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "cmd.exe");
188+
return File.Exists(system32Cmd) ? system32Cmd : "cmd.exe";
189+
}
148190
}
149191
}
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
using System;
2+
using UnityEngine;
3+
using UnityEngine.Rendering;
4+
5+
namespace MCPForUnity.Editor.Helpers
6+
{
7+
internal static class RenderPipelineUtility
8+
{
9+
internal enum PipelineKind
10+
{
11+
BuiltIn,
12+
Universal,
13+
HighDefinition,
14+
Custom
15+
}
16+
17+
private static readonly string[] BuiltInLitShaders = { "Standard", "Legacy Shaders/Diffuse" };
18+
private static readonly string[] BuiltInUnlitShaders = { "Unlit/Color", "Unlit/Texture" };
19+
private static readonly string[] UrpLitShaders = { "Universal Render Pipeline/Lit", "Universal Render Pipeline/Simple Lit" };
20+
private static readonly string[] UrpUnlitShaders = { "Universal Render Pipeline/Unlit" };
21+
private static readonly string[] HdrpLitShaders = { "HDRP/Lit", "High Definition Render Pipeline/Lit" };
22+
private static readonly string[] HdrpUnlitShaders = { "HDRP/Unlit", "High Definition Render Pipeline/Unlit" };
23+
24+
internal static PipelineKind GetActivePipeline()
25+
{
26+
var asset = GraphicsSettings.currentRenderPipeline;
27+
if (asset == null)
28+
{
29+
return PipelineKind.BuiltIn;
30+
}
31+
32+
var typeName = asset.GetType().FullName ?? string.Empty;
33+
if (typeName.IndexOf("HighDefinition", StringComparison.OrdinalIgnoreCase) >= 0 ||
34+
typeName.IndexOf("HDRP", StringComparison.OrdinalIgnoreCase) >= 0)
35+
{
36+
return PipelineKind.HighDefinition;
37+
}
38+
39+
if (typeName.IndexOf("Universal", StringComparison.OrdinalIgnoreCase) >= 0 ||
40+
typeName.IndexOf("URP", StringComparison.OrdinalIgnoreCase) >= 0)
41+
{
42+
return PipelineKind.Universal;
43+
}
44+
45+
return PipelineKind.Custom;
46+
}
47+
48+
internal static Shader ResolveShader(string requestedNameOrAlias)
49+
{
50+
var pipeline = GetActivePipeline();
51+
52+
if (!string.IsNullOrWhiteSpace(requestedNameOrAlias))
53+
{
54+
var alias = requestedNameOrAlias.Trim();
55+
var aliasMatch = ResolveAlias(alias, pipeline);
56+
if (aliasMatch != null)
57+
{
58+
WarnIfPipelineMismatch(aliasMatch.name, pipeline);
59+
return aliasMatch;
60+
}
61+
62+
var direct = Shader.Find(alias);
63+
if (direct != null)
64+
{
65+
WarnIfPipelineMismatch(direct.name, pipeline);
66+
return direct;
67+
}
68+
69+
McpLog.Warn($"Shader '{alias}' not found. Falling back to {pipeline} defaults.");
70+
}
71+
72+
var fallback = ResolveDefaultLitShader(pipeline)
73+
?? ResolveDefaultLitShader(PipelineKind.BuiltIn)
74+
?? Shader.Find("Unlit/Color");
75+
76+
if (fallback != null)
77+
{
78+
WarnIfPipelineMismatch(fallback.name, pipeline);
79+
}
80+
81+
return fallback;
82+
}
83+
84+
internal static Shader ResolveDefaultLitShader(PipelineKind pipeline)
85+
{
86+
return pipeline switch
87+
{
88+
PipelineKind.HighDefinition => TryFindShader(HdrpLitShaders) ?? TryFindShader(UrpLitShaders),
89+
PipelineKind.Universal => TryFindShader(UrpLitShaders) ?? TryFindShader(HdrpLitShaders),
90+
PipelineKind.Custom => TryFindShader(BuiltInLitShaders) ?? TryFindShader(UrpLitShaders) ?? TryFindShader(HdrpLitShaders),
91+
_ => TryFindShader(BuiltInLitShaders) ?? Shader.Find("Unlit/Color")
92+
};
93+
}
94+
95+
internal static Shader ResolveDefaultUnlitShader(PipelineKind pipeline)
96+
{
97+
return pipeline switch
98+
{
99+
PipelineKind.HighDefinition => TryFindShader(HdrpUnlitShaders) ?? TryFindShader(UrpUnlitShaders) ?? TryFindShader(BuiltInUnlitShaders),
100+
PipelineKind.Universal => TryFindShader(UrpUnlitShaders) ?? TryFindShader(HdrpUnlitShaders) ?? TryFindShader(BuiltInUnlitShaders),
101+
PipelineKind.Custom => TryFindShader(BuiltInUnlitShaders) ?? TryFindShader(UrpUnlitShaders) ?? TryFindShader(HdrpUnlitShaders),
102+
_ => TryFindShader(BuiltInUnlitShaders)
103+
};
104+
}
105+
106+
private static Shader ResolveAlias(string alias, PipelineKind pipeline)
107+
{
108+
if (string.Equals(alias, "lit", StringComparison.OrdinalIgnoreCase) ||
109+
string.Equals(alias, "default", StringComparison.OrdinalIgnoreCase) ||
110+
string.Equals(alias, "default_lit", StringComparison.OrdinalIgnoreCase))
111+
{
112+
return ResolveDefaultLitShader(pipeline);
113+
}
114+
115+
if (string.Equals(alias, "unlit", StringComparison.OrdinalIgnoreCase))
116+
{
117+
return ResolveDefaultUnlitShader(pipeline);
118+
}
119+
120+
if (string.Equals(alias, "urp_lit", StringComparison.OrdinalIgnoreCase))
121+
{
122+
return TryFindShader(UrpLitShaders);
123+
}
124+
125+
if (string.Equals(alias, "hdrp_lit", StringComparison.OrdinalIgnoreCase))
126+
{
127+
return TryFindShader(HdrpLitShaders);
128+
}
129+
130+
if (string.Equals(alias, "built_in_lit", StringComparison.OrdinalIgnoreCase))
131+
{
132+
return TryFindShader(BuiltInLitShaders);
133+
}
134+
135+
return null;
136+
}
137+
138+
private static Shader TryFindShader(params string[] shaderNames)
139+
{
140+
foreach (var shaderName in shaderNames)
141+
{
142+
var shader = Shader.Find(shaderName);
143+
if (shader != null)
144+
{
145+
return shader;
146+
}
147+
}
148+
return null;
149+
}
150+
151+
private static void WarnIfPipelineMismatch(string shaderName, PipelineKind activePipeline)
152+
{
153+
if (string.IsNullOrEmpty(shaderName))
154+
{
155+
return;
156+
}
157+
158+
var lowerName = shaderName.ToLowerInvariant();
159+
bool shaderLooksUrp = lowerName.Contains("universal render pipeline") || lowerName.Contains("urp/");
160+
bool shaderLooksHdrp = lowerName.Contains("high definition render pipeline") || lowerName.Contains("hdrp/");
161+
bool shaderLooksBuiltin = lowerName.Contains("standard") || lowerName.Contains("legacy shaders/");
162+
bool shaderLooksSrp = shaderLooksUrp || shaderLooksHdrp;
163+
164+
switch (activePipeline)
165+
{
166+
case PipelineKind.HighDefinition:
167+
if (shaderLooksUrp)
168+
{
169+
McpLog.Warn($"[RenderPipelineUtility] Active pipeline is HDRP but shader '{shaderName}' looks URP-based. Asset may appear incorrect.");
170+
}
171+
else if (shaderLooksBuiltin && !shaderLooksHdrp)
172+
{
173+
McpLog.Warn($"[RenderPipelineUtility] Active pipeline is HDRP but shader '{shaderName}' looks Built-in. Consider using an HDRP shader for correct results.");
174+
}
175+
break;
176+
case PipelineKind.Universal:
177+
if (shaderLooksHdrp)
178+
{
179+
McpLog.Warn($"[RenderPipelineUtility] Active pipeline is URP but shader '{shaderName}' looks HDRP-based. Asset may appear incorrect.");
180+
}
181+
else if (shaderLooksBuiltin && !shaderLooksUrp)
182+
{
183+
McpLog.Warn($"[RenderPipelineUtility] Active pipeline is URP but shader '{shaderName}' looks Built-in. Consider using a URP shader for correct results.");
184+
}
185+
break;
186+
case PipelineKind.BuiltIn:
187+
if (shaderLooksSrp)
188+
{
189+
McpLog.Warn($"[RenderPipelineUtility] Active pipeline is Built-in but shader '{shaderName}' targets URP/HDRP. Asset may not render as expected.");
190+
}
191+
break;
192+
}
193+
}
194+
}
195+
}

MCPForUnity/Editor/Helpers/RenderPipelineUtility.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

MCPForUnity/Editor/MenuItems/MCPForUnityMenu.cs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,42 +5,25 @@
55

66
namespace MCPForUnity.Editor.MenuItems
77
{
8-
/// <summary>
9-
/// Centralized menu items for MCP For Unity
10-
/// </summary>
118
public static class MCPForUnityMenu
129
{
13-
// ========================================
14-
// Main Menu Items
15-
// ========================================
16-
17-
/// <summary>
18-
/// Show the Setup Window
19-
/// </summary>
2010
[MenuItem("Window/MCP For Unity/Setup Window", priority = 1)]
2111
public static void ShowSetupWindow()
2212
{
2313
SetupWindowService.ShowSetupWindow();
2414
}
2515

26-
/// <summary>
27-
/// Toggle the main MCP For Unity window
28-
/// </summary>
2916
[MenuItem("Window/MCP For Unity/Toggle MCP Window %#m", priority = 2)]
3017
public static void ToggleMCPWindow()
3118
{
32-
if (EditorWindow.HasOpenInstances<MCPForUnityEditorWindow>())
19+
if (MCPForUnityEditorWindow.HasAnyOpenWindow())
3320
{
34-
foreach (var window in UnityEngine.Resources.FindObjectsOfTypeAll<MCPForUnityEditorWindow>())
35-
{
36-
window.Close();
37-
}
21+
MCPForUnityEditorWindow.CloseAllOpenWindows();
3822
}
3923
else
4024
{
4125
MCPForUnityEditorWindow.ShowWindow();
4226
}
4327
}
44-
4528
}
4629
}

0 commit comments

Comments
 (0)