API Reference
Layout CLI exposes 23 MCP tools that AI agents call automatically during development. These tools give your agent structured access to design tokens, component specs, compliance checking, live preview, and a two-way Figma bridge: everything needed to build UI that stays on brand.
npx @layoutdesign/context init and adding the MCP server config to your agent's settings. See the CLI guide for setup instructions.The Full Code-to-Design Loop
The MCP tools are designed to work together across the full development workflow, from the first prompt to a Figma-reviewed, production-ready component. No other open-source tool closes this loop.
Developer prompts Claude Code / Cursor
│
▼
Claude calls get_design_system
│ (loads colour, typography, spacing, component specs)
▼
Claude generates on-brand TSX
│
▼
Claude calls preview
│ (renders live at localhost:4321)
▼
Developer reviews in browser, requests tweaks
│
▼
Claude calls push_to_figma
│ (sends editable frames to Figma via Figma MCP)
▼
Designer reviews and tweaks in Figma
│
▼
Developer asks Claude to read Figma changes
│ (via Figma MCP read tools)
▼
Claude updates TSX to match designer's changes
│
▼
Commit. Design and code are in sync.get_design_system automatically at the start of every UI task. Add a rule to your CLAUDE.md or .cursorrules instructing the agent to fetch design context before writing any UI code. The exported bundle from Layout Studio includes this instruction pre-written.Tools
get_design_system
Returns the full layout.md file, or a specific named section of it. Use this as the first call when starting any UI task. It gives the agent the complete design context it needs to produce on-brand code.
Parameters
| Name | Type | Description |
|---|---|---|
| section | string (optional) | Named section to return. One of: "quick-reference", "colour", "typography", "spacing", "components", "elevation", "motion", "anti-patterns". Omit to return the full file. |
Example
// Agent calls this at the start of a UI task
const designSystem = await mcp.call("get_design_system");
// Or fetch a specific section to reduce token usage
const colourSystem = await mcp.call("get_design_system", {
section: "colour"
});get_tokens
Returns design tokens in a specific format and optionally filtered by token type. Use this when you need raw token values for a stylesheet, Tailwind config, or JSON exchange.
Parameters
| Name | Type | Description |
|---|---|---|
| format | "css" | "json" | "tailwind" | Output format. css returns CSS custom properties, json returns W3C DTCG format, tailwind returns a theme extension object. |
| type | "colour" | "typography" | "spacing" | "radius" | "effect" (optional) | Filter tokens by type. Omit to return all token types. |
Example
// Get all CSS tokens
const tokens = await mcp.call("get_tokens", { format: "css" });
// Get only colour tokens as JSON
const colours = await mcp.call("get_tokens", {
format: "json",
type: "colour"
});
// Get Tailwind theme extension
const tailwindTheme = await mcp.call("get_tokens", {
format: "tailwind"
});list-tokens
Returns a categorised catalogue of every design token in the loaded kit: colour, typography, spacing, radius, and shadow. Dark-mode values are tagged alongside their light counterparts. Use this to browse what exists before choosing a token or calling update_tokens.
Parameters
| Name | Type | Description |
|---|---|---|
| category | "colour" | "typography" | "spacing" | "radius" | "shadow" (optional) | Filter the catalogue to a single token category. Omit to return all categories. |
Example
// Browse the full token catalogue
const catalogue = await mcp.call("list-tokens");
// Only the colour tokens, dark-mode values tagged
const colours = await mcp.call("list-tokens", {
category: "colour"
});
// Returns entries like:
// { name: "--color-primary", value: "#6366F1", dark: "#818CF8", category: "colour" }get_component
Returns the full specification for a named component, including its anatomy, token mappings for all states, and a working TSX code example. Use this before building or modifying any component that exists in the design system.
Parameters
| Name | Type | Description |
|---|---|---|
| name | string | Component name, case-insensitive. Examples: "Button", "Card", "Input", "Modal". Use list_components to discover available names. |
Example
// Get the Button component spec before building it
const buttonSpec = await mcp.call("get_component", {
name: "Button"
});
// Returns: anatomy, token mappings for default/hover/focus/active/disabled/loading/error,
// and a full TSX example using the design system tokenslist_components
Returns an inventory of all components available in the design system, with name, description, variant count, and property definitions for each. Use this to discover what components exist before calling get_component.
Parameters
| Name | Type | Description |
|---|---|---|
| format | "text" | "json" (optional) | Output format. "text" (default) returns a readable listing, "json" returns structured data for programmatic use. |
Example
// Discover all available components
const components = await mcp.call("list_components");
// Structured output for programmatic use
const json = await mcp.call("list_components", { format: "json" });
// Returns an array like:
// [
// { name: "Button", description: "Primary action element", variants: 4 },
// { name: "Card", description: "Content container", variants: 2 },
// ...
// ]check_compliance
Validates a code snippet against the active design system's rules and tokens. Returns a list of compliance issues, each with a rule ID, severity, line reference, message, and the nearest matching design token as a suggested fix. Run this before submitting any UI code. Runs four rules: hardcoded-colours, hardcoded-spacing, missing-token-reference, and unknown-component. The same rule set powers the Check code panel in the Studio Quality tab and the compliance meter in Layout Live.
Parameters
| Name | Type | Description |
|---|---|---|
| code | string | The UI code snippet to check for design system compliance. |
| format | "text" | "json" (optional) | Output format. "text" (default) returns a readable report, "json" returns structured violations for programmatic use, each with a nearest-token suggestion where one exists. |
Example
const result = await mcp.call("check_compliance", {
code: `
<div style={{ color: "#6366f1" }}>
<button className="bg-blue-500 text-white px-4 py-2">
Submit
</button>
</div>
`,
format: "json"
});
// Returns violations with nearest-token suggestions:
// [
// { rule: "hardcoded-colours", severity: "warning", line: 2,
// value: "#6366f1", suggestion: "--color-primary" },
// { rule: "missing-token-reference", severity: "warning", line: 3 }
// ]preview
Renders a TSX component snippet live in a local browser canvas at localhost:4321. The component is transpiled server-side and displayed in a sandboxed iframe with React and Tailwind loaded. Use this to visually confirm a component looks correct before committing the code.
Parameters
| Name | Type | Description |
|---|---|---|
| code | string | The TSX component code to render. Must be a valid React component. |
| props | Record<string, unknown> (optional) | Props to pass to the rendered component. |
Example
// Render a component for visual review
await mcp.call("preview", {
code: `
export default function PricingCard({ plan, price }: { plan: string; price: string }) {
return (
<div className="rounded-xl border border-gray-200 p-6 bg-white">
<h3 className="text-lg font-semibold text-[#0a0a0a]">{plan}</h3>
<p className="text-3xl font-bold text-gray-900 mt-2">{price}</p>
</div>
);
}
`,
props: { plan: "Pro", price: "£19/mo" }
});
// Opens/refreshes localhost:4321 with the rendered componentpush_to_figma
Sends a rendered component to Figma as a set of editable frames via the Figma MCP plugin. Supports two modes: capture (default) renders the component and pushes screenshot-based frames, native creates editable Figma objects with auto-layout using the Figma MCP directly (no Playwright required). Requires the Figma MCP plugin to be installed.
Parameters
| Name | Type | Description |
|---|---|---|
| code | string | The TSX component code to render and push. |
| mode | "capture" | "native" (optional) | Push mode. "capture" (default) renders the component and pushes screenshot-based frames. "native" creates editable Figma objects with auto-layout via the Figma MCP. Native mode does not require Playwright MCP. |
| pageName | string (optional) | Figma page to push the frame to. Defaults to "AI Components". |
| frameName | string (optional) | Name for the created frame. Defaults to the component function name. |
Example
// Push a generated component to Figma for designer review (capture mode)
await mcp.call("push_to_figma", {
code: `
export default function HeroBanner() {
return (
<section className="bg-[var(--color-bg-surface)] px-8 py-16">
<h1 className="text-5xl font-black text-[var(--text-primary)]">
Your AI builds on-brand.
</h1>
</section>
);
}
`,
pageName: "Sprint 3 - Components",
frameName: "HeroBanner / Desktop"
});
// Push as editable Figma objects (native mode, no Playwright needed)
await mcp.call("push_to_figma", {
code: `
export default function HeroBanner() {
return (
<section className="bg-[var(--color-bg-surface)] px-8 py-16">
<h1 className="text-5xl font-black text-[var(--text-primary)]">
Your AI builds on-brand.
</h1>
</section>
);
}
`,
mode: "native",
pageName: "Sprint 3 - Components"
});push_tokens_to_figma
Pushes design system tokens from the loaded kit to Figma as native variables and styles. Creates colour variables, text styles, and effect styles that designers can use directly in their Figma file. Requires the Figma MCP plugin to be installed.
Parameters
| Name | Type | Description |
|---|---|---|
| fileKey | string (optional) | Figma file key to push tokens into. If omitted, creates a new file. |
Example
// Push tokens to an existing Figma file
await mcp.call("push_tokens_to_figma", {
fileKey: "EHmQZ1wq5qHUcifyRYtiBC"
});
// Push tokens to a new Figma file
await mcp.call("push_tokens_to_figma");url_to_figma
Captures a public URL (a live webpage or web app) into Figma as a set of editable frames. Each capture includes both a full-page screenshot and a viewport-cropped version. Useful for documenting reference designs or snapshotting production UI alongside component work.
Parameters
| Name | Type | Description |
|---|---|---|
| url | string | The public URL to capture. |
| pageName | string (optional) | Figma page to push the frames to. Defaults to "URL Captures". |
| viewports | Array<{ width: number; height: number }> (optional) | Viewport dimensions to capture. Defaults to desktop (1440×900) and mobile (390×844). |
Example
// Capture a reference site into Figma
await mcp.call("url_to_figma", {
url: "https://linear.app",
pageName: "Reference - Linear",
viewports: [
{ width: 1440, height: 900 },
{ width: 390, height: 844 }
]
});
// Creates annotated frames in Figma with the captured screenshotsdesign_in_figma
Designs UI directly in Figma using your extracted design tokens. Takes a natural language prompt describing what to design, extracts the relevant colour, typography, and spacing tokens from your loaded kit, and returns structured instructions for the Figma MCP generate_figma_design tool.
Parameters
| Name | Type | Description |
|---|---|---|
| prompt | string (required) | Natural language description of what to design, e.g. 'A settings page with sidebar navigation'. |
| fileKey | string (optional) | Figma file key to design into. If omitted, instructions are returned without a target file. |
| viewports | Array<{ width: number; height: number }> (optional) | Viewport dimensions for the design. Defaults to desktop (1440×900). |
Example
// Design a dashboard directly in Figma using your tokens
await mcp.call("design_in_figma", {
prompt: "A settings page with sidebar navigation and dark theme",
fileKey: "EHmQZ1wq5qHUcifyRYtiBC"
});
// Returns token palette + Figma MCP instructionsupdate_tokens
Updates or adds design tokens in the currently loaded kit. Accepts new token values and merges them into the existing token set, persisting changes to the kit files. Mode-aware: target the light values, the dark values, or both, so updating a light palette never clobbers a dark theme (and vice versa).
Parameters
| Name | Type | Description |
|---|---|---|
| tokens | Record<string, string> (required) | Object of token name-value pairs to add or update, e.g. { '--color-primary': '#6366F1' }. |
| mode | 'light' | 'dark' | 'all' (optional) | Which theme mode to write the values to. 'light' and 'dark' update only that mode's values; 'all' (default) updates both. |
| format | 'css' | 'json' | 'tailwind' (optional) | Which token file to update. Defaults to 'css' (tokens.css). |
Example
// Add a new brand colour token
await mcp.call("update_tokens", {
tokens: { "--color-brand": "#6366F1", "--color-brand-hover": "#7577F3" },
format: "css"
});
// Update only the dark-mode value, leaving light untouched
await mcp.call("update_tokens", {
tokens: { "--color-brand": "#818CF8" },
mode: "dark"
});get_screenshots
Returns design system reference screenshots captured during website extraction. Returns full-page and/or viewport screenshots as images that can be used for visual comparison when building UI components.
Parameters
| Name | Type | Description |
|---|---|---|
| type | "full-page" | "viewport" | "all" (optional) | Which screenshot to return. Defaults to "all" which returns both full-page and viewport captures. |
Example
// Get all reference screenshots
const screenshots = await mcp.call("get_screenshots");
// Get only the viewport-cropped screenshot
const viewport = await mcp.call("get_screenshots", {
type: "viewport"
});scan_project
Scans the project directory for React components and Storybook stories. Returns component names, file paths, props, import paths, and story associations. Auto-runs on MCP server startup so AI agents see your existing codebase components via list_components and reuse them instead of generating duplicates.
Parameters
| Name | Type | Description |
|---|---|---|
| path | string (optional) | Directory to scan. Defaults to the current working directory. |
| type | "storybook" | "codebase" | "both" (optional) | What to scan for. "storybook" finds CSF3 story files, "codebase" finds React component exports, "both" (default) scans for all. |
Example
// Scan the current directory for all components and stories
const result = await mcp.call("scan_project");
// Scan a specific path for Storybook stories only
const stories = await mcp.call("scan_project", {
path: "./src",
type: "storybook"
});
// Returns:
// {
// components: [
// { name: "Button", path: "src/components/Button.tsx", importPath: "@/components/Button", props: [...] },
// ...
// ],
// stories: [
// { name: "ButtonStory", component: "Button", path: "src/stories/Button.stories.tsx" },
// ...
// ]
// }check_setup
Diagnoses and optionally fixes MCP server setup issues. Call this when Figma tools (push_to_figma, design_in_figma, url_to_figma) are not working. Checks MCP registration, transport type, OAuth status, and endpoint reachability. With fix enabled, attempts to re-register missing or misconfigured servers.
Parameters
| Name | Type | Description |
|---|---|---|
| focus | "all" | "figma" | "playwright" | "layout" (optional) | What to check. Defaults to "all". |
| fix | boolean (optional) | If true, attempts to auto-fix issues by re-registering MCP servers. Defaults to false (report only). |
Example
// Check everything
const result = await mcp.call("check_setup");
// Check only Figma setup and auto-fix issues
const fixed = await mcp.call("check_setup", {
focus: "figma",
fix: true
});list_ui_components
Lists the pre-built, token-contracted Layout UI components installable into the project. Use before writing UI primitives from scratch. Returns each component's name, title, description, an install command, and, where available, usage guidance and hard 'never' rules.
No parameters. Call with no arguments.
Example
const catalogue = await mcp.call("list_ui_components");
// Returns entries like:
// { name: "button", title: "Button",
// install: "npx @layoutdesign/context add button", ... }get_selected_element
Returns the element currently selected in the Layout Live desktop app: file, line, column, component name, class list, and inner text. Lets the agent resolve 'this' or 'that one' to a real source location. Returns { running: false } if Live is not running.
No parameters. Call with no arguments.
Example
const selection = await mcp.call("get_selected_element");
// Returns:
// { selected: true, file: "src/components/Hero.tsx",
// line: 42, component: "Hero", classList: "..." }get_recent_visual_edits
Returns recent visual edits the user made in Layout Live, so the agent builds on their tweaks instead of reverting them. Reads the on-disk edit log, so it works even when Live is closed.
Parameters
| Name | Type | Description |
|---|---|---|
| limit | number (optional) | Maximum number of edits to return, most recent first. Defaults to 20, max 100. |
| since | string (optional) | Only return edits with an ISO-8601 timestamp at or after this. |
| file | string (optional) | Filter to edits in this file. |
Example
const edits = await mcp.call("get_recent_visual_edits", {
limit: 10
});get_pending_requests
Returns the free-text change requests the user left in Layout Live, pinned to a selected element, a region, or the page. Each request includes its target location so the agent can apply targeted changes.
Parameters
| Name | Type | Description |
|---|---|---|
| limit | number (optional) | Maximum number of requests to return, most recent first. Defaults to 50, max 200. |
| file | string (optional) | Filter to requests anchored to this file, relative to the project root. |
| includeDone | boolean (optional) | Include requests already marked done. |
Example
const requests = await mcp.call("get_pending_requests");
// Returns requests with targets like:
// { text: "Make this heading smaller on mobile",
// target: "src/components/Hero.tsx:42" }mark-request
Reports progress on a Layout Live request. Call it with status 'in-progress' when starting work on a request and 'done' when finished, with an optional note explaining what was changed. The request's pin recolours on the page (amber pending, blue in progress, green done) and the entry in Live's Requests panel shows 'Resolved by agent' with the note.
Parameters
| Name | Type | Description |
|---|---|---|
| id | string | The request id, as returned by get_pending_requests. |
| status | "in-progress" | "done" | The new status for the request. |
| note | string (optional) | A short note shown against the request, e.g. what was changed or why it was skipped. |
Example
// Claim a request before starting work
await mcp.call("mark-request", {
id: request.id,
status: "in-progress"
});
// Report it complete with a note
await mcp.call("mark-request", {
id: request.id,
status: "done",
note: "Reduced heading to text-2xl below the md breakpoint"
});get-live-screenshot
Returns the screenshot Layout Live captured when a request was pinned (region requests are cropped to the pinned region), or a fresh capture of the current page while Live is running. Gives the agent visual context for exactly what the user was looking at when they filed the request.
Parameters
| Name | Type | Description |
|---|---|---|
| request_id | string (optional) | Return the stored screenshot for this request id. Omit to take a fresh capture of the current page (requires Live to be running). |
Example
// The screenshot stored with a pinned request
const shot = await mcp.call("get-live-screenshot", {
request_id: request.id
});
// A fresh capture of whatever Live is showing right now
const current = await mcp.call("get-live-screenshot");lock_file
Reserves exclusive write access to a file before the agent edits it, coordinating with Layout Live so the two never overwrite each other. Locks auto-expire after the TTL.
Parameters
| Name | Type | Description |
|---|---|---|
| path | string | Path relative to the project root. |
| ttl_seconds | number (optional) | How long the lock is held before it auto-expires. Defaults to 60, max 300. |
| reason | string (optional) | Why the lock is being acquired. |
Example
const lock = await mcp.call("lock_file", {
path: "src/components/Hero.tsx",
ttl_seconds: 120
});unlock_file
Releases a previously-acquired file lock. Pass the lock_id returned by lock_file. A non-matching or already-expired lock_id releases nothing.
Parameters
| Name | Type | Description |
|---|---|---|
| lock_id | string | The lock_id returned by a prior lock_file call. |
Example
await mcp.call("unlock_file", {
lock_id: lock.lock_id
});Compliance Rules Reference
The check_compliance tool runs four rules against your code. Each rule returns issues with a severity, line reference, and message. The same rule set powers the Check code panel in the Studio Quality tab and Layout Live's edit gating, so one definition of "on-system" applies everywhere.
| Rule ID | What It Checks |
|---|---|
| hardcoded-colours | Flags hex, rgb(), and hsl() colour values that should reference design tokens instead |
| hardcoded-spacing | Flags raw pixel spacing values that should use the design system's spacing tokens |
| missing-token-reference | Flags var(--token) references to tokens that are not defined in the kit |
| unknown-component | Warns when code references component names not found in the design system inventory |