MCP Server
@csszyx/mcp-server exposes CSSzyx as an
MCP (Model Context Protocol) server so AI
assistants (Claude, Cursor, Copilot, etc.) can expand, validate, look up, and
migrate sz props directly inside your editor.
Install
Section titled “Install”Install the server next to the compiler, at the same version, so the lockfile pins the two together and the server answers with the rules your build uses:
npm install -D @csszyx/mcp-serverRequires Node.js >= 22.12.
Configure Your Editor
Section titled “Configure Your Editor”Each setup below runs the installed binary, csszyx-mcp. npx --no-install
runs it from node_modules/.bin without a registry request, and installs
nothing: a project without the server gets an error, never a release it has not
installed.
Claude Code
Section titled “Claude Code”Add .mcp.json to the project root:
{ "mcpServers": { "csszyx": { "command": "npx", "args": ["--no-install", "csszyx-mcp"] } }}or run claude mcp add csszyx -- npx --no-install csszyx-mcp in the project.
Cursor
Section titled “Cursor”Add the same block to .cursor/mcp.json in the project root.
Claude Desktop
Section titled “Claude Desktop”Claude Desktop starts servers outside any project, so give the binary’s
absolute path in claude_desktop_config.json:
{ "mcpServers": { "csszyx": { "command": "/path/to/your-app/node_modules/.bin/csszyx-mcp" } }}For a client that cannot run a project’s binary, pin the version your
compiler has and read the npm cache first:
npx --prefer-offline -y @csszyx/mcp-server@<version>.
The server speaks MCP over stdio, so any MCP-compatible client runs the same command.
The server answers with the @csszyx/compiler it was installed with. Every
tool reply names it in _meta.compilerVersion, beside the project’s in
_meta.projectCompilerVersion; when the two differ, the reply opens with a line
saying so, and the server’s instructions say it at startup.
csszyx_expand
Section titled “csszyx_expand”Expand a single sz object into Tailwind CSS class strings.
Input: { p: 4, bg: 'blue-500', hover: { bg: 'blue-700' } }Output: "p-4 bg-blue-500 hover:bg-blue-700"csszyx_batch
Section titled “csszyx_batch”Expand multiple sz objects in one call — more efficient than calling
csszyx_expand repeatedly.
Input: [{ p: 4 }, { m: 2, bg: 'red-500' }]Output: ["p-4", "m-2 bg-red-500"]csszyx_reverse
Section titled “csszyx_reverse”Convert a Tailwind class string back into an sz object.
Input: "p-4 bg-blue-500 hover:text-white"Output: { p: 4, bg: 'blue-500', hover: { color: 'white' } }A few classes depend on the project: a sign on a keyword (-z-auto) or a
fraction on a spacing key (-m-1/2) is served only when the project’s
Tailwind says so, for example through a --spacing-1\/2 theme step. For
those, the tool asks the project’s Tailwind, from the directory the server
runs in, as csszyx migrate does; with no Tailwind v4 there, the class stays
in the unrecognized list. A prefix the project’s stylesheet sets
(prefix(tw)) is read off each class the same way, and the round trip compiles
the answer back with it.
When the project cannot answer in full, a note says so: its stylesheets set
different prefixes, none compiled, or Tailwind could not be asked. A server
started in a directory without a package.json reads no stylesheet, so start
it from the project root.
csszyx_validate
Section titled “csszyx_validate”Validate a sz object before using it. Reports unknown props, CSS property name
mistakes (padding → p), and transform errors.
Input: { padding: 4 }Output: error — "Unknown prop 'padding'. Use 'p' instead."A problem the compiler reports comes as fields, the same ones csszyx check --json writes: code, message (the main sentence), help, note (each
left out when there is none) and url.
Input: { p: 1.3 }Output: warnings: [{ code: "off-scale-value", message: "`p: 1.3` is not on Tailwind's spacing scale, so the class generates no CSS.", help: "use a quarter step such as `1.25`, `1.5` or `1.75`, or a unit value such as `'1.3rem'`.", url: "https://csszyx.com/e/off-scale-value" }]csszyx_lookup
Section titled “csszyx_lookup”Look up how a CSS property or keyword maps to an sz key. Accepts CSS property names (kebab-case or camelCase), sz keys, or free-text keywords.
Input: "background-color"Output: { szKey: "bg", tailwindPrefix: "bg", examples: [...] }csszyx_migrate
Section titled “csszyx_migrate”Transform a JSX/TSX code snippet, replacing className attributes with sz
props. Handles clsx calls, ternary expressions, and template literals.
// Input<div className="p-4 bg-blue-500" />
// Output<div sz={{ p: 4, bg: 'blue-500' }} />Optional parameters:
customMap— pass a parsed.csszyx-todo.jsonmap to resolve custom classesinjectTodos— insert{/* @sz-todo: ... */}comments above unresolved elements
The snippet is read as csszyx migrate reads a file of the project the server
runs in: with the prefix its stylesheets set, and with its Tailwind answering
for the classes that depend on the project, as for csszyx_reverse. A note
says when it could not.
csszyx_theme
Section titled “csszyx_theme”Parse @theme CSS blocks and categorize custom design tokens (colors, spacings,
fonts, radii, shadows).
csszyx_compile_preview
Section titled “csszyx_compile_preview”Compile a whole source module and report what csszyx made of it: the rewritten code, the classes, the diagnostics, and the runtime helpers left over.
Every other tool takes an sz object, which assumes the code around it already
compiles. Reach for this one when the question is about that surrounding shape —
whether a szv factory precompiles into a lookup, whether a value stays dynamic
and falls back to a custom property, whether a key is unknown and ships a class
that styles nothing.
{ "source": "export const A = () => <div sz={{ p: 4 }} />;" }Pass filename when the parser matters — the extension selects it, so JSX needs
a .tsx name. It defaults to preview.tsx.
The classes carry the prefix the project’s stylesheet sets. With
@import "tailwindcss" prefix(tw) the project serves tw:p-4 and nothing for
p-4, so the tool reads the prefix from the stylesheets of the project the
server runs in, and classPrefixFrom says it did. Pass classPrefix when the
project is elsewhere, or to compile under another prefix:
{ "source": "export const A = () => <div sz={{ p: 4 }} />;", "classPrefix": "tw" }The result echoes the classPrefix it used. When none was given and none was
read, a note says why, since the classes are then in the unprefixed
vocabulary: no stylesheet sets one, or the project’s stylesheets set different
prefixes or did not compile.
The preview does not read the project’s stylesheet, so it cannot tell which
class covers which. A build can: it drops a Tailwind class that a later one on
the same element fully covers, so { pb: 2, p: 4 } and
className="pb-2" sz={{ p: 4 }} both build to p-4 while the preview lists
both classes. Whenever one static sz object in the result holds two or more
classes, or a static className sits beside a static sz, a mergeNote says
so; two elements never merge with each other, so a file of one-key objects gets
none.
Resources
Section titled “Resources”The server also exposes read-only resources that AI agents can load for context:
| URI | Content |
|---|---|
csszyx://reference | Full API reference (llms-full.txt) |
csszyx://property-map | PROPERTY_MAP as JSON |
csszyx://variants | All known variant names as a JSON array |
Prompts
Section titled “Prompts”Two guided workflow prompts are available:
| Prompt | Description |
|---|---|
migrate_component | Paste a Tailwind component and get it migrated to sz props |
create_component | Describe a UI component and get production-ready sz code |