Skip to content
Brand Stack
Esc
navigateopen⌘Jpreview
Sign up
On this page

Screenshots → mockups

Turn a screenshot your coding agent just captured into a finished product mockup, without the image ever entering the model's context.

The most common reason to connect Brand Stack to a coding agent: you’re building a feature, the agent takes a screenshot to check its work, and you want that screenshot on a device, in a scene, ready for the landing page.

Take a screenshot of the dashboard we just built, then turn it into a
MacBook Pro mockup with Brand Stack and save it to ./marketing/hero.png.

No shell? Still works

The upload command needs a shell, and not every client has one. Two tools cover chat-only clients (Claude.ai, Claude Cowork, mobile):

  • A pasted URL → the agent calls capture_screenshot, and Brand Stack’s own server renders the page and stores the capture (desktop 1440×900 or mobile 390×844 viewport, matched to the device frame you want). Paste a link in Cowork, ask for a mockup, done. No browser, no upload step. Public pages only: a local dev server is only reachable from your machine, so that stays the CLI’s job.
  • A pasted image → the agent calls create_upload_link and hands you a 30-minute link. Drop the same image there from your browser, no login needed, tell the agent it’s up, and it picks the file out of your asset catalog.

What the agent works out on its own

You shouldn’t have to configure a mockup from inside a chat. The tools tell the agent to infer everything the context already answers, and to ask at most one short question:

  • Device, from the screenshot’s shape. brandstack upload prints the image’s width×height alongside the URL. A portrait capture is a phone: the agent picks the iPhone frame without asking. A landscape capture is a desktop app, which is the one question worth asking: MacBook Pro or Apple Studio Display.
  • Persona, from your coding session. The agent knows which product it’s working on. It matches that against your workspace’s products and offers the matching personas by name, or leaves the persona out, since it’s optional.
  • Everything else defaults. Aspect ratio 16 unless the image is for a feed post (1) or a story (9); camera and lighting left to the image model.

Say “just make it a mockup” and the agent skips the question too.

Your first 10 mockups are free

A newly connected workspace gets credits for 10 free mockups on its first tool call, so you can feel the flow out before anything costs money. The grant lands in your normal credit balance: get_credits shows it, and the studio at brandstack.dev can spend it too.

Why the upload step exists

Every image parameter on create_mockup and create_scene is a URL that Brand Stack’s server fetches. That’s deliberate: it’s how the image model receives reference imagery. It also means a file on your machine is not something the tool can read: file:// URLs, localhost, and private network addresses are all refused, since a server that fetches arbitrary caller-supplied addresses is an SSRF hole.

Nor can the bytes travel through the MCP call itself. Tool arguments are JSON inside the model’s context window, and a base64-encoded screenshot there would cost more tokens than the rest of the conversation, for an image the model never needs to look at.

So the bytes take the short path instead: your agent’s shell posts them straight to your workspace, and only the URL comes back.

The flow

No setup beyond the connector. The agent captures the screenshot however it already does, then moves the file through an upload link it mints itself:

# 1. The agent captures a screenshot however it already does
npx playwright screenshot http://localhost:3000/dashboard ./shot.png

# 2. The agent calls the create_upload_link tool, which returns an
#    uploadEndpoint, and posts the file to it. No API key, no credits.
#    The response carries the hosted url plus width and height.
curl -X POST -H "content-type: image/png" \
  --data-binary @shot.png "$UPLOAD_ENDPOINT"
# {"url":"https://…/shot.png","width":1440,"height":900,…}

# 3. The agent generates, with the screenshot on a device
#    (the create_mockup tool, passing the url as screenshot_url)

With an API key: the same flow, one command shorter

If you keep an API key in the agent’s environment (npx @brandstack/cli login once, or BRANDSTACK_API_KEY), the CLI collapses the upload and can even generate from the terminal directly. Optional, and mostly interesting for CI and scripting:

npx @brandstack/cli upload ./shot.png
# https://…public.blob.vercel-storage.com/…/shot.png

npx @brandstack/cli create-mockup \
  --screenshot-url "https://…/shot.png" \
  --device-type macbook_pro \
  --atmosphere "Studio Lighting" \
  --out ./marketing/hero.png

Step 2 is optional, because create-mockup and create-scene accept a local path in any --*-url flag and upload it for you:

npx @brandstack/cli create-mockup \
  --screenshot-url ./shot.png \
  --device-type macbook_pro \
  --out ./marketing/hero.png

The CLI uploads ./shot.png first, tells you what it did on stderr, and passes the resulting URL to the tool.

Using the MCP connector instead

If you’re driving generation through the MCP connector rather than the CLI, the upload still happens through the CLI, since it’s the only half of the pair with access to your filesystem. Agents are told this in the tool descriptions, so in practice the agent runs npx @brandstack/cli upload ./shot.png in its shell and passes the URL to create_mockup over MCP without being asked.

Any public https URL works just as well, so an image already hosted somewhere (your CDN, a public bucket) needs no upload at all.

Uploading directly

upload is a thin wrapper over one endpoint, if you’d rather call it yourself:

curl -X POST https://www.brandstack.dev/api/uploads \
  -H "Authorization: Bearer $BRANDSTACK_API_KEY" \
  -H "Content-Type: image/png" \
  -H "X-Filename: shot.png" \
  --data-binary @shot.png
{
  "url": "https://…/shot.png",
  "assetId": "…",
  "filename": "shot.png",
  "bytes": 184320
}
Auth Same bearer credentials as /api/mcp (an API key or an OAuth token), with the mcp:write scope.
Types PNG, JPEG, WebP, GIF.
Size 5MB, matching what the generator will fetch. A larger file is refused here rather than accepted and silently dropped later.
Credits None. Uploading is free; only generation costs credits.
Result The image lands in your asset catalog with source_type: "upload", so list_assets and the workspace Assets page both show it.

Troubleshooting

“must be a public http(s) URL that this server can fetch”: a local path, file:// URL, or data: URI reached a generation tool. Upload it first and pass the URL.

413 or “the limit is 5MB”: re-capture at a lower device scale factor, or crop to the region you actually want on screen. Full-page screenshots at 2× cross 5MB easily.

403: the key is read-scope. Uploading writes to your workspace, so it needs mcp:write. Issue a new key in Settings → Developer.

Was this page helpful?