How a coding agent reads your design system over MCP
What happens between your prompt and the code: which Wuizard tools your agent calls, what each one returns, and how it checks its work against your sheet.
The Wuizard team6 min read
On this page
You connect your coding agent to Wuizard, ask for a settings page, and the page comes back in your colours with your toast and your modal. This post walks through what happens in between: what the agent sees, which tools it calls, what comes back, and how it checks its own work. Nothing here is hidden. You can watch every call in your agent's tool log.
MCP in one paragraph#
The Model Context Protocol is an open standard for connecting AI apps to outside tools and data. A server publishes a list of tools, each with a name, a plain-language description and the inputs it takes. The client (Claude Code, Cursor, Claude and others) shows that list to the model. When the model decides a tool would help, it calls it, and the result comes back as text in the conversation. Wuizard is an MCP server at https://wuizard.com/mcp; the setup guide shows how to connect each client.
What the agent sees when it connects#
Three things arrive when the connection opens.
- Instructions. A short brief the server sends to every client: call
get_sheetbefore building UI, load the tokens, use slotted components as they are, never invent colours, radii, fonts or springs, and runcheck_uibefore finishing. - Tools. Each with a description written for the model. Lookups are marked read only, so clients that show this can tell your agent is only reading.
- Resources. Your sheet and its
CLAUDE.md, for clients that keep standing context loaded.
The descriptions do more work than you'd expect. The agent decides which tool to use by reading them, so each one says plainly when to call it. get_slot, for example, tells the agent to use the component as it is instead of writing that UI itself.
A screen, step by step#
Say you ask for a settings page with a save confirmation. A typical run looks like this.
1. Read the sheet#
The agent calls get_sheet. It gets back a short summary of your design system: the foundations with their exact values, every slot and what fills it, and your rules. Here is part of the answer for a sheet started from the Studio vibe:
## Foundations (use these tokens, never raw values)
- color: bg #f6f5f1 · surface #ffffff · fg #141416 · muted #6b6b74 · line #e4e2dc · accent #2f5bff · on-accent #ffffff
- radius: sm 6px · md 10px · lg 16px
- type: display Inter 600 (tracking -0.02em) · body Inter
- motion.spring: stiffness 380 · damping 30
- spacing: 4px unit. Use the spacing scale (p-4 = 4 units = 16px), never arbitrary px
- shadow: soft. Use only shadow-sm / shadow-md / shadow-lg (--shadow-*), never custom shadowsNotice the wording: "use these tokens, never raw values". The answer is written to be followed, not just read.
2. Load the tokens#
Next comes get_tokens, which returns the same foundations as CSS variables, a Tailwind v4 theme, a Tailwind v3 config, JSON or a SwiftUI file. The agent adds them to your global CSS once. Every slotted component reads these variables, so from here on colours, corners, fonts and shadows come from one place.
3. Fetch the components#
For each part of the screen that has a slot, the agent calls get_slot. Asking for feedback.toast returns the component's name and version, the values resolved for your sheet, the tokens it reads, what it does when reduced motion is on, its dependencies, where to save it and the full source. The source has a small block of tunable numbers near the top, already set for your sheet:
// @wuizard:spec
const spec = { stiffness: 380, damping: 30, gap: 9 } as const;
// @wuizard:endThe stiffness and damping come from your sheet's spring, not the component's defaults. Change the spring and every sprung component follows the next time it's fetched. The reply also tells the agent plainly to use the component as it is and not restyle it, because the values are your choice.
4. Write the page#
Now the agent does what it's good at: the layout, the form, the state, the wiring. It composes the screen from your pieces and uses your tokens for anything in between, such as spacing and section backgrounds.
5. Check the work#
Before finishing, the agent passes the code it wrote to check_ui. This is a fixed set of checks, not another model's opinion, so the same code always gets the same answer. It flags colours outside your foundations (including stock Tailwind palette classes), radii off your scale, springs and fonts that aren't yours, custom shadows, spacing off your unit, icons from another set, animation without a reduced-motion fallback, and hand-written versions of components you've slotted. Each issue comes with a line number, and most with a suggested fix, so the agent can correct them before handing the screen back.
When the sheet doesn't have something#
Sooner or later a screen needs something you haven't slotted, say a date picker. The instructions are clear about what happens next: the agent calls search_library with a description, shows you what it found (with components that suit your sheet's vibe first), and waits. Only when you've picked one does it call add_to_sheet. From then on, that slot is part of your system for every future screen.
This is deliberate. An agent that quietly invents a date picker is exactly how the default look gets back in.
Whole pages and other frameworks#
If you've filled your section slots, the agent can call get_page for a landing, pricing, about, contact, blog, features, changelog, careers or not-found page. It gets one page file that imports each section, then fetches the sections with get_slot, so nothing is written twice. The docs cover how a page becomes ready.
Not on React? translate_asset returns any slot in Vue, Svelte, SwiftUI or vanilla JS, with the same values filled in.
What it costs#
Reading the sheet, tokens, slots, pages and assets is free and doesn't count against anything. Tools that do heavier work on our side, such as library search, check_ui, translations and extracting a sheet from a website, are metered. The limits table has the current numbers for each plan.
Why a lookup beats a long prompt#
- It's always current. The agent asks for your system when it needs it, so there's no stale copy pasted into last month's conversation.
- It's small. The agent loads what this screen needs, not every decision you've ever made, which leaves more of its attention for the task.
- It's exact. A value or a file can't be misread the way "make it feel premium" can.
- It's checkable. Because the system is concrete,
check_uican say precisely where code drifts from it.
Why AI-built apps all look the same covers the problem this solves in more depth, and prompting for design vs a design system compares the two approaches side by side.
If your agent skips the sheet#
Agents sometimes jump straight into writing code. Three things help. Mention the sheet in your request ("use my Wuizard sheet"). Keep the sheet's CLAUDE.md at the root of your repo so the instruction is there in every session; it comes with the export. And ask for check_ui at the end, which catches anything that slipped through.
If you want to see what your agent is reading in the first place, what goes into a design sheet walks through every part.
Questions
Does my agent read the whole library every time?
No. It reads your sheet, then fetches only the components the current screen needs with get_slot. The library is only searched when you ask for something your sheet doesn't have yet.
Can the agent change my sheet on its own?
Only two tools change a sheet's design: add_to_sheet and create_sheet_from_extraction. Both tell the agent to ask you first, and both need a connection with edit access; the Agents page shows which access each connection has. generate_media saves new images to the sheet and asks the agent to check with you before making several.
In the library