diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 06bc3b3..6c5f505 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -295,6 +295,13 @@ This is not an officially supported Google product. This project is not eligible for the [Google Open Source Software Vulnerability Rewards Program](https://bughunters.google.com/open-source-security). +## Examples + +- [Basic Design Generation](./examples/basic-design) +- [Design System Extraction](./examples/design-system-extraction) +- [Stitch MCP Server](./examples/mcp-server) +- [CI Visual Testing](./examples/ci-visual-testing/README.md) - Integrating Stitch SDK for visual regression testing. + ## License Apache 2.0 — see [LICENSE](LICENSE) for details. \ No newline at end of file diff --git a/packages/sdk/examples/ci-visual-testing/README.md b/packages/sdk/examples/ci-visual-testing/README.md new file mode 100644 index 0000000..af1ccc1 --- /dev/null +++ b/packages/sdk/examples/ci-visual-testing/README.md @@ -0,0 +1,12 @@ +# CI Visual Testing with Stitch + +This directory contains an example of how to integrate the Stitch SDK into a CI pipeline for visual testing and regression analysis. The process is broken into two parts: + +1. **Deterministic Runner** (`scripts/ci-runner.ts`): Re-runs the Stitch generation with the baseline prompt, captures the new screenshot URL, and outputs a JSON diff report. +2. **Agent Skill** (`SKILL.md`): Teaches an agent how to evaluate the visual diff report, download the before/after screenshots, and make a pass/fail judgment. + +## Running the Example + +```bash +bun run scripts/ci-runner.ts +``` diff --git a/packages/sdk/examples/ci-visual-testing/SKILL.md b/packages/sdk/examples/ci-visual-testing/SKILL.md new file mode 100644 index 0000000..ec02b34 --- /dev/null +++ b/packages/sdk/examples/ci-visual-testing/SKILL.md @@ -0,0 +1,13 @@ +# Stitch CI Visual Testing Skill + +**Description:** Teaches an agent how to evaluate visual diffs from Stitch screenshot URLs during CI. + +## Context +When the deterministic CI runner (`scripts/ci-runner.ts`) finishes, it outputs a JSON report containing the baseline screenshot URL and the new candidate screenshot URL. + +## Agent Instructions +1. **Read the CI Report**: Parse the JSON output from `scripts/ci-runner.ts`. +2. **Fetch Screenshots**: Download the images from the provided CDN URLs. +3. **Analyze Visual Differences**: Compare the layout, typography, and color schemes. +4. **Evaluate Constraints**: Check if the candidate design still meets the original prompt constraints. +5. **Output Verdict**: Produce a Pass/Fail verdict with specific reasoning based on the visual comparison. diff --git a/packages/sdk/examples/ci-visual-testing/scripts/ci-runner.ts b/packages/sdk/examples/ci-visual-testing/scripts/ci-runner.ts new file mode 100644 index 0000000..68d4342 --- /dev/null +++ b/packages/sdk/examples/ci-visual-testing/scripts/ci-runner.ts @@ -0,0 +1,33 @@ +import { stitch } from "@google/stitch-sdk"; + +// Simulate reading a baseline definition from source control +const baseline = { + projectId: "9651283129364717298", // Sample project + prompt: "A login screen with email and password fields, minimalist design", + baselineImageUrl: "https://lh3.googleusercontent.com/a/sample-baseline", +}; + +if (!process.env.STITCH_API_KEY) { + console.error("STITCH_API_KEY is required"); + process.exit(1); +} + +console.log("Starting CI Visual Test Runner..."); +const project = stitch.project(baseline.projectId); + +console.log("Generating candidate design..."); +const candidateScreen = await project.generate(baseline.prompt); + +console.log("Fetching candidate screenshot URL..."); +const candidateImageUrl = await candidateScreen.getImage(); + +const report = { + baseline: baseline.baselineImageUrl, + candidate: candidateImageUrl, + candidateScreenId: candidateScreen.id, + prompt: baseline.prompt, +}; + +console.log("\n--- CI REPORT ---"); +console.log(JSON.stringify(report, null, 2)); +console.log("-----------------"); diff --git a/packages/sdk/examples/mcp-server/README.md b/packages/sdk/examples/mcp-server/README.md new file mode 100644 index 0000000..b8769a8 --- /dev/null +++ b/packages/sdk/examples/mcp-server/README.md @@ -0,0 +1,35 @@ +# Stitch Design MCP Server Example + +This example demonstrates how to build a Model Context Protocol (MCP) server that exposes the Stitch SDK to agent frameworks. It wraps the core Stitch functionality into high-level, compound tools that are optimized for AI agents. + +## Why wrap Stitch in another MCP Server? + +Stitch itself is an MCP server, but its native tools are low-level (e.g., `create_project`, `generate_screen_from_text`). When building an AI agent that generates and implements UI designs, wrapping the Stitch SDK in a custom MCP server allows you to: + +1. **Create Compound Actions**: Combine generation, asset extraction, and theme parsing into a single tool call (e.g., `generate_and_extract`), saving the agent multiple round-trips. +2. **Add Domain-Specific Logic**: Translate Stitch's generic HTML output into your framework's specific structure (e.g., scaffolding a Next.js or Astro project automatically). +3. **Control Tool Exposure**: Expose only the specific workflows your agent needs, rather than the entire raw Stitch API. + +## Example Tools + +This server exposes compound tools: + +- `generate_and_extract`: Generates a screen from a prompt and returns the extracted theme + HTML body + screenshot URL in one call. +- `compare_themes`: Generates variants of a screen and diffs their configs. +- `scaffold_project`: Generates multiple screens based on a requirement and returns them as a page manifest. + +## Running the Server + +To start the MCP server over standard input/output (stdio), which is the standard way MCP clients communicate with servers: + +```bash +export STITCH_API_KEY="your-api-key" +bun run src/index.ts +``` + +## Using with an MCP Client + +You can use this server with any MCP-compatible client, such as the Vercel AI SDK or an agent framework. + +1. Configure your client to spawn this script as a child process. +2. The server communicates via standard input/output using the MCP protocol. diff --git a/packages/sdk/examples/mcp-server/SKILL.md b/packages/sdk/examples/mcp-server/SKILL.md new file mode 100644 index 0000000..abb5296 --- /dev/null +++ b/packages/sdk/examples/mcp-server/SKILL.md @@ -0,0 +1,94 @@ +# Skill: Building a Stitch MCP Server + +This skill teaches an agent how to wrap the Stitch SDK into a custom Model Context Protocol (MCP) server. + +## Context + +While Stitch provides its own MCP tools, agents often benefit from compound tools that combine multiple Stitch operations or add domain-specific logic. By creating a custom MCP server, you can provide an agent with high-level workflows tailored to specific tasks, such as generating a UI and immediately extracting its Tailwind config in a single step. + +## Implementation Pattern + +1. **Initialize the MCP Server**: Use the `@modelcontextprotocol/sdk/server` package. +2. **Define Compound Tools**: Create tools that encapsulate multiple Stitch SDK calls. +3. **Use the Stitch SDK**: Use `@google/stitch-sdk` to interact with Stitch within your tool handlers. +4. **Connect Transport**: Start the server using the `StdioServerTransport`. + +## Example: `generate_and_extract` Tool + +This compound tool generates a screen and extracts the relevant parts (HTML body, Tailwind config, image URL) in a single step. + +```typescript +import { Server } from "@modelcontextprotocol/sdk/server/index.js"; +import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; +import { + CallToolRequestSchema, + ListToolsRequestSchema, +} from "@modelcontextprotocol/sdk/types.js"; +import { stitch } from "@google/stitch-sdk"; + +// 1. Initialize Server +const server = new Server( + { name: "stitch-custom-mcp", version: "1.0.0" }, + { capabilities: { tools: {} } } +); + +// 2. Define Tools +server.setRequestHandler(ListToolsRequestSchema, async () => { + return { + tools: [ + { + name: "generate_and_extract", + description: "Generates a UI screen and extracts its theme and HTML body.", + inputSchema: { + type: "object", + properties: { + prompt: { type: "string", description: "The UI to generate" }, + title: { type: "string", description: "Project title" } + }, + required: ["prompt", "title"] + } + } + ] + }; +}); + +// 3. Handle Tool Calls using Stitch SDK +server.setRequestHandler(CallToolRequestSchema, async (request) => { + if (request.params.name === "generate_and_extract") { + const { prompt, title } = request.params.arguments as any; + + // Use the Stitch SDK + const project = await stitch.createProject(title); + const screen = await project.generate(prompt); + + const htmlUrl = await screen.getHtml(); + const imageUrl = await screen.getImage(); + + // Fetch and extract data (simplified for example) + const resp = await fetch(htmlUrl); + const html = await resp.text(); + const configMatch = html.match(/