Blog//6 min read
Let Claude Code install UI components with an MCP server
Connect an MCP server for UI components to Claude Code, ask for a plumber landing page, and watch the agent find, install and wire real React blocks.
MSMarco Schulz, founder of Facade UI
When I ask Claude Code to "add a hero with a phone number and rotating service words" in a project without any component context, it writes one from scratch. The result is usually fine and always different from the last one. The animations are invented on the spot, the accessibility is whatever the model remembered that day, and the next page gets a slightly different hero. An MCP server fixes this by giving the agent a catalog to pull from instead of a blank file. This is how the Facade MCP server works with Claude Code, what the agent gets back, and where it still needs a human.
What MCP is, in one paragraph
The Model Context Protocol is a small JSON-RPC protocol that lets an AI agent call tools that live outside the model. A server publishes a list of tools with names, descriptions and input schemas. The agent reads the list, decides when a tool fits the task, calls it with arguments and gets text back. Claude Code, Cursor and Codex all speak it. The Facade server runs as a plain HTTP endpoint on the same Next.js app that serves the docs, so there is nothing to install locally.
Adding Facade to Claude Code
One command registers the server:
claude mcp add --transport http facade https://facadeui.com/api/mcpThat gives the agent the 33 free items. With a Pro license, pass the key as a header so the agent can also read Pro sources:
claude mcp add --transport http facade https://facadeui.com/api/mcp \
--header "Authorization: Bearer $FACADE_LICENSE_KEY"The server exposes four tools:
list_componentssearches the catalog by free text, kind (component or block), category or tier.get_componentreturns the docs for one item: description, props table, install command, usage example and, where allowed, the full TypeScript source.get_install_commandreturns a singlenpx shadcn@latest addline for several items.suggest_pagereturns an ordered block list for a business type.
Nothing in the server writes to your project. The agent reads from it and then runs the shadcn CLI in your repo like any other shell command, so the files that land in components/facade/ are the same ones a developer would install by hand.
Asking the agent to build a plumber page
Here is a prompt I use as a test, in a fresh Next.js project with shadcn initialized:
"Build the home page for a plumber in Austin using Facade blocks. Live rating in the hero, a service area map with a ZIP checker, and a mobile call bar. Phone is 512 555 0147."
What happens, step by step:
- The agent calls
suggest_pagewith"plumber"and gets a numbered block order back: hero, logo cloud, features, process steps, service area, testimonials, pricing, FAQ, contact, footer, each with its first line of usage. - It calls
get_componentfor the blocks it decided to use, reads the props, and notices thathero-local-businessandsticky-contact-barare free whileservice-areais Pro. - It calls
get_install_commandwith the three names and runs the returned command. - It writes
app/page.tsx, passing real values from my prompt into real props.
The page it produced on my last run, lightly trimmed:
import { HeroLocalBusiness } from "@/components/facade/hero-local-business";
import { ServiceArea } from "@/components/facade/service-area";
import { StickyContactBar } from "@/components/facade/sticky-contact-bar";
export default function Home() {
return (
<>
<HeroLocalBusiness
rating={4.9}
reviewCount="640+"
headlinePrefix="Austin plumbers for"
rotatingWords={["burst pipes", "water heaters", "slab leaks", "remodels"]}
description="Licensed, insured and on the way in under an hour across Travis County."
primaryCta={{ label: "Book a visit", href: "/book" }}
phone={{ label: "(512) 555-0147", href: "tel:+15125550147" }}
trustItems={["Licensed and insured", "Same day service", "Upfront pricing"]}
/>
<ServiceArea
heading="Where we work"
checkerLabel="Check your ZIP code"
successMessage={(zip, zone) => `Yes, we serve ${zip}. ${zone.name} is a ${zone.eta ?? "same day"} call.`}
failureMessage={(zip) => `We do not cover ${zip} yet. Join the waitlist and we will let you know.`}
ctaLabel="Request a visit"
ctaHref="/book"
/>
<StickyContactBar phone="512 555 0147" address="2200 S Lamar Blvd, Austin, TX" bookingUrl="/book" />
</>
);
}Every prop in that file exists. rotatingWords is a real prop on the Hero, local business block, successMessage on the Service area block really receives the matched zone, and the Sticky contact bar really builds tel: and sms: links from the phone string and a Google Maps directions link from the address. The agent did not guess any of them, because get_component had shown it the props table a minute earlier.
What the agent gets back
The tool responses are plain text, formatted for a model rather than for a browser. list_components returns one line per item with the slug, kind, category, tier and description. get_component returns the same Markdown page a human can open by adding .md to any component URL. For free items that includes the full source, which matters: the agent can read how the hero rotates words or how the bar hides on scroll and adapt the page around it instead of treating the component as a black box.
For Pro items without a license header the source is withheld and the response says so, with a link to the setup docs. The agent still gets the props and the install command, so it can write correct usage; it just cannot read or modify the internals until the key is in place.
Limits, and prompts that work
The server is a catalog, not a designer. suggest_page knows three page shapes: real estate, agency and local business. It will not invent a block that does not exist, which is the point, but it also means that if your project needs a restaurant menu with reservations, the agent should combine the service menu and the booking picker rather than wait for a "restaurant" suggestion.
Three habits make the results better:
- Name the business and the city. "A dentist in Portland" gives the agent the data for the hero copy and the service area; "a landing page" does not.
- Give real facts. Phone number, address, hours and rating in the prompt turn into props instead of placeholders the client has to find later.
- Ask for the install, then review the page before asking for the next section. Agents are good at wiring props and less good at knowing which block the client will actually want third.
Prompts that have worked for me: "Build a landing page for a dental clinic in Miami using Facade blocks." "Replace our contact form with the Facade multi step lead form and keep our fields." "Add the Facade availability table for units A to D, data from units.json."
The block order the agent follows for home services is the same one documented on the plumber page. If you want to skip the agent entirely, that page has the one line install for the whole set.
FAQ
Does this work in Cursor or Codex too?
Yes. Any client that supports HTTP MCP servers can connect. In Cursor, add { "mcpServers": { "facade": { "url": "https://facadeui.com/api/mcp" } } } to .cursor/mcp.json. The tools and responses are identical.
Does the MCP server change files in my project?
No. It only answers questions. The shadcn CLI, run by the agent in your repository, writes the files. You can inspect every command before it runs, as with any other shell command Claude Code proposes.
Can I run the server locally or self host it?
The server is part of the Facade site, and the free catalog is also published as llms.txt and per component Markdown pages, which agents can read without MCP at all. If you need an offline copy, llms-full.txt contains the full source of every free item in one file.
Components in this article
- Hero, local businessFreeHome services hero with live rating, rotating service words and floating appointment, review and ETA cards.
- Service areaProZone map with numbered service areas, city and ZIP lists, and a ZIP code checker with arrival windows.
- Sticky contact barFreeMobile bottom bar with Call, Text, Directions and Book that hides on scroll down and returns on scroll up.