Architecture
How the Stitch SDK is built and why it works the way it does.
The Stitch SDK isn’t a hand-written REST client. It’s a generated domain layer built on top of the Model Context Protocol (MCP), designed to give you a fluent TypeScript API while keeping a single source of truth for every tool Stitch offers.
Why MCP, not REST?
Stitch already runs an MCP server that AI agents connect to directly. Instead of maintaining a separate REST API surface, the SDK connects to the same MCP server over HTTP. This means:
- One API surface. The tools available to the SDK are the exact same tools your AI agent uses. No drift.
- Instant updates. When new tools ship on the MCP server, the SDK generator picks them up automatically.
- Agent compatibility. The same
callToolsemantics work whether you’re in an SDK script or an AI agent.
The three layers
The SDK has a clear three-layer architecture:
┌─────────────────────────────────┐
│ stitch (singleton proxy) │ ← What you import
├─────────────────────────────────┤
│ Stitch / Project / Screen │ ← Generated domain classes
├─────────────────────────────────┤
│ StitchToolClient │ ← MCP-over-HTTP transport
└─────────────────────────────────┘
Layer 1: StitchToolClient (transport)
The foundation. Connects to the Stitch MCP server over HTTP, handles authentication (API key or OAuth), and exposes raw callTool(name, params) for any MCP tool. You can use this layer directly if you need full control.
Layer 2: Generated domain classes (domain)
Stitch, Project, and Screen are auto-generated from two source files:
tools-manifest.json- A snapshot of every MCP tool’s name, description, and input schema.domain-map.json- A hand-authored mapping that assigns tools to domain classes and methods.
A generation script reads both files and produces TypeScript classes in generated/src/. Each method is a thin wrapper around callTool that handles parameter mapping and response parsing.
The generation is content-hash locked - regenerating only produces changes when the manifest or domain map actually changes. This prevents churn.
Layer 3: stitch singleton (convenience)
A Proxy object that lazily initializes a StitchToolClient from environment variables and delegates method calls to either the Stitch domain class or the StitchToolClient, depending on the method name.
When you write stitch.projects(), the proxy routes to Stitch.projects(). When you write stitch.callTool(...), it routes to StitchToolClient.callTool().
Identity map pattern
stitch.project(id) and new Project(client, id) create a handle without making an API call. They parse the ID (stripping any projects/ prefix) and return a Project object that you can immediately call .generate(), .screens(), or .getScreen() on.
This is useful when you already know a project ID from a previous operation - you don’t need to re-fetch it.
The AI SDK adapter
stitchTools() (from @google/stitch-sdk/ai) bridges the SDK into the Vercel AI SDK ecosystem. It reads the same tools-manifest.json and produces a Record<string, Tool> compatible with generateText() and streamText().
The adapter has zero runtime dependency on the ai package. It reconstructs the tool schema format using Symbol.for("vercel.ai.schema") - matching the AI SDK’s internal protocol without importing any of its code. This keeps the SDK lightweight for consumers who use only the domain API.
Error handling
All domain methods catch errors internally and re-throw them as StitchError instances with structured error codes. This gives you a single error type to catch:
import { StitchError } from "@google/stitch-sdk";
try {
await screen.edit("...");
} catch (e) {
if (e instanceof StitchError) {
console.error(e.code, e.message);
}
}
Original: https://stitch.withgoogle.com/docs/sdk/architecture/
Translated from the official Google Stitch documentation. Original content © Google LLC. This is an independent, unofficial translation.