Component Library MCP: Make Agents Use Real Components
Ask Claude Code for a settings page and it will write one in a minute. It may also invent a <Button intent="primary"> your library never had, hardcode #3b82f6 where a token belongs and rebuild a date picker you already own. A component library MCP server fixes that at the source: it gives the agent tools to look up what exists, read the real props and install the real files. This guide covers how a React component library exposes itself to Claude Code, Cursor and Codex, the four pieces that make it work (an MCP server, a rules file, llms.txt and a registry), and the setup our CLI writes for you.
We build Wingo UI, so the examples use our server, CLI and registry, with output copied from release 1.7.0. The approach applies to any library, an internal design system included, and where another tool fits better, we say so. Shorter guides on agents and UI live under Building UI with AI agents: AGENTS.md vs CLAUDE.md vs Cursor rules for the rules file, a Claude Code shadcn setup for the shadcn MCP server next to a second registry, and a React AI chat UI guide for when the screen you are building is the chat itself.
What is a component library MCP server?
A component library MCP server is a Model Context Protocol (opens in a new tab) server that turns a UI library into tools an agent can call: search the catalog, read one component's props and usage, fetch the design rules, and compare installed versions with the latest release. The agent asks instead of remembering.
The client (Claude Code, Cursor, Codex, Gemini CLI) lists a server's tools and lets the model decide when to call them. A server runs as a local process over stdio or as a remote endpoint over Streamable HTTP. Remote servers are easier to keep current, because every client sees a new release the moment you deploy it.
The React component library MCP servers we checked come in three shapes. Here is how they compare, as of October 2026:
Sources, checked in October 2026: the shadcn MCP docs (opens in a new tab), the Material UI MCP guide (opens in a new tab), the React Suite MCP guide (opens in a new tab) and our MCP server docs.
The first shape is a docs lookup. MUI and React Suite ship npm packages, so the agent needs correct props and working links; it never needs source files. If your app runs on Material UI, MUI's own server is the right choice.
The second shape is a registry installer. The shadcn docs describe listing, searching and installing from any shadcn-compatible registry in components.json; they do not mention design rules or update checks. If you pull from several registries, one shadcn server covers them all, which is a real advantage.
The third shape is what a source-copy library needs: docs, install and maintenance in one server. When components live in your repository as code you can edit, the agent has to know what the library offers, which version your project has and how the library expects to be used. That last part is the one a props table alone does not carry.
Why do coding agents invent components?
Because the model writes from training data, and training data predates your library version and leans toward the most common APIs. Without a way to check, the agent fills every gap with the likeliest guess: shadcn's API on a library that is not shadcn, a prop that was renamed two majors ago, a hex color where a semantic token belongs.
The monday.com engineering team described the same failure in How We Use AI to Turn Figma Designs into Production Code (opens in a new tab) (Rivka Ungar, February 2, 2026). Their first attempt, a Figma link pasted into Cursor with the Figma MCP, produced code that hardcoded colors and skipped their design system components. Their diagnosis: "the model had no understanding of what the design system actually was." They then built an MCP server for the design system and found it was still not enough on its own: "the MCP only provided knowledge; it didn't decide how or when that knowledge should be applied across a full UI."
A server full of correct facts does nothing if the agent never calls it, calls it after writing the code, or reads the props and then restyles everything with utility classes. So the server is one of four pieces.
What does an agent need besides the MCP server?
It needs a rules file that says when to call which tool, docs it can read without MCP, and a registry plus CLI that writes the files. Each piece answers a different question and changes at a different speed:
The split that matters: the rules file stays short and stable, and everything that changes lives behind the server. Prop tables pasted into a rules file go stale with the next release, and an agent tends to trust the copy already in its context over a tool it would have to call. Our rules file names tools and commands. It never lists a component's props.
Which tools should a component library MCP server expose?
A few read-only tools, shaped around what an agent does when it builds UI: find, read, follow the rules, install, stay current. Ours has ten:
search_components: find components, blocks, hooks and helpers by keywords.list_categories: browse the categories with item counts.get_component: props, parts, usage, dependencies, the install command and the source.get_block: a full screen or section and the components it composes.get_design_rules: tokens, sizes, motion, forms, overlays and mobile rules.get_theme_tokens: the CSS variables for light and dark mode.get_install_instructions: project setup for Next.js or Vite.check_updates: compare installed items with the latest release.get_changelog: recent releases and their notes.get_account_status: whether the key has Pro, with the links to upgrade.
There is also one prompt, build_screen, that walks the agent through search, rules, install and composition. Every tool is marked read-only and idempotent in its annotations, and none of them writes to your disk. Writing files is the CLI's job.
Search should return slugs and one line each
A search result is a short list the agent can scan in one glance. This is the real answer from our server to search_components with the query "orders table with filters" and limit: 5, trimmed to the first three hits:
Every hit carries its slug, kind, access tier and version, and the last line names the next tool, so the agent never has to guess which call turns a slug into props. The third hit is a weak match. That is fine: one line of description lets the agent skip it without spending a get_component call to find out.
Props need their defaults
get_component returns the props table the docs page shows, with types and defaults, plus parts, a usage example, the npm and registry dependencies, and the install command. Defaults are what keep generated code short. An agent that knows the Button defaults to type="button", tone="neutral" and size="md" writes <Button>Cancel</Button> instead of spelling out props it guessed. One that knows loading keeps the width and sets aria-busy does not wrap the button in its own spinner logic.
Below is that Button with the brand tone and a loading label set through props.
$ npx wingo-ui@latest add buttonWithout JavaScript, the demo is one solid "Pay now" button in the brand color; pressing it shows a spinner and "Paying" in the same width.
Keep tool output small
Large answers run into hard limits in the clients. As of October 2026, Claude Code's MCP docs (opens in a new tab) say it warns when a tool result passes 10,000 tokens, caps results at 25,000 tokens by default (MAX_MCP_OUTPUT_TOKENS raises it) and saves text results over 50,000 characters to a file instead of putting them in context.
Our Data Table is one file of 3,940 lines, about 150 KB of TypeScript. Its docs without source come back as about 18,000 characters, roughly 4,500 tokens. With the source attached (a Pro key), the same call grows past 160,000 characters and passes every one of those limits. So the rule for agents, and for anyone designing one of these servers, is: docs through MCP, files through the CLI. Call get_component with includeSource: false for large items and let npx wingo-ui@latest add write the code.
The same goes for rules. get_design_rules with the topic all returns about 45,000 characters, roughly 11,000 tokens at the usual four characters per token, which is already past Claude Code's warning line. The mobile topic alone is about 1,900 characters and forms about 4,200. Ask for the topic the task needs.
Errors should say what to do next
A tool error is a prompt the agent reads, so write it like one. An unknown slug answers with the closest matches and points back to search_components. A Pro item requested without a Pro key answers with the docs and this, word for word from our server (links trimmed, lines wrapped):
"Do not re-create it from the docs" is the most important sentence on the server. An agent that has just read a complete props table and a long interaction description has everything it needs to attempt a rewrite, and the result is a half copy that matches the docs on paper and nothing else: no version record, no updates, none of the edge cases the description summarizes in one line.
Server instructions are the first thing the agent reads
Claude Code turns on tool search by default, so only tool names and each server's instructions load at the start of a session; full tool definitions load when the model looks for them. The same docs say Claude Code cuts each tool description and each server's instructions at 2,048 characters by default. The instructions are your server's pitch to the model: what tasks it handles, when to search for its tools, and the rules that must survive truncation. Put "search before you write UI" in the first lines.
We learned the cost of that limit on our own server. Its instructions run 2,235 characters in release 1.7.0, so Claude Code drops the last sentence, the one that says never to re-create a component without the right key. The rule still reaches the agent because every refusal and the rules file repeat it. Count your characters, and repeat any rule that matters somewhere the model cannot miss.
How do I connect Claude Code, Cursor and Codex?
One CLI command writes both the MCP config and the rules for your agent. With WINGO_UI_API_KEY set it writes the HTTP configs below, which read the key from the environment so it never lands in your repository; without the variable it writes the local stdio proxy. You can also add the server by hand.
Running it again changes nothing, and it keeps the other servers in your MCP configs. Where each agent's files go:
Access works in three tiers. Without a key, search, docs, props, design rules and tokens all answer, with no source. A key from a free account (email only, no card) adds the source of the 75 free items. A Pro key adds the source of all 326. Create the key in your account and export it in your shell profile as WINGO_UI_API_KEY.
Claude Code
Claude Code stores MCP servers in three scopes: local (the default, private to you in ~/.claude.json), project (.mcp.json at the repository root, committed for the whole team) and user (all your projects). For a library the team shares, use project scope; .mcp.json expands ${VAR} from the environment, so the file is safe to commit:
For a quick personal setup, the one-liner adds it in local scope:
Run /mcp inside a session to see whether the server connected. If you already run other Claude Code MCP servers, this one sits next to them in the same file, and agents install keeps the entries it did not write. Our Claude Code shadcn tutorial walks through the shadcn MCP server, its skill and a second registry in the same project.
Cursor
Cursor reads .cursor/mcp.json in the project and ~/.cursor/mcp.json for every project. It uses its own variable syntax, ${env:NAME}, documented in Cursor's MCP docs (opens in a new tab):
Codex
Codex reads MCP servers from ~/.codex/config.toml (or a trusted project's .codex/config.toml). For a remote server, bearer_token_env_var names the variable that holds the token, as the Codex MCP docs (opens in a new tab) describe. Restart Codex after adding it so it picks up the server.
Any other client
Clients that cannot send a header to a remote server can run the local proxy. It reads the key saved by wingo-ui login and mirrors the remote tools, so new tools appear without updating anything:
What goes in the rules file?
When to call which tool, how to install, and what never to do, in as few lines as you can manage. This is the whole block we put in AGENTS.md, CLAUDE.md or GEMINI.md:
A few choices in there are deliberate. Every bullet tells the agent what to do or when to do it. It names tools and commands but lists no component's props, because props change and tool names do not. It has a fallback for sessions without the MCP server, so the agent degrades to the CLI instead of guessing. And it carries a version marker: npx wingo-ui@latest agents status tells you whether your copy is current, and agents update rewrites only the text between the markers.
Claude Code also gets a skill with the longer workflow, and Cursor gets a project rule scoped to .tsx, .jsx and .css files. The full setup is on the coding agents docs page.
For an internal library, copy the structure: one line on what the library is, one on which tools to call before writing UI, one on how to install, one on styling, one fallback. Five lines that an agent follows beat fifty that it skims. Which of these files each agent reads, and how one AGENTS.md can serve Claude Code, Codex and Cursor at once, is in our AGENTS.md vs CLAUDE.md comparison.
Where do llms.txt and Markdown docs fit?
They serve assistants that can read a URL but have no MCP connection, and they back up the server when it is not configured. The llms.txt proposal (opens in a new tab), published by Jeremy Howard in September 2024, puts a Markdown file at the site root: an H1 with the name, a short summary, then sections of links. It also recommends a clean Markdown version of each page at the same URL with .md added, and its current version (updated August 2026) describes a rel="alternate" link of type text/markdown that points to it.
Our version follows that layout:
- /llms.txt is the map: what the library is, the counts, pricing, the docs pages, the install commands, a link per category and one line per item with its Markdown link.
/llms/<category>.txtholds the item docs for one category, for example every table or every overlay.- Every docs page has a Markdown twin, like /components/button.md, linked from the HTML head.
- /llms-full.txt has everything in one file, about 3.3 MB as of October 2026 (the docs of release 1.7.0 plus the blog posts).
That last file is the trap. A model handed 3.3 MB of docs either truncates it or spends its context on components it will never use. Treat llms.txt as a map and point the agent at the one category file or .md page the task needs. For a chat assistant that can fetch URLs, "read https://wingo-ui.com/components/data-table.md (opens in a new tab), then write an orders table with it" puts the real props in front of the model with one fetch.
What llms.txt cannot do is act. It cannot tell the agent which version your project has, whether your key covers an item, or write files with their dependencies. That is why it is the fallback in our rules and the MCP server is the default.
Why install through a registry instead of pasting code?
Because the registry and CLI write the exact files with their dependencies and record what they installed, and that record is the only way later releases can reach code you have edited. An agent that copies source out of a tool result skips all three steps.
Take the Login Page block. npx wingo-ui@latest add login-page writes three files into components/blocks, then pulls in the 16 registry items the block depends on (Alert, Avatar, Button, Checkbox, Input, OTP Input, Password Input, Separator, Toast and seven hooks and helpers), plus whatever those depend on, and installs its npm packages: motion, lucide-react, react-hook-form and zod. It records each item's version and content hash in wingo-ui.json and keeps a pristine copy under .wingo-ui/base/. When a release changes the block, npx wingo-ui@latest update runs a three-way merge between that pristine copy, your edited file and the new version, the way git merges branches.
An agent pasting code from get_block can miss a dependency, records nothing, and leaves you with files no tool can update. That is why every answer carries the install command and the rules say "install with the CLI" before anything about styling.
The registry also speaks the shadcn format. Free items install straight from their URL, for example npx shadcn@latest add https://wingo-ui.com/r/button.json, and Pro items install by name once the @wingo-ui registry with your key is in components.json, which also lets the shadcn MCP server install them. The trade-off is on our installation page: the shadcn CLI does not record versions, so wingo-ui update cannot merge later changes into files installed that way.
What does a full agent session look like?
Take a Next.js app that already has a wingo-ui.json and a plain prompt: "Build a sign-in page with two-step codes and an orders page with filters, using Wingo UI." With the server connected and the rules in place, the rules and server instructions lay out this path, and the prompt never names a tool:
check_updateswith the items fromwingo-ui.json, and a one-line report of what changed upstream.search_componentswith "sign in page" and the kindblock. On our server the first hit islogin-page.get_blockforlogin-page: the props, the components it composes and the install command.search_componentswith "orders table with filters", thenget_componentfordata-tablewithincludeSource: false.get_design_rulesfor theformsandmobiletopics.- One install for everything:
npx wingo-ui@latest add login-page data-table(Button, Input and the rest come along as dependencies). - Two pages built from the installed components, configured through their props.
Step 2 is the one a setup without the server skips. With nothing to search, an agent writes a sign-in form from scratch: two fields, a button, perhaps a "forgot password" link that leads nowhere. The block the search returns covers password, email link or code sign-in, Google, Apple and Microsoft buttons, two-step codes that lock for a minute after three wrong tries, and the whole password recovery flow. The page code is short because the block does the work:
A rejected promise from onSignIn shows its message in an alert above the form, and twoFactor sends a correct password to the code step. Three wrong codes lock the input for a minute whatever your handler does.
The pitfall is in the handlers the code leaves out. The block ships simulated ones so its demo works, and every on* prop you skip keeps its simulation. Without onVerifyCode, the two-step view accepts 123456. Without showProviders={false} or your own onProvider, the Google, Apple and Microsoft buttons spin for 1.2 seconds and then call onSuccess. An agent that wires onSignIn and stops ships a login page where a click on Google goes straight to /orders without signing anyone in. The get_block props table documents every one of these defaults, so the fix is the same as everywhere else: read the props, then wire each handler or turn the feature off.
The demo below runs on those simulated handlers, with the default methods and providers.
$ npx wingo-ui@latest add login-pageWithout JavaScript, the demo shows the sign-in form: email and password fields, a "Remember me for 30 days" checkbox, the sign-in button, the emailed link option and buttons for Google, Apple and Microsoft.
The orders page follows the same pattern. The Data Table props the agent read decide most of the code: typed columns from createColumns, a badge column with a tone per status, a currency column with a footer sum, filters per column and quick filter chips.
The page itself stays a server component that loads the rows and passes them down:
The split is deliberate. getRowId, rowActions and onSelect are functions (so is any custom cell renderer in the columns), and the App Router cannot pass functions from a server component to a client one. An agent that renders <DataTable> with inline callbacks straight from a server page.tsx gets that error at render time. Keeping the columns and callbacks in a client file and passing only plain rows avoids it.
Two more details come straight from the docs get_component returns. The mobile roles pick each card's title and subtitle below 768px, where the table becomes cards by default (mobileLayout="cards"). And persistKey remembers column visibility, order, widths, density and page size in local storage.
$ npx wingo-ui@latest add data-tableWithout JavaScript, the demo is a client table (client, city, status, owner, balance, last invoice) with a search field, quick filter chips such as Active and Overdue, and export and new client actions.
One more case to plan for: the Login Page and the Data Table are both Pro. Without a Pro key, steps 3 and 4 return the docs plus the refusal quoted earlier, and an agent that follows the rules reports the gap instead of rebuilding them from their props tables.
How do agent-installed components stay up to date?
The agent checks, you decide. At the start of UI work the rules ask for check_updates with the items in wingo-ui.json. The answer lists each update with its semver bump and the notes of every library release that touched the item, then the items that are current. Here is the real output for a project with an older Data Table and a current Button:
The numbers in front of the notes are library releases; the item itself goes from 1.0.0 to 1.1.0.
The Claude Code skill tells the agent to mention updates and run them only when you agree. An update is a code change in files you own, and it deserves the same review as any other diff. From the terminal the loop is three commands:
The rules have their own version: agents status reports an old copy and agents update refreshes it. To keep your own edits to a managed file, delete its wingo-ui:managed line. The updates docs cover conflicts and the --theirs flag, and our guide to updating shadcn components without losing edits shows the same 3-way merge done by hand with git.
How do I check what the agent built?
Review it like a pull request from a fast junior developer who has read the docs. The server gets the first draft onto the right components; it does not replace looking at the result. Our checklist:
- Hardcoded colors and radii. Search the diff for hex values,
rgb(and arbitraryrounded-[...]classes. The rules ask for semantic tokens, and a stray hex color is easy to miss. - Rebuilt components. A new file under
components/that looks like a library item means the agent skipped search. - Restyling instead of props. A long class list on a Button often stands in for a
variant,toneorsizethe agent did not read. - Simulated handlers. Blocks ship demo handlers for every
on*prop. Compare the handlers the agent wired with the features left on screen, as in the login example above. - Phone width and both themes. At 390px tables should become cards and menus should open as bottom sheets (our mobile-first React components guide has the full list); light and dark should both hold up.
- Library files.
npx wingo-ui@latest diff <slug>shows whether the agent edited one. Edits are allowed, but they become merge work on the next update.
Should you build an MCP server for your own design system?
If several people or agents build UI on an internal library, yes. A UI component library MCP server is a smaller project than it sounds: ours is one file of about 220 lines on the TypeScript SDK (@modelcontextprotocol/server) plus four small tool modules, and most of the effort went into the data behind it. The protocol part was the easy bit. What we would tell a design system team, from building ours:
- Start from metadata you already keep. Our tools read the same registry metadata that renders the docs pages. If your props live only in TypeScript types, extract them once into data the docs and the server share, or the two will drift.
- Keep every tool read-only. Let the agent read; let your CLI or package manager write.
- Return structured content and text. The model reads the text; scripts and future clients parse the structure.
- Make outputs small and name the next step. Slugs in search, the source behind a flag, the next tool at the end.
- Write errors as instructions. "Did you mean ..." and "do not re-create it" put the fix in front of the model at the moment it needs it.
- Keep server instructions under 2,048 characters, with the "when to use this server" sentence first. Ours are 187 characters over in 1.7.0, and the sentence that falls off is one we care about.
- Serve the release you deployed. One fresh server per request, backed by that deploy's registry, means agents never see stale props.
- Offer HTTP and stdio. Remote HTTP for clients that send headers, a local proxy for the rest.
The MCP server for UI components we run answers without an account, so you can point any client at it and see these choices from the agent's side before you design your own.
Where should I start?
To try it, connect the server with npx wingo-ui@latest agents install claude (or your agent's name) and ask for a screen in plain words. A free account adds the source of the 75 free items to MCP answers, including the Button and the OTP Input; the CLI installs those without an account. The Login Page and Data Table are part of Pro, which covers all 326 items: $8 a month, $80 a year or $150 once, on the pricing page. The MCP server docs have the per-client setup and troubleshooting.
If you maintain your own library, an MCP server is the cheapest way we know to make agents use it correctly. Pair it with five lines of rules and an installer that records versions, and the agent stops inventing your components and starts installing them.
FAQ
What is a component library MCP server?
It is a Model Context Protocol server that exposes a UI library to coding agents as tools: search the catalog, read one component's props with defaults and usage, fetch the design rules and check installed items for updates. The agent calls these tools instead of guessing an API from its training data.
Do I still need a rules file if I connect an MCP server?
Yes. The server supplies facts, but an agent does not always reach for a tool on its own. A few lines in CLAUDE.md, AGENTS.md or a Cursor rule tell it to search before it writes UI, to install with the CLI and never to rebuild a component the library has.
Is llms.txt enough without an MCP server?
It helps assistants that can only read URLs, but it cannot act on anything. It cannot install files, compare your installed versions with the latest release or tell the agent which items your plan includes.
Does the Wingo UI MCP server work without an account?
Yes for docs: search, props, usage, design rules and theme tokens answer without a key. A key from a free account (email only) adds the source of the 75 free items, and a Pro key adds the source of everything else.
Can I use the shadcn MCP server with Wingo UI?
Yes. Add the @wingo-ui registry to components.json, with your API key for Pro items, and the shadcn MCP server can search and install from it. It does not serve our design rules or update checks, and the shadcn CLI does not record versions, so wingo-ui update cannot merge later releases into files installed that way.
Which coding agents can connect to the Wingo UI MCP server?
npx wingo-ui@latest agents install writes ready configs and rules for Claude Code, Codex, Gemini CLI, Grok and Cursor. Any other client that runs local commands can use the stdio proxy, npx -y wingo-ui@latest mcp.
- MCP
- Claude Code
- Cursor
- Codex
- AI agents
- Registry