
kplrfurniture/polyboard-mcp
Developer toolsAn MCP server that turns planner output (floor plan image, per-wall elevation images, renders, and a product/spec feed) into a Polyboard-ready build.
Обзор
An MCP server that turns planner output (floor plan image, per-wall elevation images, renders, and a product/spec feed) into a Polyboard-ready build. Polyboard (the cabinet/furniture CAD tool from Boole) . Its only documented automation surfaces are: - DXF import, for room/free-shape outlines only — not cabinets, hardware, or fittings. - DXF/WoodWop/Xilog/BiesseWorks export, for CNC machines, once a project already exists inside Polyboard. So there are two real paths to get a planner image turned into something in Polyboard, and this server supports both: 1. — generates a DXF of the room's wall outline for you to import into Polyboard's room/free-shape tool. Fast, but geometry-only: no cabinets, fittings, doors, drawers, or assembly rules. Good for getting the room shape in quickly; not "manufacturing ready" on its own. 2.
README
polyboard-mcp
An MCP server that turns planner output (floor plan image, per-wall elevation images, renders, and a product/spec feed) into a Polyboard-ready build.
Why this is shaped the way it is
Polyboard (the cabinet/furniture CAD tool from Boole) has no public API or scripting interface. Its only documented automation surfaces are:
- DXF import, for room/free-shape outlines only — not cabinets, hardware, or fittings.
- DXF/WoodWop/Xilog/BiesseWorks export, for CNC machines, once a project already exists inside Polyboard.
So there are two real paths to get a planner image turned into something in Polyboard, and this server supports both:
export_dxf— generates a DXF of the room’s wall outline for you to import into Polyboard’s room/free-shape tool. Fast, but geometry-only: no cabinets, fittings, doors, drawers, or assembly rules. Good for getting the room shape in quickly; not “manufacturing ready” on its own.generate_build_plan— generates an ordered, fully parameterized list of steps (create project → add each wall → close the room shape → add one Box Cabinet per spec section, placed side by side on its wall → configure each cabinet’s doors/drawers/shelves/fittings → generate cutting list and per-part DXF/CNC output) for a computer-use agent to execute directly against your local Polyboard install. Polyboard’s own “New Cabinet” dialog only builds one free-standing Box Cabinet at a time (Width/Height/Depth plus a Panels tree), it has no “run” or “section” concept — so a speccabinetRunwith N sections becomes N separate Box Cabinets positioned side by side. This is the only path that can apply Polyboard’s own fitting, assembly, and construction rules, since there’s no API to call instead. It intentionally does not hardcode screen coordinates — a computer-use agent reads the actual screen at each step and should check the step’sverifyfield before moving on.
Vision (reading the floor plan / elevation / render images, and whatever the
planner’s product API returns) is not done inside this server. The MCP
client (e.g. Claude, already looking at the images) extracts a RoomSpec
JSON object and passes it to these tools. Call get_room_spec_schema first
to get the exact shape expected.
RoomSpec
{
"roomName": "Kitchen - Unit 12",
"units": "mm",
"walls": [
{ "id": "W1", "name": "Wall A", "lengthMm": 3600, "heightMm": 2400, "start": [0, 0], "end": [3600, 0] }
],
"cabinetRuns": [
{
"id": "R1", "wallId": "W1", "type": "base",
"startOffsetMm": 0, "lengthMm": 1800, "heightMm": 850, "depthMm": 600,
"sections": [
{ "id": "R1S1", "widthMm": 900, "doors": 2, "shelves": 1, "fittingRefs": ["HNG-110"] }
]
}
],
"products": [
{ "sku": "HNG-110", "name": "110 degree concealed hinge", "qty": 4 }
]
}
See tests/fixtures/sample_room_spec.json for a complete example and
src/schema.ts for full validation rules (wall names should match the names
on the floor plan image, so a human or computer-use agent can cross-check).
Using a Polyboard cabinet library (e.g. a Keplerwood-style kitchen catalogue)
If the user maintains a library of pre-built cabinet models inside Polyboard’s
own library system (Libraries menu), each matching one exact SKU from a
product catalogue, set sections[].librarySku to that model’s exact name
(e.g. "KBUHD72-2DO-W900") instead of (or in addition to) doors/drawers/
shelves/fittingRefs. generate_build_plan then emits an
insert_library_cabinet step (search the library for that name, drag it onto
the wall) instead of building a generic Box Cabinet from scratch - the
library model already encodes the correct carcass, fronts, and fittings for
that SKU. Pick the SKU by reading the user’s own product catalogues (SKU
structure is typically --W, e.g.
KBUHD72 = kitchen base unit, handle type, 720mm height; 2DO = 2 doors with
hinges; see the catalogue PDFs for the full code grammar, unit categories -
base/wall/high/tall/island - and positioning rules such as wall-unit start
height, fillers, and the sink/cooktop clearance rule). The exact Libraries
menu path for inserting a saved model by name has not been confirmed against
a real Polyboard session yet - insert_library_cabinet’s step text asks the
computer-use agent to find it and report back if it doesn’t match.
Tools
| Tool | Purpose |
|---|---|
get_room_spec_schema |
Returns the RoomSpec JSON schema. Call first. |
ingest_room_spec |
Validates a RoomSpec; reports errors and cross-reference warnings (overlapping/overshooting runs, unknown wall or product references). |
export_dxf |
Writes a DXF of the wall outline to disk. |
generate_build_plan |
Returns the ordered step list for a computer-use agent. |
Setup
npm install
npm run build
Then point an MCP client at node dist/server.js (stdio transport). For
Claude Desktop / Claude Code, add it as an MCP server pointing at that
command, running on the same machine where Polyboard is installed if you
intend to use generate_build_plan with a computer-use agent.
Development
npm run dev # run the server directly from TypeScript source
npm test # unit tests (schema validation, DXF output, build plan ordering)
Tests cover ingest_room_spec’s validation/warnings, export_dxf’s DXF
output, and generate_build_plan’s step ordering — all without needing
Polyboard installed. There is currently no automated test against real
Polyboard, since that requires a Windows machine with Polyboard installed
and a computer-use agent driving the screen.
Driving generate_build_plan with a computer-use agent
tools/astra_build_runner.py is a standalone local driver that executes
generate_build_plan’s JSON step list against a real Polyboard install,
using OpenAI’s native computer-use API (model gpt-6.1-sol, tool computer).
An earlier version of this script targeted model gpt-6-astra with tool
type computer_use_preview. A real run against that combination came back
400 Tool 'computer_use_preview' is not supported with gpt-6-astra —
gpt-6-astra’s documented automation path is code execution (exec_py/
exec_js function tools), not the screenshot/click loop this script uses.
gpt-6.1-sol is the model OpenAI documents for the native computer tool —
the direct successor of the old computer_use_preview flow (same
screenshot-in/computer_call-out loop), except the tool definition is just
{"type": "computer"} (no display_width/display_height/environment),
and a computer_call now carries a plural actions array instead of a
single action. The script handles both call shapes. Swap the MODEL
constant and the tool type in astra_build_runner.py if you’d rather
drive this with Claude’s computer-use API, or rewrite it around
exec_py/exec_js if you specifically want gpt-6-astra’s code-execution
path instead.
This script has been smoke-tested with --dry-run (which never calls the
API) but not yet against a real OpenAI computer-use session against a real
Polyboard install — the previous real attempt is what surfaced the
model/tool mismatch above, now fixed. Run --dry-run first, and watch the
first few real steps closely.
cd tools
python astra_build_runner.py --check-env # see what's missing - works before any pip install
pip install -r requirements.txt
set OPENAI_API_KEY=sk-... # Windows cmd; use $env:OPENAI_API_KEY= in PowerShell
python astra_build_runner.py path\to\build_plan.json --dry-run # review instructions, no API/screen calls
python astra_build_runner.py path\to\build_plan.json # drives the real screen
python astra_build_runner.py path\to\build_plan.json --start-step 5 # resume after stopping
--check-env and --dry-run need nothing installed — no pip packages, no
API key, no display access — so they’re the safe first things to run.
It runs one step at a time. After the model reports a step done, it prints
that step’s verify text. Steps marked confirm: false (creating the
project, building the room, creating the model, double-clicking the model)
continue immediately — the agent still has to match verify on screen, but
you are not asked. Naming the project, placing a cabinet on a wall, and
adding shelves, doors, or drawers still wait for y/N/q, because those
missed on a live run. Progress is saved next to the plan file
(.progress.json) so a stopped run can resume with --start-step.
Safety checks OpenAI’s API flags mid-action pause for an explicit y/N in the
terminal before continuing.
tools/test_astra_build_runner.py covers the pure logic (plan loading,
instruction formatting, safety-check ID extraction, resume slicing) with no
OpenAI or pyautogui dependency — run with python -m unittest from tools/.
Known open items
- The planner’s product/spec API (mentioned as providing per-product specs
for the room) isn’t integrated directly — the client LLM is expected to
read it and fold the results into
RoomSpec.products. If you want this server to call that API itself, it needs the API’s base URL, auth method, and a sample response. - Confirmed against a real Polyboard 7.10p session: wall creation, the New
Cabinet dialog, cabinet renaming via a double-click in Properties, and the
doors/drawers/shelves workflow (double-click the placed cabinet to open its
Model tab, select the interior zone, right-click that zone for Add
Shelves/Add Door/Add Drawers).
File > New Projecthas no name field; the name is applied bysave_project(File > Save As) at the end of the plan. Those working steps are markedconfirm: false, so the runner does not stop to ask. Placing a cabinet still asks: drag from the Model list (a drag inside the plan moves the camera; check Top View), and if the drop misses use right-click > Move selection or Properties > Cabinet positioning. - Not yet confirmed: the exact Libraries menu path and search UI for
inserting a saved cabinet-library model by name (
insert_library_cabinetstep, used when a section setslibrarySku). The first real run against this step should report back whatever the Libraries menu actually looks like so the step text can be corrected. tools/astra_build_runner.py’s OpenAI computer-use wire format (exact action field names for click/drag/scroll/keypress) is taken from OpenAI’s docs, not confirmed against a live API call — verify against current OpenAI docs if the first real run errors on an unrecognized action shape.
Установка
This server does not publish a one-line install command.
Open the repository installation guide