{"ok":true,"site":{"host":"canvasmind-design.netlify.app","url":"https://canvasmind-design.netlify.app/","type":"live","desc":"Plan a room and check whether a wheelchair user can actually reach every seat. Exposes its geometry to AI agents over WebMCP.","tools":[{"name":"get_layout","kind":"answer","impl":"imperative","description":"Return the room's name and dimensions, and every item in it with its id, type, label, exact position and size. ALL UNITS ARE CENTIMETRES, with (0,0) at the top-left corner of the room. Call this FIRST before any edit, because item ids are the only way to address furniture. The room is drawn to a bitmap canvas with no DOM, so this is the only way to know what is in it.","title":"Read the whole room","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"find_items","kind":"answer","impl":"imperative","description":"Find items by a case-insensitive substring of their label, by exact type, or both. Use this instead of get_layout when the room is busy and you only need a few items.","title":"Search the room","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"Substring of the label, or an exact item id"},"type":{"type":"string","enum":["round_table","rect_table","desk","stage","bar","pillar","wheelchair_space","door","custom"],"description":"Restrict to one furniture type"}},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"describe_selection","kind":"answer","impl":"imperative","description":"Return the item the HUMAN currently has selected, plus its four nearest neighbours and the exact gap in centimetres to each. Call this when the user says 'this table', 'that one', or 'the selected item' — it is how you resolve what they are pointing at.","title":"Read what the user selected","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"measure_gap","kind":"act","impl":"imperative","description":"Return the exact shortest distance in centimetres between two items, and whether that gap is wide enough for a wheelchair (needs 90cm). Use this to answer questions like \"can someone get between these two tables?\". Measuring a distance from rendered pixels is not something a vision model can do reliably.","title":"Measure the gap between two items","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"a":{"type":"string","description":"First item id"},"b":{"type":"string","description":"Second item id"}},"required":["a","b"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"check_accessibility","kind":"answer","impl":"imperative","description":"Run the full accessibility audit on the current layout. Checks for items outside the room, overlapping furniture, blocked door clearance zones (150cm), and — most importantly — whether every item can actually be REACHED from a doorway along a continuous 90cm wide route. Reachability is computed with a flood fill over an occupancy grid, so it catches furniture that is boxed in even when nothing overlaps. Returns ok:true when the layout passes. While it reports problems, a 'fix_accessibility' tool becomes available.","title":"Check wheelchair accessibility","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"add_item","kind":"act","impl":"imperative","description":"Place a new item in the room and return it, including its generated id. Position x,y is the TOP-LEFT corner in centimetres. Each type has sensible default dimensions (a round_table is 150x150cm and seats 8; a wheelchair_space is 90x130cm) which you can override with w and h, and a natural shape you can override with shape:'rect' or shape:'round'. Omit x and y to auto-place. A room needs at least one 'door' item on a wall or nothing can be reached.","title":"Place furniture","inputSchema":{"type":"object","properties":{"type":{"type":"string","enum":["round_table","rect_table","desk","stage","bar","pillar","wheelchair_space","door","custom"],"description":"Furniture type"},"label":{"type":"string","description":"Short name, e.g. 'Table 7' or 'Fire exit'"},"x":{"type":"number","description":"Left edge in cm from the room's left wall"},"y":{"type":"number","description":"Top edge in cm from the room's top wall"},"w":{"type":"number","description":"Override width in cm"},"h":{"type":"number","description":"Override depth in cm"},"seats":{"type":"integer","description":"Override seat count"},"shape":{"type":"string","enum":["rect","round"],"description":"Override the outline. Defaults to the type's natural shape."}},"required":["type","label"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"move_item","kind":"act","impl":"imperative","description":"Move an item so its top-left corner sits at an exact centimetre position. This is precision a vision model cannot achieve from a screenshot.","title":"Move furniture","inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"Item id from get_layout, e.g. 'i3'"},"x":{"type":"number","description":"New left edge in cm"},"y":{"type":"number","description":"New top edge in cm"}},"required":["id","x","y"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"resize_item","kind":"act","impl":"imperative","description":"Set an item's width and depth in centimetres. Minimum 20cm; the item is kept inside the room. Use this to model real furniture the user owns — a 220cm banquet table, a 60cm-deep bar. Resizing changes clearances, so re-run check_accessibility afterwards.","title":"Resize furniture","inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"Item id from get_layout"},"w":{"type":"number","minimum":20,"description":"New width in cm"},"h":{"type":"number","minimum":20,"description":"New depth in cm"}},"required":["id"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"rotate_item","kind":"act","impl":"imperative","description":"Rotate an item by 90 degrees, swapping its width and depth. Position is unchanged.","title":"Rotate furniture 90 degrees","inputSchema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_item_props","kind":"act","impl":"imperative","description":"Change an item's label and/or its seat count. Position and size are unchanged.","title":"Rename or reseat an item","inputSchema":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string","description":"New label"},"seats":{"type":"integer","minimum":0,"description":"New seat count"}},"required":["id"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"remove_item","kind":"act","impl":"imperative","description":"Take an item out of the room permanently, along with the seats it provided. Not undoable, so confirm with the user before removing anything they placed.","title":"Remove furniture","inputSchema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"align_items","kind":"act","impl":"imperative","description":"Align two or more items to their shared average on one axis. axis:'x' lines them up in a vertical column; axis:'y' lines them up in a horizontal row.","title":"Align furniture","inputSchema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string"},"minItems":2,"description":"Item ids to align"},"axis":{"type":"string","enum":["x","y"],"description":"'x' = same left edge, 'y' = same top edge"}},"required":["ids","axis"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"auto_arrange","kind":"act","impl":"imperative","description":"Push all furniture apart until every gap meets the wheelchair route width and every door clearance zone is clear, keeping everything inside the room. Animates over a few seconds and honours cancellation. Use this when the user says 'fix the spacing', 'make this accessible', 'tidy up' or 'rearrange'. Returns whether the layout is compliant afterwards.","title":"Rearrange the room for accessibility","inputSchema":{"type":"object","properties":{"minGap":{"type":"number","minimum":60,"maximum":300,"description":"Required clear gap in cm (default 90)"},"iterations":{"type":"integer","minimum":40,"maximum":600,"description":"Simulation steps (default 200)"}},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"show_accessible_route","kind":"act","impl":"imperative","description":"Toggle the visual overlay on the canvas. Green shows floor a wheelchair can actually reach from a doorway; red shows floor that is wide enough but cut off. Turn this on when explaining an accessibility problem to the user so they can see what you are describing.","title":"Show or hide the reachability overlay","inputSchema":{"type":"object","properties":{"show":{"type":"boolean","description":"true to show, false to hide, omit to toggle"}},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_room","kind":"act","impl":"imperative","description":"Set the room's name and/or its interior dimensions in centimetres. The canvas is drawn at 1 pixel per centimetre, so a 1200x700 room is 12m x 7m. Every field is optional — pass only what you want to change.","title":"Name or resize the room","inputSchema":{"type":"object","properties":{"name":{"type":"string","description":"What this room is called, e.g. 'Banquet Hall'"},"width":{"type":"number","minimum":300,"maximum":2400,"description":"Interior width in cm"},"height":{"type":"number","minimum":300,"maximum":1400,"description":"Interior depth in cm"}},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"export_image","kind":"act","impl":"imperative","description":"Download the current floor plan as an image file, with the room name and the accessibility verdict stamped underneath it — so the exported file is a shareable record, not just a screenshot. Use this when the user says they want to save, download, export or send the plan.","title":"Download the plan as an image","inputSchema":{"type":"object","properties":{"format":{"type":"string","enum":["png","jpeg"],"description":"Image format (default png)"}},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"clear_room","kind":"act","impl":"imperative","description":"Remove every item including doors. Not undoable — confirm with the user first.","title":"Empty the room","inputSchema":{"type":"object","properties":{},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"fix_accessibility","kind":"act","impl":"imperative","description":"Available ONLY while check_accessibility reports problems. Pulls furniture back inside the room, clears door zones, and separates items until every route meets the wheelchair width. Returns what it changed and whether the layout now passes.","title":"Repair the layout","inputSchema":{"type":"object","properties":{"strategy":{"type":"string","enum":["separate","clear_doors","both"],"description":"What to repair (default 'both')"}},"required":[],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"}],"favicon":"/favicons/canvasmind-design.netlify.app.ico","apiSurface":"spec","category":"Developer Tools","toolCount":18}}