Skip to main content
Glama
AssetDatabaseProvider.cs18.7 kB
using System; using System.Collections.Generic; using System.IO; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace LocalMcp.UnityServer { /// <summary> /// Provides AssetDatabase operations for Unity MCP Server. /// Handles asset searching, listing, and metadata retrieval. /// </summary> public static class AssetDatabaseProvider { /// <summary> /// Lists all assets of a specific type in the project or a specific path. /// </summary> /// <param name="paramsJson">JSON parameters containing assetType and optional path</param> /// <param name="id">JSON-RPC request ID</param> /// <returns>JSON-RPC response containing list of assets</returns> public static string ListAssets(string paramsJson, object id) { #if UNITY_EDITOR try { var parameters = JsonUtility.FromJson<ListAssetsParams>(paramsJson); if (string.IsNullOrEmpty(parameters.assetType)) { return JsonRpcResponseHelper.InvalidParams("assetType is required", id); } string searchPath = string.IsNullOrEmpty(parameters.path) ? "Assets" : parameters.path; string filter = $"t:{parameters.assetType}"; // Find all assets of the specified type string[] guids = AssetDatabase.FindAssets(filter, new[] { searchPath }); List<AssetInfo> assets = new List<AssetInfo>(); foreach (string guid in guids) { string assetPath = AssetDatabase.GUIDToAssetPath(guid); UnityEngine.Object asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(assetPath); if (asset != null) { assets.Add(new AssetInfo { name = asset.name, path = assetPath, guid = guid, type = asset.GetType().Name }); } } var result = new ListAssetsResult { assets = assets.ToArray(), total = assets.Count }; var response = JsonRpcResponse.Success(result, id); return response.ToJson(); } catch (Exception e) { Debug.LogError($"[MCP] ListAssets error: {e.Message}\n{e.StackTrace}"); return JsonRpcResponseHelper.ErrorMessage($"Failed to list assets: {e.Message}", id); } #else return JsonRpcResponseHelper.ErrorMessage("ListAssets requires Unity Editor", id); #endif } /// <summary> /// Finds a specific asset by path or GUID. /// </summary> /// <param name="paramsJson">JSON parameters containing path or guid</param> /// <param name="id">JSON-RPC request ID</param> /// <returns>JSON-RPC response containing asset information or not found status</returns> public static string FindAsset(string paramsJson, object id) { #if UNITY_EDITOR try { var parameters = JsonUtility.FromJson<FindAssetParams>(paramsJson); string assetPath = null; // Resolve path from GUID if provided if (!string.IsNullOrEmpty(parameters.guid)) { assetPath = AssetDatabase.GUIDToAssetPath(parameters.guid); } else if (!string.IsNullOrEmpty(parameters.path)) { assetPath = parameters.path; } else { return JsonRpcResponseHelper.InvalidParams("Either 'path' or 'guid' parameter is required", id); } // Check if asset exists if (string.IsNullOrEmpty(assetPath) || !File.Exists(assetPath)) { var notFoundResult = new FindAssetResult { found = false }; var notFoundResponse = JsonRpcResponse.Success(notFoundResult, id); return notFoundResponse.ToJson(); } // Load asset UnityEngine.Object asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(assetPath); if (asset == null) { var notFoundResult = new FindAssetResult { found = false }; var notFoundResponse = JsonRpcResponse.Success(notFoundResult, id); return notFoundResponse.ToJson(); } // Get asset metadata string guid = AssetDatabase.AssetPathToGUID(assetPath); FileInfo fileInfo = new FileInfo(assetPath); var assetInfo = new AssetInfoDetailed { name = asset.name, path = assetPath, guid = guid, type = asset.GetType().Name, fileSize = fileInfo.Length, lastModified = fileInfo.LastWriteTimeUtc.ToString("o") }; var result = new FindAssetResult { found = true, asset = assetInfo }; var response = JsonRpcResponse.Success(result, id); return response.ToJson(); } catch (Exception e) { Debug.LogError($"[MCP] FindAsset error: {e.Message}\n{e.StackTrace}"); return JsonRpcResponseHelper.ErrorMessage($"Failed to find asset: {e.Message}", id); } #else return JsonRpcResponseHelper.ErrorMessage("FindAsset requires Unity Editor", id); #endif } /// <summary> /// Refreshes the AssetDatabase to detect file changes and recompile scripts. /// </summary> /// <param name="paramsJson">JSON parameters (optional: importMode)</param> /// <param name="id">JSON-RPC request ID</param> /// <returns>JSON-RPC response</returns> public static string RefreshAssetDatabase(string paramsJson, object id) { #if UNITY_EDITOR try { var parameters = JsonUtility.FromJson<RefreshParams>(paramsJson); ImportAssetOptions importOptions = ImportAssetOptions.Default; // Parse import mode if (!string.IsNullOrEmpty(parameters.importMode)) { switch (parameters.importMode.ToLower()) { case "forcesynchronousimport": importOptions = ImportAssetOptions.ForceSynchronousImport; break; case "forceupdate": importOptions = ImportAssetOptions.ForceUpdate; break; case "importrecursive": importOptions = ImportAssetOptions.ImportRecursive; break; default: importOptions = ImportAssetOptions.Default; break; } } Debug.Log($"[MCP] Refreshing AssetDatabase with mode: {importOptions}"); // Refresh the AssetDatabase AssetDatabase.Refresh(importOptions); var result = new RefreshResult { success = true, message = "AssetDatabase refreshed successfully", importMode = importOptions.ToString() }; var response = JsonRpcResponse.Success(result, id); return response.ToJson(); } catch (Exception e) { Debug.LogError($"[MCP] RefreshAssetDatabase error: {e.Message}\n{e.StackTrace}"); return JsonRpcResponseHelper.ErrorMessage($"Failed to refresh AssetDatabase: {e.Message}", id); } #else return JsonRpcResponseHelper.ErrorMessage("RefreshAssetDatabase requires Unity Editor", id); #endif } /// <summary> /// Deletes an asset from the project. /// </summary> /// <param name="paramsJson">JSON parameters containing assetPath</param> /// <param name="id">JSON-RPC request ID</param> /// <returns>JSON-RPC response</returns> public static string DeleteAsset(string paramsJson, object id) { #if UNITY_EDITOR try { var parameters = JsonUtility.FromJson<AssetPathParams>(paramsJson); if (string.IsNullOrEmpty(parameters.assetPath)) { return JsonRpcResponseHelper.InvalidParams("assetPath is required", id); } // Check if asset exists if (!AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(parameters.assetPath)) { return JsonRpcResponseHelper.ErrorMessage($"Asset not found at path: {parameters.assetPath}", id); } // Delete the asset bool success = AssetDatabase.DeleteAsset(parameters.assetPath); if (!success) { return JsonRpcResponseHelper.ErrorMessage($"Failed to delete asset: {parameters.assetPath}", id); } var result = new AssetOperationResult { success = true, message = $"Asset deleted: {parameters.assetPath}", assetPath = parameters.assetPath }; var response = JsonRpcResponse.Success(result, id); return response.ToJson(); } catch (Exception e) { Debug.LogError($"[MCP] DeleteAsset error: {e.Message}\n{e.StackTrace}"); return JsonRpcResponseHelper.ErrorMessage($"Failed to delete asset: {e.Message}", id); } #else return JsonRpcResponseHelper.ErrorMessage("DeleteAsset requires Unity Editor", id); #endif } /// <summary> /// Moves an asset to a new path. /// </summary> /// <param name="paramsJson">JSON parameters containing oldPath and newPath</param> /// <param name="id">JSON-RPC request ID</param> /// <returns>JSON-RPC response</returns> public static string MoveAsset(string paramsJson, object id) { #if UNITY_EDITOR try { var parameters = JsonUtility.FromJson<MoveAssetParams>(paramsJson); if (string.IsNullOrEmpty(parameters.oldPath)) { return JsonRpcResponseHelper.InvalidParams("oldPath is required", id); } if (string.IsNullOrEmpty(parameters.newPath)) { return JsonRpcResponseHelper.InvalidParams("newPath is required", id); } // Check if source asset exists if (!AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(parameters.oldPath)) { return JsonRpcResponseHelper.ErrorMessage($"Asset not found at path: {parameters.oldPath}", id); } // Check if destination already exists if (AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(parameters.newPath)) { return JsonRpcResponseHelper.ErrorMessage($"Asset already exists at destination: {parameters.newPath}", id); } // Move the asset string error = AssetDatabase.MoveAsset(parameters.oldPath, parameters.newPath); if (!string.IsNullOrEmpty(error)) { return JsonRpcResponseHelper.ErrorMessage($"Failed to move asset: {error}", id); } var result = new AssetOperationResult { success = true, message = $"Asset moved from {parameters.oldPath} to {parameters.newPath}", assetPath = parameters.newPath }; var response = JsonRpcResponse.Success(result, id); return response.ToJson(); } catch (Exception e) { Debug.LogError($"[MCP] MoveAsset error: {e.Message}\n{e.StackTrace}"); return JsonRpcResponseHelper.ErrorMessage($"Failed to move asset: {e.Message}", id); } #else return JsonRpcResponseHelper.ErrorMessage("MoveAsset requires Unity Editor", id); #endif } /// <summary> /// Copies an asset to a new path. /// </summary> /// <param name="paramsJson">JSON parameters containing sourcePath and destinationPath</param> /// <param name="id">JSON-RPC request ID</param> /// <returns>JSON-RPC response</returns> public static string CopyAsset(string paramsJson, object id) { #if UNITY_EDITOR try { var parameters = JsonUtility.FromJson<CopyAssetParams>(paramsJson); if (string.IsNullOrEmpty(parameters.sourcePath)) { return JsonRpcResponseHelper.InvalidParams("sourcePath is required", id); } if (string.IsNullOrEmpty(parameters.destinationPath)) { return JsonRpcResponseHelper.InvalidParams("destinationPath is required", id); } // Check if source asset exists if (!AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(parameters.sourcePath)) { return JsonRpcResponseHelper.ErrorMessage($"Asset not found at path: {parameters.sourcePath}", id); } // Check if destination already exists if (AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(parameters.destinationPath)) { return JsonRpcResponseHelper.ErrorMessage($"Asset already exists at destination: {parameters.destinationPath}", id); } // Copy the asset bool success = AssetDatabase.CopyAsset(parameters.sourcePath, parameters.destinationPath); if (!success) { return JsonRpcResponseHelper.ErrorMessage($"Failed to copy asset from {parameters.sourcePath} to {parameters.destinationPath}", id); } var result = new AssetOperationResult { success = true, message = $"Asset copied from {parameters.sourcePath} to {parameters.destinationPath}", assetPath = parameters.destinationPath }; var response = JsonRpcResponse.Success(result, id); return response.ToJson(); } catch (Exception e) { Debug.LogError($"[MCP] CopyAsset error: {e.Message}\n{e.StackTrace}"); return JsonRpcResponseHelper.ErrorMessage($"Failed to copy asset: {e.Message}", id); } #else return JsonRpcResponseHelper.ErrorMessage("CopyAsset requires Unity Editor", id); #endif } } #region Data Structures /// <summary> /// Parameters for listing assets. /// </summary> [Serializable] public class ListAssetsParams { public string assetType; public string path; } /// <summary> /// Parameters for finding an asset. /// </summary> [Serializable] public class FindAssetParams { public string path; public string guid; } /// <summary> /// Basic asset information. /// </summary> [Serializable] public class AssetInfo { public string name; public string path; public string guid; public string type; } /// <summary> /// Detailed asset information including file metadata. /// </summary> [Serializable] public class AssetInfoDetailed { public string name; public string path; public string guid; public string type; public long fileSize; public string lastModified; } /// <summary> /// Result of listing assets. /// </summary> [Serializable] public class ListAssetsResult { public AssetInfo[] assets; public int total; } /// <summary> /// Result of finding an asset. /// </summary> [Serializable] public class FindAssetResult { public bool found; public AssetInfoDetailed asset; } /// <summary> /// Parameters for refreshing AssetDatabase. /// </summary> [Serializable] public class RefreshParams { public string importMode; // "Default", "ForceSynchronousImport", "ForceUpdate", "ImportRecursive" } /// <summary> /// Result of refreshing AssetDatabase. /// </summary> [Serializable] public class RefreshResult { public bool success; public string message; public string importMode; } /// <summary> /// Parameters for asset path operations. /// </summary> [Serializable] public class AssetPathParams { public string assetPath; } /// <summary> /// Parameters for moving an asset. /// </summary> [Serializable] public class MoveAssetParams { public string oldPath; public string newPath; } /// <summary> /// Parameters for copying an asset. /// </summary> [Serializable] public class CopyAssetParams { public string sourcePath; public string destinationPath; } /// <summary> /// Result of asset operations (delete, move, copy). /// </summary> [Serializable] public class AssetOperationResult { public bool success; public string message; public string assetPath; } #endregion }

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/dsgarage/UniMCP4CC'

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