From 1a35adb335255724d84272a726841d683867ce78 Mon Sep 17 00:00:00 2001 From: Gabi Date: Mon, 20 Jul 2026 21:34:51 +0200 Subject: [PATCH 1/3] fix: correct MCP tool shapes that would have failed every call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A review pass caught that several documented tool shapes no longer match the live server. Anyone following these docs would build calls the API rejects. Verified every one of the 15 tools against the live schemas rather than patching only what was reported — which turned up two more nobody had flagged. apply_design_system was the worst of it. Docs said `selectedScreenIds: ["abc123"]`; the API takes `selectedScreenInstances: [{id, sourceScreen}]`. Both new DESIGN.md skills route into it, so the feature this release is built around dead-ended. The instance id is not the source screen id, and swapping them fails — the skill now says so explicitly. update_design_system was structurally wrong: `name` was nested inside `designSystem` and `projectId` was absent entirely. The live tool takes all three as siblings, all required. Found by the sweep, not the review: - generate_variants documented `prompt` and `variantOptions` as optional; both are required - get_screen omitted `name` altogether — it's the current identifier and takes the full resource path, while projectId/screenId are deprecated but still mandatory Also corrected: - assetId goes BARE to apply_design_system but PREFIXED to generate_screen_from_text and update_design_system. Three skills taught the wrong form; each now states which tool wants which. - generate_screen_from_text was missing its `designSystem` param. Here the skills were right and our schema was stale — that param is what makes DESIGN.md -> design system -> generation actually hold together. - Input payloads sent `font`, `backgroundLight`, `backgroundDark`, `description`, `designTokens`, `styleGuidelines`. None exist on the live input. The output examples that show `font` stay — it is returned, just not settable. - DesignTheme had `required: null` despite requiring five fields - `ROBOTO` was offered as a font value; it isn't in the enum (`ROBOTO_FLEX` is). Same class as the fictional names caught earlier. - Skill/tool counts and the two new wrappers were missing from AGENTS.md and the agent definition, so the shipped agent didn't know its own new skills existed. All 15 schemas now match the live server on properties and required fields, checked programmatically. --- AGENTS.md | 12 +++-- agents/stitch-kit.md | 5 +- docs/mcp-schemas/README.md | 12 +++-- docs/mcp-schemas/apply_design_system.json | 50 +++++++++++++---- docs/mcp-schemas/create_design_system.json | 38 +++---------- .../generate_screen_from_text.json | 4 ++ docs/mcp-schemas/generate_variants.json | 50 ++++++++++++++--- docs/mcp-schemas/get_screen.json | 54 +++++++++++++++---- docs/mcp-schemas/update_design_system.json | 45 ++++++++++++---- docs/skills-index.md | 11 ++-- .../stitch-mcp-apply-design-system/SKILL.md | 37 ++++++++----- .../SKILL.md | 2 +- .../stitch-mcp-create-design-system/SKILL.md | 46 ++++++++-------- skills/stitch-mcp-create-project/SKILL.md | 6 +-- .../SKILL.md | 12 ++++- skills/stitch-mcp-get-screen/SKILL.md | 14 +++-- .../stitch-mcp-list-design-systems/SKILL.md | 12 ++--- .../stitch-mcp-update-design-system/SKILL.md | 35 ++++++------ 18 files changed, 295 insertions(+), 150 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 3328994..8f5cc0a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,7 +4,7 @@ Guidance for Claude Code, Cursor, Copilot, Codex CLI, and other AI agents workin ## What this repo is -A collection of Claude Code **skills** — 35 packaged instructions and scripts that extend AI agents with Stitch-specific capabilities: text-to-UI generation, design iteration (edit, variants, design systems), design token extraction, and multi-framework conversion. Think of it as a Stitch co-pilot that wraps 13 of the 15 Stitch MCP tools and knows the footguns so you don't have to learn them the hard way. +A collection of Claude Code **skills** — 36 packaged instructions and scripts that extend AI agents with Stitch-specific capabilities: text-to-UI generation, design iteration (edit, variants, design systems), design token extraction, and multi-framework conversion. Think of it as a Stitch co-pilot that wraps all 15 Stitch MCP tools and knows the footguns so you don't have to learn them the hard way. ## Skill structure @@ -15,7 +15,7 @@ skills/{skill-name}/ ├── SKILL.md ← Required: activation instructions and workflow ├── examples/ ← Required: worked examples (gold-standard reference) ├── resources/ ← Optional: templates, checklists, mapping tables -├── scripts/ ← Optional: bash scripts (fetch-stitch.sh, encode-image.sh, etc.) +├── scripts/ ← Optional: bash scripts (fetch-stitch.sh, init_stitch_skill.py, etc.) └── references/ ← Optional: style guides, contracts ``` @@ -88,7 +88,7 @@ For Stitch-based UI generation, load **`stitch-orchestrator`** or invoke the **` | Layer | Count | Purpose | |-------|-------|---------| | **Brain** (`stitch-ui-*`, `stitch-ideate`) | 5 | Design intelligence — ideation agent, specs, prompts, variants, UED guide | -| **Hands** (`stitch-mcp-*`) | 13 | MCP wrappers — one per Stitch API tool, handles ID format rules | +| **Hands** (`stitch-mcp-*`) | 15 | MCP wrappers — one per Stitch API tool, handles ID format rules | | **Conversion** | 7+ | Stitch HTML → framework components (Next.js, Svelte, React, HTML, RN, SwiftUI, shadcn) | | **Quality** | 3 | Design tokens, accessibility audit, animations | @@ -98,7 +98,7 @@ Skills marked `allowed-tools: ["stitch*:*"]` require the **Stitch MCP Server** c Setup guide: https://stitch.withgoogle.com/docs/mcp/setup -13 of the 15 Stitch MCP tools wrapped: `create_project`, `get_project`, `delete_project`, `list_projects`, `generate_screen_from_text`, `edit_screens`, `generate_variants`, `list_screens`, `get_screen`, `create_design_system`, `update_design_system`, `list_design_systems`, `apply_design_system` +All 15 Stitch MCP tools wrapped: `create_project`, `get_project`, `delete_project`, `list_projects`, `generate_screen_from_text`, `edit_screens`, `generate_variants`, `list_screens`, `get_screen`, `create_design_system`, `update_design_system`, `list_design_systems`, `apply_design_system`, `upload_design_md`, `create_design_system_from_design_md` Without MCP: the orchestrator falls back to prompt-only mode (generates ready-to-copy Stitch prompts instead of running the full workflow — still useful, just slower). @@ -113,6 +113,8 @@ Without MCP: the orchestrator falls back to prompt-only mode (generates ready-to | `stitch-mcp-edit-screens` | Edit existing screens with text prompts (iteration) | | `stitch-mcp-generate-variants` | Generate design alternatives with creativity controls | | `stitch-mcp-create-design-system` | Create reusable Stitch Design Systems | +| `stitch-mcp-upload-design-md` | Upload a DESIGN.md into a project (pairs with the next row) | +| `stitch-mcp-create-design-system-from-design-md` | Turn an uploaded DESIGN.md into a design system | | `stitch-mcp-apply-design-system` | Apply design systems to screens | | `stitch-mcp-get-screen` | Retrieve screen HTML + screenshot by ID | | `stitch-design-system` | Extract design tokens → CSS + Tailwind files | @@ -131,7 +133,7 @@ Without MCP: the orchestrator falls back to prompt-only mode (generates ready-to See [`docs/`](docs/) for: - `skills-index.md` — complete skills table with descriptions and layers -- `mcp-schemas/` — JSON Schema for the 13 Stitch MCP tools this repo wraps +- `mcp-schemas/` — JSON Schema for all 15 Stitch MCP tools - `color-prompt-guide.md` — 8 ready-to-use color palette prompts for Stitch - `tailwind-reference.md` — Tailwind utility class reference for conversions - `mcp-naming-convention.md` — MCP tool name → skill name mapping diff --git a/agents/stitch-kit.md b/agents/stitch-kit.md index 3493d76..ca07bfa 100644 --- a/agents/stitch-kit.md +++ b/agents/stitch-kit.md @@ -14,6 +14,7 @@ You are a Stitch design-to-code specialist. You handle the full pipeline from UI - Edit existing screens with text prompts (edit_screens) — iterate without regenerating - Generate design variants with configurable creativity and aspect controls (generate_variants) - Create, update, list, and apply Stitch Design Systems for cross-screen consistency +- Turn a DESIGN.md into a Stitch Design System (upload_design_md, then create_design_system_from_design_md — always both) - Convert Stitch HTML to Next.js 15 App Router, Svelte 5, Vite+React, HTML5, React Native/Expo, or SwiftUI - Extract design tokens → CSS custom properties (light + dark mode) - Build multi-page sites iteratively with the stitch-loop baton pattern @@ -69,9 +70,11 @@ Stitch uses inconsistent ID formats across tools. Use the `stitch-mcp-*` wrapper | `edit_screens` | Numeric | Numeric array | — | | `generate_variants` | Numeric | Numeric array | — | | `create_design_system` | Numeric (optional) | — | Returns Asset `name` | +| `upload_design_md` | Numeric | — | Body is base64; `base64 -i` on macOS | +| `create_design_system_from_design_md` | Numeric | Screen **instance** id + full `sourceScreen` path | Instance id is not the source screen id | | `update_design_system` | — | — | Asset `name` required | | `list_design_systems` | Numeric (optional) | — | Returns Asset names | -| `apply_design_system` | Numeric | Numeric array | `assetId` required | +| `apply_design_system` | Numeric | Screen **instances** (`{id, sourceScreen}`), not bare ids | `assetId` bare numeric, no `assets/` prefix | ## Framework selection guide diff --git a/docs/mcp-schemas/README.md b/docs/mcp-schemas/README.md index 1cde600..44f40f6 100644 --- a/docs/mcp-schemas/README.md +++ b/docs/mcp-schemas/README.md @@ -1,6 +1,6 @@ # Stitch MCP API Schemas -Formal JSON Schema definitions for the 13 Stitch MCP tools this repo wraps. +Formal JSON Schema definitions for the 15 Stitch MCP tools this repo wraps. Each file documents the full `arguments` (input) and `outputSchema` (output) for one tool. @@ -34,7 +34,9 @@ Each file documents the full `arguments` (input) and `outputSchema` (output) for | `create_design_system.json` | `create_design_system` | Create a reusable design system. Optional numeric `projectId`. | | `update_design_system.json` | `update_design_system` | Update an existing design system. Requires asset `name`. | | `list_design_systems.json` | `list_design_systems` | List available design systems. Optional numeric `projectId`. | -| `apply_design_system.json` | `apply_design_system` | Apply a design system to screens. **Numeric IDs** + `assetId`. | +| `apply_design_system.json` | `apply_design_system` | Apply a design system to screens. Screen **instances** (`{id, sourceScreen}`) + bare `assetId`. | +| `upload_design_md.json` | `upload_design_md` | Upload a DESIGN.md into a project. Numeric `projectId`, base64 body. | +| `create_design_system_from_design_md.json` | `create_design_system_from_design_md` | Turn an uploaded DESIGN.md into a design system. Numeric `projectId` + screen instance. | --- @@ -154,8 +156,10 @@ Useful for: targeted HTML extraction, component-level conversion, design audits. | `list_screens` | `projects/NUMERIC` | — | — | | `get_screen` | **NUMERIC only** | **NUMERIC only** | — | | `create_design_system` | **NUMERIC** (optional) | — | Returns Asset `name` | -| `update_design_system` | — | — | Asset `name` required | +| `update_design_system` | — | — | Asset `name` (prefixed) required | | `list_design_systems` | **NUMERIC** (optional) | — | Returns Asset names | -| `apply_design_system` | **NUMERIC only** | **NUMERIC array** | `assetId` required | +| `apply_design_system` | **NUMERIC only** | Screen **instances** (`{id, sourceScreen}`) | `assetId` bare numeric, no prefix | +| `upload_design_md` | **NUMERIC only** | — | Body is base64 | +| `create_design_system_from_design_md` | **NUMERIC only** | Screen **instance** (`{id, sourceScreen}`) | — | See `../mcp-naming-convention.md` for the full breakdown. diff --git a/docs/mcp-schemas/apply_design_system.json b/docs/mcp-schemas/apply_design_system.json index 90e65d5..d33a7f1 100644 --- a/docs/mcp-schemas/apply_design_system.json +++ b/docs/mcp-schemas/apply_design_system.json @@ -1,6 +1,6 @@ { "name": "apply_design_system", - "description": "Applies a Stitch Design System to one or more existing screens, updating their visual theme.\n\n**Input Requirements (CRITICAL):**\n1. **`projectId` (string - MANDATORY):** Numeric ID only.\n2. **`selectedScreenIds` (array - MANDATORY):** Numeric screen IDs.\n3. **`assetId` (string - MANDATORY):** Design system asset identifier.\n", + "description": "Applies a Stitch Design System to one or more existing screens, updating their visual theme.\n\n**Input Requirements (CRITICAL):**\n1. **`projectId` (string - MANDATORY):** Numeric ID only, no `projects/` prefix.\n2. **`selectedScreenInstances` (array of objects - MANDATORY):** Screen INSTANCES, each `{id, sourceScreen}`. NOT an array of bare screen ids. `id` is the screen instance id (from get_project's screenInstances), NOT the source screen id; `sourceScreen` is the full `projects/{p}/screens/{s}` path.\n3. **`assetId` (string - MANDATORY):** Bare numeric asset id, WITHOUT the `assets/` prefix.\n", "arguments": { "type": "object", "properties": { @@ -8,17 +8,23 @@ "description": "Required. Numeric project ID only — do NOT include 'projects/' prefix.", "type": "string" }, - "selectedScreenIds": { - "description": "Required. Array of numeric screen IDs to apply the design system to.", - "type": "array", - "items": { "type": "string" } - }, "assetId": { - "description": "Required. The design system asset identifier from list or create operations.", + "description": "Required. The asset id of the design system to apply, can be fetched from `list_design_systems`. Example: '15996705518239280238', without the `assets/` prefix.", "type": "string" + }, + "selectedScreenInstances": { + "description": "Required. The screen instances to edit, which is available in the Project info, fetched by `get_project`. NOT bare screen ids.", + "type": "array", + "items": { + "$ref": "#/$defs/SelectedScreenInstance" + } } }, - "required": ["projectId", "selectedScreenIds", "assetId"], + "required": [ + "projectId", + "selectedScreenInstances", + "assetId" + ], "description": "Request message for ApplyDesignSystem." }, "outputSchema": { @@ -28,9 +34,33 @@ "description": "Array of output components with updated screen data.", "type": "array" }, - "projectId": { "type": "string" }, - "sessionId": { "type": "string" } + "projectId": { + "type": "string" + }, + "sessionId": { + "type": "string" + } }, "description": "Response message for ApplyDesignSystem." + }, + "$defs": { + "SelectedScreenInstance": { + "type": "object", + "description": "A screen instance to be edited by the agent, selected by the user.", + "properties": { + "id": { + "description": "Required. The id of the screen instance, NOT the source screen id. Available in screenInstances from `get_project`.", + "type": "string" + }, + "sourceScreen": { + "description": "Required. The resource name of the source screen. Format: projects/{project}/screens/{screen}", + "type": "string" + } + }, + "required": [ + "id", + "sourceScreen" + ] + } } } diff --git a/docs/mcp-schemas/create_design_system.json b/docs/mcp-schemas/create_design_system.json index 31f2762..944a35d 100644 --- a/docs/mcp-schemas/create_design_system.json +++ b/docs/mcp-schemas/create_design_system.json @@ -28,14 +28,6 @@ "theme": { "$ref": "#/$defs/DesignTheme", "description": "Required. Visual theme configuration." - }, - "designTokens": { - "description": "Optional. CSS custom properties or token definitions.", - "type": "string" - }, - "styleGuidelines": { - "description": "Optional. Natural-language design rules.", - "type": "string" } }, "required": [ @@ -71,20 +63,6 @@ "description": "Primary color (hex).", "type": "string" }, - "backgroundLight": { - "description": "Light mode background (hex).", - "type": "string" - }, - "backgroundDark": { - "description": "Dark mode background (hex).", - "type": "string" - }, - "preset": { - "type": "string" - }, - "description": { - "type": "string" - }, "colorVariant": { "enum": [ "COLOR_VARIANT_UNSPECIFIED", @@ -319,15 +297,6 @@ ], "type": "string" }, - "namedColors": { - "type": "object", - "description": "Semantic color map (40+ tokens like primary, on_primary, surface, etc.)" - }, - "spacingScale": { - "format": "int32", - "type": "integer", - "description": "0=minimal, 1=compact, 2=normal, 3=spacious" - }, "designMd": { "type": "string", "description": "Auto-generated markdown design system document" @@ -360,6 +329,13 @@ "description": "Optional. Map of typography level name (e.g. \"h1\", \"body\") to Typography token overrides." } }, + "required": [ + "colorMode", + "headlineFont", + "bodyFont", + "roundness", + "customColor" + ], "type": "object" }, "Typography": { diff --git a/docs/mcp-schemas/generate_screen_from_text.json b/docs/mcp-schemas/generate_screen_from_text.json index 10e8e5e..1c41ffc 100644 --- a/docs/mcp-schemas/generate_screen_from_text.json +++ b/docs/mcp-schemas/generate_screen_from_text.json @@ -32,6 +32,10 @@ "prompt": { "description": "Required. The text prompt describing the screen to generate.", "type": "string" + }, + "designSystem": { + "description": "Optional. The design system id to use for generating the new screen, should always be configured for design consistency. Takes the `assets/` prefix. Example: 'assets/15996705518239280238'.", + "type": "string" } }, "required": ["projectId", "prompt"], diff --git a/docs/mcp-schemas/generate_variants.json b/docs/mcp-schemas/generate_variants.json index 08fa706..9d43a48 100644 --- a/docs/mcp-schemas/generate_variants.json +++ b/docs/mcp-schemas/generate_variants.json @@ -11,7 +11,9 @@ "selectedScreenIds": { "description": "Required. Array of numeric screen IDs to generate variants from.", "type": "array", - "items": { "type": "string" } + "items": { + "type": "string" + } }, "prompt": { "description": "Optional. Guidance text for the variant direction.", @@ -23,16 +25,32 @@ }, "deviceType": { "description": "Optional. Device type context.", - "enum": ["DEVICE_TYPE_UNSPECIFIED", "MOBILE", "DESKTOP", "TABLET", "AGNOSTIC"], + "enum": [ + "DEVICE_TYPE_UNSPECIFIED", + "MOBILE", + "DESKTOP", + "TABLET", + "AGNOSTIC" + ], "type": "string" }, "modelId": { "description": "Optional. GEMINI_3_1_PRO = latest Thinking model. GEMINI_3_PRO = deprecated (use 3_1_PRO). GEMINI_3_FLASH for speed.", - "enum": ["MODEL_ID_UNSPECIFIED", "GEMINI_3_PRO", "GEMINI_3_FLASH", "GEMINI_3_1_PRO"], + "enum": [ + "MODEL_ID_UNSPECIFIED", + "GEMINI_3_PRO", + "GEMINI_3_FLASH", + "GEMINI_3_1_PRO" + ], "type": "string" } }, - "required": ["projectId", "selectedScreenIds"], + "required": [ + "projectId", + "selectedScreenIds", + "prompt", + "variantOptions" + ], "description": "Request message for GenerateVariants.", "$defs": { "VariantOptions": { @@ -46,14 +64,26 @@ }, "creativeRange": { "description": "How much to deviate from the original design.", - "enum": ["CREATIVE_RANGE_UNSPECIFIED", "REFINE", "EXPLORE", "REIMAGINE"], + "enum": [ + "CREATIVE_RANGE_UNSPECIFIED", + "REFINE", + "EXPLORE", + "REIMAGINE" + ], "type": "string" }, "aspects": { "description": "Which design aspects to vary.", "type": "array", "items": { - "enum": ["ASPECT_UNSPECIFIED", "LAYOUT", "COLOR_SCHEME", "IMAGES", "TEXT_FONT", "TEXT_CONTENT"], + "enum": [ + "ASPECT_UNSPECIFIED", + "LAYOUT", + "COLOR_SCHEME", + "IMAGES", + "TEXT_FONT", + "TEXT_CONTENT" + ], "type": "string" } } @@ -69,8 +99,12 @@ "description": "Array of output components with generated variant screens.", "type": "array" }, - "projectId": { "type": "string" }, - "sessionId": { "type": "string" } + "projectId": { + "type": "string" + }, + "sessionId": { + "type": "string" + } }, "description": "Response message for GenerateVariants." } diff --git a/docs/mcp-schemas/get_screen.json b/docs/mcp-schemas/get_screen.json index 5442b97..bec8af9 100644 --- a/docs/mcp-schemas/get_screen.json +++ b/docs/mcp-schemas/get_screen.json @@ -4,16 +4,26 @@ "arguments": { "type": "object", "properties": { - "projectId": { - "description": "Required. Numeric project ID only — do NOT include 'projects/' prefix.", + "name": { + "description": "Required. Identifier. The resource name of the screen to retrieve. Format: `projects/{project}/screens/{screen}` Example: `projects/4044680601076201931/screens/98b50e2ddc9943efb387052637738f61`", "type": "string" }, + "projectId": { + "description": "Required. Numeric project ID only — do NOT include 'projects/' prefix. DEPRECATED — prefer the `name` field.", + "type": "string", + "deprecated": true + }, "screenId": { - "description": "Required. Numeric/hex screen ID — do NOT include path prefix.", - "type": "string" + "description": "Required. Numeric/hex screen ID — do NOT include path prefix. DEPRECATED — prefer the `name` field.", + "type": "string", + "deprecated": true } }, - "required": ["projectId", "screenId"], + "required": [ + "name", + "projectId", + "screenId" + ], "description": "Request message for GetScreen." }, "outputSchema": { @@ -21,10 +31,19 @@ "properties": { "deviceType": { "description": "The device type of the screen.", - "enum": ["DEVICE_TYPE_UNSPECIFIED", "MOBILE", "DESKTOP", "TABLET", "AGNOSTIC"], + "enum": [ + "DEVICE_TYPE_UNSPECIFIED", + "MOBILE", + "DESKTOP", + "TABLET", + "AGNOSTIC" + ], + "type": "string" + }, + "height": { + "description": "Screen height in pixels.", "type": "string" }, - "height": { "description": "Screen height in pixels.", "type": "string" }, "htmlCode": { "$ref": "#/$defs/File", "description": "The HTML code of the screen. Use downloadUrl to fetch the full HTML." @@ -38,8 +57,15 @@ "$ref": "#/$defs/File", "description": "PNG screenshot. Use downloadUrl to download." }, - "title": { "description": "Output only. Generated screen title.", "readOnly": true, "type": "string" }, - "width": { "description": "Screen width in pixels.", "type": "string" } + "title": { + "description": "Output only. Generated screen title.", + "readOnly": true, + "type": "string" + }, + "width": { + "description": "Screen width in pixels.", + "type": "string" + } }, "$defs": { "File": { @@ -65,7 +91,9 @@ "UserFeedback": { "description": "User feedback for a given interaction.", "properties": { - "comment": { "type": "string" }, + "comment": { + "type": "string" + }, "designFeedbackReason": { "enum": [ "DESIGN_FEEDBACK_REASON_UNSPECIFIED", @@ -80,7 +108,11 @@ "type": "string" }, "rating": { - "enum": ["RATING_UNSPECIFIED", "POSITIVE", "NEGATIVE"], + "enum": [ + "RATING_UNSPECIFIED", + "POSITIVE", + "NEGATIVE" + ], "type": "string" } }, diff --git a/docs/mcp-schemas/update_design_system.json b/docs/mcp-schemas/update_design_system.json index 69b4113..3361744 100644 --- a/docs/mcp-schemas/update_design_system.json +++ b/docs/mcp-schemas/update_design_system.json @@ -1,31 +1,54 @@ { "name": "update_design_system", - "description": "Updates an existing Stitch Design System's theme, tokens, or guidelines.\n", + "description": "Updates an existing Stitch Design System's display name and/or theme.\n", "arguments": { "type": "object", "properties": { + "name": { + "description": "Required. Identifier. The resource name of the design system to update. Format: `assets/{asset_id}` — WITH the `assets/` prefix. Example: `assets/15996705518239280238`. Note apply_design_system takes the same id BARE.", + "type": "string" + }, + "projectId": { + "description": "Required. The project ID to update the design system for, example: '4044680601076201931', without the `projects/` prefix.", + "type": "string" + }, "designSystem": { "description": "Required. Asset wrapper with name + updated fields. Full replacement, not merge.", "type": "object", "properties": { - "name": { "description": "Required. Asset name from create or list (e.g., assets/ds_abc123).", "type": "string" }, - "displayName": { "type": "string" }, - "theme": { "description": "Updated DesignTheme object.", "type": "object" }, - "designTokens": { "type": "string" }, - "styleGuidelines": { "type": "string" } + "displayName": { + "type": "string" + }, + "theme": { + "description": "Updated DesignTheme object.", + "type": "object" + } }, - "required": ["name"] + "required": [ + "displayName", + "theme" + ] } }, - "required": ["designSystem"], + "required": [ + "name", + "projectId", + "designSystem" + ], "description": "Request message for UpdateDesignSystem." }, "outputSchema": { "type": "object", "properties": { - "name": { "type": "string" }, - "displayName": { "type": "string" }, - "designSystem": { "type": "object" } + "name": { + "type": "string" + }, + "displayName": { + "type": "string" + }, + "designSystem": { + "type": "object" + } }, "description": "Updated Asset response." } diff --git a/docs/skills-index.md b/docs/skills-index.md index e782b38..89b2d9e 100644 --- a/docs/skills-index.md +++ b/docs/skills-index.md @@ -87,13 +87,16 @@ This is the most common source of bugs when calling Stitch MCP tools directly: | `list_screens` | `projects/NUMERIC_ID` | — | — | | `get_screen` | **Numeric only** | **Numeric only** | — | | `create_design_system` | **Numeric only** (optional) | — | Returns Asset `name` | -| `update_design_system` | — | — | Asset `name` required | +| `update_design_system` | — | — | Asset `name` (prefixed) required | | `list_design_systems` | **Numeric only** (optional) | — | Returns Asset names | -| `apply_design_system` | **Numeric only** | **Numeric array** | `assetId` required | +| `apply_design_system` | **Numeric only** | Screen **instances** (`{id, sourceScreen}`) | `assetId` bare numeric, no prefix | +| `upload_design_md` | **Numeric only** | — | Body is base64 | +| `create_design_system_from_design_md` | **Numeric only** | Screen **instance** (`{id, sourceScreen}`) | — | **Rules of thumb:** - **Read operations** (`get_project`, `list_screens`, `delete_project`) → `projects/ID` full path -- **Generation/mutation** (`generate_screen_from_text`, `edit_screens`, `generate_variants`, `apply_design_system`) → numeric only +- **Generation/mutation** (`generate_screen_from_text`, `edit_screens`, `generate_variants`) → numeric only +- **`apply_design_system`** → numeric `projectId`, but screen **instances** (not bare screenIds) and a bare (unprefixed) `assetId` - **Design system operations** → numeric `projectId` (optional), asset `name` for identity See `mcp-naming-convention.md` for full details. @@ -103,7 +106,7 @@ See `mcp-naming-convention.md` for full details. ## References - `mcp-naming-convention.md` — ID format rules -- `mcp-schemas/` — Formal JSON Schema definitions for the 13 Stitch MCP tools this repo wraps (fonts, roundness, componentRegions, outputComponents, variantOptions, designSystems) +- `mcp-schemas/` — Formal JSON Schema definitions for the 15 Stitch MCP tools this repo wraps (fonts, roundness, componentRegions, outputComponents, variantOptions, designSystems) - `color-prompt-guide.md` — 8 ready-to-use color palettes for Stitch prompts - `tailwind-reference.md` — Tailwind utility class reference for conversions - `prd-to-stitch-workflow.md` — PRD-driven design workflow diff --git a/skills/stitch-mcp-apply-design-system/SKILL.md b/skills/stitch-mcp-apply-design-system/SKILL.md index 9254555..6467d3c 100644 --- a/skills/stitch-mcp-apply-design-system/SKILL.md +++ b/skills/stitch-mcp-apply-design-system/SKILL.md @@ -32,8 +32,13 @@ You must have: "name": "apply_design_system", "arguments": { "projectId": "3780309359108792857", - "selectedScreenIds": ["88805abc123def456", "99906xyz789ghi012"], - "assetId": "ds_abc123" + "selectedScreenInstances": [ + { + "id": "a1b2c3d4e5f6", + "sourceScreen": "projects/3780309359108792857/screens/98b50e2ddc9943efb387052637738f61" + } + ], + "assetId": "15996705518239280238" } } ``` @@ -47,26 +52,34 @@ You must have: ❌ "projects/3780309359108792857" ``` -### `selectedScreenIds` — array of numeric screen IDs +### `selectedScreenInstances` — array of objects, not screen IDs + +This is the one that catches people. It takes screen **instances**, each a `{id, sourceScreen}` pair — not a list of screen ids. ``` -✅ ["88805abc123def456"] -❌ ["projects/123/screens/88805abc123def456"] +✅ [{ "id": "a1b2c3d4e5f6", + "sourceScreen": "projects/3780.../screens/98b5..." }] + +❌ ["88805abc123def456"] ← bare screen ids +❌ [{ "id": "98b50e2ddc99...", ... }] ← source screen id in the id slot ``` -All selected screens will have the design system applied. +Get both values from `get_project` → `screenInstances`. The `id` is the **instance** id; `sourceScreen` is the full `projects/{p}/screens/{s}` path of the screen behind it. They are different values, and swapping them fails. -### `assetId` — the design system identifier +Same shape as `create_design_system_from_design_md`, which takes a single instance rather than an array. -The `name` field from a design system asset, or just the ID portion: +### `assetId` — bare numeric, no prefix ``` -✅ "ds_abc123" +✅ "15996705518239280238" +❌ "assets/15996705518239280238" ``` -Get this from: -- `stitch-mcp-list-design-systems` → extract from the `name` field of each asset -- `stitch-mcp-create-design-system` → returned in the response `name` field +Get it from: +- `stitch-mcp-list-design-systems` → take the `name` field (`assets/15996...`) and **strip the `assets/` prefix** +- `stitch-mcp-create-design-system` → same, strip the prefix from the returned `name` + +> `apply_design_system` wants it bare, but `generate_screen_from_text`'s `designSystem` param wants it **prefixed** (`assets/15996...`). Same identifier, two formats, depending on the tool. ## Output diff --git a/skills/stitch-mcp-create-design-system-from-design-md/SKILL.md b/skills/stitch-mcp-create-design-system-from-design-md/SKILL.md index aa36254..8ed712d 100644 --- a/skills/stitch-mcp-create-design-system-from-design-md/SKILL.md +++ b/skills/stitch-mcp-create-design-system-from-design-md/SKILL.md @@ -61,7 +61,7 @@ Take the newest entry in `screenInstances` and read off both `id` and `sourceScr ## Step 3: Confirm and capture the asset id -On success you get back a design system with an asset id in `assets/NUMERIC_ID` form. Store the numeric part — that's what applying and generating need. +On success you get back a design system with an asset id in `assets/NUMERIC_ID` form. Store both forms: `apply_design_system` wants the bare numeric part, `generate_screen_from_text`'s `designSystem` param wants the full `assets/NUMERIC_ID` string. Announce it: > "Design system created from your DESIGN.md (asset `15996705518239280238`). Want me to apply it to existing screens, or use it for the next generation?" diff --git a/skills/stitch-mcp-create-design-system/SKILL.md b/skills/stitch-mcp-create-design-system/SKILL.md index 53714af..7ecb9ad 100644 --- a/skills/stitch-mcp-create-design-system/SKILL.md +++ b/skills/stitch-mcp-create-design-system/SKILL.md @@ -30,18 +30,13 @@ Creates a new Stitch Design System — a reusable theme configuration that can b "displayName": "SaaS Dashboard Theme", "theme": { "colorMode": "LIGHT", - "font": "DM_SANS", "headlineFont": "DM_SANS", "bodyFont": "DM_SANS", "labelFont": "DM_SANS", "roundness": "ROUND_EIGHT", "customColor": "#6366F1", - "backgroundLight": "#FFFFFF", - "backgroundDark": "#18181B", - "description": "Professional SaaS aesthetic — clean, indigo accent, airy spacing" - }, - "designTokens": "--color-primary: #6366F1;\n--color-bg: #FFFFFF;\n--font-family: 'DM Sans';", - "styleGuidelines": "Use indigo for interactive elements. Gray-50 backgrounds for cards. 8px border radius." + "colorVariant": "TONAL_SPOT" + } }, "projectId": "3780309359108792857" } @@ -56,27 +51,28 @@ Creates a new Stitch Design System — a reusable theme configuration that can b |-------|------|----------|-------------| | `displayName` | string | Yes | Human-readable name for the design system | | `theme` | DesignTheme | Yes | Visual configuration — see below | -| `designTokens` | string | No | CSS custom properties or token definitions | -| `styleGuidelines` | string | No | Natural-language design rules | + +`designTokens` and `styleGuidelines` are **not** accepted — the live API has no such fields on `DesignSystemInput`. Don't send them. ### `theme` (DesignTheme) — the visual configuration +Required: `colorMode`, `headlineFont`, `bodyFont`, `roundness`, `customColor`. + | Field | Type | Values | Description | |-------|------|--------|-------------| | `colorMode` | enum | `LIGHT`, `DARK` | Base appearance mode | -| `font` | enum | See font list below | **Deprecated** — sets all three font roles. Use the specific fields below instead | | `headlineFont` | enum | See font list below | Typeface for headings and titles | | `bodyFont` | enum | See font list below | Typeface for body text and paragraphs | -| `labelFont` | enum | See font list below | Typeface for labels, captions, and UI chrome | +| `labelFont` | enum | See font list below | Optional. Typeface for labels, captions, and UI chrome | | `roundness` | enum | `ROUND_FOUR`, `ROUND_EIGHT`, `ROUND_TWELVE`, `ROUND_FULL` (`ROUND_TWO` also exists but is deprecated/unused) | Border radius scale | | `customColor` | string | Hex color | Primary brand color | -| `backgroundLight` | string | Hex color | Light mode background | -| `backgroundDark` | string | Hex color | Dark mode background | -| `preset` | string | — | Optional preset theme name | -| `description` | string | — | Brief aesthetic description | -| `overridePrimaryColor` / `overrideSecondaryColor` / `overrideTertiaryColor` / `overrideNeutralColor` | string | Hex color | Exact color overrides, take precedence over `customColor` | -| `spacing` | object | Map of name → CSS value | e.g. `{"sm": "8px"}` | -| `typography` | object | Map of level name → Typography token | Each token: `fontFamily`, `fontSize`, `fontWeight`, `letterSpacing`, `lineHeight` | +| `colorVariant` | enum | `MONOCHROME`, `NEUTRAL`, `TONAL_SPOT`, `VIBRANT`, `EXPRESSIVE`, `FIDELITY`, `CONTENT`, `RAINBOW`, `FRUIT_SALAD` | Optional. Palette generation strategy from `customColor` | +| `designMd` | string | — | Optional. Design system markdown document | +| `overridePrimaryColor` / `overrideSecondaryColor` / `overrideTertiaryColor` / `overrideNeutralColor` | string | Hex color | Optional. Exact color overrides, take precedence over `customColor` | +| `spacing` | object | Map of name → CSS value | Optional. e.g. `{"sm": "8px"}` | +| `typography` | object | Map of level name → Typography token | Optional. Each token: `fontFamily`, `fontSize`, `fontWeight`, `letterSpacing`, `lineHeight` | + +`font` (the deprecated singular font field), `backgroundLight`, `backgroundDark`, `preset`, and `description` are **not** accepted as input — they only ever appear in API *responses* (`get_project`, `list_projects`, etc.), never in what you send here. ### Available fonts (68 options) @@ -106,18 +102,19 @@ When creating from extracted `design-tokens.css`: | CSS Variable | → DesignTheme field | |---|---| | `--color-primary` | `customColor` | -| `--color-bg` or `--bg-light` | `backgroundLight` | -| `--bg-dark` | `backgroundDark` | -| `--font-family` | `font` (map to closest enum value) | +| `--font-family` (headings) | `headlineFont` (map to closest enum value) | +| `--font-family` (body) | `bodyFont` (map to closest enum value) | | `--radius` or `--border-radius` | `roundness` (4px→FOUR, 8px→EIGHT, 12px→TWELVE, 16px+→FULL) | +There's no input field for exact background hex values — `backgroundLight`/`backgroundDark` are response-only. Light/dark backgrounds come from `colorMode` plus the palette Stitch derives from `customColor` and `colorVariant`; use `overridePrimaryColor` etc. if you need to pin a specific palette slot instead. + ## Output Returns an Asset object with a `name` field — **store this** for future `update_design_system` and `apply_design_system` calls: ```json { - "name": "assets/ds_abc123", + "name": "assets/15996705518239280238", "displayName": "SaaS Dashboard Theme", "designSystem": { ... } } @@ -125,6 +122,9 @@ Returns an Asset object with a `name` field — **store this** for future `updat ## After creating -- Store the `name` value (e.g., `assets/ds_abc123`) — you'll need it for apply/update +- Store the `name` value (e.g., `assets/15996705518239280238`). It's used two different ways: + - `update_design_system`'s `designSystem.name` — pass it as-is, with the `assets/` prefix + - `apply_design_system`'s `assetId` — strip the prefix, pass the bare numeric id + - `generate_screen_from_text`'s `designSystem` param — pass it as-is, with the prefix - Offer: "Apply this design system to existing screens?" → `stitch-mcp-apply-design-system` - The orchestrator stores this for automatic application in Step 5b diff --git a/skills/stitch-mcp-create-project/SKILL.md b/skills/stitch-mcp-create-project/SKILL.md index 68bbb47..6c546e9 100644 --- a/skills/stitch-mcp-create-project/SKILL.md +++ b/skills/stitch-mcp-create-project/SKILL.md @@ -63,9 +63,9 @@ The tool returns a `name` field in the format `projects/NUMERIC_ID`. You must ex "colorVariant": "TONAL_SPOT", "roundness": "ROUND_TWELVE", "spacingScale": 1, - "headlineFont": "ROBOTO", - "bodyFont": "ROBOTO", - "labelFont": "ROBOTO", + "headlineFont": "INTER", + "bodyFont": "INTER", + "labelFont": "INTER", "namedColors": {}, "designMd": "" } diff --git a/skills/stitch-mcp-generate-screen-from-text/SKILL.md b/skills/stitch-mcp-generate-screen-from-text/SKILL.md index d1df6e3..818e310 100644 --- a/skills/stitch-mcp-generate-screen-from-text/SKILL.md +++ b/skills/stitch-mcp-generate-screen-from-text/SKILL.md @@ -32,13 +32,23 @@ You must have a `projectId` before calling this. If you don't have one: "projectId": "3780309359108792857", "prompt": "[Full structured prompt — see below]", "deviceType": "MOBILE", - "modelId": "GEMINI_3_1_PRO" + "modelId": "GEMINI_3_1_PRO", + "designSystem": "assets/15996705518239280238" } } ``` ## Parameter reference +### `designSystem` — optional, PREFIXED asset id + +``` +✅ "assets/15996705518239280238" +❌ "15996705518239280238" +``` + +This is how you get design consistency across generated screens — pass the `name` of a design system from `stitch-mcp-create-design-system`, `stitch-mcp-create-design-system-from-design-md`, or `stitch-mcp-list-design-systems` (used as-is, with the `assets/` prefix). This is the opposite format from `apply_design_system`'s `assetId`, which wants the prefix stripped. + ### `projectId` — numeric ID only, no `projects/` prefix ``` ✅ "3780309359108792857" diff --git a/skills/stitch-mcp-get-screen/SKILL.md b/skills/stitch-mcp-get-screen/SKILL.md index 52444ff..94850ec 100644 --- a/skills/stitch-mcp-get-screen/SKILL.md +++ b/skills/stitch-mcp-get-screen/SKILL.md @@ -36,26 +36,34 @@ The user may provide the screen reference in different formats: ## Step 2: Call the MCP tool -**Important: Both IDs must be numeric — no `projects/` or `screens/` prefix.** +`get_screen` is mid-migration: `name` is the current identifier and takes the **full resource path**, while `projectId` and `screenId` are marked deprecated but are still required. Send all three. ```json { "name": "get_screen", "arguments": { + "name": "projects/3780309359108792857/screens/88805abc123def456", "projectId": "3780309359108792857", "screenId": "88805abc123def456" } } ``` +The prefix rule differs per field, which is the whole reason this wrapper exists: + ``` +✅ name: "projects/3780309359108792857/screens/88805abc123def456" +❌ name: "88805abc123def456" + ✅ projectId: "3780309359108792857" ❌ projectId: "projects/3780309359108792857" -✅ screenId: "88805abc123def456" -❌ screenId: "screens/88805abc123def456" +✅ screenId: "88805abc123def456" +❌ screenId: "screens/88805abc123def456" ``` +> `name` is the full path; the other two are bare. Omitting `name` fails — it's required despite the deprecated pair still being mandatory too. + ## Output schema ```json diff --git a/skills/stitch-mcp-list-design-systems/SKILL.md b/skills/stitch-mcp-list-design-systems/SKILL.md index 2c84d0b..974717c 100644 --- a/skills/stitch-mcp-list-design-systems/SKILL.md +++ b/skills/stitch-mcp-list-design-systems/SKILL.md @@ -48,7 +48,7 @@ Returns an array of Asset objects: { "assets": [ { - "name": "assets/ds_abc123", + "name": "assets/15996705518239280238", "displayName": "SaaS Dashboard Theme", "designSystem": { "theme": { @@ -58,9 +58,7 @@ Returns an array of Asset objects: "customColor": "#6366F1", "backgroundLight": "#FFFFFF", "backgroundDark": "#18181B" - }, - "designTokens": "...", - "styleGuidelines": "..." + } } } ] @@ -73,11 +71,13 @@ Present as a readable table: | # | Name | Font | Color | Mode | Asset ID | |---|------|------|-------|------|----------| -| 1 | SaaS Dashboard Theme | DM Sans | #6366F1 | Light | `ds_abc123` | +| 1 | SaaS Dashboard Theme | DM Sans | #6366F1 | Light | `15996705518239280238` | Then offer: - "Apply one of these to a screen?" → `stitch-mcp-apply-design-system` - "Update an existing design system?" → `stitch-mcp-update-design-system` - "Create a new design system?" → `stitch-mcp-create-design-system` -Extract the `name` field from each asset — this is the `assetId` needed for `apply_design_system`. +Extract the `name` field from each asset (`assets/15996...`). It's used two different ways depending on the next call: +- `apply_design_system`'s `assetId` — strip the `assets/` prefix, pass the bare numeric id +- `update_design_system`'s `designSystem.name` — pass `name` as returned, with the prefix diff --git a/skills/stitch-mcp-update-design-system/SKILL.md b/skills/stitch-mcp-update-design-system/SKILL.md index 8ecbdab..42a13cc 100644 --- a/skills/stitch-mcp-update-design-system/SKILL.md +++ b/skills/stitch-mcp-update-design-system/SKILL.md @@ -29,22 +29,18 @@ You must have the design system's asset `name` before calling this. If you don't { "name": "update_design_system", "arguments": { + "name": "assets/15996705518239280238", + "projectId": "3780309359108792857", "designSystem": { - "name": "assets/ds_abc123", "displayName": "SaaS Dashboard Theme v2", "theme": { "colorMode": "DARK", - "font": "GEIST", "headlineFont": "GEIST", "bodyFont": "GEIST", "labelFont": "GEIST", "roundness": "ROUND_TWELVE", - "customColor": "#818CF8", - "backgroundLight": "#F9FAFB", - "backgroundDark": "#09090B" - }, - "designTokens": "--color-primary: #818CF8;\n--color-bg: #09090B;", - "styleGuidelines": "Dark mode first. Geist font. Subtle indigo accent." + "customColor": "#818CF8" + } } } } @@ -52,17 +48,24 @@ You must have the design system's asset `name` before calling this. If you don't ## Parameter reference -### `designSystem` — required, Asset wrapper +Three **sibling** top-level arguments — `name` is not nested inside `designSystem`: -The object must include the `name` field (asset identifier) plus any fields you want to update: +| Argument | Type | Required | Description | +|----------|------|----------|-------------| +| `name` | string | **Yes** | Asset identifier **with** the `assets/` prefix, e.g. `assets/15996705518239280238`. Top-level, not inside `designSystem`. | +| `projectId` | string | **Yes** | Bare numeric project id, no `projects/` prefix | +| `designSystem` | object | **Yes** | `{displayName, theme}` — see below | + +### `designSystem` — `{displayName, theme}` only | Field | Type | Required | Description | |-------|------|----------|-------------| -| `name` | string | **Yes** | Asset name from create or list (e.g., `assets/ds_abc123`) | -| `displayName` | string | No | Updated human-readable name | -| `theme` | DesignTheme | No | Updated visual configuration (see `stitch-mcp-create-design-system` for full reference) | -| `designTokens` | string | No | Updated CSS custom properties | -| `styleGuidelines` | string | No | Updated design rules | +| `displayName` | string | **Yes** | Human-readable name | +| `theme` | DesignTheme | **Yes** | Visual configuration (see `stitch-mcp-create-design-system` for the full field reference) | + +> `update_design_system` takes the asset id **prefixed** (`assets/159967...`), while `apply_design_system` takes the same id **bare**. Two tools, same identifier, different formats. + +`designTokens` and `styleGuidelines` are **not** accepted — the live API has no such fields on `DesignSystem`. Don't send them. **Note:** This is a full replacement, not a merge. Include all theme fields you want to keep, not just the ones you're changing. @@ -72,7 +75,7 @@ Returns the updated Asset object: ```json { - "name": "assets/ds_abc123", + "name": "assets/15996705518239280238", "displayName": "SaaS Dashboard Theme v2", "designSystem": { ... } } From cc0bf775b1f92e53fc261cfa01865e59ecaf7e61 Mon Sep 17 00:00:00 2001 From: Gabi Date: Mon, 20 Jul 2026 21:37:24 +0200 Subject: [PATCH 2/3] fix: don't hang the installer when stdin can't answer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `npx @booplex/stitch-kit < /dev/null`, or any run without a TTY — CI, Docker, a piped install — printed the API-key prompt and then died with "Detected unsettled top-level await". readline's question callback never fires on EOF, so the promise never settled and node exited partway through. The user got a silently failed install, no error, no skills. prompt() now returns '' when stdin isn't a TTY, and listens for readline's `close` event so EOF resolves instead of hanging. Callers already treat empty as "skipped", so the install continues and prints the manual MCP config. Verified against a scratch HOME seeded with all seven client marker directories: exits 0, installs the agent and 36 skills to Codex/OpenCode, 36 skills to Crush, agent-only to Claude Code (skills ship via the plugin), and MCP-only config for Cursor and VS Code — which matches the "Works with" table in the README exactly. --- bin/stitch-kit.mjs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/bin/stitch-kit.mjs b/bin/stitch-kit.mjs index f7e678b..fb94e78 100644 --- a/bin/stitch-kit.mjs +++ b/bin/stitch-kit.mjs @@ -55,12 +55,27 @@ function logErr(msg) { console.error(` ✗ ${msg}`); } /** * Prompt the user for input via stdin. + * + * Resolves to an empty string whenever there's nobody to answer — no TTY, or + * stdin hits EOF. Callers treat empty as "skipped", which is what we want in + * CI, Docker, and `npx ... < /dev/null`: carry on with the rest of the install + * rather than hanging. + * * @param {string} question - The question to display - * @returns {Promise} The user's input (trimmed) + * @returns {Promise} The user's input (trimmed), or '' if unanswerable */ function prompt(question) { + // Non-interactive stdin: readline would wait forever for input that can't + // arrive. Skip straight to the default instead. + if (!process.stdin.isTTY) return Promise.resolve(''); + const rl = createInterface({ input: process.stdin, output: process.stdout }); return new Promise((resolve) => { + // `close` fires on EOF (ctrl-D, or a pipe closing). Without this the + // question callback never runs, the promise never settles, and node exits + // mid-install with "Detected unsettled top-level await" — an install that + // silently did nothing. + rl.on('close', () => resolve('')); rl.question(question, (answer) => { rl.close(); resolve(answer.trim()); From f11953637e383e280b913d2e45e68fee9c5539c7 Mon Sep 17 00:00:00 2001 From: Gabi Date: Mon, 20 Jul 2026 21:44:12 +0200 Subject: [PATCH 3/3] fix: finish the non-Stitch source paths the conversion skills advertise MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Accepting local HTML and URLs was bolted onto Step 1 without touching the rest of each skill, so the new routes were a door with no room behind it. Design tokens assumed a Stitch-emitted `tailwind.config` in ``. Ordinary HTML doesn't have one, so the two routes we just advertised had no way to resolve colors, fonts, radii or dark mode. All six skills now resolve tokens in order — inline tailwind.config, then CSS custom properties, then a linked or inline stylesheet, then inferring from the most frequent computed values and telling the user what was inferred. They also state that the URL route only fetches the single HTML response, so linked stylesheets may not come along, and to say so rather than invent a palette. React Native and SwiftUI promised three sources then demanded a Stitch design with `deviceType: MOBILE` in five places each — including telling users to "regenerate with deviceType: MOBILE", which is meaningless to someone who handed over a local file. The constraint was always a mobile *layout*, not a Stitch artefact. Stitch screens are still checked via deviceType; local files and URLs are checked by viewport meta, mobile-first media queries, narrow root widths and touch-sized targets. The mobile-only requirement is unchanged. Also: - README no longer claims every target ships TypeScript and ARIA. Dark mode and tokens are universal; TS/ARIA are web-target only, SwiftUI emits Swift with native accessibility APIs, and the HTML target has no build step. - `create_design_system_from_design_md.json` had `$defs` outside the `arguments` fragment the schema README calls the complete input schema, so its `$ref` didn't resolve when validated standalone. Moved inside. --- README.md | 4 +- .../create_design_system_from_design_md.json | 42 +++++++++++-------- skills/stitch-html-components/SKILL.md | 12 ++++-- skills/stitch-nextjs-components/SKILL.md | 17 +++++--- skills/stitch-react-components/SKILL.md | 21 ++++++---- .../stitch-react-native-components/SKILL.md | 32 +++++++++----- skills/stitch-svelte-components/SKILL.md | 15 +++++-- skills/stitch-swiftui-components/SKILL.md | 38 +++++++++++------ 8 files changed, 120 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index 1777b6d..777ba2c 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,9 @@ Without stitch-kit, your agent sends Stitch a half-baked prompt, gets confused b ## Ship to any framework -**Works on any HTML, not just Stitch output.** Each conversion skill takes a Stitch screen, a local HTML file, or a URL — point it at a template you bought, a page you already built, or something a different tool generated, and you get the same production components with dark mode, design tokens, TypeScript, and ARIA. Only the Stitch route needs an API key. +**Works on any HTML, not just Stitch output.** Each conversion skill takes a Stitch screen, a local HTML file, or a URL — point it at a template you bought, a page you already built, or something a different tool generated. Only the Stitch route needs an API key. + +Every target gets dark mode and design tokens. The rest depends on where you're shipping: TypeScript and ARIA on the web targets, Swift and native accessibility APIs on SwiftUI, plain semantic HTML with no build step on the HTML target. Pick your target: diff --git a/docs/mcp-schemas/create_design_system_from_design_md.json b/docs/mcp-schemas/create_design_system_from_design_md.json index 2b1bf12..ba3dcbb 100644 --- a/docs/mcp-schemas/create_design_system_from_design_md.json +++ b/docs/mcp-schemas/create_design_system_from_design_md.json @@ -24,25 +24,31 @@ ] } }, - "required": ["projectId", "selectedScreenInstance"], - "description": "Request message for CreateDesignSystemFromDesignMd." - }, - "$defs": { - "SelectedScreenInstance": { - "type": "object", - "description": "A screen instance to be edited by the agent, selected by the user.", - "properties": { - "id": { - "description": "Required. The id of the screen instance, NOT the source screen id. This is available in the screen instances in the Project info, fetched by `get_project`.", - "type": "string" + "$defs": { + "SelectedScreenInstance": { + "type": "object", + "description": "A screen instance to be edited by the agent, selected by the user.", + "properties": { + "id": { + "description": "Required. The id of the screen instance, NOT the source screen id. This is available in the screen instances in the Project info, fetched by `get_project`.", + "type": "string" + }, + "sourceScreen": { + "description": "Required. The source screen of the screen instance. The resource name of the source screen. Format: projects/{project}/screens/{screen}", + "type": "string" + } }, - "sourceScreen": { - "description": "Required. The source screen of the screen instance. The resource name of the source screen. Format: projects/{project}/screens/{screen}", - "type": "string" - } - }, - "required": ["id", "sourceScreen"] - } + "required": [ + "id", + "sourceScreen" + ] + } + }, + "required": [ + "projectId", + "selectedScreenInstance" + ], + "description": "Request message for CreateDesignSystemFromDesignMd." }, "outputSchema": { "type": "object", diff --git a/skills/stitch-html-components/SKILL.md b/skills/stitch-html-components/SKILL.md index 21ae358..af59018 100644 --- a/skills/stitch-html-components/SKILL.md +++ b/skills/stitch-html-components/SKILL.md @@ -10,7 +10,7 @@ allowed-tools: # Stitch → HTML5 + CSS (Platform-Agnostic) -You are a frontend engineer specializing in clean, dependency-free HTML and CSS. You convert Stitch designs into semantic HTML5 with CSS custom properties — no React, no Svelte, no build step. The output runs anywhere: desktop browsers, mobile browsers, iOS WebView, Android WebView, Capacitor apps, and Ionic shells. +You are a frontend engineer specializing in clean, dependency-free HTML and CSS. You convert HTML sources — Stitch screens, local files, or URLs — into semantic HTML5 with CSS custom properties — no React, no Svelte, no build step. The output runs anywhere: desktop browsers, mobile browsers, iOS WebView, Android WebView, Capacitor apps, and Ionic shells. ## When to use this skill @@ -80,13 +80,19 @@ For multi-screen projects, each screen gets its own HTML file. Shared CSS lives ## Step 3: CSS custom properties -Map Stitch colors to semantic tokens. Always generate **both light and dark** at the same time. +Map source colors to semantic tokens. Always generate **both light and dark** at the same time. Resolve the hex values in this order: + +1. **Inline `tailwind.config`** in `` (what Stitch emits) — use it directly if present. +2. **CSS custom properties** already in the source (`:root { --color-primary: ... }`) — common in hand-written and templated HTML. +3. **A linked or inline stylesheet** — parse declared colors, font-families, radii, spacing. +4. **Last resort** — derive tokens from the most frequent computed values in the markup (dominant background, text color, accent, heading/body font, border radius), and tell the user what you inferred so they can correct it. + +The URL route only downloads the single HTML response — externally-linked stylesheets may not come along for the ride. If none of the above resolves a token, say so instead of inventing a palette. ```css /* css/tokens.css */ :root { - /* Extract these from the Stitch HTML's tailwind.config in */ --color-background: [hex]; --color-surface: [hex]; --color-primary: [hex]; diff --git a/skills/stitch-nextjs-components/SKILL.md b/skills/stitch-nextjs-components/SKILL.md index 7906c47..2739f4e 100644 --- a/skills/stitch-nextjs-components/SKILL.md +++ b/skills/stitch-nextjs-components/SKILL.md @@ -10,7 +10,7 @@ allowed-tools: # Stitch → Next.js 15 App Router Components -You are a senior Next.js engineer. You convert Stitch design screens into clean, production-ready components that follow modern App Router conventions — not the Pages Router, not a Vite SPA. Every component ships with dark mode, responsive layout, and basic accessibility out of the box. +You are a senior Next.js engineer. You convert HTML sources — Stitch screens, local files, or URLs — into clean, production-ready components that follow modern App Router conventions — not the Pages Router, not a Vite SPA. Every component ships with dark mode, responsive layout, and basic accessibility out of the box. ## When to use this skill @@ -105,14 +105,21 @@ src/ ## Step 4: Dark mode with CSS variables -This project uses a CSS variable approach that works with `next-themes`. Extract colors from the Stitch design and map them to semantic tokens. +This project uses a CSS variable approach that works with `next-themes`. Resolve colors from the source in this order, then map them to semantic tokens: + +1. **Inline `tailwind.config`** in `` (what Stitch emits) — use it directly if present. +2. **CSS custom properties** already in the source (`:root { --color-primary: ... }`) — common in hand-written and templated HTML. +3. **A linked or inline stylesheet** — parse declared colors, font-families, radii, spacing. +4. **Last resort** — derive tokens from the most frequent computed values in the markup (dominant background, text color, accent, heading/body font, border radius), and tell the user what you inferred so they can correct it. + +The URL route only downloads the single HTML response — externally-linked stylesheets may not come along for the ride. If none of the above resolves a token, say so instead of inventing a palette. In `app/globals.css`: ```css :root { --color-background: #ffffff; --color-surface: #f4f4f5; - --color-primary: /* dominant action color from Stitch design */; + --color-primary: /* dominant action color from the source */; --color-primary-foreground: #ffffff; --color-text: #09090b; --color-text-muted: #71717a; @@ -151,7 +158,7 @@ export default function RootLayout({ children }: { children: React.ReactNode }) All components must work at `sm` (640px), `md` (768px), `lg` (1024px), and `xl` (1280px) breakpoints. -Apply these patterns from the Stitch design: +Apply these patterns from the source design: - **Navigation**: `hidden md:flex` for desktop nav, `flex md:hidden` for mobile hamburger - **Grid**: `grid-cols-1 sm:grid-cols-2 lg:grid-cols-3` — start single column - **Typography**: `text-2xl md:text-4xl` — scale up on larger screens @@ -183,7 +190,7 @@ If the design has complex interactivity (modals, dropdowns, tabs), use the `stit ## Step 8: Animation (optional) -If the Stitch design contains clear motion intent (hover states, transitions, reveals), use the `stitch-animate` skill after components are built. Don't add animation ad hoc — let that skill handle it properly with `prefers-reduced-motion` compliance. +If the source design contains clear motion intent (hover states, transitions, reveals), use the `stitch-animate` skill after components are built. Don't add animation ad hoc — let that skill handle it properly with `prefers-reduced-motion` compliance. ## Troubleshooting diff --git a/skills/stitch-react-components/SKILL.md b/skills/stitch-react-components/SKILL.md index c9bc6ac..cd037f1 100644 --- a/skills/stitch-react-components/SKILL.md +++ b/skills/stitch-react-components/SKILL.md @@ -86,10 +86,17 @@ src/ ## Step 3: Extract design tokens -From the Stitch HTML ``, find the `tailwind.config` or CSS variable definitions. +Resolve tokens from whatever the HTML actually gives you, in this order: + +1. **Inline `tailwind.config`** in `` (what Stitch emits) — use it directly if present. +2. **CSS custom properties** (`:root { --color-primary: ... }`) — common in hand-written and templated HTML. +3. **A linked or inline stylesheet** — parse declared colors, font-families, radii, spacing. +4. **Last resort** — derive tokens from the most frequent computed values in the markup (dominant background, text color, accent, heading/body font, border radius), and tell the user what you inferred so they can correct it. + +The URL route only downloads the single HTML response — externally-linked stylesheets may not come along for the ride. If none of the above resolves a token, say so instead of inventing a palette. ```ts -// src/theme/tokens.ts — extract hex values from Stitch HTML +// src/theme/tokens.ts export const lightTokens = { background: '#FFFFFF', surface: '#F4F4F5', @@ -154,10 +161,10 @@ export function useTheme(): ThemeTokens { ### Tailwind class mapping -Use the Stitch HTML classes directly in JSX where they don't reference Stitch-specific tokens. Map Stitch tokens to CSS variables: +Use the source HTML's Tailwind classes directly in JSX where they don't reference custom tokens. Map custom tokens to CSS variables: ```tsx -// Stitch HTML: bg-primary → CSS variable → Tailwind arbitrary value +// Source HTML: bg-primary → CSS variable → Tailwind arbitrary value // OR: use inline style with token value // Option A — Tailwind arbitrary value (if custom tokens in tailwind.config) @@ -239,14 +246,14 @@ export function StitchComponent({ ## Step 6: Integration with shadcn/ui -After converting the Stitch design to base React components, you can layer in shadcn/ui: +After converting the design to base React components, you can layer in shadcn/ui: ```bash npx shadcn@latest init # Set up shadcn in your Vite project npx shadcn@latest add button card input dialog ``` -Then use `stitch-shadcn-ui` skill to replace raw HTML elements with shadcn components while preserving the Stitch design tokens. +Then use `stitch-shadcn-ui` skill to replace raw HTML elements with shadcn components while preserving the design tokens. ## Troubleshooting @@ -261,7 +268,7 @@ Then use `stitch-shadcn-ui` skill to replace raw HTML elements with shadcn compo - `resources/component-template.tsx` — Boilerplate component - `resources/architecture-checklist.md` — Pre-ship checklist -- `references/tailwind-to-react.md` — Token + class mapping guide (Stitch HTML → React/Tailwind) +- `references/tailwind-to-react.md` — Token + class mapping guide (source HTML → React/Tailwind) - `scripts/fetch-stitch.sh` — Reliable GCS HTML downloader - `stitch-shadcn-ui` — Add shadcn/ui components after base conversion - `docs/tailwind-reference.md` — Tailwind utility class lookup diff --git a/skills/stitch-react-native-components/SKILL.md b/skills/stitch-react-native-components/SKILL.md index adb6a16..7b7fe4d 100644 --- a/skills/stitch-react-native-components/SKILL.md +++ b/skills/stitch-react-native-components/SKILL.md @@ -10,14 +10,14 @@ allowed-tools: # Stitch → React Native / Expo Components -You are a React Native engineer. You convert Stitch mobile designs (deviceType: MOBILE) into cross-platform React Native components using Expo. You work in TypeScript, use `StyleSheet.create` for styles, and follow Expo Router conventions for navigation. +You are a React Native engineer. You convert mobile UI layouts — a Stitch screen generated with `deviceType: MOBILE`, a local HTML file, or a URL — into cross-platform React Native components using Expo. You work in TypeScript, use `StyleSheet.create` for styles, and follow Expo Router conventions for navigation. ## When to use this skill Use this skill when: -- The user wants a **native mobile app** (iOS + Android) from a Stitch design +- The user wants a **native mobile app** (iOS + Android) from an existing design - The user mentions "React Native", "Expo", "mobile app", "iOS", "Android" -- The Stitch design was generated with `deviceType: MOBILE` +- The source is a **mobile layout** — narrow, vertical, touch-sized targets (a Stitch screen with `deviceType: MOBILE`, or a local file/URL that reads as mobile) **Note:** For a mobile WebView app (Capacitor, Ionic, PWA), use `stitch-html-components` instead. React Native outputs actual native UI — not web views. @@ -39,9 +39,12 @@ Also: Everything downstream reads one file: `temp/source.html`. Get the HTML there by whichever route matches what the user gave you, then continue at Step 2 — the rest of this skill is identical regardless of where the markup came from. -**From a Stitch screen:** +This skill only works on a **mobile layout** — narrow, vertical, touch-sized targets. Desktop layouts don't translate to RN regardless of source. How you confirm mobile-ness depends on where the HTML came from: + +- **Stitch screen** — check it was generated with `deviceType: MOBILE`. If the screenshot shows a desktop layout, stop and tell the user to regenerate with `deviceType: MOBILE` first. +- **Local HTML file or URL** — inspect the markup: a `` tag, mobile-first media queries, a narrow `max-width` on the root container, touch-sized tap targets. If it's clearly a desktop layout (wide multi-column grid, hover-only interactions, no viewport meta), stop and tell the user the source isn't a mobile layout — don't tell them to "regenerate with deviceType: MOBILE," that instruction is meaningless outside Stitch. -Only call this skill for **MOBILE** Stitch designs. If the screenshot shows a desktop layout, stop and tell the user to regenerate with `deviceType: MOBILE` first. +**From a Stitch screen:** 1. **Namespace discovery** — `list_tools` to find the Stitch MCP prefix 2. **Fetch metadata** — `[prefix]:get_screen` for the design JSON @@ -49,7 +52,7 @@ Only call this skill for **MOBILE** Stitch designs. If the screenshot shows a de ```bash bash scripts/fetch-stitch.sh "[htmlCode.downloadUrl]" "temp/source.html" ``` -4. **Visual audit** — check `screenshot.downloadUrl` before converting. Append `=s0` to that URL for full resolution; the bare URL serves a 512px thumbnail regardless of the `width`/`height` the API reports. Confirm it's a mobile layout (narrow, vertical). +4. **Visual audit** — check `screenshot.downloadUrl` before converting. Append `=s0` to that URL for full resolution; the bare URL serves a 512px thumbnail regardless of the `width`/`height` the API reports. Confirm it's a mobile layout, per the check above. **From a local HTML file:** @@ -57,7 +60,7 @@ Only call this skill for **MOBILE** Stitch designs. If the screenshot shows a de mkdir -p temp && cp "path/to/design.html" temp/source.html ``` -Open it and confirm it's a mobile layout before converting. +Open it and confirm it's a mobile layout, per the check above. **From a URL:** @@ -65,7 +68,7 @@ Open it and confirm it's a mobile layout before converting. bash scripts/fetch-stitch.sh "https://example.com/page" "temp/source.html" ``` -Despite the name, that script is a generic hardened downloader — follows redirects, retries transient failures, handles gzip, and fails loudly on an empty result. It does not care whether the URL points at Stitch. Confirm the page is a mobile layout before converting. +Despite the name, that script is a generic hardened downloader — follows redirects, retries transient failures, handles gzip, and fails loudly on an empty result. It does not care whether the URL points at Stitch. Confirm the page is a mobile layout, per the check above. **From a screenshot:** there's no upload route — the Stitch MCP API has no image-upload tool. Either recreate the design from a text prompt via `stitch-mcp-generate-screen-from-text`, or hand-write the HTML and use the local-file route above. @@ -146,8 +149,17 @@ const spacing = { ### Color mapping +Pull the hex values below from whatever token source the HTML actually has, in this order: + +1. **Inline `tailwind.config`** in `` (what Stitch emits) — use it directly if present. +2. **CSS custom properties** (`:root { --color-primary: ... }`) — common in hand-written and templated HTML. +3. **A linked or inline stylesheet** — parse declared colors, font-families, radii, spacing. +4. **Last resort** — derive tokens from the most frequent computed values in the markup (dominant background, text color, accent, heading/body font, border radius), and tell the user what you inferred so they can correct it. + +The URL route only downloads the single HTML response — externally-linked stylesheets may not come along for the ride. If none of the above resolves a token, say so instead of inventing a palette. + ```ts -// src/theme/tokens.ts — extract from Stitch Tailwind config +// src/theme/tokens.ts export const lightTokens = { background: '#FFFFFF', // from --color-background surface: '#F4F4F5', @@ -343,7 +355,7 @@ const styles = StyleSheet.create({ ## Execution steps -1. **Verify** it's a MOBILE Stitch design +1. **Verify** the source is a mobile layout (see Step 1) 2. **Data layer** — create `src/data/mockData.ts` from the static content in the design 3. **Tokens** — create `src/theme/tokens.ts` from extracted colors, and `useTheme.ts` 4. **Components** — convert each visual section to a component using the mapping rules above diff --git a/skills/stitch-svelte-components/SKILL.md b/skills/stitch-svelte-components/SKILL.md index 0a2ceb6..ae3391d 100644 --- a/skills/stitch-svelte-components/SKILL.md +++ b/skills/stitch-svelte-components/SKILL.md @@ -10,7 +10,7 @@ allowed-tools: # Stitch → Svelte 5 / SvelteKit Components -You are a Svelte 5 engineer. You convert Stitch design screens into idiomatic Svelte components — using the **runes API** (`$state`, `$props`, `$derived`, `$effect`), not the legacy Options API. Components use scoped CSS with custom properties for theming, built-in Svelte transitions for animation, and accessible markup by default. +You are a Svelte 5 engineer. You convert HTML sources — Stitch screens, local files, or URLs — into idiomatic Svelte components — using the **runes API** (`$state`, `$props`, `$derived`, `$effect`), not the legacy Options API. Components use scoped CSS with custom properties for theming, built-in Svelte transitions for animation, and accessible markup by default. > **Note:** This is the only Stitch skill that targets Svelte. The official `react-components` skill targets Vite/React. Use this skill when the project uses SvelteKit. @@ -136,14 +136,21 @@ static/ ← Static assets ## Step 4: Scoped CSS with design tokens -Svelte scopes CSS to the component by default — use this aggressively. Map Stitch colors to custom properties in the `:root` (via `+layout.svelte` or `app.css`) and reference them in each component. +Svelte scopes CSS to the component by default — use this aggressively. Resolve colors from the source in this order, then map them to custom properties in the `:root` (via `+layout.svelte` or `app.css`) and reference them in each component: + +1. **Inline `tailwind.config`** in `` (what Stitch emits) — use it directly if present. +2. **CSS custom properties** already in the source (`:root { --color-primary: ... }`) — common in hand-written and templated HTML. +3. **A linked or inline stylesheet** — parse declared colors, font-families, radii, spacing. +4. **Last resort** — derive tokens from the most frequent computed values in the markup (dominant background, text color, accent, heading/body font, border radius), and tell the user what you inferred so they can correct it. + +The URL route only downloads the single HTML response — externally-linked stylesheets may not come along for the ride. If none of the above resolves a token, say so instead of inventing a palette. **In `src/app.css` (global):** ```css :root { --color-background: #ffffff; --color-surface: #f4f4f5; - --color-primary: /* dominant color from Stitch design */; + --color-primary: /* dominant color from the source */; --color-primary-foreground: #ffffff; --color-text: #09090b; --color-text-muted: #71717a; @@ -197,7 +204,7 @@ Svelte scopes CSS to the component by default — use this aggressively. Map Sti ## Step 5: Built-in transitions and animations -Svelte has first-class transition support. Apply these from the Stitch design intent: +Svelte has first-class transition support. Apply these from the source design's motion intent: ```svelte