Editor/Mcp/BridgeMaterialTools.cs

Editor bridge for material and model tools, exposing MCP tool wrappers to assign models, assign materials, create .vmat materials, and set material properties via McpGate RPC calls.

Networking
// AUTO-GENERATED by scripts/emit-mcp-wrappers.mjs — DO NOT EDIT.
// Regenerate: node scripts/extract-manifest.mjs && node scripts/emit-mcp-wrappers.mjs
// Source of truth: sbox-mcp-server/src/tools/ (zod schemas) → scripts/tools-manifest.json

using System.Text.Json.Nodes;
using System.Threading.Tasks;
using Editor.Mcp;

/// <summary>
/// Assign models and materials to renderers, author .vmat materials, and set material properties.
/// </summary>
[McpToolset( "bridge_material", "Assign models and materials to renderers, author .vmat materials, and set material properties." )]
public static class BridgeMaterialTools
{
	/// <summary>
	/// Apply a material to a GameObject by setting its ModelRenderer's MaterialOverride (overrides the
	/// whole model's material). Requires an existing ModelRenderer (assign_model first) and errors if
	/// the material path can't be loaded. Returns { assigned, id, material } — tweak values afterwards
	/// with set_material_property.
	/// </summary>
	/// <param name="id">GUID of the GameObject.</param>
	/// <param name="material">Material path (e.g. 'materials/walls/brick.vmat').</param>
	/// <param name="slot">Material slot index. Defaults to 0 (first slot).</param>
	[McpTool( "assign_material" )]
	public static Task<object> AssignMaterial( string id, string material, double? slot = null )
		=> McpGate.Run( "assign_material", McpGate.Args( ( "id", id ), ( "material", material ), ( "slot", slot ) ) );

	/// <summary>
	/// Set a 3D model on a GameObject's ModelRenderer. Creates the renderer component if it doesn't
	/// exist; errors if the model path can't be loaded. Returns { assigned, id, model } — follow with
	/// assign_material / set_material_property to style it, or take a screenshot to verify.
	/// </summary>
	/// <param name="id">GUID of the GameObject.</param>
	/// <param name="model">Model path (e.g. 'models/citizen/citizen.vmdl', 'models/dev/box.vmdl').</param>
	[McpTool( "assign_model" )]
	public static Task<object> AssignModel( string id, string model )
		=> McpGate.Run( "assign_model", McpGate.Args( ( "id", id ), ( "model", model ) ) );

	/// <summary>
	/// Create a new material file (.vmat, KV1 format) with a shader and properties like color,
	/// roughness, metallic, texture. Errors if the file already exists; when no properties are given it
	/// writes sensible PBR defaults (g_flMetalness 0, g_flRoughness 1). Returns { created, path,
	/// shader, propertiesWritten } — pass the returned path to recompile_asset (so the editor compiles
	/// it) and then assign_material.
	/// </summary>
	/// <param name="path">Relative path for the material (e.g. 'materials/walls/brick.vmat').</param>
	/// <param name="shader">Shader to use. Defaults to 'shaders/complex.shader' (PBR).</param>
	/// <param name="properties">Material properties as key-value pairs (e.g. { "Color": "#ff0000", "Roughness": 0.8 }). JSON value.</param>
	[McpTool( "create_material" )]
	public static Task<object> CreateMaterial( string path, string shader = null, JsonNode properties = null )
		=> McpGate.Run( "create_material", McpGate.Args( ( "path", path ), ( "shader", shader ), ( "properties", properties ) ) );

	/// <summary>
	/// Change a property on the material assigned to a GameObject — color, roughness, metallic,
	/// texture, etc. Operates on the ModelRenderer's MaterialOverride; if none is assigned it
	/// auto-creates one from the default complex shader (no separate assign_material step needed).
	/// Returns { set, id, property, autoCreatedMaterial } — screenshot to verify the visual change.
	/// </summary>
	/// <param name="id">GUID of the GameObject.</param>
	/// <param name="property">Material property name (e.g. 'Color', 'Roughness', 'Metalness', 'Normal').</param>
	/// <param name="value">Property value — number for floats, string for texture paths/colors, {r,g,b,a} for colors. JSON value.</param>
	[McpTool( "set_material_property" )]
	public static Task<object> SetMaterialProperty( string id, string property, JsonNode value )
		=> McpGate.Run( "set_material_property", McpGate.Args( ( "id", id ), ( "property", property ), ( "value", value ) ) );
}