Skip to main content
Glama

rhino-mcp

Drive McNeel Rhino 8 and Grasshopper from Claude through the Model Context Protocol.

PyPI Python License Rhino MCP Platform

English · 한국어


Overview

rhino-mcp is a Model Context Protocol server that lets Claude (or any MCP client) drive Rhino 8 — creating geometry, manipulating layers and materials, baking Grasshopper output, exporting STEP/IGES/STL/OBJ — through plain natural-language tool calls. It runs in two modes:

  • Standalone (default): backed by rhino3dm for headless .3dm file authoring; works without Rhino installed and exposes ~242 tools (geometry, file-I/O, transform, layer, material, analysis, RhinoScript docs, composition, document hygiene, geometry validation, GH template catalogue, freeform skin / panelisation / curvature / fields, drawing-set sheet + title block, schedule / quantity, block definition, sun-position + shadow projection, BIM metadata tagging, 19 physical material presets, BRE daylight factor + Bird DNI clear-sky model, and multi-Rhino announcement-file discovery).

  • Bridge: when the C# bridge plugin is loaded in a live Rhino 8 session, the server transparently forwards every call (booleans, lofts, sweeps, viewport image capture + zoom-to-object / zoom-to-layer, render, scripting (Python and gated Roslyn C# with timeouts and extra references), deformation, NURBS editing, SubD, paneling, freeform analysis with true Gaussian curvature, drawing-set view placement + section cuts + PDF export, accurate Brep-area schedules, block explode/redefine, ray-cast solar exposure + Brep ray probe, IFC / gbXML import-export, HDRI environment, camera / light / render / turntable automation, layer-material binding, and every Grasshopper operation including batched connect_many wiring and slider placement) to RhinoCommon and Grasshopper.Instances, exposing ~245 tools.

