Maketa MCP Server: give your AI agent a real design surface
Maketa is a screen-mockup editor with a machine-readable scene model. Its MCP server lets an AI agent create screens, add and move objects, and wire up tap-through navigation — then hand a human a link that opens the result in a browser, clickable like a real app.
The point is not "AI generates a picture of a UI". The agent works on structured objects — rectangles, text, images, a bottom tab bar — that a person can afterwards drag with a mouse. Nothing is baked into a bitmap, and the same model is edited by humans in the browser, by Flutter and web apps pushing their real screens, and by agents through MCP or REST.
Connect in one line:
claude mcp add --transport http maketa https://maketa.pro/maketa/api/mcp
Remote server, Streamable HTTP, nothing to install. Endpoint: https://maketa.pro/maketa/api/mcp. Everything on this page is free; the product itself is maketa.pro (interface in Russian — see limitations).
Connect
| Client | How |
|---|---|
| Claude Code | claude mcp add --transport http maketa https://maketa.pro/maketa/api/mcp — the browser opens a Maketa sign-in, no key to copy |
| Claude web & desktop | Settings → Connectors → Add custom connector → paste the URL |
| Cursor | Add to Cursor, or Settings → Tools & Integrations → New MCP Server with the URL |
| VS Code | Add to VS Code (Copilot Chat, agent mode) |
| ChatGPT | Settings → Connectors → developer mode → Create → paste the URL. Paid plans only |
| Cline and any other client | {"mcpServers":{"maketa":{"type":"streamableHttp","url":"https://maketa.pro/maketa/api/mcp"}}} |
After sign-in the agent sees only the boards of that account. The first call is always maketa_list_boards.
Tools
Twelve tools, scoped per user — an agent only ever sees boards its account owns or collaborates on.
| Tool | What it does |
|---|---|
maketa_list_boards | List the boards (mockup files) the caller can access. Always the first call. |
maketa_list_screens | Screens of a board with a summary: kind (code/design), lock state, object count, branches, version. |
maketa_get_screen | One screen in full — every object with coordinates and properties. |
maketa_create_screen | New empty design screen: name, device preset, size, background. |
maketa_add_element | Add an object to a design screen: rect, ellipse, text, path, image, note or tabs. |
maketa_update_element | Patch an object's properties (position, size, colour, text, radius, links…). |
maketa_move_element | Move an object to new x/y. |
maketa_remove_element | Delete an object from a design screen. |
maketa_branch_screen | Branch a screen into an editable copy — the only way to redesign a screen that came from code. |
maketa_push_code_screen | Upsert a screen from source code by a stable key; every push is a new version ("commit from code"). |
maketa_list_branches | Branches of a screen. |
maketa_get_parent | The original a branch came from — navigate back to the code screen. |
Read-only subset: list_boards, list_screens, get_screen, list_branches, get_parent. Everything else writes to the user's boards. Tool errors come back as isError: true with a human-readable message.
Code ↔ design branching
Screens pushed from source code (kind: "code") are locked. An agent that wants to redesign one calls maketa_branch_screen and edits the branch — a proposal that lives next to the original. When the code moves on and a new version is pushed, existing branches are flagged baseStale, so nobody silently reviews an outdated design.
Example prompts
- "Show me the screens of my Maketa board and describe the checkout one."
- "Add a primary button at the bottom of the login screen and link it to the home screen."
- "Branch the profile screen that came from code and propose a cleaner layout."
The scene model
One JSON document per board, schema maketa.board.v1. A board holds screens; a screen holds a flat list of objects. Coordinates are absolute pixels from the top-left corner of the screen; colours are #hex or none.
Shared fields on every object: id, x, y, rot (degrees), opacity (0–1), group (id of a logical block — a button is a rect and a text in one group), locked, link (id of the screen this object navigates to), linkMode (push — slide in from the right, default; modal — sheet from the bottom).
| Type | Own fields |
|---|---|
rect | w, h, fill (#hex | none), stroke, strokeWidth 0–12, radius (number or [tl,tr,br,bl]) |
ellipse | w, h, fill, stroke, strokeWidth |
text | text (≤5000), fontSize 8–80, weight 400|500|600|700, color, align, lineHeight 1.0–2.0, w (0 = auto); emoji: text with emoji: true |
path | freehand: points [[x,y],…] relative to the anchor, color, size 1–20 |
image | w, h, src (data:image/… only), radius |
note | annotation: text, n, color — excluded from preview, export and the client's view |
tabs | bottom tab bar as one object: w, h, bg, color, muted, active, items — 2–5 × {text, icon, link} |
Two rules worth knowing before your first write:
linkis what makes a mockup clickable. Set it to a target screen id on any object — or per item on atabsobject — and the transition works in preview, in the link you send to a human, and in the video Maketa can render from the board (paid, in roubles — see limitations). A mockup without links is a set of pictures.- A tab bar is one
tabsobject, never five rectangles. Agents get this wrong constantly.
{
"screens": [{
"id": "s_home", "name": "Home",
"device": "iphone-15", "w": 393, "h": 852, "bg": "#FFFFFF",
"kind": "design", "locked": false, "parentId": null, "branches": [],
"objects": [
{"id":"o_1","type":"rect","x":20,"y":40,"w":120,"h":70,"fill":"#3A5BD9","radius":12},
{"id":"o_2","type":"text","x":20,"y":120,"text":"Hello","fontSize":20,"color":"#111827","weight":600},
{"id":"o_4","type":"tabs","x":0,"y":790,"w":393,"h":62,"active":0,
"items":[{"text":"Home","icon":"🏠"},{"text":"Profile","icon":"👤","link":"s_profile"}]}
]
}]
}
Full reference: the Russian model page and the machine-readable OpenAPI 3.1 schema. Device presets with sizes: devices.json.
Authentication
OAuth 2.1 — recommended for interactive clients
Authorization code with PKCE S256, public client, access token for 1 hour, refresh token for 30 days. Dynamic client registration (RFC 7591) is open — POST https://maketa.pro/maketa/api/oauth/register — so any client bootstraps itself the same way Figma's connector does, with no manual client id.
Metadata discovery: https://maketa.pro/.well-known/oauth-protected-resource, the path-suffixed …/oauth-protected-resource/maketa/api/mcp (RFC 9728 §3.1) and …/.well-known/oauth-authorization-server (RFC 8414). An unauthenticated request answers 401 with WWW-Authenticate: Bearer resource_metadata="…", so strict clients find the sign-in on their own. Access is revoked from the Maketa account page.
Bearer token — headless
Same endpoint, Authorization: Bearer mk_pk_… for a project key (issued by a board owner, permanent until revoked, scoped to one board — what CI uses to push screens from code; boardId is then required in every call) or Bearer mk_sb_… for an agent sandbox key (see below). The header x-maketa-key is accepted too.
curl -s -X POST https://maketa.pro/maketa/api/mcp \
-H "Authorization: Bearer mk_sb_…" -H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
| Credential | Scope | Lifetime |
|---|---|---|
| OAuth access token | all boards of the signed-in user | 1 hour (refresh token: 30 days) |
mk_pk_… project key | one board | until revoked |
mk_sb_… sandbox key | sandbox boards created with that key | 14 days, 5 boards, 200 saves/day |
For fully autonomous agents: no human, no signup
A human can draw anonymously in the browser. An agent gets a sandbox key the same way — without a person in the loop:
curl -s -X POST https://maketa.pro/maketa/api/agent/register \
-H 'content-type: application/json' \
-d '{"name":"my-agent","purpose":"mockup for a client"}'
# → {"key":"mk_sb_…","expiresAt":…,"quotas":{"boards":5,"savesPerDay":200},
# "docs":"https://maketa.pro/llms.txt"}
Limits, stated plainly: 3 registrations per day per IP; the key is shown once (the server stores only a hash) and lives 14 days; 5 boards and 200 saves per day; boards survive 30 days past key expiry and then answer 410. Sandbox keys have no access to paid AI features or billing.
Then create a board, save screens and hand over a link — over MCP with the bearer token, or over plain REST:
curl -s -X POST https://maketa.pro/maketa/api/create \
-H 'content-type: application/json' -H 'x-maketa-key: mk_sb_…' \
-d '{"doc":{"name":"Demo","screens":[{"id":"s_1","name":"Home","device":"iphone-15",
"w":393,"h":852,"bg":"#FFFFFF","objects":[]}]}}'
# → {"id":"BOARD_ID","edit":"EDIT_TOKEN","view":"VIEW_TOKEN"}
curl -s -X POST https://maketa.pro/maketa/api/save \
-H 'content-type: application/json' -H 'x-maketa-key: mk_sb_…' \
-d '{"id":"BOARD_ID","baseRev":0,"doc":{"name":"Demo","screens":[{"id":"s_1","name":"Home",
"device":"iphone-15","w":393,"h":852,"bg":"#FFFFFF","objects":[
{"id":"o_1","type":"rect","x":20,"y":40,"w":353,"h":120,"fill":"#EEF1F6","radius":16},
{"id":"o_2","type":"text","x":36,"y":64,"text":"Hello!","fontSize":24,"weight":700,"color":"#111827"}]}]}}'
# → {"ok":true,"rev":1,…}
# The human-facing link (read-only by default; the prototype is clickable):
# https://maketa.pro/app/?b=BOARD_ID
# Your boards with links: GET /maketa/api/agent/boards (header x-maketa-key)
# Cheap change check: GET /maketa/api/rev?id=BOARD_ID → {"rev","updatedAt"}
Always send baseRev (the rev from your last /load, /save or /rev) when saving. Without it a write silently overwrites a concurrent edit; with it you get 409 {"error":"conflict","rev":N} — re-read, merge, retry. Permanent access later: the board owner issues a project key mk_pk_… from the editor.
Working end-to-end walkthrough with every endpoint: llms.txt (Russian comments, English keys).
Errors and limits
Every REST error is {error, hint}: error is a stable machine code, hint is a Russian sentence for a human. Key off error.
| Response | Meaning |
|---|---|
409 conflict | the server has a newer revision — re-read /load, merge, save with the new baseRev |
404 not_found | a board with this id never existed |
410 gone | the board was deleted (tombstone) — do not retry |
401 bad_key / key_expired | unknown or revoked key / sandbox key older than 14 days — register a new one |
403 quota_boards | 6th board on a sandbox key |
429 quota_saves / too_many | 201st save today / rate limit; retryAfterMin says when |
- MCP rate limit: 600 requests per hour per key or user.
- Board limits: 12 MB per scene, 200 screens per board, 4000 objects per screen.
- Transport: Streamable HTTP without SSE —
POSTonly,application/jsonresponses, no sessions. The server echoes the protocol version the client sent ininitialize(2024-11-05by default).
Honest limitations
- The editor UI is in Russian. Tool names, argument schemas and error codes are English; tool descriptions returned by
tools/listand the human-readablehintin error responses are currently Russian. This page is the English reference. - Product documentation is in Russian apart from this page.
llms.txtandopenapi.jsonhave Russian prose around English keys. - Paid AI features (screen generation, screenshot parsing) and video rendering are billed in roubles through a Russian payment method and are not practically available outside Russia. Everything on this page — MCP, REST, boards, sharing, collaboration — is free and has no such restriction.
- This is a mockup tool, not an app builder. It produces screens and tap-through navigation, not a running application.
- No auto-layout, no component variants, no design systems. If your agent needs to operate on a production design system, it needs Figma, not this.
- No public repository or npm package yet. The remote server is the supported way in; a local stdio server exists but is not published.
Privacy & security
The server sees only your boards (screen objects), your account e-mail and board ids. No payment data passes through MCP. An OAuth token grants read/write to that user's boards only; a project key is limited to one board; a sandbox key is limited to its own sandbox boards, expires in 14 days and cannot use paid features. Access can be revoked from the Maketa account page; project keys via POST /project/key/revoke.
Privacy policy: maketa.pro/privacy/ · Terms: maketa.pro/oferta/ (both in Russian).
Who makes it
Maketa is built by demda.pro, a custom software studio. The editor is free because it is how we meet the people who later need a development team. We would rather say that outright than have you wonder where the catch is.
Questions and bug reports: Telegram @demda.
Updated 2 September 2026