Storyflow: the user's projects hold boards (whiteboards of notes, todos, tables, documents and folders) and documents. Drill down: list_projects, then list_boards or list_documents with a project_uid, then get_whiteboard_elements or get_document. Every tool takes project_uid; board tools also take whiteboard_uid (empty for the project's root board), and a board is named by that pair, never by a numeric id. Write tools exist only when this connection carries the write scope, and only on the projects the user approved it for. A picture the user attached in the chat never reaches Storyflow: call request_photo_upload for the board and give them its link; never say Storyflow cannot take their photo.
Protocol
Pass100/10020 / 20 pts
Connection, authentication, and protocol compatibility.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
List the user's Flow projects — the top-level containers holding whiteboards, documents and tactics. Returns id, uid, title, status, the user's role, and created_by_you: false means someone else made this project and shared it, so what is on it is mostly THEIR work, not the user's. Use a project uid with other tools to drill in. Order by 'viewed' to see what they actually work on; the default 'created' is newest-made first, which for a long-standing account is mostly the projects they opened once.
The description explains the capability, when to use it, and what to expect.
Inputs44/100
2 of 4 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
key_word
Case-insensitive title filter.
Clear enough to supply this argument.
limit
Not provided
Missing description. Explain what this value means and how to supply it.
offset
Not provided
Missing description. Explain what this value means and how to supply it.
order
created = newest first (default). viewed = most recently opened first.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "list_projects",
"title": "List projects",
"description": "List the user's Flow projects — the top-level containers holding whiteboards, documents and tactics. Returns id, uid, title, status, the user's role, and created_by_you: false means someone else made this project and shared it, so what is on it is mostly THEIR work, not the user's. Use a project uid with other tools to drill in. Order by 'viewed' to see what they actually work on; the default 'created' is newest-made first, which for a long-standing account is mostly the projects they opened once.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"limit": {
"type": "integer",
"maximum": 200,
"exclusiveMinimum": 0
},
"order": {
"enum": [
"created",
"viewed"
],
"type": "string",
"description": "created = newest first (default). viewed = most recently opened first."
},
"offset": {
"type": "integer",
"minimum": 0
},
"key_word": {
"type": "string",
"description": "Case-insensitive title filter."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_project",
"title": "Get project",
"description": "Fetch a single project by uid, including title, status and the user's permission level.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid"
],
"properties": {
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description93/100
List a project's boards as a tree: each folder's board with its name, uid (pass it as whiteboard_uid), parent board and the folder element that opens it. Names only; read a board's content with get_whiteboard_elements and its whiteboard_uid.
The description explains the capability, when to use it, and what to expect.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "list_boards",
"title": "List boards",
"description": "List a project's boards as a tree: each folder's board with its name, uid (pass it as whiteboard_uid), parent board and the folder element that opens it. Names only; read a board's content with get_whiteboard_elements and its whiteboard_uid.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid"
],
"properties": {
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
List the people who have access to this board — the same roster the assignee picker shows. Use it to answer 'who is on this board', and before filling a table's person column when the user did not name someone exactly. Returns each person's id and name; a person cell is written with the NAME.
The description explains the capability, when to use it, and what to expect.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_board_people",
"title": "Get board people",
"description": "List the people who have access to this board — the same roster the assignee picker shows. Use it to answer 'who is on this board', and before filling a table's person column when the user did not name someone exactly. Returns each person's id and name; a person cell is written with the NAME.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid"
],
"properties": {
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description84/100
Fetch a whiteboard's metadata by the owning project id (and optionally the board uid; omit it for the project's root board). Board-level metadata only — use get_whiteboard_elements for the actual content.
Describe the returned information so the agent knows whether it will answer the request.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_whiteboard",
"title": "Get whiteboard",
"description": "Fetch a whiteboard's metadata by the owning project id (and optionally the board uid; omit it for the project's root board). Board-level metadata only — use get_whiteboard_elements for the actual content.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid"
],
"properties": {
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description90/100
Read what is on a board, with the real text of each element: notes, todos, headings, tickets, tables, documents, tactics, frames and walls. Pass element_uids to read specific elements, or parent_uid to read inside one wall, kanban, group or frame; otherwise the whole board. Containers include their children. An element someone else wrote is marked createdByYou: false.
The description explains the capability, when to use it, and what to expect.
Inputs96/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
element_uids
Specific element uids to read.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
parent_uid
Read the children of this container element.
Clear enough to supply this argument.
include_children
Expand containers into their children. Defaults to true.
Clear enough to supply this argument.
max_content_chars
Cap each element's text content at this many characters (a cut ends with …). Use it for structural work — grouping, counting, arranging — where a title and an opening line decide everything and full bodies only slow the turn.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_whiteboard_elements",
"title": "Get whiteboard elements",
"description": "Read what is on a board, with the real text of each element: notes, todos, headings, tickets, tables, documents, tactics, frames and walls. Pass element_uids to read specific elements, or parent_uid to read inside one wall, kanban, group or frame; otherwise the whole board. Containers include their children. An element someone else wrote is marked createdByYou: false.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid"
],
"properties": {
"parent_uid": {
"type": "string",
"description": "Read the children of this container element."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"element_uids": {
"type": "array",
"items": {
"type": "string"
},
"description": "Specific element uids to read."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
},
"include_children": {
"type": "boolean",
"description": "Expand containers into their children. Defaults to true."
},
"max_content_chars": {
"type": "integer",
"description": "Cap each element's text content at this many characters (a cut ends with …). Use it for structural work — grouping, counting, arranging — where a title and an opening line decide everything and full bodies only slow the turn.",
"exclusiveMinimum": 0
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_whiteboard_edges",
"title": "Get whiteboard edges",
"description": "Read a board's edges: the arrows and connections between its elements, with their text.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid"
],
"properties": {
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description92/100
List the user's documents. scope: 'project' (requires project_uid), 'private', 'shared', or 'recent'. Returns summaries; use get_document for full content.
The description explains the capability, when to use it, and what to expect.
Inputs33/100
2 of 6 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
scope
Not provided
Missing description. Explain what this value means and how to supply it.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
key_word
Not provided
Missing description. Explain what this value means and how to supply it.
limit
Not provided
Missing description. Explain what this value means and how to supply it.
offset
Not provided
Missing description. Explain what this value means and how to supply it.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description89/100
Fetch a document by uid: title, content and notes. The content HTML carries data-block-id attributes — those are what the edit tools target, so read the document before editing it. The uid in a table's document CELL (inside its tableData payload) is a valid uid here — that is how you read what a cell's document actually says.
The description explains the capability, when to use it, and what to expect.
Inputs67/100
2 of 3 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
document_uid
Not provided
Missing description. Explain what this value means and how to supply it.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_document",
"title": "Get document",
"description": "Fetch a document by uid: title, content and notes. The content HTML carries data-block-id attributes — those are what the edit tools target, so read the document before editing it. The uid in a table's document CELL (inside its tableData payload) is a valid uid here — that is how you read what a cell's document actually says.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"document_uid",
"project_uid"
],
"properties": {
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"document_uid": {
"type": "string"
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_tactic",
"title": "Get tactic",
"description": "Fetch a tactic (blueprint) by uid — an expert framework of ordered flip-cards, possibly with a document view. Use get_tactic_cards to read its cards.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"blueprint_uid",
"project_uid"
],
"properties": {
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"blueprint_uid": {
"type": "string",
"description": "The tactic's (blueprint's) uid."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description76/100
Search the tactic LIBRARY — the published expert frameworks a user can attach or start from. Use this to find a tactic by name. Different from get_tactic, which reads a tactic already living inside a project.
Describe the returned information so the agent knows whether it will answer the request.
Inputs50/100
3 of 5 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
key_word
Filter by title.
Explain the meaning of this value, not just its name.
limit
Not provided
Missing description. Explain what this value means and how to supply it.
offset
Not provided
Missing description. Explain what this value means and how to supply it.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "list_tactics",
"title": "List tactics",
"description": "Search the tactic LIBRARY — the published expert frameworks a user can attach or start from. Use this to find a tactic by name. Different from get_tactic, which reads a tactic already living inside a project.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 100,
"exclusiveMinimum": 0
},
"offset": {
"type": "integer",
"minimum": 0
},
"key_word": {
"type": "string",
"description": "Filter by title."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description81/100
Read the cards of a tactic from the LIBRARY, in display order — each card's title, subtitle and body are the steps of the framework. This is the tool to call for a tactic the user ATTACHED to their message.
Describe the returned information so the agent knows whether it will answer the request.
Inputs60/100
3 of 5 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
tactic_id
Numeric tactic (blueprint admin template) id — the id given in the attached-tactic note.
Clear enough to supply this argument.
limit
Not provided
Missing description. Explain what this value means and how to supply it.
offset
Not provided
Missing description. Explain what this value means and how to supply it.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_tactic_template_cards",
"title": "Get tactic template cards",
"description": "Read the cards of a tactic from the LIBRARY, in display order — each card's title, subtitle and body are the steps of the framework. This is the tool to call for a tactic the user ATTACHED to their message.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"tactic_id",
"project_uid"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 500,
"exclusiveMinimum": 0
},
"offset": {
"type": "integer",
"minimum": 0
},
"tactic_id": {
"type": "integer",
"description": "Numeric tactic (blueprint admin template) id — the id given in the attached-tactic note.",
"exclusiveMinimum": 0
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description97/100
An index of what is on a whiteboard — element counts by type, the names of its walls and folders, and the titles of what they hold — without reading every element's content. Use this FIRST for any board the user attached, and for any board you are deciding whether to read. Use get_whiteboard_elements instead once you know you need the actual content. It also reports authorship — how much of what was read the user wrote themselves.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_board_summary",
"title": "Get board summary",
"description": "An index of what is on a whiteboard — element counts by type, the names of its walls and folders, and the titles of what they hold — without reading every element's content. Use this FIRST for any board the user attached, and for any board you are deciding whether to read. Use get_whiteboard_elements instead once you know you need the actual content. It also reports authorship — how much of what was read the user wrote themselves.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid"
],
"properties": {
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
The board's real geometry: every element's position and the size the canvas actually draws it at (stored sizes are not real — notes fit their text, walls grow with their cards, documents draw as large cards). Positions are absolute board coordinates; a wall's cards come with parent_uid and their place inside the wall. Use it before placing, aligning or resizing things relative to what is already there. Each element says whether its box was measured or estimated. A board that changed since its last measure takes a few seconds to measure. Returns at most 500 elements, top to bottom, and says so in `note` when a board holds more.
The description explains the capability, when to use it, and what to expect.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_board_layout",
"title": "Get board layout",
"description": "The board's real geometry: every element's position and the size the canvas actually draws it at (stored sizes are not real — notes fit their text, walls grow with their cards, documents draw as large cards). Positions are absolute board coordinates; a wall's cards come with parent_uid and their place inside the wall. Use it before placing, aligning or resizing things relative to what is already there. Each element says whether its box was measured or estimated. A board that changed since its last measure takes a few seconds to measure. Returns at most 500 elements, top to bottom, and says so in `note` when a board holds more.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid"
],
"properties": {
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description95/100
What HAPPENED on this board — per card: created, edited, moved, refiled (into or out of a wall), restyled or deleted, who did it, when, and whether it was your own earlier work in this chat. Answers 'what changed?', 'what did I do here since last time?', 'how has this board evolved?'. Default window is since your last turn in this chat. Not a board read: it says what changed, not what is there — read the board itself with get_board_summary or get_whiteboard_elements.
The description explains the capability, when to use it, and what to expect.
Inputs92/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
since
How far back. last_turn = since the newest message in this chat (a first turn reads a week); all = as far back as the read allows, newest first.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_board_changes",
"title": "Get board changes",
"description": "What HAPPENED on this board — per card: created, edited, moved, refiled (into or out of a wall), restyled or deleted, who did it, when, and whether it was your own earlier work in this chat. Answers 'what changed?', 'what did I do here since last time?', 'how has this board evolved?'. Default window is since your last turn in this chat. Not a board read: it says what changed, not what is there — read the board itself with get_board_summary or get_whiteboard_elements.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid"
],
"properties": {
"since": {
"enum": [
"last_turn",
"day",
"week",
"month",
"all"
],
"type": "string",
"default": "last_turn",
"description": "How far back. last_turn = since the newest message in this chat (a first turn reads a week); all = as far back as the read allows, newest first."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
What is in this board's trash: everything deleted from it in the last 7 days, split into what the user deleted and what others deleted. Each entry carries the history_id that restore_deleted_elements needs — element uids do not restore anything. Use it when the user says something was deleted, lost or went missing from a board. Only board elements have a trash: a deleted project, document or gallery upload is gone for good, so say that instead of searching for it.
The description explains the capability, when to use it, and what to expect.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "get_deleted_elements",
"title": "Get deleted elements",
"description": "What is in this board's trash: everything deleted from it in the last 7 days, split into what the user deleted and what others deleted. Each entry carries the history_id that restore_deleted_elements needs — element uids do not restore anything. Use it when the user says something was deleted, lost or went missing from a board. Only board elements have a trash: a deleted project, document or gallery upload is gone for good, so say that instead of searching for it.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid"
],
"properties": {
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description97/100
Read the text of a FILE on the board (PDF, DOCX, XLSX, XLS, CSV, TXT, MD, code…) and return its contents. Use this BEFORE answering anything about a file — summarising it, pulling its rows into a table, turning it into tasks or a shotlist. A board read gives you only the file's name and address; its contents come from here. Never answer from a filename. Long files come back truncated, and the result says so.
The description explains the capability, when to use it, and what to expect.
Inputs94/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
element_uid
The file element's uid, from a board read or the user's selection.
Clear enough to supply this argument.
max_characters
Cap on the returned text. Defaults to 40000, which is also the maximum.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "read_file",
"title": "Read file",
"description": "Read the text of a FILE on the board (PDF, DOCX, XLSX, XLS, CSV, TXT, MD, code…) and return its contents. Use this BEFORE answering anything about a file — summarising it, pulling its rows into a table, turning it into tasks or a shotlist. A board read gives you only the file's name and address; its contents come from here. Never answer from a filename. Long files come back truncated, and the result says so.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"element_uid",
"project_uid"
],
"properties": {
"element_uid": {
"type": "string",
"description": "The file element's uid, from a board read or the user's selection."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"max_characters": {
"type": "integer",
"maximum": 40000,
"minimum": 1000,
"description": "Cap on the returned text. Defaults to 40000, which is also the maximum."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description92/100
Create ONE element on a whiteboard and return its uid. This is the only way to put anything on a board. Each call is one element, and every call whose inputs you already have goes in the SAME step: they land one after another in the order you write them, so the user still watches the board fill, and each step you do not take is one less re-read of the whole prompt. Wait for the next step only for a call that needs a uid another call returns.
Compose whatever structure fits. A new wall and its cards are ONE build_section call; here, a card for a wall that already exists takes parent_uid set to that wall's uid. On a board that has walls, a folder, document or note goes in one; only a title note (background_color "transparent"), a picture or a shape sits loose.
Position and size are decided for you so nothing overlaps — there is no geometry to pass. Creates are immediate and not reviewed; the user can undo.
A CHECKLIST IS ONE CARD: for a to-do list, make a single todo call with every task on its own line in `text`. Each line becomes a checkbox on that one card. A separate card per task is not a list, even when earlier turns in this conversation or cards already on the board look like that.
NOT for changing something that already exists. Adding detail to, expanding, or rewriting an existing element is update_element on THAT element — never a new element beside it holding the addition, even if the board or earlier turns already show that pattern.
The description explains the capability, when to use it, and what to expect.
Inputs87/100
32 of 33 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
type
What to create. Each renders differently AND is sized for a different amount of content — every one of them can hold the same words, so pick by how much the SUBJECT carries:
note — a card of prose, sized for a line to a few paragraphs: a thought, a summary, a short script or one scene of a longer one. If it would have to be scrolled to read, the subject has outgrown a note. With background_color 'transparent' it loses the card entirely and becomes text sitting on the canvas: that, plus font_size, is how a board or a row of walls gets its title.
todo — a card of tickable checkboxes, for short tasks and reminders that need no explaining. Put EVERY task in ONE call, one per line in `text`: each line becomes its own checkbox on a single checklist card. A card per task is wrong.
heading — ONE line of text at a fixed size, no card. It holds a single line and nothing else: no second line, no sentence under the title, no size of its own. Use it only when the user asked for a heading; to title something you are building, use a transparent note.
ticket — ONE task or decision carrying real information: what needs doing, why, what is blocking it, what came back. It has its own title and description because it is meant to be opened and worked on over time. A task you can state in six words is a todo line instead. ALWAYS give a ticket its one chip in `labels` — the card draws an empty 'Label' slot without one, which reads as a ticket you left unfinished.
link — a clickable link card showing the page title and a short description.
video — an embedded player; a YouTube or Vimeo url plays inline on the board. Omit the url and you get an EMPTY player with a url box on it, which is how you leave a slot for a video only the user has: their showreel, their channel, the cut they have not uploaded yet. Give it a title saying which video belongs there. Never invent a url to fill one.
image — a picture from generate_image, or an EMPTY frame when you omit image_url: a placeholder the user fills themselves or asks you to generate into later.
comment — a comment card: a remark ABOUT the board, in a bubble, rather than content on it. It is posted as the SIGNED-IN USER, because that is the only person you can post as — so when you are copying a comment someone else wrote, lead the text with who wrote it and when ('Michael, 11 June 2020: …'). Never write it as though the user said it.
file — a document card: a named slot for a real file, a PDF, a deck, a spreadsheet. It lands EMPTY, named by `file_name`, for the user to drop the document onto. Use it when a board you are copying shows a document tile, or when the user names a file that belongs on the board but has not sent it. For a file they ATTACHED to this message, use add_attachment_to_board instead — that puts the real file there, where this would leave them an empty tile over a document they already sent. Never use it to carry text — a file card holds no words, and prose belongs in a note.
table — a real grid with column headers and rows, editable cell by cell, for several things that share the same fields. Give every table a `title` (its heading, shown above the grid), a one-line `description` (the caption under it) and, when the title alone would not say the topic, a `table_icon` — a titled, captioned table reads as something; a bare grid of cells does not.
color — ONE swatch carrying its hex and a name in `text`, for a single colour added to something that already exists, or for colours going INSIDE a wall (pass parent_uid). A whole PALETTE is create_color_palette instead, in one call: swatch after swatch through this tool cannot make a grid — each one lands to the right of the last and the palette runs off the canvas. A palette is never described in a note.
document — a NEW rich-text document that opens full screen for long-form writing, its opening section in text — anything the user will READ rather than scan. To put a document that ALREADY exists on the board (one the user attached, or one you found), use add_document_to_board instead — this would create a blank one beside it.
wall — a titled container holding one SECTION of the board, and mixed by nature: folders, notes, todos, links, a table, a couple of images can all sit in the same wall. Create it first, then create its cards with parent_uid set to its uid.
folder — a nested BOARD that opens as its own canvas, shown as a folder tile. For a subject with so much inside it that cards cannot hold it: one client, one production, one department is a whole board of its own. A wall groups cards in place, a folder holds a whole board behind it, and on an overview board the folder is the normal unit rather than the exception. Creating one returns opens_whiteboard_id: pass that as whiteboard_id on your next calls to build inside it, in this same turn.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
text
Text for note/todo/heading, the document body, or a colour's caption.
Clear enough to supply this argument.
title
Wall title, ticket title, link label, table name, document title, or folder name. A table is ALWAYS given one — it is the heading shown above the grid, and a table without it lands as an anonymous block of cells.
Clear enough to supply this argument.
description
Ticket description, a link's one-line summary, or a table's caption — the line under the grid saying what it holds or how to read it. Give every table one short sentence.
Clear enough to supply this argument.
folder_icon
For folder only — the TOPIC of the folder, which picks its icon. Pick the closest one from: research, idea, strategy, planning, tasks, notes, meeting, launch, archive, inbox, templates, settings, design, writing, brand, photo, video, music, audio, marketing, sales, finance, budget, invoice, analytics, legal, clients, team, support, product, shop, engineering, bugs, security, data, cloud, travel, food, health, fitness, home, education, science, nature, mountain, camping, weather, transport, gear, events, gifts, reading, location, global, favourites, important, private, time, folder. Leave it out and the icon is chosen from the folder's name. Pass 'none' ONLY if the user said they do not want an icon. Anything outside this list falls back to a plain folder, so use a word from it rather than inventing an icon name.
Clear enough to supply this argument.
folder_color
For folder only — its tile colour, one of: tan, blue, rose, purple, steel, brown, red, navy, violet, slate, coral, orange. LEAVE IT OUT WHENEVER YOU ARE MAKING SEVERAL FOLDERS: each then takes a colour of its own from its name, which is what lets a set of tiles be told apart at a glance. One word repeated across the set — or borrowed from the wall they sit in — makes them all look the same. Pass it for a single folder the user asked to colour. Pass 'none' ONLY if the user asked for no colour.
Clear enough to supply this argument.
folder_cover_image
For folder only — a PICTURE on the tile instead of an icon, which is what a cover image or folder thumbnail means. Pass a stored image key: a board image's imageUrl, a generated image's image_url, a find_images result, or a gallery key. A folder shows a picture or an icon, never both, so this wins over folder_icon. Raw web urls (http/https/data/blob) are not stored images and are ignored — get the picture through find_images, which stores what it finds, or use one already on the board.
Clear enough to supply this argument.
table_icon
For table only — the TOPIC of the table as a whole, which picks the icon shown beside its title. Pick the closest word from: name, title, owner, assignee, person, team, client, company, audience, character, identity, personality, background, relationship, story, status, stage, progress, priority, approval, done, task, checklist, type, category, tags, topic, platform, channel, date, deadline, schedule, calendar, duration, time, count, quantity, id, budget, cost, price, revenue, invoice, payment, percent, score, rating, metrics, data, notes, description, video, image, photo, audio, file, document, attachment, link, email, phone, comment, message, location, country, address, travel, campaign, marketing, sales, product, keyword, views, engagement, goal, launch, project, shop, discount, code, bug, security, version, book, education, language, weather, home, vehicle, important, private, archive, settings, idea, edit. Leave it out when the table's own name already says the topic (a 'Content calendar' picks its glyph from the name), and set it when the name is evocative rather than literal. Pass 'none' only if the user asked for no icon. Anything outside this list is ignored and the name is used instead, so use a word from it rather than inventing an icon name.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
url
For link and video. Must be a real URL that appeared in research results or that the user gave you — NEVER one you composed yourself. A url you can READ in a picture they attached counts as given: a board screenshot with 'vimeo.com/71977557' printed under its player is that url, and leaving the player empty beside a legible address drops something they handed you. One you infer from a title, complete from a domain, or remember is not. YouTube and Vimeo urls render as players.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
color_hex
For colour swatches.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
background_color
Background of the card itself. Works on note, todo, heading, ticket and wall; ignored elsewhere.
SET IT when the user asked for colour or a theme, and when the board already carries a pattern you are matching. OMIT it on a board you are building from nothing — a fresh board is themed through highlight_color on its walls instead, so the colour reads as an accent stripe rather than as a row of filled blocks nobody asked for. Omit it too when you are adding a few elements to a board that has no colour pattern of its own, and on cards inside a wall you have filled, which take their colour from that wall automatically.
Any hex is accepted and is snapped to the nearest of the canvas's twelve themes (red, terracotta, amber, olive, green, emerald, teal, blue, indigo, violet, magenta, graphite), so name the colour you actually mean — a brand's real hex is the right thing to pass. The snap is what lets the colour flip correctly between light and dark mode; a raw hex could not.
'transparent' is the exception to all of that and means something different: on a note or a todo it removes the card completely, leaving the text on the canvas with no box, no fill and no shadow. That is what a title or a label above a group of elements should look like, so use it for those without being asked. Ignored on every other type.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
font_size
For note and todo — how big the text is, in px. It sizes the note's markdown HEADING lines (the ones starting with #), or the whole note when it has none, so a note written as a '# Title' line plus a sentence under it gets a big title and a normally sized sentence from this one number. Normal note text is 16 and needs nothing set. Reach for it when text is meant to READ as a title: around 40 for the title of a whole board, 28 to 32 for a label above one section or row. A loose note is widened to keep its biggest line unwrapped; inside a wall the width stays the wall's.
Clear enough to supply this argument.
highlight_color
Accent stripe along the top. Note, todo, heading, ticket and wall; ignored elsewhere. On a WALL this is how you theme a board you are building from nothing: pass the palette colour here and leave background_color off, and the wall carries the theme as a stripe, with no fill on the wall and no tint on the cards inside it. A wall you ARE filling never needs it: it gets its theme's stripe automatically, exactly as the canvas's own wall theme does, so background_color is the whole job there. On a TICKET, pass it to ASK for a stripe — when the ticket also carries a background_color the shade is taken from that same theme whatever you pass, so the two can never disagree. On a NOTE, TODO or HEADING the stripe is MARKING, not theming: it is snapped to the nearest of the twelve accent stripes rather than derived from the card's fill, because the point of it is that these cards go together and the card's own theme is not that. Omit it when the element has no theme and the board carries no colour pattern.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
labels › items › text
Not provided
Missing description. Explain what this value means and how to supply it.
labels › items › color_hex
OMIT and a colour is chosen for you. Pass one to put the pill in the board's colour family: any hex is snapped to the nearest canvas palette colour (#CDDFDD, #D0E3F7, #DDD6F1, #F7DCE4, #F8DDD9, #F3E4C5, #EACFD5, #D9DEE1). A label the user already owns keeps its own colour.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
image_url
For image. A STORED IMAGE KEY: a generate_image or find_images result, or the imageUrl of a picture already on the board, read straight off a board read. Never a URL from anywhere else, which will not render. OMIT it to lay down an EMPTY frame: a placeholder the user can drop their own picture into, or ask you to fill later. Note that the two picture tools PLACE what they make themselves, so you rarely need this: pass it when you are building an element around a picture you already have — including one the board already holds, when the user points at it ("put the hero shot on each card"). Reusing the board's own picture costs nothing and is the same picture; finding or generating a second one is neither.
Clear enough to supply this argument.
file_name
For file only — the document's name WITH its extension, e.g. 'Values and manifesto.pdf'. The extension is what picks the card's icon, so a name without one lands as a generic document. Read it off the tile when you are copying a board; never invent a filename.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
date
Ticket due date, YYYY-MM-DD. Set it ONLY when the user stated a date or it follows directly from what they said; never infer or invent one.
Clear enough to supply this argument.
columns › items › anyOf › 1 › name
The column header text. Name it for what the column HOLDS, never for its cell_type — a person column is 'Owner' or 'Assignee', not 'Person'.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
columns › items › anyOf › 1 › cell_type
How the whole column behaves on the canvas. Pick the one that matches the data: currency for money, percent for rates, number for plain figures, datetime for dates (cells then open a date picker), duration for a LENGTH of time (a runtime, not a date), checkbox for done/not-done, rating for a 1-5 score, labels for category tags the user invents, status for progress through fixed stages, person for who OWNS or is ASSIGNED the row, url / email / phone for addresses the cell should link to — ONE address per row, written bare — text for anything else, including a column that cites SEVERAL sources per row. Omit for text.
status is a FIXED list — its cells must be one of: Not started, Blocked, In progress, In review, Done, Archived. For any other set of stages ('Scripting', 'Filming'), use labels.
person needs a board that HAS other people on it (get_board_people lists them): on a board whose only member is the user there is nobody to assign, so make an owner column text there and write the names as text.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
columns › items › anyOf › 1 › width
Column width in px (80-600, default 168). Set it only when the content clearly needs it — long text or notes ~280-320, tags ~240, dates/checkboxes can go narrower (~120).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
columns › items › anyOf › 1 › icon
The TOPIC of this column, which picks the icon shown in its header. USUALLY OMIT IT: the icon is chosen from the column's name automatically, so a well-named column is already right. Set it only when the name would not resolve on its own or reads as something else — e.g. a column called 'Fuji summit' that holds locations. Then pick the closest word from: name, title, owner, assignee, person, team, client, company, audience, character, identity, personality, background, relationship, story, status, stage, progress, priority, approval, done, task, checklist, type, category, tags, topic, platform, channel, date, deadline, schedule, calendar, duration, time, count, quantity, id, budget, cost, price, revenue, invoice, payment, percent, score, rating, metrics, data, notes, description, video, image, photo, audio, file, document, attachment, link, email, phone, comment, message, location, country, address, travel, campaign, marketing, sales, product, keyword, views, engagement, goal, launch, project, shop, discount, code, bug, security, version, book, education, language, weather, home, vehicle, important, private, archive, settings, idea, edit. Pass 'none' only if the user asked for no icon. Anything outside this list is ignored and the name is used instead, so use a word from it rather than inventing an icon name.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
rows
Table rows, each an array of cell values in column order — REQUIRED, in the SAME call as the columns: a table sent as a header alone is refused. Adding rows later costs a resend of the whole grid through update_element, so send the rows you have now. Write every cell as plain text — typed columns are converted for you: a date as YYYY-MM-DD, a checkbox as true/false, a duration as 1:30 or 90 or '1h 20m', a rating as a number, a labels cell as comma-separated tags, a status cell as one of its stage names, a person cell as the NAMES of people already on this board (comma-separated for two owners).
A column whose cells the canvas cannot represent — a name that belongs to nobody on the board, a word that is not one of the status stages — falls back to a plain TEXT column, so nothing you write is lost, but the column stops behaving as the type you asked for. Keep the values in the type's own vocabulary, and leave a cell empty rather than inventing a person (get_board_people lists who is on the board).
AN ADDRESS IN A TEXT CELL IS WRITTEN AS A NAMED LINK: `[Andes Handbook](https://www.andeshandbook.org/details/general/55)` shows the name and links it, so a Sources column reads as source names instead of wrapped url text. One per line, three at most per cell. A bare url still links, but the cell shortens it on screen, so name the ones you cite. A url COLUMN is the other shape and takes the bare address, never a named link.
Clear enough to supply this argument.
width
For wall only — how wide to build it, in px (478-1400). Omit it and the wall is the standard width, which is right for notes, to-dos and images. Set it when you are putting something inside that renders at a FIXED width and would otherwise be CLIPPED — a table is the case that matters, since it draws at the sum of its column widths and neither stretches nor shrinks to its wall. Pass the widest child's own width plus 28, the wall's inner padding. Ignored on every other type.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
layout_columns
For wall only — lay this wall's cards out on a GRID of this many columns instead of the single column. The canvas owns the geometry (ADR-0045): each card names its `cell`, a card without one flows in after the placed ones, and the wall reflows as content grows. Use it for content that reads as a grid — a gallery of images, a centrepiece over a row of swatches. Omit it for the ordinary single column of cards.
Clear enough to supply this argument.
cell › col
Column, 0 for the leftmost.
Clear enough to supply this argument.
cell › row
Row, 0 for the top one.
Clear enough to supply this argument.
cell › span
How many columns this card covers, for one wider than the cards under it.
Clear enough to supply this argument.
parent_uid
Put this element inside that wall. A folder, document or note ALWAYS needs one (or frame_uid): it goes in the wall whose subject it belongs to, or in a wall made for it. Omit only for a title note (background_color "transparent") and for other types that belong to no section.
Clear enough to supply this argument.
after_uid
Put this element directly UNDER that card in the same wall instead of at the bottom. Use it whenever what you are creating belongs to a card that is already there — the folder for the mountain that note describes, the picture of what that note covers — which is the normal case on a wall you did not build this turn. Pass the uid from get_whiteboard_elements; the wall is read off it, so parent_uid is not needed as well. Omit it while building a wall of your own, where creating in reading order is enough.
Clear enough to supply this argument.
frame_uid
Put this element inside that FRAME (a loose spatial container, elementType ToolFrame — pass its uid from get_whiteboard_elements). It is placed below the frame's existing contents. An element created at a position over a frame joins it on its own; this is for when the user names the frame as the destination.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "create_whiteboard_element",
"title": "Create whiteboard element",
"description": "Create ONE element on a whiteboard and return its uid. This is the only way to put anything on a board. Each call is one element, and every call whose inputs you already have goes in the SAME step: they land one after another in the order you write them, so the user still watches the board fill, and each step you do not take is one less re-read of the whole prompt. Wait for the next step only for a call that needs a uid another call returns.\n\nCompose whatever structure fits. A new wall and its cards are ONE build_section call; here, a card for a wall that already exists takes parent_uid set to that wall's uid. On a board that has walls, a folder, document or note goes in one; only a title note (background_color \"transparent\"), a picture or a shape sits loose.\n\nPosition and size are decided for you so nothing overlaps — there is no geometry to pass. Creates are immediate and not reviewed; the user can undo.\n\nA CHECKLIST IS ONE CARD: for a to-do list, make a single todo call with every task on its own line in `text`. Each line becomes a checkbox on that one card. A separate card per task is not a list, even when earlier turns in this conversation or cards already on the board look like that.\n\nNOT for changing something that already exists. Adding detail to, expanding, or rewriting an existing element is update_element on THAT element — never a new element beside it holding the addition, even if the board or earlier turns already show that pattern.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid",
"type"
],
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "For link and video. Must be a real URL that appeared in research results or that the user gave you — NEVER one you composed yourself. A url you can READ in a picture they attached counts as given: a board screenshot with 'vimeo.com/71977557' printed under its player is that url, and leaving the player empty beside a legible address drops something they handed you. One you infer from a title, complete from a domain, or remember is not. YouTube and Vimeo urls render as players."
},
"cell": {
"type": "object",
"required": [
"col",
"row"
],
"properties": {
"col": {
"type": "integer",
"maximum": 11,
"minimum": 0,
"description": "Column, 0 for the leftmost."
},
"row": {
"type": "integer",
"maximum": 23,
"minimum": 0,
"description": "Row, 0 for the top one."
},
"span": {
"type": "integer",
"maximum": 12,
"minimum": 1,
"description": "How many columns this card covers, for one wider than the cards under it."
}
},
"description": "For a card going into a GRID wall (parent_uid set, the wall carrying `layout_columns`): which cell it occupies. A card without one flows in after the placed ones. Ignored outside a grid wall — an ordinary wall lays its cards out top to bottom by itself.",
"additionalProperties": false
},
"date": {
"type": "string",
"pattern": "^(\\d{4}-\\d{2}-\\d{2})?$",
"description": "Ticket due date, YYYY-MM-DD. Set it ONLY when the user stated a date or it follows directly from what they said; never infer or invent one."
},
"rows": {
"type": "array",
"items": {
"type": "array",
"items": {
"type": "string"
}
},
"maxItems": 50,
"description": "Table rows, each an array of cell values in column order — REQUIRED, in the SAME call as the columns: a table sent as a header alone is refused. Adding rows later costs a resend of the whole grid through update_element, so send the rows you have now. Write every cell as plain text — typed columns are converted for you: a date as YYYY-MM-DD, a checkbox as true/false, a duration as 1:30 or 90 or '1h 20m', a rating as a number, a labels cell as comma-separated tags, a status cell as one of its stage names, a person cell as the NAMES of people already on this board (comma-separated for two owners).\nA column whose cells the canvas cannot represent — a name that belongs to nobody on the board, a word that is not one of the status stages — falls back to a plain TEXT column, so nothing you write is lost, but the column stops behaving as the type you asked for. Keep the values in the type's own vocabulary, and leave a cell empty rather than inventing a person (get_board_people lists who is on the board).\nAN ADDRESS IN A TEXT CELL IS WRITTEN AS A NAMED LINK: `[Andes Handbook](https://www.andeshandbook.org/details/general/55)` shows the name and links it, so a Sources column reads as source names instead of wrapped url text. One per line, three at most per cell. A bare url still links, but the cell shortens it on screen, so name the ones you cite. A url COLUMN is the other shape and takes the bare address, never a named link."
},
"text": {
"type": "string",
"description": "Text for note/todo/heading, the document body, or a colour's caption."
},
"type": {
"enum": [
"note",
"todo",
"heading",
"ticket",
"link",
"video",
"color",
"table",
"document",
"image",
"wall",
"folder",
"file",
"comment"
],
"type": "string",
"description": "What to create. Each renders differently AND is sized for a different amount of content — every one of them can hold the same words, so pick by how much the SUBJECT carries:\nnote — a card of prose, sized for a line to a few paragraphs: a thought, a summary, a short script or one scene of a longer one. If it would have to be scrolled to read, the subject has outgrown a note. With background_color 'transparent' it loses the card entirely and becomes text sitting on the canvas: that, plus font_size, is how a board or a row of walls gets its title.\ntodo — a card of tickable checkboxes, for short tasks and reminders that need no explaining. Put EVERY task in ONE call, one per line in `text`: each line becomes its own checkbox on a single checklist card. A card per task is wrong.\nheading — ONE line of text at a fixed size, no card. It holds a single line and nothing else: no second line, no sentence under the title, no size of its own. Use it only when the user asked for a heading; to title something you are building, use a transparent note.\nticket — ONE task or decision carrying real information: what needs doing, why, what is blocking it, what came back. It has its own title and description because it is meant to be opened and worked on over time. A task you can state in six words is a todo line instead. ALWAYS give a ticket its one chip in `labels` — the card draws an empty 'Label' slot without one, which reads as a ticket you left unfinished.\nlink — a clickable link card showing the page title and a short description.\nvideo — an embedded player; a YouTube or Vimeo url plays inline on the board. Omit the url and you get an EMPTY player with a url box on it, which is how you leave a slot for a video only the user has: their showreel, their channel, the cut they have not uploaded yet. Give it a title saying which video belongs there. Never invent a url to fill one.\nimage — a picture from generate_image, or an EMPTY frame when you omit image_url: a placeholder the user fills themselves or asks you to generate into later.\ncomment — a comment card: a remark ABOUT the board, in a bubble, rather than content on it. It is posted as the SIGNED-IN USER, because that is the only person you can post as — so when you are copying a comment someone else wrote, lead the text with who wrote it and when ('Michael, 11 June 2020: …'). Never write it as though the user said it.\nfile — a document card: a named slot for a real file, a PDF, a deck, a spreadsheet. It lands EMPTY, named by `file_name`, for the user to drop the document onto. Use it when a board you are copying shows a document tile, or when the user names a file that belongs on the board but has not sent it. For a file they ATTACHED to this message, use add_attachment_to_board instead — that puts the real file there, where this would leave them an empty tile over a document they already sent. Never use it to carry text — a file card holds no words, and prose belongs in a note.\ntable — a real grid with column headers and rows, editable cell by cell, for several things that share the same fields. Give every table a `title` (its heading, shown above the grid), a one-line `description` (the caption under it) and, when the title alone would not say the topic, a `table_icon` — a titled, captioned table reads as something; a bare grid of cells does not.\ncolor — ONE swatch carrying its hex and a name in `text`, for a single colour added to something that already exists, or for colours going INSIDE a wall (pass parent_uid). A whole PALETTE is create_color_palette instead, in one call: swatch after swatch through this tool cannot make a grid — each one lands to the right of the last and the palette runs off the canvas. A palette is never described in a note.\ndocument — a NEW rich-text document that opens full screen for long-form writing, its opening section in text — anything the user will READ rather than scan. To put a document that ALREADY exists on the board (one the user attached, or one you found), use add_document_to_board instead — this would create a blank one beside it.\nwall — a titled container holding one SECTION of the board, and mixed by nature: folders, notes, todos, links, a table, a couple of images can all sit in the same wall. Create it first, then create its cards with parent_uid set to its uid.\nfolder — a nested BOARD that opens as its own canvas, shown as a folder tile. For a subject with so much inside it that cards cannot hold it: one client, one production, one department is a whole board of its own. A wall groups cards in place, a folder holds a whole board behind it, and on an overview board the folder is the normal unit rather than the exception. Creating one returns opens_whiteboard_id: pass that as whiteboard_id on your next calls to build inside it, in this same turn."
},
"title": {
"type": "string",
"description": "Wall title, ticket title, link label, table name, document title, or folder name. A table is ALWAYS given one — it is the heading shown above the grid, and a table without it lands as an anonymous block of cells."
},
"width": {
"type": "integer",
"maximum": 1400,
"minimum": 478,
"description": "For wall only — how wide to build it, in px (478-1400). Omit it and the wall is the standard width, which is right for notes, to-dos and images. Set it when you are putting something inside that renders at a FIXED width and would otherwise be CLIPPED — a table is the case that matters, since it draws at the sum of its column widths and neither stretches nor shrinks to its wall. Pass the widest child's own width plus 28, the wall's inner padding. Ignored on every other type."
},
"labels": {
"type": "array",
"items": {
"type": "object",
"required": [
"text"
],
"properties": {
"text": {
"type": "string",
"maxLength": 40,
"minLength": 1
},
"color_hex": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$",
"description": "OMIT and a colour is chosen for you. Pass one to put the pill in the board's colour family: any hex is snapped to the nearest canvas palette colour (#CDDFDD, #D0E3F7, #DDD6F1, #F7DCE4, #F8DDD9, #F3E4C5, #EACFD5, #D9DEE1). A label the user already owns keeps its own colour."
}
},
"additionalProperties": false
},
"maxItems": 4,
"description": "Small tag pills shown ON the card, for a status or category. Works on note, todo, wall, image, colour, file and video — not on a heading, which shows none. A ticket shows ONE chip and is NEVER built without it: pass a single label and it becomes the ticket's own. Name it for what the ticket IS on this board — its kind, phase, owner or what it is waiting on (Booking, Permit, Blocked, Week 2, Research) — read off the ticket's own title and description rather than repeating them. A ticket with no label draws an empty 'Label' slot on the card, so omitting one is never the neutral choice."
},
"columns": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "object",
"required": [
"name"
],
"properties": {
"icon": {
"type": "string",
"description": "The TOPIC of this column, which picks the icon shown in its header. USUALLY OMIT IT: the icon is chosen from the column's name automatically, so a well-named column is already right. Set it only when the name would not resolve on its own or reads as something else — e.g. a column called 'Fuji summit' that holds locations. Then pick the closest word from: name, title, owner, assignee, person, team, client, company, audience, character, identity, personality, background, relationship, story, status, stage, progress, priority, approval, done, task, checklist, type, category, tags, topic, platform, channel, date, deadline, schedule, calendar, duration, time, count, quantity, id, budget, cost, price, revenue, invoice, payment, percent, score, rating, metrics, data, notes, description, video, image, photo, audio, file, document, attachment, link, email, phone, comment, message, location, country, address, travel, campaign, marketing, sales, product, keyword, views, engagement, goal, launch, project, shop, discount, code, bug, security, version, book, education, language, weather, home, vehicle, important, private, archive, settings, idea, edit. Pass 'none' only if the user asked for no icon. Anything outside this list is ignored and the name is used instead, so use a word from it rather than inventing an icon name."
},
"name": {
"type": "string",
"description": "The column header text. Name it for what the column HOLDS, never for its cell_type — a person column is 'Owner' or 'Assignee', not 'Person'."
},
"width": {
"type": "integer",
"maximum": 600,
"minimum": 80,
"description": "Column width in px (80-600, default 168). Set it only when the content clearly needs it — long text or notes ~280-320, tags ~240, dates/checkboxes can go narrower (~120)."
},
"cell_type": {
"enum": [
"text",
"number",
"currency",
"percent",
"datetime",
"duration",
"checkbox",
"rating",
"labels",
"status",
"person",
"url",
"email",
"phone",
"document"
],
"type": "string",
"description": "How the whole column behaves on the canvas. Pick the one that matches the data: currency for money, percent for rates, number for plain figures, datetime for dates (cells then open a date picker), duration for a LENGTH of time (a runtime, not a date), checkbox for done/not-done, rating for a 1-5 score, labels for category tags the user invents, status for progress through fixed stages, person for who OWNS or is ASSIGNED the row, url / email / phone for addresses the cell should link to — ONE address per row, written bare — text for anything else, including a column that cites SEVERAL sources per row. Omit for text.\nstatus is a FIXED list — its cells must be one of: Not started, Blocked, In progress, In review, Done, Archived. For any other set of stages ('Scripting', 'Filming'), use labels.\nperson needs a board that HAS other people on it (get_board_people lists them): on a board whose only member is the user there is nobody to assign, so make an owner column text there and write the names as text."
}
},
"additionalProperties": false
}
]
},
"maxItems": 8,
"minItems": 1,
"description": "Table columns — REQUIRED for a table, in the same call as its rows. Either a plain header string, or an object to also set the column's cell type and width."
},
"after_uid": {
"$ref": "#/properties/parent_uid",
"description": "Put this element directly UNDER that card in the same wall instead of at the bottom. Use it whenever what you are creating belongs to a card that is already there — the folder for the mountain that note describes, the picture of what that note covers — which is the normal case on a wall you did not build this turn. Pass the uid from get_whiteboard_elements; the wall is read off it, so parent_uid is not needed as well. Omit it while building a wall of your own, where creating in reading order is enough."
},
"color_hex": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$",
"description": "For colour swatches."
},
"file_name": {
"type": "string",
"description": "For file only — the document's name WITH its extension, e.g. 'Values and manifesto.pdf'. The extension is what picks the card's icon, so a name without one lands as a generic document. Read it off the tile when you are copying a board; never invent a filename."
},
"font_size": {
"type": "integer",
"maximum": 144,
"minimum": 8,
"description": "For note and todo — how big the text is, in px. It sizes the note's markdown HEADING lines (the ones starting with #), or the whole note when it has none, so a note written as a '# Title' line plus a sentence under it gets a big title and a normally sized sentence from this one number. Normal note text is 16 and needs nothing set. Reach for it when text is meant to READ as a title: around 40 for the title of a whole board, 28 to 32 for a label above one section or row. A loose note is widened to keep its biggest line unwrapped; inside a wall the width stays the wall's."
},
"frame_uid": {
"$ref": "#/properties/parent_uid",
"description": "Put this element inside that FRAME (a loose spatial container, elementType ToolFrame — pass its uid from get_whiteboard_elements). It is placed below the frame's existing contents. An element created at a position over a frame joins it on its own; this is for when the user names the frame as the destination."
},
"image_url": {
"type": "string",
"description": "For image. A STORED IMAGE KEY: a generate_image or find_images result, or the imageUrl of a picture already on the board, read straight off a board read. Never a URL from anywhere else, which will not render. OMIT it to lay down an EMPTY frame: a placeholder the user can drop their own picture into, or ask you to fill later. Note that the two picture tools PLACE what they make themselves, so you rarely need this: pass it when you are building an element around a picture you already have — including one the board already holds, when the user points at it (\"put the hero shot on each card\"). Reusing the board's own picture costs nothing and is the same picture; finding or generating a second one is neither."
},
"parent_uid": {
"type": "string",
"description": "Put this element inside that wall. A folder, document or note ALWAYS needs one (or frame_uid): it goes in the wall whose subject it belongs to, or in a wall made for it. Omit only for a title note (background_color \"transparent\") and for other types that belong to no section."
},
"table_icon": {
"type": "string",
"description": "For table only — the TOPIC of the table as a whole, which picks the icon shown beside its title. Pick the closest word from: name, title, owner, assignee, person, team, client, company, audience, character, identity, personality, background, relationship, story, status, stage, progress, priority, approval, done, task, checklist, type, category, tags, topic, platform, channel, date, deadline, schedule, calendar, duration, time, count, quantity, id, budget, cost, price, revenue, invoice, payment, percent, score, rating, metrics, data, notes, description, video, image, photo, audio, file, document, attachment, link, email, phone, comment, message, location, country, address, travel, campaign, marketing, sales, product, keyword, views, engagement, goal, launch, project, shop, discount, code, bug, security, version, book, education, language, weather, home, vehicle, important, private, archive, settings, idea, edit. Leave it out when the table's own name already says the topic (a 'Content calendar' picks its glyph from the name), and set it when the name is evocative rather than literal. Pass 'none' only if the user asked for no icon. Anything outside this list is ignored and the name is used instead, so use a word from it rather than inventing an icon name."
},
"description": {
"type": "string",
"description": "Ticket description, a link's one-line summary, or a table's caption — the line under the grid saying what it holds or how to read it. Give every table one short sentence."
},
"folder_icon": {
"type": "string",
"description": "For folder only — the TOPIC of the folder, which picks its icon. Pick the closest one from: research, idea, strategy, planning, tasks, notes, meeting, launch, archive, inbox, templates, settings, design, writing, brand, photo, video, music, audio, marketing, sales, finance, budget, invoice, analytics, legal, clients, team, support, product, shop, engineering, bugs, security, data, cloud, travel, food, health, fitness, home, education, science, nature, mountain, camping, weather, transport, gear, events, gifts, reading, location, global, favourites, important, private, time, folder. Leave it out and the icon is chosen from the folder's name. Pass 'none' ONLY if the user said they do not want an icon. Anything outside this list falls back to a plain folder, so use a word from it rather than inventing an icon name."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"folder_color": {
"type": "string",
"description": "For folder only — its tile colour, one of: tan, blue, rose, purple, steel, brown, red, navy, violet, slate, coral, orange. LEAVE IT OUT WHENEVER YOU ARE MAKING SEVERAL FOLDERS: each then takes a colour of its own from its name, which is what lets a set of tiles be told apart at a glance. One word repeated across the set — or borrowed from the wall they sit in — makes them all look the same. Pass it for a single folder the user asked to colour. Pass 'none' ONLY if the user asked for no colour."
},
"layout_columns": {
"type": "integer",
"maximum": 12,
"minimum": 2,
"description": "For wall only — lay this wall's cards out on a GRID of this many columns instead of the single column. The canvas owns the geometry (ADR-0045): each card names its `cell`, a card without one flows in after the placed ones, and the wall reflows as content grows. Use it for content that reads as a grid — a gallery of images, a centrepiece over a row of swatches. Omit it for the ordinary single column of cards."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
},
"highlight_color": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$",
"description": "Accent stripe along the top. Note, todo, heading, ticket and wall; ignored elsewhere. On a WALL this is how you theme a board you are building from nothing: pass the palette colour here and leave background_color off, and the wall carries the theme as a stripe, with no fill on the wall and no tint on the cards inside it. A wall you ARE filling never needs it: it gets its theme's stripe automatically, exactly as the canvas's own wall theme does, so background_color is the whole job there. On a TICKET, pass it to ASK for a stripe — when the ticket also carries a background_color the shade is taken from that same theme whatever you pass, so the two can never disagree. On a NOTE, TODO or HEADING the stripe is MARKING, not theming: it is snapped to the nearest of the twelve accent stripes rather than derived from the card's fill, because the point of it is that these cards go together and the card's own theme is not that. Omit it when the element has no theme and the board carries no colour pattern."
},
"background_color": {
"type": "string",
"pattern": "^(#[0-9a-fA-F]{6}|transparent)$",
"description": "Background of the card itself. Works on note, todo, heading, ticket and wall; ignored elsewhere.\nSET IT when the user asked for colour or a theme, and when the board already carries a pattern you are matching. OMIT it on a board you are building from nothing — a fresh board is themed through highlight_color on its walls instead, so the colour reads as an accent stripe rather than as a row of filled blocks nobody asked for. Omit it too when you are adding a few elements to a board that has no colour pattern of its own, and on cards inside a wall you have filled, which take their colour from that wall automatically.\nAny hex is accepted and is snapped to the nearest of the canvas's twelve themes (red, terracotta, amber, olive, green, emerald, teal, blue, indigo, violet, magenta, graphite), so name the colour you actually mean — a brand's real hex is the right thing to pass. The snap is what lets the colour flip correctly between light and dark mode; a raw hex could not.\n'transparent' is the exception to all of that and means something different: on a note or a todo it removes the card completely, leaving the text on the canvas with no box, no fill and no shadow. That is what a title or a label above a group of elements should look like, so use it for those without being asked. Ignored on every other type."
},
"folder_cover_image": {
"type": "string",
"description": "For folder only — a PICTURE on the tile instead of an icon, which is what a cover image or folder thumbnail means. Pass a stored image key: a board image's imageUrl, a generated image's image_url, a find_images result, or a gallery key. A folder shows a picture or an icon, never both, so this wins over folder_icon. Raw web urls (http/https/data/blob) are not stored images and are ignored — get the picture through find_images, which stores what it finds, or use one already on the board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description86/100
Put an EXISTING document on the board — the one the user attached, or one you found with list_documents. Use this whenever they ask to add/put/place a document they already have onto the board. Do NOT use create_whiteboard_element with type 'document' for this: that makes a NEW blank document instead of showing theirs. The document may live in another project; pass only its uid.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
document_uid
Uid of the document that already exists.
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
project_uid
Uid of the project to work in, from list_projects.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "add_document_to_board",
"title": "Add document to board",
"description": "Put an EXISTING document on the board — the one the user attached, or one you found with list_documents. Use this whenever they ask to add/put/place a document they already have onto the board. Do NOT use create_whiteboard_element with type 'document' for this: that makes a NEW blank document instead of showing theirs. The document may live in another project; pass only its uid.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"document_uid",
"project_uid"
],
"properties": {
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"document_uid": {
"type": "string",
"description": "Uid of the document that already exists."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description85/100
Draw an arrow between two elements on a board, to show flow or relationship. Both uids must be elements you have seen via get_whiteboard_elements. Connecting two walls standing side by side also widens the gap between them, so the line and any text on it have room.
The read gave you both elements' positions, so USE THEM: an element sitting BELOW another is joined bottom to top, and leaving the default right-to-left there draws a line that loops around the outside of its own card before it arrives.
The description explains the capability, when to use it, and what to expect.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
source_uid
Element uid the arrow starts from.
Clear enough to supply this argument.
target_uid
Element uid the arrow points to.
Clear enough to supply this argument.
label
Short text riding the middle of the line, for what neither end already says: how long the step takes ("2 weeks"), what has to be true before it starts ("on sign-off"), who it passes to. Two or three words. Leave it out when the order is the whole message, and never invent a duration.
Clear enough to supply this argument.
from_side
Which EDGE of the source the line leaves. Work it out from the two locations the board read gave you: the side facing the other element. Defaults to the right, which is only correct when the target is to the right.
Clear enough to supply this argument.
to_side
Which EDGE of the target the line arrives at, facing back the way it came. Defaults to the left.
Clear enough to supply this argument.
color
The line's colour as a hex. It colours the LINE AND ITS LABEL together — the chip takes the line's colour and works out its own text contrast. Omit for the ordinary dark line.
Clear enough to supply this argument.
dashed
TRUE for a dashed line, the convention for an optional, automatic or fallback path.
Clear enough to supply this argument.
line
The line's shape. Defaults to `curved`, which suits a loose link across a board. Use `stepped` for the right-angled connector a flowchart or an org chart draws between elements sitting on a grid, and `straight` for a plain line.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "connect_whiteboard_elements",
"title": "Connect whiteboard elements",
"description": "Draw an arrow between two elements on a board, to show flow or relationship. Both uids must be elements you have seen via get_whiteboard_elements. Connecting two walls standing side by side also widens the gap between them, so the line and any text on it have room.\nThe read gave you both elements' positions, so USE THEM: an element sitting BELOW another is joined bottom to top, and leaving the default right-to-left there draws a line that loops around the outside of its own card before it arrives.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"source_uid",
"target_uid",
"project_uid"
],
"properties": {
"line": {
"enum": [
"curved",
"straight",
"stepped"
],
"type": "string",
"description": "The line's shape. Defaults to `curved`, which suits a loose link across a board. Use `stepped` for the right-angled connector a flowchart or an org chart draws between elements sitting on a grid, and `straight` for a plain line."
},
"color": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$",
"description": "The line's colour as a hex. It colours the LINE AND ITS LABEL together — the chip takes the line's colour and works out its own text contrast. Omit for the ordinary dark line."
},
"label": {
"type": "string",
"maxLength": 24,
"description": "Short text riding the middle of the line, for what neither end already says: how long the step takes (\"2 weeks\"), what has to be true before it starts (\"on sign-off\"), who it passes to. Two or three words. Leave it out when the order is the whole message, and never invent a duration."
},
"dashed": {
"type": "boolean",
"description": "TRUE for a dashed line, the convention for an optional, automatic or fallback path."
},
"to_side": {
"enum": [
"left",
"right",
"top",
"bottom"
],
"type": "string",
"description": "Which EDGE of the target the line arrives at, facing back the way it came. Defaults to the left."
},
"from_side": {
"enum": [
"left",
"right",
"top",
"bottom"
],
"type": "string",
"description": "Which EDGE of the source the line leaves. Work it out from the two locations the board read gave you: the side facing the other element. Defaults to the right, which is only correct when the target is to the right."
},
"source_uid": {
"type": "string",
"description": "Element uid the arrow starts from."
},
"target_uid": {
"$ref": "#/properties/source_uid",
"description": "Element uid the arrow points to."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description95/100
Build one section of a board in one call: a wall and every card inside it, top to bottom, written in the order given. Send every section of a board this way; create_whiteboard_element is for loose items and for adding to a wall that already exists.
A card takes the fields of create_whiteboard_element (type, title, text, table columns and rows, labels) except parent_uid, after_uid, frame_uid, project_uid and whiteboard_uid, and is never a wall. Give the wall a width when a card is a table. A document's card may carry its opening section in text.
A card that fails leaves the others in place: the result lists each card's uid or error, so resend only a failed card with create_whiteboard_element and after_uid set to the card above it. A folder's contents go in a later call with whiteboard_uid set to the folder's board, from list_boards.
Describe the returned information so the agent knows whether it will answer the request.
Inputs88/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
wall › title
The wall's title.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
cards › items › type
As create_whiteboard_element's type.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "build_section",
"title": "Build section",
"description": "Build one section of a board in one call: a wall and every card inside it, top to bottom, written in the order given. Send every section of a board this way; create_whiteboard_element is for loose items and for adding to a wall that already exists.\n\nA card takes the fields of create_whiteboard_element (type, title, text, table columns and rows, labels) except parent_uid, after_uid, frame_uid, project_uid and whiteboard_uid, and is never a wall. Give the wall a width when a card is a table. A document's card may carry its opening section in text.\n\nA card that fails leaves the others in place: the result lists each card's uid or error, so resend only a failed card with create_whiteboard_element and after_uid set to the card above it. A folder's contents go in a later call with whiteboard_uid set to the folder's board, from list_boards.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid",
"wall",
"cards"
],
"properties": {
"wall": {
"type": "object",
"required": [
"title"
],
"properties": {
"title": {
"type": "string",
"minLength": 1,
"description": "The wall's title."
}
},
"description": "The wall: its title, plus any create_whiteboard_element field a wall takes (width, layout_columns, background_color).",
"additionalProperties": true
},
"cards": {
"type": "array",
"items": {
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"enum": [
"note",
"todo",
"heading",
"ticket",
"link",
"video",
"color",
"table",
"document",
"image",
"wall",
"folder",
"file",
"comment"
],
"type": "string",
"description": "As create_whiteboard_element's type."
}
},
"additionalProperties": true
},
"maxItems": 40,
"minItems": 1,
"description": "The wall's cards, top to bottom."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description88/100
Update an EXISTING element in place: its content and/or its styling. Applies immediately, exactly like the user editing on the canvas, and the user can undo it. content: for a note, todo or heading pass the full replacement text, markdown or HTML; for a ticket pass an object with the fields to change (title, description, label, labelColorHex, date); for other types pass an object patching the content keys you saw in get_whiteboard_elements A FOLDER takes {boardName} to rename it, {iconName} to change its icon and {iconColorHex} for its colour — for those two pass a WORD, not a hex or an icon name: iconName is one of [research, idea, strategy, planning, tasks, notes, meeting, launch, archive, inbox, templates, settings, design, writing, brand, photo, video, music, audio, marketing, sales, finance, budget, invoice, analytics, legal, clients, team, support, product, shop, engineering, bugs, security, data, cloud, travel, food, health, fitness, home, education, science, nature, mountain, camping, weather, transport, gear, events, gifts, reading, location, global, favourites, important, private, time, folder] and iconColorHex is one of [tan, blue, rose, purple, steel, brown, red, navy, violet, slate, coral, orange] (either can be 'none' to clear it), and {coverImage} to put a PICTURE on the tile instead of an icon — that is what a folder's cover image or thumbnail is. coverImage takes a stored image key (a board image's imageUrl, a generated image's image_url, or a gallery key), never a web url; 'none' clears it back to a plain tile. A folder shows a picture or an icon, never both, so setting iconName on a folder that has a cover replaces the picture. Changing only the colour leaves the icon or cover exactly as it is. An IMAGE (or AI image) takes {caption} — the line shown UNDER the picture, which is what "caption this" or "write a caption" means; a bare string is read as the caption too. An empty caption hides the caption row, and {showCaption: false} hides a caption while keeping its text. Nothing else about an image is edited here: its url, crop and source images are refused. Captions are not labels — labels are the parameter below. A TABLE is the one fiddly case: pass {tableData: "<json STRING>"} — tableData is stringified JSON, not an object — shaped {id, type:'table', data:{name, columns:[{id,name,type}], columnOrder:[id], rows:[{id, values:{<columnId>: cell}}], rowOrder:[id]}}. Keep the ids of everything you are not changing. Adding a column means appending to BOTH columns and columnOrder and adding that column's id to EVERY row's values; removing one means deleting it from all three; reordering means reordering columnOrder or rowOrder alone. Send the WHOLE table back, not a fragment. A column may also carry cellType ('number'|'currency'|'percent'|'datetime'|'duration'|'checkbox'|'rating'|'labels'|'status'|'person'|'url'|'email'|'phone'), width (px), icon (its header glyph) and, on a currency column, currency (an ISO code like 'EUR' picking the symbol its cells render in — the cells hold a bare number either way). data itself carries the table's own heading: title (the name shown ABOVE the grid), description (the caption under it) and icon (the glyph beside the title, a WORD from the same list as a column's). Renaming a table means changing data.title — data.name is the payload's internal label and is invisible on the canvas. PRESERVE every such field you are not deliberately changing, or you will silently reset the user's column types, widths, icons, captions and the table's own name. A column's icon is normally left off entirely, because the canvas derives one from the column's NAME — so renaming a column is usually all it takes to change its icon. To pin a specific one, set icon to a WORD from [name, title, owner, assignee, person, team, client, company, audience, character, identity, personality, background, relationship, story, status, stage, progress, priority, approval, done, task, checklist, type, category, tags, topic, platform, channel, date, deadline, schedule, calendar, duration, time, count, quantity, id, budget, cost, price, revenue, invoice, payment, percent, score, rating, metrics, data, notes, description, video, image, photo, audio, file, document, attachment, link, email, phone, comment, message, location, country, address, travel, campaign, marketing, sales, product, keyword, views, engagement, goal, launch, project, shop, discount, code, bug, security, version, book, education, language, weather, home, vehicle, important, private, archive, settings, idea, edit]; an unrecognised word is dropped and the name is used instead. Typed cells are written as WORDS and resolved here, so write what you mean and let the column hold it: a labels cell is its tags comma-separated ('Introductory, Technical classic'), a person cell the assignees' names, a status cell one of (Not started, Blocked, In progress, In review, Done, Archived), a rating a number 0-5, a checkbox 'true'/'false', a datetime 'YYYY-MM-DD', a duration what was typed ('1:30'). Labels are matched against the user's own palette and created when they are new; names are matched against this board's members. A cell you are not changing can be copied through in whatever form you were shown it. A column that cannot honour one of its values — a name nobody on the board has, a word that is not one of the stages — becomes a plain TEXT column so the words still show, so pick the cellType that fits what you are actually writing. attributes: patch using the canvas's OWN key names — backgroundColor, topBarHighlightColor (that is the accent stripe, NOT 'highlightColor'), width, height, borderColor, fontSize, textAlign. backgroundColor 'transparent' on a note or todo takes its card away and leaves the text on the canvas, which is what turns one into a title; '' puts the card back. labels: the element's complete new chip label set — it REPLACES what is there, so send the labels you are keeping too, and an empty array clears them. Notes and todos take 8; images, AI images, colours, files, videos and walls take 4, the same limit the canvas's label menu enforces. Nothing else takes chip labels: a ticket's single label is part of its content. Documents are edited with the document tools, never here; a deck's content with update_deck and a design page's html or name with update_html_app.
The description explains the capability, when to use it, and what to expect.
Inputs71/100
6 of 7 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
project_uid
Uid of the project to work in, from list_projects.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
element_uid
The element's uid, exactly as get_whiteboard_elements returned it.
Clear enough to supply this argument.
content
Full replacement HTML string, or an object of content fields to change.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
attributes
Attribute patch, e.g. {backgroundColor: '#FFF3C4'} or {width: 350}.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
labels › items › label
Not provided
Missing description. Explain what this value means and how to supply it.
labels › items › labelColorHex
OMIT and a colour is chosen for you. Pass one to put the pill in the board's colour family: any hex is snapped to the nearest canvas palette colour (#CDDFDD, #D0E3F7, #DDD6F1, #F7DCE4, #F8DDD9, #F3E4C5, #EACFD5, #D9DEE1). It is ignored entirely for a label the user already owns.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "update_element",
"title": "Update element",
"description": "Update an EXISTING element in place: its content and/or its styling. Applies immediately, exactly like the user editing on the canvas, and the user can undo it. content: for a note, todo or heading pass the full replacement text, markdown or HTML; for a ticket pass an object with the fields to change (title, description, label, labelColorHex, date); for other types pass an object patching the content keys you saw in get_whiteboard_elements A FOLDER takes {boardName} to rename it, {iconName} to change its icon and {iconColorHex} for its colour — for those two pass a WORD, not a hex or an icon name: iconName is one of [research, idea, strategy, planning, tasks, notes, meeting, launch, archive, inbox, templates, settings, design, writing, brand, photo, video, music, audio, marketing, sales, finance, budget, invoice, analytics, legal, clients, team, support, product, shop, engineering, bugs, security, data, cloud, travel, food, health, fitness, home, education, science, nature, mountain, camping, weather, transport, gear, events, gifts, reading, location, global, favourites, important, private, time, folder] and iconColorHex is one of [tan, blue, rose, purple, steel, brown, red, navy, violet, slate, coral, orange] (either can be 'none' to clear it), and {coverImage} to put a PICTURE on the tile instead of an icon — that is what a folder's cover image or thumbnail is. coverImage takes a stored image key (a board image's imageUrl, a generated image's image_url, or a gallery key), never a web url; 'none' clears it back to a plain tile. A folder shows a picture or an icon, never both, so setting iconName on a folder that has a cover replaces the picture. Changing only the colour leaves the icon or cover exactly as it is. An IMAGE (or AI image) takes {caption} — the line shown UNDER the picture, which is what \"caption this\" or \"write a caption\" means; a bare string is read as the caption too. An empty caption hides the caption row, and {showCaption: false} hides a caption while keeping its text. Nothing else about an image is edited here: its url, crop and source images are refused. Captions are not labels — labels are the parameter below. A TABLE is the one fiddly case: pass {tableData: \"<json STRING>\"} — tableData is stringified JSON, not an object — shaped {id, type:'table', data:{name, columns:[{id,name,type}], columnOrder:[id], rows:[{id, values:{<columnId>: cell}}], rowOrder:[id]}}. Keep the ids of everything you are not changing. Adding a column means appending to BOTH columns and columnOrder and adding that column's id to EVERY row's values; removing one means deleting it from all three; reordering means reordering columnOrder or rowOrder alone. Send the WHOLE table back, not a fragment. A column may also carry cellType ('number'|'currency'|'percent'|'datetime'|'duration'|'checkbox'|'rating'|'labels'|'status'|'person'|'url'|'email'|'phone'), width (px), icon (its header glyph) and, on a currency column, currency (an ISO code like 'EUR' picking the symbol its cells render in — the cells hold a bare number either way). data itself carries the table's own heading: title (the name shown ABOVE the grid), description (the caption under it) and icon (the glyph beside the title, a WORD from the same list as a column's). Renaming a table means changing data.title — data.name is the payload's internal label and is invisible on the canvas. PRESERVE every such field you are not deliberately changing, or you will silently reset the user's column types, widths, icons, captions and the table's own name. A column's icon is normally left off entirely, because the canvas derives one from the column's NAME — so renaming a column is usually all it takes to change its icon. To pin a specific one, set icon to a WORD from [name, title, owner, assignee, person, team, client, company, audience, character, identity, personality, background, relationship, story, status, stage, progress, priority, approval, done, task, checklist, type, category, tags, topic, platform, channel, date, deadline, schedule, calendar, duration, time, count, quantity, id, budget, cost, price, revenue, invoice, payment, percent, score, rating, metrics, data, notes, description, video, image, photo, audio, file, document, attachment, link, email, phone, comment, message, location, country, address, travel, campaign, marketing, sales, product, keyword, views, engagement, goal, launch, project, shop, discount, code, bug, security, version, book, education, language, weather, home, vehicle, important, private, archive, settings, idea, edit]; an unrecognised word is dropped and the name is used instead. Typed cells are written as WORDS and resolved here, so write what you mean and let the column hold it: a labels cell is its tags comma-separated ('Introductory, Technical classic'), a person cell the assignees' names, a status cell one of (Not started, Blocked, In progress, In review, Done, Archived), a rating a number 0-5, a checkbox 'true'/'false', a datetime 'YYYY-MM-DD', a duration what was typed ('1:30'). Labels are matched against the user's own palette and created when they are new; names are matched against this board's members. A cell you are not changing can be copied through in whatever form you were shown it. A column that cannot honour one of its values — a name nobody on the board has, a word that is not one of the stages — becomes a plain TEXT column so the words still show, so pick the cellType that fits what you are actually writing. attributes: patch using the canvas's OWN key names — backgroundColor, topBarHighlightColor (that is the accent stripe, NOT 'highlightColor'), width, height, borderColor, fontSize, textAlign. backgroundColor 'transparent' on a note or todo takes its card away and leaves the text on the canvas, which is what turns one into a title; '' puts the card back. labels: the element's complete new chip label set — it REPLACES what is there, so send the labels you are keeping too, and an empty array clears them. Notes and todos take 8; images, AI images, colours, files, videos and walls take 4, the same limit the canvas's label menu enforces. Nothing else takes chip labels: a ticket's single label is part of its content. Documents are edited with the document tools, never here; a deck's content with update_deck and a design page's html or name with update_html_app.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid",
"element_uid"
],
"properties": {
"labels": {
"type": "array",
"items": {
"type": "object",
"required": [
"label"
],
"properties": {
"label": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"labelColorHex": {
"type": "string",
"maxLength": 9,
"description": "OMIT and a colour is chosen for you. Pass one to put the pill in the board's colour family: any hex is snapped to the nearest canvas palette colour (#CDDFDD, #D0E3F7, #DDD6F1, #F7DCE4, #F8DDD9, #F3E4C5, #EACFD5, #D9DEE1). It is ignored entirely for a label the user already owns."
}
},
"additionalProperties": false
},
"maxItems": 8,
"description": "Complete new label set; an empty array removes all labels."
},
"content": {
"anyOf": [
{
"type": "string"
},
{
"type": "object",
"additionalProperties": {}
}
],
"description": "Full replacement HTML string, or an object of content fields to change."
},
"attributes": {
"type": "object",
"description": "Attribute patch, e.g. {backgroundColor: '#FFF3C4'} or {width: 350}.",
"additionalProperties": {}
},
"element_uid": {
"type": "string",
"minLength": 1,
"description": "The element's uid, exactly as get_whiteboard_elements returned it."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description89/100
Move an EXISTING element: into a wall (parent_uid + parent_order_index), out of a wall (parent_uid: '' plus a canvas location), reordering within a wall, or repositioning any element (location only, in board coordinates). Frame membership follows the destination on its own — land inside a frame to join it, outside to leave it. Applies immediately, like the user dragging it; the user can undo.
The description explains the capability, when to use it, and what to expect.
Inputs71/100
5 of 7 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
element_uid
The element's uid, exactly as get_whiteboard_elements returned it.
Clear enough to supply this argument.
parent_uid
New parent container uid; empty string moves the element out onto the canvas.
Clear enough to supply this argument.
parent_order_index
Position among the parent's children, 0-based. Omit to append at the bottom when entering a different wall.
Clear enough to supply this argument.
location › x
Not provided
Missing description. Explain what this value means and how to supply it.
location › y
Not provided
Missing description. Explain what this value means and how to supply it.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "move_element",
"title": "Move element",
"description": "Move an EXISTING element: into a wall (parent_uid + parent_order_index), out of a wall (parent_uid: '' plus a canvas location), reordering within a wall, or repositioning any element (location only, in board coordinates). Frame membership follows the destination on its own — land inside a frame to join it, outside to leave it. Applies immediately, like the user dragging it; the user can undo.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid",
"element_uid"
],
"properties": {
"location": {
"type": "object",
"required": [
"x",
"y"
],
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
}
},
"description": "Canvas coordinates; required when moving out of a container.",
"additionalProperties": false
},
"parent_uid": {
"type": "string",
"description": "New parent container uid; empty string moves the element out onto the canvas."
},
"element_uid": {
"type": "string",
"minLength": 1,
"description": "The element's uid, exactly as get_whiteboard_elements returned it."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
},
"parent_order_index": {
"type": "integer",
"minimum": 0,
"description": "Position among the parent's children, 0-based. Omit to append at the bottom when entering a different wall."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description94/100
Change the text riding on arrows already on the board, or clear it with an empty string. This is the answer to 'put the durations on those arrows' or 'make that one 6 weeks'. Do NOT delete the arrow and draw a new one: redrawing loses the curve the user dragged into it and gives the connection a new uid. edge uids come from get_whiteboard_edges or connect_whiteboard_elements' result — element uids are not edge uids.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
connections › items › edge_uid
Uid of the arrow, exactly as a read returned it.
Clear enough to supply this argument.
connections › items › text
What the arrow should say — two or three words, for what neither end already says. Empty string clears it.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "set_connection_text",
"title": "Set connection text",
"description": "Change the text riding on arrows already on the board, or clear it with an empty string. This is the answer to 'put the durations on those arrows' or 'make that one 6 weeks'. Do NOT delete the arrow and draw a new one: redrawing loses the curve the user dragged into it and gives the connection a new uid. edge uids come from get_whiteboard_edges or connect_whiteboard_elements' result — element uids are not edge uids.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"connections",
"project_uid"
],
"properties": {
"connections": {
"type": "array",
"items": {
"type": "object",
"required": [
"edge_uid",
"text"
],
"properties": {
"text": {
"type": "string",
"maxLength": 24,
"description": "What the arrow should say — two or three words, for what neither end already says. Empty string clears it."
},
"edge_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the arrow, exactly as a read returned it."
}
},
"additionalProperties": false
},
"maxItems": 20,
"minItems": 1
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description93/100
Create ONE native chart element (bar, line or pie) on the board. Data and styling live in the element; the canvas renders it as a real interactive chart. Use real values only — never invented numbers. This is the RIGHT answer to most requests to chart something: one fact is one chart, and the same measure across several categories is this tool called once per category (small multiples read better than one crowded chart). Reach for create_dashboard only when the ask is an overview of several different measures. ALWAYS send value_format when the values are money or percentages — without it they render as bare numbers — and add a caption saying what the chart shows whenever you have a finding worth stating.
BUILDING FROM A PICTURE THE USER PASTED: what carries across is the DATA, the category and series names, the chart type, the bar direction and the series colours. Nothing else does — the background, typography, gridlines, spacing and legend placement are the canvas's own and are not settable here. So say what you actually matched. Announcing a chart as being in "the same style" beside a screenshot it visibly does not resemble is the one claim the user checks immediately, and it costs you the ones they cannot check.
The description explains the capability, when to use it, and what to expect.
Inputs63/100
24 of 36 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
chart_type
Not provided
Missing description. Explain what this value means and how to supply it.
title
The chart's title, as short as it can be and still be right — about 40 characters. It is read at the width of a chat panel, not a slide.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
subtitle
One muted line ABOVE the chart saying what it plots and over what — the reading instruction, not the finding ("Top PRs ranked by lines added", "Share of the 50 cancellations, by stated reason"). Say where the numbers came from when that is not obvious from the title. The finding goes in `caption`, below.
Clear enough to supply this argument.
caption
One short line under the chart saying what it SHOWS — the finding, not the title again ("Churn fell every month after March", "Q4 cleared the target on its own"). This is what makes a chart read as an answer instead of a picture; add one whenever you have something to say about the data. ONE line, and it is drawn on one line: past about 90 characters it is clipped rather than wrapped.
Clear enough to supply this argument.
x_label
Not provided
Missing description. Explain what this value means and how to supply it.
y_label
Not provided
Missing description. Explain what this value means and how to supply it.
categories
Bar/line: the x-axis categories. WRITE THEM SHORT — two or three words, about 20 characters. They are drawn beside every bar at a small size, so "What the agent puts on the board" takes half the chart's width from the bars and then ellipsises anyway, while "Board creation" says the same thing. Summarise; do not truncate mid-phrase, and never abbreviate to something the reader cannot decode. The title and the caption carry the context the labels no longer need.
Clear enough to supply this argument.
series › items › name
Not provided
Missing description. Explain what this value means and how to supply it.
series › items › data
Values, one per category (bar/line/radar/metric).
Clear enough to supply this argument.
series › items › points › items › x
Not provided
Missing description. Explain what this value means and how to supply it.
series › items › points › items › y
Not provided
Missing description. Explain what this value means and how to supply it.
slices › items › label
Not provided
Missing description. Explain what this value means and how to supply it.
slices › items › value
Not provided
Missing description. Explain what this value means and how to supply it.
value
Gauge: the numeric value. Metric: the headline value shown big.
Clear enough to supply this argument.
data
Metric only: the sparkline values. Omit it for a figure with no history — the tile then prints the number on its own. Never invent a series to fill it.
Clear enough to supply this argument.
metrics
Radar only: the axis names.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
colors
Optional palette; OMIT IT unless the colour means something. The default is the house blue, and one measure across categories is one colour — a chart whose bars are six different colours is saying they are six different things. Send colours when they carry a fact: shades of the same blue to rank or to sequence, or a muted palette with ONE accent to point at the outlier. On a single-series bar chart they colour the bars one by one; with `groups` they index the GROUPS.
Clear enough to supply this argument.
groups
Bar only, ONE series: the group each category belongs to, same length and order as `categories` (e.g. ["tool exists","tool exists","no tool",…]). Bars are coloured by group and the legend names the groups. Use this whenever the categories split into kinds — it is the alternative to faking the same picture with one series per group padded with zeros, which doubles the bars and prints a 0 on every empty one. `colors` indexes the GROUPS here, so a two-group chart takes exactly two colours.
Clear enough to supply this argument.
layout
Bar only.
Clear enough to supply this argument.
stack
Bar only.
Clear enough to supply this argument.
scale
Bar/line: the VALUE axis scale, default linear. Send "log" when the values span orders of magnitude — a funnel of 396 → 15 → 8 → 2 → 1 draws every step after the first as a sliver on a linear axis, which hides the very drop the chart is about. Every value must be zero or more, and say so in the caption ("note the log axis") because a reader assumes linear.
Clear enough to supply this argument.
stats › items › label
What the number is ("Distinct users").
Clear enough to supply this argument.
stats › items › value
The number as it should READ ("3.8%", "396", "53%").
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
show_values
Bar only: print each bar's value on it. Do this for a ranking or any chart of about eight bars or fewer — it is what makes a bar chart readable without an axis. Leave it off when many grouped bars would crowd.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
reference › value
Not provided
Missing description. Explain what this value means and how to supply it.
reference › label
Not provided
Missing description. Explain what this value means and how to supply it.
value_format › style
Not provided
Missing description. Explain what this value means and how to supply it.
value_format › currency
ISO 4217, e.g. 'GBP', 'USD'.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
value_format › decimals
Not provided
Missing description. Explain what this value means and how to supply it.
value_format › compact
Abbreviate: 1.2K, 3.4M.
Clear enough to supply this argument.
value_min
Gauge only: the low end of the scale. ALWAYS send min and max when the range is not 0-100 — NPS runs -100 to 100, a CSAT score 0 to 5. Without them the ring is drawn against 0-100 and is simply wrong.
Clear enough to supply this argument.
value_max
Gauge only: the high end of the scale.
Clear enough to supply this argument.
value_label
Gauge: the caption under the number. Metric: the small label under the headline value (e.g. "vs last quarter").
Clear enough to supply this argument.
delta
Metric only: the fractional change behind the trend badge (0.124 renders +12.4%). Send it when you know it; otherwise it is inferred from the sparkline's first and last points.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "create_chart",
"title": "Create chart",
"description": "Create ONE native chart element (bar, line or pie) on the board. Data and styling live in the element; the canvas renders it as a real interactive chart. Use real values only — never invented numbers. This is the RIGHT answer to most requests to chart something: one fact is one chart, and the same measure across several categories is this tool called once per category (small multiples read better than one crowded chart). Reach for create_dashboard only when the ask is an overview of several different measures. ALWAYS send value_format when the values are money or percentages — without it they render as bare numbers — and add a caption saying what the chart shows whenever you have a finding worth stating.\n\nBUILDING FROM A PICTURE THE USER PASTED: what carries across is the DATA, the category and series names, the chart type, the bar direction and the series colours. Nothing else does — the background, typography, gridlines, spacing and legend placement are the canvas's own and are not settable here. So say what you actually matched. Announcing a chart as being in \"the same style\" beside a screenshot it visibly does not resemble is the one claim the user checks immediately, and it costs you the ones they cannot check.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"chart_type",
"title",
"project_uid"
],
"properties": {
"data": {
"type": "array",
"items": {
"type": "number"
},
"description": "Metric only: the sparkline values. Omit it for a figure with no history — the tile then prints the number on its own. Never invent a series to fill it."
},
"delta": {
"type": "number",
"description": "Metric only: the fractional change behind the trend badge (0.124 renders +12.4%). Send it when you know it; otherwise it is inferred from the sparkline's first and last points."
},
"scale": {
"enum": [
"linear",
"log"
],
"type": "string",
"description": "Bar/line: the VALUE axis scale, default linear. Send \"log\" when the values span orders of magnitude — a funnel of 396 → 15 → 8 → 2 → 1 draws every step after the first as a sliver on a linear axis, which hides the very drop the chart is about. Every value must be zero or more, and say so in the caption (\"note the log axis\") because a reader assumes linear."
},
"stack": {
"enum": [
"none",
"total",
"percent"
],
"type": "string",
"description": "Bar only."
},
"stats": {
"type": "array",
"items": {
"type": "object",
"required": [
"label",
"value"
],
"properties": {
"label": {
"type": "string",
"maxLength": 28,
"minLength": 1,
"description": "What the number is (\"Distinct users\")."
},
"value": {
"type": "string",
"maxLength": 12,
"minLength": 1,
"description": "The number as it should READ (\"3.8%\", \"396\", \"53%\")."
}
},
"additionalProperties": false
},
"maxItems": 4,
"description": "Up to 4 headline figures printed large across the top of the chart. Use them for the numbers a reader would otherwise have to work out off the bars — a total, a conversion rate, a share — not for restating the tallest bar. The value is display text, so it can carry a unit the chart itself does not (a chart of user counts headlined by a percentage)."
},
"title": {
"type": "string",
"minLength": 1,
"description": "The chart's title, as short as it can be and still be right — about 40 characters. It is read at the width of a chat panel, not a slide."
},
"value": {
"type": [
"number",
"string"
],
"description": "Gauge: the numeric value. Metric: the headline value shown big."
},
"colors": {
"type": "array",
"items": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$"
},
"description": "Optional palette; OMIT IT unless the colour means something. The default is the house blue, and one measure across categories is one colour — a chart whose bars are six different colours is saying they are six different things. Send colours when they carry a fact: shades of the same blue to rank or to sequence, or a muted palette with ONE accent to point at the outlier. On a single-series bar chart they colour the bars one by one; with `groups` they index the GROUPS."
},
"groups": {
"type": "array",
"items": {
"type": "string"
},
"description": "Bar only, ONE series: the group each category belongs to, same length and order as `categories` (e.g. [\"tool exists\",\"tool exists\",\"no tool\",…]). Bars are coloured by group and the legend names the groups. Use this whenever the categories split into kinds — it is the alternative to faking the same picture with one series per group padded with zeros, which doubles the bars and prints a 0 on every empty one. `colors` indexes the GROUPS here, so a two-group chart takes exactly two colours."
},
"layout": {
"enum": [
"vertical",
"horizontal"
],
"type": "string",
"description": "Bar only."
},
"series": {
"type": "array",
"items": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "number"
},
"description": "Values, one per category (bar/line/radar/metric)."
},
"name": {
"type": "string",
"default": ""
},
"points": {
"type": "array",
"items": {
"type": "object",
"required": [
"x",
"y"
],
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
}
},
"additionalProperties": false
},
"description": "Scatter only: the series' points."
}
},
"additionalProperties": false
}
},
"slices": {
"type": "array",
"items": {
"type": "object",
"required": [
"label",
"value"
],
"properties": {
"label": {
"type": "string",
"minLength": 1
},
"value": {
"type": "number"
}
},
"additionalProperties": false
},
"description": "Pie only. Labels as short as the categories above — two or three words."
},
"caption": {
"type": "string",
"maxLength": 120,
"description": "One short line under the chart saying what it SHOWS — the finding, not the title again (\"Churn fell every month after March\", \"Q4 cleared the target on its own\"). This is what makes a chart read as an answer instead of a picture; add one whenever you have something to say about the data. ONE line, and it is drawn on one line: past about 90 characters it is clipped rather than wrapped."
},
"metrics": {
"type": "array",
"items": {
"type": "string"
},
"description": "Radar only: the axis names."
},
"x_label": {
"type": "string"
},
"y_label": {
"type": "string"
},
"subtitle": {
"type": "string",
"maxLength": 90,
"description": "One muted line ABOVE the chart saying what it plots and over what — the reading instruction, not the finding (\"Top PRs ranked by lines added\", \"Share of the 50 cancellations, by stated reason\"). Say where the numbers came from when that is not obvious from the title. The finding goes in `caption`, below."
},
"reference": {
"type": "object",
"required": [
"value"
],
"properties": {
"label": {
"type": "string",
"maxLength": 40
},
"value": {
"type": "number"
}
},
"description": "Bar/line: a target or benchmark drawn as a line across the plot, e.g. {value: 900000, label: \"£900k target\"}. When the point is \"how are we doing against X\", this IS the answer — put the target on the chart rather than adding a separate gauge tile.",
"additionalProperties": false
},
"value_max": {
"type": "number",
"description": "Gauge only: the high end of the scale."
},
"value_min": {
"type": "number",
"description": "Gauge only: the low end of the scale. ALWAYS send min and max when the range is not 0-100 — NPS runs -100 to 100, a CSAT score 0 to 5. Without them the ring is drawn against 0-100 and is simply wrong."
},
"categories": {
"type": "array",
"items": {
"type": "string"
},
"description": "Bar/line: the x-axis categories. WRITE THEM SHORT — two or three words, about 20 characters. They are drawn beside every bar at a small size, so \"What the agent puts on the board\" takes half the chart's width from the bars and then ellipsises anyway, while \"Board creation\" says the same thing. Summarise; do not truncate mid-phrase, and never abbreviate to something the reader cannot decode. The title and the caption carry the context the labels no longer need."
},
"chart_type": {
"enum": [
"bar",
"line",
"pie"
],
"type": "string"
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"show_values": {
"type": "boolean",
"description": "Bar only: print each bar's value on it. Do this for a ranking or any chart of about eight bars or fewer — it is what makes a bar chart readable without an axis. Leave it off when many grouped bars would crowd."
},
"value_label": {
"type": "string",
"maxLength": 60,
"description": "Gauge: the caption under the number. Metric: the small label under the headline value (e.g. \"vs last quarter\")."
},
"value_format": {
"type": "object",
"properties": {
"style": {
"enum": [
"number",
"currency",
"percent"
],
"type": "string"
},
"compact": {
"type": "boolean",
"description": "Abbreviate: 1.2K, 3.4M."
},
"currency": {
"type": "string",
"maxLength": 3,
"minLength": 3,
"description": "ISO 4217, e.g. 'GBP', 'USD'."
},
"decimals": {
"type": "integer",
"maximum": 4,
"minimum": 0
}
},
"description": "How to write the numbers, on the axis, the labels and the tooltip. Send it whenever the values are money or percentages — without it they render as bare numbers.",
"additionalProperties": false
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description92/100
Create a whole dashboard: chart tiles laid out in a justified grid the tool computes. You design WHICH tiles share a row and their relative spans; the tool owns the pixels. Rows render top to bottom; a good dashboard opens with a row of 3-4 metric tiles, then chart rows of 1-3 tiles. Max 16 tiles. Real values only. USE IT WHEN THE ASK IS AN OVERVIEW — a dashboard, a report, a summary, 'how are we doing' — or when four or more different measures are worth showing at once. A request for a chart, a graph or a picture of ONE thing is create_chart, not a grid with that chart buried in it. Never invent a tile to fill the grid: if the data holds four things worth showing, the dashboard is four tiles. ALWAYS send value_format on tiles whose values are money or percentages, and give a gauge its real value_min/value_max (NPS runs -100 to 100) — the ring is drawn against 0-100 otherwise and is wrong.
The description explains the capability, when to use it, and what to expect.
Inputs56/100
25 of 37 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
rows › items › tiles › items › kind
Not provided
Missing description. Explain what this value means and how to supply it.
rows › items › tiles › items › span
Relative width within the row (default 1).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
rows › items › tiles › items › title
The chart's title, as short as it can be and still be right — about 40 characters. It is read at the width of a chat panel, not a slide.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
rows › items › tiles › items › subtitle
One muted line ABOVE the chart saying what it plots and over what — the reading instruction, not the finding ("Top PRs ranked by lines added", "Share of the 50 cancellations, by stated reason"). Say where the numbers came from when that is not obvious from the title. The finding goes in `caption`, below.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
rows › items › tiles › items › caption
One short line under the chart saying what it SHOWS — the finding, not the title again ("Churn fell every month after March", "Q4 cleared the target on its own"). This is what makes a chart read as an answer instead of a picture; add one whenever you have something to say about the data. ONE line, and it is drawn on one line: past about 90 characters it is clipped rather than wrapped.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
rows › items › tiles › items › x_label
Not provided
Missing description. Explain what this value means and how to supply it.
rows › items › tiles › items › y_label
Not provided
Missing description. Explain what this value means and how to supply it.
rows › items › tiles › items › categories
Bar/line: the x-axis categories. WRITE THEM SHORT — two or three words, about 20 characters. They are drawn beside every bar at a small size, so "What the agent puts on the board" takes half the chart's width from the bars and then ellipsises anyway, while "Board creation" says the same thing. Summarise; do not truncate mid-phrase, and never abbreviate to something the reader cannot decode. The title and the caption carry the context the labels no longer need.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
rows › items › tiles › items › series › items › name
Not provided
Missing description. Explain what this value means and how to supply it.
rows › items › tiles › items › series › items › data
Values, one per category (bar/line/radar/metric).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
rows › items › tiles › items › series › items › points › items › x
Not provided
Missing description. Explain what this value means and how to supply it.
rows › items › tiles › items › series › items › points › items › y
Not provided
Missing description. Explain what this value means and how to supply it.
Missing description. Explain what this value means and how to supply it.
rows › items › tiles › items › value
Gauge: the numeric value. Metric: the headline value shown big.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
rows › items › tiles › items › data
Metric only: the sparkline values. Omit it for a figure with no history — the tile then prints the number on its own. Never invent a series to fill it.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
rows › items › tiles › items › metrics
Radar only: the axis names.
Clear enough to supply this argument.
rows › items › tiles › items › colors
Optional palette; OMIT IT unless the colour means something. The default is the house blue, and one measure across categories is one colour — a chart whose bars are six different colours is saying they are six different things. Send colours when they carry a fact: shades of the same blue to rank or to sequence, or a muted palette with ONE accent to point at the outlier. On a single-series bar chart they colour the bars one by one; with `groups` they index the GROUPS.
Clear enough to supply this argument.
rows › items › tiles › items › groups
Bar only, ONE series: the group each category belongs to, same length and order as `categories` (e.g. ["tool exists","tool exists","no tool",…]). Bars are coloured by group and the legend names the groups. Use this whenever the categories split into kinds — it is the alternative to faking the same picture with one series per group padded with zeros, which doubles the bars and prints a 0 on every empty one. `colors` indexes the GROUPS here, so a two-group chart takes exactly two colours.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
rows › items › tiles › items › layout
Bar only.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
rows › items › tiles › items › stack
Bar only.
Clear enough to supply this argument.
rows › items › tiles › items › scale
Bar/line: the VALUE axis scale, default linear. Send "log" when the values span orders of magnitude — a funnel of 396 → 15 → 8 → 2 → 1 draws every step after the first as a sliver on a linear axis, which hides the very drop the chart is about. Every value must be zero or more, and say so in the caption ("note the log axis") because a reader assumes linear.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
The number as it should READ ("3.8%", "396", "53%").
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
rows › items › tiles › items › show_values
Bar only: print each bar's value on it. Do this for a ranking or any chart of about eight bars or fewer — it is what makes a bar chart readable without an axis. Leave it off when many grouped bars would crowd.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
rows › items › tiles › items › reference › value
Not provided
Missing description. Explain what this value means and how to supply it.
rows › items › tiles › items › reference › label
Not provided
Missing description. Explain what this value means and how to supply it.
Gauge only: the low end of the scale. ALWAYS send min and max when the range is not 0-100 — NPS runs -100 to 100, a CSAT score 0 to 5. Without them the ring is drawn against 0-100 and is simply wrong.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
rows › items › tiles › items › value_max
Gauge only: the high end of the scale.
Clear enough to supply this argument.
rows › items › tiles › items › value_label
Gauge: the caption under the number. Metric: the small label under the headline value (e.g. "vs last quarter").
Clear enough to supply this argument.
rows › items › tiles › items › delta
Metric only: the fractional change behind the trend badge (0.124 renders +12.4%). Send it when you know it; otherwise it is inferred from the sparkline's first and last points.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "create_dashboard",
"title": "Create dashboard",
"description": "Create a whole dashboard: chart tiles laid out in a justified grid the tool computes. You design WHICH tiles share a row and their relative spans; the tool owns the pixels. Rows render top to bottom; a good dashboard opens with a row of 3-4 metric tiles, then chart rows of 1-3 tiles. Max 16 tiles. Real values only. USE IT WHEN THE ASK IS AN OVERVIEW — a dashboard, a report, a summary, 'how are we doing' — or when four or more different measures are worth showing at once. A request for a chart, a graph or a picture of ONE thing is create_chart, not a grid with that chart buried in it. Never invent a tile to fill the grid: if the data holds four things worth showing, the dashboard is four tiles. ALWAYS send value_format on tiles whose values are money or percentages, and give a gauge its real value_min/value_max (NPS runs -100 to 100) — the ring is drawn against 0-100 otherwise and is wrong.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"rows",
"project_uid"
],
"properties": {
"rows": {
"type": "array",
"items": {
"type": "object",
"required": [
"tiles"
],
"properties": {
"tiles": {
"type": "array",
"items": {
"type": "object",
"required": [
"kind",
"title"
],
"properties": {
"data": {
"type": "array",
"items": {
"type": "number"
},
"description": "Metric only: the sparkline values. Omit it for a figure with no history — the tile then prints the number on its own. Never invent a series to fill it."
},
"kind": {
"enum": [
"metric",
"bar",
"line",
"pie",
"gauge",
"radar",
"scatter"
],
"type": "string"
},
"span": {
"type": "integer",
"maximum": 4,
"minimum": 1,
"description": "Relative width within the row (default 1)."
},
"delta": {
"type": "number",
"description": "Metric only: the fractional change behind the trend badge (0.124 renders +12.4%). Send it when you know it; otherwise it is inferred from the sparkline's first and last points."
},
"scale": {
"enum": [
"linear",
"log"
],
"type": "string",
"description": "Bar/line: the VALUE axis scale, default linear. Send \"log\" when the values span orders of magnitude — a funnel of 396 → 15 → 8 → 2 → 1 draws every step after the first as a sliver on a linear axis, which hides the very drop the chart is about. Every value must be zero or more, and say so in the caption (\"note the log axis\") because a reader assumes linear."
},
"stack": {
"enum": [
"none",
"total",
"percent"
],
"type": "string",
"description": "Bar only."
},
"stats": {
"type": "array",
"items": {
"type": "object",
"required": [
"label",
"value"
],
"properties": {
"label": {
"type": "string",
"maxLength": 28,
"minLength": 1,
"description": "What the number is (\"Distinct users\")."
},
"value": {
"type": "string",
"maxLength": 12,
"minLength": 1,
"description": "The number as it should READ (\"3.8%\", \"396\", \"53%\")."
}
},
"additionalProperties": false
},
"maxItems": 4,
"description": "Up to 4 headline figures printed large across the top of the chart. Use them for the numbers a reader would otherwise have to work out off the bars — a total, a conversion rate, a share — not for restating the tallest bar. The value is display text, so it can carry a unit the chart itself does not (a chart of user counts headlined by a percentage)."
},
"title": {
"type": "string",
"minLength": 1,
"description": "The chart's title, as short as it can be and still be right — about 40 characters. It is read at the width of a chat panel, not a slide."
},
"value": {
"type": [
"number",
"string"
],
"description": "Gauge: the numeric value. Metric: the headline value shown big."
},
"colors": {
"type": "array",
"items": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$"
},
"description": "Optional palette; OMIT IT unless the colour means something. The default is the house blue, and one measure across categories is one colour — a chart whose bars are six different colours is saying they are six different things. Send colours when they carry a fact: shades of the same blue to rank or to sequence, or a muted palette with ONE accent to point at the outlier. On a single-series bar chart they colour the bars one by one; with `groups` they index the GROUPS."
},
"groups": {
"type": "array",
"items": {
"type": "string"
},
"description": "Bar only, ONE series: the group each category belongs to, same length and order as `categories` (e.g. [\"tool exists\",\"tool exists\",\"no tool\",…]). Bars are coloured by group and the legend names the groups. Use this whenever the categories split into kinds — it is the alternative to faking the same picture with one series per group padded with zeros, which doubles the bars and prints a 0 on every empty one. `colors` indexes the GROUPS here, so a two-group chart takes exactly two colours."
},
"layout": {
"enum": [
"vertical",
"horizontal"
],
"type": "string",
"description": "Bar only."
},
"series": {
"type": "array",
"items": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "number"
},
"description": "Values, one per category (bar/line/radar/metric)."
},
"name": {
"type": "string",
"default": ""
},
"points": {
"type": "array",
"items": {
"type": "object",
"required": [
"x",
"y"
],
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
}
},
"additionalProperties": false
},
"description": "Scatter only: the series' points."
}
},
"additionalProperties": false
}
},
"slices": {
"type": "array",
"items": {
"type": "object",
"required": [
"label",
"value"
],
"properties": {
"label": {
"type": "string",
"minLength": 1
},
"value": {
"type": "number"
}
},
"additionalProperties": false
},
"description": "Pie only. Labels as short as the categories above — two or three words."
},
"caption": {
"type": "string",
"maxLength": 120,
"description": "One short line under the chart saying what it SHOWS — the finding, not the title again (\"Churn fell every month after March\", \"Q4 cleared the target on its own\"). This is what makes a chart read as an answer instead of a picture; add one whenever you have something to say about the data. ONE line, and it is drawn on one line: past about 90 characters it is clipped rather than wrapped."
},
"metrics": {
"type": "array",
"items": {
"type": "string"
},
"description": "Radar only: the axis names."
},
"x_label": {
"type": "string"
},
"y_label": {
"type": "string"
},
"subtitle": {
"type": "string",
"maxLength": 90,
"description": "One muted line ABOVE the chart saying what it plots and over what — the reading instruction, not the finding (\"Top PRs ranked by lines added\", \"Share of the 50 cancellations, by stated reason\"). Say where the numbers came from when that is not obvious from the title. The finding goes in `caption`, below."
},
"reference": {
"type": "object",
"required": [
"value"
],
"properties": {
"label": {
"type": "string",
"maxLength": 40
},
"value": {
"type": "number"
}
},
"description": "Bar/line: a target or benchmark drawn as a line across the plot, e.g. {value: 900000, label: \"£900k target\"}. When the point is \"how are we doing against X\", this IS the answer — put the target on the chart rather than adding a separate gauge tile.",
"additionalProperties": false
},
"value_max": {
"type": "number",
"description": "Gauge only: the high end of the scale."
},
"value_min": {
"type": "number",
"description": "Gauge only: the low end of the scale. ALWAYS send min and max when the range is not 0-100 — NPS runs -100 to 100, a CSAT score 0 to 5. Without them the ring is drawn against 0-100 and is simply wrong."
},
"categories": {
"type": "array",
"items": {
"type": "string"
},
"description": "Bar/line: the x-axis categories. WRITE THEM SHORT — two or three words, about 20 characters. They are drawn beside every bar at a small size, so \"What the agent puts on the board\" takes half the chart's width from the bars and then ellipsises anyway, while \"Board creation\" says the same thing. Summarise; do not truncate mid-phrase, and never abbreviate to something the reader cannot decode. The title and the caption carry the context the labels no longer need."
},
"show_values": {
"type": "boolean",
"description": "Bar only: print each bar's value on it. Do this for a ranking or any chart of about eight bars or fewer — it is what makes a bar chart readable without an axis. Leave it off when many grouped bars would crowd."
},
"value_label": {
"type": "string",
"maxLength": 60,
"description": "Gauge: the caption under the number. Metric: the small label under the headline value (e.g. \"vs last quarter\")."
},
"value_format": {
"type": "object",
"properties": {
"style": {
"enum": [
"number",
"currency",
"percent"
],
"type": "string"
},
"compact": {
"type": "boolean",
"description": "Abbreviate: 1.2K, 3.4M."
},
"currency": {
"type": "string",
"maxLength": 3,
"minLength": 3,
"description": "ISO 4217, e.g. 'GBP', 'USD'."
},
"decimals": {
"type": "integer",
"maximum": 4,
"minimum": 0
}
},
"description": "How to write the numbers, on the axis, the labels and the tooltip. Send it whenever the values are money or percentages — without it they render as bare numbers.",
"additionalProperties": false
}
},
"additionalProperties": false
},
"maxItems": 4,
"minItems": 1
}
},
"additionalProperties": false
},
"maxItems": 8,
"minItems": 1
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
Change a chart that is ALREADY on the board — its data, its title, or how it is drawn. This is a patch: send only what changes and the rest of the chart is kept, so "make it horizontal" is {layout: "horizontal"} and nothing else. Use it instead of building a replacement whenever the chart is nearly right — the user keeps its place, size and the undo history that goes with it. It applies immediately and the user can undo it. A chart's TYPE cannot change here (a bar chart cannot become a line chart): that is a create plus a delete of the old one.
The description explains the capability, when to use it, and what to expect.
Inputs69/100
25 of 36 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
element_uid
The chart element's uid.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
title
The chart's title, as short as it can be and still be right — about 40 characters. It is read at the width of a chat panel, not a slide.
Clear enough to supply this argument.
subtitle
One muted line ABOVE the chart saying what it plots and over what — the reading instruction, not the finding ("Top PRs ranked by lines added", "Share of the 50 cancellations, by stated reason"). Say where the numbers came from when that is not obvious from the title. The finding goes in `caption`, below.
Clear enough to supply this argument.
caption
One short line under the chart saying what it SHOWS — the finding, not the title again ("Churn fell every month after March", "Q4 cleared the target on its own"). This is what makes a chart read as an answer instead of a picture; add one whenever you have something to say about the data. ONE line, and it is drawn on one line: past about 90 characters it is clipped rather than wrapped.
Clear enough to supply this argument.
x_label
Not provided
Missing description. Explain what this value means and how to supply it.
y_label
Not provided
Missing description. Explain what this value means and how to supply it.
categories
Bar/line: the x-axis categories. WRITE THEM SHORT — two or three words, about 20 characters. They are drawn beside every bar at a small size, so "What the agent puts on the board" takes half the chart's width from the bars and then ellipsises anyway, while "Board creation" says the same thing. Summarise; do not truncate mid-phrase, and never abbreviate to something the reader cannot decode. The title and the caption carry the context the labels no longer need.
Clear enough to supply this argument.
series › items › name
Not provided
Missing description. Explain what this value means and how to supply it.
series › items › data
Values, one per category (bar/line/radar/metric).
Clear enough to supply this argument.
series › items › points › items › x
Not provided
Missing description. Explain what this value means and how to supply it.
series › items › points › items › y
Not provided
Missing description. Explain what this value means and how to supply it.
slices › items › label
Not provided
Missing description. Explain what this value means and how to supply it.
slices › items › value
Not provided
Missing description. Explain what this value means and how to supply it.
value
Gauge: the numeric value. Metric: the headline value shown big.
Clear enough to supply this argument.
data
Metric only: the sparkline values. Omit it for a figure with no history — the tile then prints the number on its own. Never invent a series to fill it.
Clear enough to supply this argument.
metrics
Radar only: the axis names.
Clear enough to supply this argument.
colors
Optional palette; OMIT IT unless the colour means something. The default is the house blue, and one measure across categories is one colour — a chart whose bars are six different colours is saying they are six different things. Send colours when they carry a fact: shades of the same blue to rank or to sequence, or a muted palette with ONE accent to point at the outlier. On a single-series bar chart they colour the bars one by one; with `groups` they index the GROUPS.
Clear enough to supply this argument.
groups
Bar only, ONE series: the group each category belongs to, same length and order as `categories` (e.g. ["tool exists","tool exists","no tool",…]). Bars are coloured by group and the legend names the groups. Use this whenever the categories split into kinds — it is the alternative to faking the same picture with one series per group padded with zeros, which doubles the bars and prints a 0 on every empty one. `colors` indexes the GROUPS here, so a two-group chart takes exactly two colours.
Clear enough to supply this argument.
layout
Bar only.
Clear enough to supply this argument.
stack
Bar only.
Clear enough to supply this argument.
scale
Bar/line: the VALUE axis scale, default linear. Send "log" when the values span orders of magnitude — a funnel of 396 → 15 → 8 → 2 → 1 draws every step after the first as a sliver on a linear axis, which hides the very drop the chart is about. Every value must be zero or more, and say so in the caption ("note the log axis") because a reader assumes linear.
Clear enough to supply this argument.
stats › items › label
What the number is ("Distinct users").
Clear enough to supply this argument.
stats › items › value
The number as it should READ ("3.8%", "396", "53%").
Clear enough to supply this argument.
show_values
Bar only: print each bar's value on it. Do this for a ranking or any chart of about eight bars or fewer — it is what makes a bar chart readable without an axis. Leave it off when many grouped bars would crowd.
Clear enough to supply this argument.
reference › value
Not provided
Missing description. Explain what this value means and how to supply it.
reference › label
Not provided
Missing description. Explain what this value means and how to supply it.
value_format › style
Not provided
Missing description. Explain what this value means and how to supply it.
value_format › currency
ISO 4217, e.g. 'GBP', 'USD'.
Clear enough to supply this argument.
value_format › decimals
Not provided
Missing description. Explain what this value means and how to supply it.
value_format › compact
Abbreviate: 1.2K, 3.4M.
Clear enough to supply this argument.
value_min
Gauge only: the low end of the scale. ALWAYS send min and max when the range is not 0-100 — NPS runs -100 to 100, a CSAT score 0 to 5. Without them the ring is drawn against 0-100 and is simply wrong.
Clear enough to supply this argument.
value_max
Gauge only: the high end of the scale.
Clear enough to supply this argument.
value_label
Gauge: the caption under the number. Metric: the small label under the headline value (e.g. "vs last quarter").
Clear enough to supply this argument.
delta
Metric only: the fractional change behind the trend badge (0.124 renders +12.4%). Send it when you know it; otherwise it is inferred from the sparkline's first and last points.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "update_chart",
"title": "Update chart",
"description": "Change a chart that is ALREADY on the board — its data, its title, or how it is drawn. This is a patch: send only what changes and the rest of the chart is kept, so \"make it horizontal\" is {layout: \"horizontal\"} and nothing else. Use it instead of building a replacement whenever the chart is nearly right — the user keeps its place, size and the undo history that goes with it. It applies immediately and the user can undo it. A chart's TYPE cannot change here (a bar chart cannot become a line chart): that is a create plus a delete of the old one.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"element_uid",
"project_uid"
],
"properties": {
"data": {
"type": "array",
"items": {
"type": "number"
},
"description": "Metric only: the sparkline values. Omit it for a figure with no history — the tile then prints the number on its own. Never invent a series to fill it."
},
"delta": {
"type": "number",
"description": "Metric only: the fractional change behind the trend badge (0.124 renders +12.4%). Send it when you know it; otherwise it is inferred from the sparkline's first and last points."
},
"scale": {
"enum": [
"linear",
"log"
],
"type": "string",
"description": "Bar/line: the VALUE axis scale, default linear. Send \"log\" when the values span orders of magnitude — a funnel of 396 → 15 → 8 → 2 → 1 draws every step after the first as a sliver on a linear axis, which hides the very drop the chart is about. Every value must be zero or more, and say so in the caption (\"note the log axis\") because a reader assumes linear."
},
"stack": {
"enum": [
"none",
"total",
"percent"
],
"type": "string",
"description": "Bar only."
},
"stats": {
"type": "array",
"items": {
"type": "object",
"required": [
"label",
"value"
],
"properties": {
"label": {
"type": "string",
"maxLength": 28,
"minLength": 1,
"description": "What the number is (\"Distinct users\")."
},
"value": {
"type": "string",
"maxLength": 12,
"minLength": 1,
"description": "The number as it should READ (\"3.8%\", \"396\", \"53%\")."
}
},
"additionalProperties": false
},
"maxItems": 4,
"description": "Up to 4 headline figures printed large across the top of the chart. Use them for the numbers a reader would otherwise have to work out off the bars — a total, a conversion rate, a share — not for restating the tallest bar. The value is display text, so it can carry a unit the chart itself does not (a chart of user counts headlined by a percentage)."
},
"title": {
"type": "string",
"minLength": 1,
"description": "The chart's title, as short as it can be and still be right — about 40 characters. It is read at the width of a chat panel, not a slide."
},
"value": {
"type": [
"number",
"string"
],
"description": "Gauge: the numeric value. Metric: the headline value shown big."
},
"colors": {
"type": "array",
"items": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$"
},
"description": "Optional palette; OMIT IT unless the colour means something. The default is the house blue, and one measure across categories is one colour — a chart whose bars are six different colours is saying they are six different things. Send colours when they carry a fact: shades of the same blue to rank or to sequence, or a muted palette with ONE accent to point at the outlier. On a single-series bar chart they colour the bars one by one; with `groups` they index the GROUPS."
},
"groups": {
"type": "array",
"items": {
"type": "string"
},
"description": "Bar only, ONE series: the group each category belongs to, same length and order as `categories` (e.g. [\"tool exists\",\"tool exists\",\"no tool\",…]). Bars are coloured by group and the legend names the groups. Use this whenever the categories split into kinds — it is the alternative to faking the same picture with one series per group padded with zeros, which doubles the bars and prints a 0 on every empty one. `colors` indexes the GROUPS here, so a two-group chart takes exactly two colours."
},
"layout": {
"enum": [
"vertical",
"horizontal"
],
"type": "string",
"description": "Bar only."
},
"series": {
"type": "array",
"items": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "number"
},
"description": "Values, one per category (bar/line/radar/metric)."
},
"name": {
"type": "string",
"default": ""
},
"points": {
"type": "array",
"items": {
"type": "object",
"required": [
"x",
"y"
],
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
}
},
"additionalProperties": false
},
"description": "Scatter only: the series' points."
}
},
"additionalProperties": false
}
},
"slices": {
"type": "array",
"items": {
"type": "object",
"required": [
"label",
"value"
],
"properties": {
"label": {
"type": "string",
"minLength": 1
},
"value": {
"type": "number"
}
},
"additionalProperties": false
},
"description": "Pie only. Labels as short as the categories above — two or three words."
},
"caption": {
"type": "string",
"maxLength": 120,
"description": "One short line under the chart saying what it SHOWS — the finding, not the title again (\"Churn fell every month after March\", \"Q4 cleared the target on its own\"). This is what makes a chart read as an answer instead of a picture; add one whenever you have something to say about the data. ONE line, and it is drawn on one line: past about 90 characters it is clipped rather than wrapped."
},
"metrics": {
"type": "array",
"items": {
"type": "string"
},
"description": "Radar only: the axis names."
},
"x_label": {
"type": "string"
},
"y_label": {
"type": "string"
},
"subtitle": {
"type": "string",
"maxLength": 90,
"description": "One muted line ABOVE the chart saying what it plots and over what — the reading instruction, not the finding (\"Top PRs ranked by lines added\", \"Share of the 50 cancellations, by stated reason\"). Say where the numbers came from when that is not obvious from the title. The finding goes in `caption`, below."
},
"reference": {
"type": "object",
"required": [
"value"
],
"properties": {
"label": {
"type": "string",
"maxLength": 40
},
"value": {
"type": "number"
}
},
"description": "Bar/line: a target or benchmark drawn as a line across the plot, e.g. {value: 900000, label: \"£900k target\"}. When the point is \"how are we doing against X\", this IS the answer — put the target on the chart rather than adding a separate gauge tile.",
"additionalProperties": false
},
"value_max": {
"type": "number",
"description": "Gauge only: the high end of the scale."
},
"value_min": {
"type": "number",
"description": "Gauge only: the low end of the scale. ALWAYS send min and max when the range is not 0-100 — NPS runs -100 to 100, a CSAT score 0 to 5. Without them the ring is drawn against 0-100 and is simply wrong."
},
"categories": {
"type": "array",
"items": {
"type": "string"
},
"description": "Bar/line: the x-axis categories. WRITE THEM SHORT — two or three words, about 20 characters. They are drawn beside every bar at a small size, so \"What the agent puts on the board\" takes half the chart's width from the bars and then ellipsises anyway, while \"Board creation\" says the same thing. Summarise; do not truncate mid-phrase, and never abbreviate to something the reader cannot decode. The title and the caption carry the context the labels no longer need."
},
"element_uid": {
"type": "string",
"minLength": 1,
"description": "The chart element's uid."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"show_values": {
"type": "boolean",
"description": "Bar only: print each bar's value on it. Do this for a ranking or any chart of about eight bars or fewer — it is what makes a bar chart readable without an axis. Leave it off when many grouped bars would crowd."
},
"value_label": {
"type": "string",
"maxLength": 60,
"description": "Gauge: the caption under the number. Metric: the small label under the headline value (e.g. \"vs last quarter\")."
},
"value_format": {
"type": "object",
"properties": {
"style": {
"enum": [
"number",
"currency",
"percent"
],
"type": "string"
},
"compact": {
"type": "boolean",
"description": "Abbreviate: 1.2K, 3.4M."
},
"currency": {
"type": "string",
"maxLength": 3,
"minLength": 3,
"description": "ISO 4217, e.g. 'GBP', 'USD'."
},
"decimals": {
"type": "integer",
"maximum": 4,
"minimum": 0
}
},
"description": "How to write the numbers, on the axis, the labels and the tooltip. Send it whenever the values are money or percentages — without it they render as bare numbers.",
"additionalProperties": false
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description97/100
Draw a DIAGRAM in one call — a flowchart, a user journey, an org chart, a swimlane, a state machine, a process: boxes on a grid with labelled arrows between them. Use this whenever the shape of the answer is boxes-and-arrows, however the user said it ('map the signup flow', 'how does a ticket move through support', 'chart our approval process').
It CANNOT be built one element at a time. Free placement answers 'somewhere free' rather than 'column 2, row 3', so the boxes step diagonally across the canvas and the arrows between them mean nothing. Here you say which CELL each node is in and the tool owns every coordinate: one width for every box, a column as wide as its widest node, and the space a labelled arrow needs bought out of the boundary it crosses so no chip lands on a box.
Use create_mindmap for a centre with branches radiating off it, create_constellation for a web of notes with sub-branches, and create_orbit for one ring of small things around a hub. This is the one for a flow that goes somewhere.
This builds BOARD ELEMENTS the user keeps working on. When they want ONE finished thing to take away instead — a timeline, framework or explainer to screenshot into a deck, show a client or send — that is create_html_app, which lays the same material out as a single designed page.
The description explains the capability, when to use it, and what to expect.
Inputs88/100
34 of 37 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
place
Where the diagram goes relative to what is already on the board. 'below' puts it under everything, for a board that reads top to bottom; 'right' sets it beside the content, level with the top.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
nodes › items › type
What this node IS. A flowchart's boxes are `note`; use `heading` for a band title, `ticket` for a box with its own title line and detail under it, `image` for a picture or icon, `color` for a swatch. Everything the create tool makes is available — a diagram whose nodes are documents or folders is an index, and it works the same way.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
nodes › items › text
Text for note/todo/heading, the document body, or a colour's caption.
Clear enough to supply this argument.
nodes › items › title
Wall title, ticket title, link label, table name, document title, or folder name. A table is ALWAYS given one — it is the heading shown above the grid, and a table without it lands as an anonymous block of cells.
Clear enough to supply this argument.
nodes › items › description
Ticket description, a link's one-line summary, or a table's caption — the line under the grid saying what it holds or how to read it. Give every table one short sentence.
Clear enough to supply this argument.
nodes › items › url
For link and video. Must be a real URL that appeared in research results or that the user gave you — NEVER one you composed yourself. A url you can READ in a picture they attached counts as given: a board screenshot with 'vimeo.com/71977557' printed under its player is that url, and leaving the player empty beside a legible address drops something they handed you. One you infer from a title, complete from a domain, or remember is not. YouTube and Vimeo urls render as players.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
nodes › items › image_url
For image. A STORED IMAGE KEY: a generate_image or find_images result, or the imageUrl of a picture already on the board, read straight off a board read. Never a URL from anywhere else, which will not render. OMIT it to lay down an EMPTY frame: a placeholder the user can drop their own picture into, or ask you to fill later. Note that the two picture tools PLACE what they make themselves, so you rarely need this: pass it when you are building an element around a picture you already have — including one the board already holds, when the user points at it ("put the hero shot on each card"). Reusing the board's own picture costs nothing and is the same picture; finding or generating a second one is neither.
Clear enough to supply this argument.
nodes › items › file_name
For file only — the document's name WITH its extension, e.g. 'Values and manifesto.pdf'. The extension is what picks the card's icon, so a name without one lands as a generic document. Read it off the tile when you are copying a board; never invent a filename.
Clear enough to supply this argument.
nodes › items › color_hex
For colour swatches.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
nodes › items › background_color
Background of the card itself. Works on note, todo, heading, ticket and wall; ignored elsewhere.
SET IT when the user asked for colour or a theme, and when the board already carries a pattern you are matching. OMIT it on a board you are building from nothing — a fresh board is themed through highlight_color on its walls instead, so the colour reads as an accent stripe rather than as a row of filled blocks nobody asked for. Omit it too when you are adding a few elements to a board that has no colour pattern of its own, and on cards inside a wall you have filled, which take their colour from that wall automatically.
Any hex is accepted and is snapped to the nearest of the canvas's twelve themes (red, terracotta, amber, olive, green, emerald, teal, blue, indigo, violet, magenta, graphite), so name the colour you actually mean — a brand's real hex is the right thing to pass. The snap is what lets the colour flip correctly between light and dark mode; a raw hex could not.
'transparent' is the exception to all of that and means something different: on a note or a todo it removes the card completely, leaving the text on the canvas with no box, no fill and no shadow. That is what a title or a label above a group of elements should look like, so use it for those without being asked. Ignored on every other type.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
nodes › items › highlight_color
Accent stripe along the top. Note, todo, heading, ticket and wall; ignored elsewhere. On a WALL this is how you theme a board you are building from nothing: pass the palette colour here and leave background_color off, and the wall carries the theme as a stripe, with no fill on the wall and no tint on the cards inside it. A wall you ARE filling never needs it: it gets its theme's stripe automatically, exactly as the canvas's own wall theme does, so background_color is the whole job there. On a TICKET, pass it to ASK for a stripe — when the ticket also carries a background_color the shade is taken from that same theme whatever you pass, so the two can never disagree. On a NOTE, TODO or HEADING the stripe is MARKING, not theming: it is snapped to the nearest of the twelve accent stripes rather than derived from the card's fill, because the point of it is that these cards go together and the card's own theme is not that. Omit it when the element has no theme and the board carries no colour pattern.
Clear enough to supply this argument.
nodes › items › font_size
For note and todo — how big the text is, in px. It sizes the note's markdown HEADING lines (the ones starting with #), or the whole note when it has none, so a note written as a '# Title' line plus a sentence under it gets a big title and a normally sized sentence from this one number. Normal note text is 16 and needs nothing set. Reach for it when text is meant to READ as a title: around 40 for the title of a whole board, 28 to 32 for a label above one section or row. A loose note is widened to keep its biggest line unwrapped; inside a wall the width stays the wall's.
Clear enough to supply this argument.
nodes › items › labels › items › text
Not provided
Missing description. Explain what this value means and how to supply it.
nodes › items › labels › items › color_hex
OMIT and a colour is chosen for you. Pass one to put the pill in the board's colour family: any hex is snapped to the nearest canvas palette colour (#CDDFDD, #D0E3F7, #DDD6F1, #F7DCE4, #F8DDD9, #F3E4C5, #EACFD5, #D9DEE1). A label the user already owns keeps its own colour.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
nodes › items › folder_icon
For folder only — the TOPIC of the folder, which picks its icon. Pick the closest one from: research, idea, strategy, planning, tasks, notes, meeting, launch, archive, inbox, templates, settings, design, writing, brand, photo, video, music, audio, marketing, sales, finance, budget, invoice, analytics, legal, clients, team, support, product, shop, engineering, bugs, security, data, cloud, travel, food, health, fitness, home, education, science, nature, mountain, camping, weather, transport, gear, events, gifts, reading, location, global, favourites, important, private, time, folder. Leave it out and the icon is chosen from the folder's name. Pass 'none' ONLY if the user said they do not want an icon. Anything outside this list falls back to a plain folder, so use a word from it rather than inventing an icon name.
Clear enough to supply this argument.
nodes › items › folder_color
For folder only — its tile colour, one of: tan, blue, rose, purple, steel, brown, red, navy, violet, slate, coral, orange. LEAVE IT OUT WHENEVER YOU ARE MAKING SEVERAL FOLDERS: each then takes a colour of its own from its name, which is what lets a set of tiles be told apart at a glance. One word repeated across the set — or borrowed from the wall they sit in — makes them all look the same. Pass it for a single folder the user asked to colour. Pass 'none' ONLY if the user asked for no colour.
Clear enough to supply this argument.
nodes › items › table_icon
For table only — the TOPIC of the table as a whole, which picks the icon shown beside its title. Pick the closest word from: name, title, owner, assignee, person, team, client, company, audience, character, identity, personality, background, relationship, story, status, stage, progress, priority, approval, done, task, checklist, type, category, tags, topic, platform, channel, date, deadline, schedule, calendar, duration, time, count, quantity, id, budget, cost, price, revenue, invoice, payment, percent, score, rating, metrics, data, notes, description, video, image, photo, audio, file, document, attachment, link, email, phone, comment, message, location, country, address, travel, campaign, marketing, sales, product, keyword, views, engagement, goal, launch, project, shop, discount, code, bug, security, version, book, education, language, weather, home, vehicle, important, private, archive, settings, idea, edit. Leave it out when the table's own name already says the topic (a 'Content calendar' picks its glyph from the name), and set it when the name is evocative rather than literal. Pass 'none' only if the user asked for no icon. Anything outside this list is ignored and the name is used instead, so use a word from it rather than inventing an icon name.
Clear enough to supply this argument.
nodes › items › date
Ticket due date, YYYY-MM-DD. Set it ONLY when the user stated a date or it follows directly from what they said; never infer or invent one.
How the whole column behaves on the canvas. Pick the one that matches the data: currency for money, percent for rates, number for plain figures, datetime for dates (cells then open a date picker), duration for a LENGTH of time (a runtime, not a date), checkbox for done/not-done, rating for a 1-5 score, labels for category tags the user invents, status for progress through fixed stages, person for who OWNS or is ASSIGNED the row, url / email / phone for addresses the cell should link to — ONE address per row, written bare — text for anything else, including a column that cites SEVERAL sources per row. Omit for text.
status is a FIXED list — its cells must be one of: Not started, Blocked, In progress, In review, Done, Archived. For any other set of stages ('Scripting', 'Filming'), use labels.
person needs a board that HAS other people on it (get_board_people lists them): on a board whose only member is the user there is nobody to assign, so make an owner column text there and write the names as text.
Column width in px (80-600, default 168). Set it only when the content clearly needs it — long text or notes ~280-320, tags ~240, dates/checkboxes can go narrower (~120).
The TOPIC of this column, which picks the icon shown in its header. USUALLY OMIT IT: the icon is chosen from the column's name automatically, so a well-named column is already right. Set it only when the name would not resolve on its own or reads as something else — e.g. a column called 'Fuji summit' that holds locations. Then pick the closest word from: name, title, owner, assignee, person, team, client, company, audience, character, identity, personality, background, relationship, story, status, stage, progress, priority, approval, done, task, checklist, type, category, tags, topic, platform, channel, date, deadline, schedule, calendar, duration, time, count, quantity, id, budget, cost, price, revenue, invoice, payment, percent, score, rating, metrics, data, notes, description, video, image, photo, audio, file, document, attachment, link, email, phone, comment, message, location, country, address, travel, campaign, marketing, sales, product, keyword, views, engagement, goal, launch, project, shop, discount, code, bug, security, version, book, education, language, weather, home, vehicle, important, private, archive, settings, idea, edit. Pass 'none' only if the user asked for no icon. Anything outside this list is ignored and the name is used instead, so use a word from it rather than inventing an icon name.
Clear enough to supply this argument.
nodes › items › rows
Table rows, each an array of cell values in column order — REQUIRED, in the SAME call as the columns: a table sent as a header alone is refused. Adding rows later costs a resend of the whole grid through update_element, so send the rows you have now. Write every cell as plain text — typed columns are converted for you: a date as YYYY-MM-DD, a checkbox as true/false, a duration as 1:30 or 90 or '1h 20m', a rating as a number, a labels cell as comma-separated tags, a status cell as one of its stage names, a person cell as the NAMES of people already on this board (comma-separated for two owners).
A column whose cells the canvas cannot represent — a name that belongs to nobody on the board, a word that is not one of the status stages — falls back to a plain TEXT column, so nothing you write is lost, but the column stops behaving as the type you asked for. Keep the values in the type's own vocabulary, and leave a cell empty rather than inventing a person (get_board_people lists who is on the board).
AN ADDRESS IN A TEXT CELL IS WRITTEN AS A NAMED LINK: `[Andes Handbook](https://www.andeshandbook.org/details/general/55)` shows the name and links it, so a Sources column reads as source names instead of wrapped url text. One per line, three at most per cell. A bare url still links, but the cell shortens it on screen, so name the ones you cite. A url COLUMN is the other shape and takes the bare address, never a named link.
Clear enough to supply this argument.
nodes › items › ref
A short name YOU invent for this node — 'register', 'step2'. Every node needs one, because the arrows are written as pairs of them.
Clear enough to supply this argument.
nodes › items › col
Not provided
Missing description. Explain what this value means and how to supply it.
nodes › items › row
Not provided
Missing description. Explain what this value means and how to supply it.
nodes › items › col_span
How many COLUMNS this node covers, when it is wider than the things under it. Defaults to 1. This is what a centrepiece needs: a big picture with a row of five colour swatches beneath it is the picture at `col_span: 5` on row 0 and the five swatches at columns 0-4 on row 1. Without it the picture takes one column's width and the swatches line up beside it instead of under it.
Clear enough to supply this argument.
connections › items › from
The `ref` of the element the arrow leaves.
Clear enough to supply this argument.
connections › items › to
The `ref` of the element the arrow points at.
Clear enough to supply this argument.
connections › items › label
The words ON the arrow — '2 weeks', 'Step 1', 'Clicks on genre'. The grid buys the run the chip needs out of the boundary the arrow crosses, so a label costs space rather than sitting across the boxes at either end.
Clear enough to supply this argument.
connections › items › from_side
Which EDGE of the source the line leaves. Omit it and the side facing the other end is used, which is what a grid wants: a box above its next step leaves the bottom, one to its left leaves the right. Name it for the lines that do something else — one that drops out of the bottom and comes back up the left, one that leaves sideways to get around the box between.
Clear enough to supply this argument.
connections › items › to_side
Which EDGE of the target the line arrives at. Same rule as `from_side`.
Clear enough to supply this argument.
connections › items › line
The line's SHAPE. `stepped` is the right-angled connector a flowchart draws — across then down, never a diagonal — and it is what two nodes on the grid get unless you say otherwise. `straight` is a plain line between the two handles. `curved` is a sweep, which is what a hand-drawn arrow looks like and what an arrow between two walls should stay.
Clear enough to supply this argument.
connections › items › color
The line's colour as a hex. It colours the LINE AND ITS LABEL together — the chip takes the line's colour and works out its own text contrast. Colour the lines that MEAN something apart from the rest: the automated path, the recovery route, the failure branch. Colouring them all says nothing.
Clear enough to supply this argument.
connections › items › dashed
TRUE for a dashed line, the convention for the path that is optional, automatic or a recovery route rather than the main flow.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "create_diagram",
"title": "Create diagram",
"description": "Draw a DIAGRAM in one call — a flowchart, a user journey, an org chart, a swimlane, a state machine, a process: boxes on a grid with labelled arrows between them. Use this whenever the shape of the answer is boxes-and-arrows, however the user said it ('map the signup flow', 'how does a ticket move through support', 'chart our approval process').\n\nIt CANNOT be built one element at a time. Free placement answers 'somewhere free' rather than 'column 2, row 3', so the boxes step diagonally across the canvas and the arrows between them mean nothing. Here you say which CELL each node is in and the tool owns every coordinate: one width for every box, a column as wide as its widest node, and the space a labelled arrow needs bought out of the boundary it crosses so no chip lands on a box.\n\nUse create_mindmap for a centre with branches radiating off it, create_constellation for a web of notes with sub-branches, and create_orbit for one ring of small things around a hub. This is the one for a flow that goes somewhere.\n\nThis builds BOARD ELEMENTS the user keeps working on. When they want ONE finished thing to take away instead — a timeline, framework or explainer to screenshot into a deck, show a client or send — that is create_html_app, which lays the same material out as a single designed page.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"nodes",
"project_uid"
],
"properties": {
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"type",
"ref",
"col",
"row"
],
"properties": {
"col": {
"type": "integer",
"maximum": 11,
"minimum": 0
},
"ref": {
"type": "string",
"maxLength": 40,
"description": "A short name YOU invent for this node — 'register', 'step2'. Every node needs one, because the arrows are written as pairs of them."
},
"row": {
"type": "integer",
"maximum": 23,
"minimum": 0
},
"url": {
"type": "string",
"format": "uri",
"description": "For link and video. Must be a real URL that appeared in research results or that the user gave you — NEVER one you composed yourself. A url you can READ in a picture they attached counts as given: a board screenshot with 'vimeo.com/71977557' printed under its player is that url, and leaving the player empty beside a legible address drops something they handed you. One you infer from a title, complete from a domain, or remember is not. YouTube and Vimeo urls render as players."
},
"date": {
"type": "string",
"pattern": "^(\\d{4}-\\d{2}-\\d{2})?$",
"description": "Ticket due date, YYYY-MM-DD. Set it ONLY when the user stated a date or it follows directly from what they said; never infer or invent one."
},
"rows": {
"type": "array",
"items": {
"type": "array",
"items": {
"type": "string"
}
},
"maxItems": 50,
"description": "Table rows, each an array of cell values in column order — REQUIRED, in the SAME call as the columns: a table sent as a header alone is refused. Adding rows later costs a resend of the whole grid through update_element, so send the rows you have now. Write every cell as plain text — typed columns are converted for you: a date as YYYY-MM-DD, a checkbox as true/false, a duration as 1:30 or 90 or '1h 20m', a rating as a number, a labels cell as comma-separated tags, a status cell as one of its stage names, a person cell as the NAMES of people already on this board (comma-separated for two owners).\nA column whose cells the canvas cannot represent — a name that belongs to nobody on the board, a word that is not one of the status stages — falls back to a plain TEXT column, so nothing you write is lost, but the column stops behaving as the type you asked for. Keep the values in the type's own vocabulary, and leave a cell empty rather than inventing a person (get_board_people lists who is on the board).\nAN ADDRESS IN A TEXT CELL IS WRITTEN AS A NAMED LINK: `[Andes Handbook](https://www.andeshandbook.org/details/general/55)` shows the name and links it, so a Sources column reads as source names instead of wrapped url text. One per line, three at most per cell. A bare url still links, but the cell shortens it on screen, so name the ones you cite. A url COLUMN is the other shape and takes the bare address, never a named link."
},
"text": {
"type": "string",
"description": "Text for note/todo/heading, the document body, or a colour's caption."
},
"type": {
"enum": [
"note",
"todo",
"heading",
"ticket",
"link",
"video",
"color",
"image",
"table",
"document",
"folder",
"file",
"comment"
],
"type": "string",
"description": "What this node IS. A flowchart's boxes are `note`; use `heading` for a band title, `ticket` for a box with its own title line and detail under it, `image` for a picture or icon, `color` for a swatch. Everything the create tool makes is available — a diagram whose nodes are documents or folders is an index, and it works the same way."
},
"title": {
"type": "string",
"description": "Wall title, ticket title, link label, table name, document title, or folder name. A table is ALWAYS given one — it is the heading shown above the grid, and a table without it lands as an anonymous block of cells."
},
"labels": {
"type": "array",
"items": {
"type": "object",
"required": [
"text"
],
"properties": {
"text": {
"type": "string",
"maxLength": 40,
"minLength": 1
},
"color_hex": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$",
"description": "OMIT and a colour is chosen for you. Pass one to put the pill in the board's colour family: any hex is snapped to the nearest canvas palette colour (#CDDFDD, #D0E3F7, #DDD6F1, #F7DCE4, #F8DDD9, #F3E4C5, #EACFD5, #D9DEE1). A label the user already owns keeps its own colour."
}
},
"additionalProperties": false
},
"maxItems": 4,
"description": "Small tag pills shown ON the card, for a status or category. Works on note, todo, wall, image, colour, file and video — not on a heading, which shows none. A ticket shows ONE chip and is NEVER built without it: pass a single label and it becomes the ticket's own. Name it for what the ticket IS on this board — its kind, phase, owner or what it is waiting on (Booking, Permit, Blocked, Week 2, Research) — read off the ticket's own title and description rather than repeating them. A ticket with no label draws an empty 'Label' slot on the card, so omitting one is never the neutral choice."
},
"columns": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "object",
"required": [
"name"
],
"properties": {
"icon": {
"type": "string",
"description": "The TOPIC of this column, which picks the icon shown in its header. USUALLY OMIT IT: the icon is chosen from the column's name automatically, so a well-named column is already right. Set it only when the name would not resolve on its own or reads as something else — e.g. a column called 'Fuji summit' that holds locations. Then pick the closest word from: name, title, owner, assignee, person, team, client, company, audience, character, identity, personality, background, relationship, story, status, stage, progress, priority, approval, done, task, checklist, type, category, tags, topic, platform, channel, date, deadline, schedule, calendar, duration, time, count, quantity, id, budget, cost, price, revenue, invoice, payment, percent, score, rating, metrics, data, notes, description, video, image, photo, audio, file, document, attachment, link, email, phone, comment, message, location, country, address, travel, campaign, marketing, sales, product, keyword, views, engagement, goal, launch, project, shop, discount, code, bug, security, version, book, education, language, weather, home, vehicle, important, private, archive, settings, idea, edit. Pass 'none' only if the user asked for no icon. Anything outside this list is ignored and the name is used instead, so use a word from it rather than inventing an icon name."
},
"name": {
"type": "string",
"description": "The column header text. Name it for what the column HOLDS, never for its cell_type — a person column is 'Owner' or 'Assignee', not 'Person'."
},
"width": {
"type": "integer",
"maximum": 600,
"minimum": 80,
"description": "Column width in px (80-600, default 168). Set it only when the content clearly needs it — long text or notes ~280-320, tags ~240, dates/checkboxes can go narrower (~120)."
},
"cell_type": {
"enum": [
"text",
"number",
"currency",
"percent",
"datetime",
"duration",
"checkbox",
"rating",
"labels",
"status",
"person",
"url",
"email",
"phone",
"document"
],
"type": "string",
"description": "How the whole column behaves on the canvas. Pick the one that matches the data: currency for money, percent for rates, number for plain figures, datetime for dates (cells then open a date picker), duration for a LENGTH of time (a runtime, not a date), checkbox for done/not-done, rating for a 1-5 score, labels for category tags the user invents, status for progress through fixed stages, person for who OWNS or is ASSIGNED the row, url / email / phone for addresses the cell should link to — ONE address per row, written bare — text for anything else, including a column that cites SEVERAL sources per row. Omit for text.\nstatus is a FIXED list — its cells must be one of: Not started, Blocked, In progress, In review, Done, Archived. For any other set of stages ('Scripting', 'Filming'), use labels.\nperson needs a board that HAS other people on it (get_board_people lists them): on a board whose only member is the user there is nobody to assign, so make an owner column text there and write the names as text."
}
},
"additionalProperties": false
}
]
},
"maxItems": 8,
"minItems": 1,
"description": "Table columns — REQUIRED for a table, in the same call as its rows. Either a plain header string, or an object to also set the column's cell type and width."
},
"col_span": {
"type": "integer",
"maximum": 12,
"minimum": 1,
"description": "How many COLUMNS this node covers, when it is wider than the things under it. Defaults to 1. This is what a centrepiece needs: a big picture with a row of five colour swatches beneath it is the picture at `col_span: 5` on row 0 and the five swatches at columns 0-4 on row 1. Without it the picture takes one column's width and the swatches line up beside it instead of under it."
},
"color_hex": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$",
"description": "For colour swatches."
},
"file_name": {
"type": "string",
"description": "For file only — the document's name WITH its extension, e.g. 'Values and manifesto.pdf'. The extension is what picks the card's icon, so a name without one lands as a generic document. Read it off the tile when you are copying a board; never invent a filename."
},
"font_size": {
"type": "integer",
"maximum": 144,
"minimum": 8,
"description": "For note and todo — how big the text is, in px. It sizes the note's markdown HEADING lines (the ones starting with #), or the whole note when it has none, so a note written as a '# Title' line plus a sentence under it gets a big title and a normally sized sentence from this one number. Normal note text is 16 and needs nothing set. Reach for it when text is meant to READ as a title: around 40 for the title of a whole board, 28 to 32 for a label above one section or row. A loose note is widened to keep its biggest line unwrapped; inside a wall the width stays the wall's."
},
"image_url": {
"type": "string",
"description": "For image. A STORED IMAGE KEY: a generate_image or find_images result, or the imageUrl of a picture already on the board, read straight off a board read. Never a URL from anywhere else, which will not render. OMIT it to lay down an EMPTY frame: a placeholder the user can drop their own picture into, or ask you to fill later. Note that the two picture tools PLACE what they make themselves, so you rarely need this: pass it when you are building an element around a picture you already have — including one the board already holds, when the user points at it (\"put the hero shot on each card\"). Reusing the board's own picture costs nothing and is the same picture; finding or generating a second one is neither."
},
"table_icon": {
"type": "string",
"description": "For table only — the TOPIC of the table as a whole, which picks the icon shown beside its title. Pick the closest word from: name, title, owner, assignee, person, team, client, company, audience, character, identity, personality, background, relationship, story, status, stage, progress, priority, approval, done, task, checklist, type, category, tags, topic, platform, channel, date, deadline, schedule, calendar, duration, time, count, quantity, id, budget, cost, price, revenue, invoice, payment, percent, score, rating, metrics, data, notes, description, video, image, photo, audio, file, document, attachment, link, email, phone, comment, message, location, country, address, travel, campaign, marketing, sales, product, keyword, views, engagement, goal, launch, project, shop, discount, code, bug, security, version, book, education, language, weather, home, vehicle, important, private, archive, settings, idea, edit. Leave it out when the table's own name already says the topic (a 'Content calendar' picks its glyph from the name), and set it when the name is evocative rather than literal. Pass 'none' only if the user asked for no icon. Anything outside this list is ignored and the name is used instead, so use a word from it rather than inventing an icon name."
},
"description": {
"type": "string",
"description": "Ticket description, a link's one-line summary, or a table's caption — the line under the grid saying what it holds or how to read it. Give every table one short sentence."
},
"folder_icon": {
"type": "string",
"description": "For folder only — the TOPIC of the folder, which picks its icon. Pick the closest one from: research, idea, strategy, planning, tasks, notes, meeting, launch, archive, inbox, templates, settings, design, writing, brand, photo, video, music, audio, marketing, sales, finance, budget, invoice, analytics, legal, clients, team, support, product, shop, engineering, bugs, security, data, cloud, travel, food, health, fitness, home, education, science, nature, mountain, camping, weather, transport, gear, events, gifts, reading, location, global, favourites, important, private, time, folder. Leave it out and the icon is chosen from the folder's name. Pass 'none' ONLY if the user said they do not want an icon. Anything outside this list falls back to a plain folder, so use a word from it rather than inventing an icon name."
},
"folder_color": {
"type": "string",
"description": "For folder only — its tile colour, one of: tan, blue, rose, purple, steel, brown, red, navy, violet, slate, coral, orange. LEAVE IT OUT WHENEVER YOU ARE MAKING SEVERAL FOLDERS: each then takes a colour of its own from its name, which is what lets a set of tiles be told apart at a glance. One word repeated across the set — or borrowed from the wall they sit in — makes them all look the same. Pass it for a single folder the user asked to colour. Pass 'none' ONLY if the user asked for no colour."
},
"highlight_color": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$",
"description": "Accent stripe along the top. Note, todo, heading, ticket and wall; ignored elsewhere. On a WALL this is how you theme a board you are building from nothing: pass the palette colour here and leave background_color off, and the wall carries the theme as a stripe, with no fill on the wall and no tint on the cards inside it. A wall you ARE filling never needs it: it gets its theme's stripe automatically, exactly as the canvas's own wall theme does, so background_color is the whole job there. On a TICKET, pass it to ASK for a stripe — when the ticket also carries a background_color the shade is taken from that same theme whatever you pass, so the two can never disagree. On a NOTE, TODO or HEADING the stripe is MARKING, not theming: it is snapped to the nearest of the twelve accent stripes rather than derived from the card's fill, because the point of it is that these cards go together and the card's own theme is not that. Omit it when the element has no theme and the board carries no colour pattern."
},
"background_color": {
"type": "string",
"pattern": "^(#[0-9a-fA-F]{6}|transparent)$",
"description": "Background of the card itself. Works on note, todo, heading, ticket and wall; ignored elsewhere.\nSET IT when the user asked for colour or a theme, and when the board already carries a pattern you are matching. OMIT it on a board you are building from nothing — a fresh board is themed through highlight_color on its walls instead, so the colour reads as an accent stripe rather than as a row of filled blocks nobody asked for. Omit it too when you are adding a few elements to a board that has no colour pattern of its own, and on cards inside a wall you have filled, which take their colour from that wall automatically.\nAny hex is accepted and is snapped to the nearest of the canvas's twelve themes (red, terracotta, amber, olive, green, emerald, teal, blue, indigo, violet, magenta, graphite), so name the colour you actually mean — a brand's real hex is the right thing to pass. The snap is what lets the colour flip correctly between light and dark mode; a raw hex could not.\n'transparent' is the exception to all of that and means something different: on a note or a todo it removes the card completely, leaving the text on the canvas with no box, no fill and no shadow. That is what a title or a label above a group of elements should look like, so use it for those without being asked. Ignored on every other type."
}
},
"additionalProperties": false
},
"maxItems": 40,
"minItems": 2,
"description": "Every box, each with the CELL it sits in. Read your own diagram out as a grid before you write it: count the columns left to right and the rows top to bottom, and give every node its `col` and `row`. A flow that runs left to right along one row is row 0 with rising `col`; one that runs down a column is col 0 with rising `row`; a flow that turns a corner uses both, which is what makes it read as a diagram rather than a queue. Leave a cell empty simply by not using it."
},
"place": {
"enum": [
"right",
"below"
],
"type": "string",
"default": "below",
"description": "Where the diagram goes relative to what is already on the board. 'below' puts it under everything, for a board that reads top to bottom; 'right' sets it beside the content, level with the top."
},
"connections": {
"type": "array",
"items": {
"type": "object",
"required": [
"from",
"to"
],
"properties": {
"to": {
"type": "string",
"maxLength": 40,
"description": "The `ref` of the element the arrow points at."
},
"from": {
"type": "string",
"maxLength": 40,
"description": "The `ref` of the element the arrow leaves."
},
"line": {
"enum": [
"curved",
"straight",
"stepped"
],
"type": "string",
"description": "The line's SHAPE. `stepped` is the right-angled connector a flowchart draws — across then down, never a diagonal — and it is what two nodes on the grid get unless you say otherwise. `straight` is a plain line between the two handles. `curved` is a sweep, which is what a hand-drawn arrow looks like and what an arrow between two walls should stay."
},
"color": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$",
"description": "The line's colour as a hex. It colours the LINE AND ITS LABEL together — the chip takes the line's colour and works out its own text contrast. Colour the lines that MEAN something apart from the rest: the automated path, the recovery route, the failure branch. Colouring them all says nothing."
},
"label": {
"type": "string",
"maxLength": 40,
"description": "The words ON the arrow — '2 weeks', 'Step 1', 'Clicks on genre'. The grid buys the run the chip needs out of the boundary the arrow crosses, so a label costs space rather than sitting across the boxes at either end."
},
"dashed": {
"type": "boolean",
"description": "TRUE for a dashed line, the convention for the path that is optional, automatic or a recovery route rather than the main flow."
},
"to_side": {
"$ref": "#/properties/connections/items/properties/from_side",
"description": "Which EDGE of the target the line arrives at. Same rule as `from_side`."
},
"from_side": {
"enum": [
"left",
"right",
"top",
"bottom"
],
"type": "string",
"description": "Which EDGE of the source the line leaves. Omit it and the side facing the other end is used, which is what a grid wants: a box above its next step leaves the bottom, one to its left leaves the right. Name it for the lines that do something else — one that drops out of the bottom and comes back up the left, one that leaves sideways to get around the box between."
}
},
"additionalProperties": false
},
"maxItems": 60,
"description": "Every arrow, as a pair of `ref`s. A diagram without them is a grid of cards: the arrows are what say it is a flow. Label the ones whose step is not obvious from the two boxes it joins."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description92/100
Create a whole mind map in one call: a central topic, branches and sub-branches, laid out and colored by the tool with connecting edges. You supply ONLY the content tree; never create mindmap notes or edges yourself. Node text is concise (3-8 words).
A NODE HOLDS 3-8 WORDS, so a request that names the SECTIONS it wants — premise, acts, characters, themes, arcs — is asking for a board of walls it can write paragraphs in, and the word "map" in it does not make it a mind map. Build those with walls and cards; reach here for a branching tree of short labels, or when they ask for a mind map by name.
THERE IS NO EXTEND. This always builds a WHOLE map, so "add more to this mind map" means deleting the one that is there and putting a replacement in its place — which costs every node the user dragged, and anything they attached to the old nodes. Ask before doing that, and if you do it, say it was REBUILT. Reporting a replacement as an expansion ("expanded the mindmap, keeping the same three branches") is a claim the layout itself contradicts the moment they look at it.
Explain mutations, irreversible effects, or prerequisites that matter before calling this tool.
Inputs91/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
central
The central topic (the root node's text).
Clear enough to supply this argument.
style
balanced = classic left/right map (default); right / down = pyramid.
Clear enough to supply this argument.
nodes › items › id
Your short unique id for this node (e.g. 'b1', 'b1a').
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
nodes › items › parent_id
The parent node's id. Omit for a top-level branch off the central topic.
Clear enough to supply this argument.
nodes › items › text
A short label, 3 to 8 words — not a sentence.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "create_mindmap",
"title": "Create mindmap",
"description": "Create a whole mind map in one call: a central topic, branches and sub-branches, laid out and colored by the tool with connecting edges. You supply ONLY the content tree; never create mindmap notes or edges yourself. Node text is concise (3-8 words).\n\nA NODE HOLDS 3-8 WORDS, so a request that names the SECTIONS it wants — premise, acts, characters, themes, arcs — is asking for a board of walls it can write paragraphs in, and the word \"map\" in it does not make it a mind map. Build those with walls and cards; reach here for a branching tree of short labels, or when they ask for a mind map by name.\n\nTHERE IS NO EXTEND. This always builds a WHOLE map, so \"add more to this mind map\" means deleting the one that is there and putting a replacement in its place — which costs every node the user dragged, and anything they attached to the old nodes. Ask before doing that, and if you do it, say it was REBUILT. Reporting a replacement as an expansion (\"expanded the mindmap, keeping the same three branches\") is a claim the layout itself contradicts the moment they look at it.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"central",
"nodes",
"project_uid"
],
"properties": {
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"text"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "Your short unique id for this node (e.g. 'b1', 'b1a')."
},
"text": {
"type": "string",
"minLength": 1,
"description": "A short label, 3 to 8 words — not a sentence."
},
"parent_id": {
"type": "string",
"description": "The parent node's id. Omit for a top-level branch off the central topic."
}
},
"additionalProperties": false
},
"maxItems": 60,
"minItems": 2
},
"style": {
"enum": [
"balanced",
"right",
"down"
],
"type": "string",
"description": "balanced = classic left/right map (default); right / down = pyramid."
},
"central": {
"type": "string",
"minLength": 1,
"description": "The central topic (the root node's text)."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description79/100
Create a whole constellation in one call: a radial web of rich notes (a central idea, themes, sub-notes) laid out and connected by the tool. You supply ONLY the content tree; never create constellation notes or edges yourself. 20-35 nodes make a good constellation; node text can be a sentence or two.
The description explains the capability, when to use it, and what to expect.
Inputs91/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
central
The central idea (the root note's text).
Clear enough to supply this argument.
nodes › items › id
Your short unique id for this node (e.g. 'b1', 'b1a').
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
nodes › items › parent_id
The parent node's id. Omit for a top-level branch off the central topic.
Clear enough to supply this argument.
nodes › items › text
The note's full content: a heading line then substantive paragraphs. Root 150-300 words, theme notes 100-200, sub-notes 80-150 — real, specific, information-dense.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "create_constellation",
"title": "Create constellation",
"description": "Create a whole constellation in one call: a radial web of rich notes (a central idea, themes, sub-notes) laid out and connected by the tool. You supply ONLY the content tree; never create constellation notes or edges yourself. 20-35 nodes make a good constellation; node text can be a sentence or two.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"central",
"nodes",
"project_uid"
],
"properties": {
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"text"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "Your short unique id for this node (e.g. 'b1', 'b1a')."
},
"text": {
"type": "string",
"minLength": 1,
"description": "The note's full content: a heading line then substantive paragraphs. Root 150-300 words, theme notes 100-200, sub-notes 80-150 — real, specific, information-dense."
},
"parent_id": {
"type": "string",
"description": "The parent node's id. Omit for a top-level branch off the central topic."
}
},
"additionalProperties": false
},
"maxItems": 60,
"minItems": 4
},
"central": {
"type": "string",
"minLength": 1,
"description": "The central idea (the root note's text)."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description88/100
Create an ORBIT in one call: a small central label with things ringed around it and a curved line drawn from the centre out to each one. ANY mix of cards can ring the hub — pictures, colour swatches, notes, links, videos, tickets, checklists, documents and folders — so this is the shape for 'everything about X in one place', as well as the film colour palette and inspiration wall the boards we ship use it for. It CANNOT be built by creating the pieces one at a time: free placement steps them diagonally across the canvas and nothing joins them up. Supply only the centre and the members; the tool owns every coordinate, the ring radius and every line.
Use create_color_palette instead when the user wants a plain palette block (a grid of swatches, no hub, no lines) — that is the commoner request. Use create_constellation for a web of substantial NOTES with sub-branches; an orbit is ONE ring of small things.
The description explains the capability, when to use it, and what to expect.
Inputs89/100
17 of 18 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
center
The hub's label — a couple of words naming what the ring is: 'Colors', 'Inspiration', 'Locations'. It is a small node, not a paragraph.
Clear enough to supply this argument.
center_color
Hub background. Omit to leave it neutral; pass the board's accent to tie it in.
Clear enough to supply this argument.
place
Where the ring goes relative to what is already on the board. 'right' sets it beside the content, level with the top — the loose region beside a row of walls. 'below' puts it under everything, for a board that reads top to bottom.
Clear enough to supply this argument.
members › items › type
What this member is. MIX THEM FREELY — a ring about one subject is usually several kinds: a picture, two notes, the brief as a document, the reference clip as a video. Only a palette ring is all one kind by nature.
image — a picture; image_url from find_images or generate_image, or omit it for an EMPTY frame the user drops their own into. Its `title` is the caption.
note — a few lines of prose in `text`. The default when nothing else fits.
color — a swatch; needs color_hex, and `text` names it ('Guards Red').
link — a real url from research or the user, with a `title` and a one-line `description`. Never a url you composed.
video — an embedded player (YouTube/Vimeo `url` plays inline); omit the url to ring an empty player the user pastes their own into.
ticket — one task or decision carrying a title, a description and optionally a date. todo — ONE card of checkboxes, every task on its own line in `text`.
document — a full document that opens for reading; `title` names it and `text` is its body. For anything longer than a note holds.
folder — a nested BOARD as a tile, for a member with a whole board's worth inside it. The call reports each folder's board id so you can build in it.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
members › items › text
Text for note/todo/heading, the document body, or a colour's caption.
Clear enough to supply this argument.
members › items › title
The member's own name: a link's label, a ticket's or document's title, a folder's name — and a PICTURE's caption, one line saying why this reference is here (the grade, the framing, the texture). An uncaptioned reference ring is a mood, not a brief. A colour's name goes in `text` instead, and never its hex: the swatch renders its own hex and RGB.
Clear enough to supply this argument.
members › items › description
Ticket description, a link's one-line summary, or a table's caption — the line under the grid saying what it holds or how to read it. Give every table one short sentence.
Clear enough to supply this argument.
members › items › url
For link and video. Must be a real URL that appeared in research results or that the user gave you — NEVER one you composed yourself. A url you can READ in a picture they attached counts as given: a board screenshot with 'vimeo.com/71977557' printed under its player is that url, and leaving the player empty beside a legible address drops something they handed you. One you infer from a title, complete from a domain, or remember is not. YouTube and Vimeo urls render as players.
Clear enough to supply this argument.
members › items › image_url
For image. A STORED IMAGE KEY: a generate_image or find_images result, or the imageUrl of a picture already on the board, read straight off a board read. Never a URL from anywhere else, which will not render. OMIT it to lay down an EMPTY frame: a placeholder the user can drop their own picture into, or ask you to fill later. Note that the two picture tools PLACE what they make themselves, so you rarely need this: pass it when you are building an element around a picture you already have — including one the board already holds, when the user points at it ("put the hero shot on each card"). Reusing the board's own picture costs nothing and is the same picture; finding or generating a second one is neither.
Clear enough to supply this argument.
members › items › color_hex
For colour swatches.
Explain the meaning of this value, not just its name.
members › items › date
Ticket due date, YYYY-MM-DD. Set it ONLY when the user stated a date or it follows directly from what they said; never infer or invent one.
Clear enough to supply this argument.
members › items › background_color
Background of the card itself. Works on note, todo, heading, ticket and wall; ignored elsewhere.
SET IT when the user asked for colour or a theme, and when the board already carries a pattern you are matching. OMIT it on a board you are building from nothing — a fresh board is themed through highlight_color on its walls instead, so the colour reads as an accent stripe rather than as a row of filled blocks nobody asked for. Omit it too when you are adding a few elements to a board that has no colour pattern of its own, and on cards inside a wall you have filled, which take their colour from that wall automatically.
Any hex is accepted and is snapped to the nearest of the canvas's twelve themes (red, terracotta, amber, olive, green, emerald, teal, blue, indigo, violet, magenta, graphite), so name the colour you actually mean — a brand's real hex is the right thing to pass. The snap is what lets the colour flip correctly between light and dark mode; a raw hex could not.
'transparent' is the exception to all of that and means something different: on a note or a todo it removes the card completely, leaving the text on the canvas with no box, no fill and no shadow. That is what a title or a label above a group of elements should look like, so use it for those without being asked. Ignored on every other type.
Clear enough to supply this argument.
members › items › labels › items › text
Not provided
Missing description. Explain what this value means and how to supply it.
members › items › labels › items › color_hex
OMIT and a colour is chosen for you. Pass one to put the pill in the board's colour family: any hex is snapped to the nearest canvas palette colour (#CDDFDD, #D0E3F7, #DDD6F1, #F7DCE4, #F8DDD9, #F3E4C5, #EACFD5, #D9DEE1). A label the user already owns keeps its own colour.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
members › items › folder_icon
For folder only — the TOPIC of the folder, which picks its icon. Pick the closest one from: research, idea, strategy, planning, tasks, notes, meeting, launch, archive, inbox, templates, settings, design, writing, brand, photo, video, music, audio, marketing, sales, finance, budget, invoice, analytics, legal, clients, team, support, product, shop, engineering, bugs, security, data, cloud, travel, food, health, fitness, home, education, science, nature, mountain, camping, weather, transport, gear, events, gifts, reading, location, global, favourites, important, private, time, folder. Leave it out and the icon is chosen from the folder's name. Pass 'none' ONLY if the user said they do not want an icon. Anything outside this list falls back to a plain folder, so use a word from it rather than inventing an icon name.
Clear enough to supply this argument.
members › items › folder_color
For folder only — its tile colour, one of: tan, blue, rose, purple, steel, brown, red, navy, violet, slate, coral, orange. LEAVE IT OUT WHENEVER YOU ARE MAKING SEVERAL FOLDERS: each then takes a colour of its own from its name, which is what lets a set of tiles be told apart at a glance. One word repeated across the set — or borrowed from the wall they sit in — makes them all look the same. Pass it for a single folder the user asked to colour. Pass 'none' ONLY if the user asked for no colour.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "create_orbit",
"title": "Create orbit",
"description": "Create an ORBIT in one call: a small central label with things ringed around it and a curved line drawn from the centre out to each one. ANY mix of cards can ring the hub — pictures, colour swatches, notes, links, videos, tickets, checklists, documents and folders — so this is the shape for 'everything about X in one place', as well as the film colour palette and inspiration wall the boards we ship use it for. It CANNOT be built by creating the pieces one at a time: free placement steps them diagonally across the canvas and nothing joins them up. Supply only the centre and the members; the tool owns every coordinate, the ring radius and every line.\nUse create_color_palette instead when the user wants a plain palette block (a grid of swatches, no hub, no lines) — that is the commoner request. Use create_constellation for a web of substantial NOTES with sub-branches; an orbit is ONE ring of small things.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"center",
"members",
"project_uid"
],
"properties": {
"place": {
"enum": [
"right",
"below"
],
"type": "string",
"default": "right",
"description": "Where the ring goes relative to what is already on the board. 'right' sets it beside the content, level with the top — the loose region beside a row of walls. 'below' puts it under everything, for a board that reads top to bottom."
},
"center": {
"type": "string",
"maxLength": 60,
"minLength": 1,
"description": "The hub's label — a couple of words naming what the ring is: 'Colors', 'Inspiration', 'Locations'. It is a small node, not a paragraph."
},
"members": {
"type": "array",
"items": {
"type": "object",
"required": [
"type"
],
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "For link and video. Must be a real URL that appeared in research results or that the user gave you — NEVER one you composed yourself. A url you can READ in a picture they attached counts as given: a board screenshot with 'vimeo.com/71977557' printed under its player is that url, and leaving the player empty beside a legible address drops something they handed you. One you infer from a title, complete from a domain, or remember is not. YouTube and Vimeo urls render as players."
},
"date": {
"type": "string",
"pattern": "^(\\d{4}-\\d{2}-\\d{2})?$",
"description": "Ticket due date, YYYY-MM-DD. Set it ONLY when the user stated a date or it follows directly from what they said; never infer or invent one."
},
"text": {
"type": "string",
"description": "Text for note/todo/heading, the document body, or a colour's caption."
},
"type": {
"enum": [
"note",
"image",
"color",
"link",
"video",
"ticket",
"todo",
"document",
"folder"
],
"type": "string",
"description": "What this member is. MIX THEM FREELY — a ring about one subject is usually several kinds: a picture, two notes, the brief as a document, the reference clip as a video. Only a palette ring is all one kind by nature.\nimage — a picture; image_url from find_images or generate_image, or omit it for an EMPTY frame the user drops their own into. Its `title` is the caption.\nnote — a few lines of prose in `text`. The default when nothing else fits.\ncolor — a swatch; needs color_hex, and `text` names it ('Guards Red').\nlink — a real url from research or the user, with a `title` and a one-line `description`. Never a url you composed.\nvideo — an embedded player (YouTube/Vimeo `url` plays inline); omit the url to ring an empty player the user pastes their own into.\nticket — one task or decision carrying a title, a description and optionally a date. todo — ONE card of checkboxes, every task on its own line in `text`.\ndocument — a full document that opens for reading; `title` names it and `text` is its body. For anything longer than a note holds.\nfolder — a nested BOARD as a tile, for a member with a whole board's worth inside it. The call reports each folder's board id so you can build in it."
},
"title": {
"type": "string",
"description": "The member's own name: a link's label, a ticket's or document's title, a folder's name — and a PICTURE's caption, one line saying why this reference is here (the grade, the framing, the texture). An uncaptioned reference ring is a mood, not a brief. A colour's name goes in `text` instead, and never its hex: the swatch renders its own hex and RGB."
},
"labels": {
"type": "array",
"items": {
"type": "object",
"required": [
"text"
],
"properties": {
"text": {
"type": "string",
"maxLength": 40,
"minLength": 1
},
"color_hex": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$",
"description": "OMIT and a colour is chosen for you. Pass one to put the pill in the board's colour family: any hex is snapped to the nearest canvas palette colour (#CDDFDD, #D0E3F7, #DDD6F1, #F7DCE4, #F8DDD9, #F3E4C5, #EACFD5, #D9DEE1). A label the user already owns keeps its own colour."
}
},
"additionalProperties": false
},
"maxItems": 4,
"description": "Small tag pills shown ON the card, for a status or category. Works on note, todo, wall, image, colour, file and video — not on a heading, which shows none. A ticket shows ONE chip and is NEVER built without it: pass a single label and it becomes the ticket's own. Name it for what the ticket IS on this board — its kind, phase, owner or what it is waiting on (Booking, Permit, Blocked, Week 2, Research) — read off the ticket's own title and description rather than repeating them. A ticket with no label draws an empty 'Label' slot on the card, so omitting one is never the neutral choice."
},
"color_hex": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$",
"description": "For colour swatches."
},
"image_url": {
"type": "string",
"description": "For image. A STORED IMAGE KEY: a generate_image or find_images result, or the imageUrl of a picture already on the board, read straight off a board read. Never a URL from anywhere else, which will not render. OMIT it to lay down an EMPTY frame: a placeholder the user can drop their own picture into, or ask you to fill later. Note that the two picture tools PLACE what they make themselves, so you rarely need this: pass it when you are building an element around a picture you already have — including one the board already holds, when the user points at it (\"put the hero shot on each card\"). Reusing the board's own picture costs nothing and is the same picture; finding or generating a second one is neither."
},
"description": {
"type": "string",
"description": "Ticket description, a link's one-line summary, or a table's caption — the line under the grid saying what it holds or how to read it. Give every table one short sentence."
},
"folder_icon": {
"type": "string",
"description": "For folder only — the TOPIC of the folder, which picks its icon. Pick the closest one from: research, idea, strategy, planning, tasks, notes, meeting, launch, archive, inbox, templates, settings, design, writing, brand, photo, video, music, audio, marketing, sales, finance, budget, invoice, analytics, legal, clients, team, support, product, shop, engineering, bugs, security, data, cloud, travel, food, health, fitness, home, education, science, nature, mountain, camping, weather, transport, gear, events, gifts, reading, location, global, favourites, important, private, time, folder. Leave it out and the icon is chosen from the folder's name. Pass 'none' ONLY if the user said they do not want an icon. Anything outside this list falls back to a plain folder, so use a word from it rather than inventing an icon name."
},
"folder_color": {
"type": "string",
"description": "For folder only — its tile colour, one of: tan, blue, rose, purple, steel, brown, red, navy, violet, slate, coral, orange. LEAVE IT OUT WHENEVER YOU ARE MAKING SEVERAL FOLDERS: each then takes a colour of its own from its name, which is what lets a set of tiles be told apart at a glance. One word repeated across the set — or borrowed from the wall they sit in — makes them all look the same. Pass it for a single folder the user asked to colour. Pass 'none' ONLY if the user asked for no colour."
},
"background_color": {
"type": "string",
"pattern": "^(#[0-9a-fA-F]{6}|transparent)$",
"description": "Background of the card itself. Works on note, todo, heading, ticket and wall; ignored elsewhere.\nSET IT when the user asked for colour or a theme, and when the board already carries a pattern you are matching. OMIT it on a board you are building from nothing — a fresh board is themed through highlight_color on its walls instead, so the colour reads as an accent stripe rather than as a row of filled blocks nobody asked for. Omit it too when you are adding a few elements to a board that has no colour pattern of its own, and on cards inside a wall you have filled, which take their colour from that wall automatically.\nAny hex is accepted and is snapped to the nearest of the canvas's twelve themes (red, terracotta, amber, olive, green, emerald, teal, blue, indigo, violet, magenta, graphite), so name the colour you actually mean — a brand's real hex is the right thing to pass. The snap is what lets the colour flip correctly between light and dark mode; a raw hex could not.\n'transparent' is the exception to all of that and means something different: on a note or a todo it removes the card completely, leaving the text on the canvas with no box, no fill and no shadow. That is what a title or a label above a group of elements should look like, so use it for those without being asked. Ignored on every other type."
}
},
"additionalProperties": false
},
"maxItems": 24,
"minItems": 2,
"description": "What rings the hub, in the order it should read clockwise from the right."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"center_color": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$",
"description": "Hub background. Omit to leave it neutral; pass the board's accent to tie it in."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description95/100
Put a COLOUR PALETTE on the board: several swatches laid out as a grid, in ONE call. This is how a palette is built — never several create_whiteboard_element calls with type 'color', which cannot make a grid and leaves the swatches in one long row running off the canvas. Each swatch shows its colour, the name you give it, and its hex and RGB values (those two are rendered from the hex, so do not write them into the name). Use it whenever the user asks for a palette, colour scheme, brand colours or swatches — including when you are reading the colours off a picture they attached. The swatches sit loose on the canvas as a block; to put colours INSIDE a wall instead, use create_whiteboard_element with a parent_uid.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
4 of 5 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
colors › items › name
What this colour is called — a real name like 'Cod Gray', 'Sea Mist' or 'Brand Red', or the role it plays ('Background', 'Primary accent'). Never 'Colour 1'.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
colors › items › hex
Not provided
Missing description. Explain what this value means and how to supply it.
columns
How many swatches per row. OMIT and a good shape is chosen from the count (four across for most palettes, a single row for six or fewer). Pass one only when the user asked for a specific shape.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "create_color_palette",
"title": "Create color palette",
"description": "Put a COLOUR PALETTE on the board: several swatches laid out as a grid, in ONE call. This is how a palette is built — never several create_whiteboard_element calls with type 'color', which cannot make a grid and leaves the swatches in one long row running off the canvas. Each swatch shows its colour, the name you give it, and its hex and RGB values (those two are rendered from the hex, so do not write them into the name). Use it whenever the user asks for a palette, colour scheme, brand colours or swatches — including when you are reading the colours off a picture they attached. The swatches sit loose on the canvas as a block; to put colours INSIDE a wall instead, use create_whiteboard_element with a parent_uid.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"colors",
"project_uid"
],
"properties": {
"colors": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"hex"
],
"properties": {
"hex": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$"
},
"name": {
"type": "string",
"maxLength": 40,
"minLength": 1,
"description": "What this colour is called — a real name like 'Cod Gray', 'Sea Mist' or 'Brand Red', or the role it plays ('Background', 'Primary accent'). Never 'Colour 1'."
}
},
"additionalProperties": false
},
"maxItems": 24,
"minItems": 2,
"description": "The palette, in the order it should read. A palette of one is not a palette; more than 24 is a colour list, not a palette someone can use."
},
"columns": {
"type": "integer",
"maximum": 8,
"minimum": 2,
"description": "How many swatches per row. OMIT and a good shape is chosen from the count (four across for most palettes, a single row for six or fewer). Pass one only when the user asked for a specific shape."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description94/100
Draw a LINE between groups of content so the board reads as separate sections — the vertical rule between a personal column and the team's columns, the line under a header row. Name what sits on each side and the line is measured and drawn for you: the sections are slid apart to make room, and the rule runs down the middle of that space, the height of the tallest thing it divides.
Use it when the user asks to divide, split or separate parts of a board, and when a board YOU have just built has two runs of content that belong to different people, time ranges or stages — a divider is what says they are different rather than a long row of walls.
Call it LAST, after everything it separates is on the board: it measures what is actually there, so a wall created afterwards lands on the wrong side of the line. Name the WALLS and other top-level elements, never the cards inside a wall.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
sections › items › element_uids
The top-level elements making up this section — wall uids, loose notes, images, folders. A card that lives inside a wall is not on the board's top level: name the wall instead.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "divide_board_sections",
"title": "Divide board sections",
"description": "Draw a LINE between groups of content so the board reads as separate sections — the vertical rule between a personal column and the team's columns, the line under a header row. Name what sits on each side and the line is measured and drawn for you: the sections are slid apart to make room, and the rule runs down the middle of that space, the height of the tallest thing it divides.\nUse it when the user asks to divide, split or separate parts of a board, and when a board YOU have just built has two runs of content that belong to different people, time ranges or stages — a divider is what says they are different rather than a long row of walls.\nCall it LAST, after everything it separates is on the board: it measures what is actually there, so a wall created afterwards lands on the wrong side of the line. Name the WALLS and other top-level elements, never the cards inside a wall.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"sections",
"project_uid"
],
"properties": {
"sections": {
"type": "array",
"items": {
"type": "object",
"required": [
"element_uids"
],
"properties": {
"element_uids": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 50,
"minItems": 1,
"description": "The top-level elements making up this section — wall uids, loose notes, images, folders. A card that lives inside a wall is not on the board's top level: name the wall instead."
}
},
"additionalProperties": false
},
"maxItems": 8,
"minItems": 2,
"description": "The sections to separate, one entry each. A line is drawn between every neighbouring pair, so three sections get two lines. Order does not matter — the sections are sorted by where they sit on the board."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description94/100
Build a shot list in the CARD format — a connected left-to-right row of shot walls, each holding its frame, a chips note, a 'Shots required' checklist, a scene-direction note and an equipment note, with an arrow to the next shot. Use this INSTEAD of many create_whiteboard_element calls whenever you are building shot cards: it is one call for the whole row, so a 20- or 40-shot list actually finishes. You supply the content of every shot; the tool owns the walls, card order, colours and arrows. Pass EVERY shot the user asked for in one call. WHEN THE PICTURES ARE ALREADY ON THE BOARD — selected, or asked for in words — pass each one's uid as that shot's image_element_uid in THIS call, so their own pictures become the frames. Moving them in after the call instead leaves the empty placeholder frame this tool built standing in every wall beside them. Never leave a selected picture without a shot.
The description explains the capability, when to use it, and what to expect.
Inputs79/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
heading
A title placed above the row, e.g. the production's name. Omit to add none.
Clear enough to supply this argument.
shots › items › title
The wall title — the shot number and a few words, e.g. "Shot 3 - Open train door".
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
shots › items › subject
One short line naming the subject and the setting, e.g. "Sam in the open train door. Dunes to the horizon." No heading, no second sentence.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
shots › items › chips
2 to 4 short chips for this shot: the size (Wide, Medium, Close Up, Aerial), the light or time (Golden Hour, Blue Hour, Studio, Daylight), and the camera or format (Sony FX3, 200mm, Drone).
Resolve the mismatch between this description and its schema constraints.
shots › items › coverage
The "Shots required" checklist: 3 to 5 concrete pieces of coverage this setup needs. Specific to this shot, never generic filler.
Resolve the mismatch between this description and its schema constraints.
shots › items › scene_heading
The scene this shot belongs to, e.g. "Scene 3" — becomes the direction card's heading.
Clear enough to supply this argument.
shots › items › scene_direction
One to three sentences of direction: what the camera does, what the moment is about, how it is lit.
Clear enough to supply this argument.
shots › items › equipment
The real gear this setup needs — body, lens with aperture, support, lighting, audio. e.g. ["Sony FX3", "24-70mm f/2.8", "Gimbal stabilizer", "Wireless audio"].
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
shots › items › image_url
A value returned by generate_image, or by find_images with source web and place_on_board false. OMIT it for an empty placeholder frame the user fills themselves. Web frames must also set frames_from_web on the call.
Clear enough to supply this argument.
shots › items › image_element_uid
The uid of a picture ALREADY on the board — the user's own — to move into this wall as its frame. Use this for every shot whose picture the user already has, whether they selected it or asked for the ones on the board: their pictures ARE the frames, and the uid here is what stops an empty frame being created in the wall first. It takes precedence over image_url, and nothing is generated or duplicated.
Clear enough to supply this argument.
frames_from_web
TRUE when the image_url values came from find_images with source web. Every frame is then captioned as reference, which is what keeps a real photograph from reading as footage the user already has. Never set it for generated frames.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "create_shot_cards",
"title": "Create shot cards",
"description": "Build a shot list in the CARD format — a connected left-to-right row of shot walls, each holding its frame, a chips note, a 'Shots required' checklist, a scene-direction note and an equipment note, with an arrow to the next shot. Use this INSTEAD of many create_whiteboard_element calls whenever you are building shot cards: it is one call for the whole row, so a 20- or 40-shot list actually finishes. You supply the content of every shot; the tool owns the walls, card order, colours and arrows. Pass EVERY shot the user asked for in one call. WHEN THE PICTURES ARE ALREADY ON THE BOARD — selected, or asked for in words — pass each one's uid as that shot's image_element_uid in THIS call, so their own pictures become the frames. Moving them in after the call instead leaves the empty placeholder frame this tool built standing in every wall beside them. Never leave a selected picture without a shot.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"shots",
"project_uid"
],
"properties": {
"shots": {
"type": "array",
"items": {
"type": "object",
"required": [
"title",
"subject",
"coverage",
"scene_heading",
"scene_direction",
"equipment"
],
"properties": {
"chips": {
"type": "array",
"items": {
"type": "string",
"maxLength": 40,
"minLength": 1
},
"maxItems": 4,
"description": "2 to 4 short chips for this shot: the size (Wide, Medium, Close Up, Aerial), the light or time (Golden Hour, Blue Hour, Studio, Daylight), and the camera or format (Sony FX3, 200mm, Drone)."
},
"title": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The wall title — the shot number and a few words, e.g. \"Shot 3 - Open train door\"."
},
"subject": {
"type": "string",
"maxLength": 300,
"minLength": 1,
"description": "One short line naming the subject and the setting, e.g. \"Sam in the open train door. Dunes to the horizon.\" No heading, no second sentence."
},
"coverage": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 8,
"minItems": 1,
"description": "The \"Shots required\" checklist: 3 to 5 concrete pieces of coverage this setup needs. Specific to this shot, never generic filler."
},
"equipment": {
"type": "array",
"items": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"maxItems": 10,
"minItems": 1,
"description": "The real gear this setup needs — body, lens with aperture, support, lighting, audio. e.g. [\"Sony FX3\", \"24-70mm f/2.8\", \"Gimbal stabilizer\", \"Wireless audio\"]."
},
"image_url": {
"type": "string",
"description": "A value returned by generate_image, or by find_images with source web and place_on_board false. OMIT it for an empty placeholder frame the user fills themselves. Web frames must also set frames_from_web on the call."
},
"scene_heading": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "The scene this shot belongs to, e.g. \"Scene 3\" — becomes the direction card's heading."
},
"scene_direction": {
"type": "string",
"maxLength": 600,
"minLength": 1,
"description": "One to three sentences of direction: what the camera does, what the moment is about, how it is lit."
},
"image_element_uid": {
"type": "string",
"description": "The uid of a picture ALREADY on the board — the user's own — to move into this wall as its frame. Use this for every shot whose picture the user already has, whether they selected it or asked for the ones on the board: their pictures ARE the frames, and the uid here is what stops an empty frame being created in the wall first. It takes precedence over image_url, and nothing is generated or duplicated."
}
},
"additionalProperties": false
},
"maxItems": 60,
"minItems": 1,
"description": "Every shot, in shooting order. One wall is built per entry."
},
"heading": {
"type": "string",
"maxLength": 120,
"description": "A title placed above the row, e.g. the production's name. Omit to add none."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
},
"frames_from_web": {
"type": "boolean",
"description": "TRUE when the image_url values came from find_images with source web. Every frame is then captioned as reference, which is what keeps a real photograph from reading as footage the user already has. Never set it for generated frames."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description91/100
Build a strip board — the shooting schedule — in ONE call: a wall per shoot day, a coloured strip per scene, in shooting order, each day totalled in pages and chained to the next by an arrow. Use this INSTEAD of individual create_whiteboard_element calls for any strip board or shooting schedule: pass EVERY day and every strip at once. Strip colours are the industry code (INT/EXT × day/night) and the tool sets them — never colour a strip yourself. Take scenes, page counts and cast from the script's SCENE INDEX (read_script_scenes) or the scene table on the board, never from memory of the prose.
The description explains the capability, when to use it, and what to expect.
Inputs89/100
10 of 11 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
heading
A title placed above the row — the production's name. Omit to add none.
Clear enough to supply this argument.
days › items › title
The wall title — "Day 1", or with its real date ONLY when the user gave one: "Day 1 — Mon 12 Aug".
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
days › items › strips › items › scene
The scene number as the script prints it — "24", "24A".
Clear enough to supply this argument.
days › items › strips › items › slugline
The scene heading as written — "INT. KITCHEN - NIGHT".
Clear enough to supply this argument.
days › items › strips › items › int_ext
Not provided
Missing description. Explain what this value means and how to supply it.
days › items › strips › items › time
A CONTINUOUS, LATER or SAME TIME slugline takes the time of the scene BEFORE it — resolve it from the running order, never guess.
Clear enough to supply this argument.
days › items › strips › items › pages
The scene's length in pages and eighths — "2 3/8", "3/8". From the scene index; omit when unknown.
Clear enough to supply this argument.
days › items › strips › items › cast
Speaking parts in the scene — "MARIA, TOM".
Clear enough to supply this argument.
days › items › strips › items › synopsis
One line of what happens, in the script's own terms.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "create_strip_board",
"title": "Create strip board",
"description": "Build a strip board — the shooting schedule — in ONE call: a wall per shoot day, a coloured strip per scene, in shooting order, each day totalled in pages and chained to the next by an arrow. Use this INSTEAD of individual create_whiteboard_element calls for any strip board or shooting schedule: pass EVERY day and every strip at once. Strip colours are the industry code (INT/EXT × day/night) and the tool sets them — never colour a strip yourself. Take scenes, page counts and cast from the script's SCENE INDEX (read_script_scenes) or the scene table on the board, never from memory of the prose.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"days",
"project_uid"
],
"properties": {
"days": {
"type": "array",
"items": {
"type": "object",
"required": [
"title",
"strips"
],
"properties": {
"title": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The wall title — \"Day 1\", or with its real date ONLY when the user gave one: \"Day 1 — Mon 12 Aug\"."
},
"strips": {
"type": "array",
"items": {
"type": "object",
"required": [
"scene",
"slugline",
"int_ext",
"time"
],
"properties": {
"cast": {
"type": "string",
"maxLength": 200,
"description": "Speaking parts in the scene — \"MARIA, TOM\"."
},
"time": {
"enum": [
"DAY",
"NIGHT",
"DUSK",
"DAWN",
"MORNING",
"EVENING"
],
"type": "string",
"description": "A CONTINUOUS, LATER or SAME TIME slugline takes the time of the scene BEFORE it — resolve it from the running order, never guess."
},
"pages": {
"type": "string",
"maxLength": 10,
"description": "The scene's length in pages and eighths — \"2 3/8\", \"3/8\". From the scene index; omit when unknown."
},
"scene": {
"type": "string",
"maxLength": 8,
"minLength": 1,
"description": "The scene number as the script prints it — \"24\", \"24A\"."
},
"int_ext": {
"enum": [
"INT",
"EXT",
"INT/EXT"
],
"type": "string"
},
"slugline": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The scene heading as written — \"INT. KITCHEN - NIGHT\"."
},
"synopsis": {
"type": "string",
"maxLength": 200,
"description": "One line of what happens, in the script's own terms."
}
},
"additionalProperties": false
},
"maxItems": 40,
"minItems": 1,
"description": "This day's scenes, in shooting order."
}
},
"additionalProperties": false
},
"maxItems": 30,
"minItems": 1,
"description": "Every shoot day, in shooting order."
},
"heading": {
"type": "string",
"maxLength": 120,
"description": "A title placed above the row — the production's name. Omit to add none."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description96/100
Put a DECK on the board: one element that shows one slide at a time, with every slide created under it. Each slide is a self-contained static HTML page at the deck's fixed slide size, written against the deck theme's CSS variables (--deck-bg, --deck-fg, --deck-accent, --deck-muted, --deck-font, --deck-scale) so one theme change re-skins every slide. The same hard constraints as create_html_app apply to every slide: no scripts, no external URLs, pictures as empty data-image-slot elements named in image_slots. The user edits slides by hand afterwards, presents the deck fullscreen and exports it as one PDF.
This is what a request for SLIDES builds — a pitch deck, a treatment, a lookbook, "a ten-page treatment" — not the PDF tools, which compose a file (ADR-0112). A social CAROUSEL post (Instagram, LinkedIn, TikTok slides) is not a deck: create_carousel_pages (ADR-0118). A shot list asked for by name is the card row create_shot_cards builds; only the design-shot-list workflow wants it as a deck.
A deck already on the board does not make a request an edit; what the user asked for decides. Asked to change THAT deck ("the deck", "my deck", "this slide", "it", add, remove or reorder slides, re-theme it): change it with update_html_app per slide, add_deck_slides, remove_deck_slides, reorder_deck_slides, update_deck for the theme, and never build a second deck beside one the user asked you to alter. Asked for A deck ("a new pitch deck", "another deck", "a deck from these images"): this tool, and the deck already there is left exactly as it is: none of its slides rewritten, filled or removed. Only a whole-deck redo that could mean either ("redo the pitch deck with these pictures") gets one question first, even though it names the deck: change the deck on the board, or build a new one beside it.
Pictures the user attached to their message go into the slides with fill_image_slot, not onto the board on their own.
The description explains the capability, when to use it, and what to expect.
Inputs36/100
6 of 14 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
title
Not provided
Missing description. Explain what this value means and how to supply it.
aspect
Asked once; every slide is designed at this size — 16:9 is 1280×720, 4:3 is 1280×960, A4 portrait is 794×1123 px.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
theme › palette › bg
Not provided
Missing description. Explain what this value means and how to supply it.
theme › palette › fg
Not provided
Missing description. Explain what this value means and how to supply it.
theme › palette › accent
Not provided
Missing description. Explain what this value means and how to supply it.
theme › palette › muted
Not provided
Missing description. Explain what this value means and how to supply it.
theme › fontStack
Not provided
Missing description. Explain what this value means and how to supply it.
theme › scale
Base type size in px at the slide's design width; 24 reads as a slide, 14-16 as a document page.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
slides › items › title
The slide's one idea; stored as the page's name.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
slides › items › html
The COMPLETE HTML document for this slide. html and body are sized to the slide BY THE DECK — 16:9 is 1280×720, 4:3 is 1280×960, A4 portrait is 794×1123 px — so never set their width or height yourself; design for that box. A slide number, the deck's length or the deck's title is written as an empty <span data-deck-slide-number></span>, <span data-deck-slide-count></span> or <span data-deck-title></span>, which the deck fills and keeps right when slides move; never as text. Lay out inside that box and never let content overflow it. Vertical margins AND padding in px, not per cent — a percentage one is a share of the WIDTH, so it lands far larger than it reads inside a panel shorter than it is wide. A box with a top margin cannot also be height: 100%, or it hangs off the bottom; and a panel with a fixed height needs a rule for where its content sits, or it falls to the top and leaves the rest of the panel empty. EVERY font-size is calc(var(--deck-scale)*N) — a title around 2.4, body 1, a caption 0.75 — never px: the deck's type controls set that variable and the render turns it down to fit a slide that overruns, and a size in px answers neither.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
slides › items › image_slots › items › id
Not provided
Missing description. Explain what this value means and how to supply it.
slides › items › image_slots › items › label
Not provided
Missing description. Explain what this value means and how to supply it.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "create_deck",
"title": "Create deck",
"description": "Put a DECK on the board: one element that shows one slide at a time, with every slide created under it. Each slide is a self-contained static HTML page at the deck's fixed slide size, written against the deck theme's CSS variables (--deck-bg, --deck-fg, --deck-accent, --deck-muted, --deck-font, --deck-scale) so one theme change re-skins every slide. The same hard constraints as create_html_app apply to every slide: no scripts, no external URLs, pictures as empty data-image-slot elements named in image_slots. The user edits slides by hand afterwards, presents the deck fullscreen and exports it as one PDF.\nThis is what a request for SLIDES builds — a pitch deck, a treatment, a lookbook, \"a ten-page treatment\" — not the PDF tools, which compose a file (ADR-0112). A social CAROUSEL post (Instagram, LinkedIn, TikTok slides) is not a deck: create_carousel_pages (ADR-0118). A shot list asked for by name is the card row create_shot_cards builds; only the design-shot-list workflow wants it as a deck.\nA deck already on the board does not make a request an edit; what the user asked for decides. Asked to change THAT deck (\"the deck\", \"my deck\", \"this slide\", \"it\", add, remove or reorder slides, re-theme it): change it with update_html_app per slide, add_deck_slides, remove_deck_slides, reorder_deck_slides, update_deck for the theme, and never build a second deck beside one the user asked you to alter. Asked for A deck (\"a new pitch deck\", \"another deck\", \"a deck from these images\"): this tool, and the deck already there is left exactly as it is: none of its slides rewritten, filled or removed. Only a whole-deck redo that could mean either (\"redo the pitch deck with these pictures\") gets one question first, even though it names the deck: change the deck on the board, or build a new one beside it.\nPictures the user attached to their message go into the slides with fill_image_slot, not onto the board on their own.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"title",
"aspect",
"slides",
"project_uid"
],
"properties": {
"theme": {
"type": "object",
"properties": {
"scale": {
"type": "integer",
"maximum": 48,
"minimum": 14,
"description": "Base type size in px at the slide's design width; 24 reads as a slide, 14-16 as a document page."
},
"palette": {
"type": "object",
"properties": {
"bg": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$"
},
"fg": {
"$ref": "#/properties/theme/properties/palette/properties/bg"
},
"muted": {
"$ref": "#/properties/theme/properties/palette/properties/bg"
},
"accent": {
"$ref": "#/properties/theme/properties/palette/properties/bg"
}
},
"additionalProperties": false
},
"fontStack": {
"type": "string",
"maxLength": 200,
"minLength": 3
}
},
"description": "Omit for the house neutral; pass the brand's colours when the board holds them.",
"additionalProperties": false
},
"title": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"aspect": {
"enum": [
"16:9",
"4:3",
"a4-portrait"
],
"type": "string",
"description": "Asked once; every slide is designed at this size — 16:9 is 1280×720, 4:3 is 1280×960, A4 portrait is 794×1123 px."
},
"slides": {
"type": "array",
"items": {
"type": "object",
"required": [
"title",
"html",
"image_slots"
],
"properties": {
"html": {
"type": "string",
"minLength": 20,
"description": "The COMPLETE HTML document for this slide. html and body are sized to the slide BY THE DECK — 16:9 is 1280×720, 4:3 is 1280×960, A4 portrait is 794×1123 px — so never set their width or height yourself; design for that box. A slide number, the deck's length or the deck's title is written as an empty <span data-deck-slide-number></span>, <span data-deck-slide-count></span> or <span data-deck-title></span>, which the deck fills and keeps right when slides move; never as text. Lay out inside that box and never let content overflow it. Vertical margins AND padding in px, not per cent — a percentage one is a share of the WIDTH, so it lands far larger than it reads inside a panel shorter than it is wide. A box with a top margin cannot also be height: 100%, or it hangs off the bottom; and a panel with a fixed height needs a rule for where its content sits, or it falls to the top and leaves the rest of the panel empty. EVERY font-size is calc(var(--deck-scale)*N) — a title around 2.4, body 1, a caption 0.75 — never px: the deck's type controls set that variable and the render turns it down to fit a slide that overruns, and a size in px answers neither."
},
"title": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The slide's one idea; stored as the page's name."
},
"image_slots": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"label"
],
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z0-9][a-z0-9-]{0,39}$"
},
"label": {
"type": "string",
"maxLength": 60,
"minLength": 1
}
},
"additionalProperties": false
},
"description": "Every data-image-slot in this slide's document."
}
},
"additionalProperties": false
},
"maxItems": 30,
"minItems": 1
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description91/100
Change a deck that is already on the board: its title, its aspect, or any part of its theme. A PATCH — pass only what changes, because the palette, font and type scale the user set by hand are all in here and sending the ones you did not mean to touch resets them. Re-theming re-skins every slide at once; you never rewrite slides to change a colour.
The description explains the capability, when to use it, and what to expect.
Inputs36/100
4 of 11 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
deck_uid
Not provided
Missing description. Explain what this value means and how to supply it.
title
Not provided
Missing description. Explain what this value means and how to supply it.
aspect
The deck's box. Changing it does NOT re-lay the slides: each keeps the composition it was drawn for, scaled to fit and centred in the new box with the deck's ground around it. When the user wants the slides to USE the new box, rewrite each with update_html_app afterwards.
Clear enough to supply this argument.
theme › palette › bg
Not provided
Missing description. Explain what this value means and how to supply it.
theme › palette › fg
Not provided
Missing description. Explain what this value means and how to supply it.
theme › palette › accent
Not provided
Missing description. Explain what this value means and how to supply it.
theme › palette › muted
Not provided
Missing description. Explain what this value means and how to supply it.
theme › fontStack
Not provided
Missing description. Explain what this value means and how to supply it.
theme › scale
Base type size in px at the slide's design width; 24 reads as a slide, 14-16 as a document page.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "update_deck",
"title": "Update deck",
"description": "Change a deck that is already on the board: its title, its aspect, or any part of its theme. A PATCH — pass only what changes, because the palette, font and type scale the user set by hand are all in here and sending the ones you did not mean to touch resets them. Re-theming re-skins every slide at once; you never rewrite slides to change a colour.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"deck_uid",
"project_uid"
],
"properties": {
"theme": {
"type": "object",
"properties": {
"scale": {
"type": "integer",
"maximum": 48,
"minimum": 14,
"description": "Base type size in px at the slide's design width; 24 reads as a slide, 14-16 as a document page."
},
"palette": {
"type": "object",
"properties": {
"bg": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$"
},
"fg": {
"$ref": "#/properties/theme/properties/palette/properties/bg"
},
"muted": {
"$ref": "#/properties/theme/properties/palette/properties/bg"
},
"accent": {
"$ref": "#/properties/theme/properties/palette/properties/bg"
}
},
"additionalProperties": false
},
"fontStack": {
"type": "string",
"maxLength": 200,
"minLength": 3
}
},
"additionalProperties": false
},
"title": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"aspect": {
"enum": [
"16:9",
"4:3",
"a4-portrait"
],
"type": "string",
"description": "The deck's box. Changing it does NOT re-lay the slides: each keeps the composition it was drawn for, scaled to fit and centred in the new box with the deck's ground around it. When the user wants the slides to USE the new box, rewrite each with update_html_app afterwards."
},
"deck_uid": {
"type": "string"
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description84/100
Add slides to a deck that already exists, written against the same theme variables as the rest (--deck-bg, --deck-fg, --deck-accent, --deck-muted, --deck-font, --deck-scale). Use this to grow a deck the user asked to extend; never build a second deck beside the first. A request for a new or another deck is create_deck, never slides added to this one.
The description explains the capability, when to use it, and what to expect.
Inputs44/100
4 of 8 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
deck_uid
Not provided
Missing description. Explain what this value means and how to supply it.
at_index
Insert before this slide position. Omit to append.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
slides › items › title
Not provided
Missing description. Explain what this value means and how to supply it.
slides › items › html
The COMPLETE HTML document for this slide. html and body are sized to the slide BY THE DECK — 16:9 is 1280×720, 4:3 is 1280×960, A4 portrait is 794×1123 px — so never set their width or height yourself; design for that box. A slide number, the deck's length or the deck's title is written as an empty <span data-deck-slide-number></span>, <span data-deck-slide-count></span> or <span data-deck-title></span>, which the deck fills and keeps right when slides move; never as text. Read the deck first for its aspect. Vertical margins and padding in px, not per cent, and a box with a top margin cannot also be height: 100%.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
slides › items › image_slots › items › id
Not provided
Missing description. Explain what this value means and how to supply it.
slides › items › image_slots › items › label
Not provided
Missing description. Explain what this value means and how to supply it.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "add_deck_slides",
"title": "Add deck slides",
"description": "Add slides to a deck that already exists, written against the same theme variables as the rest (--deck-bg, --deck-fg, --deck-accent, --deck-muted, --deck-font, --deck-scale). Use this to grow a deck the user asked to extend; never build a second deck beside the first. A request for a new or another deck is create_deck, never slides added to this one.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"deck_uid",
"slides",
"project_uid"
],
"properties": {
"slides": {
"type": "array",
"items": {
"type": "object",
"required": [
"title",
"html",
"image_slots"
],
"properties": {
"html": {
"type": "string",
"minLength": 20,
"description": "The COMPLETE HTML document for this slide. html and body are sized to the slide BY THE DECK — 16:9 is 1280×720, 4:3 is 1280×960, A4 portrait is 794×1123 px — so never set their width or height yourself; design for that box. A slide number, the deck's length or the deck's title is written as an empty <span data-deck-slide-number></span>, <span data-deck-slide-count></span> or <span data-deck-title></span>, which the deck fills and keeps right when slides move; never as text. Read the deck first for its aspect. Vertical margins and padding in px, not per cent, and a box with a top margin cannot also be height: 100%."
},
"title": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"image_slots": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"label"
],
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z0-9][a-z0-9-]{0,39}$"
},
"label": {
"type": "string",
"maxLength": 60,
"minLength": 1
}
},
"additionalProperties": false
},
"description": "Every data-image-slot in this slide's document."
}
},
"additionalProperties": false
},
"maxItems": 30,
"minItems": 1
},
"at_index": {
"type": "integer",
"minimum": 0,
"description": "Insert before this slide position. Omit to append."
},
"deck_uid": {
"type": "string"
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description94/100
Delete slides from a deck by uid and close the gap in the order. A deck has to keep at least one slide; to get rid of a whole deck, delete the deck element itself.
The description explains the capability, when to use it, and what to expect.
Inputs44/100
2 of 4 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
deck_uid
Not provided
Missing description. Explain what this value means and how to supply it.
slide_uids
Not provided
Missing description. Explain what this value means and how to supply it.
project_uid
Uid of the project to work in, from list_projects.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "remove_deck_slides",
"title": "Remove deck slides",
"description": "Delete slides from a deck by uid and close the gap in the order. A deck has to keep at least one slide; to get rid of a whole deck, delete the deck element itself.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"deck_uid",
"slide_uids",
"project_uid"
],
"properties": {
"deck_uid": {
"type": "string"
},
"slide_uids": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 30,
"minItems": 1
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": true
}
}
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "reorder_deck_slides",
"title": "Reorder deck slides",
"description": "Put a deck's slides in a new order. Pass EVERY slide uid, in the order you want them — a partial list is refused rather than guessed at.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"deck_uid",
"slide_uids",
"project_uid"
],
"properties": {
"deck_uid": {
"type": "string"
},
"slide_uids": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 200,
"minItems": 2,
"description": "All of the deck's slides, in the wanted order."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description96/100
Put a social CAROUSEL POST on the board: every slide as its own design page, laid out left to right in slide order, all at the post's fixed size. This is what "carousel posts", "a swipe post", "slides for Instagram / LinkedIn / TikTok" build — never create_deck, whose slides live inside one element and move with it. Once placed, the pages are independent: the user drags, deletes or edits any one alone, and update_html_app rewrites one. Each page is a self-contained static HTML document under the same constraints as create_html_app: no scripts, no external URLs, pictures as empty data-image-slot elements named in image_slots.
The description explains the capability, when to use it, and what to expect.
Inputs64/100
5 of 7 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
title
What the post is about, in a few words. Each page is named "<title> · 2/5".
Clear enough to supply this argument.
aspect
The post's shape, asked up front. 4:5 is 1080×1350, 1:1 is 1080×1080, 9:16 is 1080×1920, 16:9 is 1280×720 px; every slide is designed at that size.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
pages › items › html
The COMPLETE HTML document for this slide. html and body are sized to the post box for you, so never set their width or height; lay out inside the box and never let content overflow it — what overflows is cut off. Vertical margins and padding in px, not per cent. Every slide of the post shares one type scale, palette and margin.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
pages › items › image_slots › items › id
Not provided
Missing description. Explain what this value means and how to supply it.
pages › items › image_slots › items › label
Not provided
Missing description. Explain what this value means and how to supply it.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "create_carousel_pages",
"title": "Create carousel pages",
"description": "Put a social CAROUSEL POST on the board: every slide as its own design page, laid out left to right in slide order, all at the post's fixed size. This is what \"carousel posts\", \"a swipe post\", \"slides for Instagram / LinkedIn / TikTok\" build — never create_deck, whose slides live inside one element and move with it. Once placed, the pages are independent: the user drags, deletes or edits any one alone, and update_html_app rewrites one. Each page is a self-contained static HTML document under the same constraints as create_html_app: no scripts, no external URLs, pictures as empty data-image-slot elements named in image_slots.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"title",
"aspect",
"pages",
"project_uid"
],
"properties": {
"pages": {
"type": "array",
"items": {
"type": "object",
"required": [
"html",
"image_slots"
],
"properties": {
"html": {
"type": "string",
"minLength": 20,
"description": "The COMPLETE HTML document for this slide. html and body are sized to the post box for you, so never set their width or height; lay out inside the box and never let content overflow it — what overflows is cut off. Vertical margins and padding in px, not per cent. Every slide of the post shares one type scale, palette and margin."
},
"image_slots": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"label"
],
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z0-9][a-z0-9-]{0,39}$"
},
"label": {
"type": "string",
"maxLength": 60,
"minLength": 1
}
},
"additionalProperties": false
},
"description": "Every data-image-slot in this slide's document."
}
},
"additionalProperties": false
},
"maxItems": 20,
"minItems": 2,
"description": "Every slide, in the order they are swiped. At most 20: asked for more, build 20 and tell the user 20 is the limit — never ask about it or split the rest into another carousel."
},
"title": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "What the post is about, in a few words. Each page is named \"<title> · 2/5\"."
},
"aspect": {
"enum": [
"1:1",
"4:5",
"9:16",
"16:9"
],
"type": "string",
"description": "The post's shape, asked up front. 4:5 is 1080×1350, 1:1 is 1080×1080, 9:16 is 1080×1920, 16:9 is 1280×720 px; every slide is designed at that size."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description97/100
Search the board templates this app ships (Film Plan, Shotlist, Storyboard, Agency Hub, Moodboard, Second Brain and dozens more) and get back their names and uids. Use it when the user names a template, or when a request matches a board we already have a good shape for and starting from it beats building the shape from nothing. Returns candidates only — picking one and applying it is apply_board_template.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
3 of 4 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
keyword
Words from the template's NAME — 'film plan', 'shot list'. Descriptions are not searched.
Clear enough to supply this argument.
limit
Not provided
Missing description. Explain what this value means and how to supply it.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "find_board_template",
"title": "Find board template",
"description": "Search the board templates this app ships (Film Plan, Shotlist, Storyboard, Agency Hub, Moodboard, Second Brain and dozens more) and get back their names and uids. Use it when the user names a template, or when a request matches a board we already have a good shape for and starting from it beats building the shape from nothing. Returns candidates only — picking one and applying it is apply_board_template.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"keyword",
"project_uid"
],
"properties": {
"limit": {
"type": "integer",
"default": 8,
"maximum": 25,
"minimum": 1
},
"keyword": {
"type": "string",
"minLength": 2,
"description": "Words from the template's NAME — 'film plan', 'shot list'. Descriptions are not searched."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Put a whole shipped template onto the board the user is on, in one go, with its exact layout — every wall, card, colour and connection where the template puts them. Then it reads the board back and returns an inventory of what landed, with a uid for every element, so you can rewrite the cards for THIS user's subject with update_element.
The template arrives carrying its own worked example (Film Plan ships a North Face climbing commercial). That content is a starting point to REPLACE, not to leave: after applying, work through the inventory and rewrite every card that names the example's subject. Leaving it is worse than never applying, because the user is handed a stranger's production.
Only apply when the user asked for that template, or agreed to start from it. Never apply one speculatively onto a board that already has their work on it.
The description explains the capability, when to use it, and what to expect.
Inputs81/100
Explain the meaning of this value, not just its name.
template_uid
From find_board_template.
Explain the meaning of this value, not just its name.
template_name
The template's exact name, when a workflow recipe gave you one. Use this rather than searching first: it matches the name exactly, so it cannot land on a near-namesake.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "apply_board_template",
"title": "Apply board template",
"description": "Put a whole shipped template onto the board the user is on, in one go, with its exact layout — every wall, card, colour and connection where the template puts them. Then it reads the board back and returns an inventory of what landed, with a uid for every element, so you can rewrite the cards for THIS user's subject with update_element.\nThe template arrives carrying its own worked example (Film Plan ships a North Face climbing commercial). That content is a starting point to REPLACE, not to leave: after applying, work through the inventory and rewrite every card that names the example's subject. Leaving it is worse than never applying, because the user is handed a stranger's production.\nOnly apply when the user asked for that template, or agreed to start from it. Never apply one speculatively onto a board that already has their work on it.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid"
],
"properties": {
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"template_uid": {
"type": "string",
"minLength": 1,
"description": "From find_board_template."
},
"template_name": {
"type": "string",
"minLength": 2,
"description": "The template's exact name, when a workflow recipe gave you one. Use this rather than searching first: it matches the name exactly, so it cannot land on a near-namesake."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description78/100
Append to (or replace) the contents of a document by uid. Use this to fill a document you created on a board, one section per call, so it builds up rather than arriving all at once. For the document currently open on screen, use the editing tools instead.
Explain mutations, irreversible effects, or prerequisites that matter before calling this tool.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
element_uid
The uid returned by create_whiteboard_element: the element on the board, whose cached copy of the document has to be kept in step with the document itself. REQUIRED for a document that has a card on the board — without it that card keeps showing an empty document until the page is reloaded. Omit it ONLY for a document held in a table's document cell, which has no board element. Never invent one.
Clear enough to supply this argument.
document_uid
The document_uid returned by create_whiteboard_element, or the documentUid field on the card in a board read. NOT the element's own uid — that is the board card. The card's uid is accepted and resolved for you, and the result says so.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
html
The section to write, as HTML. Markdown is converted for you.
Clear enough to supply this argument.
mode
append adds to the end; replace overwrites the whole document.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "write_document_content",
"title": "Write document content",
"description": "Append to (or replace) the contents of a document by uid. Use this to fill a document you created on a board, one section per call, so it builds up rather than arriving all at once. For the document currently open on screen, use the editing tools instead.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"document_uid",
"project_uid",
"html"
],
"properties": {
"html": {
"type": "string",
"minLength": 1,
"description": "The section to write, as HTML. Markdown is converted for you."
},
"mode": {
"enum": [
"append",
"replace"
],
"type": "string",
"default": "append",
"description": "append adds to the end; replace overwrites the whole document."
},
"element_uid": {
"type": "string",
"minLength": 1,
"description": "The uid returned by create_whiteboard_element: the element on the board, whose cached copy of the document has to be kept in step with the document itself. REQUIRED for a document that has a card on the board — without it that card keeps showing an empty document until the page is reloaded. Omit it ONLY for a document held in a table's document cell, which has no board element. Never invent one."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"document_uid": {
"type": "string",
"minLength": 1,
"description": "The document_uid returned by create_whiteboard_element, or the documentUid field on the card in a board read. NOT the element's own uid — that is the board card. The card's uid is accepted and resolved for you, and the result says so."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description75/100
Give a document an icon and a banner image, the way a person would from the document header. Do this for documents YOU create — not for one the user made and you only edited.
icon takes a TOPIC WORD, not an icon name: research, idea, strategy, planning, tasks, notes, meeting, launch, archive, inbox, templates, settings, design, writing, brand, photo, video, music, audio, marketing, sales, finance, budget, invoice, analytics, legal, clients, team, support, product, shop, engineering, bugs, security, data, cloud, travel, food, health, fitness, home, education, science, nature, mountain, camping, weather, transport, gear, events, gifts, reading, location, global, favourites, important, private, time, folder. A word outside that list sets no icon and tells you so. It also accepts a stored image key to use a picture as the icon.
banner takes 'gradient' for one of the app's own gradients (free, and the right answer unless the subject genuinely wants a photograph), or a stored image key from find_document_images or generate_document_image. A url from the open web is refused: a cover comes from the same places the user's own picker offers.
Explain mutations, irreversible effects, or prerequisites that matter before calling this tool.
Inputs92/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
document_uid
The document's own uid — the documentUid field on its card in a board read, NOT the card's uid. The card's uid is accepted and resolved for you, and the result says so.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
icon
A topic word from the vocabulary, or a stored image key.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
banner
'gradient', or a stored image key.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
clear
Remove a cover the document already has. Leaving a field out never removes it.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "set_document_cover",
"title": "Set document cover",
"description": "Give a document an icon and a banner image, the way a person would from the document header. Do this for documents YOU create — not for one the user made and you only edited.\n\nicon takes a TOPIC WORD, not an icon name: research, idea, strategy, planning, tasks, notes, meeting, launch, archive, inbox, templates, settings, design, writing, brand, photo, video, music, audio, marketing, sales, finance, budget, invoice, analytics, legal, clients, team, support, product, shop, engineering, bugs, security, data, cloud, travel, food, health, fitness, home, education, science, nature, mountain, camping, weather, transport, gear, events, gifts, reading, location, global, favourites, important, private, time, folder. A word outside that list sets no icon and tells you so. It also accepts a stored image key to use a picture as the icon.\n\nbanner takes 'gradient' for one of the app's own gradients (free, and the right answer unless the subject genuinely wants a photograph), or a stored image key from find_document_images or generate_document_image. A url from the open web is refused: a cover comes from the same places the user's own picker offers.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"document_uid",
"project_uid"
],
"properties": {
"icon": {
"type": "string",
"minLength": 1,
"description": "A topic word from the vocabulary, or a stored image key."
},
"clear": {
"type": "array",
"items": {
"enum": [
"icon",
"banner"
],
"type": "string"
},
"description": "Remove a cover the document already has. Leaving a field out never removes it."
},
"banner": {
"type": "string",
"minLength": 1,
"description": "'gradient', or a stored image key."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"document_uid": {
"type": "string",
"minLength": 1,
"description": "The document's own uid — the documentUid field on its card in a board read, NOT the card's uid. The card's uid is accepted and resolved for you, and the result says so."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description97/100
Move whole notes into documents, keeping their text exactly as written. Use this whenever a note is long enough to be a document — roughly a screenful or more — and whenever the user asks for documents. NEVER retype a note's content into a new document yourself: that is slow, it risks dropping their words, and this does it as a move. The originals are deleted in the same undo step, so the board is left holding the documents and not both. Give wall_uid to file them into a wall you have already created.
The description explains the capability, when to use it, and what to expect.
Inputs97/100
Input documentation gives an agent enough context to populate the arguments.
element_uids
The notes to convert. Their content is moved verbatim; you never restate it.
Clear enough to supply this argument.
wall_uid
Wall to put the documents in. Omitted, they land beside what they came from.
Clear enough to supply this argument.
titles
One title per uid, in the same order. Omitted, each document is named from the note's own first heading — which is usually what the user already called it.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "convert_notes_to_documents",
"title": "Convert notes to documents",
"description": "Move whole notes into documents, keeping their text exactly as written. Use this whenever a note is long enough to be a document — roughly a screenful or more — and whenever the user asks for documents. NEVER retype a note's content into a new document yourself: that is slow, it risks dropping their words, and this does it as a move. The originals are deleted in the same undo step, so the board is left holding the documents and not both. Give wall_uid to file them into a wall you have already created.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"element_uids",
"project_uid"
],
"properties": {
"titles": {
"type": "array",
"items": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"description": "One title per uid, in the same order. Omitted, each document is named from the note's own first heading — which is usually what the user already called it."
},
"wall_uid": {
"type": "string",
"description": "Wall to put the documents in. Omitted, they land beside what they came from."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"element_uids": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 25,
"minItems": 1,
"description": "The notes to convert. Their content is moved verbatim; you never restate it."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description88/100
Create a project document and put it in one cell of a table's document column, so that cell opens the document. Use for 'give every episode an outline', 'add a script to each scene'. The cell shows the document's own name and icon — do NOT also write the title into a text cell. Fill the document afterwards with write_document_content, passing the returned document_uid and NO element_uid.
Describe the returned information so the agent knows whether it will answer the request.
Inputs86/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
table_uid
uid of the ToolTable element.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
row_index
0-based BODY row index. Row 0 is the first row under the header.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
column_index
0-based column index. The column must already be a document column.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
title
The document's name, shown in the cell.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
html
Optional starting content. Markdown is converted for you.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "create_document_in_table_cell",
"title": "Create document in table cell",
"description": "Create a project document and put it in one cell of a table's document column, so that cell opens the document. Use for 'give every episode an outline', 'add a script to each scene'. The cell shows the document's own name and icon — do NOT also write the title into a text cell. Fill the document afterwards with write_document_content, passing the returned document_uid and NO element_uid.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"table_uid",
"row_index",
"column_index",
"project_uid",
"title"
],
"properties": {
"html": {
"type": "string",
"description": "Optional starting content. Markdown is converted for you."
},
"title": {
"type": "string",
"minLength": 1,
"description": "The document's name, shown in the cell."
},
"row_index": {
"type": "integer",
"minimum": 0,
"description": "0-based BODY row index. Row 0 is the first row under the header."
},
"table_uid": {
"type": "string",
"minLength": 1,
"description": "uid of the ToolTable element."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"column_index": {
"type": "integer",
"minimum": 0,
"description": "0-based column index. The column must already be a document column."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description82/100
Point a cell of a table's document column at a project document that already exists. Find candidates with list_documents. To create a new one instead, use create_document_in_table_cell.
The description explains the capability, when to use it, and what to expect.
Inputs88/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
table_uid
uid of the ToolTable element.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
row_index
0-based BODY row index. Row 0 is the first row under the header.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
column_index
0-based column index. The column must already be a document column.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
document_uid
uid of an existing project document.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "put_document_in_table_cell",
"title": "Put document in table cell",
"description": "Point a cell of a table's document column at a project document that already exists. Find candidates with list_documents. To create a new one instead, use create_document_in_table_cell.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"table_uid",
"row_index",
"column_index",
"project_uid",
"document_uid"
],
"properties": {
"row_index": {
"type": "integer",
"minimum": 0,
"description": "0-based BODY row index. Row 0 is the first row under the header."
},
"table_uid": {
"type": "string",
"minLength": 1,
"description": "uid of the ToolTable element."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"column_index": {
"type": "integer",
"minimum": 0,
"description": "0-based column index. The column must already be a document column."
},
"document_uid": {
"type": "string",
"minLength": 1,
"description": "uid of an existing project document."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "clear_document_from_table_cell",
"title": "Clear document from table cell",
"description": "Empty a cell of a table's document column. The document itself is NOT deleted — it stays in the project's documents and can be put back.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"table_uid",
"row_index",
"column_index",
"project_uid"
],
"properties": {
"row_index": {
"type": "integer",
"minimum": 0,
"description": "0-based BODY row index. Row 0 is the first row under the header."
},
"table_uid": {
"type": "string",
"minLength": 1,
"description": "uid of the ToolTable element."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"column_index": {
"type": "integer",
"minimum": 0,
"description": "0-based column index. The column must already be a document column."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
Rehouse elements that are ALREADY on the board into walls — the whole plan in ONE call. Each group either makes a new wall (title) or files into a wall already there (wall_uid), and the elements are MOVED, so the user keeps the cards they wrote and the board holds no copies.
This is how a board gets organized. Never do it as a run of create_whiteboard_element + move_element calls: fifty cards is fifty round trips, the user watches it crawl, and a turn that runs out of room leaves the board half sorted. A new wall joins the board's wall row, or — on a board with no walls yet — lands beside the material it holds. Every write shares this turn's single undo step.
It moves elements and names walls. It never writes, rewrites or splits what the user wrote.
The receipt carries `still_loose`: how many fileable cards are STILL on the canvas after your plan ran. Cards you meant to leave out are in that number too, so read it against what you intended — if it is higher than that, the plan missed cards and a second call files them.
The description explains the capability, when to use it, and what to expect.
Inputs92/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
groups › items › title
Name for a NEW wall, in the user's own vocabulary. Omit when wall_uid is given. 'Group 1', 'Other' and 'Miscellaneous' are failures — name the theme you actually found.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
groups › items › wall_uid
An EXISTING wall to file these into, appended after its current cards. Use this whenever the board already has a wall for the theme rather than making a second one.
Clear enough to supply this argument.
groups › items › highlight_color
Hex for a new wall's theme; its cards adopt the matching child colour. Omit it and the wall takes the next colour from the tool's own palette — pass one only to match a colour scheme the board already has.
Clear enough to supply this argument.
groups › items › element_uids
The elements to rehouse. A NEW wall holds them in this order; an existing wall keeps what it has and appends them after it, in this order.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "group_into_walls",
"title": "Group into walls",
"description": "Rehouse elements that are ALREADY on the board into walls — the whole plan in ONE call. Each group either makes a new wall (title) or files into a wall already there (wall_uid), and the elements are MOVED, so the user keeps the cards they wrote and the board holds no copies.\n\nThis is how a board gets organized. Never do it as a run of create_whiteboard_element + move_element calls: fifty cards is fifty round trips, the user watches it crawl, and a turn that runs out of room leaves the board half sorted. A new wall joins the board's wall row, or — on a board with no walls yet — lands beside the material it holds. Every write shares this turn's single undo step.\n\nIt moves elements and names walls. It never writes, rewrites or splits what the user wrote.\n\nThe receipt carries `still_loose`: how many fileable cards are STILL on the canvas after your plan ran. Cards you meant to leave out are in that number too, so read it against what you intended — if it is higher than that, the plan missed cards and a second call files them.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"groups",
"project_uid"
],
"properties": {
"groups": {
"type": "array",
"items": {
"type": "object",
"required": [
"element_uids"
],
"properties": {
"title": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "Name for a NEW wall, in the user's own vocabulary. Omit when wall_uid is given. 'Group 1', 'Other' and 'Miscellaneous' are failures — name the theme you actually found."
},
"wall_uid": {
"type": "string",
"description": "An EXISTING wall to file these into, appended after its current cards. Use this whenever the board already has a wall for the theme rather than making a second one."
},
"element_uids": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 50,
"minItems": 1,
"description": "The elements to rehouse. A NEW wall holds them in this order; an existing wall keeps what it has and appends them after it, in this order."
},
"highlight_color": {
"type": "string",
"description": "Hex for a new wall's theme; its cards adopt the matching child colour. Omit it and the wall takes the next colour from the tool's own palette — pass one only to match a colour scheme the board already has."
}
},
"additionalProperties": false
},
"maxItems": 12,
"minItems": 1,
"description": "One entry per wall. Aim for 4 to 7 on a whole-board organize."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description96/100
Put pictures you already have the addresses of onto the board: photos from your own web search, images on a page the user shared, links the user pasted. Storyflow downloads each one and keeps its own copy in the user's gallery, so it stays on the board after the link dies. Pass the image file's own address (ends in .jpg, .png, .webp or serves an image), not the page it sits on.
BY DEFAULT IT PLACES THE PICTURES ITSELF, loose or inside parent_uid; do not create image elements for them afterwards. To fill an EMPTY image frame already on the board, pass one image and its target_uid. When the pictures go into something you build (deck slides, orbit members, shot-card frames, one picture per wall across several walls), pass place_on_board: false and use the image_url values it returns.
Only use addresses you actually found or were given, never invented ones. An address that could not be stored comes back in `missing`: say which, and offer to try another link.
Describe the returned information so the agent knows whether it will answer the request.
Inputs96/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
images › items › url
The image's own address, from your search or from the user.
Clear enough to supply this argument.
aspect
Shape for the set. Every picture is CROPPED to this shape's exact ratio (landscape 4:3, portrait 3:4, square 1:1), so the whole batch lands as uniform tiles. Pass the SAME one for every picture in a set — uniform tiles are what makes a moodboard read as a board rather than scattered pictures. A batch of two or more defaults to landscape; omit it on a SINGLE picture to keep the image's natural shape.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
parent_uid
Put the pictures inside this wall. Omit to place them loose on the canvas.
Clear enough to supply this argument.
target_uid
An EMPTY image frame already on the board to fill. Only with a SINGLE image; the picture lands in THAT frame and parent_uid is not used.
Clear enough to supply this argument.
place_on_board
Defaults to TRUE: each picture is placed on the board as its own image element, loose or inside parent_uid.
Set it FALSE when the pictures are going to be BUILT INTO SOMETHING ELSE and you just need their image_url values back — create_orbit members, create_shot_cards frames, one picture per wall across several different walls, a folder_cover_image. Placing and then building would leave every picture on the board TWICE: once loose where this tool dropped it, once inside the thing you built.
Clear enough to supply this argument.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "add_images",
"title": "Add images",
"description": "Put pictures you already have the addresses of onto the board: photos from your own web search, images on a page the user shared, links the user pasted. Storyflow downloads each one and keeps its own copy in the user's gallery, so it stays on the board after the link dies. Pass the image file's own address (ends in .jpg, .png, .webp or serves an image), not the page it sits on.\n\nBY DEFAULT IT PLACES THE PICTURES ITSELF, loose or inside parent_uid; do not create image elements for them afterwards. To fill an EMPTY image frame already on the board, pass one image and its target_uid. When the pictures go into something you build (deck slides, orbit members, shot-card frames, one picture per wall across several walls), pass place_on_board: false and use the image_url values it returns.\n\nOnly use addresses you actually found or were given, never invented ones. An address that could not be stored comes back in `missing`: say which, and offer to try another link.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"images",
"project_uid"
],
"properties": {
"aspect": {
"enum": [
"square",
"landscape",
"portrait"
],
"type": "string",
"description": "Shape for the set. Every picture is CROPPED to this shape's exact ratio (landscape 4:3, portrait 3:4, square 1:1), so the whole batch lands as uniform tiles. Pass the SAME one for every picture in a set — uniform tiles are what makes a moodboard read as a board rather than scattered pictures. A batch of two or more defaults to landscape; omit it on a SINGLE picture to keep the image's natural shape."
},
"images": {
"type": "array",
"items": {
"type": "object",
"required": [
"url"
],
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "The image's own address, from your search or from the user."
}
},
"additionalProperties": false
},
"maxItems": 12,
"minItems": 1,
"description": "One entry per picture, in the order they should land."
},
"parent_uid": {
"type": "string",
"description": "Put the pictures inside this wall. Omit to place them loose on the canvas."
},
"target_uid": {
"type": "string",
"description": "An EMPTY image frame already on the board to fill. Only with a SINGLE image; the picture lands in THAT frame and parent_uid is not used."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"place_on_board": {
"type": "boolean",
"description": "Defaults to TRUE: each picture is placed on the board as its own image element, loose or inside parent_uid.\nSet it FALSE when the pictures are going to be BUILT INTO SOMETHING ELSE and you just need their image_url values back — create_orbit members, create_shot_cards frames, one picture per wall across several different walls, a folder_cover_image. Placing and then building would leave every picture on the board TWICE: once loose where this tool dropped it, once inside the thing you built."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description100/100
Create a new, empty Storyflow project with the given title, the same way the app's New project button does: it comes with its root board. Returns the new project's uid; pass it as project_uid to the board and document tools to fill it in. Use only when the user asks for a new project.
The description explains the capability, when to use it, and what to expect.
Inputs99/100
Input documentation gives an agent enough context to populate the arguments.
title
The project's name, exactly as the user wants it.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "create_project",
"title": "Create project",
"description": "Create a new, empty Storyflow project with the given title, the same way the app's New project button does: it comes with its root board. Returns the new project's uid; pass it as project_uid to the board and document tools to fill it in. Use only when the user asks for a new project.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"title"
],
"properties": {
"title": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "The project's name, exactly as the user wants it."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
A picture the user attached in this chat never reaches Storyflow: you see it, Storyflow cannot. Call this to let them put pictures from their phone or computer on a board in one tap. It returns a link good for 15 minutes; put it in your reply as a link whose text is "Add your photos". The user taps it, picks any number of pictures, and each one lands on the board as it uploads, visible in the board card and in Storyflow. Pass target_uids for empty frames you placed for them, or parent_uid for the wall the pictures belong in; with neither, a wall is made for them when the first picture arrives. Never tell the user Storyflow cannot take their photo, and never ask them to upload inside Storyflow.
The description explains the capability, when to use it, and what to expect.
Inputs98/100
Input documentation gives an agent enough context to populate the arguments.
project_uid
Uid of the project to work in, from list_projects.
Clear enough to supply this argument.
whiteboard_uid
Uid of the board inside that project, from list_boards. Omit or pass "" for the project's root board.
Clear enough to supply this argument.
target_uids
Empty image frames already on the board, in the order the pictures should fill them: the frames you placed for the pictures the user attached. Omit when there are none.
Clear enough to supply this argument.
parent_uid
The wall the pictures join once the frames are filled, or all of them when there are no frames.
Clear enough to supply this argument.
title
What the pictures are, for the wall made for them when you name no wall and the frames run out: 'Korea food', 'Day 4'.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "request_photo_upload",
"title": "Add photos from the user's device",
"description": "A picture the user attached in this chat never reaches Storyflow: you see it, Storyflow cannot. Call this to let them put pictures from their phone or computer on a board in one tap. It returns a link good for 15 minutes; put it in your reply as a link whose text is \"Add your photos\". The user taps it, picks any number of pictures, and each one lands on the board as it uploads, visible in the board card and in Storyflow. Pass target_uids for empty frames you placed for them, or parent_uid for the wall the pictures belong in; with neither, a wall is made for them when the first picture arrives. Never tell the user Storyflow cannot take their photo, and never ask them to upload inside Storyflow.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"project_uid"
],
"properties": {
"title": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "What the pictures are, for the wall made for them when you name no wall and the frames run out: 'Korea food', 'Day 4'."
},
"parent_uid": {
"type": "string",
"description": "The wall the pictures join once the frames are filled, or all of them when there are no frames."
},
"project_uid": {
"type": "string",
"minLength": 1,
"description": "Uid of the project to work in, from list_projects."
},
"target_uids": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 200,
"description": "Empty image frames already on the board, in the order the pictures should fill them: the frames you placed for the pictures the user attached. Omit when there are none."
},
"whiteboard_uid": {
"type": "string",
"description": "Uid of the board inside that project, from list_boards. Omit or pass \"\" for the project's root board."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description92/100
Search the user's Storyflow projects, boards and documents by title. Returns ids for fetch: project:<uid>, board:<project_uid>/<whiteboard_uid>, document:<project_uid>/<uid>.
The description explains the capability, when to use it, and what to expect.
Inputs0/100
0 of 1 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values.
query
Not provided
Missing description. Explain what this value means and how to supply it.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "fetch",
"title": "Fetch",
"description": "Fetch one record by an id returned from search: a project, a board's elements or a document.",
"inputSchema": {
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"id"
],
"properties": {
"id": {
"type": "string"
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
Loading score analytics…
Put your MCP to the test
A few tasks worth trying with this server, chosen from its reviewed tools. These have not been run.
01List projectsList the user's Flow projects — the top-level containers holding whiteboards, documents and tactics.
02SearchSearch the user's Storyflow projects, boards and documents by title.
03List boardsList a project's boards as a tree: each folder's board with its name, uid (pass it as whiteboard_uid), parent board and the folder element that opens it.
04Get whiteboard elementsRead what is on a board, with the real text of each element: notes, todos, headings, tickets, tables, documents, tactics, frames and walls.
05Get projectFetch a single project by uid, including title, status and the user's permission level.
Want to run these tasks against your MCP server with us?
storyflow setup, tools, quality score, publishing readiness, and alternatives.
How do I add storyflow to Claude, ChatGPT, or Cursor?
Add storyflow to Claude, ChatGPT, or Cursor by connecting its remote MCP URL in each client's MCP settings. In Claude, add a custom connector. In ChatGPT, add an MCP app. In Cursor, add an MCP server under Settings. The MCP URL is https://mcp.storyflow.so/mcp.
Is storyflow MCP ready for ChatGPT and Claude?
As of October 15, 2026, storyflow scores 96/100 on Manufact's MCP publishing checklist. The scan meets ChatGPT publishing checks and meets Claude publishing checks. Passing these checks does not guarantee marketplace approval.
How clear is storyflow's MCP tool documentation?
As of October 15, 2026, storyflow scores 78/100 in Manufact's review of tool titles, descriptions, input and output schemas, and behavior annotations. The review covers 56 of 56 discovered tools. The quality score measures documentation clarity; runtime behavior and marketplace readiness require separate checks.
What are the best alternatives to storyflow?
As of October 16, 2026, alternatives to storyflow in design-creative on the Manufact MCP catalog include Motion, MotionVid, Sleek, Streamloop MCP, and Image Generation.
How can storyflow improve its MCP documentation?
fetch is the lowest-scoring reviewed tool at 49/100. 0 of 1 inputs have descriptions. Add descriptions to the missing inputs, including where to obtain IDs and how to supply values. Open its review for feedback and a copyable fix prompt, then rerun the documentation review after updating your tool metadata.
Not your MCP?
Review any public or OAuth MCP server for protocol compatibility, tool documentation, and ChatGPT and Claude publishing readiness. No account required.