Skip to main content
Glama
AssetHandler.cs10 kB
using UnityEngine; using UnityEditor; using System; using System.IO; using System.Linq; using System.Collections.Generic; namespace UnityMCP { /// <summary> /// Handler for console logs, assets, and project operations /// Provides access to Unity's console, asset database, and project structure /// </summary> public static class AssetHandler { private static List<LogEntry> consoleLogs = new List<LogEntry>(); private const int MAX_LOGS = 5000; [InitializeOnLoadMethod] public static void Initialize() { Application.logMessageReceived += OnLogMessageReceived; } public static void OnLogMessageReceived(string condition, string stackTrace, LogType type) { consoleLogs.Add(new LogEntry { message = condition, stackTrace = stackTrace, type = type.ToString(), timestamp = DateTime.Now.ToString("HH:mm:ss") }); // Keep only recent logs if (consoleLogs.Count > MAX_LOGS) { consoleLogs.RemoveAt(0); } } public static string HandleCommand(string path, string body, string query) { try { switch (path) { case "/console/get_logs": return GetConsoleLogs(body); case "/console/clear": return ClearConsole(); case "/asset/create_prefab": return CreatePrefab(body); case "/project/get_assets": return GetAssets(body); case "/asset/refresh": return RefreshAssets(); default: return JsonResponse(false, $"Unknown endpoint: {path}"); } } catch (Exception e) { return JsonResponse(false, e.Message); } } // ===== CONSOLE OPERATIONS ===== public static string GetConsoleLogs(string body) { var data = ParseJson(body); string logType = data.ContainsKey("logType") ? data["logType"] : "all"; int limit = data.ContainsKey("limit") ? int.Parse(data["limit"]) : 50; var filtered = consoleLogs.AsEnumerable(); if (logType != "all") { filtered = filtered.Where(log => log.type.ToLower() == logType.ToLower()); } var logs = filtered.TakeLast(limit).Select(log => new { message = log.message, type = log.type, timestamp = log.timestamp, stackTrace = log.stackTrace }).ToArray(); return JsonResponse(true, $"Retrieved {logs.Length} console logs", new { logs, total = consoleLogs.Count }); } public static string ClearConsole() { consoleLogs.Clear(); // Also clear Unity's internal console var logEntries = System.Type.GetType("UnityEditor.LogEntries, UnityEditor.dll"); var clearMethod = logEntries?.GetMethod("Clear", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public); clearMethod?.Invoke(null, null); return JsonResponse(true, "Console cleared"); } // ===== ASSET OPERATIONS ===== public static string CreatePrefab(string body) { var data = ParseJson(body); string prefabName = data.ContainsKey("prefabName") ? data["prefabName"] : ""; string folderPath = data.ContainsKey("folderPath") ? data["folderPath"] : "Assets/Prefabs"; if (string.IsNullOrEmpty(prefabName)) { return JsonResponse(false, "prefabName is required"); } if (Selection.activeGameObject == null) { return JsonResponse(false, "No GameObject selected. Please select a GameObject to create a prefab from."); } // Ensure folder exists if (!AssetDatabase.IsValidFolder(folderPath)) { string[] folders = folderPath.Split('/'); string currentPath = folders[0]; for (int i = 1; i < folders.Length; i++) { string newPath = currentPath + "/" + folders[i]; if (!AssetDatabase.IsValidFolder(newPath)) { AssetDatabase.CreateFolder(currentPath, folders[i]); } currentPath = newPath; } } string prefabPath = $"{folderPath}/{prefabName}.prefab"; if (File.Exists(prefabPath)) { return JsonResponse(false, $"Prefab already exists: {prefabPath}"); } GameObject selectedObject = Selection.activeGameObject; PrefabUtility.SaveAsPrefabAsset(selectedObject, prefabPath); AssetDatabase.Refresh(); return JsonResponse(true, $"Prefab created: {prefabPath}", new { path = prefabPath, name = prefabName }); } public static string GetAssets(string body) { var data = ParseJson(body); string type = data.ContainsKey("type") ? data["type"] : ""; string folder = data.ContainsKey("folder") ? data["folder"] : "Assets"; string[] guids; if (!string.IsNullOrEmpty(type)) { guids = AssetDatabase.FindAssets($"t:{type}", new[] { folder }); } else { guids = AssetDatabase.FindAssets("", new[] { folder }); } var assets = guids.Select(guid => { string path = AssetDatabase.GUIDToAssetPath(guid); return new { path, name = Path.GetFileName(path), type = AssetDatabase.GetMainAssetTypeAtPath(path)?.Name }; }).ToArray(); return JsonResponse(true, $"Found {assets.Length} assets", new { assets, folder, filterType = type }); } public static string RefreshAssets() { AssetDatabase.Refresh(); return JsonResponse(true, "Asset database refreshed"); } // ===== HELPER METHODS ===== private static Dictionary<string, string> ParseJson(string json) { var result = new Dictionary<string, string>(); if (string.IsNullOrEmpty(json)) return result; json = json.Trim(); if (!json.StartsWith("{")) return result; json = json.Trim('{', '}'); var parts = new List<string>(); int braceLevel = 0; int quoteCount = 0; string current = ""; foreach (char c in json) { if (c == '"') quoteCount++; if (c == '{') braceLevel++; if (c == '}') braceLevel--; if (c == ',' && braceLevel == 0 && quoteCount % 2 == 0) { parts.Add(current); current = ""; } else { current += c; } } if (!string.IsNullOrEmpty(current)) { parts.Add(current); } foreach (var part in parts) { var colonIndex = part.IndexOf(':'); if (colonIndex > 0) { string key = part.Substring(0, colonIndex).Trim().Trim('"', ' '); string value = part.Substring(colonIndex + 1).Trim().Trim('"', ' '); result[key] = value; } } return result; } public static string JsonResponse(bool success, string message, object data = null) { string dataJson = data != null ? $",\"data\":{SimpleJsonSerialize(data)}" : ""; return $"{{\"success\":{success.ToString().ToLower()},\"message\":\"{message}\"{dataJson}}}"; } public static string SimpleJsonSerialize(object obj) { if (obj == null) return "null"; if (obj is string str) return $"\"{str}\""; if (obj is bool b) return b.ToString().ToLower(); if (obj is int || obj is float || obj is double) return obj.ToString(); var type = obj.GetType(); if (type.IsArray || (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))) { var items = new List<string>(); foreach (var item in (System.Collections.IEnumerable)obj) { items.Add(SimpleJsonSerialize(item)); } return $"[{string.Join(",", items)}]"; } var fields = type.GetFields(); var items2 = new List<string>(); foreach (var field in fields) { var value = field.GetValue(obj); items2.Add($"\"{field.Name}\":{SimpleJsonSerialize(value)}"); } return $"{{{string.Join(",", items2)}}}"; } private class LogEntry { public string message; public string stackTrace; public string type; public string timestamp; } } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/muammar-yacoob/unity-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server