Features

  • Full geometry catalogue — points, lines, polylines, arcs, circles, ellipses, polygons, helixes, NURBS curves, rebuilds.

  • Solids and meshes — boxes, spheres, cylinders, cones, tori, mesh boxes; booleans / sweeps / lofts / fillets via the bridge.

  • Transforms — move, rotate, scale, mirror, plane-to-plane orient, linear/polar/rectangular arrays.

  • Script execution — run arbitrary RhinoScript Python (IronPython) or RhinoCommon C# (Roslyn) code in a live Rhino session, with built-in RhinoScript API documentation search (899 functions).

  • Advanced modeling — deformation (bend/twist/taper/flow), NURBS editing (rebuild/unroll/evaluate), SubD, surface matching, extraction (dup edge/border/isocurve/Make2D), control points, and paneling tools.

  • Drawing-set authoring — sheet / title block / north arrow / scale bar in standalone; multi-view placement, section cuts, and PDF export through the bridge.

  • Quantity & schedule — per-layer / per-material / per-user_text aggregation with CSV export; bridge mode uses AreaMassProperties / VolumeMassProperties for accurate Brep area + volume.

  • Block / instance reuse — define / insert / list blocks in standalone; explode / redefine in bridge mode for synchronized component edits.

  • Environmental analysis — sun position + monthly sun-path polylines + shadow projection (NOAA SPA approximation); ray-cast solar exposure in bridge mode. Daylight precision adds Bird DNI clear-sky model with Kasten-Young air mass and Linke turbidity, plus BRE simplified daylight factor.

  • BIM interchange — IFC2x3 / IFC4 / IFC4x3 import & export, gbXML export, and IFC PropertySet metadata tagging that round-trips through user_text.

  • Material presets + HDRI — 19 bundled physical presets (concrete / brick / steel / aluminium / glass / timber / stone / plaster / fabric / landscape) keyed by category; HDRI environment for rendering.

  • Render automation — camera / light / render-engine setup, render-to-file, and parametric turntable sequences (bridge mode).

  • Undo / redo and batch operations — every bridge operation is wrapped in undo records; batch modify changes many objects in a single call.

  • Layers, materials, blocks, groups — full attribute control on the document.

  • File I/O — open/save .3dm, export OBJ/STL standalone; STEP/IGES/DXF and screenshots via the bridge.

  • Inline base64 screenshotsrhino_screenshot(as_base64=True) returns the PNG payload inline for visual verification by the LLM.

  • Rich object selectionrhino_object_select filters by glob name pattern, layer, RGB color, object type, and user-text key/value pairs.

  • Pagination on bulk queriesrhino_list_objects returns a pagination: {total, offset, limit, returned, has_more} block so large documents stay manageable.

  • Scene composition shortcuts (v0.2) — rhino_place_grid, rhino_stack_floors, rhino_scatter, rhino_replicate_along_curve collapse "loop + transform" into a single tool call.

  • Document hygiene tools (v0.2) — query/set units, tolerances, and base point (rhino_document_units_*, rhino_tolerance_*, rhino_origin_set); rhino_document_summary exposes them so the LLM can verify scale before issuing geometry calls.

  • Geometry validation (v0.2) — rhino_validate_brep, rhino_report_mesh_health, rhino_curve_continuity, plus rhino_check_naked_edges (bridge) for explicit topology diagnostics before booleans / exports.

  • Grasshopper template loader (v0.2) — gh_template_list reads a manifest of pre-wired definitions; gh_load_template, gh_bind_template_parameter, gh_run_template (bridge) load, parameterise, and bake them.

  • Free-form architecture toolkitrhino_skin_from_sections, rhino_uv_grid_panels, rhino_panel_planarity, rhino_panel_curvature_classify, rhino_surface_developable_score, rhino_attractor_displace_points, rhino_smooth_polyline. Bridge mode adds true Gaussian / mean / principal curvature, world-axis slicing, and waffle ribs.

  • Strategy prompts for the LLM — seven @mcp.prompt() guides (general_strategy, rhinoscript_workflow, viewport_workflow, parametric_workflow, bim_authoring_workflow, design_dialogue_workflow, freeform_workflow) help Claude pick the right tool, avoid hallucinated APIs, and keep the user in the loop on design decisions.

  • Async-capable tools — read-only query tools run on async def so concurrent bridge round-trips don't stall the MCP transport.

  • Robust connection layer — JSON-RPC over named pipe / Unix socket / TCP with MSG_PEEK liveness probes and exponential backoff with jitter on reconnect.

  • Grasshopper automation — open .gh files, drop components, wire them, set sliders/panels/toggles, run, bake, read DataTrees.

  • Three transports — stdio (Claude Desktop), Streamable HTTP, Docker/TCP.

  • Capability-aware registration — bridge-only tools are simply not registered when no bridge is reachable; no stub functions, ever.

  • Actionable errors — every failure carries a category, a remediation hint, and details the agent can act on.

Architecture

