Canvas-based AI generation studio powered by MCP providers — a desktop app that wires AI generation providers into one workflow with an agent terminal inside
Atoll defines 8 tools with clear, domain-specific names (canvas_state, canvas_add_node, canvas_run, job_wait) that follow verb_noun conventions. All tools have descriptions (avg ~120 chars, within baseline 34 - 392). Input schemas are present and properly typed with enums where appropriate (e.g., canvas_add_node.kind, list_models.output_type). However, parameter descriptions are sparse or missing context: canvas_add_node.values lacks detail on expected field structure; canvas_set_value.value has no type hint or format guidance; job_wait.timeoutSeconds lacks min/max bounds. Output schemas are undocumented, LLMs cannot infer what canvas_state returns or what job_wait yields. Error handling is absent: no guidance on retryability, user-fixable vs fatal errors, or recovery paths. Tool composition is sound (single responsibility, proper chaining via nodeId/jobId), but lack of output documentation and error recovery patterns limits production readiness.
Add a node to the canvas. When kind=model, ref is a model id from list_models. Use the returned nodeId to set values, connect, and run.
Connect a node output to another node's input port. Types must match (image output → image input).
Remove a connection.
Run a generation (model) node — this spends real credits. Pending result nodes are created automatically and jobIds are returned. Wait for completion with job_wait.
Set a node field value (prompt, options, etc.). Check field names with canvas_state first.
Read the current canvas graph — nodes (kind, model, values, status) and connections. Always check this before making changes. The id in @atoll:node/<id> pasted by the user matches the node ids here.
Output schemas undocumented. canvas_state, list_models, canvas_run, and job_wait lack documented return types. LLMs cannot plan downstream tool calls or extract required fields (e.g., nodeId from canvas_add_node, jobId from canvas_run, result URLs from job_wait).
Parameter descriptions lack format/constraint guidance. canvas_add_node.values is described as 'Initial field values (e.g. {"prompt": "..."})' but does not specify which fields are valid, required, or type-constrained. canvas_set_value.value has no type hint. job_wait.timeoutSeconds lacks min/max bounds (default 180 is stated but range is not).
No error handling or recovery guidance. Tools lack descriptions of failure modes, retryability, or next steps. canvas_run is marked IRREVERSIBLE but provides no confirmation pattern or dry-run option. job_wait timeout or failure scenarios are not documented.
Inferred effective spec: 2025-06-18+.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 64 | 2025-06-18+ | v2 |
Wait for a generation job to settle (default 180 seconds). Returns result URLs on completion, or the failure reason.
Catalog of available generation models — id (ref), name, output type (image/video/audio/3d), description. Use the id as the ref for canvas_add_node.
Tool composition assumes agent knowledge of internal state. canvas_add_node returns nodeId but description does not state this; canvas_run returns jobIds but job_wait expects jobId, the connection is implicit, not documented.
canvas_set_value.name parameter lacks enum or discovery mechanism. LLM must call canvas_state first to learn valid field names; no guidance on this dependency is provided in the description.