Open source infinite canvas — Canvas 2D + Yjs CRDT. A collaborative workspace application with boards, documents, and projects.
Tuval exposes 14 REST-style tools with basic descriptions but critical gaps in schema completeness and parameter documentation. Tool names lack action verbs (e.g., 'GET /records' instead of 'list_records'). Most parameters have type and description, but several tools lack input schemas entirely (e.g., GET /cycles, GET /labels, GET /boards have empty input objects). Descriptions are present but generic (10-100 chars, below the 50-200 char baseline for LLM optimization). No output schemas documented. Error handling is minimal, no recovery guidance or actionable error messages. Security concerns: API keys passed as bearer tokens in headers (correct), but no mention of rate limiting or permission gates. The code comment warns about untrusted user content but does not translate to tool-level safeguards.
Delete a board
Delete a record
List boards in the workspace
Get a board by ID
List cycles in the workspace
List labels in the workspace
List records in the workspace
Get a single record by ID
Tool names do not start with action verbs. REST paths like 'GET /records' should be 'list_records', 'GET /records/<id>' should be 'get_record'. LLMs infer intent from verb-noun naming; HTTP method + path is opaque.
Three tools (GET /cycles, GET /labels, GET /boards) have empty input schemas ({}). These tools should document what filters or pagination they accept.
No output schemas documented for any tool. LLMs cannot plan downstream calls or extract required fields (e.g., record_id for chaining). Responses are inferred from code but not declared in tool definitions.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | F | 36 | 2026-07-28+ | v2 |
Get markdown representation of a record
Search records by query
Update a board. The same board again. An integration that publishes every sprint had to make a new board each run and could not tidy up the old ones.
Update a record
Create a new board from a brief. The items are not made here: the canvas is a CRDT this door cannot compose, so the brief waits on the row and the first browser to open the board draws it.
Create a new record
Descriptions are generic and under 50 characters (e.g., 'List records in the workspace', 'Get a single record by ID'). Baseline for LLM-optimized descriptions is 50 - 200 chars with context on WHEN to use and WHAT it returns.
No error handling guidance. Code returns JSON errors (e.g., 'That key is not valid') but tools do not document what errors are possible, whether they are retryable, or what the LLM should do next. Per pattern:recovery-guide, errors must guide recovery.