Documentation Index
Fetch the complete documentation index at: https://docs.moda.app/llms.txt
Use this file to discover all available pages before exploring further.
The Moda MCP server provides 20+ tools for working with canvas designs. These tools are called automatically by your AI coding agent when it needs design data or wants to create and manage designs.
| Tool | Description | Auth required |
|---|
whoami | Identity, active workspace, and entitlements (call first) | Yes |
set_context | Set your active organization and team | Yes |
get_context | Show your current session context | Yes |
set_session_brand_kit | Pin a brand kit for this session | Yes |
get_moda_canvas | Fetch semantic pseudo-HTML and design tokens | Public links: No |
get_moda_canvas_tokens | Extract design tokens only | Public links: No |
list_moda_canvas_pages | List pages with dimensions and node counts | Public links: No |
export_canvas | Export as PNG, JPEG, PDF, or PPTX | Public links: No |
get_export_status | Poll an in-progress export | Public links: No |
list_my_canvases | Browse your canvases | Yes |
search_canvases | Search canvases by name | Yes |
list_organizations | List your orgs and teams | Yes |
find_brand_kits | JSON-only brand-kit lookup (agent-side, no iframe) | Yes |
list_brand_kits | List brand kits — renders visual showcase iframe | Yes |
create_brand_kit | Create brand kit from website URL | Yes |
update_brand_kit | Update brand kit colors, fonts, etc. | Yes |
set_default_brand_kit | Mark a brand kit as the team’s default (destructive) | Yes |
list_brand_kit_images | List logos and reference images for a kit | Yes |
remove_brand_kit_image | Detach an image from a brand kit | Yes |
upload_file | Upload a file from URL for attachments | Yes |
start_design_task | Start an AI design task | Yes |
get_task_status | Get task status and progress | Yes |
list_tasks | List recent design tasks | Yes |
remix_design | Duplicate canvas + optional AI edits | Yes |
list_my_websites | Browse websites in your team | Yes |
get_website | Read HTML, title, share state, published URL | Yes |
create_website_from_upload | Create a website from an HTML upload | Yes |
update_website_from_upload | Replace HTML and/or title of an existing website | Yes |
Session context
When you first connect, Moda uses your default organization and team. If you belong to multiple organizations, you can switch with set_context:
- Call
list_organizations to see your orgs and teams.
- Call
set_context with the org name (and optionally team name).
- All subsequent tool calls use that workspace automatically.
Your context persists for 24 hours across reconnections. Tools like list_brand_kits, create_brand_kit, start_design_task, and remix_design all read from your session context automatically. You can also pass org_id or team_id explicitly to override the session context for a single call.
All tools that accept a url parameter support these formats:
| Format | Example |
|---|
| Share link | https://moda.app/s/abc123-token |
| Private canvas URL | https://moda.app/canvas/550e8400-e29b-41d4-a716-446655440000 |
| Raw share token | abc123-token |
| Legacy domain | https://app.moda.so/s/abc123-token |
Private canvas URLs require authentication via the remote server.
set_context
Sets your preferred organization and team for the current session. Once set, all subsequent tools that operate within a workspace (brand kits, design tasks, remixes) will use these defaults automatically.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Parameters
| Parameter | Type | Required | Description |
|---|
org_name | string | Yes | Name of the organization to use (case-insensitive). Use list_organizations to see options. |
team_name | string | No | Name of the team within the org (case-insensitive). Defaults to the org’s default team. |
Returns
A confirmation string:
Context set to organization 'Acme Corp' and team 'Design Team'. All subsequent operations will use this workspace.
Example usage
# Set org (uses default team)
set_context(org_name="Acme Corp")
# Set org and specific team
set_context(org_name="Acme Corp", team_name="Marketing")
Notes
- Call
list_organizations first to see available organization and team names
- Context persists for 24 hours across reconnections
- You can call
set_context again at any time to switch workspaces
get_context
Shows your current session context — which organization and team are active for workspace-scoped tools.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Parameters
This tool takes no parameters.
Returns
A string describing your current context:
Organization: Acme Corp | Team: Design Team
If no context is set:
No session context set. Call set_context to choose your organization and team.
whoami
A single-payload identity check. Returns the active user, the active workspace, and the entitlements that affect tool-call decisions. Most useful at the start of a conversation — the response tells you everything you need to skip downstream lookups when defaults are unambiguous.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Parameters
This tool takes no parameters.
Returns
{
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Jane Doe",
"email": "jane@acme.com"
},
"session": {
"org_id": "660e8400-e29b-41d4-a716-446655440000",
"org_name": "Acme Corp",
"team_id": "770e8400-e29b-41d4-a716-446655440000",
"team_name": "Design Team",
"brand_kit_id": null
},
"org_count": 1,
"team_default_brand_kit": {
"id": "880e8400-e29b-41d4-a716-446655440000",
"title": "Acme Corp"
},
"brand_kit_count": 1,
"plan": "paid",
"concurrency_cap": 10
}
| Field | Type | Description |
|---|
user.id | string | The Moda user UUID. |
user.name | string | Display name. |
user.email | string | Email address. |
session.org_id | string | null | Active org for this session, or null if unset. |
session.team_id | string | null | Active team for this session. |
session.brand_kit_id | string | null | Session-pinned brand kit, if any. Set via the showcase iframe button or set_session_brand_kit. |
org_count | integer | Total orgs the user belongs to. If 1, no multi-org disambiguation is needed. |
team_default_brand_kit | object | null | The team default’s id + title, if a default exists. |
brand_kit_count | integer | Brand kits in the active team. If 1, the agent can use that kit without further listing. |
plan | string | Billing plan: free, free_beta, paid, ultra, or enterprise. |
concurrency_cap | integer | Max concurrent design tasks for this plan. Use as the upper bound for bulk fan-out. |
Notes
- Reads from existing session context — no side effects.
- A good first call on any new conversation:
org_count, brand_kit_count, and concurrency_cap collectively eliminate the need for several downstream tool calls.
- The
plan value is the same enum returned by the billing service; concurrency_cap is pre-resolved so callers don’t need to maintain their own mapping.
set_session_brand_kit
Pin a brand kit for the current session without changing the team default. Subsequent calls to start_design_task / remix_design that omit brand_kit_id will resolve to this kit instead of the team default.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
This is what the brand-kit showcase iframe’s Use for this session button calls. For changing the team default (destructive, affects every team member), use set_default_brand_kit instead.
Parameters
| Parameter | Type | Required | Description |
|---|
brand_kit_id | string | null | No | Brand kit UUID (or bk_… wire form). Pass null/empty to clear the session pin. |
Returns
A confirmation string:
Session brand kit set to <uuid>. Subsequent design tasks will apply it unless overridden.
Or when cleared:
Session brand kit cleared. Subsequent design tasks will use the team default.
Notes
- Switching workspaces via
set_context clears the session brand kit (kits are team-scoped).
- Resolution order for
start_design_task / remix_design: explicit brand_kit_id → session preference → team default → none (if skip_brand_kit=true).
- The kit must belong to the active team; trying to pin a kit from a different team raises a tool error.
get_moda_canvas
The primary tool for design-to-code workflows. Fetches a Moda canvas and returns semantic pseudo-HTML with CSS properties and design tokens that AI agents can translate to any frontend framework.
Parameters
| Parameter | Type | Required | Description |
|---|
url | string | Yes | Moda share URL (https://moda.app/s/...), private canvas URL (https://moda.app/canvas/...), or raw share token |
page_number | integer | null | No | 1-indexed page number. Omit to get all pages. |
Returns
A string containing semantic pseudo-HTML with CSS properties, followed by a design tokens summary.
# Moda Design Export — Canvas Title # Source: https://moda.app/s/abc123 ## Page: Login Screen (1440x900) [page 1]
<section
background="#f3f4f6"
height="900px"
width="1440px"
display="flex"
justify-content="center"
align-items="center"
>
<Card background="#ffffff" border-radius="16px" width="600px" display="flex" flex-direction="column" gap="20px">
<Heading font-size="32px" font-weight="700" color="#111827">Welcome back</Heading>
<Text font-size="14px" color="#6b7280"> Sign in to your account</Text>
<TextInput border="1px solid #d1d5db" border-radius="8px" height="48px" width="520px" />
<button background="#2563eb" border-radius="8px" height="48px" width="520px">Sign in</button>
</Card>
</section>
## Design Tokens - Colors: #111827, #2563eb, #6b7280, #d1d5db, #f3f4f6, #ffffff - Font Inter: weights [400, 700] roles
[body, heading] - Corner radii: 8px, 16px
The transformer assigns semantic tag names based on visual properties and layer names:
| Tag | When used |
|---|
Heading | Text with font-size >= 24px or font-weight >= 600 |
Text | Default text elements |
Button | Rectangle with text, dark fill, and button-like dimensions |
TextInput | Rectangle with light fill, thin border, no text |
Image | Element with an image fill |
Avatar | Small circular element with an image fill |
Card | Group with a background rectangle and content |
Row | Container with flex-direction: row |
Column | Container with flex-direction: column |
Divider | Line element |
Nav, Hero, Footer | Matched from layer names |
Layer names in Moda take priority over visual heuristics. See Naming Layers for best practices.
Example usage
# Fetch all pages
get_moda_canvas(url="https://moda.app/s/abc123")
# Fetch a specific page
get_moda_canvas(url="https://moda.app/s/abc123", page_number=2)
# Fetch a private canvas (requires authentication)
get_moda_canvas(url="https://moda.app/canvas/550e8400-e29b-41d4-a716-446655440000")
Notes
- The output is intentionally HTML-like so agents can map it directly to React, Vue, or HTML components
- Design tokens are appended as a summary at the end of the output
- For multi-page canvases, omitting
page_number returns all pages in a single response
- Hidden layers are excluded from the output
- Rich text extracts the first style span’s properties; mixed-style paragraphs use the first style encountered
get_moda_canvas_tokens
Returns only the design tokens from a canvas — colors, fonts, variables, and corner radii — as structured JSON. Use this when you need to generate theme configuration files without the full semantic layout.
Parameters
| Parameter | Type | Required | Description |
|---|
url | string | Yes | Moda share URL, private canvas URL, or raw share token |
page_number | integer | null | No | 1-indexed page number. Omit for all pages. |
Returns
{
"variables": {
"primary": "#2563eb",
"secondary": "#6b7280",
"background": "#f3f4f6"
},
"colors": ["#111827", "#2563eb", "#6b7280", "#d1d5db", "#f3f4f6", "#ffffff"],
"fonts": [
{
"family": "Inter",
"weights": [400, 700],
"roles": ["body", "heading"]
}
],
"radii": ["8px", "16px"],
"dimensions": {
"width": 1440,
"height": 900
}
}
| Field | Type | Description |
|---|
variables | object | Named design variables defined in the canvas (colors, numbers, strings) |
colors | string[] | All unique colors used in the canvas |
fonts | object[] | Font families with weights and inferred roles |
radii | string[] | All unique corner radii used |
dimensions | object | Canvas page dimensions (width and height) |
Example usage
# Extract tokens for theme generation
get_moda_canvas_tokens(url="https://moda.app/s/abc123")
# Extract tokens from a specific page
get_moda_canvas_tokens(url="https://moda.app/s/abc123", page_number=1)
Notes
- Variables defined in the Moda canvas (via the variables panel) appear in the
variables field with their default values
- Colors are deduplicated and sorted
- Font roles (
body, heading) are inferred from usage context (font size and weight)
list_moda_canvas_pages
Returns metadata about each page in a canvas, including page names, dimensions, and the number of design elements. Use this to understand the structure of multi-page canvases before fetching specific pages.
Parameters
| Parameter | Type | Required | Description |
|---|
url | string | Yes | Moda share URL, private canvas URL, or raw share token |
Returns
{
"canvas_name": "Marketing Website",
"total_pages": 3,
"pages": [
{
"page_number": 1,
"name": "Hero Section",
"width": 1440,
"height": 900,
"node_count": 12
},
{
"page_number": 2,
"name": "Features",
"width": 1440,
"height": 1200,
"node_count": 24
}
]
}
| Field | Type | Description |
|---|
canvas_name | string | Name of the canvas |
total_pages | integer | Total number of pages |
pages[].page_number | integer | 1-indexed page number |
pages[].name | string | Page name as set in Moda |
pages[].width | number | Page width in pixels |
pages[].height | number | Page height in pixels |
pages[].node_count | integer | Number of design elements on the page |
Notes
- Page numbers are 1-indexed
- The
node_count includes all visible elements on the page (shapes, text, images, groups)
- Hidden elements are excluded from the count
export_canvas
Export a Moda canvas as an image or document file. Pass exactly one of canvas_id or url.
Parameters
| Parameter | Type | Required | Default | Description |
|---|
canvas_id | string | No | — | Canvas UUID to export directly. Preferred after start_design_task returns a new canvas. |
url | string | No | — | Moda share URL, private canvas URL, or raw share token. Use this for share-link or design-to-code workflows. |
format | string | No | "png" | Export format: png, jpeg, pdf, or pptx |
page_number | integer | null | No | null | 1-indexed page number. Omit to export all pages — PDF/PPTX bundle every page natively, while multi-page PNG/JPEG are returned as a .zip of per-page files (page-1.png, page-2.png, …) since a single image container can’t hold multiple pages. Single-page canvases still return a raw PNG/JPEG. The format field in the response reflects what was actually delivered (zip in the bundled case). |
task_id | string | null | No | null | Optional task identifier to scope the export’s cache key. When provided, the rendered file is cached as a stable snapshot for that task — useful for design-task progress UIs that should keep showing the original task output even after the canvas is edited. When omitted (typical LLM use), the cache busts on any canvas-data change so direct re-exports always reflect the current state. |
wait | boolean | No | true | When true (default), block up to ~20s for the export to finish before returning an in-progress handle. When false, return status='in_progress' with a task_id immediately — call get_export_status(task_id) to retrieve the URL once the background work completes. Cache hits return synchronously regardless. |
| Format | Best for |
|---|
png | Design-to-code workflows — lossless image, ideal for visual reference |
jpeg | Smaller file size when lossless quality isn’t needed |
pdf | Multi-page documents, printing, sharing |
pptx | PowerPoint presentations, slide decks |
For multi-page PNG/JPEG without page_number, the response carries format: "zip" and the URL serves a .zip of per-page raster files. The requested raster format is preserved inside the archive (page-1.png, page-2.png, …).
Returns
On success:
{
"status": "completed",
"url": "https://assets-cdn.moda.app/exports/abc123.png",
"format": "png"
}
When the canvas has multiple pages and page_number was omitted, a PNG/JPEG export bundles into a zip:
{
"status": "completed",
"url": "https://assets-cdn.moda.app/exports/abc123.zip",
"format": "zip",
"total_pages": 8
}
When the export hasn’t finished within the synchronous wait budget (large multi-page canvases, cold renders), the call returns an in-progress handle. Call get_export_status(task_id) to fetch the URL once it’s ready — the same task_id keeps returning the in-progress shape until terminal:
{
"status": "in_progress",
"task_id": "550e8400-e29b-41d4-a716-446655440000",
"canvas_id": "660e8400-e29b-41d4-a716-446655440000",
"canvas_url": "https://moda.app/canvas/660e8400-e29b-41d4-a716-446655440000",
"format": "pdf",
"total_pages": 23,
"retry_after_seconds": 5
}
If a design task is still active for the target canvas:
{
"status": "not_ready",
"reason": "active_design_job",
"retry_after_seconds": 3,
"canvas_id": "550e8400-e29b-41d4-a716-446655440000",
"canvas_url": "https://moda.app/canvas/550e8400-e29b-41d4-a716-446655440000",
"task_id": "990e8400-e29b-41d4-a716-446655440000"
}
canvas_id, canvas_url, and task_id are only included for authenticated private-canvas exports (i.e., when using canvas_id or a private URL). Share-link exports omit these fields to avoid leaking internal identifiers.
| Field | Type | Description |
|---|
status | string | "completed", "in_progress", or "not_ready" (active design job blocks export) |
url | string | Signed URL to the exported file (only when status='completed') |
format | string | The format that was used for the export |
reason | string | Retryable not-ready reason: active_design_task or task_status_unavailable |
retry_after_seconds | integer | Suggested delay before retrying when status is "not_ready" or "in_progress" |
task_id | string | Export task ID when status='in_progress'; pass to get_export_status to poll. Also surfaces the active design task ID when status='not_ready'. |
canvas_id | string | Canvas UUID for the export target (private exports only) |
canvas_url | string | Direct Moda link to the canvas (private exports only) |
total_pages | integer | Total page count for the canvas (echoed for client convenience) |
Example usage
Provide exactly one of canvas_id or url per call:
# Export as PNG for design-to-code (default)
export_canvas(url="https://moda.app/s/abc123")
# Export directly from a canvas_id returned by start_design_task
export_canvas(canvas_id="550e8400-e29b-41d4-a716-446655440000", format="pdf")
# Export a specific page as JPEG
export_canvas(url="https://moda.app/s/abc123", format="jpeg", page_number=2)
# Export all pages as a PDF
export_canvas(url="https://moda.app/s/abc123", format="pdf")
# Export as a PowerPoint file
export_canvas(url="https://moda.app/s/abc123", format="pptx")
Notes
- Pass exactly one of
canvas_id or url
- For design-generation workflows, prefer
canvas_id from start_design_task / get_task_status
- Export-before-ready and temporary readiness-check failures are normal retryable MCP states, not tool failures
- The signed URL expires after 7 days
- In production, the URL is served from the signed
assets-cdn.moda.app CDN; raw storage.googleapis.com links are a fallback and not the canonical host
- Page exports are cached in Redis for 4 hours per
(canvas, page, ratio) combo. The cache key includes the canvas updated_at, so any edit auto-invalidates. Re-exporting an unchanged page returns in milliseconds.
- For document formats (
pdf, pptx), all pages are included by default unless page_number is specified
- For PNG/JPEG: pass a specific
page_number to get a single image; omit it to get every page — single-page canvases return a raw image, multi-page canvases return a .zip of page-1.png/page-2.png/… (format: "zip" in the response)
- When a design task auto-exports via
export_on_complete, the artifact lives at result.export on the task and is keyed identically to a manual export_canvas call. A follow-up export_canvas for the same canvas with no edits hits the cache instead of re-rendering.
- Screenshots are rendered server-side using a headless browser
get_export_status
Poll the status of an asynchronous export started by export_canvas. Use when export_canvas returned status='in_progress' (large multi-page exports that exceed the synchronous wait budget).
Parameters
| Parameter | Type | Required | Description |
|---|
task_id | string | Yes | Export task ID returned by export_canvas when status='in_progress' — bare UUID or prefixed wire form. |
Returns
While running:
{
"status": "running",
"is_terminal": false,
"task_id": "550e8400-e29b-41d4-a716-446655440000",
"canvas_id": "660e8400-e29b-41d4-a716-446655440000",
"canvas_url": "https://moda.app/canvas/660e8400-e29b-41d4-a716-446655440000",
"format": "pdf",
"total_pages": 23,
"retry_after_seconds": 5
}
On completion:
{
"status": "completed",
"is_terminal": true,
"task_id": "550e8400-e29b-41d4-a716-446655440000",
"canvas_id": "660e8400-e29b-41d4-a716-446655440000",
"canvas_url": "https://moda.app/canvas/660e8400-e29b-41d4-a716-446655440000",
"format": "pdf",
"url": "https://assets-cdn.moda.app/exports/abc123.pdf",
"total_pages": 23
}
On failure:
{
"status": "failed",
"is_terminal": true,
"task_id": "550e8400-e29b-41d4-a716-446655440000",
"error": "Failed to export document: ...",
"format": "pdf"
}
| Field | Type | Description |
|---|
status | string | queued, running, completed, or failed. |
is_terminal | boolean | true once the task has reached completed or failed. |
task_id | string | The export task ID being polled. |
url | string | Signed download URL once status='completed'. |
error | string | Failure detail when status='failed'. |
retry_after_seconds | integer | Suggested poll cadence while is_terminal is false. |
Notes
- Export task records are kept for ~1 hour. After that the task ID is treated as unknown and the call returns a tool error.
- Call
get_export_status instead of repeatedly calling export_canvas while a known task is running — export_canvas may return the same in-progress handle, but get_export_status is the canonical poll path.
list_my_canvases
Returns a paginated list of canvases accessible to the authenticated user. Use this to browse available canvases when you don’t have a specific URL.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Parameters
| Parameter | Type | Required | Default | Description |
|---|
limit | integer | No | 20 | Number of canvases to return (max 100) |
offset | integer | No | 0 | Number of canvases to skip for pagination |
Returns
{
"canvases": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Marketing Website",
"url": "https://moda.app/canvas/550e8400-e29b-41d4-a716-446655440000",
"updated_at": "2025-03-15T10:30:00Z"
}
],
"total": 42,
"limit": 20,
"offset": 0
}
| Field | Type | Description |
|---|
canvases[].id | string | Canvas UUID |
canvases[].name | string | Canvas name |
canvases[].url | string | Direct canvas URL |
canvases[].updated_at | string | Last update timestamp (ISO 8601) |
total | integer | Total number of canvases |
limit | integer | Page size |
offset | integer | Current offset |
Notes
- Canvases are returned in order of most recently updated
- The
url field can be passed directly to other tools like get_moda_canvas
- The maximum
limit is 100 per request
search_canvases
Searches your canvases by name or content and returns matching results. Use this when you know what you’re looking for but don’t have the exact URL.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Parameters
| Parameter | Type | Required | Default | Description |
|---|
query | string | Yes | — | Search query to match against canvas names and content |
limit | integer | No | 20 | Maximum number of results to return (max 100) |
Returns
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Marketing Website v2",
"url": "https://moda.app/canvas/550e8400-e29b-41d4-a716-446655440000"
}
]
| Field | Type | Description |
|---|
[].id | string | Canvas UUID |
[].name | string | Canvas name |
[].url | string | Direct canvas URL |
Notes
- The search matches against canvas names and content
- Results are ranked by relevance
- The returned
url can be passed directly to other tools like get_moda_canvas
- The maximum
limit is 100 per request
list_organizations
Returns a list of organizations and teams you belong to. Use this to discover available workspaces, then call set_context to choose which one to use.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Parameters
This tool takes no parameters.
Returns
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Acme Corp",
"role": "admin",
"teams": [
{
"id": "660e8400-e29b-41d4-a716-446655440000",
"name": "Design Team",
"is_default": true
},
{
"id": "770e8400-e29b-41d4-a716-446655440000",
"name": "Marketing",
"is_default": false
}
]
}
]
| Field | Type | Description |
|---|
[].id | string | Organization UUID |
[].name | string | Organization name |
[].role | string | Your role in the organization (admin or member) |
[].teams | array | Teams you have access to within this org |
[].teams[].id | string | Team UUID |
[].teams[].name | string | Team name |
[].teams[].is_default | boolean | Whether this is the org’s default team |
Notes
- Use org and team names with
set_context to choose your active workspace
- IDs are included but typically don’t need to be shown to users — use names in conversation instead
- Organizations are sorted alphabetically by name
- Only teams you have access to are included
find_brand_kits
JSON-only sibling of list_brand_kits. Same data, same parameters — the difference is presentation. find_brand_kits does not render the visual brand-kit showcase iframe, so it’s appropriate when the agent is just looking up a brand_kit_id to pass to another tool (e.g. start_design_task).
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Per the MCP Apps spec, iframe rendering is decided at tool-listing time from a tool’s _meta.ui.resourceUri. There is no per-call way to suppress rendering. So Moda exposes two tools sharing the same backing data:
find_brand_kits — JSON-only. Use for tool-call decisions.
list_brand_kits — renders the visual showcase. Use when the user asked to see their kits.
Parameters
Identical to list_brand_kits: org_id, team_id, verbose, limit, offset.
Returns
Identical to list_brand_kits.
list_brand_kits
Returns brand kits for a team. Renders the visual brand-kit showcase iframe on every call (on app-aware hosts like claude.ai and Claude Desktop). Brand kits contain colors, fonts, logos, and brand guidelines that were extracted from company websites. Uses your session context (set via set_context) or defaults to your primary workspace.
For agent-side lookups where the iframe would take over screen space the user didn’t ask for, prefer find_brand_kits — same data, no UI.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Parameters
| Parameter | Type | Required | Description |
|---|
org_id | string | No | Organization UUID. Overrides session context for this call. |
team_id | string | No | Team UUID. Overrides session context for this call. |
verbose | boolean | No | Default true. Include full kit detail (colors, fonts, logos, brand values). Pass false for an id/title-only projection. |
limit | integer | No | Default 10. Caps the response so teams with many kits don’t overflow the host’s tool-result context window. Use offset to paginate. |
offset | integer | No | Default 0. Pagination offset; check has_more in the response to know when to stop. |
If neither org_id nor team_id is provided, uses your session context or defaults to your primary workspace.
Returns
{
"brand_kits": [
{
"id": "880e8400-e29b-41d4-a716-446655440000",
"title": "Acme Corp",
"is_default": true,
"created_at": "2025-03-15T10:30:00",
"updated_at": "2025-03-16T14:20:00",
"company_name": "Acme Corp",
"company_url": "https://acme.com",
"company_description": "Modern design tools for teams",
"tagline": "Design at scale",
"brand_values": ["innovation", "simplicity"],
"brand_aesthetic": ["modern", "minimal"],
"brand_tone_of_voice": ["professional", "friendly"],
"default_color_mode": "light",
"colors": [
{ "id": "clr_01HT9WK8N3M2J4A5Z6P7Q8R9TV", "color": "#2563eb", "label": "Primary", "mode": "light" },
{ "id": "clr_01HT9WK8N3M2J4A5Z6P7Q8R9TW", "color": "#111827", "label": "Text", "mode": null }
],
"fonts": [{ "family": "Inter", "label": "Body", "weight": 400, "supported": true }],
"logos": [
{
"group_name": "Primary Logo",
"images": [{ "name": "logo-dark.svg", "url": "https://..." }]
}
]
}
],
"team_id": "660e8400-e29b-41d4-a716-446655440000",
"total": 12,
"offset": 0,
"limit": 10,
"has_more": true
}
| Field | Type | Description |
|---|
[].id | string | Brand kit UUID |
[].title | string | Display name for the brand kit |
[].is_default | boolean | Whether this kit is the team’s default, applied automatically by start_design_task |
[].default_color_mode | string | Preferred color mode when both light and dark palettes are present. Matches colors[].mode — typically "light" or "dark", or null when no mode distinction exists. |
[].colors | array | Ordered brand color palette (lower index = higher primacy) |
[].colors[].id | string | Unique identifier for this color entry |
[].colors[].color | string | Hex color value (e.g. "#2563eb") |
[].colors[].label | string | Semantic role label (e.g. "Primary", "Text") |
[].colors[].mode | string | Color palette mode: "light", "dark", or null when the color isn’t mode-specific |
[].fonts | array | Brand typography entries |
[].logos | array | Logo image groups |
When verbose=false, each kit drops the colors, fonts, logos, brand_values, brand_aesthetic, brand_tone_of_voice, company_url, and company_description fields — useful when you only need ids/titles to pick a kit by name.
Notes
- Uses your session context to determine the workspace. Call
set_context to switch organizations or teams.
- Default-kit-first, then created-at descending. Stable across paginated calls when no edits intervene.
- The
is_default brand kit is automatically used by start_design_task when no brand_kit_id is specified.
- Cache: signed export URLs and signed CDN logo URLs are valid for 24h; a chat refresh that re-renders the showcase iframe within that window hits a Redis cache instead of re-signing.
create_brand_kit
Creates a brand kit by extracting brand information from a company website. Provide a URL or domain and Moda will extract colors, fonts, logos, and brand guidelines automatically. Uses your session context (set via set_context) or defaults to your primary workspace.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Parameters
| Parameter | Type | Required | Description |
|---|
url | string | Yes | Website URL or domain (e.g., stripe.com or https://stripe.com) |
org_id | string | No | Organization UUID. Overrides session context for this call. |
team_id | string | No | Team UUID. Overrides session context for this call. |
Returns
Returns the created brand kit in the same format as list_brand_kits entries.
{
"id": "880e8400-e29b-41d4-a716-446655440000",
"title": "Stripe",
"is_default": false,
"company_name": "Stripe",
"company_url": "https://stripe.com",
"company_description": "Financial infrastructure for the internet",
"default_color_mode": null,
"colors": [
{ "id": "clr_01HT9WK8N3M2J4A5Z6P7Q8R9TV", "color": "#635bff", "label": "Primary", "mode": null },
{ "id": "clr_01HT9WK8N3M2J4A5Z6P7Q8R9TW", "color": "#0a2540", "label": "Dark", "mode": null }
],
"fonts": [{ "family": "Inter", "label": "Body", "weight": 400, "supported": true }],
"logos": []
}
Notes
- Extraction typically takes 10–30 seconds depending on the website
- Uses Firecrawl to scrape the website and extract brand data
- If the brand has been extracted before, a cached result is used for faster response
- The first brand kit created for a team is automatically set as the default
update_brand_kit
Updates an existing brand kit. Pass only the fields you want to change — all other fields remain unchanged.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Parameters
| Parameter | Type | Required | Description |
|---|
brand_kit_id | string | Yes | ID of the brand kit to update |
title | string | No | Display title for the brand kit |
colors | array | No | Array of { color, label?, id?, mode? } objects (replaces all colors). color is required (hex string). id is assigned automatically if omitted. |
fonts | array | No | Array of { family, label, weight } objects |
company_name | string | No | Company name |
company_description | string | No | Company description |
tagline | string | No | Brand tagline |
brand_values | string[] | No | List of brand values |
brand_aesthetic | string[] | No | List of aesthetic descriptors |
brand_tone_of_voice | string[] | No | List of tone descriptors |
Returns
Returns the updated brand kit in the same format as list_brand_kits entries.
Notes
- Pass only the fields you want to change — omitted fields are not modified
- When updating
colors or fonts, the entire array is replaced (not merged)
- You must have access to the team that owns the brand kit
set_default_brand_kit
Marks a brand kit as the team’s default and clears the default flag on the previously-default kit. The default brand kit is automatically applied by start_design_task when no brand_kit_id is provided.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Destructive — affects every team member. This tool clears the default flag on whichever kit was previously default.
Only call it when the user explicitly asks to change their team default brand kit. For session-only changes
(no team-wide impact), use set_session_brand_kit instead — that’s what the Brand Kit
Showcase iframe’s “Use for this session” button now calls.
Parameters
| Parameter | Type | Required | Description |
|---|
brand_kit_id | string | Yes | Brand kit UUID — bare UUID or prefixed bk_ wire form is accepted |
Returns
Returns the team’s brand kits in the same shape as list_brand_kits, with the new default first. Use this to rerender any UI that depends on default-kit state without an additional round-trip.
Example usage
# Promote a kit to default after the user explicitly asks
set_default_brand_kit(brand_kit_id="880e8400-e29b-41d4-a716-446655440000")
Notes
- Idempotent: setting the already-default kit is a no-op
- Only the user’s currently-active team is affected
- Pairs with the Brand Kit Showcase interactive app, which calls this tool from its “Set as default” button
list_brand_kit_images
Returns every image attached to a brand kit — both logos and design references — in newest-insertion order. Useful when reconciling an existing brand kit before adding new images, since blindly calling add_brand_kit_image would create duplicates.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Parameters
| Parameter | Type | Required | Description |
|---|
brand_kit_id | string | Yes | Brand kit UUID — bare UUID or prefixed bk_ wire form is accepted |
Returns
{
"brand_kit_id": "bk_abc123",
"images": [
{
"id": "bki_550e8400e29b41d4a716446655440000",
"role": "logo",
"file_id": "file_660e8400e29b41d4a716446655440000",
"url": "https://assets-cdn.moda.app/brand-kits/.../logo-dark.svg",
"name": "logo-dark.svg",
"group_id": "770e8400-e29b-41d4-a716-446655440000",
"group_name": "Primary Logo"
},
{
"id": "bki_aa0e8400e29b41d4a716446655440000",
"role": "reference",
"file_id": "file_bb0e8400e29b41d4a716446655440000",
"url": "https://assets-cdn.moda.app/brand-kits/.../homepage-hero.png",
"name": "homepage-hero.png",
"group_id": "cc0e8400-e29b-41d4-a716-446655440000",
"group_name": "Website screenshots"
}
]
}
| Field | Type | Description |
|---|
brand_kit_id | string | Echoed back for round-tripping |
images[].id | string | Image-row ID (prefixed bki_) — pass to remove_brand_kit_image |
images[].role | string | "logo" or "reference" |
images[].file_id | string | Underlying file ID (prefixed file_) |
images[].url | string | Direct URL to the image (CDN-served) |
images[].name | string | Original filename, if known |
images[].group_id | string | UUID of the containing logo group / reference group |
images[].group_name | string | Display name of the group (e.g., "Primary Logo", "Photography") |
Example usage
list_brand_kit_images(brand_kit_id="880e8400-e29b-41d4-a716-446655440000")
Notes
- Pairs with the Brand Kit Image Gallery interactive app, which renders the images grouped by role
- The image
url is served from the signed CDN; treat it as opaque
remove_brand_kit_image
Detaches an image from a brand kit by its bki_ ID. Returns the freshly re-listed images so callers can rerender from authoritative state.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Destructive. Only call this when the user explicitly asks to remove a specific image, or in response to a user
action (e.g., the per-card Remove button in the Brand Kit Image Gallery iframe). The underlying file remains in
storage; only the brand-kit reference is removed.
Parameters
| Parameter | Type | Required | Description |
|---|
brand_kit_id | string | Yes | Brand kit UUID — bare UUID or prefixed bk_ wire form is accepted |
image_id | string | Yes | Brand-kit image-row ID — bare UUID or prefixed bki_ wire form |
Returns
Returns the same payload shape as list_brand_kit_images after the removal completes, so the caller can rerender directly from the response.
Example usage
remove_brand_kit_image(
brand_kit_id="880e8400-e29b-41d4-a716-446655440000",
image_id="bki_550e8400e29b41d4a716446655440000",
)
Notes
- The underlying file is not deleted from storage — only the brand-kit reference is removed
- Pairs with the Brand Kit Image Gallery interactive app, which calls this tool from each card’s Remove button
- Not idempotent: calling twice with the same
image_id raises a not-found error on the second call
upload_file
Uploads a file from a URL to Moda’s storage. Returns a stable proxy URL that can be used as an attachment in start_design_task. Supports images, PDFs, and PPTX files.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Parameters
| Parameter | Type | Required | Description |
|---|
source_url | string | Yes | Public URL of the file to download and store |
filename | string | No | Filename to use. Inferred from URL if omitted. |
org_id | string | No | Organization UUID. Overrides session context for this call. |
team_id | string | No | Team UUID. Overrides session context for this call. |
Returns
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"url": "https://api.moda.app/api/v2/images/ref/550e8400-e29b-41d4-a716-446655440000?h=abc123",
"filename": "design-reference.png",
"mime_type": "image/png",
"size_bytes": 245760,
"was_duplicate": false,
"message": "File uploaded successfully. Use the 'url' field as an attachment URL in start_design_task."
}
| Field | Type | Description |
|---|
id | string | Unique file identifier (UUID) |
url | string | Stable proxy URL for the uploaded file |
filename | string | Filename of the uploaded file |
mime_type | string | MIME type of the file |
size_bytes | integer | File size in bytes |
was_duplicate | boolean | True if an identical file already existed |
message | string | Human-readable confirmation message |
Example usage
# Upload an image for use as a design reference
upload_file(source_url="https://example.com/mockup.png")
# Upload with a custom filename
upload_file(source_url="https://example.com/file.pdf", filename="brand-guidelines.pdf")
Notes
- The returned
url can be passed directly as an attachment URL in start_design_task
- Files are deduplicated by content hash — uploading the same file twice returns the existing record
- Supported types include images (PNG, JPEG, WebP, etc.), PDFs, and PPTX files
start_design_task
Starts an AI design task using Moda’s design agent. The agent creates or edits a canvas based on your prompt. Provide a canvas_id to edit an existing canvas, or omit it to create a new one.
By default this tool returns immediately in milliseconds with a task handle ({task_id, canvas_id, canvas_url, status: 'queued'}). On hosts that support interactive apps (claude.ai web, Claude Desktop), the paired Design Task Progress iframe shows live progress and rendered pages, so you don’t need to block on completion. On non-interactive hosts, poll get_task_status(task_id) to track progress and detect completion. Pass wait=True to opt back into synchronous behavior — useful only for non-interactive consumers that need a single blocking call.
Uses your session context (set via set_context) or defaults to your primary workspace.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Parameters
| Parameter | Type | Required | Default | Description |
|---|
prompt | string | Yes | — | Design instructions for the AI agent |
canvas_id | string | No | — | Canvas to edit. Omit to create a new canvas. Ignored when resuming a conversation. |
canvas_name | string | No | — | Name for the new canvas (only used when canvas_id is omitted) |
brand_kit_id | string | No | — | Brand kit to apply. Defaults to the team’s default brand kit. |
org_id | string | No | — | Organization UUID. Overrides session context for this call. |
team_id | string | No | — | Team UUID. Overrides session context for this call. |
conversation_id | string | No | — | UUID of a previous conversation to resume. The agent will have full context of all prior interactions. Returned in every response — pass it back to continue. |
attachments | array | No | — | List of reference files. Each item is either a URL-shape object {url, name?, type?} (type ∈ "image" / "pdf" / "pptx" / "url") or a file-id-shape object {file_id, role, label?} where file_id is returned by upload_file and role ∈ "source" (extract content) / "reference" (emulate style) / "asset" (use directly in outputs). Prefer the file-id form for uploaded files — it surfaces role metadata to the agent. |
reference_canvas_ids | string[] | No | — | List of canvas UUIDs to use as design inspiration. The agent can see these designs and reference their style, layout, or content. |
format_category | string | No | — | Format category — recommended for new designs. "slides" for presentations, "pdf" for documents/reports, "social" for social media posts, "diagram" for flowcharts/diagrams, "ui" for UI mockups, or "other". Without this, the agent may default to an incorrect format. |
format_width | integer | No | — | Canvas width in pixels. Common: 1920x1080 (slides), 1080x1080 (social square), 1080x1920 (social story). |
format_height | integer | No | — | Canvas height in pixels. |
model_tier | string | No | — | AI model tier: "pro" (most capable), "standard", or "lite" (fastest). Defaults to automatic selection. |
wait | boolean | No | false | When false (default), return immediately with a task handle so callers can render the live-progress iframe or poll get_task_status. When true, block until the agent finishes and return the complete design — only needed for synchronous, non-interactive consumers. |
export_on_complete | object | No | — | Auto-export preferences applied when the task finishes — the rendered file is attached to result.export and the cache is warmed so a follow-up export_canvas for the same canvas hits it instantly. Shape: {enabled?: boolean = true, format?: "png" | "jpeg" | "pdf" | "pptx", pixel_ratio?: 1..4}. Omit to use the canvas category default (slides→PPTX, pdf→PDF, others→PNG). Pass {enabled: false} to skip the auto-export. Multi-page PNG/JPEG bundles into a .zip of per-page files; result.export.format is "zip" in that case. |
Returns
{
"task_id": "990e8400-e29b-41d4-a716-446655440000",
"canvas_id": "550e8400-e29b-41d4-a716-446655440000",
"canvas_url": "https://moda.app/canvas/550e8400-e29b-41d4-a716-446655440000",
"conversation_id": "bb0e8400-e29b-41d4-a716-446655440000",
"theme_canvas_id": null,
"status": "queued",
"message": "Design task started. Use get_task_status to check progress.",
"retry_after_seconds": 3
}
theme_canvas_id reports the brand kit’s slides theme that was auto-applied to the new canvas — the canvas whose page layouts the agent themes from. It’s populated only when you create a fresh slides deck (format_category="slides", no canvas_id) with a brand kit that has a saved default theme; it’s null for non-slides designs, edits of existing canvases, and brand kits without a saved theme.
Once get_task_status reports status: "completed", the same envelope additionally carries result.export with the auto-exported artifact:
{
"result": {
"canvas_id": "550e8400-e29b-41d4-a716-446655440000",
"canvas_url": "https://moda.app/canvas/550e8400-e29b-41d4-a716-446655440000",
"export": {
"url": "https://assets-cdn.moda.app/exports/abc123.pptx",
"format": "pptx",
"status": "completed",
"page_count": 8
}
}
}
| Field | Type | Description |
|---|
result.export.url | string | Signed download URL for the rendered file (expires after 7 days). |
result.export.format | string | Delivered format — png, jpeg, pdf, pptx, or zip (multi-page PNG/JPEG bundle). |
result.export.status | string | completed when the file is ready; failed if the auto-export couldn’t render (the design task still succeeded). |
result.export.page_count | integer | Total pages in the canvas — useful for sizing UIs ahead of downloading. |
Example usage
# Create a new design (returns a conversation_id)
start_design_task(prompt="Create a modern SaaS landing page with a hero section, features grid, and pricing table")
# Resume the conversation to make changes (agent remembers previous context)
start_design_task(prompt="Change the color scheme to use blues and grays", conversation_id="bb0e8400...")
# Edit an existing canvas
start_design_task(prompt="Add a footer section", canvas_id="550e8400...")
# Create slides with specific dimensions
start_design_task(prompt="Create a pitch deck", format_category="slides", format_width=1920, format_height=1080)
# Create a PDF document (report, resume, etc.)
start_design_task(prompt="Create a project report", format_category="pdf")
# Provide reference images as attachments — file-id form (recommended)
# Upload first, then reference the returned file_id with a role:
uploaded = upload_file(file_url="https://example.com/reference.png")
start_design_task(
prompt="Recreate this design in our brand style",
attachments=[{"file_id": uploaded["id"], "role": "reference", "label": "brand-style ref"}],
brand_kit_id="880e8400..."
)
# Or the legacy URL form — still accepted for hosted public URLs:
start_design_task(
prompt="Recreate this design in our brand style",
attachments=[{"url": "https://example.com/reference.png", "type": "image"}],
brand_kit_id="880e8400..."
)
# Mix shapes in one call — a source brief plus a reference image:
start_design_task(
prompt="Build a pitch deck from the brief; match the reference style",
attachments=[
{"file_id": "file_01HT9W…", "role": "source", "label": "Q2 strategy brief"},
{"file_id": "file_01HT9X…", "role": "reference"},
],
)
# Use existing canvases as design inspiration
start_design_task(
prompt="Create a similar landing page",
reference_canvas_ids=["550e8400...", "660e8400..."]
)
# Canonical MCP flow: start -> poll -> read result.export (no second render)
task = start_design_task(prompt="Create a sales deck", format_category="slides")
status = get_task_status(task_id=task["task_id"])
while not status["can_export"] and not status["is_terminal"]:
# Wait status["retry_after_seconds"] seconds, then poll again.
status = get_task_status(task_id=task["task_id"])
# When the task auto-exports successfully, the rendered file rides in
# status["result"]["export"] — read it directly instead of calling
# export_canvas (the cache would hit, but result.export saves a round trip).
if status["can_export"]:
export_info = status["result"]["export"]
print(export_info["url"], export_info["format"]) # e.g. ".../abc.pptx", "pptx"
# Opt out of the auto-export when you don't need it:
start_design_task(prompt="Iterate on the layout", canvas_id="550e8400...", export_on_complete={"enabled": False})
# Or override the format/scale (e.g. PDF instead of the slides category default):
start_design_task(prompt="Build a deck", format_category="slides", export_on_complete={"format": "pdf", "pixel_ratio": 3})
Notes
- The default
wait=False returns a task handle in milliseconds. Pass wait=True only when you specifically want a single blocking call.
- On iframe-aware hosts (claude.ai web, Claude Desktop), the paired Design Task Progress app polls and renders pages on its own — see Interactive Apps.
- Use
retry_after_seconds as the default delay before the first get_task_status(task_id) call
- Keep polling until
can_export == true or is_terminal == true
can_export becomes true only after successful completion with exportable canvas data
- If no
brand_kit_id is provided, the team’s default brand kit is used automatically
- If no
canvas_id is provided, a new canvas is created with the name from canvas_name or “Untitled”
- Every response includes a
conversation_id. Pass it back in subsequent calls so the agent has context of all previous interactions.
- When resuming a conversation, the
canvas_id parameter is ignored — the agent automatically operates on the conversation’s canvas
- Use
upload_file to upload local files first, then pass the returned file_id in an attachments item with a role (source / reference / asset). The older URL form is still accepted but drops role metadata.
- Reference canvas IDs let the agent see and draw inspiration from existing designs without modifying them
- Always pass
format_category when creating new designs — without it, the agent may default to slides regardless of what the user asked for
- The auto-export attached to
result.export is keyed identically to a follow-up export_canvas(canvas_id=...), so calling export_canvas afterward with default args hits the cache instead of re-rendering. Pin export_on_complete.format and export_on_complete.pixel_ratio when you need a non-default artifact — the cache match depends on the exact (format, pixel_ratio) pair.
get_task_status
Returns the status and progress of a specific design task. Use this to check on tasks started with start_design_task or remix_design.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Parameters
| Parameter | Type | Required | Description |
|---|
task_id | string | Yes | ID of the task to check |
Returns
{
"task_id": "990e8400-e29b-41d4-a716-446655440000",
"canvas_id": "550e8400-e29b-41d4-a716-446655440000",
"canvas_url": "https://moda.app/canvas/550e8400-e29b-41d4-a716-446655440000",
"conversation_id": "bb0e8400-e29b-41d4-a716-446655440000",
"theme_canvas_id": null,
"status": "running",
"task": "Create a modern SaaS landing page...",
"progress_percent": 45,
"current_step": "Generating hero section",
"is_terminal": false,
"can_export": false,
"retry_after_seconds": 3,
"operations_streamed": 12,
"created_at": "2025-03-15T10:30:00",
"started_at": "2025-03-15T10:30:02",
"completed_at": null,
"error": null
}
| Field | Type | Description |
|---|
task_id | string | Task UUID |
canvas_id | string | Canvas being edited |
canvas_url | string | Direct link to the canvas |
conversation_id | string | Conversation UUID. Pass to start_design_task to resume the conversation. |
theme_canvas_id | string | Brand-kit slides theme attached to the canvas, or null when unthemed. |
status | string | queued, running, completed, failed, or cancelled |
prompt | string | The original prompt, in full |
progress_percent | integer | Estimated progress (0-100), if available |
current_step | string | Description of what the agent is currently doing |
is_terminal | boolean | true when the task is finished and polling can stop |
can_export | boolean | true when the task completed successfully and export_canvas can be called |
retry_after_seconds | integer | Suggested delay before polling again when the task is still in progress |
operations_streamed | integer | Number of canvas operations applied so far |
created_at | string | Job creation timestamp (ISO 8601) |
started_at | string | When the agent started working (ISO 8601) |
completed_at | string | When the task finished (ISO 8601), or null |
error | string | Error message if the task failed, or null |
Notes
- Use this after
start_design_task to poll for progress
- Poll again after
retry_after_seconds while is_terminal == false
- On
status="completed", the response carries a result.export block ({url, format, status, page_count}) with the auto-exported design — read it directly instead of calling export_canvas for the same canvas. If the auto-export was disabled via export_on_complete: {enabled: false} or skipped (animation canvases), result.export is absent.
- Failed or cancelled tasks are terminal, but they do not set
can_export
- The
prompt field carries the user’s original prompt in full (the task-progress iframe surfaces it verbatim)
list_tasks
Returns a list of recent design tasks. Use this to see what design tasks have been run recently, optionally filtered by canvas or status.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Parameters
| Parameter | Type | Required | Default | Description |
|---|
canvas_id | string | No | — | Filter tasks to a specific canvas |
status | string | No | — | Filter by status (queued, running, completed, failed) |
limit | integer | No | 10 | Number of tasks to return (max 50) |
Returns
{
"tasks": [
{
"task_id": "990e8400-e29b-41d4-a716-446655440000",
"canvas_id": "550e8400-e29b-41d4-a716-446655440000",
"canvas_url": "https://moda.app/canvas/550e8400-e29b-41d4-a716-446655440000",
"conversation_id": "bb0e8400-e29b-41d4-a716-446655440000",
"theme_canvas_id": null,
"status": "completed",
"prompt": "Create a modern SaaS landing page...",
"progress_percent": 100,
"current_step": null,
"operations_streamed": 42,
"created_at": "2025-03-15T10:30:00",
"started_at": "2025-03-15T10:30:02",
"completed_at": "2025-03-15T10:32:15",
"error": null
}
]
}
Notes
- Tasks are returned in order of most recently created
- The maximum
limit is 50 per request
- Only tasks for canvases you have access to are returned
remix_design
Duplicates an existing canvas and optionally starts a design task on the copy. Use this to create variations of existing designs without modifying the original. When a prompt is provided, the tool returns a task handle immediately — poll get_task_status the same way as start_design_task. Uses your session context (set via set_context) or defaults to your primary workspace.
This tool requires authentication via the remote MCP server at mcp.moda.app. It is not
available when using the local stdio server.
Parameters
| Parameter | Type | Required | Default | Description |
|---|
canvas_id | string | Yes | — | Canvas to duplicate |
prompt | string | No | — | Design instructions to apply to the copy. Omit for a plain duplicate. |
new_name | string | No | — | Name for the new canvas. Defaults to "<original name> (Remix)". |
brand_kit_id | string | No | — | Brand kit to apply (only used when prompt is provided) |
org_id | string | No | — | Organization UUID. Overrides session context for this call. |
team_id | string | No | — | Team UUID. Overrides session context for this call. |
Returns
Without a prompt (plain duplicate):
{
"canvas_id": "aa0e8400-e29b-41d4-a716-446655440000",
"canvas_url": "https://moda.app/canvas/aa0e8400-e29b-41d4-a716-446655440000",
"canvas_name": "Marketing Website (Remix)",
"source_canvas_id": "550e8400-e29b-41d4-a716-446655440000",
"message": "Canvas duplicated successfully."
}
With a prompt (duplicate + design task):
{
"canvas_id": "aa0e8400-e29b-41d4-a716-446655440000",
"canvas_url": "https://moda.app/canvas/aa0e8400-e29b-41d4-a716-446655440000",
"canvas_name": "Marketing Website (Remix)",
"source_canvas_id": "550e8400-e29b-41d4-a716-446655440000",
"task_id": "990e8400-e29b-41d4-a716-446655440000",
"job_status": "queued",
"message": "Design task started. Use get_task_status to check progress.",
"retry_after_seconds": 3
}
Example usage
# Plain duplicate
remix_design(canvas_id="550e8400...")
# Duplicate and restyle
remix_design(canvas_id="550e8400...", prompt="Change the color scheme to dark mode")
# Duplicate with new branding
remix_design(canvas_id="550e8400...", prompt="Apply our new brand", brand_kit_id="880e8400...")
Notes
- The original canvas is never modified — all changes are applied to the copy
- When a
prompt is provided, a design task is started on the duplicate and the tool returns immediately with a task handle
- Poll
get_task_status(task_id) until can_export == true or the task reaches a terminal failure state, same as start_design_task
Websites
Moda websites are HTML projects you can draft and manage, then publish from the Moda editor to a public *.moda.page URL. These four MCP tools let your agent draft, inspect, and update websites in Moda — available to every authenticated MCP user.
Publishing the resulting draft is opt-in: create_website_from_upload and update_website_from_upload both accept a publish flag that defaults to false. Passing publish=true requires the website-publishing feature on your Moda account (paid plan); otherwise the call errors and the agent should re-call with publish=false to save the draft. The user can then publish from the editor at any time.
HTML payloads are uploaded out-of-band (presigned URL → PUT bytes → call the tool with the returned storage_key) so large HTML documents — especially ones with inlined base64 images — don’t have to pass through MCP tool args. Inline data: images are extracted to Moda Files automatically so the published artifact stays small.
Every website tool requires authentication via the remote MCP server at mcp.moda.app. The
local stdio server does not expose them.
list_my_websites
Lists the websites visible to the caller in the active team, newest-updated first. Scoped to the team in your session context — call set_context first if you belong to multiple teams.
Parameters
| Parameter | Type | Required | Description |
|---|
limit | integer | No | Page size (default 20, clamped to 100 server-side). |
offset | integer | No | Pagination offset, 0-indexed. |
Returns
{
"websites": [
{
"id": "bb0e8400-e29b-41d4-a716-446655440000",
"title": "Launch Announcement",
"url": "https://launch-announcement.moda.page",
"share_state": "public",
"comments_enabled": true,
"recent_comments_count": 3,
"updated_at": "2026-05-26T17:42:11Z"
}
],
"total": 1,
"limit": 20,
"offset": 0,
"has_more": false
}
url is null for unpublished drafts.
get_website
Fetches the full agent-facing projection of one website — the source HTML for the home page, title, share state, comments toggle, editor URL, and (if published) the live *.moda.page URL. Use this before calling update_website_from_upload so the agent has the current source as a base.
Parameters
| Parameter | Type | Required | Description |
|---|
website_id | string | Yes | ID of the website to fetch. |
Returns
{
"website_id": "bb0e8400-e29b-41d4-a716-446655440000",
"title": "Launch Announcement",
"html": "<!doctype html><html>…</html>",
"editor_url": "https://moda.app/website/bb0e8400-e29b-41d4-a716-446655440000",
"published_url": "https://launch-announcement.moda.page",
"url": "https://launch-announcement.moda.page",
"share_state": "public",
"comments_enabled": true,
"recent_comments_summary": []
}
published_url and url are both null for unpublished drafts. url is a deprecated alias kept for backward compatibility — prefer published_url in new code.
create_website_from_upload
Creates a new Moda website from an HTML file. The HTML is uploaded out-of-band first so large documents (especially ones with inlined base64 images) don’t have to pass through MCP args.
Required upload sequence:
create_upload_url(filename="site.html", mime_type="text/html") → returns {upload_url, storage_key}.
- PUT the HTML bytes to
upload_url with header Content-Type: text/html.
- Call
create_website_from_upload(storage_key=…) with the storage_key from step 1.
Server-side, Moda extracts every inline data:image/… URI to a CDN-hosted Moda File, rewrites the HTML to reference the proxy URL, then creates the website row. Sites default to category='html-document', share_state='unlisted', and comments_enabled=true.
Parameters
| Parameter | Type | Required | Description |
|---|
storage_key | string | Yes | The storage_key from create_upload_url, after you PUT the HTML bytes to its upload_url. Not the upload_url itself, not a filename. |
title | string | No | Display title. Omit to let Moda auto-generate a title from the page content. |
publish | boolean | No | When true, also publish to a slugified *.moda.page URL. Defaults to false (draft only). Requires the website-publishing feature when true — otherwise the call errors and the agent should re-call with publish=false. |
category | string | No | Website category. Defaults to html-document for uploaded HTML documents. Valid values are html-document, landing-page, email, and other. |
Returns
{
"website_id": "bb0e8400-e29b-41d4-a716-446655440000",
"editor_url": "https://moda.app/website/bb0e8400-e29b-41d4-a716-446655440000",
"published_url": "https://launch-announcement.moda.page",
"share_state": "unlisted",
"comments_enabled": true,
"extracted_image_count": 4,
"skipped_inline_asset_count": 0
}
editor_url is always present — give this link to the user.
published_url is the live *.moda.page URL when publish=true succeeded; null for drafts. Do not fabricate a *.moda.page URL from the website_id.
update_website_from_upload
Replace the HTML and/or title of an existing website. The website_id is preserved, existing comments stay anchored via a reconciliation pass over the new DOM, and inline data: images in the uploaded HTML are extracted to Moda Files (same pipeline as create_website_from_upload).
Same upload sequence as create_website_from_upload — omit storage_key to keep the current HTML and only rename via title.
Parameters
| Parameter | Type | Required | Description |
|---|
website_id | string | Yes | The website’s ID. |
storage_key | string | No | storage_key from create_upload_url after you PUT the new HTML bytes. Omit to keep the current HTML and only change the title. |
title | string | No | New display title. Omit to keep the current title. |
publish | boolean | No | When true, republish so the live URL reflects the new content. Defaults to false (draft update). Requires website-publishing when true. |
Supply at least one of storage_key or title — a call with neither is rejected.
Returns
{
"website_id": "bb0e8400-e29b-41d4-a716-446655440000",
"editor_url": "https://moda.app/website/bb0e8400-e29b-41d4-a716-446655440000",
"published_url": "https://launch-announcement.moda.page",
"updated_at": "2026-05-26T17:42:11Z",
"extracted_image_count": 4,
"skipped_inline_asset_count": 0
}
published_url is null when publish=false — the live URL keeps serving the previously-published version until the user republishes from the editor.