Almond MCP
# Almond MCP for Rhino
**0.7.0-rc.2 — structural analysis pre-release.** The Structure workspace now runs
Almond's own 3D frame solver: floor and placed-model loads, EN 1990 combinations,
rigid/simple joints, stability (αcr, sway imperfections, P-Δ), EN 1993-1-1 member
checks, per-curve sections (`almond:section`) and the **Almond Results** panel for
every member, support and combination. Concrete, timber and aluminium are indicative.
Start with the [Structure workspace tutorial](docs/structural-tutorial.md); release
notes and the pre-release checklist are in [docs/release-0.7.md](docs/release-0.7.md).
Install from Rhino's Package Manager with **Include pre-releases** ticked; the
stable release remains 0.6.0.
**0.6.0 — Almond workspace release.** Run **Almond** in Rhino
for a dockable Neo Swiss menu with **Models** and **Structural Validation**.
**AlmondLibrary** opens models directly; **AlmondStructure** (or **AlmondKaramba**)
opens the analysis workspace. Models retain compact tiles, Light/Original detail and
shared-block viewport placement. The structural workspace runs Almond's built-in
native solver (no Karamba needed: floor and placed-model loads, EN 1990
combinations, rigid/simple connections, stability, a live viewport overlay) or,
optionally, Karamba3D; both add selection capture, explicit assumptions,
support/load diagram toggles, mapped utilization and an exportable result record.
See [docs/native-solver.md](docs/native-solver.md#in-the-almond-panel).
The active IKEA catalogue, source links and four supplier-specific MCP tools
are retired. Existing local downloads and historical scene records are retained.
Karamba and the generated model/source libraries remain available.
See the [Rhino quickstart](docs/rhino-archive-quickstart.md) and
[release infrastructure](docs/release-0.6.md). Viewport dragging was confirmed
by the user on rc.6. Stable 0.6.0 passed its Rhino smoke test and is published
on Rhino Package Manager (`almondbridge`) and PyPI (`almond-mcp`).
Run
`almond-mcp library --open` for the local Neo Swiss interface: 47 Meshy models,
7 drawing elements, linked SVG/DXF views, downloads, and source evidence in
one searchable catalogue. The same index is exposed through the MCP tool
`search_asset_repository` and `almond://repository/{asset_id}` resources.
See the [Object Archive guide](docs/object-archive-0.6-rc3.md).
All 50 generated
models now carry embedded asset passports and ship with the Python package,
including their sidecar contracts and previews. New MCP tools recommend assets
with reasons and check rotated clearance envelopes before placement. See
[the release guide](docs/semantic-assets-0.6.md) for the workflow, packaging,
verification and remaining Rhino integration checks. The
[drafting update](docs/drafting-0.6-rc2.md) adds a ten-model SVG/DXF pilot,
custom GLB drawing generation, source discovery and drawing revision checks.
<p align="center"><img src="assets/almond-icon.svg" width="120" alt="Almond"></p>
Almond exposes Rhino 8 and a semantic design layer as MCP tools: curated
furniture/drawing/diagram libraries with spatial contracts, audited Karamba
capsules, structured retrieval (SQLite FTS5 + R-tree scene ledger), script
execution over a TCP bridge, and publishing into Chestnut.
## What Almond is
Most Rhino MCP servers give the model a single power: *run a script*. That
demos well, but generation is blind — the model has no memory of what is
already in the scene, no real-world dimensions, no constraints, and no way
to check its own work. The result is geometry that looks plausible and
measures wrong.
Almond is a **semantic layer around Rhino**, built so a language model can
design with spatial awareness and produce high-detail, high-fidelity output:
- **A persistent scene ledger** (SQLite) — scenes, rooms, placed instances,
delta-based revisions. The model *queries* the current state instead of
guessing it.
- **Curated asset libraries with spatial contracts** — every furniture and
drawing asset carries its real catalogue dimensions plus an authored
contract: anchor point, floor footprint, functional clearances (e.g.
900 mm in front of a bookcase), collision shape, placement priority.
Placement respects ergonomics, not just bounding boxes.
- **Structured retrieval** — FTS5 natural-language search and R-tree spatial
indexes, isolated per library, returning compact asset cards sized for a
model's context window.
- **Layout validation** — an R-tree broad-phase overlap and room-containment
check the model can run *before* committing a layout.
- **Audited Karamba capsules** — typed input/output contracts
(`ALMOND_IN_*`/`ALMOND_OUT_*`) over structural Grasshopper definitions, so
generated structures get real displacement/utilization feedback.
- **Drawing recipes** — layer hierarchies, plot weights, and linetype
standards applied as one command, so output reads as an architectural
drawing rather than raw curves.
- **Script execution and GLB publishing** — the raw `execute_rhino_script`
power is still there, plus one-call publishing of selected geometry into
Chestnut with physics metadata.
The design goal: the model composes from **verified parts and validated
layouts** instead of hallucinating geometry.
Two pieces work together:
- **`almond-mcp`** (this Python package, on PyPI) — the MCP server Claude
talks to. Holds the semantic layer; needs no Rhino SDK.
- **`almondbridge`** (a Rhino 8 plugin, on the Rhino Package Manager) —
listens on `127.0.0.1:5000` (local only) inside Rhino and executes what
the server sends. Starts automatically with Rhino.
## Setting up with an AI assistant?
Paste this to your assistant (Claude, Codex, etc.) — it prevents the two
most common failure modes (installing a different "Rhino MCP" product, and
needlessly upgrading Rhino):
> Install **Almond MCP** from https://github.com/liangjunglj-cpu/almond-mcp
> by following that repo's `AGENTS.md` exactly. The Rhino plugin is
> **almondbridge** on the Rhino 8 Package Manager
> (`& "C:\Program Files\Rhino 8\System\Yak.exe" install almondbridge`);
> the server is **almond-mcp** on PyPI, registered as `uvx almond-mcp`.
> Do not install any other "Rhino MCP" implementation, and do not upgrade
> Rhino — every Rhino 8 service release is supported.
## Setup, step by step
Fresh machine to working in about five minutes. You need Rhino 8 on Windows
and a Claude that supports MCP (Claude Desktop or Claude Code).
1. **Install the bridge.** In Rhino 8 run `_PackageManager`, search
`almondbridge`, install, restart Rhino. You should see
`RhinoAlmondBridge: TCP listener started on port 5000` in the command
history — no command needed. (`AlmondMCPStatus` checks it any time.)
2. **Install [uv](https://docs.astral.sh/uv/)** (Python not required —
uv manages everything):
```powershell
winget install astral-sh.uv
```
3. **Register the server with Claude.**
- *Claude Desktop:* edit `%APPDATA%\Claude\claude_desktop_config.json`:
```json
{
"mcpServers": {
"Almond": {
"command": "uvx",
"args": ["almond-mcp"]
}
}
}
```
- *Claude Code:* `claude mcp add Almond -- uvx almond-mcp`
4. **Restart Claude.** The Almond tools (`execute_rhino_script`,
`search_generated_assets`, `create_design_scene`, …) appear in the tool
list. First run creates `%LOCALAPPDATA%\Almond` with the library
manifests and the scene database.
5. **Check the plumbing** (Rhino open):
```powershell
uvx almond-mcp doctor
```
6. **Populate the asset libraries** (optional — everything except model
*placement* works without it). The manifests ship with the package, but
the model files are 3D Warehouse content that cannot legally be
redistributed (see `THIRD-PARTY-NOTICES.md`), so each user downloads
them from the original source pages:
```powershell
uvx almond-mcp fetch-assets --open # opens each missing model's source page
uvx almond-mcp fetch-assets # re-run to verify sha256 checksums
```
Save each download into the library's `models/` folder under the exact
file name shown; the command verifies every checksum.
7. **Optional extras:** Karamba3D 3.1 enables `validate_structure` (found at
runtime — never bundled); point `RHINO_MCP_LIBRARY_DIR` at your own
Grasshopper definition library to expose it via `list_library`.
## CLI
```text
almond-mcp start the MCP server (also: almond-mcp serve)
almond-mcp fetch-assets report missing/invalid model files and their sources
almond-mcp doctor check directories, manifests, state DB, bridge port
almond-mcp paths print every resolved directory
```
Directory resolution order: `RHINO_MCP_*` environment variable → repository
checkout (development) → `%LOCALAPPDATA%\Almond` (installed). Overridable
locations:
| Environment variable | Default folder |
| --- | --- |
| `RHINO_MCP_LIBRARY_DIR` | `Grasshopperfiles` (your GH/Karamba definitions) |
| `RHINO_MCP_DRAWING_ASSET_DIR` | `DrawingAssetfiles` |
| `RHINO_MCP_DIAGRAM_ASSET_DIR` | `DiagramAssetfiles` |
| `RHINO_MCP_DRAWING_RECIPE_DIR` | `DrawingRecipes` |
| `RHINO_MCP_GENERATED_ASSET_DIR` | `GeneratedAssetfiles` |
| `RHINO_MCP_CAPSULE_DIR` | `capsules` |
| `RHINO_MCP_STATE_DB` | `%LOCALAPPDATA%\Almond\almond_state.sqlite3` |
## Rhino to Chestnut
After `execute_rhino_script` returns the GUIDs it created, publish only those
objects with:
```text
publish_to_chestnut(
guids=[...],
asset_name="Timber Pavilion"
)
```
This preferred tool applies semantic defaults automatically. Its optional
`behavior` presets are `architecture`, `object`, and `animated`. Use the
lower-level tool only when explicit physics control is needed:
```text
publish_objects_to_chestnut(
guids=[...],
asset_name="Timber Pavilion",
asset_id="timber-pavilion-01",
body_type="static",
collider="box",
preserve_scale=true,
mass=0
)
```
The tool:
1. asks Rhino 8 to export the supplied GUIDs as GLB;
2. explicitly maps Rhino Z-up to glTF Y-up;
3. uploads the GLB and its source/physics metadata to Chestnut;
4. creates or updates the stable `asset_id`; and
5. removes the temporary GLB after publishing.
Reusing an `asset_id` updates the geometry while Chestnut placements continue
to reference the same asset URL.
Chestnut defaults to the deployed service at
`https://chestnut-mnvo.onrender.com`. Override it before starting the MCP
server when local development is required:
```powershell
$env:CHESTNUT_URL = "http://127.0.0.1:3000"
almond-mcp
```
## Architectural drawing asset library
Representation-only entourage and graphic proxies live in the independent
drawing asset library. They have a dedicated search:
```text
search_drawing_assets(query="landscape tree")
get_drawing_asset(asset_id="context-tree-chinese-elm-a708cff4")
place_drawing_asset(
asset_id="context-tree-chinese-elm-a708cff4",
x=12000,
y=8000
)
```
Audited drawing recipes are stored separately in `DrawingRecipes`. The first
recipe creates a technical-axon layer hierarchy with plot weights and custom
hidden/overhead linetypes:
```text
list_drawing_recipes()
get_drawing_recipe(recipe_id="technical_axon_v1")
apply_drawing_style(recipe_id="technical_axon_v1")
create_generation_plan(
goal="Produce a technical axonometric",
scope="drawing"
)
```
## Generated asset library (open, redistributable)
The optional drawing library describes community models that each user
must download themselves. `GeneratedAssetfiles/` is different: 47 (and
growing) architectural models generated with Meshy from Almond's own
prompts, owned by the project and released under **CC BY 4.0**, so they ship
with the repository and the 0.6 wheel for offline use. Categories:
| Group | Assets |
| --- | --- |
| Entourage | standing / walking / sitting person, deciduous and conifer tree, sedan car, bicycle |
| Site furniture | park bench, street lamp, bollard, bike hoop, litter bin |
| Building components | round and square column, glass balustrade (doors, windows and stairs are deliberately excluded: they need exact dimensions, so model them directly) |
| Fixtures and appliances | toilet, pedestal basin, bathtub, shower enclosure, range cooker, fridge-freezer |
| Generic furniture | three-seat sofa, dining table and chair, double bed, desk, office chair |
| Design-idiom furniture | bent-birch stool, table, trolley, webbed and cantilevered armchairs; moulded-plywood, shell and leather lounge chairs with ottoman; freeform coffee table, slatted bench, mesh task chair; loose-cover sofa, cube and track shelving, wire side table |
| Lighting | spherical pendant, arc floor lamp, balanced-arm task lamp |
Every GLB is normalised by `tools/build_generated_assets.py`: scaled to its
catalogue height, bottom-centre on the origin, measured (never nominal)
bounds in the manifest, one `ALMOND::<material_id>` material so
`import_asset_contract`'s restore step gives it the canonical Almond
material, and a `.almond.json` contract beside it.
```text
search_generated_assets(query="bench", max_height_mm=1000)
get_generated_asset(asset_id="gen-park-bench-1")
place_generated_asset(asset_id="gen-park-bench-1", x_mm=2400, y_mm=800, rotation_degrees=90)
register_scene_instance(scene_id=..., asset_id="gen-park-bench-1", ...) # then validate_scene_layout
```
To extend the library, add an entry to `GeneratedAssetfiles/catalogue.json`
(prompt, nominal size, material, clearances), generate it with Meshy
(the recipe is recorded in the catalogue: nano-banana concept image →
meshy-t2 smart-topology mesh, untextured), save the GLB as
`GeneratedAssetfiles/raw/<asset_id>.glb`, record the task ids in
`provenance.json`, and run the build script. Provenance and licensing are
documented in `docs/licensing-audit.md`.
## Structural validation with reports
`validate_structure(guids, structure_type, load_kn, material)` checks
generated geometry through three pathways in strict order of confidence —
real **Karamba 3.1 FEA** (api, high), audited capsule templates (medium),
or span-rule heuristics (rule_based, low) — and always labels which one
ran. Pass criteria: deflection ≤ span/250 and utilization below yield.
Every run is recorded in the local state database;
`export_structural_report()` renders the history to a Markdown report
(inputs, pathway, span/deflection/utilization/reactions, warnings,
PASS/FAIL). Details: `docs/structural-validation.md`.
On top of the solver, a **construction knowledge layer**
(`get_construction_guidance`, `Constructionfiles/manifest.json`) grounds
generated structures in real building assemblies: 23 curated systems (wood
joist floors to precast tees, platform framing to steel rigid frames) with
span ranges, depth rules of thumb, member spacings, and element roles
distilled from Ching's *Building Construction Illustrated* (4th ed.). Call
it before generating to pick a system and size members like a builder
would; `validate_structure` then appends a `construction_check` that flags
spans no real system covers — so geometry that merely solves numerically
but could not be constructed as drawn is caught too. Details:
`docs/construction-guidance.md`.
## Materials and cross-application exchange
Almond carries a curated PBR material library (`list_materials`) and stamps
geometry with machine-readable material metadata (`assign_material`): a
physically-based Rhino material plus `almond:*` user text (material_id,
`ue_material_slot`, base colour, metallic, roughness, opacity — and, for
structural members, `structural_role` / `construction_system` /
`structural_material`, declaring in construction terms what each object
is). GLB export
then carries real PBR channels, and Datasmith imports the user text as
Unreal asset metadata — so imports remap to your master materials by slot
name instead of being guessed from display colours.
The same metadata makes assets portable between applications:
```text
export_asset_contract(guids=[...], asset_id="canopy-01") # GLB + .almond.json
import_asset_contract(contract_path="...", x_mm=0, y_mm=0) # into any Rhino doc
get_blender_helper_script(action="export", asset_id="bench-01")
```
An *asset contract* travels beside the GLB carrying what the file format
drops — real dimensions, anchor, clearances, and each object's Almond
`material_id`. On import Almond collapses the duplicate materials glTF
creates, restores canonical colours (glTF round trips shift them), re-attaches
the metadata, places the asset by its anchor, and verifies the measured size
against the contract. `get_blender_helper_script` returns Python to run in
Blender (through blender-mcp) so Blender joins the workflow without a
dedicated bridge. Background and measurements:
`docs/cross-app-blender.md`.
## Karamba capsules
Audited capsule manifests (`capsules/*.capsule.json`) declare typed
input/output contracts for structural Grasshopper definitions using reserved
`ALMOND_IN_*` / `ALMOND_OUT_*` nicknames — beams, trusses, frames, shells,
gridshells, membranes, canopies, and high-rises. See `capsules/AUTHORING.md`
to bind your own definitions. Karamba3D itself is user-installed; the bridge
finds it at runtime via reflection.
## Structured retrieval and scene state
Almond builds a local SQLite database from the asset manifests at startup.
The database provides:
- library-isolated dimensional and category filters;
- FTS5 natural-language retrieval;
- R-tree asset and scene-instance spatial indexes;
- stable scene, room, asset, and instance handles;
- delta-based scene revisions; and
- dependency-ordered generation plans.
Search and list tools return compact asset cards. Full provenance,
footprints, clearances, and source metadata are returned only by
`get_generated_asset`. Geometry and Grasshopper files remain local.
Useful tools:
```text
get_retrieval_status()
create_design_scene(name="Apartment test")
upsert_design_room(
scene_id="scene_...",
name="Living room",
bounds_mm=[0, 0, 0, 6000, 4500, 2800]
)
register_scene_instance(
scene_id="scene_...",
room_id="room_...",
asset_id="gen-sofa-3-seat-1",
x_mm=3000,
y_mm=3900
)
validate_scene_layout(scene_id="scene_...")
create_generation_plan(
goal="Generate and furnish a compact house",
scope="house",
scene_id="scene_..."
)
```
The current spatial validator is an R-tree world-AABB broad phase plus room
containment. Oriented-footprint, functional-clearance, and automatic
resolution passes can build on the same persistent scene ledger.
## Development
```powershell
git clone <repo> almond-mcp
cd almond-mcp
uv run pytest # 23 tests, no Rhino required
uv run almond-mcp doctor
```
On OneDrive-synced folders set `UV_LINK_MODE=copy` (OneDrive rejects uv's
hardlinks). Licensing: `LICENSE` (MIT), `THIRD-PARTY-NOTICES.md`, and
`docs/licensing-audit.md` for what may and may not be distributed.
# Drawing pilot — 0.6.0rc2
Almond now exports traceable mesh silhouettes as scaled SVG, full-size DXF and
A3 SVG sheets. Ten generated models have bundled plan/front/right views;
other library models and custom static GLBs can be processed on demand.
Generation evidence and geometry hashes travel with the drawings, and an audit
detects changed outputs or stale source geometry. Six architectural reference
directories are searchable without DETAIL access.
See [drafting workflow and limits](docs/drafting-0.6-rc2.md) and open
[the pilot gallery](Draftingfiles/index.html). These are mesh outlines for
layout/entourage; section assemblies and hidden-line drafting remain future work.
### Compact Rhino library placement (0.6.0rc13)
The docked archive now uses small, two-column thumbnails. Drag a model into a
viewport, or choose Place and pick an insertion point. Light detail targets
20,000 triangles on heavier models; Original retains the source mesh.
Repeated objects share Rhino blocks and materials. Source records and
transformation/reduction metadata stay attached to each placed object.
The prepared candidate requires an interactive Rhino placement check before
publication; see docs/rhino-archive-quickstart.md.
TDQS
Scored across 33 tools
Each tool targets a distinct entity or action (e.g., get vs list vs place for different asset types). The only potential overlap between publish_objects_to_chestnut and publish_to_chestnut is clearly differentiated by their descriptions (detailed vs simplified). No two tools serve the same purpose.
All 33 tools follow a consistent verb_noun snake_case pattern (e.g., apply_drawing_style, create_design_scene, list_capsules). No mixing of conventions like camelCase or different verb styles.
33 tools cover a broad domain (scene creation, asset management, scripts, physics, publishing, validation). While slightly high compared to typical well-scoped servers (3-15), the number is justified by the breadth of functionality and each tool serves a clear purpose.
The surface covers core workflows: creation, retrieval, placement, execution, validation, and publishing. Minor gaps exist, such as lack of explicit delete/remove tools for objects or scenes, and no update tool for scenes. However, most lifecycle stages are present.