Editor/Mcp/BridgeVehicleTools.cs

Editor tool bindings for the MCP (Manifest Control Panel). Declares static methods that call McpGate.Run to generate vehicle-related C# components and to apply handling presets: create physics grab tool, seat system, vehicle controller, and tune vehicle via reflection.

Reflection
// 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>
/// Make things drivable: generate raycast-car controllers with built-in driver seats, standalone
/// enter/exit seats, and physgun-style grab tools; apply arcade/drift/offroad/race handling presets
/// to any vehicle component. Attach the generated components with batch_add_component; verify by
/// driving in play mode.
/// </summary>
[McpToolset( "bridge_vehicle", "Make things drivable: generate raycast-car controllers with built-in driver seats, standalone enter/exit seats, and physgun-style grab tools; apply arcade/drift/offroad/race handling presets to any vehicle component. Attach the generated components with batch_add_component; verify by driving in play mode." )]
public static class BridgeVehicleTools
{
	/// <summary>
	/// Generate a physgun-lite player component: hold attack2 while looking at a Rigidbody prop within
	/// Range to grab it — it spring-follows a point in front of your view with physics LIVE (collides
	/// and swings, unlike the parented create_carry_system) — attack1 throws it, release lets go. Grab
	/// requests route through the host, which assigns the grabber network ownership. Returns { created,
	/// path, className, nextSteps } — trigger_hotload + compile_status, attach to the player object;
	/// ensure_input_action if attack1/attack2 aren't bound.
	/// </summary>
	/// <param name="name">Class/file name (default 'PhysicsGrabTool' -&gt; Code/PhysicsGrabTool.cs). Errors if the file exists.</param>
	/// <param name="directory">Directory for the .cs file. Default 'Code'.</param>
	[McpTool( "create_physics_grab_tool" )]
	public static Task<object> CreatePhysicsGrabTool( string name = null, string directory = null )
		=> McpGate.Run( "create_physics_grab_tool", McpGate.Args( ( "name", name ), ( "directory", directory ) ) );

	/// <summary>
	/// Generate a standalone networked one-occupant seat component: press E (use) to sit — claims route
	/// through the host so seats can't be shared — E to stand; the occupant parents to the seat with
	/// their controller input disabled and restored on exit, which tries each ExitOffsets entry and
	/// takes the first spot with clearance. Static OnOccupantChanged event for camera/UI. For chairs,
	/// benches, turret mounts; vehicles get a seat built into create_vehicle_controller. Returns {
	/// created, path, className, nextSteps } — trigger_hotload + compile_status, then attach to any
	/// prop.
	/// </summary>
	/// <param name="name">Class/file name (default 'Seat' -&gt; Code/Seat.cs). Errors if the file exists.</param>
	/// <param name="directory">Directory for the .cs file. Default 'Code'.</param>
	[McpTool( "create_seat_system" )]
	public static Task<object> CreateSeatSystem( string name = null, string directory = null )
		=> McpGate.Run( "create_seat_system", McpGate.Args( ( "name", name ), ( "directory", directory ) ) );

	/// <summary>
	/// Generate a drivable raycast-car component: 4-corner spring/damper suspension, mass-scaled engine
	/// force, speed-scaled yaw steering, lateral grip (lower = drift), and a BUILT-IN driver seat
	/// (press E to enter — the driver is hidden while driving so their controller can't fight the
	/// vehicle transform, the host assigns them ownership, and a chase camera follows the car — E to
	/// exit). Attach it plus a Rigidbody and collider to any prop and it drives. Returns { created,
	/// path, className, nextSteps } — follow with trigger_hotload + compile_status, then
	/// batch_add_component the parts. Apply handling presets with tune_vehicle. HONEST LIMIT: compiles
	/// + runs is verified; driving FEEL needs a human playtest — tune from the inspector while playing.
	/// </summary>
	/// <param name="name">Class/file name (default 'VehicleController' -&gt; Code/VehicleController.cs). Errors if the file exists.</param>
	/// <param name="directory">Directory for the .cs file. Default 'Code'.</param>
	/// <param name="engineForce">Engine force (mass-scaled). Default 900.</param>
	/// <param name="steerStrength">Yaw rate in rad/s at full speed factor. Default 2.0.</param>
	/// <param name="grip">Lateral grip 0-1 — fraction of sideways velocity killed per tick; lower = drift. Default 0.85.</param>
	[McpTool( "create_vehicle_controller" )]
	public static Task<object> CreateVehicleController( string name = null, string directory = null, double? engineForce = null, double? steerStrength = null, double? grip = null )
		=> McpGate.Run( "create_vehicle_controller", McpGate.Args( ( "name", name ), ( "directory", directory ), ( "engineForce", engineForce ), ( "steerStrength", steerStrength ), ( "grip", grip ) ) );

	/// <summary>
	/// Apply a handling preset to a vehicle component on a GameObject: arcade (forgiving), drift (low
	/// grip, sharp steering), offroad (soft long-travel suspension), or race (fast, planted). Sets
	/// EngineForce/MaxSpeed/SteerStrength/GripFactor/SuspensionStrength/SuspensionDamping by name via
	/// reflection — targets create_vehicle_controller scaffolds out of the box, partially tunes
	/// anything exposing those property names. Returns { tuned, preset, component, applied, missing } —
	/// missing lists properties the component lacks. Auto-finds the first component with 'Vehicle' in
	/// its type name; pass component to target explicitly. Scene-mutating: refused during play mode
	/// (use set_property on runtime objects while playing).
	/// </summary>
	/// <param name="id">GUID of the GameObject carrying the vehicle component (from find_objects).</param>
	/// <param name="preset">Handling preset to apply. One of: arcade | drift | offroad | race.</param>
	/// <param name="component">Component type name to tune. Default: first component with 'Vehicle' in its name.</param>
	[McpTool( "tune_vehicle" )]
	public static Task<object> TuneVehicle( string id, string preset, string component = null )
		=> McpGate.Run( "tune_vehicle", McpGate.Args( ( "id", id ), ( "preset", preset ), ( "component", component ) ) );
}