Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,29 @@ namespace MCPForUnityTests.Editor.Tools
public class CommandRegistryTests
{
[Test]
public void GetHandler_ReturnsNull_ForUnknownCommand()
public void GetHandler_ThrowException_ForUnknownCommand()
{
var unknown = "HandleDoesNotExist";
var handler = CommandRegistry.GetHandler(unknown);
Assert.IsNull(handler, "Expected null handler for unknown command name.");
try
{
var handler = CommandRegistry.GetHandler(unknown);
Assert.Fail("Should throw InvalidOperation for unknown handler.");
}
catch (InvalidOperationException)
{

}
catch
{
Assert.Fail("Should throw InvalidOperation for unknown handler.");
}
}

[Test]
public void GetHandler_ReturnsManageGameObjectHandler()
{
var handler = CommandRegistry.GetHandler("HandleManageGameObject");
Assert.IsNotNull(handler, "Expected a handler for HandleManageGameObject.");
var handler = CommandRegistry.GetHandler("manage_gameobject");
Assert.IsNotNull(handler, "Expected a handler for manage_gameobject.");

var methodInfo = handler.Method;
Assert.AreEqual("HandleCommand", methodInfo.Name, "Handler method name should be HandleCommand.");
Expand Down
28 changes: 5 additions & 23 deletions UnityMcpBridge/Editor/MCPForUnityBridge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ private static bool IsDebugEnabled()
{
try { return EditorPrefs.GetBool("MCPForUnity.DebugLogs", false); } catch { return false; }
}

private static void LogBreadcrumb(string stage)
{
if (IsDebugEnabled())
Expand All @@ -82,7 +82,7 @@ private static void LogBreadcrumb(string stage)
public static void StartAutoConnect()
{
Stop(); // Stop current connection

try
{
// Prefer stored project port and start using the robust Start() path (with retries/options)
Expand Down Expand Up @@ -314,7 +314,7 @@ public static void Start()
const int maxImmediateRetries = 3;
const int retrySleepMs = 75;
int attempt = 0;
for (;;)
for (; ; )
{
try
{
Expand Down Expand Up @@ -755,7 +755,7 @@ private static async System.Threading.Tasks.Task<string> ReadFrameAsUtf8Async(Ne
{
byte[] header = await ReadExactAsync(stream, 8, timeoutMs, cancel).ConfigureAwait(false);
ulong payloadLen = ReadUInt64BigEndian(header);
if (payloadLen > MaxFrameBytes)
if (payloadLen > MaxFrameBytes)
{
throw new System.IO.IOException($"Invalid framed length: {payloadLen}");
}
Expand Down Expand Up @@ -1040,25 +1040,7 @@ private static string ExecuteCommand(Command command)
// Use JObject for parameters as the new handlers likely expect this
JObject paramsObject = command.@params ?? new JObject();

// Route command based on the new tool structure from the refactor plan
object result = command.type switch
{
// Maps the command type (tool name) to the corresponding handler's static HandleCommand method
// Assumes each handler class has a static method named 'HandleCommand' that takes JObject parameters
"manage_script" => ManageScript.HandleCommand(paramsObject),
// Run scene operations on the main thread to avoid deadlocks/hangs (with diagnostics under debug flag)
"manage_scene" => HandleManageScene(paramsObject)
?? throw new TimeoutException($"manage_scene timed out after {FrameIOTimeoutMs} ms on main thread"),
"manage_editor" => ManageEditor.HandleCommand(paramsObject),
"manage_gameobject" => ManageGameObject.HandleCommand(paramsObject),
"manage_asset" => ManageAsset.HandleCommand(paramsObject),
"manage_shader" => ManageShader.HandleCommand(paramsObject),
"read_console" => ReadConsole.HandleCommand(paramsObject),
"manage_menu_item" => ManageMenuItem.HandleCommand(paramsObject),
_ => throw new ArgumentException(
$"Unknown or unsupported command type: {command.type}"
),
};
object result = CommandRegistry.GetHandler(command.type)(paramsObject);

// Standard success response format
var response = new { status = "success", result };
Expand Down
37 changes: 19 additions & 18 deletions UnityMcpBridge/Editor/Tools/CommandRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ public static class CommandRegistry
// to the corresponding static HandleCommand method in the appropriate tool class.
private static readonly Dictionary<string, Func<JObject, object>> _handlers = new()
{
{ "HandleManageScript", ManageScript.HandleCommand },
{ "HandleManageScene", ManageScene.HandleCommand },
{ "HandleManageEditor", ManageEditor.HandleCommand },
{ "HandleManageGameObject", ManageGameObject.HandleCommand },
{ "HandleManageAsset", ManageAsset.HandleCommand },
{ "HandleReadConsole", ReadConsole.HandleCommand },
{ "HandleManageMenuItem", ManageMenuItem.HandleCommand },
{ "HandleManageShader", ManageShader.HandleCommand},
{ "manage_script", ManageScript.HandleCommand },
{ "manage_scene", ManageScene.HandleCommand },
{ "manage_editor", ManageEditor.HandleCommand },
{ "manage_gameobject", ManageGameObject.HandleCommand },
{ "manage_asset", ManageAsset.HandleCommand },
{ "read_console", ReadConsole.HandleCommand },
{ "manage_menu_item", ManageMenuItem.HandleCommand },
{ "manage_shader", ManageShader.HandleCommand},
};

/// <summary>
Expand All @@ -31,17 +31,18 @@ public static class CommandRegistry
/// <returns>The command handler function if found, null otherwise.</returns>
public static Func<JObject, object> GetHandler(string commandName)
{
// Use case-insensitive comparison for flexibility, although Python side should be consistent
return _handlers.TryGetValue(commandName, out var handler) ? handler : null;
// Consider adding logging here if a handler is not found
/*
if (_handlers.TryGetValue(commandName, out var handler)) {
return handler;
} else {
UnityEngine.Debug.LogError($\"[CommandRegistry] No handler found for command: {commandName}\");
return null;
if (!_handlers.TryGetValue(commandName, out var handler))
{
throw new InvalidOperationException(
$"Unknown or unsupported command type: {commandName}");
}
*/

return handler;
}

public static void Add(string commandName, Func<JObject, object> handler)
{
_handlers.Add(commandName, handler);
}
}
}
Expand Down