MCP Claude & Rhino

MCP Rhinoceros

Claude MCP ↔ Rhino.February 2026

Pablo Nuñez, from Fablab Leon, documented in the instructors bootcamp repository all the steps to work in Blender using natural language.

Along with Pablo’s documentation, the AI recitation on Monday 23.02.2026 by Cesar, Amina and Eric video was the trigger that finally pushed me to take the step and try connecting Rhinoceros and Grasshopper with AI.

In Grasshopper, it is easy to set up by installing Raven from the Package Manager; from the Rhinoceroscommand line it works flawlessly and is truly impressive. As a professional tool, it is outstanding, but as a learning aid for getting started with Grasshopper, it is simply wonderful.

I usually use Rhinoceros and Grasshopper as my daily tools for parametric design and digital fabrication, and I wanted to replicate Pablo’s steps, this time with Rhino. This February, I had the opportunity to complete an Erasmus stay at the Fablab in the School of Architecture at the University of Limerick. Ger and Javi, thank you for the opportunity to spend these days in Limerick and for giving me the chance to experiment with things like this.

Required software for installation on Windows

(besides Rhinoceros, of course)

SoftwareVersionHow to installRole
Node.js≥20.17.0https://nodejs.orgRuns the local Express server
npm11.9.0Bundled with Node.jsNode package manager
Express5.2.1npm install expressHTTP framework, port 3000
Python (CPython)3.14https://python.orgRequired to install uv/uvx
uv / uvx0.10.6pip install uvTool runner that launches rhinomcp (uvx side)
rhinomcp0.2.0Rhino Package Manager (Yak)Rhino plugin (.rhp), MCP bridge, adds mcpstart command
CPython in Rhino 83.9 (embedded)Bundled with Rhino 8Runtime for Rhino scripts, no install needed
Claude Desktop1.1.4328https://claude.ai/downloadAnthropic desktop app, web interface does NOT support MCP

Two Python runtimes coexist: CPython 3.14 (system, for uv/uvx) and CPython 3.9 (embedded in Rhino 8, for scripts). They are completely independent.

Installation — step by step

1. Install Node.js

Download and install version ≥20.17.0 from https://nodejs.org

Verify in terminal:

node --version
npm --version

2. Install Python (CPython 3.14)

Download and install from https://python.org

This is only needed to install uv/uvx. Rhino’s CPython 3.9 is bundled separately and requires no installation.

3. Install uv / uvx

Using pip:

pip install uv

Or with the official installer (Windows PowerShell):

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
⚠️
Important notice from Pablo
TROUBLESHOOTING: \If its not working: try to execute this command in the powershell console in Windows:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/0.7.20/install.ps1 | iex"

Verify:

uvx --version
# Expected: uv 0.10.6

Executable path on your machine:

C:\Users\pepe-vazquez\.local\bin\uvx.exe

4. Install rhinomcp plugin in Rhino

  1. Open Rhino 8
  2. Run the command PackageManager in the Rhino command bar
  3. Search for rhinomcp
  4. Install version 0.2.0 (author: Jingcheng Chen) Many thxs Jingcheng-chen Github
  5. Restart Rhino

This installs the plugin at:

C:\Users\pepe-vazquez\AppData\Roaming\McNeel\Rhinoceros\packages\8.0\rhinomcp\0.2.0\net8.0\rhinomcp.rhp

And adds the mcpstart command to Rhino, which launches the MCP bridge between Rhino and Claude Desktop.

MCP Start

But wait, you still need to install Claude for everything to work. However, once you activate the server in the following steps, you’ll be able to run a few simple tests to make sure everything is set up correctly.

5. Create the Express server folder

mkdir D:/Rhino-mcp
cd D:/Rhino-mcp
npm init -y
npm install express

6. Create server.js

Create D:/Rhino-mcp/server.js:

const express = require("express");

const app = express();
app.use(express.json());

app.post("/gh", (req, res) => {
  console.log("Data from Rhino:", req.body);
  res.json({ reply: "OK from MCP", received: req.body });
});

app.listen(3000, () => {
  console.log("Server running on port 3000");
});

The server echoes back received: req.body so Rhino can confirm what was sent and received.

7. Create Rhino scripts (CPython 3.9)

Create the folder D:/Rhino-mcp/scripts_Rhino/ with these two files.
These scripts run on CPython 3.9, which is Rhino’s embedded Python runtime.
That means you must use urllib.request instead of urllib2.
To make sure everything works correctly:

  • In the Rhinoceros command line, type RhinoCode or _ScriptEditor.
  • Then set the runtime selector to Python 3 (CPython), not IronPython.

Hello.py — Connection test

import urllib.request
import json

url = "http://localhost:3000/gh"
data = json.dumps({"message": "Hello from Rhino 8 (CPython 3.9)"}).encode('utf-8')
req = urllib.request.Request(url, data, {'Content-Type': 'application/json'})
response = urllib.request.urlopen(req)
print(response.read().decode('utf-8'))

Hello from Rhino

Python version — version control

import sys
print(sys.version)

Pyhton versiono

