"""Blender startup script for headless HF Spaces (NOT blender -b). Run under a virtual display so Blender's GUI event loop runs and the MCP addon's bpy.app.timers dispatcher fires (upstream explicitly refuses -b background mode for this reason): xvfb-run -a blender --python /app/bootstrap.py What it does: 1. Enables the bundled blender_mcp addon (expects addon.py copied to the Blender scripts/addons dir as blender_mcp.py by the Dockerfile). 2. Sets the socket port (env BLENDER_PORT, default 9876). 3. Calls the addon's own start operator (blendermcp.start_server) — no clicks needed. Blender stays alive afterwards (GUI loop under xvfb), serving MCP clients until the container stops. """ import os import sys import bpy def main() -> None: port = int(os.environ.get("BLENDER_PORT", "9876")) bpy.ops.preferences.addon_enable(module="blender_mcp") scene = bpy.context.scene if hasattr(scene, "blendermcp_port"): scene.blendermcp_port = port bpy.ops.blendermcp.start_server() running = getattr(getattr(bpy.types, "blendermcp_server", None), "running", False) print(f"BOOTSTRAP: blendermcp_server running={running} port={port}", flush=True) if not running: print("BOOTSTRAP FATAL: server did not start", flush=True) sys.exit(1) if __name__ == "__main__": main()