Editor/Commands/Tools/CloudInstallTool.cs
// Copyright Braxnet 2025 unless specified otherwise
// https://braxnet.online
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
using Editor;
using Sandbox;
namespace Braxnet.Commands.Tools;
[MCPTool( "cloud_install", "Cloud Install", "Install assets from the cloud" )]
public class CloudInstallTool : IMCPTool
{
public string Name => "cloud_install";
public string Title => "Cloud Install";
public string Description => "Install assets from the cloud";
public JsonElement InputSchema => JsonSerializer.SerializeToElement( new
{
type = "object",
properties = new
{
packageIdent = new { type = "string", description = "Full ident of the package to install" }
},
required = new[] { "packageIdent" }
} );
public JsonElement OutputSchema => default;
public async Task<CallToolResult> ExecuteAsync( Dictionary<string, object> arguments, string sessionId )
{
var result = new CallToolResult();
if ( arguments == null || !arguments.ContainsKey( "packageIdent" ) )
{
result.IsError = true;
result.Content.Add( new TextContent { Text = "Full package ident is required" } );
return result;
}
var packageIdent = arguments["packageIdent"].ToString();
if ( string.IsNullOrEmpty( packageIdent ) )
{
result.IsError = true;
result.Content.Add( new TextContent { Text = "Package ident cannot be empty" } );
return result;
}
var package = await Package.FetchAsync( packageIdent, false );
if ( package == null )
{
result.IsError = true;
result.Content.Add( new TextContent { Text = $"Package not found: {packageIdent}" } );
return result;
}
if ( !AssetSystem.CanCloudInstall( package ) )
{
result.IsError = true;
result.Content.Add(
new TextContent { Text = $"Package cannot be installed from the cloud: {packageIdent}" } );
return result;
}
if ( AssetSystem.IsCloudInstalled( package ) )
{
string assetPath = package.GetMeta<string>( "PrimaryAsset" );
var asset = AssetSystem.FindByPath( assetPath );
if ( asset != null )
{
result.Content.Add( new TextContent { Text = $"Asset already installed at: {assetPath}" } );
result.StructuredContent = new
{
Asset = new AssetInfo()
{
Path = asset.RelativePath,
RenderMins = package.GetMeta( "RenderMins", "" ),
RenderMaxs = package.GetMeta( "RenderMaxs", "" ),
PhysicsMins = package.GetMeta( "PhysicsMins", "" ),
PhysicsMaxs = package.GetMeta( "PhysicsMaxs", "" ),
}
};
return result;
}
else
{
result.IsError = true;
result.Content.Add(
new TextContent { Text = $"Asset already installed but not found at: {assetPath}" } );
return result;
}
}
await GameTask.MainThread(); // Ensure this runs on the main thread
var installedAsset = await AssetSystem.InstallAsync( package.FullIdent );
if ( installedAsset == null )
{
result.IsError = true;
result.Content.Add( new TextContent { Text = $"Failed to install package: {packageIdent}" } );
return result;
}
result.Content.Add( new TextContent { Text = $"Successfully installed package: {packageIdent}" } );
result.StructuredContent = new
{
Asset = new AssetInfo()
{
Path = installedAsset.RelativePath,
RenderMins = package.GetMeta( "RenderMins", "" ),
RenderMaxs = package.GetMeta( "RenderMaxs", "" ),
PhysicsMins = package.GetMeta( "PhysicsMins", "" ),
PhysicsMaxs = package.GetMeta( "PhysicsMaxs", "" ),
}
};
return result;
}
public class AssetInfo
{
public string Path { get; set; }
public string RenderMins { get; set; }
public string RenderMaxs { get; set; }
public string PhysicsMins { get; set; }
public string PhysicsMaxs { get; set; }
}
}