PointCoordinates.py — Geometry sender For this test, you need to draw a point in Rhino so you can select it afterward. The code will then return its position in space.

import urllib.request
import json
import rhinoscriptsyntax as rs

pt = rs.GetPoint("Select a point")

if pt:
    payload = {"x": pt.X, "y": pt.Y, "z": pt.Z}
    print("Sending: x={x}, y={y}, z={z}".format(**payload))

    data = json.dumps(payload).encode('utf-8')
    req = urllib.request.Request(
        "http://localhost:3000/gh",
        data,
        {'Content-Type': 'application/json'}
    )
    response = urllib.request.urlopen(req)
    result = json.loads(response.read().decode('utf-8'))
    print("Received by server: x={x}, y={y}, z={z}".format(**result["received"]))

Select a Point

8. Configure Claude Desktop

Edit or create:

C:\Users\pepe-vazquez\AppData\Roaming\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "rhino": {
      "command": "C:\\Users\\pepe-vazquez\\.local\\bin\\uvx.exe",
      "args": ["rhinomcp"],
      "env": {
        "RUST_LOG": "debug"
      }
    }
  }
}

You must replace pepe-vazquez with your username in all paths.
The uvx-side rhinomcp package is downloaded and cached automatically on first run.

Now you need to configure the local MCP server in Claude desktop.

Claude settings developer

ℹ️
Claude mentioned that a hammer icon should appear on the left side of the chat. It wasn’t showing up for me, and I struggled with it for quite a while, until it occurred to me to ask Claude directly in the chat, “Are you connected to Rhinoceros?” and it replied yes, hahaha. Everything was connected and I didn’t even realize it, I was just there looking for that hammer icon 🔨.

Final file structure

D:/Rhino-mcp/
├── server.js               ← Express server (port 3000)
├── package.json            ← dependency: express 5.2.1
├── package-lock.json
├── node_modules/           ← generated by npm install
└── scripts_Rhino/
    ├── Hello.py            ← connection test (CPython 3.9)
    └── PointCoordinates.py ← geometry sender (CPython 3.9)

Startup order (every session)

#Action
1Open Rhino 8
2Run mcpstart in the Rhino command bar, opens the TCP socket server
3Open Claude Desktop automatically launches uvx rhinomcp and connects to Rhino
4(Optional) Open a terminal and run node server.js — only needed to use your custom CPython scripts

WinError 10061 means node server.js is not running (only relevant for custom scripts).

Connection architecture

┌─────────────────────────────────────┐
│              RHINO 8                │
│  rhinomcp plugin v0.2.0             │
│  activated via: mcpstart            │
│  TCP socket server                  │
└────────────────┬────────────────────┘
                 │ MCP protocol (TCP socket)
┌────────────────▼────────────────────┐
│    uvx rhinomcp 0.10.6              │
│    C:\Users\pepe-vazquez\.local\bin\uvx.exe│
│    launched automatically by        │
│    Claude Desktop on startup        │
└────────────────┬────────────────────┘
                 │
┌────────────────▼────────────────────┐
│          CLAUDE DESKTOP             │
│     Anthropic desktop app           │
└─────────────────────────────────────┘

── Optional: custom CPython scripts ──

┌─────────────────────────────────────┐
│              RHINO 8                │
│  CPython 3.9 (embedded)             │
│  C:\Users\pepe-vazquez\.rhinocode\py39-rh8 │
│  urllib.request → POST /gh          │
└────────────────┬────────────────────┘
                 │ POST http://localhost:3000/gh
                 │ { "x": -29.77, "y": 8.10, "z": 0.0 }
┌────────────────▼────────────────────┐
│         EXPRESS SERVER              │
│     D:/Rhino-mcp/server.js          │
│     Node.js ≥20.17.0, port 3000     │
│     returns { reply, received }     │
└─────────────────────────────────────┘

Python paths reference

RuntimeVersionPath
CPython (system)3.14C:\Users\pepe-vazquez\AppData\Local\Programs\Python\Python314\
CPython (Rhino 8)3.9C:\Users\pepe-vazquez\.rhinocode\py39-rh8\python.exe
IronPython (Rhino 8)2.7.12C:\Program Files\Rhino 8\Plug-ins\IronPython\
uvx executableC:\Users\pepe-vazquez\.local\bin\uvx.exe

Notes and warnings

  • The connection is 100% local — no ports are exposed to the internet.
  • In Rhino’s Script Editor, always select Python 3 as the runtime, not IronPython.
  • Claude Desktop is required. The web interface at claude.ai does not support MCP.
  • mcpstart must be run in Rhino before opening Claude Desktop.
  • node server.js must be running in a terminal before executing any script from Rhino.
  • RUST_LOG: debug in claude_desktop_config.json enables detailed logs for troubleshooting.
  • The uvx-side rhinomcp package is downloaded and cached automatically the first time Claude Desktop starts.

You must replace pepe-vazquez with your username.
rhinomcp (uvx side) is downloaded and cached automatically on first run, no manual install needed.
After editing this file, restart Claude Desktop for changes to take effect.

First tests

Click here…

Last updated on