sandbox_draft
Sketches screens before you build them: you send JSON, the server draws hand-drawn phone mockups (up to 3 boards of up to 4 phones), and they come back in the result and appear on the design's page in the person's app, where the person circles, talks and writes on them. No box is needed.
| Input | Output |
|---|---|
topic (at most 80 characters, the same for every version), boards (1–3), optional note (at most 300 characters: what this version changed), optional id (a box, to show the design on that box's page too) |
ok, designId (dsg_…, the design), reviewId (dsn_…, this version), kind (draft), topic, version, appUrl, boxId when you passed id, imageUrls, next, warnings when there are any, fromHuman when the person left notes for this conversation; the pictures follow the JSON as image content, one per board |
Its tool title (the MCP title, which some clients show for the tool) is Sketch screens; it is annotated readOnlyHint: false (each successful call saves a version), destructiveHint: false and openWorldHint: false.
When to use it
The order of work for anything new or changed is: sandbox_draft (screens) → sandbox_architecture (services) → sandbox_schema (stored data) → build in the box → sandbox_review. Skip a step only when the task does not touch it: a change with no screen has no draft.
Use sandbox_draft whenever the person asks for a draft, sketch, wireframe or mockup (草稿, ラフ), and before you build a new screen or change one, so the person judges the layout and the flow on their phone first. Do not make HTML, SVG or image files for this instead, and do not build the screen in the box to show what it will look like: this tool draws it, keeps every version, and gives the person the tools to answer.
Look at the existing screens before you sketch changes to them (the running app with sandbox_shot, or the code).
The box
A design needs no box. It belongs to the person's account and to the conversation that draws it: you can draw, revise and get the person's feedback without sandbox_start, and a design stays when a box stops or its pictures are deleted.
id is optional: pass the box of this piece of work to show the design on that box's page too, under its Draft, Architecture or Schema tab; leave it out and the design stands on its own, on its page in the app (appUrl) and in the Designs list. A design shows on the last box passed with it: a later version without id stays on that box, and a version with another box's id moves it there. An id that is not a box of this account fails the call.
Drawing happens on the server, not in a box: the call never wakes a frozen box or runs anything in it. With id naming a box that has not stopped, a successful call counts as use of that box: it moves lastUsedAt, which pushes back when the idle rules freeze and stop the box, the conversation that calls it holds the box (Box states), and the version is a step in its steps[]. A call that fails, or one without id, uses no box.
What to draw
Draw only what the person needs to judge. Every picture carries the same legend at the top right: red is new or changed, black and gray are what stays as it is (the legend's words follow the account's language; see Fixed words on the picture).
new: truemarks what is new or different compared with the product as it is now: it is drawn red. It compares with the product as it is now, not with the previous version: a version after the first keepsnew: trueon everything that is still new compared with what exists now, andnotesays what changed since the previous version.- Leave the rest without
new: it is drawn black and gray. scribblestands in for text that does not matter: write only the words that matter.unchanged: trueon a phone whose screen stays as it is: the items you give are drawn, the rest of the screen is scribbled and stamped UNCHANGED (the stamp's word follows the account's language).- Write every label in the language the person reads.
Characters the font lacks, such as emoji, are drawn as boxes and named in warnings: replace them and draw again. Common symbols are swapped for ones it has (✓ becomes √, ✕ ×, ➜ →, ⭐ ★, ≈ ~, ≤ ≦, ≥ ≧, ☐ □, ☑ ■).
Fixed words on the picture
A few words on the picture are written by the drawing itself, not by you, on drafts and on sandbox_architecture diagrams. They follow the account's language (the language the person picked on the account page of the app: Traditional Chinese, English or Japanese; Traditional Chinese until they pick one). What you write (title, text, note, notes and so on) is drawn as given, never translated, so write it in the language the person reads. warnings and error messages are always in English. A sandbox_schema is text, not a picture, and its few fixed words are always in English.
| Where | Traditional Chinese | English | Japanese |
|---|---|---|---|
| Legend, line 1 (drafts) | 紅字=這次加的或改的 | Red = new or changed this version | 赤字=今回追加・変更したもの |
| Legend, line 1 (architecture diagrams) | 藍色=這次加的或改的 | Blue = new or changed this version | 青=今回追加・変更したもの |
| Legend, line 2 | 黑字、灰字=原樣 | Black / gray = as it is | 黒字・グレー=変更なし |
Before note (under the title: red on a draft, blue on an architecture diagram) |
這版改了什麼: | What changed: | 今回の変更: |
Stamp on an unchanged: true phone |
原樣 | UNCHANGED | 変更なし |
| Line at the bottom of a phone whose content did not fit (N items cut) | ⋯ 下面還有 N 項,手機放不下 | ⋯ N more below, does not fit | ⋯ 下にあと N 件、入りきりません |
boards
Each board is drawn as one picture, its title numbered in a circle, the phones side by side with their notes under them.
| Field | Required | Limit | What it is |
|---|---|---|---|
title |
yes | 80 characters | what this board shows ("Outer list: switch between sandboxes and designs") |
phones |
yes | 1–4 | the phones, left to right |
Each phone (every field optional):
| Field | Limit | What it is |
|---|---|---|
items |
60 (120 counting the items inside cards) | the screen, from top to bottom (next table) |
tabs |
2–5, each 20 characters | the bottom tab bar; leave it out when the app has none |
tab |
one of tabs |
the selected bottom tab |
badges |
keys from tabs, values 4 characters |
number dots on bottom tabs: {"Review": "5"} |
newTabs |
from tabs |
bottom tabs this work adds (drawn red) |
unchanged |
true: this screen stays as it is (see above) |
|
notes |
8, each text 150 characters |
notes under the phone, {"text": "…", "new": true}: red with new, gray without |
The screen has a fixed height. Content that does not fit is cut after the last item that fits, the phone says how many items are hidden, and warnings says so: move them to another phone. Long text wraps, English at word breaks; when a single word in a title is too long for the line, the whole title first gets smaller, and only then is the word split. One-line items (buttons, segment, tabs, dropdown) first shrink their text, then cut it with "…".
Items: each has type (required) and an optional new; a card's new covers everything inside it. Indexes (primary, selected) start at 0.
type |
Fields (* required) |
Limits | Drawn as |
|---|---|---|---|
title |
text*, back, gear |
80 / 20 / 16 characters | the page heading in bold; back puts "‹ back to" above it, gear a gear with that word at the right ("Settings") |
sub |
text* (may contain \n) |
300 | a small gray note |
label |
text*, badge |
80 / 4 | a gray bold section name, with an optional number dot |
line |
text*, right, tag, bold |
120 / 30 / 16 | a line of text; right is gray text at the right ("sent", "v1"), tag a boxed tag after the text |
row |
text*, sub, right, badge, tag, chevron (default true) |
120 / 160 / 30 / 4 / 16 | a list row: large text, a gray line under it, gray text at the right, an arrow and an underline; chevron: false drops the arrow |
para |
text* (may contain \n), bold |
300 | a paragraph |
buttons |
items*, primary |
1–4 labels of 20; primary 0–3 |
a row of equal-width buttons; primary is the index of the filled one, none filled without it |
tabs |
items*, selected (default 0) |
2–6 labels of 20 | in-page tabs, the selected one bold and underlined |
segment |
items*, selected (default 0) |
2–5 labels of 20 | a segmented control, the selected part filled |
chips |
items*, selected |
1–12 labels of 20 | rounded filter chips that wrap; selected is filled, none without it |
dropdown |
text* |
80 | a dropdown with a triangle |
field |
label, value |
12 / 300 | a gray label at the left and a tappable value with an arrow at the right |
input |
label, text |
40 / 80 | an input box; label above it, text gray inside (a placeholder or a filled value) |
checkbox |
text*, checked |
120 | a checkbox with its text |
picture |
height (default 200), caption |
40–800 px / 80 | an image placeholder (a frame with diagonals), with a gray caption under it |
scribble |
lines (default 3) |
1–20 | gray scribble standing in for text that does not matter |
card |
items |
as a phone's items; cards nest at most 3 deep |
a hand-drawn card around other items |
gap |
size (default 24) |
0–300 px | empty space |
divider |
a light gray line |
A field a type does not take, a misspelled field or an unknown type is an error that lists what is allowed; nothing is ignored silently. Limits count characters (a CJK character is one). An empty optional string counts as not given. Tabs, control and zero-width characters are removed, and only sub and para text and note keep \n. Everything in the call except id, topic and note is the drawing's spec, at most 64 KB of JSON.
Example
{
"topic": "Sign-in page",
"boards": [
{
"title": "Sign in with email",
"phones": [
{
"items": [
{ "type": "title", "text": "Sign in" },
{ "type": "input", "label": "Email", "text": "you@example.com", "new": true },
{ "type": "buttons", "items": ["Sign in"], "primary": 0 }
],
"notes": [ { "text": "The email field is new", "new": true } ]
}
]
}
]
}
The result
- The pictures follow the JSON as image content, one per board: look at them before you tell the person anything. Then tell them in one line what to look at;
nextsays the same. designId(dsg_…) is the design: every version of this kind andtopicin the account has the same one.reviewId(dsn_…) is this version's id. The stdio adapterparallelsandbox-mcpregistersreviewIdthe way it registers asandbox_reviewround, so the person's report on this version comes back to this conversation (What automatic return needs), and adds a last text block to the result saying whether it will come back on its own.versioncounts per account, kind andtopic, whichever box you pass or none: 1 for a new topic, then 2, 3…appUrlis the design's page in the person's ParallelSandbox app,https://app.parallelsandbox.com/design/<designId>; it opens without signing in, so the person can pass it to anyone, and only their account can circle and send feedback on it.imageUrlsare the same pictures as download URLs, valid one hour.boxIdis the box you passed asid; it is missing when you passed none.warnings: the picture was drawn, but something needs fixing: a phone whose content was cut off, or characters the font lacks.
In the person's app
Every design has its own page in the app (appUrl, /design/<designId>), with all its versions. Anyone with the link can look at it without signing in; another account, or someone not signed in, sees the versions only: no feedback, and not the box it shows on. The box list has a switch between Sandboxes and Designs; Designs lists the latest version of every design in the account, newest first, whether or not it shows on a box and whatever state that box is in, stopped included. A design opened from Designs opens on its page.
A design passed with a box's id also shows on that box's page. Every box's page has the same four units, a row of four tabs at the top in the order of work: Draft, Architecture, Schema and Sandbox. A unit the box has nothing in yet is still there and says so in the app's language, naming the tool that fills it: "No drafts yet. Drafts appear here when AI draws one with sandbox_draft.", "No architecture diagrams yet. Diagrams appear here when AI draws one with sandbox_architecture." or "No schema yet. The schema appears here when AI writes one with sandbox_schema." A box opened from Sandboxes opens on Sandbox.
On a design's page, or in a box's unit after picking the design when the box has more than one of that kind, the person picks the version (the newest by default), reads its note, and under each picture reports on it with Report here: they circle on it, talk, and write text on it, then send. Tapping a draft's picture shows one phone at a time with the notes under it, starting at that picture's first phone, large enough to read on a phone without zooming and scrolling when it is tall: tapping the right half shows the next phone, the left half the previous one, going through the first picture's phones left to right and then the next picture's, and stopping at the first and the last (on a computer the arrow keys do the same, and Esc closes it). A draft version drawn before the app could show one phone at a time opens as the whole picture instead. An architecture picture opens whole, with pinch zoom. A schema is shown as text, not a picture (sandbox_schema).
A box's card shows the step the work is at: the kind of the last design shown on that box, or review once you have called sandbox_review after it.
Their feedback
When the person sends a report on a version, from the design's page or from a box's unit, it comes back to the conversation that drew that version, the way review feedback does, with or without a box:
- In a conversation set up for app feedback (started with
parallelsandbox-agent, or a client with ParallelSandbox's feedback hooks; seesandbox_review; designs need more, below), the report wakes this conversation with a message such asThe person sent feedback in the ParallelSandbox app on design version <reviewId>. Call the parallelsandbox sandbox_report tool with exactly {"reportId":"<reportId>"} to read it, change what they asked, then call the same design tool again with the same topic for the next version.Read it withsandbox_reportandreportIdalone, noid. - Otherwise it arrives as
fromHumanin the result of this conversation's next call to a design tool (this one included, with or withoutid) or to any tool on a box, and the person can paste Copy message for AI from the app's receipt here; it asks you to read the report withsandbox_report({ "reportId": "<reportId>" }is enough for a design; a boxidgiven with it does no harm).
The message names the design and its version: Feedback on draft "Sign-in page" v1: <what they wrote>. Read the attached report (annotated images, voice transcript, text written on the image in notes[].labels). Change it as asked, then call sandbox_draft again with the same topic for the next version. When they wrote nothing, <what they wrote> is N annotated notes and M recordings. Read the circled pictures, the voice transcript and the text they wrote on the picture (notes[].labels) before you change anything. The report's reviewId is the reviewId (dsn_…) of the version they looked at. A report on a design does not end a waiting sandbox_review card.
What automatic return needs
- The stdio adapter
parallelsandbox-mcp0.6.0 or later for a design drawn withoutid, 0.5.4 or later for one drawn with a box'sid;parallelsandbox-agentis in the same package, and a conversation started with it needs the same. Versions before 0.6.0 register a design version only together with its box, and versions before 0.5.4 register onlysandbox_review, so then a report on a design comes back only the second way above (fromHuman, or Copy message for AI). The same holds for a connection to the HTTP endpoint without the adapter. - Claude Code and Gemini CLI also need ParallelSandbox's feedback hooks to cover the design tools. Hooks installed before 0.5.4 fire only for
sandbox_review(in Claude Code,sandbox_reviewandsandbox_report) and miss reports on designs. 0.5.4 treats such old hooks as not installed: the server instructions and the design tools' results carry the install command, such asnpx -y parallelsandbox-mcp install claude-code(install geminifor Gemini CLI; run the command exactly as the result gives it). Changing the person's user settings needs their consent: ask in this conversation, and run it once if they agree. It replaces only ParallelSandbox's own hooks, keeps the other settings and a backup of the previous file, and can be run again. Claude Code applies it at once, Gemini CLI from its next start. Cursor's hooks need no reinstall (they run the same package, so 0.5.4 or later is enough); Codex needs no hooks. - Only versions drawn after the hooks are installed wake this conversation on their own. A version drawn before does not. The install note in its result says so from adapter 0.5.5; 0.5.4's note says to call
sandbox_reviewwith itsreviewId, which is meant for review cards: do not do that with a design'sdsn_id. For that version, ask the person to paste Copy message for AI from the app here, and read the report withsandbox_report.
The next version
There is no approval step. Change what the person asked, then call sandbox_draft again with the same topic (and the same id if you passed one; a box is never required), the whole spec again (not only the changes) and a note: one sentence on what changed since the previous version, which is drawn in red under the title (after "What changed:", in the account's language) and is the first thing the person reads in the app. That call is the next version (v2, v3…), from any box or none; a new topic starts again at v1.
Errors
The call fails with a message that names the field; nothing is saved, and it does not count as use of a box:
box not found (it must be one of yours; see sandbox_status or GET /v1/boxes): theidyou passed is not a box of this account. Leaveidout to draw without a box.topic is required: …,topic is at most 80 characters,note is at most 300 characters,spec is at most 64 KB.- Anything the drawing does not accept comes back as
<path>: <problem>, the path being the arguments of your call, such asboards[0].phones[0].items[0]: unknown field "lable" (allowed: type, new, text, right, tag, bold),boards[0].phones[0].tab: "C" is not one of tabs ["A", "B"]orboards[0].phones[0].items[2].primary: is 2 but there are only 1 items (0 = first). Every argument other thanid,topicandnotegoes to the drawing (which calls themspectogether), so a stray or misspelled top-level argument fails too:spec: unknown field "board" (allowed: boards). Fix that field and call again. another version of "<topic>" was saved at the same time; call again.
Every tool and topic is listed in the tool reference.