I made some hefty .gh scripts to simulate the behaviour of kites for making energy
My automation / looping / runtime control skills are flakey at best.
It took ages to coordinate all the actions involved in running the script, recording results resetting, repeating… I got bored
I’m one of those AI shiny toy bandwagon folk now and
I started finding uses for MCP servers while playing AI in VS Code
So far AI has been useless for developing my kite simulations
But I can now run reasoning models locally and they’re able to use these MCP servers / tools / clients to perform tasks locally and integrate with other software - more standard reliable code services.
So I’m looking for your advice -
Do I let the AI guide me into doing it’s bidding and following the approach described below for developing a two way communication between gh and a computer user AI with a reasoning model so that it can run tests over and over for me ? OR is this doomed/pointless from the start? Or am I going to miss out on all the .gh fun by giving the computer the tools
Am I hopelessly optimistic and need much tighter defined mission specification parameters ?
Here’s the plan according to the machines
To enable an AI to interact with RhinoPython components in Grasshopper locally, follow this structured approach using an MCP (Message Control Protocol) server:
- Architecture Overview
MCP Server: Embedded within Rhino via a RhinoPython script, handling TCP communication and Grasshopper interaction.AI Client: External client sending JSON commands to the server.
Workflow: AI → Client → MCP Server → Grasshopper → Results → AI.
- Components & Tools
MCP Server (Inside Rhino)
Technology: RhinoPython (IronPython) with .NET System.Net.Sockets.Role:
Listen for TCP connections.
Process JSON commands (component ID, inputs).
Manipulate Grasshopper components and return outputs.
AI Client
Language: Python (or any language supporting sockets).Role: Send commands to the MCP server and handle responses.
Grasshopper Setup
Ensure components have unique IDs/names for easy access.Use a .gh file with predefined logic for the AI to control.
- Step-by-Step Implementation
- MCP Server in RhinoPython
python
Copy
import clr
import System
from System.Net import Sockets
from System.IO import StreamReader, StreamWriter
from System.Text import Encoding
from System.Threading import Thread, ThreadStartclr.AddReference(“Grasshopper”)
import Grasshopper as ghdef handle_client(client):
try:
stream = client.GetStream()
reader = StreamReader(stream)
writer = StreamWriter(stream)# Read JSON command json_cmd = reader.ReadLine() cmd = parse_command(json_cmd) # Implement parsing # Execute on UI thread Rhino.RhinoApp.InvokeOnUiThread(lambda: process_command(cmd)) # Send response response = get_response() # Capture outputs writer.WriteLine(response) writer.Flush() except Exception as e: print(f"Error: {e}") finally: client.Close()
def start_server():
listener = TcpListener(System.Net.IPAddress.Parse(“127.0.0.1”), 12345)
listener.Start()
print(“Server started…”)while True: client = listener.AcceptTcpClient() thread = Thread(ThreadStart(lambda: handle_client(client))) thread.Start()
Start server in a background thread
server_thread = Thread(ThreadStart(start_server))
server_thread.IsBackground = True
server_thread.Start()
2. Command Processing
python
Copy
def process_command(cmd):
doc = gh.Instances.ActiveCanvas.Document # Access Grasshopper doc
component = next((c for c in doc.Objects if c.NickName == cmd[“component”]), None)if component: # Set inputs (example: first input) component.Params.Input[0].AddPersistentData(cmd["inputs"]) doc.NewSolution(False) # Recompute # Capture outputs outputs = [str(param.VolatileData[0]) for param in component.Params.Output] return {"outputs": outputs} else: return {"error": "Component not found"}
- AI Client (Python Example)
python
Copy
import socket
import jsondef send_command(cmd):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((“localhost”, 12345))
s.sendall(json.dumps(cmd).encode() + b’\n’)
response = s.recv(1024).decode()
return json.loads(response)Example usage
response = send_command({
“component”: “MyComponent”,
“inputs”: [1.5, 3.7]
})
print(response)
4. Setup & Execution
In Rhino:Open Grasshopper and load your .gh file.
Run the MCP server script (directly in RhinoPython editor).
AI Client:
Execute the client script, sending commands to localhost:12345.
- Key Considerations
Thread Safety: Use InvokeOnUiThread for Grasshopper operations.Error Handling: Robust error checking in both server and client.
Performance: Optimize Grasshopper definitions for speed.
Security: Add authentication tokens if exposing beyond localhost.
- Advanced Enhancements
Bidirectional Communication: Implement asynchronous updates from Grasshopper to AI.Multiple Components: Allow batch commands for complex interactions.
Plugin Integration: Wrap the server into a Grasshopper plugin for ease of use.
This setup enables seamless interaction between an AI and Grasshopper, leveraging local TCP communication for real-time control and feedback.
Rod here again
So I suspect a lot of that is just hopeless dreamy hallucination right?