Velloo documentation
Markdown for LLMs ↗MCP: discovery
Read operations. List and fetch screens, boards, the component and snippet catalogue, canvas fidelity, the preview entry, the theme, annotations, notes, and comment threads, and query a screen tree with find_nodes.
Discovery operations are reads. With one exception they never mutate the design folder, and they are the recommended first calls of any session: list_components (index mode), get_theme, and list_boards, plus component_status before claiming an app component renders exactly. In a folder whose app has components of its own, preview_status comes first of all.
The exception is set_preview_entry, documented here beside the preview_status check it reruns rather than on the mutations page.
list_screens
List every screen in the design folder.
| Arg | Type | Required | Description |
|---|---|---|---|
includeTree | boolean | no | Embed each screen’s full tree: one round-trip instead of list_screens plus N get_screen calls. Default false |
Returns { screens: [{ id, name, tree? }] }.
get_screen
Return the JSON for a single screen.
| Arg | Type | Required | Description |
|---|---|---|---|
screenId | string | yes | |
mode | string | no | "full" (default) returns the complete screen. "outline" returns { id, name, tree } where each node is stripped to ref (or snippet, or param), $id when present, a classSnippet of its className capped at 40 characters, and children |
Use mode: "outline" to scan a large screen before drilling in with inspect or @id locators. An unknown id returns ScreenNotFound.
list_boards
List the folder’s boards in sidebar order.
| Arg | Type | Required | Description |
|---|---|---|---|
includeFrames | boolean | no | Embed each board’s frames and groups lists in one round-trip. Default false |
includeArchived | boolean | no | Also list archived boards. Default false; archived boards are hidden |
Returns { boards: [{ id, name, frameCount, group?, archivedAt?, frames?, groups? }] }. group is the name of the sidebar group the board is filed under (absent means ungrouped); archivedAt appears only on archived boards.
get_board
Return one board’s full JSON: frames (placements of screens at chosen sizes) and groups.
| Arg | Type | Required | Description |
|---|---|---|---|
boardId | string | yes |
An unknown id returns BoardNotFound.
list_components
List the tag namespace that compose resolves: the app’s own components, library components, registered extensions, and snippets.
| Arg | Type | Required | Description |
|---|---|---|---|
filter | string | no | Case-insensitive substring match on ids (for snippets, the PascalCase tag) |
mode | string | no | "index" (default), "summary", or "full" |
kind | string | no | "repo", "library", "extension", or "snippet" narrows the result |
unusedOnly | boolean | no | List only snippets no screen reaches, directly or through another snippet. Implies kind: "snippet" |
The three modes trade size for detail:
indexreturns families on shelves:{ snapshotVersion, groups: [{ group, label, families: [{ id, pieces?, designModeNotes? }] }], totals: { components, families } }. A family’s sub-components are folded intopieces(FieldlistsFieldLabel,FieldDescription,FieldError), and extensions and snippets each get a shelf of their own. Status is reported only as exceptions:unavailableInDesignandnotInstalledInApplist the ids that differ from the norm. Read this first.summary:{ snapshotVersion, components: [...] }, one entry per component withid,category,source,props(names only),designModeNotes,kind,availableInDesign,installedInApp, andimportPathwhere known.full: complete descriptors with prop types, enum values, and a workingexample. A prop that enumerates a huge value set (for exampleIcon.name, roughly 4,000 lucide names) is truncated to 40 values plus anenumValuesTruncatedcount.
Repo entries are your app’s own components, shelved first and grouped by source — Repo · this app's components, Repo · @mantine/core. Each carries importPath, exportName, member for a compound part, extracted props (with an inheritedProps count when some were folded away), acceptsChildren, styleProps, preview states, parts, and provenance naming where the app uses it. When a component reads data for itself, dataSources lists the hooks — props alone won’t fill a component that reads a store. An id that would collide with a provider component is qualified (Mantine.Button), and designModeNotes says why. In index mode a repo note reports each app’s preview-entry state, so check it before trusting the shelves.
Snippet entries use the snippet’s PascalCase tag as id and carry the persisted kebab-case id as snippetId. In full mode their props are the declared params, each with a derived required flag (true when the param has no default and isn’t optional). A snippet nothing reaches carries unused: true, and its designModeNotes say so in every mode.
installedInApp describes the host app only; false never blocks design. There is no install operation: emit_code returns componentsToInstall for the implementation handoff. Snippets have no separate listing either; they are the kind: "snippet" entries here, and get_snippet returns one definition.
component_status
Compile-check components for the browser canvas and report how each one actually renders, so a fidelity claim rests on a check rather than an assumption. Pass screen or ids.
| Arg | Type | Required | Description |
|---|---|---|---|
screen | string | one of the two | Screen id: check the components that screen uses and whether it mounts |
ids | string[] | one of the two | Component ids, as list_components returns them. Repo catalog ids are accepted |
library | string | no | With ids: the library to check. Default: the folder’s default library. A screen names its own |
Each diagnostic carries the component id, a status, usually a note, and — when the status isn’t exact — a code and a remedy:
| Status | Meaning |
|---|---|
exact | Rendered from the app’s own source |
adapted | Rendered with a named canvas-safe adaptation |
unstyled | Rendered, but its stylesheet wasn’t loaded, so it can’t be reported exact |
proxy | Couldn’t render; the snippet named in $repo.proxy stands in |
fallback | Rendered from Velloo’s bundled components instead of the app’s |
unavailable | Couldn’t render and has no proxy; a labelled frame stands in |
unknown | Not a component this library or catalog has |
The codes are stable: missing-provider, render-threw, missing-export, compile-failed, server-only, resolve-failed, unstyled. missing-provider almost always means the preview entry needs another wrapper.
With screen, returns { library, screen, mounted, note?, diagnostics, errors }. Two different mount behaviours apply, and the difference matters:
- Library components mount all-or-nothing. When one can’t compile, the whole screen — and every capture of it — renders from Velloo’s bundled components whatever the others report, and
notesays why. - Repository components fall back individually. A screen using the app’s own components always mounts; each one that can’t render becomes its proxy snippet or a labelled frame on its own, leaving the rest real. For such a screen the report also merges what the mounted frame found at runtime (
render-threw,missing-provider,unstyled,missing-export) and setsruntimeChecked.
A screen whose library renders server-side only, or that uses no components, returns { screen, mounted: false, note, diagnostics: [], errors: [] }.
With ids, returns { library, usable, diagnostics, errors }. An id neither the library nor the repo catalog has is reported with status: "unknown" rather than as a canvas failure. A provider without repo-backed canvas mounting reports each recognized id as fallback.
Passing neither argument returns BadRequest; an unknown screen returns ScreenNotFound.
preview_status
Check the preview entry your app’s own components render inside on the canvas: the providers and global stylesheets they need. It proves the answer by mounting a real component in a headless browser rather than inspecting the file. Run it once per folder before the first screen.
| Arg | Type | Required | Description |
|---|---|---|---|
app | string | no | config.hostApps key; the default app when omitted |
component | string | no | Catalog id to probe. Default: the first one the app uses, preferring one with recorded props |
probe | boolean | no | Mount a component to verify. Default true |
Returns { state, preview, recipes, appWrappers, appStylesheets, components, probe?, suggestedPreviewEntry?, warnings?, next }.
stateisabsent(no entry and components need one),valid(a component mounted cleanly), orfailing(the probe found a problem).previewdescribes what’s in force:kindisfile(yourpreview.tsx, with itspath),recipe(a built-in wrapper for a known library), ornone.appWrappersandappStylesheetsare what the app’s own entry point uses — the raw material for writing an entry.codePropsflags a wrapper prop that was an expression rather than a literal.probereports the mount:component,mounted,status,code,note,remedy, pluspreviewErrorwhen the entry itself threw and up to fiveconsoleErrors.suggestedPreviewEntryis a draft to adapt, present whenever the current entry isn’t a verified file.nextis the concrete step to take from this state.
set_preview_entry
Write the design folder’s preview entry and verify it by mounting a real component. Returns the same report as preview_status.
| Arg | Type | Required | Description |
|---|---|---|---|
source | string | yes | TSX/JSX module source, up to 100,000 bytes |
app | string | no | config.hostApps key. Writes preview.<app>.tsx; omitted writes preview.tsx |
The module’s default export receives { children, colorScheme, theme, recipeTheme } and returns the providers and fixtures your components need, with the app’s global stylesheets imported at the top. Source without a default export is rejected with BadRequest, as is an unknown app.
Keep the entry free of network calls and credentials: it runs in your local browser during design, and it’s a fixture rather than a bootstrap of the real app.
get_snippet
Return the full JSON for a single snippet: id, name, params (each with the derived required flag), and the body tree.
| Arg | Type | Required | Description |
|---|---|---|---|
snippetId | string | yes | The kebab-case snippet id |
An unknown id returns SnippetNotFound.
get_theme
Return a theme’s token tree.
| Arg | Type | Required | Description |
|---|---|---|---|
theme | string | no | Named theme to read. Default "default" |
Returns the theme’s tokens plus two derived fields: typeScale, what the default typeset computes to per type role, and customCss, the folder’s custom CSS. Edit through the theme operations, not per-node sizes.
list_annotations
List annotations on a screen: designer-authored guidance plus any the agent pinned.
| Arg | Type | Required | Description |
|---|---|---|---|
screenId | string | yes |
Returns { annotations }. Each carries an author, a target: { locator }, a markdown body, and a resolved path, null when the targeted node has since been removed (treat dangling annotations as low-priority; the note is stale). User-authored annotations are read-only to the agent. Agent annotations are written with the operations on the Lifecycle page.
list_notes
List the markdown notes on one board.
| Arg | Type | Required | Description |
|---|---|---|---|
boardId | string | yes |
Returns { notes }. Free notes live in board coordinates (the same space as frame x/y); an attached note carries attachment: { frameId, screenId, locator } naming the node it anchors to. Writable via add_note / update_note / remove_note on the Lifecycle page.
list_comment_threads
List visual feedback threads. Every open thread is a change the user expects.
| Arg | Type | Required | Description |
|---|---|---|---|
boardId | string | no | Narrow to one board. Default: every board in the folder |
status | string | no | "open" (default), "resolved", or "all" |
scope | string | no | "local", "shared" (threads left on a published link), or "all" (default) |
Returns { threads }. A thread’s anchor reports its attached path, or that it is stale when the original node is gone.
get_comment_thread
Read one complete thread, including its anchor and replies.
| Arg | Type | Required | Description |
|---|---|---|---|
threadId | string (UUID) | yes |
Returns { thread }.
update_comment_thread
Act on a thread. Pass reply, status, or both; replying with what changed and resolving in one call is the normal close-out.
| Arg | Type | Required | Description |
|---|---|---|---|
threadId | string (UUID) | yes | |
reply | string | no | Agent message to post, 1–4000 characters. Posted before any status change |
status | string | no | "resolved", "open", or "deleted". Deletion is permanent; only on the user’s explicit request |
Returns { thread }. Passing neither reply nor status returns BadRequest; comment-store failures return CommentStore with a code. The full loop is in the velloo://guide/comments resource.
find_nodes
Query a screen tree for matching nodes. All filters AND together. Accepts snippet:<id> to search a snippet body.
| Arg | Type | Required | Description |
|---|---|---|---|
screenId | string | yes | |
ref | string | no | Exact component $ref, e.g. "Button" |
snippetId | string | no | Exact $snippet id for snippet instances |
id | string | no | Exact $id anchor |
classContains | string | no | Substring of props.className |
prop | string | no | Prop key that must be present |
propValue | any | no | With prop: strict-equal value match |
limit | number | no | Max matches; default 50 |
{ "screenId": "home", "ref": "Icon", "prop": "name", "propValue": "Github" }
Returns { matches: [{ path, kind, ref?, id?, className?, textPreview?, childCount }], total }. kind is component, snippet, or param, and total counts matches before limit. Use it to locate targets for the path-accepting operations without fetching and walking the whole tree.
Assets and captures
list_assets lists the files in the folder’s assets/ directory, and list_captures / get_capture read page captures recorded by start_capture_session. Both families are documented with the rest of the visual tooling on Visual, assets, and batch.