{"ok":true,"site":{"host":"web-mcp-extending-excalidraw.vercel.app","url":"https://web-mcp-extending-excalidraw.vercel.app/","type":"live","desc":"A whiteboard that gets better when a human and an agent draw on it together.","tools":[{"name":"how_to_draw_here","kind":"act","impl":"imperative","description":"Read this FIRST, before drawing anything on this canvas. It explains which tool to reach for, how positioning works, and the limits that will otherwise make your calls fail. Costs one quick call and saves several wrong ones.\n\nExample: {}","annotations":{"readOnlyHint":true},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_scene","kind":"answer","impl":"imperative","description":"Read what is currently drawn on the canvas. Call this before modifying anything you did not just create, so you use real element ids instead of guessing.\n\nReturns compact records: id, type, x, y, w, h, and label/text where present. \"summary\" (default) caps the list so the response stays small; use \"full\" only when you genuinely need every element.\n\nExample: {\"detail\":\"summary\"}","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"detail":{"description":"summary caps at 80 elements and groups counts by type; full returns everything up to `limit`.","default":"summary","type":"string","enum":["summary","full"]},"limit":{"description":"Maximum elements to return. Defaults to 80.","type":"integer","exclusiveMinimum":0,"maximum":500}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_selection","kind":"answer","impl":"imperative","description":"Read the elements the human currently has selected on the canvas. This is how you act on what they mean by \"these\" or \"this one\" without asking them to describe it.\n\nCall this first whenever the request refers to something the user has highlighted. Returns the selected elements and their combined bounding box; an empty list means nothing is selected.\n\nExample: {}","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_viewport","kind":"answer","impl":"imperative","description":"Read the region of the canvas the human is currently looking at, plus zoom level. Useful when you want to reason about whether something you drew is actually on screen. Most of the time you do not need this — drawing tools already default to placing content in the visible area.\n\nExample: {}","annotations":{"readOnlyHint":true},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"find_elements","kind":"answer","impl":"imperative","description":"Find elements whose text or label contains a phrase (case-insensitive). Use this to extend or edit an existing diagram instead of redrawing it — e.g. the user says \"make the Login box red\" and you need its id.\n\nExample: {\"query\":\"login\"}","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"query":{"description":"Substring to look for in element text and labels.","type":"string","minLength":1},"type":{"description":"Optional element type filter, e.g. \"rectangle\" or \"text\".","type":"string"}},"required":["query"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"add_elements","kind":"act","impl":"imperative","description":"Draw new shapes, text and arrows on the canvas. Use this for freeform or small structures; prefer draw_flowchart when the user describes a process with steps, and draw_chart/draw_table for data.\n\nBindings are the important part: give each shape a \"tempId\", then an arrow with start/end referring to those tempIds will attach to the shapes and re-route automatically when the human drags them. Put text inside a shape with \"label\", not as a separate text element.\n\nYou usually should NOT pass x/y — omit them and the content is placed where the human is looking.\n\nExample: {\"elements\":[\n  {\"tempId\":\"a\",\"type\":\"rectangle\",\"label\":\"Draft\"},\n  {\"tempId\":\"b\",\"type\":\"rectangle\",\"label\":\"Review\",\"x\":300,\"y\":0},\n  {\"tempId\":\"e\",\"type\":\"arrow\",\"label\":\"submit\",\"start\":{\"tempId\":\"a\"},\"end\":{\"tempId\":\"b\"}}\n]}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"elements":{"description":"The shapes to draw. Coordinates are relative to each other; the whole group gets positioned by `placement`.","minItems":1,"maxItems":40,"type":"array","items":{"type":"object","properties":{"tempId":{"description":"Your own name for this element, so later elements in the same call can bind arrows to it.","type":"string"},"type":{"type":"string","enum":["rectangle","ellipse","diamond","text","arrow","line","frame"]},"label":{"description":"Text INSIDE a shape, or ON an arrow. Prefer this over a separate text element — it stays centred and moves with the shape.","type":"string"},"text":{"description":"Content for type \"text\" only.","type":"string"},"x":{"type":"number"},"y":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"},"start":{"description":"Arrows only. Bind the tail: {\"tempId\":\"a\"} for something in this call, {\"id\":\"<realId>\"} for an existing element.","type":"object","properties":{"tempId":{"type":"string"},"id":{"type":"string"}}},"end":{"description":"Arrows only. Bind the head, same shape as `start`.","type":"object","properties":{"tempId":{"type":"string"},"id":{"type":"string"}}},"children":{"description":"Frames only: real ids of the elements this frame contains.","type":"array","items":{"type":"string"}},"name":{"description":"Frames only: the frame's title.","type":"string"},"strokeColor":{"description":"Hex, e.g. \"#e03131\".","type":"string"},"backgroundColor":{"description":"Fill, e.g. \"#ffec99\". Use \"transparent\" for none.","type":"string"},"fillStyle":{"type":"string","enum":["hachure","cross-hatch","solid"]},"strokeWidth":{"type":"number"},"roughness":{"description":"0 = clean lines, 1 = hand-drawn (default), 2 = sketchy.","type":"number"},"fontSize":{"type":"number"},"opacity":{"type":"number","minimum":0,"maximum":100}},"required":["type"]}},"placement":{"description":"Where to put it. Omit for the centre of the human's current view. {\"mode\":\"next_to\",\"refId\":\"<id>\",\"side\":\"right\"} places it beside an existing element; {\"mode\":\"free_space\"} puts it clear of everything already drawn.","anyOf":[{"type":"object","properties":{"mode":{"type":"string","const":"viewport"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"next_to"},"refId":{"type":"string"},"side":{"type":"string","enum":["right","below","left","above"]},"gap":{"type":"number"}},"required":["mode","refId"]},{"type":"object","properties":{"mode":{"type":"string","const":"free_space"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"absolute"},"x":{"type":"number"},"y":{"type":"number"}},"required":["mode","x","y"]}]}},"required":["elements"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"update_elements","kind":"act","impl":"imperative","description":"Change existing elements by id — move, resize, recolour, or retext them. Get ids from get_scene, get_selection or find_elements.\n\nTo change only colours on several elements at once, restyle is simpler. Use this when you need to move or resize things.\n\nExample: {\"updates\":[{\"id\":\"abc123\",\"patch\":{\"x\":400,\"backgroundColor\":\"#ffec99\"}}]}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"updates":{"minItems":1,"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"patch":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"},"strokeColor":{"type":"string"},"backgroundColor":{"type":"string"},"fillStyle":{"type":"string","enum":["hachure","cross-hatch","solid"]},"strokeWidth":{"type":"number"},"roughness":{"type":"number"},"opacity":{"type":"number","minimum":0,"maximum":100},"angle":{"type":"number"},"text":{"description":"New text. Works on text elements and on a shape's bound label.","type":"string"},"fontSize":{"type":"number"}}}},"required":["id","patch"]}}},"required":["updates"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"duplicate_elements","kind":"act","impl":"imperative","description":"Copy existing elements and place the copies somewhere else. Use this to repeat a shape or a whole diagram instead of rebuilding it call by call — \"another one of these\", \"copy that flowchart and change the labels\", \"three more of this box\".\n\nArrows between the copied elements are re-bound to the COPIES, so the duplicate is independent: editing or moving it does not disturb the original. Text inside a copied shape comes along automatically.\n\nReturns \"idMap\" (original id -> new id) so you can immediately restyle or retext the copy.\n\nExample: {\"ids\":[\"abc123\"],\"placement\":{\"mode\":\"next_to\",\"refId\":\"abc123\",\"side\":\"right\"}}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"ids":{"description":"Elements to copy. Get them from get_selection, get_scene or find_elements.","minItems":1,"type":"array","items":{"type":"string"}},"count":{"description":"How many copies to make. Each is offset further along.","default":1,"type":"integer","minimum":1,"maximum":10},"placement":{"description":"Where to put it. Omit for the centre of the human's current view. {\"mode\":\"next_to\",\"refId\":\"<id>\",\"side\":\"right\"} places it beside an existing element; {\"mode\":\"free_space\"} puts it clear of everything already drawn.","anyOf":[{"type":"object","properties":{"mode":{"type":"string","const":"viewport"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"next_to"},"refId":{"type":"string"},"side":{"type":"string","enum":["right","below","left","above"]},"gap":{"type":"number"}},"required":["mode","refId"]},{"type":"object","properties":{"mode":{"type":"string","const":"free_space"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"absolute"},"x":{"type":"number"},"y":{"type":"number"}},"required":["mode","x","y"]}]}},"required":["ids"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"delete_elements","kind":"act","impl":"imperative","description":"Remove elements from the canvas by id. They are soft-deleted, so undo_agent_step can bring them back. Get ids from get_scene, get_selection or find_elements.\n\nExample: {\"ids\":[\"abc123\",\"def456\"]}","annotations":{"readOnlyHint":false,"destructiveHint":true},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"ids":{"minItems":1,"type":"array","items":{"type":"string"}}},"required":["ids"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"restyle","kind":"act","impl":"imperative","description":"Change the appearance of several elements at once without touching their position or text. This is the tool for \"make these yellow\", \"make the decision box red\", \"thicken these lines\".\n\nExample: {\"ids\":[\"abc\",\"def\"],\"backgroundColor\":\"#ffec99\",\"fillStyle\":\"solid\"}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"ids":{"minItems":1,"type":"array","items":{"type":"string"}},"strokeColor":{"type":"string"},"backgroundColor":{"type":"string"},"fillStyle":{"type":"string","enum":["hachure","cross-hatch","solid"]},"strokeWidth":{"type":"number"},"roughness":{"description":"0 = clean, 1 = hand-drawn, 2 = sketchy.","type":"number"},"fontSize":{"type":"number"},"opacity":{"type":"number","minimum":0,"maximum":100}},"required":["ids"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"focus_on","kind":"act","impl":"imperative","description":"Scroll and zoom the human's view so the given elements fill the screen, and select them. Use this after drawing something off-screen, or to point at what you are talking about.\n\nExample: {\"ids\":[\"abc123\"]}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"ids":{"minItems":1,"type":"array","items":{"type":"string"}},"select":{"description":"Also highlight the elements. Off by default, because selecting opens Excalidraw's style panel over the canvas.","default":false,"type":"boolean"}},"required":["ids"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"draw_flowchart","kind":"act","impl":"imperative","description":"Draw a proper flowchart with automatic layout. Use this — not add_elements — whenever the user describes a process, algorithm, decision tree, pipeline, or any set of steps connected by arrows. Layout, spacing and arrow routing are handled for you.\n\nGive either \"nodes\" + \"edges\" (preferred — you do not have to know Mermaid) or a raw \"mermaid\" string. Use shape \"diamond\" for decision points.\n\nKeep it under 40 nodes; for anything bigger, split it into a draw_board with several panels.\n\nExample: {\"nodes\":[{\"id\":\"s\",\"label\":\"Submit\",\"shape\":\"stadium\"},{\"id\":\"d\",\"label\":\"Approved?\",\"shape\":\"diamond\"},{\"id\":\"p\",\"label\":\"Publish\"}],\"edges\":[{\"from\":\"s\",\"to\":\"d\"},{\"from\":\"d\",\"to\":\"p\",\"label\":\"yes\"}],\"direction\":\"LR\"}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"nodes":{"type":"array","items":{"type":"object","properties":{"id":{"description":"Short identifier you will use in edges, e.g. \"start\".","type":"string"},"label":{"description":"Text shown in the box. Keep it under about six words.","type":"string"},"shape":{"description":"Use \"diamond\" for decisions and \"stadium\" for start/end. Defaults to rectangle.","type":"string","enum":["rectangle","diamond","round","stadium","circle"]}},"required":["id","label"]}},"edges":{"type":"array","items":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"label":{"description":"Text on the arrow, e.g. \"yes\" / \"no\".","type":"string"}},"required":["from","to"]}},"direction":{"description":"TD = top-down (default), LR = left-to-right. Use LR for pipelines.","default":"TD","type":"string","enum":["TD","LR","BT","RL"]},"mermaid":{"description":"Raw Mermaid, e.g. \"flowchart LR\\n A[One] --> B[Two]\". Only use if you specifically need Mermaid syntax.","type":"string"},"placement":{"description":"Where to put it. Omit for the centre of the human's current view. {\"mode\":\"next_to\",\"refId\":\"<id>\",\"side\":\"right\"} places it beside an existing element; {\"mode\":\"free_space\"} puts it clear of everything already drawn.","anyOf":[{"type":"object","properties":{"mode":{"type":"string","const":"viewport"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"next_to"},"refId":{"type":"string"},"side":{"type":"string","enum":["right","below","left","above"]},"gap":{"type":"number"}},"required":["mode","refId"]},{"type":"object","properties":{"mode":{"type":"string","const":"free_space"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"absolute"},"x":{"type":"number"},"y":{"type":"number"}},"required":["mode","x","y"]}]}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"draw_chart","kind":"act","impl":"imperative","description":"Draw a bar or line chart from data. Use this whenever the user gives you numbers — a CSV, a table, a list of figures — and wants them visualised. Axes, ticks, labels and a legend are computed for you; you only supply the data.\n\nReturns an id for every bar or point, keyed as \"<seriesIndex>:<labelIndex>\", so you can follow up with annotate to call out a specific one (e.g. the tallest bar).\n\nExample: {\"kind\":\"bar\",\"title\":\"Revenue by quarter\",\"labels\":[\"Q1\",\"Q2\",\"Q3\",\"Q4\"],\"series\":[{\"name\":\"2025\",\"values\":[12,19,3,17]}]}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"kind":{"default":"bar","type":"string","enum":["bar","line"]},"title":{"type":"string"},"labels":{"description":"Category labels along the x axis.","minItems":1,"maxItems":30,"type":"array","items":{"type":"string"}},"series":{"minItems":1,"maxItems":6,"type":"array","items":{"type":"object","properties":{"name":{"description":"Series name, shown in the legend when there is more than one.","type":"string"},"values":{"minItems":1,"type":"array","items":{"type":"number"}}},"required":["values"]}},"width":{"default":620,"type":"number","minimum":200,"maximum":2000},"height":{"default":400,"type":"number","minimum":150,"maximum":1400},"placement":{"description":"Where to put it. Omit for the centre of the human's current view. {\"mode\":\"next_to\",\"refId\":\"<id>\",\"side\":\"right\"} places it beside an existing element; {\"mode\":\"free_space\"} puts it clear of everything already drawn.","anyOf":[{"type":"object","properties":{"mode":{"type":"string","const":"viewport"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"next_to"},"refId":{"type":"string"},"side":{"type":"string","enum":["right","below","left","above"]},"gap":{"type":"number"}},"required":["mode","refId"]},{"type":"object","properties":{"mode":{"type":"string","const":"free_space"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"absolute"},"x":{"type":"number"},"y":{"type":"number"}},"required":["mode","x","y"]}]}},"required":["labels","series"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"draw_table","kind":"act","impl":"imperative","description":"Draw a table as a grid of cells with a shaded header row. Use this for comparisons, result summaries, or any small tabular data the user wants on the canvas rather than in chat.\n\nReturns cell ids keyed \"row:col\" (header row is row 0), so you can restyle or annotate individual cells afterwards.\n\nKeep it readable: at most about 8 columns and 20 rows. For long data, summarise first.\n\nExample: {\"headers\":[\"Method\",\"Accuracy\"],\"rows\":[[\"Baseline\",\"71%\"],[\"Ours\",\"88%\"]]}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"headers":{"minItems":1,"maxItems":10,"type":"array","items":{"type":"string"}},"rows":{"minItems":1,"maxItems":40,"type":"array","items":{"type":"array","items":{"type":"string"}}},"columnWidth":{"default":170,"type":"number","minimum":60,"maximum":500},"placement":{"description":"Where to put it. Omit for the centre of the human's current view. {\"mode\":\"next_to\",\"refId\":\"<id>\",\"side\":\"right\"} places it beside an existing element; {\"mode\":\"free_space\"} puts it clear of everything already drawn.","anyOf":[{"type":"object","properties":{"mode":{"type":"string","const":"viewport"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"next_to"},"refId":{"type":"string"},"side":{"type":"string","enum":["right","below","left","above"]},"gap":{"type":"number"}},"required":["mode","refId"]},{"type":"object","properties":{"mode":{"type":"string","const":"free_space"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"absolute"},"x":{"type":"number"},"y":{"type":"number"}},"required":["mode","x","y"]}]}},"required":["headers","rows"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"draw_hierarchy","kind":"act","impl":"imperative","description":"Draw a tree: section outlines, org charts, taxonomies, \"chapter -> sections -> key points\". Use this when the structure is strictly nested (every item has one parent). If items connect to each other in more than one direction, use draw_graph instead.\n\nNest with \"children\" to any depth. Keep the whole tree under 40 nodes — for a long document, produce a draw_board with one hierarchy panel per major section instead.\n\nExample: {\"root\":{\"label\":\"Chapter 3\",\"children\":[{\"label\":\"Method\",\"children\":[{\"label\":\"Sampling\"}]},{\"label\":\"Results\"}]},\"direction\":\"TD\"}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string"},"root":{"$ref":"#/$defs/__schema0"},"direction":{"description":"TD = top-down. LR reads better for deep outlines.","default":"TD","type":"string","enum":["TD","LR"]},"placement":{"description":"Where to put it. Omit for the centre of the human's current view. {\"mode\":\"next_to\",\"refId\":\"<id>\",\"side\":\"right\"} places it beside an existing element; {\"mode\":\"free_space\"} puts it clear of everything already drawn.","anyOf":[{"type":"object","properties":{"mode":{"type":"string","const":"viewport"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"next_to"},"refId":{"type":"string"},"side":{"type":"string","enum":["right","below","left","above"]},"gap":{"type":"number"}},"required":["mode","refId"]},{"type":"object","properties":{"mode":{"type":"string","const":"free_space"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"absolute"},"x":{"type":"number"},"y":{"type":"number"}},"required":["mode","x","y"]}]}},"required":["root"],"$defs":{"__schema0":{"type":"object","properties":{"label":{"description":"Short — under about six words.","type":"string"},"children":{"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"required":["label"]}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"draw_graph","kind":"act","impl":"imperative","description":"Draw a relationship graph — things connected to each other in no particular hierarchy. Use this for characters in a novel, concepts in a literature review, components in a system, or citations between works.\n\nUse \"group\" on nodes to cluster related items; each group is drawn as a labelled box around its members. Edges are undirected by default; set \"directed\": true for an arrow.\n\nKeep it under 40 nodes. If the structure is a strict tree, draw_hierarchy gives a cleaner result.\n\nExample: {\"nodes\":[{\"id\":\"anna\",\"label\":\"Anna\",\"group\":\"Family\"},{\"id\":\"pyotr\",\"label\":\"Pyotr\",\"group\":\"Family\"},{\"id\":\"vronsky\",\"label\":\"Vronsky\"}],\"edges\":[{\"from\":\"anna\",\"to\":\"pyotr\",\"label\":\"married to\"},{\"from\":\"anna\",\"to\":\"vronsky\",\"label\":\"affair\",\"directed\":true}]}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string"},"nodes":{"minItems":1,"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"group":{"description":"Nodes sharing a group are drawn inside a labelled cluster.","type":"string"}},"required":["id","label"]}},"edges":{"default":[],"type":"array","items":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"label":{"type":"string"},"directed":{"default":false,"type":"boolean"}},"required":["from","to"]}},"direction":{"default":"LR","type":"string","enum":["TD","LR"]},"placement":{"description":"Where to put it. Omit for the centre of the human's current view. {\"mode\":\"next_to\",\"refId\":\"<id>\",\"side\":\"right\"} places it beside an existing element; {\"mode\":\"free_space\"} puts it clear of everything already drawn.","anyOf":[{"type":"object","properties":{"mode":{"type":"string","const":"viewport"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"next_to"},"refId":{"type":"string"},"side":{"type":"string","enum":["right","below","left","above"]},"gap":{"type":"number"}},"required":["mode","refId"]},{"type":"object","properties":{"mode":{"type":"string","const":"free_space"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"absolute"},"x":{"type":"number"},"y":{"type":"number"}},"required":["mode","x","y"]}]}},"required":["nodes"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"draw_timeline","kind":"act","impl":"imperative","description":"Draw an ordered sequence of events along an axis: plot events, experiment stages, project milestones, historical background. Labels alternate above and below the line so they do not collide.\n\nUse this when order matters but there is no branching. If steps branch or loop, use draw_flowchart.\n\nExample: {\"title\":\"Study timeline\",\"events\":[{\"label\":\"Recruit\",\"detail\":\"n=120\"},{\"label\":\"Baseline\"},{\"label\":\"Follow-up\",\"detail\":\"12 weeks\"}],\"orientation\":\"horizontal\"}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string"},"events":{"minItems":2,"maxItems":40,"type":"array","items":{"type":"object","properties":{"label":{"description":"Short name for the event.","type":"string"},"detail":{"description":"Secondary line — dates, counts, notes. Put detail HERE, not in the label.","type":"string"}},"required":["label"]}},"orientation":{"default":"horizontal","type":"string","enum":["horizontal","vertical"]},"placement":{"description":"Where to put it. Omit for the centre of the human's current view. {\"mode\":\"next_to\",\"refId\":\"<id>\",\"side\":\"right\"} places it beside an existing element; {\"mode\":\"free_space\"} puts it clear of everything already drawn.","anyOf":[{"type":"object","properties":{"mode":{"type":"string","const":"viewport"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"next_to"},"refId":{"type":"string"},"side":{"type":"string","enum":["right","below","left","above"]},"gap":{"type":"number"}},"required":["mode","refId"]},{"type":"object","properties":{"mode":{"type":"string","const":"free_space"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"absolute"},"x":{"type":"number"},"y":{"type":"number"}},"required":["mode","x","y"]}]}},"required":["events"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"draw_board","kind":"act","impl":"imperative","description":"Draw SEVERAL diagrams at once, laid out in a grid, each with its own heading. This is the right tool for a long document — a thesis chapter, a paper, a novel — where one diagram would be an unreadable hairball.\n\nDo not try to fit a whole document into one diagram. Produce 3 to 6 panels, one per major section or theme, each under 25 nodes. Keep labels under six words and put detail in \"detail\" fields rather than in node labels.\n\nEach panel's \"spec\" is exactly what you would pass to that kind's own tool. Returns per-panel ids so you can extend one panel later instead of redrawing everything.\n\nExample: {\"columns\":2,\"panels\":[\n  {\"title\":\"Structure\",\"kind\":\"hierarchy\",\"spec\":{\"root\":{\"label\":\"Chapter 3\",\"children\":[{\"label\":\"Method\"},{\"label\":\"Results\"}]}}},\n  {\"title\":\"Procedure\",\"kind\":\"flowchart\",\"spec\":{\"nodes\":[{\"id\":\"a\",\"label\":\"Recruit\"},{\"id\":\"b\",\"label\":\"Measure\"}],\"edges\":[{\"from\":\"a\",\"to\":\"b\"}]}}\n]}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"description":"Overall board heading.","type":"string"},"panels":{"minItems":1,"maxItems":8,"type":"array","items":{"type":"object","properties":{"title":{"description":"Panel heading, shown above the diagram.","type":"string"},"kind":{"type":"string","enum":["flowchart","hierarchy","timeline","graph","table","chart"]},"spec":{"description":"The input you would pass to that kind's own tool, minus `placement`.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["title","kind","spec"]}},"columns":{"default":2,"type":"integer","minimum":1,"maximum":4},"placement":{"description":"Where to put it. Omit for the centre of the human's current view. {\"mode\":\"next_to\",\"refId\":\"<id>\",\"side\":\"right\"} places it beside an existing element; {\"mode\":\"free_space\"} puts it clear of everything already drawn.","anyOf":[{"type":"object","properties":{"mode":{"type":"string","const":"viewport"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"next_to"},"refId":{"type":"string"},"side":{"type":"string","enum":["right","below","left","above"]},"gap":{"type":"number"}},"required":["mode","refId"]},{"type":"object","properties":{"mode":{"type":"string","const":"free_space"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"absolute"},"x":{"type":"number"},"y":{"type":"number"}},"required":["mode","x","y"]}]}},"required":["panels"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"place_image","kind":"act","impl":"imperative","description":"Put an image on the canvas. Use \"upload\" to ask the human to pick a file, or \"dataURL\" if you already have the image bytes.\n\nThe common use is tracing: place a photo of a hand-drawn sketch faded in the background, then redraw it cleanly beside it with draw_flowchart or add_elements. Default opacity is 40 for exactly that.\n\nNote: you cannot see the image this returns. Read the picture from the user's chat attachment and use this tool only to put a reference copy on the canvas.\n\nExample: {\"source\":\"upload\",\"opacity\":40}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"source":{"description":"\"upload\" opens a file chooser, \"camera\" opens the webcam, \"dataURL\" uses the string you pass.","default":"upload","type":"string","enum":["upload","camera","dataURL"]},"dataURL":{"description":"Required when source is \"dataURL\". Must start with \"data:image/\".","type":"string"},"opacity":{"description":"40 makes it a faint tracing reference. Use 100 for a normal image.","default":40,"type":"number","minimum":0,"maximum":100},"maxWidth":{"description":"Longest edge in canvas units; aspect ratio is preserved.","default":600,"type":"number","minimum":50,"maximum":2000},"placement":{"description":"Where to put it. Omit for the centre of the human's current view. {\"mode\":\"next_to\",\"refId\":\"<id>\",\"side\":\"right\"} places it beside an existing element; {\"mode\":\"free_space\"} puts it clear of everything already drawn.","anyOf":[{"type":"object","properties":{"mode":{"type":"string","const":"viewport"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"next_to"},"refId":{"type":"string"},"side":{"type":"string","enum":["right","below","left","above"]},"gap":{"type":"number"}},"required":["mode","refId"]},{"type":"object","properties":{"mode":{"type":"string","const":"free_space"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"absolute"},"x":{"type":"number"},"y":{"type":"number"}},"required":["mode","x","y"]}]}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"capture_photo","kind":"act","impl":"imperative","description":"Open the camera so the human can photograph something — typically a sketch on paper — and place the photo on the canvas as a faded reference.\n\nYou cannot see the resulting photo. To redraw a paper sketch, ask the user to attach it in the chat where you can actually look at it; use this tool only to get a reference copy onto the canvas beside your clean version.\n\nExample: {}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"opacity":{"default":40,"type":"number","minimum":0,"maximum":100},"maxWidth":{"default":600,"type":"number","minimum":50,"maximum":2000},"placement":{"description":"Where to put it. Omit for the centre of the human's current view. {\"mode\":\"next_to\",\"refId\":\"<id>\",\"side\":\"right\"} places it beside an existing element; {\"mode\":\"free_space\"} puts it clear of everything already drawn.","anyOf":[{"type":"object","properties":{"mode":{"type":"string","const":"viewport"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"next_to"},"refId":{"type":"string"},"side":{"type":"string","enum":["right","below","left","above"]},"gap":{"type":"number"}},"required":["mode","refId"]},{"type":"object","properties":{"mode":{"type":"string","const":"free_space"}},"required":["mode"]},{"type":"object","properties":{"mode":{"type":"string","const":"absolute"},"x":{"type":"number"},"y":{"type":"number"}},"required":["mode","x","y"]}]}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"arrange","kind":"act","impl":"imperative","description":"Reposition existing elements into a tidy row, column, or grid. This is the tool for \"line these up\", \"make these a horizontal pipeline\", \"tidy this up\".\n\nUsually you call get_selection first and pass those ids. Arrows bound to the moved shapes stay attached.\n\nExample: {\"ids\":[\"a1\",\"b2\",\"c3\"],\"mode\":\"row\",\"gap\":60,\"align\":\"center\"}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"ids":{"minItems":2,"type":"array","items":{"type":"string"}},"mode":{"description":"row = left to right, column = top to bottom, grid = wrapped rows.","default":"row","type":"string","enum":["row","column","grid"]},"gap":{"description":"Space between elements in canvas units.","default":60,"type":"number","minimum":0,"maximum":400},"align":{"description":"How to line up the cross axis.","default":"center","type":"string","enum":["left","center","top"]},"columns":{"description":"Grid mode only: how many per row.","type":"integer","minimum":1,"maximum":10}},"required":["ids"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"annotate","kind":"act","impl":"imperative","description":"Add a callout note pointing at a specific element: a short piece of text placed beside it, with an arrow linking the two. Use this to draw attention to something — the tallest bar in a chart, the bottleneck in a flowchart, the cell with the best result.\n\nGet the target id from draw_chart's \"points\", draw_table's \"cells\", a draw_* tool's \"nodeIds\", get_selection, or find_elements.\n\nExample: {\"targetId\":\"abc123\",\"text\":\"biggest jump\",\"side\":\"top\",\"color\":\"#e03131\"}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"targetId":{"description":"The element the note points at.","type":"string"},"text":{"description":"Keep it short — a phrase, not a paragraph.","type":"string","minLength":1,"maxLength":200},"side":{"description":"Which side of the target to put the note on.","default":"top","type":"string","enum":["top","right","bottom","left"]},"color":{"description":"Hex colour for the note and arrow, e.g. \"#e03131\".","type":"string"}},"required":["targetId","text"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"export_png","kind":"act","impl":"imperative","description":"Export the canvas as a PNG and hand it to the human as a download. Use it when the user asks to save, export, or download what has been drawn.\n\nPass \"ids\" to export just part of the canvas, or omit it for everything.\n\nExample: {}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"ids":{"description":"Export only these elements. Omit for the whole canvas.","type":"array","items":{"type":"string"}},"scale":{"description":"2 gives a crisp image on high-DPI screens.","default":2,"type":"number","minimum":1,"maximum":3},"background":{"description":"Include the canvas background colour.","default":true,"type":"boolean"}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"undo_agent_step","kind":"act","impl":"imperative","description":"Undo your own most recent change(s) to the canvas. Use this when the human says that was wrong, or you realise you drew the wrong thing.\n\nThis only reverses YOUR actions — it never touches what the human drew themselves.\n\nExample: {\"steps\":1}","annotations":{"readOnlyHint":false},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"steps":{"description":"How many of your recent actions to reverse. Defaults to 1.","default":1,"type":"integer","exclusiveMinimum":0,"maximum":20}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"clear_canvas","kind":"act","impl":"imperative","description":"Erase everything on the canvas. This removes the human's own work too, so ALWAYS ask them to confirm in the conversation before calling it, and only call it when they have clearly said yes.\n\nExample: {\"confirm\":true}","annotations":{"readOnlyHint":false,"destructiveHint":true},"inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"confirm":{"description":"Must be exactly true, and only after the human has agreed.","type":"boolean","const":true}},"required":["confirm"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"}],"apiSurface":"spec","category":"Developer Tools","toolCount":25}}