King Hippopotamus

MCP server · Rhinoceros 3D · v0.2.2

golem-3dmcp

Gives an AI agent read and write access to a running Rhino 8 session over the Model Context Protocol, through 89 named tools.

pip install golem-3dmcp

0.2.2

on PyPI

89

tools on the bridge

245

tests, run before publish

MIT

license

What it is

golem-3dmcp implements the Model Context Protocol so an agent can drive Rhino 8 directly — create geometry, run booleans, drive Grasshopper, capture viewports, and execute Python inside the application. It works with any MCP-compatible host.

Specification

PropertyValue
ProtocolModel Context Protocol (stdio and Docker)
Host applicationRhinoceros 3D 8.x, with a plug-in on the application side
Tools89, counted from the live registry
Wire format4-byte big-endian length prefix, UTF-8, JSON object body, 64 MB ceiling
Python3.10 and above on the server side; the embedded interpreter is stdlib-only
Dependenciesmcp[cli] >=1.0.0,<2 — every runtime dependency capped at the next major
Tests245, run before publish
LicenseMIT

Recorded session

A recorded terminal session for this package is pending. The demo that exists is the generated city — a full Rhino scene built end to end by an agent through these tools: roads, towers, houses, trees, a stadium, a bridge, a harbour and the wind turbines behind it. Nothing stands in for a recording here until one is captured against the published release.

How it works

The bridge has two halves that cannot share code: a modern Python server, and a plug-in living inside the application's embedded interpreter that can install nothing.

The bridge

Two halves, one wire contract

The embedded half cannot install a dependency, so the contract between them is the thing that is kept identical.

Wire

The protocol module is vendored twice on purpose

Once for modern Python, once for the application's stdlib-only embedded interpreter. A shared compatibility shim would have had to satisfy modern lint and type rules on both sides; instead each copy pins the same wire contract and the lint config excludes the old-dialect half by path.

4-byte big-endian length | UTF-8 | JSON body
ceiling: 64 MB
Framing

A reply is matched to its request

Every response id is compared with the id of the request it answers. A mismatch raises RhinoProtocolError and closes the connection, instead of returning another command's result as if it were this one's.

if resp["id"] != req_id:
    raise RhinoProtocolError(...)
Timeout

A timed-out command cannot desynchronise the next one

The socket is closed and the connection marked disconnected, so a late reply is never read by the following command. The next command reconnects.

tests/test_connection_desync.py
# regression tests against a fake plug-in

Release

What the last release fixed

The 0.2.2 changelog, because a version number on its own says nothing.

Pin

An unbounded dependency shipped a release the server could not import

mcp 2.0.0 removed mcp.server.fastmcp, which the server imports, so an unbounded requirement broke a fresh install from both pip and the Docker image. Every runtime dependency is now capped at the next major.

mcp[cli] >= 1.0.0, < 2
Build

The Docker image reports its real version

The workflow passes the tag as a build argument the Dockerfile turns into the version. Previously every image built without a git directory reported 0.0.0.

SETUPTOOLS_SCM_PRETEND_VERSION=${VERSION}

Limits

What this does not do, and where it should not be trusted. These stay on the page whatever else changes.

  • Rhino 8 is required, and so is the plug-in on the application side. The package is a bridge; it does not model anything on its own and there is no headless mode.

  • Tool calls execute inside your running Rhino session with your permissions — including a tool that runs arbitrary Python. Point it only at hosts and prompts you trust.

  • The two halves of the wire module are vendored copies. They are kept identical by review and by the pinned contract, not by a shared import, so a change has to be made twice.

  • The published Docker image and the PyPI package track the same tag, but hosted CI runs are unavailable on this account: the release was built and uploaded by hand, and the scheduled dependency matrix is a file waiting for a runner.

Links

Defects in this package are issues in its own repository.

Author approval — 2026-08-23, hash c85a22c4