{"ok":true,"site":{"host":"mcp-five-puce.vercel.app","url":"https://mcp-five-puce.vercel.app/","type":"live","desc":"A floor planner where the page owns the geometry and the agent owns the intent. 28 WebMCP tools, 28 rules, and a page that refuses a layout it knows is wrong.","tools":[{"name":"get_room","kind":"answer","impl":"imperative","description":"Call this first. The whole room: size, doors, windows, outlets, every item in cm (x,y = top-left of footprint, rot clockwise, rot 0 faces south), the rules in force, the violations and the score out of 100. Also humanChanges — what the human did since your last call, as events {action, item, from, to, text}. Every tool returns those, so you always see their side. Workflow: get_room → brief → sense_room → set_profile → find_space per item → move_items → say.","title":"Read the room","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","properties":{},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"sense_room","kind":"act","impl":"imperative","description":"Whether this reads as a room someone lives in — the judgement collision rules cannot make. Returns a verdict and ranked composition problems (no focal point, one-sided balance, seats that form no group, dead corners, a bed or wardrobe stranded off its wall), plus how full it is, its focal point, daylight per window through the day, and each light fixture with its layer, colour temperature and reach. Read it BEFORE arranging and quote it back in say() — it makes advice sound like a person.","title":"How the room feels","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"find_space","kind":"answer","impl":"imperative","description":"Where a footprint fits: up to 5 positions {x,y,rot} that break no rule. NEVER invent coordinates — the page owns the geometry. Pass `id` to re-place something already here, `type` for something new, or raw `w`/`h`.\n\nEvery call is judged against the room AS IT IS NOW, so placing several pieces needs `ignore` (ids you will move anyway) and `plan` (spots already chosen), or they will overlap.\n\n`caveat` = the free spots cut a walkway. `least_bad` = nothing legal exists; set something aside.","title":"Find a spot that breaks no rule","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"type":{"type":"string","enum":["sofa","armchair","tv_unit","coffee_table","dining_table","chair","desk","bed_double","bed_single","wardrobe","bookshelf","plant","lamp","rug","counter","toilet","basin","shower","bathtub","sink","hob","fridge","blind","ceiling_light","pendant","spotlight_bar","chandelier","downlights","cove_strip","wall_sconce","track_light"]},"w":{"type":"number"},"h":{"type":"number"},"prefer":{"type":"string","enum":["wall","corner","center","near_window","near_outlet","any"]},"near":{"type":"string","description":"item id to stay close to"},"facing":{"type":"string","description":"item id the front should face (e.g. sofa facing tv)"},"id":{"type":"string","description":"an existing item you want to RE-place — its size and type are taken from it and its current position is ignored"},"ignore":{"type":"array","items":{"type":"string"},"description":"item ids to treat as not in the room, because you are about to move them too"},"plan":{"type":"array","description":"placements you have already decided but not applied yet — pass them and the page will not hand you a spot that sits on top of one","items":{"type":"object","properties":{"type":{"type":"string","enum":["sofa","armchair","tv_unit","coffee_table","dining_table","chair","desk","bed_double","bed_single","wardrobe","bookshelf","plant","lamp","rug","counter","toilet","basin","shower","bathtub","sink","hob","fridge","blind","ceiling_light","pendant","spotlight_bar","chandelier","downlights","cove_strip","wall_sconce","track_light"]},"w":{"type":"number"},"h":{"type":"number"},"x":{"type":"number"},"y":{"type":"number"},"rot":{"type":"number","enum":[0,90,180,270]}},"required":["x","y"]}}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"add_item","kind":"act","impl":"imperative","description":"Add a piece of furniture or a light fixture from the catalogue. Give x,y from find_space if you have somewhere in mind — or leave them out and the page picks a spot that breaks no rule, which is what you want most of the time. Returns the new item id. sense_room lists what each light fixture is for.","title":"Add furniture","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"type":{"type":"string","enum":["sofa","armchair","tv_unit","coffee_table","dining_table","chair","desk","bed_double","bed_single","wardrobe","bookshelf","plant","lamp","rug","counter","toilet","basin","shower","bathtub","sink","hob","fridge","blind","ceiling_light","pendant","spotlight_bar","chandelier","downlights","cove_strip","wall_sconce","track_light"]},"x":{"type":"number"},"y":{"type":"number"},"rot":{"type":"number","enum":[0,90,180,270]},"prefer":{"type":"string","enum":["wall","corner","center","near_window","near_outlet","any"],"description":"where it should look, when the page is choosing the spot"}},"required":["type"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"say","kind":"act","impl":"imperative","description":"Speak to the human ON the plan: a bubble on an item, pinned at a point (`x,y`), or a banner. Use it after every change, one sentence under 90 chars. kind: say, ok, warn, idea. `options` makes it a question with up to 3 clickable answers; their choice arrives in humanChanges. If your sentence states a measurement, pass it as `claim` — the page checks it against its own geometry and either ticks it or corrects you in public. A claim you can prove beats confident prose.","title":"Speak on the plan","annotations":{"readOnlyHint":false,"untrustedContentHint":true},"inputSchema":{"type":"object","properties":{"text":{"type":"string"},"item":{"type":"string","description":"item id to attach the bubble to"},"x":{"type":"number"},"y":{"type":"number"},"kind":{"type":"string","enum":["say","ok","warn","idea"]},"options":{"type":"array","items":{"type":"string"},"minItems":2,"maxItems":3,"description":"turns the bubble into a question with clickable answers"},"clear":{"type":"boolean","description":"remove all existing bubbles first"},"claim":{"type":"object","description":"OPTIONAL measurable claim in your sentence, which the page checks against its own geometry and marks true or corrects in front of the human","properties":{"kind":{"type":"string","enum":["distance","gap","angle","clear"],"description":"distance: centre to centre. gap: clear space between two pieces. clear: to the nearest WALL, not to a door. angle: how far b sits off a's facing."},"a":{"type":"string","description":"the item the measurement is about"},"b":{"type":"string","description":"the second item; distance, gap and angle need one"},"value":{"type":"number","description":"the number you said out loud"},"unit":{"type":"string"}},"required":["kind","a","value"]}},"required":["text"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"show","kind":"act","impl":"imperative","description":"Direct the human's attention. `highlight`: dim all but these ids while you explain a problem. `route_to`: draw and measure the walk from the door to an item. `view`: 2D for precise work, 3D for a finished layout or the lighting after dark. `eye`: SIT THEM INSIDE THE ROOM, at that seat's eye height facing the way it faces — the argument a plan cannot make. Put them in the wheelchair by the door and let them see the sofa blocking it, then show({eye:'off'}).","title":"Point the human at something","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"highlight":{"type":"array","items":{"type":"string"}},"route_to":{"type":"string"},"panel":{"type":"string","enum":["hide","show"],"description":"fold the side panel away to give the plan the whole screen, or bring it back"},"width":{"type":"number","description":"route corridor width in cm; defaults to the profile (60, or 90 for accessibility)"},"view":{"type":"string","enum":["2d","3d"]},"eye":{"type":"string","description":"item id to SIT INSIDE and look out from; switches to 3D on its own. 'off' stands back up."},"eye_height":{"type":"number","description":"cm above the floor: 120 seated in a chair, 115 in a wheelchair, 160 standing. Defaults from the piece."}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"brief","kind":"act","impl":"imperative","description":"Record WHO uses the room and WHAT they do in it — the half of the problem geometry cannot see. A desk for one and a desk for five look identical to a collision check. Once set, the page counts places, chairs and desks against real people and catches a layout that works on paper but not in life: five desks welded into a slab is a conference table, not five places to work. ASK the human, do not assume. Call it before arranging anything. No arguments reads the current brief back.","title":"Who is this room for","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"people":{"type":"number","description":"how many people use the room at once"},"activity":{"type":"string","enum":["study","work","dine","watch","sleep","talk"]},"who":{"type":"string","description":"what to call them in plain words — \"kids\", \"guests\", \"my dad\" — used in the messages the human reads"}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_profile","kind":"act","impl":"imperative","description":"Set the design goal; this switches which rules apply, and the page may give you NEW TOOLS as a result — accessibility adds a wheelchair audit tool, 90cm corridors, 150cm turning circles and socket-reach checks; theater adds viewing distance, angle and glare; bedroom adds bed clearance; office adds glare and back-to-door. Returns the new rule list and violations. Re-read your tool list after calling this.","title":"Set the design goal","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"profile":{"type":"string","enum":["general","theater","office","bedroom","accessibility"]}},"required":["profile"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"sun","kind":"act","impl":"imperative","description":"Read or set the sun. `hour` 0–23 is the time of day; `north` is the compass bearing of the wall at the top of the plan (0 = it faces north); `season` changes the sun's height and the day length. No arguments just reads. Always returns where the sun is now, which windows it enters and how strongly, how far the beam reaches across the floor, and for every screen the hours a window will shine on it. Ask \"which way do your windows face?\" rather than guessing.","title":"Sun, time of day and orientation","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"hour":{"type":"number","minimum":0,"maximum":23},"north":{"type":"number","description":"0-359; bearing of the top wall"},"season":{"type":"string","enum":["summer","spring","winter"]}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_room","kind":"act","impl":"imperative","description":"Size in cm unless you pass `units`. w and h alone RESIZE the room, keeping doors, windows, outlets and furniture (anything the smaller room cannot hold is set aside, not deleted) — use it when the human gives you their real measurements. Add doors/windows/outlets to build a NEW EMPTY room instead. `pos` is the offset along the wall from its top/left end. Openings are ALWAYS in cm whatever `units` says, so leave them out and add them after.","title":"Define or resize the room","annotations":{"readOnlyHint":false,"untrustedContentHint":true,"destructiveHint":true},"inputSchema":{"type":"object","properties":{"w":{"type":"number"},"h":{"type":"number"},"units":{"type":"string","enum":["cm","m","in","ft"],"description":"unit for w and h; default cm. If they said \"12 by 14 feet\" pass ft and 12/14 — never convert in your head."},"doors":{"type":"array","items":{"type":"object","properties":{"wall":{"type":"string","enum":["N","S","E","W"]},"pos":{"type":"number"},"width":{"type":"number"}},"required":["wall","pos"]}},"windows":{"type":"array","items":{"type":"object","properties":{"wall":{"type":"string","enum":["N","S","E","W"]},"pos":{"type":"number"},"width":{"type":"number"}},"required":["wall","pos"]}},"outlets":{"type":"array","items":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"]}}},"required":["w","h"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"define_flat","kind":"act","impl":"imperative","description":"Set up a home of several rooms — \"2BHK for four of us\" — instead of one room in isolation. Give the number of bedrooms and how many people live there; the page builds a hall, that many bedrooms, a kitchen and a bathroom at ordinary sizes, works out who sleeps where, and sets each room the goal it should be judged against. Rooms start empty for you to furnish. Add a study or a balcony with `extras`. Ask the human how many bedrooms and how many people before you call this.","title":"Lay out a whole home","annotations":{"readOnlyHint":false,"untrustedContentHint":true,"destructiveHint":true},"inputSchema":{"type":"object","properties":{"bedrooms":{"type":"number","description":"1 to 4 — the B in 2BHK"},"people":{"type":"number","description":"how many live here in total"},"extras":{"type":"array","items":{"type":"string","enum":["study","balcony"]}}},"required":["bedrooms","people"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"saves","kind":"act","impl":"imperative","description":"Named rooms kept in this browser only — nothing is uploaded. No action lists them. `save` stores the room as it stands right now under `name` (up to 12; saving over a name replaces it). `load` reopens one, replacing the current room. `delete` removes one for good. Offer to save before you rearrange anything the human might want back, and tell them the name you used.","title":"Save or reopen a room on this device","annotations":{"readOnlyHint":false,"untrustedContentHint":true,"destructiveHint":true},"inputSchema":{"type":"object","properties":{"action":{"type":"string","enum":["list","save","load","delete"]},"name":{"type":"string","description":"what to call it, up to 24 characters"}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"preset","kind":"act","impl":"imperative","description":"With no id, lists the ready-made scenes (id, title, the problem each one poses) so you can offer the human a different room. With an id, loads it, replacing the current room.","title":"List or load a demo scene","annotations":{"readOnlyHint":false,"untrustedContentHint":true,"destructiveHint":true},"inputSchema":{"type":"object","properties":{"id":{"type":"string","enum":["living-pile","studio-tight","office-glare","dad-visits","open-plan","blank"]}},"required":[]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"}],"favicon":"/favicons/mcp-five-puce.vercel.app.svg","apiSurface":"spec","category":"AI & Agents","toolCount":13}}