Skip to main content
Glama

Compose design

compose_design

Create a new social media design (a single image or a multi-slide carousel) from a layout you describe in the JSON format below, and save it to the workspace, where it can be opened in the Blaze editor. Inputs: workspace_key, dsl; optional title. Call get_brand_kit first for the brand colors and fonts; search_fonts finds other fonts and search_media or generate_image provide photos.

Layout: content in "stack", "row", and "grid" containers and "overlay" anchors is placed automatically and cannot overflow the frame, so no coordinates are needed. Decorative elements in "free" can be placed at exact x/y positions, including partly off the canvas.

Pass dsl as: { "frames": [ Frame, ... ] } (one frame = one slide; carousels have several) Frame { "w": 1080, "h": 1350, // 4:5 social default (1080x1920 for a story) "pad": 96, // safe-area inset "justify": "center"|"start"|"end"|"between", // vertical placement of the stack "align": "start"|"center", // default horizontal alignment "bg": { "color": } | { "gradient": [,...], "angle": } | { "image": }, "stack": [ Block, ... ], // main content, flows vertically "overlay": [ { "anchor": , "block": Block } ], // pinned to a corner/edge/center "free": [ { "at": { "x": , "y": } | { "region": , "dx": , "dy": }, "block": Block } ] // exact placement for decoration (off-canvas ok) } = top-left|top-right|bottom-left|bottom-right|top-center|bottom-center|center

Block (one of): TEXT: { "type": "text", "role": "display"|"title"|"body"|"eyebrow"|"credit", "color": , "text": "..." OR "runs": [ { "t": "...", "color": <color?>, "weight": <num?>, "italic": <bool?>, "underline": <bool?>, "strikethrough": <bool?>, "caps": <bool?> } ], "font": <family?>, // override the role font with any family (e.g. from search_fonts) "weight": <num?>, "tracking": <int?>, // thousandths of an em (160 = 0.16em) "autoWidth": <bool?>, // size the box to ONE line of content — the text (and any // panel) hugs its glyphs instead of filling the column; single-line "panel": { "color": , "opacity": <0..1>, "shape": "box"|"silhouetteRounded"|"callToAction" }? } SHAPE: { "type": "shape", "geo": "rectangle"|"roundedRectangle"|"circle"|"triangle"|"diamond"| "hexagon"|"pill"|"fivePointStar"|... , "w": , "h": , "fill": , "stroke": { "color": , "width": }?, "radius": <num?>, "shadow": { "x","y","blur","color","opacity" }? } IMAGE: { "type": "image", "url": , "w": , "h": , "fit": "cover"|"contain", "radius": <num?>, // a placed photo card / band (not full-bleed) "stroke": { "color": , "width": }?, "logo": <bool?> } // logo: true = brand mark GROUP: { "type": "group", "w": , "h": , "layout": "stack"|"row"|"grid", "children": [ Block, ... ] } // moves/rotates as one unit (e.g. a pill = shape + text) ROW: { "type": "row", "gap": <num?>, "justify": "start"|"center"|"end", "align": "top"|"middle"|"bottom", "children": [ Block, ... ] } GRID: { "type": "grid", "cols": , "gap": <num?>, "children": [ Block, ... ] } SPACE: { "type": "space", "h": } // vertical spacer in a stack

Any block also accepts UNIVERSAL props: "rotate": , "opacity": <0..1>, "z": (higher z paints later / on top; use negative z for background decoration).

= | { "gradient": [,...], "angle": } = a brand color token from get_brand_kit ("primary", "accent", …, plus "paper" and "ink", which always exist) or any hex such as "#FF006E". Tokens keep the design in the brand palette.

RULES:

  • "role" picks the font automatically (display/title = title font; body/eyebrow/credit = body font). Only set "font" when you deliberately want a different family.

  • Use "runs" to color one or two key words with an accent color; highlighting more reduces the contrast.

  • "display" = short headline (about 9 words or fewer). "title" = medium. "body" = supporting copy.

  • "eyebrow" is ALL-CAPS small (brand mark / kicker / slide number) — usually an overlay (top-left = brand, top-right = "01 / 05").

  • Shapes, gradients, rotation and free placement are for art direction — accents, dividers, badges, framing. Keep the composition clean; don't clutter.

  • Per carousel slide, vary the bg for rhythm and ensure text contrasts its background. For legibility over a busy area, give text a "panel" (e.g. a dark box at ~0.55 opacity).

  • For a photo: use bg.image for a full-bleed background (get a URL from search_media or generate_image), or a placed "image" block for a card/band inside the layout. Over a photo, keep text in the safe area with high-contrast colors and a panel.

  • Keep on-image text short. The post caption is set separately.

Returns the design id, an editor URL, the element structure (with the aliases the design edit tools use, such as set_design_text and move_design_element), and a rendered preview of every slide. It always creates a new design.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "workspace_key": "<workspace_key>",
      "dsl": "<dsl>"
    },
    "name": "compose_design"
  }
}

Input Schema

NameRequiredDescriptionDefault
dslYesThe design layout: { "frames": [ Frame, ... ] }. See the frame and block format in the tool description.
titleNoOptional design title. Defaults to the first line of copy.
workspace_keyYesKey of the workspace to act in. Call list_workspaces to see the workspaces you have access to and their keys.

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observed

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare non-readOnly, non-idempotent, non-destructive, open-world, and the description reinforces the key one ('always creates a new design') and discloses the return payload: design id, editor URL, element structure with aliases, and a rendered preview of every slide. It also explains layout invariants (stack/row/grid/overlay cannot overflow; free placement may go off-canvas). It stops short of stating auth/plan requirements or any limits on frame count or payload size for carousels.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose, prerequisites and return values are front-loaded, and the bulk of the length is a genuinely necessary DSL schema for a deeply nested parameter. The RULES section drifts into general art-direction coaching ('don't clutter', 'about 9 words or fewer') that is useful but less essential than the format spec.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a high-complexity creation tool with a nested DSL input, no output schema, and mutation annotations, the description covers input format, prerequisite tool order, layout constraints, and the exact shape of the response — everything an agent needs to call it correctly on the first attempt.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the schema defers entirely to the description for the nested dsl object ('See the frame and block format in the tool description'), so the description must carry it — and it does, enumerating Frame fields, every Block type, universal props, color-token resolution, and defaults like the 4:5 1080x1350 frame. This is meaningful semantics well beyond what the schema exposes.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Create a new social media design, single image or multi-slide carousel') plus the side effect (saved to workspace, openable in the Blaze editor). The closing line 'It always creates a new design' cleanly separates it from the many design-mutation siblings like set_design_text and move_design_element.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly prescribes the prerequisite workflow: 'Call get_brand_kit first for the brand colors and fonts; search_fonts finds other fonts and search_media or generate_image provide photos.' It also routes the agent elsewhere after creation by naming the edit tools (set_design_text, move_design_element), so the create-vs-edit boundary is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.