Design to code · AI coding agents · Workflow
Canva to a coding agent: the export path, not the MCP server
The Canva MCP server is for building Canva apps, not reading your designs. The real route is an asynchronous Connect API export — and the format you choose decides how much structure survives.
Flowpoint Analytics · · 8 min read
The MCP server is the wrong door
Canva publishes an MCP server, and if you have spent any time connecting agents to design tools your instinct will be to reach for it. It is the wrong door. That server exists for engineers building Canva apps and integrations — it connects an agent to Canva's developer documentation so the agent can write code *for* Canva. It does not extract anything *from* your designs.
The route that actually moves a design is the Connect API export. It is less elegant than a live MCP connection and it puts files in your repository instead of a socket between two tools — but it works with every agent, including ones with no Canva integration whatsoever, and the artefacts it produces are diffable. The three transport shapes and when each applies are covered in how to export a UI design to a coding agent.
The export is a job, not a request
The single most common implementation mistake here is treating the export as a synchronous call. It is not. Rendering takes time and the API does not block, so an export runs as a three-step job.
- Create the job: POST to the exports endpoint with the design ID and the format you want. The response gives you a job with an ID and a status.
- Poll for completion: GET the job by ID until its status stops being in progress. This is the step people skip.
- Collect the download URLs: A completed job carries the links to the rendered files. Fetch them and write them to disk.
# 1. Create the export job
curl -X POST 'https://api.canva.com/rest/v1/exports' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{ "design_id": "<design-id>", "format": { "type": "html_bundle" } }'
# 2. Poll until the job is no longer in progress
curl 'https://api.canva.com/rest/v1/exports/<export-id>' \
-H 'Authorization: Bearer <token>'
# 3. Download the URLs the completed job returnsGet this wrong and the failure is quiet rather than loud. A naive single request returns a job that has not finished, your script writes nothing, and the export looks empty rather than unfinished. Then you spend twenty minutes wondering why Canva exported a blank design.
Pick the format deliberately
Canva can render to pdf, jpg, png, gif, pptx, mp4, csv, html_bundle and html_standalone, with availability varying by design type. For handing a design to a coding agent, the choice matters more than anything else in this workflow.
| Format | What the agent gets | Use it? |
|---|---|---|
| html_bundle | Document structure preserved, assets kept as separate files with real references | Yes — the default |
| html_standalone | Same structure, every asset inlined as base64 | Only if you cannot handle multiple files |
| Text stays text, inside a fixed page model | Acceptable fallback | |
| png / jpg | Pixels. All structure must be inferred | No, despite being the common choice |
The gap between the top and bottom row is the whole game. With html_bundle the agent reads element boundaries and points at real image files. With a PNG it is reverse-engineering a layout from a picture, which is exactly the task everyone assumed AI would be good at and which produces the least reliable results of anything here. html_standalone looks convenient and is not: inlined base64 blobs are enormous, and they consume the context window that should be spent on your code.
Commit the export, then point the agent at it
Write exports into the repository under a predictable path and commit them. This turns a design into a first-class input the agent reads the way it reads any other file — and, more usefully, gives you a diff when the design changes.
design/
canva/
pricing-page/
index.html
assets/
onboarding-email/
index.html
assets/Then document it once in the project instructions file — CLAUDE.md for Claude Code, AGENTS.md for Codex and Replit, a rule file under .cursor/rules for Cursor. Two sentences is enough: where exports live, and what the format does to the design. That second sentence matters more than it looks, because it prevents a specific misreading covered next.
What the export loses
Canva exports arrive flat and absolutely positioned — a stack of elements with coordinates rather than a nested hierarchy of containers. Three consequences follow, and an agent that has not been warned will get all three wrong.
- Position does not imply grouping: Three elements sitting next to each other are not marked as related. The agent has to infer that they form a card, and it will sometimes infer differently on the next screen.
- There is no responsive intent to recover: Nothing in the export says what should wrap, stack or hide at a smaller width, because that intent never existed in the source. Anything the agent produces for mobile is invention.
- Text sizes are literal, not semantic: A heading is 34px, not "heading level two". Build several screens this way and you accumulate a set of one-off sizes rather than a type scale.
And the omission that matters most: Brand Kits do not come with the export. Your palette, fonts and logo variants live in Canva and stay there. The agent receives one design's geometry with no account of what any colour means, which typeface owns which role, or what the system permits. Told nothing, it fills the gap with the average of everything it has seen.
Supply both inputs
A working Canva handoff is therefore two inputs, not one: the export, which describes this design, and a set of brand rules the agent can read, which describe every design. Colour roles rather than bare hex codes, the type scale and who owns each level, real spacing values, the audience the copy addresses, and an explicit list of things your product never does.
If you only supply the first, you get a faithful reproduction of one screen and guesswork for everything after it. Our contrast checker and colour palette generator are useful for pinning down the palette side of that before you write it down.
Test it
Export a design as html_bundle and ask the agent to build the page. Then ask it for a new section in the same style — one that was never in the Canva design. If it reuses your typography and colour hierarchy, the export carried enough structure and your rules are reaching it. If it invents new sizes and a new accent, you have just confirmed the split: the export moved geometry, and nothing moved the system.
Frequently asked questions
Can a coding agent read my Canva designs through the Canva MCP server?
No. Canva's MCP server connects agents to Canva's developer documentation so they can build Canva apps and integrations. It does not extract your designs. Use the Connect API export instead.
Which Canva export format is best for AI coding agents?
html_bundle. It preserves the document's structure and keeps assets as separate files, so the agent sees element boundaries and real image references. html_standalone inlines everything as base64 and wastes context, and PNG or JPG discards structure entirely.
Why is my Canva export empty?
Almost always because the export was treated as a synchronous request. Creating an export starts an asynchronous job; you have to poll the job by ID until it completes before the download URLs exist. An unfinished job looks like an empty export.
Does a Canva export include my Brand Kit?
No. Palettes, fonts and logo variants stay in Canva. The export carries one design's geometry with no indication of what colours mean or which typeface owns which role, so brand rules have to reach the agent separately.
The Brand Kit that does not travel with the export has to reach the agent some other way. Serving it as a queryable source rather than a pasted paragraph is the idea behind moodspec.