FigClank MCP Design Contract
The stable contract for the FigClank read-only MCP server.
Overview
- Mode: Read-only. No mutations are allowed via MCP.
- Auth: Wallet-based authentication. All document-scoped tools require user authentication.
- Units: All dimensions are in pixels (px) unless otherwise noted.
- IDs: All identifiers (nodeId, documentId, componentId, styleId) are strings.
Node Types
type NodeType =
| "PAGE"
| "FRAME"
| "RECTANGLE"
| "TEXT"
| "COMPONENT"
| "INSTANCE"
| "GROUP"
| "VECTOR"
| "ELLIPSE"
| "LINE"
| "POLYGON"
| "STAR"
| "BOOLEAN_OPERATION";Core Schemas
MCPNode
The canonical node schema exposed by the MCP. All fields use consistent types and units.
interface MCPNode {
// Identity
id: string;
name: string;
type: NodeType;
parentId: string | null;
// Transform (all in px)
x: number;
y: number;
width: number;
height: number;
rotation?: number; // degrees
// Visibility
visible?: boolean;
locked?: boolean;
opacity?: number; // 0-1
// Layout (Auto Layout)
layout?: {
mode: "NONE" | "HORIZONTAL" | "VERTICAL";
primaryAxisAlign: "MIN" | "CENTER" | "MAX" | "SPACE_BETWEEN";
counterAxisAlign: "MIN" | "CENTER" | "MAX" | "STRETCH";
primaryAxisSizing: "FIXED" | "AUTO" | "FILL";
counterAxisSizing: "FIXED" | "AUTO" | "FILL";
padding: { top: number; right: number; bottom: number; left: number; };
itemSpacing: number | "AUTO";
wrap?: boolean;
};
// Style
style?: {
fills?: MCPFill[];
strokes?: MCPStroke[];
effects?: MCPEffect[];
cornerRadius?: number;
clipsContent?: boolean;
blendMode?: string;
};
// Text (for TEXT nodes)
text?: {
characters: string;
fontSize: number;
fontFamily: string;
fontStyle: string;
textAlignHorizontal: "LEFT" | "CENTER" | "RIGHT" | "JUSTIFIED";
textAlignVertical: "TOP" | "CENTER" | "BOTTOM";
autoResize: "WIDTH_AND_HEIGHT" | "HEIGHT" | "NONE";
};
// Component reference (for INSTANCE nodes)
componentRef?: {
componentId: string;
componentKey?: string;
};
}MCPFill
interface MCPFill {
type: "SOLID" | "GRADIENT_LINEAR" | "GRADIENT_RADIAL" | "GRADIENT_ANGULAR" | "GRADIENT_DIAMOND" | "IMAGE";
visible?: boolean;
opacity?: number; // 0-1
blendMode?: string;
// For SOLID
color?: MCPColor;
// For gradients
gradientStops?: Array<{ position: number; color: MCPColor; }>;
// For IMAGE
imageRef?: string;
scaleMode?: "FILL" | "FIT" | "CROP" | "TILE";
}MCPColor
interface MCPColor {
r: number; // 0-1
g: number; // 0-1
b: number; // 0-1
a: number; // 0-1
}MCPEffect
interface MCPEffect {
type: "DROP_SHADOW" | "INNER_SHADOW" | "LAYER_BLUR" | "BACKGROUND_BLUR";
visible?: boolean;
radius?: number; // px
color?: MCPColor;
offset?: { x: number; y: number }; // px
spread?: number; // px
}Tool Categories
Discovery
| Tool | Description |
|---|---|
| auth.whoami | Get current user info |
| workspace.listProjects | List user's projects/designs |
| documents.list | List documents in a project |
| documents.get | Get document metadata |
Snapshots & History
| Tool | Description |
|---|---|
| documents.getSnapshot | Get lightweight snapshot summary |
| history.listVersions | List document versions |
Node Inspection
| Tool | Description |
|---|---|
| nodes.get | Get single node |
| nodes.listChildren | List children of a node |
| nodes.getSubtree | Get subtree with depth limit |
| nodes.query | Query nodes by criteria |
Design System
| Tool | Description |
|---|---|
| components.list | List components |
| components.get | Get component definition |
| styles.list | List styles |
| tokens.get | Get design tokens |
Export / Render
| Tool | Description |
|---|---|
| render.thumbnail | Get node thumbnail |
| export.svg | Export node as SVG |
| export.png | Export node as PNG |
Read-Only Guarantee
Important
This MCP server is strictly read-only. No tools modify document state. No tools create, update, or delete nodes. No tools change styles, components, or tokens. All operations are idempotent. To edit designs, use the FigClank web application.
Error Codes
| Tool | Description |
|---|---|
| NOT_FOUND | Resource does not exist (404) |
| FORBIDDEN | User lacks permission (403) |
| VALIDATION_ERROR | Invalid input parameters (400) |
| RATE_LIMITED | Too many requests (429) |
| INTERNAL_ERROR | Server error (500) |
Version Pinning
All document-scoped tools accept an optional version parameter:
// Load a specific version (deterministic)
nodes.get({ nodeId, documentId, version: 42 })
// Load latest (may change between calls)
nodes.get({ nodeId, documentId })Agents should pass version for reproducible codegen workflows.