From 36c05e7196046ee29dc611cac317662de3342623 Mon Sep 17 00:00:00 2001 From: ahujasid Date: Thu, 13 Mar 2025 17:02:04 +0530 Subject: [PATCH] added polyhaven checkbox --- README.md | 4 +- addon.py | 56 +++++++++++++++++++-------- src/blender_mcp/server.py | 80 +++++++++++++++++++-------------------- 3 files changed, 80 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index be1c05d..e274fa1 100644 --- a/README.md +++ b/README.md @@ -80,8 +80,8 @@ uvx blender-mcp 1. In Blender, go to the 3D View sidebar (press N if not visible) 2. Find the "BlenderMCP" tab -3. Set the port number (default: 9876) -4. Click "Start MCP Server" +3. Turn on the Poly Haven checkbox if you want assets from their API (optional) +4. Click "Connect to Claude" 5. Make sure the MCP server is running in your terminal ### Using with Claude diff --git a/addon.py b/addon.py index 039a8ba..3e73095 100644 --- a/addon.py +++ b/addon.py @@ -148,14 +148,12 @@ class BlenderMCPServer: cmd_type = command.get("type") params = command.get("params", {}) - # Add a simple ping handler - if cmd_type == "ping": - print("Handling ping command") - return {"status": "success", "result": {"pong": True}} + # Add a handler for checking PolyHaven status + if cmd_type == "get_polyhaven_status": + return {"status": "success", "result": self.get_polyhaven_status()} + # Base handlers that are always available handlers = { - "ping": lambda **kwargs: {"pong": True}, - "get_simple_info": self.get_simple_info, "get_scene_info": self.get_scene_info, "create_object": self.create_object, "modify_object": self.modify_object, @@ -163,14 +161,19 @@ class BlenderMCPServer: "get_object_info": self.get_object_info, "execute_code": self.execute_code, "set_material": self.set_material, - "render_scene": self.render_scene, - # Add Polyhaven handlers - "get_polyhaven_categories": self.get_polyhaven_categories, - "search_polyhaven_assets": self.search_polyhaven_assets, - "download_polyhaven_asset": self.download_polyhaven_asset, - "set_texture": self.set_texture, + "get_polyhaven_status": self.get_polyhaven_status, } + # Add Polyhaven handlers only if enabled + if bpy.context.scene.blendermcp_use_polyhaven: + polyhaven_handlers = { + "get_polyhaven_categories": self.get_polyhaven_categories, + "search_polyhaven_assets": self.search_polyhaven_assets, + "download_polyhaven_asset": self.download_polyhaven_asset, + "set_texture": self.set_texture, + } + handlers.update(polyhaven_handlers) + handler = handlers.get(cmd_type) if handler: try: @@ -1137,7 +1140,20 @@ class BlenderMCPServer: traceback.print_exc() return {"error": f"Failed to apply texture: {str(e)}"} - + def get_polyhaven_status(self): + """Get the current status of PolyHaven integration""" + enabled = bpy.context.scene.blendermcp_use_polyhaven + if enabled: + return {"enabled": True, "message": "PolyHaven integration is enabled and ready to use."} + else: + return { + "enabled": False, + "message": """PolyHaven integration is currently disabled. To enable it: + 1. In the 3D Viewport, find the BlenderMCP panel in the sidebar (press N if hidden) + 2. Check the 'Use assets from Poly Haven' checkbox + 3. Restart the connection to Claude""" + } + # Blender UI Panel class BLENDERMCP_PT_Panel(bpy.types.Panel): bl_label = "Blender MCP" @@ -1151,6 +1167,7 @@ class BLENDERMCP_PT_Panel(bpy.types.Panel): scene = context.scene layout.prop(scene, "blendermcp_port") + layout.prop(scene, "blendermcp_use_polyhaven", text="Use assets from Poly Haven") if not scene.blendermcp_server_running: layout.operator("blendermcp.start_server", text="Start MCP Server") @@ -1161,7 +1178,7 @@ class BLENDERMCP_PT_Panel(bpy.types.Panel): # Operator to start the server class BLENDERMCP_OT_StartServer(bpy.types.Operator): bl_idname = "blendermcp.start_server" - bl_label = "Start BlenderMCP Server" + bl_label = "Connect to Claude" bl_description = "Start the BlenderMCP server to connect with Claude" def execute(self, context): @@ -1180,8 +1197,8 @@ class BLENDERMCP_OT_StartServer(bpy.types.Operator): # Operator to stop the server class BLENDERMCP_OT_StopServer(bpy.types.Operator): bl_idname = "blendermcp.stop_server" - bl_label = "Stop BlenderMCP Server" - bl_description = "Stop the BlenderMCP server" + bl_label = "Stop the connection to Claude" + bl_description = "Stop the connection to Claude" def execute(self, context): scene = context.scene @@ -1210,6 +1227,12 @@ def register(): default=False ) + bpy.types.Scene.blendermcp_use_polyhaven = bpy.props.BoolProperty( + name="Use Poly Haven", + description="Enable Poly Haven asset integration", + default=False + ) + bpy.utils.register_class(BLENDERMCP_PT_Panel) bpy.utils.register_class(BLENDERMCP_OT_StartServer) bpy.utils.register_class(BLENDERMCP_OT_StopServer) @@ -1228,6 +1251,7 @@ def unregister(): del bpy.types.Scene.blendermcp_port del bpy.types.Scene.blendermcp_server_running + del bpy.types.Scene.blendermcp_use_polyhaven print("BlenderMCP addon unregistered") diff --git a/src/blender_mcp/server.py b/src/blender_mcp/server.py index 8504b71..9828220 100644 --- a/src/blender_mcp/server.py +++ b/src/blender_mcp/server.py @@ -196,17 +196,19 @@ mcp = FastMCP( # Global connection for resources (since resources can't access context) _blender_connection = None +_polyhaven_enabled = False # Add this global variable def get_blender_connection(): """Get or create a persistent Blender connection""" - global _blender_connection + global _blender_connection, _polyhaven_enabled # Add _polyhaven_enabled to globals # If we have an existing connection, check if it's still valid if _blender_connection is not None: - # Test if the connection is still alive with a simple ping try: - # Just try to send a small message to check if the socket is still connected - _blender_connection.sock.sendall(b'') + # First check if PolyHaven is enabled by sending a ping command + result = _blender_connection.send_command("get_polyhaven_status") + # Store the PolyHaven status globally + _polyhaven_enabled = result.get("enabled", False) return _blender_connection except Exception as e: # Connection is dead, close it and create a new one @@ -260,33 +262,7 @@ def get_object_info(ctx: Context, object_name: str) -> str: logger.error(f"Error getting object info from Blender: {str(e)}") return f"Error getting object info: {str(e)}" -# Tool endpoints -@mcp.tool() - - -@mcp.tool() -def set_object_property( - ctx: Context, - name: str, - property: str, - value: Any -) -> str: - """ - Set a single property of an object. - - Parameters: - - name: Name of the object - - property: Property to set (location, rotation, scale, color, visible) - - value: New value for the property - """ - try: - blender = get_blender_connection() - params = {"name": name, property: value} - result = blender.send_command("modify_object", params) - return f"Set {property} of {name} to {value}" - except Exception as e: - return f"Error setting property: {str(e)}" @mcp.tool() def create_object( @@ -447,11 +423,11 @@ def get_polyhaven_categories(ctx: Context, asset_type: str = "hdris") -> str: Parameters: - asset_type: The type of asset to get categories for (hdris, textures, models, all) - - Returns a list of categories with the count of assets in each category. """ try: blender = get_blender_connection() + if not _polyhaven_enabled: + return "PolyHaven integration is disabled. Select it in the sidebar in BlenderMCP, then run it again." result = blender.send_command("get_polyhaven_categories", {"asset_type": asset_type}) if "error" in result: @@ -632,25 +608,45 @@ def set_texture( logger.error(f"Error applying texture: {str(e)}") return f"Error applying texture: {str(e)}" +@mcp.tool() +def get_polyhaven_status(ctx: Context) -> str: + """ + Check if PolyHaven integration is enabled in Blender. + Returns a message indicating whether PolyHaven features are available. + """ + try: + blender = get_blender_connection() + result = blender.send_command("get_polyhaven_status") + enabled = result.get("enabled", False) + message = result.get("message", "") + + return message + except Exception as e: + logger.error(f"Error checking PolyHaven status: {str(e)}") + return f"Error checking PolyHaven status: {str(e)}" + @mcp.prompt() def asset_creation_strategy() -> str: """Defines the preferred strategy for creating assets in Blender""" - return """When creating 3D content in Blender, follow these priorities: + return """When creating 3D content in Blender, always start by checking if PolyHaven is available: - 1. First, try to find and use appropriate PolyHaven assets: + 0. Before anything, always check the scene from get_scene_info() + 1. First use get_polyhaven_status() to verify if PolyHaven integration is enabled. + + 2. If PolyHaven is enabled: - For objects/models: Use download_polyhaven_asset() with asset_type="models" - For materials/textures: Use download_polyhaven_asset() with asset_type="textures" - For environment lighting: Use download_polyhaven_asset() with asset_type="hdris" - 2. Only fall back to basic creation tools when: - - A simple primitive is explicitly requested - - No suitable PolyHaven asset exists - - The task specifically requires a basic material/color - - Time or resource constraints make downloading assets impractical + 3. If PolyHaven is disabled or when falling back to basic tools: + - create_object() for basic primitives (CUBE, SPHERE, CYLINDER, etc.) + - set_material() for basic colors and materials - Basic creation tools to use as fallback: - - create_object() for basic primitives - - set_material() for basic colors and materials + Only fall back to basic creation tools when: + - PolyHaven is disabled + - A simple primitive is explicitly requested + - No suitable PolyHaven asset exists + - The task specifically requires a basic material/color """ # Main execution