Content
# ultramock-mcp
An MCP server that lets an AI agent (Claude Code, Claude Desktop, etc.) create and
configure [ultramock.io](https://www.ultramock.io) product mockups using **your own
logged-in subscription**.
Ultramock currently renders the final image/video **in the browser** with WebGL,
canvas and video encoder APIs. The public app does not expose a server-side
"render and download" endpoint. This MCP covers the operations that can be done
headlessly through Ultramock's HTTP APIs: projects, templates, full project
payload/config editing, source asset uploads, and authenticated source asset
downloads.
Use `get_capabilities` from an agent to see the current boundary in machine-readable
form. A final rendered image/video export still requires either Ultramock to add a
server render API or a headless browser automation layer.
## Tools
| Tool | What it does |
|------|--------------|
| `get_capabilities` | Report which operations work without a browser and why final rendered export does not. |
| `get_status` | Fetch the authenticated editor status/account payload exposed by Ultramock. |
| `list_projects` | List your projects (id, name, version, editor URL). |
| `get_project` | Full config of one project: dial values, full payload, asset keys/URLs, editor URL. |
| `create_project` | New project, optionally seeded from a template. |
| `duplicate_project` | Copy a project including its config and screen image. |
| `rename_project` | Rename a project. |
| `delete_project` | Delete a project (permanent). |
| `list_templates` | System + your templates (use with create/apply). |
| `apply_template` | Apply a template's device/angle/lighting to a project. |
| `update_config` | Merge dial values (camera, scene, effects, device, border) into a project. |
| `update_payload` | Deep-merge arbitrary JSON into the full project payload, including viewport/timeline/editor settings. |
| `set_screenshot` | Upload a local PNG/JPG/WebP as the on-device screen content. |
| `set_scene_screenshot` | Upload a local PNG/JPG/WebP and assign it to a specific timeline scene. |
| `set_background_image` | Upload a local PNG/JPG/WebP as the project background image. |
| `download_asset` | Download source assets (screen image, background, scene screenshot) to a local file. |
| `get_editor_url` | The URL to open only when you need visual preview or final rendered export. |
### Dial keys used by `update_config`
Pass a `dials` object of `key -> value`. Only the keys you pass change.
- **camera**: `Viewport.camera.tiltX`, `.tiltY`, `.roll`, `.fov`, `.zoom`, `.panX`, `.panY`, `.flap`, `.flapX`
- **scene**: `Viewport.scene.bgMode`, `.darkMode`, `.bgColor` (hex), `.bgImage`, `.bgBlur`, `.transparentBg`, `.envId`, `.lightHeight`, `.lightPos`, `.lift`, `Viewport.devices.mockupModel`
- **device**: `Viewport.devices.mockupBgMode`, `.mockupBg`, `.mockupBgImage`, `.mockupPadding`, `.iphoneFinish`, `.statusBar`, `.hdrYaw`, `.contactShadow`, `.iblIntensity`, `.keyLight`, `.keyLightHeight`, `.keyLightRotation`
- **border**: `Viewport.border.borderRadius`, `.borderStyle`, `.glassWidth`
- **effects**: `Viewport.effects.depth`, `.sharpen`, `.vignette`, `.grain`, `.pixelGrid`, `.caStrength`, `.bloom`, `.bloomStrength`, `.bloomThreshold`, `.bloomRadius`, `.lighting`, `.lightingAngle`, `.lightingIntensity`, `.lightingSoftness`, `.reflection`, `.strength`
- **blur**: `Viewport.blur.mode`, `.strength`, `.falloff`, `.bokeh`, `.focusX`, `.focusY`, `.focusSize`, `.angle`, `.position`
Use `update_payload` for settings stored outside `payload.dialValues`, such as
`editorSettings`, `viewport`, `timeline.scenes`, text/logo scene data and export
metadata. Object patches are merged recursively; arrays and scalar values are
replaced.
## Setup
```bash
npm install
npm run build
```
### Get your session token
Auth uses your ultramock login cookie (no separate API key exists).
1. Open <https://www.ultramock.io> and sign in.
2. DevTools → Application → Cookies → `https://www.ultramock.io`.
3. Copy the value of **`__Secure-authjs.session-token`** (a UUID).
That value is `ULTRAMOCK_SESSION_TOKEN`. It rotates when you sign out / the session
expires (~30 days); refresh it if calls start returning auth errors.
### Register with Claude Code
```bash
claude mcp add ultramock \
--env ULTRAMOCK_SESSION_TOKEN=<your-token> \
-- node /path/to/ultramock-mcp/dist/index.js
```
Or add it to your MCP config (`~/.claude.json` / Claude Desktop
`claude_desktop_config.json`):
```json
{
"mcpServers": {
"ultramock": {
"command": "node",
"args": ["/path/to/ultramock-mcp/dist/index.js"],
"env": { "ULTRAMOCK_SESSION_TOKEN": "your-token-here" }
}
}
}
```
Optional env: `ULTRAMOCK_BASE_URL` (defaults to `https://www.ultramock.io`).
## Typical agent flow
1. `get_capabilities` -> confirm what can be done without a browser.
2. `list_templates` -> pick a look (e.g. "Realistic iPhone").
3. `create_project` with `fromTemplateId` -> get a project id.
4. `set_screenshot`, `set_scene_screenshot` or `set_background_image` -> upload source assets.
5. `update_config` or `update_payload` -> tweak camera, background, effects, viewport or timeline data.
6. `download_asset` -> retrieve source assets again if needed.
7. `get_editor_url` -> only for visual preview or final rendered image/video export.
## Notes
- Writes use Ultramock's lease + optimistic-version model; this server acquires and
releases the edit lease for you on each write. If another session holds the lease
(e.g. the project is open in a browser tab), the server takes it over and that tab
drops to read-only.
- `download_asset` downloads the source images stored on the project. It does not
render the composed mockup.
- Image upload tools accept PNG, JPG/JPEG and WebP files up to Ultramock's 1 MB
upload limit.
- I verified the current app behavior against Ultramock's public client bundle:
`/api/capture` and `/api/video-authorize` authorize exports, while the final
image/video bytes are generated in the browser and downloaded from a local blob URL.