Moda is an AI design agent. The MCP server at https://mcp.moda.app/mcp lets you create designs from a prompt, remix existing canvases, and export to PNG / JPEG / PDF / PPTX. Public share links (moda.app/s/…) work unauthenticated; everything else requires OAuth (default in Claude / Cursor / VS Code / Gemini CLI) or an API key (moda_live_… for scripts, CI, scheduled jobs).
Call whoami first
On any new conversation, call whoami before doing anything else. It returns identity + active workspace + entitlements in one payload (~no UI, no side effects) and lets you skip a lot of downstream tool calls:
org_count == 1→ the user has one organization; no need to calllist_organizationsor ask which workspace to use.brand_kit_count == 1→ useteam_default_brand_kit.iddirectly; don't callfind_brand_kits.brand_kit_count == 0→ no kit exists; offercreate_brand_kit(url=…)or proceed withskip_brand_kit=true.concurrency_cap→ the bulk fan-out window for this plan (3 free / 10 paid / 15 ultra/enterprise). Use it instead of defaulting to 3.session.brand_kit_id→ if non-null, the user has pinned a kit for this session; honor it.
If whoami shows org_count > 1 and the active session isn't set, call set_context(org_name=…) (or ask the user) before any workspace-scoped tool.
Pick a design-task recipe
After whoami, the next thing to do is match the user's intent to one of five canonical workflows. Open the matching recipe before calling start_design_task — each one covers the right parameters, what's preserved vs mutated, and what to surface back to the user.
| User intent | Recipe |
|---|---|
| Build something from scratch ("make me a deck", "create a LinkedIn post") | recipes/create-new-design.md |
| Modify a canvas in place ("add a footer to my deck") — destructive | recipes/edit-existing-canvas.md |
| Fill a template with new content, same brand | recipes/fill-template.md |
| Rebrand a template for a different brand kit | recipes/rebrand-template.md |
| Fan out N variants in parallel (windowed launch, concurrency cap) | recipes/bulk-variants.md |
Most "design something" requests fit one of these. Picking the right one up front avoids the most common failure modes.
Tool catalog
25+ tools across session context, canvas read, design-to-code, brand kits, uploads, design tasks, and export. Full signatures with defaults: references/tools.md.
Gotchas — what silently goes wrong
The recipes above are the happy paths. This list is the corrections / corner cases — consult references/gotchas.md when something surprises you, when you're about to do something the recipes don't cover, or before any non-trivial flow.
format_categorysilently defaults to slides onstart_design_task. Always pass it explicitly for social, carousel, pdf, diagram, ui, or other.- Slide count goes in the prompt text, not a parameter. The REST API exposes
number_of_slides; the MCP server does not. remix_designdefaults towait=True— opposite ofstart_design_task'swait=False. For bulk fan-out, passwait=Falseexplicitly or each call blocks in series.- Per-team concurrency cap on design tasks:
free/free_beta= 3,paid= 10,ultra/enterprise= 15. Exceeding it errors out the call. Use a windowed launch for bulk; default the window to 3 when the plan is unknown. - Carousel cap = 5 panels (
carousel_page_count). "10 IG carousel slides" violates the cap — offer 5 panels or 10 standalone social posts. - Canvas-target parameters on
start_design_taskinteract carefully.template_canvas_id(fork a source into a new canvas, with optional brand swap) is mutually exclusive with bothcanvas_id(edit existing in place) andconversation_id(keep iterating) — passing either pair raises a tool error.canvas_id+conversation_idtogether does NOT error:canvas_idis silently ignored and the agent uses the conversation's canvas. - Design tasks auto-export — don't re-export. A completed
start_design_task/remix_designreturns the finished design already rendered to a file atresult.export({url, format, status, page_count}). Read that; only callexport_canvasfor a different format or page. export_canvas{status: "not_ready"}is a retry state, not an error — returned while a design task is still running on the canvas. Retry afterretry_after_seconds.- Large exports return
{status: "in_progress", task_id}when they exceed the sync budget. Pollget_export_statusfor the URL. - Brand-kit resolution order on
start_design_task/remix_design: explicitbrand_kit_id→ session preference (fromset_session_brand_kitor the showcase iframe's "Use for this session" button) → team default → none (only ifskip_brand_kit=true). Don't restate colors / fonts / logos in the prompt — the resolved kit owns them. find_brand_kitsfor lookups;list_brand_kitsonly when the user asks to see them. Both return the same data, butlist_brand_kitsrenders a visual showcase iframe on every call (per the MCP Apps spec, can't be suppressed per-call). Usefind_brand_kitswhen picking abrand_kit_idfor another tool.- Attachments have two shapes:
{file_id, role}(preferred — carriesrole∈source/reference/assetthat changes agent behavior) and{url, type}(legacy, drops role metadata).
Setup & auth
Per-editor install: docs.moda.app/mcp/setup. OAuth vs API-key tradeoffs: docs.moda.app/mcp/authentication. In Claude Desktop / claude.ai, the user must enable the Moda connector for the current chat (click + → Connectors) before any tool call works.