From daa09c66e3a94a66eb06acdc2e55a5aff15757be Mon Sep 17 00:00:00 2001 From: nekos Date: Sun, 29 Jun 2025 23:52:13 +0900 Subject: [PATCH 1/2] feat: Add configurable port support for MCP server - Add port parameter to start_server() and initialize_plugin() - Add --port command line argument to houdini_mcp_server.py - Maintain backward compatibility with default port 9876 - Update comments to document the new functionality --- __init__.py | 22 ++++++++++++++-------- houdini_mcp_server.py | 32 +++++++++++++++++++++++--------- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/__init__.py b/__init__.py index eac5f5e..1339b00 100644 --- a/__init__.py +++ b/__init__.py @@ -1,9 +1,9 @@ import hou from .server import HoudiniMCPServer -def start_server(): +def start_server(port=9876): if not hasattr(hou.session, "houdinimcp_server") or hou.session.houdinimcp_server is None: - hou.session.houdinimcp_server = HoudiniMCPServer() + hou.session.houdinimcp_server = HoudiniMCPServer(port=port) hou.session.houdinimcp_server.start() else: print("Houdini MCP Server is already running.") @@ -15,13 +15,19 @@ def stop_server(): else: print("Houdini MCP Server is not running.") -# Optionally auto-start -def initialize_plugin(): +# Optional auto-start +# Note: This requires Houdini GUI mode (won't work in hython/hbatch) +# +# Usage: +# If you want the MCP server to start automatically when Houdini launches, +# add the following to your pythonrc.py: +# +# import houdinimcp +# houdinimcp.initialize_plugin(port=9876) # You can change the port number +# +def initialize_plugin(port=9876): # Set up default session toggles if desired if not hasattr(hou.session, "houdinimcp_use_assetlib"): hou.session.houdinimcp_use_assetlib = False # Auto-start server if you want: - start_server() - -# If you want the plugin to auto-load on import: -initialize_plugin() + start_server(port) diff --git a/houdini_mcp_server.py b/houdini_mcp_server.py index 22f8de0..8c659e0 100644 --- a/houdini_mcp_server.py +++ b/houdini_mcp_server.py @@ -4,11 +4,12 @@ This is the "bridge" or "driver" script that Claude will run via `uv run`. It uses the MCP library (fastmcp) to communicate with Claude over stdio, -and relays each command to the local Houdini plugin on port 9876. +and relays each command to the local Houdini plugin on a configurable port. """ import sys import os import site +import argparse # Get the directory where the script is located script_dir = os.path.dirname(os.path.abspath(__file__)) @@ -442,7 +443,7 @@ def send_command(self, cmd_type: str, params: Dict[str, Any] = None) -> Dict[str """ if not self.connect(): # Instead of raising, return an error dict consistent with API errors - error_msg = "Could not connect to Houdini on port 9876." + error_msg = f"Could not connect to Houdini on port {self.port}." logger.error(error_msg) # Return structure similar to API failures return {"status": "error", "message": error_msg, "origin": "mcp_server_connection"} @@ -513,19 +514,20 @@ def send_command(self, cmd_type: str, params: Dict[str, Any] = None) -> Dict[str # A global Houdini connection object _houdini_connection: HoudiniConnection = None +_houdini_port: int = 9876 # Default port def get_houdini_connection() -> HoudiniConnection: """Get or create a persistent HoudiniConnection object.""" - global _houdini_connection + global _houdini_connection, _houdini_port if _houdini_connection is None: - logger.info("Creating new HoudiniConnection.") - _houdini_connection = HoudiniConnection(host="localhost", port=9876) + logger.info(f"Creating new HoudiniConnection on port {_houdini_port}.") + _houdini_connection = HoudiniConnection(host="localhost", port=_houdini_port) # Always try to connect, returns True if already connected or successful now if not _houdini_connection.connect(): # Connection failed, reset _houdini_connection to allow retry next time? _houdini_connection = None - raise ConnectionError("Could not connect to Houdini on localhost:9876. Is the plugin running?") + raise ConnectionError(f"Could not connect to Houdini on localhost:{_houdini_port}. Is the plugin running?") return _houdini_connection @@ -889,11 +891,23 @@ def get_opus_job_result(batch_job_id: str) -> dict: def main(): """Run the MCP server on stdio.""" + global _houdini_port + + # Parse command line arguments + parser = argparse.ArgumentParser(description='Houdini MCP Server Bridge') + parser.add_argument('--port', type=int, default=9876, + help='Port to connect to Houdini (default: 9876)') + args = parser.parse_args() + + # Set the global port variable + _houdini_port = args.port + logger.info(f"Configured to connect to Houdini on port {_houdini_port}") + # Check necessary RapidAPI variables are set before running if not RAPIDAPI_HOST_URL or not RAPIDAPI_HOST or not RAPIDAPI_KEY: - logger.critical("RAPIDAPI_HOST_URL, RAPIDAPI_HOST, and RAPIDAPI_KEY environment variables are not set. Please configure urls.env.") - logger.critical("Server will not start.") - sys.exit(1) # Exit if critical configuration is missing + logger.critical("RAPIDAPI_HOST_URL, RAPIDAPI_HOST, and RAPIDAPI_KEY environment variables are not set. Please configure urls.env.") + logger.critical("Server will not start.") + sys.exit(1) # Exit if critical configuration is missing logger.info(f"Using RapidAPI Host URL: {RAPIDAPI_HOST_URL}") logger.info(f"Using RapidAPI Host Header: {RAPIDAPI_HOST}") From 1ea6c52a6217600352bf857f0ad39b0bdb20de45 Mon Sep 17 00:00:00 2001 From: nekos Date: Wed, 2 Jul 2025 20:47:54 +0900 Subject: [PATCH 2/2] - Update README.md with port configuration examples" --- README.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ea8d40a..ff6cf16 100644 --- a/README.md +++ b/README.md @@ -72,12 +72,14 @@ Label: "MCP" import hou import houdinimcp + _PORT = 9876 + if hasattr(hou.session, "houdinimcp_server") and hou.session.houdinimcp_server: houdinimcp.stop_server() hou.ui.displayMessage("Houdini MCP Server stopped") else: - houdinimcp.start_server() - hou.ui.displayMessage("Houdini MCP Server started on localhost:9876") + houdinimcp.start_server(_PORT) + hou.ui.displayMessage(f"Houdini MCP Server started on localhost:{_PORT}") ``` @@ -128,12 +130,17 @@ Add an entry: "args": [ "run", "python", - "C:/Users//Documents/houdini19.5/scripts/python/houdinimcp/houdini_mcp_server.py" + "C:/Users//Documents/houdini19.5/scripts/python/houdinimcp/houdini_mcp_server.py", + "--port", + "9876" ] } } } ``` +Note: The port number must match between the shelf tool and Claude Desktop configuration. +If you change it in one place, make sure to update it in the other. + if uv run was successful and claude failed to load mcp, make sure claude is using the same python version, use: ```cmd python -c "import sys; print(sys.executable)" @@ -152,6 +159,7 @@ you will need a Rapid API key to log in. Create an account at: [RapidAPI](https: Subscribe to OPUS API at: [OPUS API Subscribe](https://rapidapi.com/genel-gi78OM1rB/api/opus5/pricing) Get your Rapid API key at [OPUS API](https://rapidapi.com/genel-gi78OM1rB/api/opus5) add the key to urls.env -### 4 Acknowledgement + +### 6 Acknowledgement Houdini-MCP was built following [blender-mcp](https://github.com/ahujasid/blender-mcp). We thank them for the contribution.