┌──────────────┐     stdio | HTTP     ┌────────────────┐
│  Claude /    │ ◀──────────────────▶ │   rhino-mcp    │
│  MCP client  │                      │   (Python)     │
└──────────────┘                      └─────┬──────────┘
                                            │
                              JSON-RPC 2.0  │   (named pipe / unix socket / TCP)
                                            │
                                  ┌─────────▼──────────┐
                                  │  C# Bridge Plugin  │
                                  │  (inside Rhino 8)  │
                                  │  ────────────────  │
                                  │  RhinoCommon       │
                                  │  Grasshopper       │
                                  │  Roslyn (C# exec)  │
                                  │  IronPython (Py)   │
                                  └────────────────────┘

In standalone mode the right-hand side is replaced by an in-process rhino3dm.File3dm document; bridge-only tools are unregistered.

Requirements

  • Python 3.11 or newer

  • rhino3dm >= 8.9, mcp[cli] >= 1.2, pydantic >= 2.6 (installed automatically)

  • Optional: McNeel Rhino 8 (any platform) — needed only for bridge mode

  • Optional: .NET 8 SDK — to build the C# bridge plugin (dotnet build)

  • Optional: pywin32 on Windows for the named-pipe transport

Installation

uv tool install rhino-mcp
# or, from a checkout:
uv sync && uv run rhino-mcp

Using pip

pip install rhino3dm-mcp
rhino-mcp --version

One-shot Claude Desktop wiring

After installing the package, register the server with Claude Desktop in a single command instead of editing claude_desktop_config.json by hand:

rhino-mcp install                         # auto-detect launcher (uvx / rhino-mcp / python)
rhino-mcp install --mode bridge           # force bridge mode in the env block
rhino-mcp install --force                 # overwrite an existing entry
rhino-mcp install --dry-run               # preview the JSON without writing

The command writes a timestamped .bak.* copy of the existing config before saving, and is idempotent — re-running with the same flags is a no-op. Restart Claude Desktop afterwards to pick up the change.

From inside Rhino — _McpInstall

If the bridge plugin is loaded, type _McpInstall on the Rhino command line. The command is non-interactive: it locates uvx / rhino-mcp / python on PATH (with ~/.local/bin, ~/.cargo/bin, /opt/homebrew/bin, and /usr/local/bin searched on macOS so the GUI-app PATH is enough), runs the same install pipeline as rhino-mcp install, and streams the outcome to the Rhino command line. The MCP server is registered with --mode auto so Claude Desktop attaches to the bridge when Rhino is running and falls back to standalone (rhino3dm) when it is not.

Docker

docker compose -f docker/docker-compose.yml up --build

The container exposes the server over Streamable HTTP on TCP :8765.

Running the server

rhino-mcp is normally launched by an MCP client (Claude Desktop / Cursor / claude.ai connector) via the command + args you put into the client's config. You can also run it manually for debugging.

Launch modes

Use case

Command

Stdio (Claude Desktop default)

uvx rhino3dm-mcp or rhino-mcp

Streamable HTTP (local dev / Cursor)

rhino-mcp --transport http --host 127.0.0.1 --port 8765

Streamable HTTP (claude.ai connector)

rhino-mcp --transport http --host 0.0.0.0 --port 8765 --allow-external --stateless

Docker (HTTP on :8765)

docker compose -f docker/docker-compose.yml up --build

Force standalone (no Rhino needed)

RHINO_MCP_FORCE_MODE=standalone rhino-mcp

Force bridge (fail fast if Rhino down)

RHINO_MCP_FORCE_MODE=bridge rhino-mcp

Force bridge with HTTP fallback

RHINO_MCP_FORCE_MODE=bridge RHINO_MCP_BRIDGE_OPTIONAL=1 rhino-mcp --transport http

Show all CLI flags

rhino-mcp --help

The HTTP endpoint is http://<host>:<port>/mcp. Use --allow-external only when exposing the server through ngrok / Cloudflare Tunnel / etc. — it disables DNS-rebinding protection.

Claude Desktop (stdio)

claude_desktop_config.json lives at:

OS

Path

macOS

~/Library/Application Support/Claude/claude_desktop_config.json

Windows

%APPDATA%\Claude\claude_desktop_config.json

Linux

~/.config/Claude/claude_desktop_config.json

Paste this entry under mcpServers:

{
  "mcpServers": {
    "rhino-mcp": {
      "command": "uvx",
      "args": ["rhino3dm-mcp"],
      "env": {
        "RHINO_MCP_TRANSPORT": "stdio",
        "RHINO_HOST": "127.0.0.1",
        "RHINO_PORT": "4242",
        "RHINO_MCP_LOG_LEVEL": "INFO"
      }
    }
  }
}

Prefer a checkout? Point command at uv and run from the repo:

{
  "mcpServers": {
    "rhino-mcp": {
      "command": "uv",
      "args": ["--directory", "/absolute/path/to/rhino-mcp", "run", "rhino-mcp"],
      "env": { "RHINO_MCP_LOG_LEVEL": "DEBUG" }
    }
  }
}

Restart Claude Desktop; the rhino-mcp tools and the three strategy prompts (general_strategy, rhinoscript_workflow, viewport_workflow) appear in the palette.

Cursor IDE

Cursor reads ~/.cursor/mcp.json (global) or <project>/.cursor/mcp.json (per-project):

{
  "mcpServers": {
    "rhino-mcp": {
      "command": "uvx",
      "args": ["rhino3dm-mcp"],
      "env": { "RHINO_MCP_FORCE_MODE": "bridge" }
    }
  }
}

claude.ai remote connector (Streamable HTTP)

  1. Run the server with HTTP + external access:

    rhino-mcp --transport http --host 0.0.0.0 --port 8765 --allow-external --stateless
  2. Tunnel it (e.g. ngrok http 8765) and grab the public HTTPS URL.

  3. In claude.ai → Settings → Connectors → Add custom connector, set the URL to https://<your-tunnel>/mcp.

Generic stdio MCP clients

Any MCP-compatible client (mcp-inspector, Continue, Claude Code, etc.) that can spawn a subprocess will work — give it uvx rhino3dm-mcp or the path to your rhino-mcp entry-point and inherit env vars from the table below.

Build and install the C# plugin for full 235 tool support. The included helper script wraps dotnet build and verifies the post-build install location:

./scripts/build-plugin.sh             # debug build + install
./scripts/build-plugin.sh --release   # release build
./scripts/build-plugin.sh --clean     # clean + rebuild

# Or invoke dotnet directly:
dotnet build rhino_plugin/csharp/RhinoMCPPlugin.csproj -c Release

Post-build targets copy the .rhp:

OS

Path

macOS

/Applications/Rhino 8.app/Contents/PlugIns/rhino-mcp.rhp

Windows

%APPDATA%/McNeel/Rhinoceros/8.0/Plug-ins/rhino-mcp/rhino-mcp.rhp

Restart Rhino 8 — the bridge starts automatically on load (TCP :4242 by default). Then restart rhino-mcp (or set RHINO_MCP_FORCE_MODE=bridge) and the bridge-only tools become available.

Quick start

# After "rhino-mcp" is configured in Claude Desktop, ask Claude:
#   "Create a 10-unit sphere at the origin and save the document to /tmp/demo.3dm"
# Behind the scenes Claude calls rhino_sphere → rhino_save.

Strategy prompts

Three MCP prompts are registered automatically and surfaced in the client's prompt picker:

Prompt

When to use

general_strategy

Decision tree for orienting in a document → choosing the right tool → best practices.

rhinoscript_workflow

Mandatory steps before invoking rhino_execute_python so the LLM doesn't hallucinate APIs.

viewport_workflow

How to combine rhino_zoom_extent + rhino_screenshot(as_base64=True) for visual checks.

Telling Claude "use the general_strategy prompt before you start" gives much better tool selection on long sessions.

Visual verification with base64 screenshots

"Build a 5x5x5 box on layer 'Demo', then take a 1280x720 base64 screenshot so you can confirm it landed."

Claude calls rhino_box → rhino_zoom_extent → rhino_screenshot(as_base64=True) and reads the inline PNG from the response (image_base64 field) on the next turn.

Pagination & rich filtering

"List the first 50 curves on the 'Walls' layer, then select every object whose name matches 'Pillar_*' on layer 'Structure'."

rhino_list_objects returns a pagination block; iterate with offset += limit until has_more is false. rhino_object_select accepts name_pattern, layer, color, object_type, user_text, and deselect_first.

Standalone smoke run from the shell:

RHINO_MCP_FORCE_MODE=standalone uv run python - <<'PY'
import asyncio
from rhino_mcp.server import build_server
from rhino_mcp.utils.registry import Mode

mcp, count = build_server(runtime_mode=Mode.STANDALONE, bridge_client=None)
print(f"{count} tools registered")
sphere = asyncio.run(
    mcp._tool_manager._tools["rhino_sphere"].run(
        {"args": {"center": {"x": 0, "y": 0, "z": 0}, "radius": 10.0}}
    )
)
print(sphere)
PY

Tools reference (summary)

Category

Standalone

+ Bridge

Notable members

Geometry

14

14

rhino_point, rhino_circle, rhino_helix, rhino_nurbs_curve, rhino_rebuild_curve

Curves

3

3

rhino_curve_length, rhino_curve_point_at, rhino_curve_split

Solids

5

10

rhino_box, rhino_sphere, rhino_boolean_union (bridge)

Surfaces

0

11

rhino_loft, rhino_sweep1, rhino_revolve

Mesh

1

8

rhino_mesh_box, rhino_weld_mesh (bridge)

Transform

9

11

rhino_array_polar, rhino_orient, rhino_flow (bridge)

Annotation

2

8

rhino_text_dot, rhino_dimension_linear (bridge)

Layer / Object

6

8

rhino_layer_create, rhino_block_insert (bridge)

Material

2

3

rhino_material_create, rhino_render_viewport (bridge)

File I/O

5

9

rhino_save, rhino_export_step (bridge)

Analysis

4

9

rhino_volume, rhino_zebra (bridge)

Query

7

8

rhino_list_objects, rhino_document_summary, rhino_get_selected_objects (bridge)

Display

0

5

rhino_zoom_extent, rhino_named_view_save

Scripting

0

2

rhino_execute_python, rhino_execute_csharp

RS Docs

4

4

rhino_search_rhinoscript_functions, rhino_get_rhinoscript_docs

History

0

2

rhino_undo, rhino_redo

Batch

0

1

rhino_batch_modify

Deformation

0

4

rhino_bend, rhino_twist, rhino_taper, rhino_flow_along_curve

NURBS

0

5

rhino_rebuild_surface, rhino_unroll, rhino_surface_from_points

SubD

0

2

rhino_create_subd, rhino_subd_to_nurbs

Srf Match

0

3

rhino_match_surface, rhino_blend_surface_edges, rhino_merge_surfaces

Extraction

0

4

rhino_dup_edge, rhino_dup_border, rhino_isocurve, rhino_make2d

Ctrl Points

0

2

rhino_get_control_points, rhino_set_control_points

Paneling

0

3

rhino_panelize_surface, rhino_create_uv_grid, rhino_panel_frames

Grasshopper

0

22

gh_set_slider, gh_bake_to_rhino, gh_data_tree_get

Drawing

2

5

rhino_drawing_sheet_create, rhino_drawing_title_block_add, rhino_drawing_view_place (bridge)

Schedule

5

5

rhino_schedule_by_layer, rhino_schedule_by_user_text, rhino_object_quantity

Blocks

3

5

rhino_block_define, rhino_block_insert, rhino_block_explode (bridge)

Environment

3

4

rhino_sun_position, rhino_sun_path, rhino_shadow_project

Freeform

8

11

rhino_skin_from_sections, rhino_panel_curvature_classify, rhino_attractor_displace_points

BIM I/O

1

4

rhino_bim_metadata_set, rhino_export_ifc (bridge), rhino_import_ifc (bridge), rhino_export_gbxml (bridge)

Materials+

2

3

rhino_material_preset_list, rhino_material_preset_create, rhino_environment_set (bridge)

Render

0

5

rhino_camera_set, rhino_light_add, rhino_render_setup, rhino_render_to_file, rhino_turntable_render

Daylight

2

2

rhino_direct_irradiance, rhino_daylight_factor

Detailed signatures live in docs/en/tools-reference.md.

Grasshopper integration

1. Start Rhino 8 → open Grasshopper → load your `.gh` definition.
2. Ensure the C# bridge plugin (`rhino-mcp.rhp`) is loaded in Rhino.
3. Set `RHINO_MCP_FORCE_MODE=bridge` and restart rhino-mcp.
4. From Claude:
   - "Open /work/wing.gh, set the 'span' slider to 12.5, run, bake to layer 'Wing'."
   - "Read the output of the 'Voronoi' component as a DataTree."

See docs/en/grasshopper-guide.md for canvas/component/cluster recipes.

Configuration

Every knob is controlled by an environment variable. CLI flags override env where applicable.

Variable

Default

Purpose

RHINO_MCP_TRANSPORT

stdio

stdio or http (Streamable HTTP)

RHINO_MCP_FORCE_MODE

(auto)

Force standalone or bridge

RHINO_MCP_BRIDGE_OPTIONAL

0

When 1 and RHINO_MCP_FORCE_MODE=bridge, fall back to standalone if the bridge is unreachable (recommended for HTTP connectors).

RHINO_MCP_TRANSPORT_KIND

(auto)

Bridge transport selector: pipe / unix / tcp

RHINO_HOST, RHINO_PORT

localhost:4242

TCP transport endpoint

RHINO_MCP_PIPE

rhino_mcp

Windows named-pipe name

RHINO_MCP_SOCKET

(XDG runtime)

Unix socket path override

RHINO_MCP_BRIDGE_TIMEOUT

1 (auto), 5 (forced)

Seconds to wait for a bridge ping

RHINO_MCP_RECONNECT_RETRIES

1

Max reconnect attempts after a transient transport failure

RHINO_MCP_RECONNECT_BASE_DELAY

0.5

Base delay (seconds) for exponential backoff

RHINO_MCP_RECONNECT_JITTER

0.25

Symmetric jitter ratio (0 disables, useful for tests)

RHINO_MCP_LOG_LEVEL

INFO

Stderr log level. Set DEBUG to see every bridge JSON-RPC call.

Development

git clone https://github.com/easehee/rhino-mcp.git
cd rhino-mcp
uv venv && source .venv/bin/activate
uv pip install -e '.[dev]'

# Tests + coverage
uv run pytest --cov=src/rhino_mcp

# Lint + type check
uv run ruff check src/ tests/
uv run mypy src/rhino_mcp

# Build the C# bridge plugin (auto-installs into Rhino on macOS/Windows)
./scripts/build-plugin.sh --release

# Wheel + sdist
./scripts/build.sh

Manual smoke test against a running server

# Terminal A — start the server with verbose logging
RHINO_MCP_LOG_LEVEL=DEBUG rhino-mcp --transport http --port 8765

# Terminal B — list tools via the MCP inspector or a curl probe
npx @modelcontextprotocol/inspector http://127.0.0.1:8765/mcp

Troubleshooting

Symptom

Likely cause / remediation

Cannot reach Rhino bridge.

Start Rhino 8 with the C# bridge plugin loaded; verify RHINO_HOST/RHINO_PORT.

Bridge-only tool absent in Claude

Server is in standalone mode — load the bridge plugin or set RHINO_MCP_FORCE_MODE=bridge.

Invalid parameter: axis (cylinder)

Standalone supports only {x:0,y:0,z:1}; switch to bridge for arbitrary axes.

non-3DM import error

Standalone import is .3dm-only; use bridge mode for STEP/IGES/DXF.

transport failure on tcp://...

The bridge crashed or Rhino was closed — rhino-mcp will reconnect with exponential backoff (RHINO_MCP_RECONNECT_RETRIES).

Stdout corrupted under stdio transport

Always log to stderr; rhino-mcp does this — verify no third-party libraries print to stdout.

image_base64 missing from screenshot

Caller passed as_base64=False (default) or the screenshot file failed to write — check the summary.path and base64_error fields.

Pagination loops forever

Always advance offset by pagination.returned, not by limit; the last page may be partial.

rhino_object_select returns 0 matches

Filters AND together — try removing one filter at a time; the color filter only works on objects with ColorSource=ColorFromObject.

More in docs/en/troubleshooting.md.

License

MIT — see LICENSE.

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
4dRelease cycle
5Releases (12mo)

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/EaseHee/rhino-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server