@@ -32,6 +32,7 @@ public static object HandleEditorControl(JObject @params)
3232 "BUILD" => HandleBuild ( commandParams ) ,
3333 "EXECUTE_COMMAND" => HandleExecuteCommand ( commandParams ) ,
3434 "READ_CONSOLE" => ReadConsole ( commandParams ) ,
35+ "GET_AVAILABLE_COMMANDS" => GetAvailableCommands ( ) ,
3536 _ => new { error = $ "Unknown editor control command: { command } " } ,
3637 } ;
3738 }
@@ -583,5 +584,367 @@ private static List<string> ReadLastLines(string filePath, int lineCount)
583584
584585 return result ;
585586 }
587+
588+ /// <summary>
589+ /// Gets a comprehensive list of available Unity commands, including editor menu items,
590+ /// internal commands, utility methods, and other actionable operations that can be executed.
591+ /// </summary>
592+ /// <returns>Object containing categorized lists of available command paths</returns>
593+ private static object GetAvailableCommands ( )
594+ {
595+ var menuCommands = new HashSet < string > ( ) ;
596+ var utilityCommands = new HashSet < string > ( ) ;
597+ var assetCommands = new HashSet < string > ( ) ;
598+ var sceneCommands = new HashSet < string > ( ) ;
599+ var gameObjectCommands = new HashSet < string > ( ) ;
600+ var prefabCommands = new HashSet < string > ( ) ;
601+ var shortcutCommands = new HashSet < string > ( ) ;
602+ var otherCommands = new HashSet < string > ( ) ;
603+
604+ // Add a simple command that we know will work for testing
605+ menuCommands . Add ( "Window/Unity MCP" ) ;
606+
607+ Debug . Log ( "Starting command collection..." ) ;
608+
609+ try
610+ {
611+ // Add all EditorApplication static methods - these are guaranteed to work
612+ Debug . Log ( "Adding EditorApplication methods..." ) ;
613+ foreach ( MethodInfo method in typeof ( EditorApplication ) . GetMethods ( BindingFlags . Public | BindingFlags . Static ) )
614+ {
615+ utilityCommands . Add ( $ "EditorApplication.{ method . Name } ") ;
616+ }
617+ Debug . Log ( $ "Added { utilityCommands . Count } EditorApplication methods") ;
618+
619+ // Add built-in menu commands directly - these are common ones that should always be available
620+ Debug . Log ( "Adding built-in menu commands..." ) ;
621+ string [ ] builtInMenus = new [ ] {
622+ "File/New Scene" ,
623+ "File/Open Scene" ,
624+ "File/Save" ,
625+ "File/Save As..." ,
626+ "Edit/Undo" ,
627+ "Edit/Redo" ,
628+ "Edit/Cut" ,
629+ "Edit/Copy" ,
630+ "Edit/Paste" ,
631+ "Edit/Duplicate" ,
632+ "Edit/Delete" ,
633+ "GameObject/Create Empty" ,
634+ "GameObject/3D Object/Cube" ,
635+ "GameObject/3D Object/Sphere" ,
636+ "GameObject/3D Object/Capsule" ,
637+ "GameObject/3D Object/Cylinder" ,
638+ "GameObject/3D Object/Plane" ,
639+ "GameObject/Light/Directional Light" ,
640+ "GameObject/Light/Point Light" ,
641+ "GameObject/Light/Spotlight" ,
642+ "GameObject/Light/Area Light" ,
643+ "Component/Mesh/Mesh Filter" ,
644+ "Component/Mesh/Mesh Renderer" ,
645+ "Component/Physics/Rigidbody" ,
646+ "Component/Physics/Box Collider" ,
647+ "Component/Physics/Sphere Collider" ,
648+ "Component/Physics/Capsule Collider" ,
649+ "Component/Audio/Audio Source" ,
650+ "Component/Audio/Audio Listener" ,
651+ "Window/General/Scene" ,
652+ "Window/General/Game" ,
653+ "Window/General/Inspector" ,
654+ "Window/General/Hierarchy" ,
655+ "Window/General/Project" ,
656+ "Window/General/Console" ,
657+ "Window/Analysis/Profiler" ,
658+ "Window/Package Manager" ,
659+ "Assets/Create/Material" ,
660+ "Assets/Create/C# Script" ,
661+ "Assets/Create/Prefab" ,
662+ "Assets/Create/Scene" ,
663+ "Assets/Create/Folder" ,
664+ } ;
665+
666+ foreach ( string menuItem in builtInMenus )
667+ {
668+ menuCommands . Add ( menuItem ) ;
669+ }
670+ Debug . Log ( $ "Added { builtInMenus . Length } built-in menu commands") ;
671+
672+ // Get menu commands from MenuItem attributes - wrapped in separate try block
673+ Debug . Log ( "Searching for MenuItem attributes..." ) ;
674+ try
675+ {
676+ int itemCount = 0 ;
677+ foreach ( Assembly assembly in AppDomain . CurrentDomain . GetAssemblies ( ) )
678+ {
679+ if ( assembly . IsDynamic ) continue ;
680+
681+ try
682+ {
683+ foreach ( Type type in assembly . GetExportedTypes ( ) )
684+ {
685+ try
686+ {
687+ foreach ( MethodInfo method in type . GetMethods ( BindingFlags . Static | BindingFlags . Public | BindingFlags . NonPublic ) )
688+ {
689+ try
690+ {
691+ object [ ] attributes = method . GetCustomAttributes ( typeof ( UnityEditor . MenuItem ) , false ) ;
692+ if ( attributes != null && attributes . Length > 0 )
693+ {
694+ foreach ( var attr in attributes )
695+ {
696+ var menuItem = attr as UnityEditor . MenuItem ;
697+ if ( menuItem != null && ! string . IsNullOrEmpty ( menuItem . menuItem ) )
698+ {
699+ menuCommands . Add ( menuItem . menuItem ) ;
700+ itemCount ++ ;
701+ }
702+ }
703+ }
704+ }
705+ catch ( Exception methodEx )
706+ {
707+ Debug . LogWarning ( $ "Error getting menu items for method { method . Name } : { methodEx . Message } ") ;
708+ continue ;
709+ }
710+ }
711+ }
712+ catch ( Exception typeEx )
713+ {
714+ Debug . LogWarning ( $ "Error processing type: { typeEx . Message } ") ;
715+ continue ;
716+ }
717+ }
718+ }
719+ catch ( Exception assemblyEx )
720+ {
721+ Debug . LogWarning ( $ "Error examining assembly { assembly . GetName ( ) . Name } : { assemblyEx . Message } ") ;
722+ continue ;
723+ }
724+ }
725+ Debug . Log ( $ "Found { itemCount } menu items from attributes") ;
726+ }
727+ catch ( Exception menuItemEx )
728+ {
729+ Debug . LogError ( $ "Failed to get menu items: { menuItemEx . Message } ") ;
730+ }
731+
732+ // Add EditorUtility methods as commands
733+ Debug . Log ( "Adding EditorUtility methods..." ) ;
734+ foreach ( MethodInfo method in typeof ( EditorUtility ) . GetMethods ( BindingFlags . Public | BindingFlags . Static ) )
735+ {
736+ utilityCommands . Add ( $ "EditorUtility.{ method . Name } ") ;
737+ }
738+ Debug . Log ( $ "Added { typeof ( EditorUtility ) . GetMethods ( BindingFlags . Public | BindingFlags . Static ) . Length } EditorUtility methods") ;
739+
740+ // Add AssetDatabase methods as commands
741+ Debug . Log ( "Adding AssetDatabase methods..." ) ;
742+ foreach ( MethodInfo method in typeof ( AssetDatabase ) . GetMethods ( BindingFlags . Public | BindingFlags . Static ) )
743+ {
744+ assetCommands . Add ( $ "AssetDatabase.{ method . Name } ") ;
745+ }
746+ Debug . Log ( $ "Added { typeof ( AssetDatabase ) . GetMethods ( BindingFlags . Public | BindingFlags . Static ) . Length } AssetDatabase methods") ;
747+
748+ // Add EditorSceneManager methods as commands
749+ Debug . Log ( "Adding EditorSceneManager methods..." ) ;
750+ Type sceneManagerType = typeof ( UnityEditor . SceneManagement . EditorSceneManager ) ;
751+ if ( sceneManagerType != null )
752+ {
753+ foreach ( MethodInfo method in sceneManagerType . GetMethods ( BindingFlags . Public | BindingFlags . Static ) )
754+ {
755+ sceneCommands . Add ( $ "EditorSceneManager.{ method . Name } ") ;
756+ }
757+ Debug . Log ( $ "Added { sceneManagerType . GetMethods ( BindingFlags . Public | BindingFlags . Static ) . Length } EditorSceneManager methods") ;
758+ }
759+
760+ // Add GameObject manipulation commands
761+ Debug . Log ( "Adding GameObject methods..." ) ;
762+ foreach ( MethodInfo method in typeof ( GameObject ) . GetMethods ( BindingFlags . Public | BindingFlags . Static ) )
763+ {
764+ gameObjectCommands . Add ( $ "GameObject.{ method . Name } ") ;
765+ }
766+ Debug . Log ( $ "Added { typeof ( GameObject ) . GetMethods ( BindingFlags . Public | BindingFlags . Static ) . Length } GameObject methods") ;
767+
768+ // Add Selection-related commands
769+ Debug . Log ( "Adding Selection methods..." ) ;
770+ foreach ( MethodInfo method in typeof ( Selection ) . GetMethods ( BindingFlags . Public | BindingFlags . Static ) )
771+ {
772+ gameObjectCommands . Add ( $ "Selection.{ method . Name } ") ;
773+ }
774+ Debug . Log ( $ "Added { typeof ( Selection ) . GetMethods ( BindingFlags . Public | BindingFlags . Static ) . Length } Selection methods") ;
775+
776+ // Add PrefabUtility methods as commands
777+ Debug . Log ( "Adding PrefabUtility methods..." ) ;
778+ Type prefabUtilityType = typeof ( UnityEditor . PrefabUtility ) ;
779+ if ( prefabUtilityType != null )
780+ {
781+ foreach ( MethodInfo method in prefabUtilityType . GetMethods ( BindingFlags . Public | BindingFlags . Static ) )
782+ {
783+ prefabCommands . Add ( $ "PrefabUtility.{ method . Name } ") ;
784+ }
785+ Debug . Log ( $ "Added { prefabUtilityType . GetMethods ( BindingFlags . Public | BindingFlags . Static ) . Length } PrefabUtility methods") ;
786+ }
787+
788+ // Add Undo related methods
789+ Debug . Log ( "Adding Undo methods..." ) ;
790+ foreach ( MethodInfo method in typeof ( Undo ) . GetMethods ( BindingFlags . Public | BindingFlags . Static ) )
791+ {
792+ utilityCommands . Add ( $ "Undo.{ method . Name } ") ;
793+ }
794+ Debug . Log ( $ "Added { typeof ( Undo ) . GetMethods ( BindingFlags . Public | BindingFlags . Static ) . Length } Undo methods") ;
795+
796+ // The rest of the command gathering can be attempted but might not be critical
797+ try
798+ {
799+ // Get commands from Unity's internal command system
800+ Debug . Log ( "Trying to get internal CommandService commands..." ) ;
801+ Type commandServiceType = typeof ( UnityEditor . EditorWindow ) . Assembly . GetType ( "UnityEditor.CommandService" ) ;
802+ if ( commandServiceType != null )
803+ {
804+ Debug . Log ( "Found CommandService type" ) ;
805+ PropertyInfo instanceProperty = commandServiceType . GetProperty ( "Instance" ,
806+ BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Static ) ;
807+
808+ if ( instanceProperty != null )
809+ {
810+ Debug . Log ( "Found Instance property" ) ;
811+ object commandService = instanceProperty . GetValue ( null ) ;
812+ if ( commandService != null )
813+ {
814+ Debug . Log ( "Got CommandService instance" ) ;
815+ MethodInfo findAllCommandsMethod = commandServiceType . GetMethod ( "FindAllCommands" ,
816+ BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Instance ) ;
817+
818+ if ( findAllCommandsMethod != null )
819+ {
820+ Debug . Log ( "Found FindAllCommands method" ) ;
821+ var commandsResult = findAllCommandsMethod . Invoke ( commandService , null ) ;
822+ if ( commandsResult != null )
823+ {
824+ Debug . Log ( "Got commands result" ) ;
825+ var commandsList = commandsResult as System . Collections . IEnumerable ;
826+ if ( commandsList != null )
827+ {
828+ int commandCount = 0 ;
829+ foreach ( var cmd in commandsList )
830+ {
831+ try
832+ {
833+ PropertyInfo nameProperty = cmd . GetType ( ) . GetProperty ( "name" ) ??
834+ cmd . GetType ( ) . GetProperty ( "path" ) ??
835+ cmd . GetType ( ) . GetProperty ( "commandName" ) ;
836+ if ( nameProperty != null )
837+ {
838+ string commandName = nameProperty . GetValue ( cmd ) ? . ToString ( ) ;
839+ if ( ! string . IsNullOrEmpty ( commandName ) )
840+ {
841+ otherCommands . Add ( commandName ) ;
842+ commandCount ++ ;
843+ }
844+ }
845+ }
846+ catch ( Exception cmdEx )
847+ {
848+ Debug . LogWarning ( $ "Error processing command: { cmdEx . Message } ") ;
849+ continue ;
850+ }
851+ }
852+ Debug . Log ( $ "Added { commandCount } internal commands") ;
853+ }
854+ }
855+ else
856+ {
857+ Debug . LogWarning ( "FindAllCommands returned null" ) ;
858+ }
859+ }
860+ else
861+ {
862+ Debug . LogWarning ( "FindAllCommands method not found" ) ;
863+ }
864+ }
865+ else
866+ {
867+ Debug . LogWarning ( "CommandService instance is null" ) ;
868+ }
869+ }
870+ else
871+ {
872+ Debug . LogWarning ( "Instance property not found on CommandService" ) ;
873+ }
874+ }
875+ else
876+ {
877+ Debug . LogWarning ( "CommandService type not found" ) ;
878+ }
879+ }
880+ catch ( Exception e )
881+ {
882+ Debug . LogWarning ( $ "Failed to get internal Unity commands: { e . Message } ") ;
883+ }
884+
885+ // Other additional command sources can be tried
886+ // ... other commands ...
887+ }
888+ catch ( Exception e )
889+ {
890+ Debug . LogError ( $ "Error getting Unity commands: { e . Message } \n { e . StackTrace } ") ;
891+ }
892+
893+ // Create command categories dictionary for the result
894+ var commandCategories = new Dictionary < string , List < string > >
895+ {
896+ { "MenuCommands" , menuCommands . OrderBy ( x => x ) . ToList ( ) } ,
897+ { "UtilityCommands" , utilityCommands . OrderBy ( x => x ) . ToList ( ) } ,
898+ { "AssetCommands" , assetCommands . OrderBy ( x => x ) . ToList ( ) } ,
899+ { "SceneCommands" , sceneCommands . OrderBy ( x => x ) . ToList ( ) } ,
900+ { "GameObjectCommands" , gameObjectCommands . OrderBy ( x => x ) . ToList ( ) } ,
901+ { "PrefabCommands" , prefabCommands . OrderBy ( x => x ) . ToList ( ) } ,
902+ { "ShortcutCommands" , shortcutCommands . OrderBy ( x => x ) . ToList ( ) } ,
903+ { "OtherCommands" , otherCommands . OrderBy ( x => x ) . ToList ( ) }
904+ } ;
905+
906+ // Calculate total command count
907+ int totalCount = commandCategories . Values . Sum ( list => list . Count ) ;
908+
909+ Debug . Log ( $ "Command retrieval complete. Found { totalCount } total commands.") ;
910+
911+ // Create a simplified response with just the essential data
912+ // The complex object structure might be causing serialization issues
913+ var allCommandsList = commandCategories . Values . SelectMany ( x => x ) . OrderBy ( x => x ) . ToList ( ) ;
914+
915+ // Use simple string array instead of JArray for better serialization
916+ string [ ] commandsArray = allCommandsList . ToArray ( ) ;
917+
918+ // Log the array size for verification
919+ Debug . Log ( $ "Final commands array contains { commandsArray . Length } items") ;
920+
921+ try
922+ {
923+ // Return a simple object with just the commands array and count
924+ var result = new
925+ {
926+ commands = commandsArray ,
927+ count = commandsArray . Length
928+ } ;
929+
930+ // Verify the result can be serialized properly
931+ var jsonTest = JsonUtility . ToJson ( new { test = "This is a test" } ) ;
932+ Debug . Log ( $ "JSON serialization test successful: { jsonTest } ") ;
933+
934+ return result ;
935+ }
936+ catch ( Exception ex )
937+ {
938+ Debug . LogError ( $ "Error creating response: { ex . Message } ") ;
939+
940+ // Ultimate fallback - don't use any JObject/JArray
941+ return new
942+ {
943+ message = $ "Found { commandsArray . Length } commands",
944+ firstTen = commandsArray . Take ( 10 ) . ToArray ( ) ,
945+ count = commandsArray . Length
946+ } ;
947+ }
948+ }
586949 }
587950}
0 commit comments