Skip to content

Commit f2d0541

Browse files
committed
refactor(utils): rename McpConfigUtils → McpUtils
feat: Unity now installs the Node.js server and it's dependencies - automatically runs on Unity starts - add “Force Install Server” button for manual invoke chore(node.js): remove build/ and node_modules/ folders as now they are built by Unity on start chore(unity): port variable is now saved in the MCP settings docs: sync all readme files - remove extra FAQs - replace OS-specific timeout sections with generic instructions - append standardized Support/Feedback, Contributing, License, Acknowledgements
1 parent cbfecd4 commit f2d0541

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+337
-944
lines changed

.gitignore

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ GvhProjectSettings.xml
115115
**/package-lock.json.meta
116116
.codeiumignore
117117
.windsurf
118-
Server/log.txt
119-
Server/log.txt.meta
118+
Server~/log.txt
119+
Server~/log.txt.meta
120120
log.txt
121121
log.txt.meta
122+
Server~/build/*
123+
Server~/node_modules/*

Editor/UnityBridge/McpUnityEditorWindow.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,8 @@ private void DrawServerTab()
164164

165165
GUI.enabled = true;
166166
EditorGUILayout.EndHorizontal();
167-
168-
EditorGUILayout.Space();
167+
168+
EditorGUILayout.Space();
169169

170170
EditorGUILayout.LabelField("Connected Clients", EditorStyles.boldLabel);
171171
EditorGUILayout.BeginVertical("box"); // Keep the default gray box for the container
@@ -210,7 +210,7 @@ private void DrawServerTab()
210210

211211
if (string.IsNullOrEmpty(_mcpConfigJson) || before != _tabsIndentationJson)
212212
{
213-
_mcpConfigJson = McpConfigUtils.GenerateMcpConfigJson(_tabsIndentationJson);
213+
_mcpConfigJson = McpUtils.GenerateMcpConfigJson(_tabsIndentationJson);
214214
}
215215

216216
if (GUILayout.Button("Copy to Clipboard", GUILayout.Height(30)))
@@ -224,7 +224,7 @@ private void DrawServerTab()
224224

225225
if (GUILayout.Button("Configure Windsurf IDE", GUILayout.Height(30)))
226226
{
227-
bool added = McpConfigUtils.AddToWindsurfIdeConfig(_tabsIndentationJson);
227+
bool added = McpUtils.AddToWindsurfIdeConfig(_tabsIndentationJson);
228228
if (added)
229229
{
230230
EditorUtility.DisplayDialog("Success", "The MCP configuration was successfully added to the Windsurf config file.", "OK");
@@ -239,7 +239,7 @@ private void DrawServerTab()
239239

240240
if (GUILayout.Button("Configure Claude Desktop", GUILayout.Height(30)))
241241
{
242-
bool added = McpConfigUtils.AddToClaudeDesktopConfig(_tabsIndentationJson);
242+
bool added = McpUtils.AddToClaudeDesktopConfig(_tabsIndentationJson);
243243
if (added)
244244
{
245245
EditorUtility.DisplayDialog("Success", "The MCP configuration was successfully added to the Claude Desktop config file.", "OK");
@@ -254,7 +254,7 @@ private void DrawServerTab()
254254

255255
if (GUILayout.Button("Configure Cursor", GUILayout.Height(30)))
256256
{
257-
bool added = McpConfigUtils.AddToCursorConfig(_tabsIndentationJson);
257+
bool added = McpUtils.AddToCursorConfig(_tabsIndentationJson);
258258
if (added)
259259
{
260260
EditorUtility.DisplayDialog("Success", "The MCP configuration was successfully added to the Cursor config file.", "OK");
@@ -266,6 +266,14 @@ private void DrawServerTab()
266266
}
267267

268268
EditorGUILayout.EndVertical();
269+
270+
EditorGUILayout.Space();
271+
272+
// Force Install Server button
273+
if (GUILayout.Button("Force Install Server", GUILayout.Height(30)))
274+
{
275+
McpUnityServer.Instance.InstallServer();
276+
}
269277
}
270278

271279
private void DrawHelpTab()

Editor/UnityBridge/McpUnityServer.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
using McpUnity.Services;
99
using McpUnity.Utils;
1010
using WebSocketSharp.Server;
11+
using System.IO;
12+
using System.Diagnostics;
1113

1214
namespace McpUnity.Unity
1315
{
@@ -74,6 +76,7 @@ public static McpUnityServer Instance
7476
/// </summary>
7577
private McpUnityServer()
7678
{
79+
InstallServer();
7780
InitializeServices();
7881
RegisterResources();
7982
RegisterTools();
@@ -138,6 +141,33 @@ public bool TryGetResource(string name, out McpResourceBase resource)
138141
{
139142
return _resources.TryGetValue(name, out resource);
140143
}
144+
145+
/// <summary>
146+
/// Installs the MCP Node.js server by running 'npm install' and 'npm run build'
147+
/// in the server directory if 'node_modules' or 'build' folders are missing.
148+
/// </summary>
149+
public void InstallServer()
150+
{
151+
string serverPath = McpUtils.GetServerPath();
152+
153+
if (string.IsNullOrEmpty(serverPath) || !Directory.Exists(serverPath))
154+
{
155+
McpLogger.LogError($"Server path not found or invalid: {serverPath}. Make sure that MCP Node.js server is installed.");
156+
return;
157+
}
158+
159+
string nodeModulesPath = Path.Combine(serverPath, "node_modules");
160+
if (!Directory.Exists(nodeModulesPath))
161+
{
162+
McpUtils.RunNpmCommand("install", serverPath);
163+
}
164+
165+
string buildPath = Path.Combine(serverPath, "build");
166+
if (!Directory.Exists(buildPath))
167+
{
168+
McpUtils.RunNpmCommand("run build", serverPath);
169+
}
170+
}
141171

142172
/// <summary>
143173
/// Register all available tools

Editor/UnityBridge/McpUnitySettings.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,15 @@ public class McpUnitySettings
1919

2020
private const string EnvUnityPort = "UNITY_PORT";
2121
private const string EnvUnityRequestTimeout = "UNITY_REQUEST_TIMEOUT";
22-
/// <remarks>
23-
/// This file path is also read by the MCP server. Changes here will require updates to it. See mcpUnity.ts
24-
/// </remarks>
2522
private const string SettingsPath = "ProjectSettings/McpUnitySettings.json";
2623

2724
private static McpUnitySettings _instance;
2825

29-
// Server settings
30-
public int Port { get; set; } = 8090;
26+
[Tooltip("Port number for MCP server")]
27+
public int Port = 8090;
3128

3229
[Tooltip("Timeout in seconds for tool request")]
33-
public int RequestTimeoutSeconds { get; set; } = RequestTimeoutMinimum;
30+
public int RequestTimeoutSeconds = RequestTimeoutMinimum;
3431

3532
[Tooltip("Whether to automatically start the MCP server when Unity opens")]
3633
public bool AutoStartServer = true;

Editor/Utils/McpConfigUtils.cs renamed to Editor/Utils/McpUtils.cs

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ namespace McpUnity.Utils
1212
/// <summary>
1313
/// Utility class for MCP configuration operations
1414
/// </summary>
15-
public static class McpConfigUtils
15+
/// <summary>
16+
/// Utility class for MCP configuration and system operations
17+
/// </summary>
18+
public static class McpUtils
1619
{
1720
/// <summary>
1821
/// Generates the MCP configuration JSON to setup the Unity MCP server in different AI Clients
@@ -293,5 +296,72 @@ private static string GetCursorConfigPath()
293296
// Return the path to the mcp_config.json file
294297
return Path.Combine(basePath, "mcp.json");
295298
}
299+
300+
/// <summary>
301+
/// Runs an npm command (such as install or build) in the specified working directory.
302+
/// Handles cross-platform compatibility (Windows/macOS/Linux) for invoking npm.
303+
/// Logs output and errors to the Unity console.
304+
/// </summary>
305+
/// <param name="arguments">Arguments to pass to npm (e.g., "install" or "run build").</param>
306+
/// <param name="workingDirectory">The working directory where the npm command should be executed.</param>
307+
public static void RunNpmCommand(string arguments, string workingDirectory)
308+
{
309+
string shellCommand = "/bin/bash";
310+
string shellArguments = $"-c \"npm {arguments}\"";
311+
312+
if (Application.platform == RuntimePlatform.WindowsEditor)
313+
{
314+
shellCommand = "cmd.exe";
315+
shellArguments = $"/c npm {arguments}";
316+
}
317+
318+
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo
319+
{
320+
FileName = shellCommand,
321+
Arguments = shellArguments,
322+
WorkingDirectory = workingDirectory,
323+
RedirectStandardOutput = true,
324+
RedirectStandardError = true,
325+
UseShellExecute = false,
326+
CreateNoWindow = true
327+
};
328+
329+
try
330+
{
331+
using (var process = System.Diagnostics.Process.Start(startInfo))
332+
{
333+
if (process == null)
334+
{
335+
Debug.LogError($"[MCP Unity] Failed to start npm process with arguments: {arguments} in {workingDirectory}. Process object is null.");
336+
return;
337+
}
338+
339+
string output = process.StandardOutput.ReadToEnd();
340+
string error = process.StandardError.ReadToEnd();
341+
342+
process.WaitForExit();
343+
344+
if (process.ExitCode == 0)
345+
{
346+
Debug.Log($"[MCP Unity] npm {arguments} completed successfully in {workingDirectory}.");
347+
}
348+
else
349+
{
350+
Debug.LogError($"[MCP Unity] npm {arguments} failed in {workingDirectory}. Exit Code: {process.ExitCode}");
351+
}
352+
353+
if (!string.IsNullOrEmpty(output)) Debug.Log($"[MCP Unity] Output:\n{output}");
354+
if (!string.IsNullOrEmpty(error)) Debug.LogError($"[MCP Unity] Error:\n{error}");
355+
}
356+
}
357+
catch (System.ComponentModel.Win32Exception ex) // Catch specific exception for "file not found"
358+
{
359+
Debug.LogError($"[MCP Unity] Failed to run npm command '{shellCommand} {shellArguments}'. Ensure Node.js and npm are installed and in your system's PATH. Error: {ex.Message}");
360+
}
361+
catch (Exception ex)
362+
{
363+
Debug.LogError($"[MCP Unity] Exception while running npm command '{shellCommand} {shellArguments}' in {workingDirectory}: {ex.Message}\nDetails: {ex.StackTrace}");
364+
}
365+
}
296366
}
297367
}

Editor/Utils/McpConfigUtils.cs.meta renamed to Editor/Utils/McpUtils.cs.meta

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)