added polyhaven checkbox
This commit is contained in:
parent
40a8334b97
commit
36c05e7196
@ -80,8 +80,8 @@ uvx blender-mcp
|
|||||||
|
|
||||||
1. In Blender, go to the 3D View sidebar (press N if not visible)
|
1. In Blender, go to the 3D View sidebar (press N if not visible)
|
||||||
2. Find the "BlenderMCP" tab
|
2. Find the "BlenderMCP" tab
|
||||||
3. Set the port number (default: 9876)
|
3. Turn on the Poly Haven checkbox if you want assets from their API (optional)
|
||||||
4. Click "Start MCP Server"
|
4. Click "Connect to Claude"
|
||||||
5. Make sure the MCP server is running in your terminal
|
5. Make sure the MCP server is running in your terminal
|
||||||
|
|
||||||
### Using with Claude
|
### Using with Claude
|
||||||
|
|||||||
54
addon.py
54
addon.py
@ -148,14 +148,12 @@ class BlenderMCPServer:
|
|||||||
cmd_type = command.get("type")
|
cmd_type = command.get("type")
|
||||||
params = command.get("params", {})
|
params = command.get("params", {})
|
||||||
|
|
||||||
# Add a simple ping handler
|
# Add a handler for checking PolyHaven status
|
||||||
if cmd_type == "ping":
|
if cmd_type == "get_polyhaven_status":
|
||||||
print("Handling ping command")
|
return {"status": "success", "result": self.get_polyhaven_status()}
|
||||||
return {"status": "success", "result": {"pong": True}}
|
|
||||||
|
|
||||||
|
# Base handlers that are always available
|
||||||
handlers = {
|
handlers = {
|
||||||
"ping": lambda **kwargs: {"pong": True},
|
|
||||||
"get_simple_info": self.get_simple_info,
|
|
||||||
"get_scene_info": self.get_scene_info,
|
"get_scene_info": self.get_scene_info,
|
||||||
"create_object": self.create_object,
|
"create_object": self.create_object,
|
||||||
"modify_object": self.modify_object,
|
"modify_object": self.modify_object,
|
||||||
@ -163,14 +161,19 @@ class BlenderMCPServer:
|
|||||||
"get_object_info": self.get_object_info,
|
"get_object_info": self.get_object_info,
|
||||||
"execute_code": self.execute_code,
|
"execute_code": self.execute_code,
|
||||||
"set_material": self.set_material,
|
"set_material": self.set_material,
|
||||||
"render_scene": self.render_scene,
|
"get_polyhaven_status": self.get_polyhaven_status,
|
||||||
# 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,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 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)
|
handler = handlers.get(cmd_type)
|
||||||
if handler:
|
if handler:
|
||||||
try:
|
try:
|
||||||
@ -1137,6 +1140,19 @@ class BlenderMCPServer:
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return {"error": f"Failed to apply texture: {str(e)}"}
|
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
|
# Blender UI Panel
|
||||||
class BLENDERMCP_PT_Panel(bpy.types.Panel):
|
class BLENDERMCP_PT_Panel(bpy.types.Panel):
|
||||||
@ -1151,6 +1167,7 @@ class BLENDERMCP_PT_Panel(bpy.types.Panel):
|
|||||||
scene = context.scene
|
scene = context.scene
|
||||||
|
|
||||||
layout.prop(scene, "blendermcp_port")
|
layout.prop(scene, "blendermcp_port")
|
||||||
|
layout.prop(scene, "blendermcp_use_polyhaven", text="Use assets from Poly Haven")
|
||||||
|
|
||||||
if not scene.blendermcp_server_running:
|
if not scene.blendermcp_server_running:
|
||||||
layout.operator("blendermcp.start_server", text="Start MCP Server")
|
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
|
# Operator to start the server
|
||||||
class BLENDERMCP_OT_StartServer(bpy.types.Operator):
|
class BLENDERMCP_OT_StartServer(bpy.types.Operator):
|
||||||
bl_idname = "blendermcp.start_server"
|
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"
|
bl_description = "Start the BlenderMCP server to connect with Claude"
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
@ -1180,8 +1197,8 @@ class BLENDERMCP_OT_StartServer(bpy.types.Operator):
|
|||||||
# Operator to stop the server
|
# Operator to stop the server
|
||||||
class BLENDERMCP_OT_StopServer(bpy.types.Operator):
|
class BLENDERMCP_OT_StopServer(bpy.types.Operator):
|
||||||
bl_idname = "blendermcp.stop_server"
|
bl_idname = "blendermcp.stop_server"
|
||||||
bl_label = "Stop BlenderMCP Server"
|
bl_label = "Stop the connection to Claude"
|
||||||
bl_description = "Stop the BlenderMCP server"
|
bl_description = "Stop the connection to Claude"
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
scene = context.scene
|
scene = context.scene
|
||||||
@ -1210,6 +1227,12 @@ def register():
|
|||||||
default=False
|
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_PT_Panel)
|
||||||
bpy.utils.register_class(BLENDERMCP_OT_StartServer)
|
bpy.utils.register_class(BLENDERMCP_OT_StartServer)
|
||||||
bpy.utils.register_class(BLENDERMCP_OT_StopServer)
|
bpy.utils.register_class(BLENDERMCP_OT_StopServer)
|
||||||
@ -1228,6 +1251,7 @@ def unregister():
|
|||||||
|
|
||||||
del bpy.types.Scene.blendermcp_port
|
del bpy.types.Scene.blendermcp_port
|
||||||
del bpy.types.Scene.blendermcp_server_running
|
del bpy.types.Scene.blendermcp_server_running
|
||||||
|
del bpy.types.Scene.blendermcp_use_polyhaven
|
||||||
|
|
||||||
print("BlenderMCP addon unregistered")
|
print("BlenderMCP addon unregistered")
|
||||||
|
|
||||||
|
|||||||
@ -196,17 +196,19 @@ mcp = FastMCP(
|
|||||||
|
|
||||||
# Global connection for resources (since resources can't access context)
|
# Global connection for resources (since resources can't access context)
|
||||||
_blender_connection = None
|
_blender_connection = None
|
||||||
|
_polyhaven_enabled = False # Add this global variable
|
||||||
|
|
||||||
def get_blender_connection():
|
def get_blender_connection():
|
||||||
"""Get or create a persistent 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 we have an existing connection, check if it's still valid
|
||||||
if _blender_connection is not None:
|
if _blender_connection is not None:
|
||||||
# Test if the connection is still alive with a simple ping
|
|
||||||
try:
|
try:
|
||||||
# Just try to send a small message to check if the socket is still connected
|
# First check if PolyHaven is enabled by sending a ping command
|
||||||
_blender_connection.sock.sendall(b'')
|
result = _blender_connection.send_command("get_polyhaven_status")
|
||||||
|
# Store the PolyHaven status globally
|
||||||
|
_polyhaven_enabled = result.get("enabled", False)
|
||||||
return _blender_connection
|
return _blender_connection
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Connection is dead, close it and create a new one
|
# 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)}")
|
logger.error(f"Error getting object info from Blender: {str(e)}")
|
||||||
return f"Error getting object info: {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()
|
@mcp.tool()
|
||||||
def create_object(
|
def create_object(
|
||||||
@ -447,11 +423,11 @@ def get_polyhaven_categories(ctx: Context, asset_type: str = "hdris") -> str:
|
|||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- asset_type: The type of asset to get categories for (hdris, textures, models, all)
|
- 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:
|
try:
|
||||||
blender = get_blender_connection()
|
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})
|
result = blender.send_command("get_polyhaven_categories", {"asset_type": asset_type})
|
||||||
|
|
||||||
if "error" in result:
|
if "error" in result:
|
||||||
@ -632,25 +608,45 @@ def set_texture(
|
|||||||
logger.error(f"Error applying texture: {str(e)}")
|
logger.error(f"Error applying texture: {str(e)}")
|
||||||
return 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()
|
@mcp.prompt()
|
||||||
def asset_creation_strategy() -> str:
|
def asset_creation_strategy() -> str:
|
||||||
"""Defines the preferred strategy for creating assets in Blender"""
|
"""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 objects/models: Use download_polyhaven_asset() with asset_type="models"
|
||||||
- For materials/textures: Use download_polyhaven_asset() with asset_type="textures"
|
- For materials/textures: Use download_polyhaven_asset() with asset_type="textures"
|
||||||
- For environment lighting: Use download_polyhaven_asset() with asset_type="hdris"
|
- For environment lighting: Use download_polyhaven_asset() with asset_type="hdris"
|
||||||
|
|
||||||
2. Only fall back to basic creation tools when:
|
3. If PolyHaven is disabled or when falling back to basic tools:
|
||||||
- A simple primitive is explicitly requested
|
- create_object() for basic primitives (CUBE, SPHERE, CYLINDER, etc.)
|
||||||
- No suitable PolyHaven asset exists
|
- set_material() for basic colors and materials
|
||||||
- The task specifically requires a basic material/color
|
|
||||||
- Time or resource constraints make downloading assets impractical
|
|
||||||
|
|
||||||
Basic creation tools to use as fallback:
|
Only fall back to basic creation tools when:
|
||||||
- create_object() for basic primitives
|
- PolyHaven is disabled
|
||||||
- set_material() for basic colors and materials
|
- A simple primitive is explicitly requested
|
||||||
|
- No suitable PolyHaven asset exists
|
||||||
|
- The task specifically requires a basic material/color
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Main execution
|
# Main execution
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user