MCP Tools
Handoff exposes a Model Context Protocol server at https://demo.handoff.com/api/mcp. Connect Cursor, Claude, or Windsurf to read design tokens, search components, look up icons, and generate components from design artifacts.
Setup — Cursor & Claude
Connect AI assistants to this Handoff deployment for reference materials, components, sync, design library, and design-to-component generation. MCP uses the same OAuth token as the CLI — run handoff-app login first (step 1).
MCP endpoint on this deployment: https://demo.handoff.com/api/mcp
Get your access token
After handoff-app login, run handoff-app mcp-token to print your token, and paste it in place of PASTE_ACCESS_TOKEN_FROM_CLI_AUTH below. (The token also lives in .handoff/cli-auth.json — keep it out of git.)
handoff-app mcp-token
- Create or edit
.cursor/mcp.jsonin your design repo (project-only), or~/.cursor/mcp.jsonfor all workspaces. - Paste the config below, replace the token, then restart Cursor or open Cursor Settings → MCP and enable the handoff server.
- In chat, ask the agent to call
handoff_get_project_contextfirst, then use reference, sync, or design tools. Pair with Figma MCP for design-to-code.
{
"mcpServers": {
"handoff": {
"url": "https://demo.handoff.com/api/mcp",
"headers": {
"Authorization": "Bearer PASTE_ACCESS_TOKEN_FROM_CLI_AUTH"
}
}
}
}Common MCP tools
handoff_get_project_context— stack profile, paths, workspace summary (call first)handoff_get_stack_guide— Handlebars/React authoring ruleshandoff_get_reference— catalog, tokens, icons, property-patterns (maintained in Admin → Reference; regenerate after catalog changes)handoff_get_design_guidelines/handoff_get_brand_voice— team settings from Design → Settingshandoff_get_component_reference— buttons / inputs / iconography reference imageshandoff_sync_pull/handoff_sync_push— team sync (patches applied in your repo)handoff_start_component_from_design— design library → component job
Full tool list and scopes: see docs/HANDOFF-MCP-RFC.md in the handoff-app package.
Context
handoff_get_brand_voiceFormatted brand voice / copy guidelines from design workspace.
handoff_get_design_guidelinesTeam Design.MD guidelines from design workspace settings.
handoff_get_project_contextProject hydration: stack profile, paths, Figma key, translation hints.
handoff_get_stack_guideMarkdown authoring rules for the active stack (bootstrap-handlebars, react-tailwind, react-scss).
handoff_update_brand_voiceUpdate the team brand voice in design workspace settings (admin + sync:write). Accepts any subset of fields and MERGES over the stored value — omitted fields are left alone, and a field set to "" is cleared. This is the standing copy guidance every future generation inherits (design images, page copy, component previews, DESIGN.md exports), not a per-request override — it changes output for everyone until it is changed again. The response echoes a per-field before/after so the overwritten text is recoverable.
handoff_update_design_guidelinesReplace the team Design.MD guidelines in design workspace settings (admin + sync:write). This REPLACES the whole document — there is no merge, so send the complete text (read the current value with handoff_get_design_guidelines first). These are the standing design instructions every future generation inherits, not a per-request override. The response returns the previous content alongside the new one so the overwritten version is recoverable.
Components
handoff_browse_componentsOpen an INTERACTIVE inline gallery of the design system's components — a searchable card grid. The user can Select a component to hand it back to you, or Open it in Handoff. Use when the user wants to browse or pick a component; use handoff_search_components for raw catalog data.
handoff_get_componentComponent implementation data by id — code/html/sass/css, properties, variants, and usage guidance. Slimmed for context use: excludes the compiled sharedStyles CSS (~97% of the raw row), validationResults, and Figma sync metadata. Each preview may carry a `purpose` — structural (placeholder copy showing the form) / example (real content) / builder (seed for a new block) / edge (stresses the contract) — which is what tells you which one to read or copy; previews with no `purpose` are unclassified, not "generic".
handoff_get_component_referenceComponent style reference image for a slot: buttons | inputs | iconography.
handoff_get_referenceFetch generated reference material by id: catalog | tokens | icons | property-patterns. (May also be passed as "type".)
handoff_search_componentsSearch the component catalog. Matches every word of the query against a component's id, title, group, tags and description, so word order does not matter. Returns a `use` line saying what each block is for — read it before choosing, because several blocks hold copy and they are not interchangeable.
Tokens
handoff_browse_tokensOpen an INTERACTIVE inline palette of the design system's foundation tokens (color swatches, type specimens, spacing scale). The user can click a token to hand it back to you. Use when the user wants to SEE and pick tokens; use handoff_get_tokens for raw token data.
handoff_export_design_mdExport a compact DESIGN.md framing brief for this design system — system identity, token brief (colors/type/spacing/radius/grid), component vocabulary, brand voice, and design guidelines. Commit it to a project and reference it from CLAUDE.md so an agent has design-system context without a live MCP call. For a multi-axis system, pass brand/scheme to frame the brief around that resolved theme.
handoff_get_tokensFoundation design tokens (colors, typography, effects, and any spacing/radius/grid when extracted). Slimmed for context use — excludes icon/logo SVGs, per-component token usage, and the SCSS $map. Use handoff_get_icon_catalog/handoff_get_logo_set/handoff_get_component for those. Multi-axis (brand × scheme): the response advertises available `axes`; pass brand/scheme to get axis-resolved tokens under `axisTokens`.
Icons & Logos
handoff_get_icon_catalogReturn the full icon catalog as defined in the design system. Optionally filter by category. Each entry includes id, name, description, category, tags, usage guidance, and source (SVG content or iconify/fa-pro reference).
handoff_get_logo_setReturn all logo variants for the design system, including SVG content, usage guidance, and variant metadata (light/dark/color/mono, primary/alternate/wordmark/icon-only). Optionally filter by variant or form.
handoff_search_iconsSearch the icon catalog by name, tag, or description substring. Returns matching IconCatalogEntry objects including SVG content where available.
Assets
handoff_get_assetGet full details for a single asset including component usages and size info.
handoff_list_asset_collectionsList all asset collections (Figma sections or manually created groups).
handoff_search_assetsSearch the asset library — logos, icons and images. Matches every word of the query across title, alt text, description and tags; if nothing matches all of them, falls back to any of them and says so. Returns a summary per asset: id, title, type, storageUrl, alt text, description, tags and native dimensions. Use `handoff_get_asset` for full detail including SVG content, file size and component usages.
Design Artifacts
handoff_create_design_artifactCreate design artifact with base64 image (design:write).
handoff_generate_component_from_designFetch a design artifact's spec and extracted assets to generate a component locally. If no spec exists yet, queues server-side spec generation. Returns the full spec, markdown, image URLs, and stack guide context for you to implement the component in the local codebase.
handoff_get_component_specGet the component specification (structured spec + editable markdown) for a saved DESIGN ARTIFACT — takes an `artifactId`, not a component id. Returns the full ComponentSpec JSON and the rendered markdown for local component generation. **For an existing component's contract (properties, previews, should_do/should_not_do), use handoff_get_component instead.**
handoff_get_design_artifactGet design artifact by id.
handoff_list_design_artifactsList saved design library artifacts. Registry mode only.
Design Workbench
handoff_extract_design_assetsDEPRECATED — use handoff_transition_to_dev, which this now forwards to. Runs the dev handoff for a design artifact.
handoff_generate_design_imageQueue an AI design image generation (async). A durable background runner processes the job within ~1 min; poll handoff_get_design_job for the result. Requires server AI to be configured.
handoff_get_design_jobPoll a design image generation job (from handoff_generate_design_image). Read-only.
handoff_set_design_statusSet a design artifact's lifecycle status (draft → review → approved). Moving to review or approved kicks off server-side asset extraction + spec generation (when server AI is configured), so the artifact's spec/assets are ready for handoff_generate_component_from_design.
handoff_transition_to_devTransition a design artifact to developer-ready: extracts its assets (backgrounds, states, icons) and generates the full specification — props, behavior, accessibility, text inventory, design-token mapping against the registry's real tokens, and a brand-voice check of the copy. One operation; poll handoff_get_design_artifact and read `devHandoff` for stage-level progress (extracting_assets → generating_spec → ready). Read the result with handoff_get_component_spec.
Pages & Compositions
handoff_create_pageCompose a NEW playground page (landing page) from component blocks and save it (source: playground). Each block is {id (component id), preview? (existing preview key), args? (prop values)}. To compose blocks that render WELL (not just validly), call handoff_scaffold_args for each component first — it returns correctly-shaped `args` (seeded from a real preview) + per-field shapes; tweak and pass them here. Or reference an existing preview by key via `preview` and override only what changes in `args`. Every block is validated against its contract (unknown ids / out-of-contract args are rejected). Richtext fields are stored as Portable Text; HTML in and out by default, so pass the HTML you would write and read it back the same way. Any VISUAL slot you leave unset renders blank — the returned `report[].emptySlots` flags those. `editUrl` renders your exact args live now; `publishedUrl` (the standalone page) only reflects this composition after a rebuild.
handoff_delete_pageArchive a playground page. **This is not a hard delete** — the record and its history stay, the page is taken out of every listing, and any build briefs made from it (plus the pages built from those) are archived with it. There is no un-archive yet, so treat it as final from a caller's point of view. Added because a page composed by mistake previously had no way to be cleaned up at all.
handoff_get_pageGet one playground page (pattern): its ordered block composition ([{id, preview?, args}]) + metadata. Read this before editing/swapping blocks, then pass the modified blocks to handoff_update_page. Richtext fields are STORED as Portable Text but returned as HTML by default — HTML in and out, so blocks you read here can be edited and passed straight back. Ask for `richTextFormat: "portableText"` for the canonical stored shape, or "markdown" to read the copy without the markup.
handoff_list_pagesList playground pages — saved compositions of component blocks ("patterns"). Use to see or reuse existing landing pages before composing a new one. Optionally filter by group.
handoff_scaffold_argsGet a ready-to-fill `args` template for a component so you dispatch blocks/previews that render WELL instead of guessing prop shapes. Seeds `args` from a real preview (correctly-shaped slots, images, arrays) when one exists, and annotates every field with its editorType + expected shape (richtext = HTML string, image = { src, alt, … }, etc). Fill/tweak the returned `args`, then pass it to handoff_create_page (as a block's args) or handoff_create_preview. Call this BEFORE authoring to avoid empty slots / wrong-shaped values.
handoff_update_pageUpdate a playground page: metadata and/or its full block composition. To add/remove/swap/reorder blocks (e.g. swap in a new hero), read the page with handoff_get_page, modify the blocks array, and pass the FULL new array here. Blocks are validated against contracts before saving. Richtext fields take HTML (or the Portable Text a "portableText" read returned) and are stored as Portable Text.
Previews
handoff_create_previewAuthor a NEW registry preview for a component — a named, semantic value-set (e.g. a "Primary CTA" button). Call handoff_scaffold_args first for correctly-shaped `values`. Values are validated against the component contract; invalid values are rejected, not saved. This is how Claude publishes a configured, meaningful example to the workbench. Richtext fields are stored as Portable Text; HTML in and out by default — pass the HTML you would write. Returns `verifyUrl` — the component page with `?preview=<key>`, which opens on this value-set. **It resolves the preview through a live API call, so on a statically exported registry it will not appear until `handoff-app build` runs.** Also returns a `report` (empty visual slots + each field's editorType) to self-check the values. Set `purpose` so the preview is grouped and picked correctly — an unpurposed preview lands in the component page's trailing "Other" group. Once a value-set is approved, mark it canonical with handoff_promote_preview.
handoff_preview_componentRender an INTERACTIVE, inline preview of a component (embedded app) — the real rendered component with responsive width controls. Pass a component id and optionally a preview key. Use when the user wants to SEE a component, not just read its data (handoff_get_component). With no key it picks by `purpose` — the component's `builder` seed, else its `example`.
handoff_promote_previewApprove a registry preview: mark its value-set canonical (semantic="canonical") so it reads as the blessed, reference example for its component. Use after review to promote a value-set authored via handoff_create_preview / handoff_update_preview. Lifecycle only — it does not touch `purpose`, which says what the preview is FOR. Zero contract change — no rebuild, no migration.
handoff_update_previewUpdate an existing registry preview (by its id). Provide any of title / values / semantic / purpose / rationale. Changed values are re-validated against the component contract; richtext fields are stored as Portable Text, and HTML is accepted (and returned) as it always was. `purpose` is authoring classification (what the value-set is FOR); to approve/canonicalize a value-set instead, use handoff_promote_preview, which sets `semantic` and leaves `purpose` alone.
Documentation
handoff_create_doc_pageCreate a NEW markdown doc page. Fails if the slug already exists (use handoff_update_doc_page). The page appears in the sidebar nav automatically.
handoff_get_doc_pageGet one markdown doc page by slug — its frontmatter + markdown body.
handoff_list_doc_pagesList markdown documentation pages (slug, title, description). These are doc/content pages — distinct from playground pages (block compositions; use handoff_list_pages for those).
handoff_update_doc_pageUpdate an existing markdown doc page (by slug). Fails if it does not exist. Provide markdown and/or title/frontmatter; frontmatter is merged with the existing.
Change Inquiry
handoff_change_whyThe reason a specific change was made: returns the human-authored push message if present, otherwise generates and caches a one-sentence AI summary from the diff. Pass the change type and id as returned by handoff_recent_changes / handoff_component_history.
handoff_component_historyVersion history for one component (newest first): version number, when, who, the "why" when recorded, and the CATEGORIES that moved — contract | visual | content | asset | config. Contract versions also carry the property-level delta (added / removed / retyped / newly required), so this answers "can I still pass <prop>?" as well as "what changed in <component>" and "how has it evolved".
handoff_recent_changesRecent changes across the design system, grouped by PUSH — one entry per push, newest first, not one per row. Each push gives who pushed it, when, the "why" (the push message, or a drafted summary), the commit, and the entities it touched with the categories that moved: contract (properties/slots), visual (artifacts/theme), content (previews/docs/metadata), asset (images), config (source/handoff config). Use to answer "what changed recently/lately/since <when>". Filter with contractOnly to answer "did anything break?". For the reason behind one specific row, follow up with handoff_change_why using its entity type + changeId.
Build & Sync
handoff_enqueue_buildDEPRECATED — server-side builds retired. Builds run locally via `handoff-app build`. Returns workspace-mode notice.
handoff_list_reference_materialsList reference material ids and sizes.
handoff_sync_pullFetch a bounded page of sync changes since cursor (JSON patches for local apply). Registry mode only. Results are paginated: if the response has `hasMore: true`, pull again with `since` set to `nextCursor` and repeat until `hasMore` is false to drain the full feed.
handoff_sync_pushUpload sync changes (requires sync:write). Registry mode only.
handoff_sync_statusRemote sync cursor and health. Returns workspace-mode notice if no registry is connected.
Other
handoff_component_contract_historyContract history for one component: only the versions whose properties or slots changed, each with the property delta (added / removed / retyped / newly required) and whether it was breaking. Use before upgrading a consumer, or to answer "can I still pass <prop>?" / "when did <prop> become required?" / "has this component ever broken its API?". Ignores the visual, content, asset and config versions that handoff_component_history also lists.
handoff_delete_doc_pageDelete a markdown doc page by slug. Removes it from the sidebar nav and records the deletion in the changelog. Fails if the slug does not exist.
handoff_list_review_queueList playground pages awaiting review — typically pages built by someone outside the team through a guest share link. Each entry carries who submitted it (a self-declared, UNVERIFIED name), the template it was built from, the share link that admitted them, and their note to the reviewer. Decide an entry with handoff_review_page.
handoff_move_doc_pageMove (rename) a markdown doc page from one slug to another, preserving its content. Fails if fromSlug does not exist or toSlug is already taken. Use this instead of delete+create so the page keeps its history and the nav tree updates atomically.
handoff_review_pageApprove a submitted playground page, or send it back to its author. "approve" marks it approved; "reject" returns it to draft, which also re-opens editing for the guest who built it, so a rejection with a message is how you ask for another pass. Visibility is never changed — promoting a page to a wider audience stays a separate, deliberate act. Maintainer only.