Developers
The workbench is also an MCP server. Connect your own agent and it builds with real parts inside one of your builds, where you can watch, edit and build the result.
TipStart from Connect an agent in the workbench. OAuth is recommended; legacy keys remain available for clients that need them.
Nothing on this page matches that.
Overview#
The Model Context Protocol lets an AI agent use tools from outside its own app. Nooks offers the workbench's construction tools this way: your agent does the thinking, and Nooks turns what it asks for into real parts, checks how they connect and whether the model holds together and stands, and saves every build as a revision.
- Your agent, your model. Nooks makes no model calls of its own for your agent; it supplies tools.
- Real parts only. Everything is built from parts the workbench draws, by their LDraw numbers and real colours.
- You stay in the loop. Each revision appears in the workbench and its history. You can edit it by hand, and the agent builds on your edits.
Quick start#
- Sign in. Building needs a free account.
- Open Connect an agent in the workbench, and start a build for your agent (or pick one of yours).
- Add the Nooks MCP address to your client. A compatible client opens Nooks sign-in and consent. Choose the builds it may use and whether it may edit them.
- Verify the connection. Ask the client to call
list_buildsorread_project. A chat instruction alone cannot install a connection in every app. - Ask your agent to build. For example: "Read the Nooks project and its runtime guide, then build a small red tower on a 4×4 base, part by part, and check it."
Endpoint and authorization#
| Address | https://nooks.place/api/mcp |
| Transport | Streamable HTTP. Stateless: each POST is one JSON-RPC exchange, answered as JSON. |
| Auth | OAuth authorization code with PKCE for compatible clients. Nooks opens sign-in and consent, then issues a short-lived resource-bound token. Legacy Bearer keys remain available for clients without OAuth. |
| Account keys | A key from Agents in your account menu (nooks_acc_…) works across your builds: your agent lists them with list_builds and picks one with open_build (or starts one with create_build). A client that keeps no MCP session names the build with ?build=<id> on the address, or a Nooks-Build header. A read-only key is offered only the tools that change nothing. |
OAuth is the recommended path. The consent screen identifies the client, shows the requested read or edit access and lets you restrict it to selected builds. Inspect or revoke connected clients from your account; revoked access stops on the next call, including an active MCP session. Legacy keys coexist with OAuth: a build key opens one build, while an account key can cover selected builds and be read-only.
Connect a client#
For an OAuth-capable remote MCP client, add https://nooks.place/api/mcp. The client discovers Nooks authorization, opens sign-in and consent, and returns after approval. Do not treat setup as successful until the client calls a Nooks tool. Client support varies; some apps still require the manual key setup below.
One page for every client has the command, the config file and the sign-in step for Claude Code, Codex, Cursor, OpenClaw, Hermes and Grok Build, with the 13-tool core and the full profile side by side.
Codex OAuth#
codex mcp add nooks --url https://nooks.place/api/mcp
codex mcp login nooksComplete Nooks sign-in and consent in the browser, then verify the server in Codex. The login flow has been tested; a model-driven Codex tool call has not.
Legacy key fallback#
If the client cannot authorize a remote MCP server, choose My client requires a key in Connect an agent and put the resulting key where nooks_agt_… appears below. Keep it out of URLs, source files and logs.
Claude Code#
claude mcp add --transport http --scope user nooks https://nooks.place/api/mcp \
--header "Authorization: Bearer nooks_agt_…"Then start Claude Code and check that /mcp lists nooks. --scope user makes it available in every folder; leave it out for this folder only.
Codex#
# ~/.codex/config.toml
[mcp_servers.nooks]
url = "https://nooks.place/api/mcp"
bearer_token_env_var = "NOOKS_AGENT_KEY"
# then, in the shell you start Codex from:
export NOOKS_AGENT_KEY=nooks_agt_…Codex reads the key from the environment variable, so it stays out of the config file. In PowerShell: $env:NOOKS_AGENT_KEY="…". Check with /mcp in Codex.
Claude Desktop#
{
"mcpServers": {
"nooks": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://nooks.place/api/mcp",
"--header",
"Authorization:${NOOKS_AUTH}"
],
"env": {
"NOOKS_AUTH": "Bearer nooks_agt_…"
}
}
}
}Settings › Developer › Edit config, add this and restart. It bridges through mcp-remote, which needs Node.js.
Other clients#
{
"mcpServers": {
"nooks": {
"url": "https://nooks.place/api/mcp",
"headers": {
"Authorization": "Bearer nooks_agt_…"
}
}
}
}Any client that speaks MCP over Streamable HTTP and can send a header needs only the address and the Authorization header.
Build programs#
An agent builds the way a person does: part by part, each placed by its connectors (this stud into that hole, this pin into that beam), so hinges, clips, Technic and minifigures join exactly. It writes the steps as a build program: plain JSON, never code, kept with the revision so it can be read, replayed and edited.
{
"name": "bridge",
"ops": [
{
"op": "add",
"name": "left",
"part": "brick 1x1",
"color": "tan"
},
{
"op": "add",
"name": "right",
"part": "brick 1x1",
"pose": [
{
"at": [
2,
0,
0
]
}
],
"color": "tan"
},
{
"op": "attach",
"name": "span",
"part": "plate 1x3",
"to": "left.stud[0]",
"by": [
"hole",
0
],
"color": "red"
},
{
"op": "contact",
"a": "span.hole[2]",
"b": "right.stud[0]"
}
]
}The ops: add and attach (with yaw, flip, slide, align and orient), define…end for a sub-build placed many times, mirror, contact for a join the check must also find, and base to start from a saved revision. runtime_guide has them all, with worked examples.
Every part your agent can find, describe and place is sold loose, in the colours it is sold in, so whatever it builds can be ordered as a kit. A part or colour that is not is refused, with the closest one that is. Hoses and strings are switched off for now. export_python gives any build as a standalone Python script for the open-source construction library the runtime follows, which builds the same parts at the same poses.
A typical loop:
- Find parts with
find_parts, and what joins a connector withparts_that_fit. - See where to build next with
program_connectors: each connector of a placement, free or joined. - Check with
check_program: every join, collision and stability problem, and an inventory if you give one, each naming its parts. - Look with
viewfrom several sides. - Save with
build_program, then change it withedit_program.
An agent can also save a model it placed part by part (save_parts) or an LDraw file (import_ldraw).
Code. Instead of a list of ops, your agent can write Python with run_code: loops, variables, arithmetic and parts it can ask where their connectors are. The code runs in a sandbox of its own, a small virtual machine with no network and none of our data, for at most 30 seconds. What it builds is checked like any program and saved with the code, so you can read how a build was made and your agent can run it again.
Live sessions. Each connection also has a live model. Your agent builds it up a step at a time (session_ops, or code cells that remember their variables), asks it anything (session_query: its size, parts, joins, free connectors, a full check, a picture), takes steps back, and saves it as a revision only when it is right. It is kept if the connection drops. If you edit the build in the workbench meanwhile, your agent is told and puts its work on top of yours.
Checks. Joins, collisions and the two-second gravity test for agents run on the physics engine the open-source library uses, in a sandbox; the workbench's own Test gravity runs another engine in your browser on the same part shapes and the same rule. They agree on the builds we test, though a build right at the edge can pass one and not the other; every result says which engine gave it. The report names the rule, the elements it is about and the op, code line or step that placed them.
How to read a report#
A check returns a report, not just a pass or a fail. Every finding names its level and its rule, then the fact it found; the lines under it say where and which parts or discs:
error[overlap]: the bodies of 2 parts share positive volume
--> x 2..4 y 0..2 z 3..4 (1.2 .. 1.6 mm)
= #3 3001 Brick 2 x 4, Red op 14 "roof-3"
= #7 3020 Plate 2 x 4, White op 9 "base-2"
warn[unstable-component]: 1 group of 3 parts tips toward -y
--> x 0..6 y 2..8 z 12..18 (4.8 .. 7.2 mm)
= #11 3005 Brick 1 x 1, Tan op 21 "finial"
checked 42 parts against 12 rules (piece-budget, size-bounds, palette ignored): 1 error, 1 warning- The heading is
level[rule].errorfails the build,warnis reported without failing it, andignoreis off until a request turns it on.okis true only when no error remains. - The region after
-->is an axis-aligned box in model units: LDU for bricks (with its height in millimetres), millimetres for Brain Flakes. - Each
=line is one element the caller already knows: a part key or connector address, or a disc and slot. Its source follows where there is one:op 14 "roof-3",line 12,step 4or a revision id. - The closing line counts what was checked, names the ignored rules, and reports errors and warnings. It counts omitted findings too, and names any deferred rule and why, so a truncated or partial report never reads as a pass.
Rules are configured, never passes: a request can raise or lower a rule's level, or enable one whose default is ignore. The rule reference lists every rule, its default level and the pass that checks it.
Revisions and conflicts#
Every build is saved as a new revision on top of the one before. Pass the build's currentRevision from read_project as baseRevision when you build.
A 409 means someone saved in between, often you, editing by hand in the workbench: read again and build on the latest. An agent replaces a hand edit only if it passes replaceHumanEdit: true, which it should do only when you have said so.
Tools#
Start here#
| Tool | What it does |
|---|---|
read_project | The build, its revision history (who made each and why), and one revision: its build program, size, colours and whether it holds together. |
runtime_guide | How build programs work: units and axes, connectors and how they pair, and every op with worked examples. Read it first. |
explain_rule | What a rule named in a check report means, for bricks and Brain Flakes: its name, default level, the check that runs it and the condition in plain words. |
Your builds (account keys)#
| Tool | What it does |
|---|---|
list_builds | The builds of yours this key may open, newest change first. |
open_build | Work on one of them: every later call on the connection reads, checks and saves it. Switch any time. |
create_build | Start a new, empty build in your account (only a key that can edit all your builds). |
remix_kit | Start a build from a shared kit (its nooks.place/kit link or id), credited to its maker (only a key that can edit all your builds). |
delete_build | Delete the build this connection works on, with its revisions, sources, keys and shared kits; the build name must be typed back. Permanent. |
delete_kit | Take a kit this build shared down from its public page and player, with the kit title typed back; the build stays. |
kit_parts | Open a parts page for a public kit, including a wanted list and links to individual parts. |
list_kits | List the public Nooks demo kits and BrickBench builds, with their title, parts, maker and system. |
read_kit | Read an existing kit’s build as LDraw text, with its title, parts count and maker. |
What a build starts from#
| Tool | What it does |
|---|---|
record_source | Keep the person’s own words and photo privately with the build; the photo appears with the kit only when the person shares it. |
Estimated inventories#
| Tool | What it does |
|---|---|
start_inventory_scan | Start a loose-brick photo scan; for a set box, search the catalog by name or number. |
submit_inventory_photo | Submit one photo for an inventory estimate. The external service may retain and reuse it. The result is an AI inference, not verified physical inventory. |
inventory_scan_status | Read scan status and inferred candidates; they are not verified physical inventory. |
lookup_inventory_sets | Find set matches by name or number in the local catalog. |
choose_inventory_set | Choose a set catalog candidate for the build. Its inventory assumes the set is complete. |
inspect_set_inventory | Inspect a candidate’s catalog list, assuming the set is complete. |
list_inventories | List estimates and catalog inventories for this build. |
select_inventory | Use an inventory for checks and builds, or clear the selection. Physical availability is not verified. |
3D models#
| Tool | What it does |
|---|---|
import_3d | A 3D model (.glb, .obj, .stl) by link or as data: its size and pictures from three sides to build against, or filled with bricks as a starting revision. |
export_3d | A saved revision as an STL (for printing), OBJ or GLB (with colours): a download link that works for half an hour. |
A real place#
| Tool | What it does |
|---|---|
read_place | A square of the real world from OpenStreetMap at the scale you ask: the ground stud by stud, and each building's footprint, height in plates, colours and roof, for the agent to build. |
Parts and connectors#
| Tool | What it does |
|---|---|
find_parts | Search every part the workbench draws by words ("brick 2x4", "hinge plate") for LDraw numbers and names. |
describe_part | A part's connectors by address (stud[0], hole[3], pin[1]…) with position, axis and bounds. |
parts_that_fit | The parts with a connector that joins a given one (a stud, a pin hole, a clip), with which of their connectors fit, the most used parts first. |
program_connectors | Where a placement's connectors are in the model, and which are free or joined (and to what), so the agent knows where it can build next. Reaches parts inside sub-builds as copy/inner. |
minifigure | A whole minifigure from real figure parts, dressed and posed, as program ops or LDraw lines. |
brainflakes_technique | Tested Brain Flakes construction techniques (beam, post, panel, arc, block, sculpt, ring) returned as ready definitions to place with instance. |
brainflakes_catalog | Brain Flakes disc specifications, slot frames, legal mating poses, confirmed manufacturer colours, standard set inventories, and benchmark tasks. |
inspect_brainflakes | Inspect Brain Flakes disc poses, connector locations and optional symmetry of centers, normals and colours. |
Build programs#
| Tool | What it does |
|---|---|
check_program | Run a program and check it without saving: joins, collisions and the gravity test (in a sandbox, on the open-source library’s physics engine), and an inventory if you give one. |
simulate_program | Two seconds of gravity with each connected group rigid, reporting how far anything moves. |
build_program | Run, check and save a program as a new revision, kept so it can be edited. |
edit_program | Replace, insert, remove or append ops in the latest program and build it. |
run_code | Build with Python instead of a list of ops: loops, variables and live parts, run in a sandbox of its own with no network. What it builds is checked like any program, and saved with the code so it can be read and run again. |
Live sessions#
| Tool | What it does |
|---|---|
session_ops | Add steps to a live model the agent builds up call by call, kept between calls and across reconnects, saved only when it says so. |
session_query | Ask the live model anything without changing it: its size, its parts, every join, a placement's free connectors, a full check, or a render. |
session_status | Where the live model stands: what it builds on, and whether the person has saved a newer version since. |
session_undo | Take back the last change to the live model, or several. |
session_save | Save the live model as a new version, checked like any build. |
session_rebase | Put the live model on top of the person's newer version, their parts kept where they left them. |
session_reset | Start the live model again, empty. Nothing saved is touched. |
Looking and checking#
| Tool | What it does |
|---|---|
view | A real render of a program or a saved revision, from any angle. |
render_preview | A quick blockout PNG of each part's bounding box, for shape and colour layout. |
check_model | The build checker: one connected assembly, no part inside another, stands up, stock parts only, plus any limits you set (pieces, size, colours, inventory). |
Saving and history#
| Tool | What it does |
|---|---|
save_parts | Save a model placed part by part (part number, colour, position in studs and plates). |
import_ldraw | Save an LDraw .ldr or .mpd file as a new revision; sub-models and steps carry over. |
finalize_model | Check, simulate, render and export one explicit saved revision. Returns its revision and model hash; missing evidence never passes. |
check_instructions | Check a revision’s manual and report its issues. |
edit_instructions | Save manual edits as a revision while preserving the construction parts. |
plan_instructions | Plan or repair the building instructions. |
read_instructions | Read manual steps, views, callouts and page settings. |
render_instructions | Preview up to four manual pages. |
try_instructions | Try manual edits without saving. |
export_kit | Export a saved revision: manual steps, parts CSV, BrickLink wanted list and the link to buy parts directly from sellers. Preview and print the illustrated manual in the workbench. |
export_ldraw | Any revision as an LDraw .mpd file, with its manual's steps. |
export_python | Any revision as a standalone Python script for the open-source construction library the runtime follows: run it to build the same parts at the same poses. |
restore_revision | Make an earlier revision the latest again. Nothing in the history is removed. |
share_kit | When the person asks for a share or a link, publish the kit free in the community gallery and return its public link and a Post on X link. |
Box art#
| Tool | What it does |
|---|---|
prepare_box_art | For a saved brick revision, the exact product render and the front-art prompt to give an image provider, with print guidance. It does not generate the art itself. |
save_box_art | Attach provider-generated 3:2 front artwork to a saved brick revision; a shared kit’s player then offers a Box view. |
Briefs#
| Tool | What it does |
|---|---|
list_briefs | Briefs to build against: a prompt (some with a picture), the setting (Model, Set or Alt-Build), the questions a person reviews a build with, and constraints the checker tests. People build the same briefs, so builds can be compared. |
start_brief | Link this build to a brief, so it counts as an agent build of it, next to the builds people made. Returns the brief and its rubric: the setting and question graph. |
evaluate_brainflakes_benchmark | Score a Brain Flakes build program against one of the standard Brain Flakes benchmark tasks (flower, ball, tower, animal, or jar-500 starburst). |
Community#
| Tool | What it does |
|---|---|
list_contributions | Published community models and tasks, newest first. |
read_contribution | One published contribution: its description, a task's constraints, or a model's program and checks. |
evaluate_task | Run a published task's software checks on your build and answer valid (no error-level rule failed), with the task's setting and question graph. _meta.usage sums the run's reported tokens and prices them from a published table, or says unknown; it submits nothing. |
Rule reference#
Every rule a check can report, generated from the rule tables the checks use (lib/rules/bricks.mjs, lib/rules/instructions.mjs and lib/rules/brainflakes.mjs). A rule is one kind of fact: a kebab-case name, a default level, the pass that checks it and the condition in plain words. People and agents configure rules, never passes.
Levels are error (the build fails), warn (reported, does not fail) and ignore (off unless a constraint or an explicit level turns it on). The default is what applies when a request says nothing; a constraint such as maxPieces runs its rule at error.
Bricks#
12 rules. Parts, connections, collisions, stability, inventory and the catalogue. Regions are in LDU, with the height also in millimetres.
| Rule | Default level | Pass | What it means |
|---|---|---|---|
overlap | error | collision | Two parts' bodies share positive volume; touching faces do not count. |
missing-connection | error | connectivity | A join the build requires has connectors that do not meet, so the parts are not held together there. |
floating-part | error | connectivity | No chain of stud connections reaches the desk, or reaches a part that reaches it. |
unstable-component | warn | stability | A group's centre of mass leaves the hull of what holds it up, or the group moves under gravity. |
inventory-exceeded | error | inventory | A part or colour count is greater than the count in the inventory given. |
unsold-part | error | catalogue | A part or colour is not sold loose; minifigure pieces are excepted. |
stock-part | error | catalogue | A designed part that is not a stock element is present while stockPartsOnly applies. |
piece-budget | ignore | size | The part count lies outside minPieces..maxPieces. |
size-bounds | ignore | size | The model's bounding box exceeds maxDimensionsMm. |
palette | ignore | palette | A part colour is outside allowedColours. |
part-unplaceable | error | catalogue | Geometry or connector data is missing, so no verdict is possible. |
physics-incomplete | error | stability | The engine could not run, or it ran past its bound. |
Instructions#
8 rules. Findings about a saved revision's printed manual; the source is the step.
| Rule | Default level | Pass | What it means |
|---|---|---|---|
instructions-size | warn | instructions | Steps are neither too big nor too small, and there are about as many as a real manual of that size has. |
instructions-hidden | warn | instructions | A part added in a step is hidden in that step's picture, by the step's other parts or by what is already built. |
instructions-repeats | warn | instructions | A sub-assembly built more than once is not shown once, marked ×N. |
instructions-camera | warn | instructions | The camera does not stay put, or the turn icon is missing wherever the view turns. |
instructions-bom | warn | instructions | A part is not in exactly one step and in the parts list, or the parts list page is missing. |
instructions-buildable | warn | instructions | A step does not build on the steps before it: a part comes before what holds it, or is left in the air. |
instructions-insertion-blocked | warn | instructions | A part's straight-line insertion path is blocked by a part built before it, or the insertion check could not complete. |
instructions-approach-closed | warn | instructions | A part has no open way in at all, because what is built closes every approach. A part that can come in along another open, held way than its natural one is not reported: the natural way is a preference, not a rule. The current checker reports this placement as the instructions-insertion-blocked rule (rule "blocked"); this rule is retained for older reports. |
Brain Flakes#
14 rules. Discs, slots, colours and the tasks’ limits. Regions are in millimetres, and elements are disc and slot ids.
| Rule | Default level | Pass | What it means |
|---|---|---|---|
unintended-overlap | error | collision | Two discs intersect and the pair is not a designed press-fit. |
inexact-connection | error | connectivity | A connection's slots do not line up. |
floating-disc | warn | connectivity | A disc is not joined to anything and does not rest on the floor or on another disc. |
invalid-op | error | program | An op cannot be applied; source.op names it. |
palette-unknown | error | palette | A colour is outside the confirmed catalogue. |
palette-disallowed | ignore | palette | A colour is outside the task's allowed list. |
symmetry-unmatched | ignore | symmetry | A requested reflection has no counterpart. |
disc-budget | ignore | size | The disc count lies outside minDiscs..maxDiscs. |
loop-minimum | ignore | topology | There are fewer closed loops than required. |
size-bounds | ignore | size | The bounding box exceeds the task's. |
reach-minimum | ignore | size | The largest span is under the task's minimum. |
set-mix-exceeded | ignore | inventory | A colour needs more discs than the chosen set has. |
support-unsupported | warn | support | The static support estimate cannot hold a component. |
mesh-incomplete | error | mesh | The mesh check could not complete; it is never a pass. |
Limits and safety#
- Sharing is yours. When you ask, an agent can publish your kit in the public gallery and give you a link. Agents cannot order parts.
- Other people's text is data. Community titles and descriptions are written by contributors; the server tells agents never to follow instructions in them.
- Wrong keys are refused. A key is checked before any tool runs, and an address that keeps sending wrong keys is turned away for a while (
429, withRetry-After).