Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
  1. Home
  2. Blog
  3. Building UI with AI agents
  4. Gemini CLI shadcn MCP Setup for Real React UI
Auf Deutsch lesen
  1. Blog
  2. Building UI with AI agents
  3. Gemini CLI shadcn MCP Setup for Real React UI
Building UI with AI agents
Building UI with AI agents

Gemini CLI shadcn MCP Setup for Real React UI

SR
Serban Rusu · Founder of Wingo UI
Nov 5, 2026 · 11 min read

On this page

0%
  1. Can you still use Gemini CLI in November 2026?
  2. What does a Gemini CLI MCP setup need?
  3. How do I add the shadcn MCP server to Gemini CLI?
  4. How do I connect a component library through settings.json or gemini mcp add?
    1. What does gemini mcp add write?
  5. Why does gemini mcp list say Disabled?
  6. What should GEMINI.md say?
  7. Which prompts get Gemini CLI to build UI from real components?
    1. Prompt 1: a customers table
    2. Prompt 2: a sign-in screen
    3. Prompt 3: swap a hand-written spinner
  8. What goes wrong, and how do I fix it?
  9. Where should I start?
  10. FAQ
    1. Does the shadcn MCP server work with Gemini CLI?
    2. Where does Gemini CLI store MCP servers?
    3. Why does gemini mcp list show my server as Disabled?
    4. Can Gemini CLI read an API key from an environment variable in settings.json?
    5. Is Gemini CLI still available after the move to Antigravity CLI?

TL;DR

To connect Gemini CLI to shadcn or another component registry, add the server under mcpServers in .gemini/settings.json (or run gemini mcp add), trust the folder, and put a rules block in GEMINI.md that says to search before writing UI. For shadcn/ui use npx -y shadcn@latest mcp; for a library with props and blocks, npx wingo-ui@latest agents install gemini writes both files. Check with gemini mcp list: Disabled means an untrusted folder, Disconnected means a bad key or a failed start.

Published Nov 5, 2026

Ask Gemini CLI for a customers table and it writes one from memory: a plain <table>, a hand-rolled filter, a layout that falls apart on a phone. A Gemini CLI shadcn setup fixes that by giving the agent a registry to search and a rules file that tells it to search first. This tutorial connects Gemini CLI to the shadcn MCP server and to a component library with props and full-screen blocks (ours, Wingo UI), through settings.json or gemini mcp add, adds a GEMINI.md block, and ends with prompts that turn into a real data table and a sign-in screen.

We ran every config below on November 5, 2026 with Gemini CLI 0.67.0, shadcn 4.23.0 and our CLI 1.0.4, in a clean project with its own home folder, and checked each one with gemini mcp list. We did not grade model output: what Gemini writes depends on the model and your auth. The config syntax matches Google's MCP server docs (opens in a new tab) and configuration reference (opens in a new tab) as of the same day. Why an agent needs a component server at all is in our component library MCP guide.

Can you still use Gemini CLI in November 2026?

Yes, with the right account. Google's May 19, 2026 announcement (opens in a new tab) moved individual users to Antigravity CLI: Gemini CLI stopped serving Google AI Pro and Ultra subscribers and free Gemini Code Assist users on June 18, 2026. Access stays unchanged for Gemini Code Assist Standard and Enterprise, and the post says Gemini CLI remains available with paid Gemini and Gemini Enterprise Agent Platform API keys.

If you moved to Antigravity CLI, check its own docs for MCP: Google's post does not cover it, and everything below is for Gemini CLI.

What does a Gemini CLI MCP setup need?

Two config files, a trusted folder and a restart:

PieceWhereJob
MCP servers.gemini/settings.json (project) or ~/.gemini/settings.json (user), key mcpServersLets Gemini search registries and read component APIs
RulesGEMINI.md in the project, or ~/.gemini/GEMINI.mdTells Gemini to search before it writes UI, and how to install
Folder trust~/.gemini/trustedFolders.json, set through the trust prompt or /permissionsUntrusted folders skip project settings and MCP servers
A key (optional)WINGO_UI_API_KEY in your shellSource for free or Pro items from our server

Gemini re-reads settings.json when it starts. Inside a session, /mcp shows each server's status and tools, and /memory show prints the GEMINI.md text it loaded.

How do I add the shadcn MCP server to Gemini CLI?

Write the Gemini CLI shadcn MCP entry by hand. shadcn's MCP docs (opens in a new tab) list Claude Code, Cursor, VS Code, Codex and OpenCode for npx shadcn@latest mcp init --client, and Gemini CLI is not among them as of November 5, 2026. The JSON shape is the same one Claude Code and Cursor use, with one change:

json
{
"mcpServers": {
"shadcn": {
"command": "npx",
"args": ["-y", "shadcn@latest", "mcp"]
}
}
}

The -y matters. With shadcn's documented args (["shadcn@latest", "mcp"]) in a project where shadcn was not installed, gemini mcp list showed ✗ shadcn ... Disconnected: npx stops to ask before it downloads a package, and a server started by Gemini has nobody to answer. With -y it showed Connected. shadcn's own mcp init avoids the problem for its clients by installing shadcn as a dev dependency (source (opens in a new tab), checked November 5, 2026), which you can also do.

The shadcn server searches the registries in your components.json and hands back npx shadcn@latest add commands. In our Claude Code shadcn MCP setup it returned no props, so for components with a real API surface you want the library's own server next to it.

How do I connect a component library through settings.json or gemini mcp add?

Our CLI writes both files in one step. In the project root:

bash
npx wingo-ui@latest login # once per computer; a free account needs only an email
npx wingo-ui@latest agents install gemini

In our clean test project, without a key in the environment, it printed:

text
Coding agents (Gemini CLI; MCP over the local stdio proxy)
created GEMINI.md
created .gemini/settings.json

For Gemini the default is the project scope (--scope user writes ~/.gemini/settings.json and ~/.gemini/GEMINI.md instead), and running it again changes nothing. This is the Gemini CLI settings.json MCP entry it writes, in each mode:

json
{
"mcpServers": {
"wingo-ui": {
"command": "npx",
"args": ["-y", "wingo-ui@latest", "mcp"]
}
}
}
json
{
"mcpServers": {
"wingo-ui": {
"httpUrl": "https://wingo-ui.com/mcp",
"headers": { "Authorization": "Bearer ${WINGO_UI_API_KEY}" }
}
}
}

The first runs a local proxy that uses the key saved by login. The second, which the CLI picks when WINGO_UI_API_KEY is set (or with --mcp http), calls the server directly. Gemini resolves ${WINGO_UI_API_KEY} from your environment when it loads the settings, so the file holds only the variable name and is safe to commit.

What does gemini mcp add write?

The same thing, through Gemini's own command. Scope defaults to project, transport to stdio:

bash
# project scope, stdio proxy
gemini mcp add wingo-ui npx -y wingo-ui@latest mcp
# user scope, HTTP; single quotes keep the variable unexpanded in the file
gemini mcp add --scope user --transport http wingo-ui https://wingo-ui.com/mcp \
-H 'Authorization: Bearer ${WINGO_UI_API_KEY}'

Two details from our run. The HTTP form wrote "url" with "type": "http" instead of httpUrl; both connected. And with double quotes, your shell expands the variable before Gemini sees it, which puts the key itself in settings.json.

Why does gemini mcp list say Disabled?

Because the folder is not trusted. Our first gemini mcp list in the new project printed:

text
Warning: MCP servers are configured but disabled because this folder is untrusted.
User-level servers are also suppressed in untrusted folders to prevent accidental side-effects.
Configured MCP servers:
○ wingo-ui: npx -y wingo-ui@latest mcp (stdio) - Disabled

Note the second line: even a server in ~/.gemini/settings.json stays off in an untrusted folder. gemini mcp add in project scope refused outright with "Cannot modify settings in an untrusted workspace". Trust the folder when Gemini asks at startup, or run /permissions in a session; the choice is saved in ~/.gemini/trustedFolders.json. After that:

text
Configured MCP servers:
✓ wingo-ui: npx -y wingo-ui@latest mcp (stdio) - Connected

Then ask one question only the server can answer: "Call get_account_status on the wingo-ui server." Without a key it answers that you are anonymous: docs, props and search work, and no source is sent.

What should GEMINI.md say?

When to search, how to install, and which tokens to use. This is the block agents install wrote, between markers that npx wingo-ui@latest agents update rewrites later:

md
<!-- wingo-ui:start v=3 -->
## Wingo UI
This project builds its UI with Wingo UI (React 19 + Tailwind CSS v4 components installed as source, see `wingo-ui.json`).
- Before writing UI, use the `wingo-ui` MCP tools: `search_components` to find what exists (blocks for whole screens), `get_component` / `get_block` for props and usage, `get_design_rules` for tokens, sizes, motion and mobile rules. Never recreate a component the library has.
- Install with `npx wingo-ui@latest add <slug...>`. At the start of UI work run `check_updates` (or `npx wingo-ui@latest outdated`) and mention updates; update with `npx wingo-ui@latest update`.
- Semantic tokens only (`bg-background`, `bg-surface`, `text-muted-foreground`, `border-border`), configure components through props, keep `cn()`, `data-slot` and license headers in copied files. Check 390px and 1440px, light and dark.
- Never put a card, panel, tile or field on a background of the same or a very similar shade: step the fill (page, `bg-surface`, `bg-foreground/5`). Pages: `PageBackdrop` with a tinted `background` plus bands via `MarketingSection background="muted"`. Border-only designs are the allowed, not recommended exception.
- No MCP tools available? The CLI has `search`, `info`, `add`, `outdated`, `update`; the docs for models are at https://wingo-ui.com/llms.txt.
<!-- wingo-ui:end -->

Per Google's GEMINI.md docs (opens in a new tab), Gemini joins ~/.gemini/GEMINI.md, the files in your workspace and its parent folders, and files it finds next to code it reads, then sends them with every prompt. /memory reload rescans after an edit. If the repository already has an AGENTS.md for Codex, set "context": { "fileName": ["AGENTS.md", "GEMINI.md"] } in settings.json and keep one rules file; our AGENTS.md vs CLAUDE.md comparison has a fuller template.

With both servers in one project, add a line that says which registry owns which folder: shadcn/ui and our library both install a button.tsx with different props, so Gemini has to know which API it is reading.

Which prompts get Gemini CLI to build UI from real components?

For Gemini CLI UI design work, the prompts that work name the screen, the data, and what Gemini should report back. The GEMINI.md rules already send it to search_components, then get_component or get_block, then the install command; the prompt supplies what a rules file cannot: columns, routes and copy. Gemini asks before every MCP tool call by default, even though all 10 of our server's tools are read-only. Add "trust": true to the server entry to skip those prompts, and keep the shell installs on confirm.

Prompt 1: a customers table

text
Build app/customers with the Wingo UI data table. Search first and read its props with get_component.
Columns: name, email, status (Active, Trial, Past due) as a badge with a filter, plan, MRR with a total,
signup date. Multiple selection with an Export CSV bulk action, a Past due quick filter, and each row
opens /customers/<id>. Install it with the CLI and list anything you could not wire.

A search for "users table with filters" on our server lists the Data Table in its top three, next to a members table and an audit log, and its props cover every line of that prompt. The client component we expect back, type-checked against the current release:

tsx
// app/customers/customers-table.tsx
"use client";
import { useRouter } from "next/navigation";
import { DataTable, createColumns } from "@/components/ui/data-table";
export type Customer = {
id: string;
name: string;
email: string;
plan: "Free" | "Pro";
status: "Active" | "Trial" | "Past due";
mrr: number;
signedUpAt: string;
};
const col = createColumns<Customer>();
const columns = col([
col.accessor("name", { header: "Customer", mobile: "title" }),
col.accessor("email", { header: "Email", mobile: "subtitle" }),
col.accessor("status", {
header: "Status",
type: "badge",
badge: { Active: { tone: "success" }, Trial: { tone: "info" }, "Past due": { tone: "danger" } },
filter: "multi-select",
mobile: "meta",
}),
col.accessor("plan", { header: "Plan", filter: "select" }),
col.accessor("mrr", { header: "MRR", type: "currency", footer: "sum" }),
col.accessor("signedUpAt", { header: "Signed up", type: "date" }),
]);
type Props = { customers: Customer[]; onExport: (ids: string[]) => Promise<unknown> };
export function CustomersTable({ customers, onExport }: Props) {
const router = useRouter();
return (
<DataTable
data={customers}
columns={columns}
caption="Customers"
locale="en-US"
selectionMode="multiple"
bulkActions={(_rows, keys) => [{ label: "Export CSV", onSelect: () => onExport(keys) }]}
quickFilters={[{ id: "past-due", label: "Past due", columnFilter: { id: "status", value: ["Past due"] } }]}
onRowClick={(row) => router.push(`/customers/${row.id}`)}
/>
);
}

The mobile roles are the part a model writing from memory skips: below 768px each row becomes a card with the name as its title, and selection starts with a long press.

Tick two rows to see the bulk bar replace the toolbar, then narrow the window below 768px: rows turn into cards and a long press starts selecting
$ npx wingo-ui@latest add data-table
ProData Table docs

Prompt 2: a sign-in screen

text
Build /login from the Wingo UI login-page block, card layout, password and 6 digit email code, no
social buttons. Post to our /api/auth routes, go to /dashboard on success, and replace every
Northwind string in the labels with Harbor. List each handler you left on its sample default.

The Login Page ships sample handlers so its demo runs, and its default labels name Northwind CRM. That is why the prompt asks for a report: without onVerifyCode, the code view accepts 123456 for anyone. In the card layout with two-factor off, appName, signInDescription and copyright are the only Northwind labels on screen; the split layout's hero adds heroLabel, customersTitle and the testimonial, and twoFactor adds twoFactorDescription. A good result:

tsx
// app/login/login-screen.tsx
"use client";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { LoginPage, type SignInValues, type VerifyCodeContext } from "@/components/blocks/login-page";
async function post(path: string, body: unknown) {
const res = await fetch(path, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
// the page shows a rejected promise's message in its error alert
if (!res.ok) throw new Error("That did not work. Check your details and try again.");
}
export function LoginScreen() {
const router = useRouter();
return (
<LoginPage
layout="card"
methods={["password", "otp"]}
showProviders={false}
logo={<span className="text-lg font-semibold">Harbor</span>}
labels={{
appName: "Harbor",
signInDescription: "Sign in to your Harbor account to continue.",
copyright: "© 2026 Harbor Inc.",
}}
onSignIn={(values: SignInValues) => post("/api/auth/sign-in", values)}
onSendCode={(email) => post("/api/auth/send-code", { email })}
onVerifyCode={(code: string, context: VerifyCodeContext) => post("/api/auth/verify-code", { code, ...context })}
onForgot={(email) => post("/api/auth/forgot", { email })}
onReset={(password) => post("/api/auth/reset", { password })}
onSuccess={() => router.push("/dashboard")}
linkComponent={(props) => <Link {...props} />}
/>
);
}
Type any email and a password shorter than 8 characters to see the error alert, then open Forgot password: the email carries over
$ npx wingo-ui@latest add login-page
ProLogin Page docs

Prompt 3: swap a hand-written spinner

text
Find every button in app/account that renders its own spinner while saving and replace it with the
Wingo UI button. Read its props with get_component first and show me the diff.

Our Button has a loading prop, so the spinner markup and the disabled juggling go away:

tsx
import { Button } from "@/components/ui/button";
export function SaveButton({ saving, onSave }: { saving: boolean; onSave: () => void }) {
return (
<Button tone="brand" loading={saving} loadingText="Saving" onClick={onSave}>
Save changes
</Button>
);
}

What goes wrong, and how do I fix it?

  • Disabled in gemini mcp list. Untrusted folder. Trust it, then list again.
  • Disconnected over HTTP. With a made-up key in WINGO_UI_API_KEY, our server refused the connection and Gemini showed ✗ ... Disconnected. Check the key on your account's API keys page, or switch to the proxy with npx wingo-ui@latest agents install gemini --mcp stdio.
  • Connected, but no source. With the variable missing, Gemini sent an empty bearer token and connected anonymously. Export the key in the shell profile of the terminal that starts Gemini, then restart it.
  • Disconnected over stdio. Usually npx waiting for an install answer: add -y to args, as above.
  • Pro blocks with a free key. get_block still returns props and usage for login-page, and npx wingo-ui@latest add login-page stops because the block is part of Pro. The Button is free; the Data Table and Login Page are Pro ($8 a month, $80 a year or $150 once, on the pricing page).
  • Server names with underscores. Gemini prefixes tools as mcp_<server>_<tool> and its docs warn that underscores in a server name can break policy matching. Keep wingo-ui and shadcn as they are.

Where should I start?

Create a free account, run npx wingo-ui@latest agents install gemini in your project, trust the folder and try prompt 3 on the free Button. The MCP server docs list every tool and the coding agents docs cover the --scope and --mcp options. The same setup for other agents is in our Codex MCP setup, the Copilot shadcn setup for VS Code and the rest of Building UI with AI agents.

Components in this post

  • Button

    The React button component every screen starts with: five variants, six tones, all sizes, and a loading state that never jumps.

    Free
  • Data Table

    A React data table on TanStack Table: search, filters, sorting, bulk actions, pinning, resizing, virtualization and cards on phones.

    Pro
  • Login Page

    A React login page with password, magic link or code sign-in, Google, Apple and Microsoft buttons, two-step codes and password recovery.

    Pro

FAQ

Does the shadcn MCP server work with Gemini CLI?

Yes, through a manual entry in .gemini/settings.json. shadcn's mcp init command does not list Gemini CLI as a client (as of November 2026), so add the server under mcpServers with command npx and args -y, shadcn@latest, mcp.

Where does Gemini CLI store MCP servers?

Under mcpServers in settings.json: ~/.gemini/settings.json for every project, or .gemini/settings.json in the project. gemini mcp add writes to the project file by default; --scope user picks the home file.

Why does gemini mcp list show my server as Disabled?

The folder is not trusted. With folder trust on, Gemini CLI ignores the project settings and suppresses user-level servers too in an untrusted folder; trust it when Gemini asks or through /permissions, and the server connects.

Can Gemini CLI read an API key from an environment variable in settings.json?

Yes. String values in settings.json can reference $VAR or ${VAR}, which Gemini resolves when it loads the settings, so a header like Authorization: Bearer ${WINGO_UI_API_KEY} keeps the key out of the file.

Is Gemini CLI still available after the move to Antigravity CLI?

For some users. Google's May 19, 2026 post says it stopped serving Google AI Pro, Ultra and free Code Assist users on June 18, 2026, and stays available with Code Assist Standard or Enterprise and with paid Gemini API keys.

Try it in your project

Button

Free

The React button component every screen starts with: five variants, six tones, all sizes, and a loading state that never jumps.

75 components free, no account needed. Pro from $8 a month.

Open Button liveSee pricing
  • Gemini CLI
  • MCP
  • shadcn/ui
  • GEMINI.md
  • AI agents

Share

SR

About the author

Serban Rusu

Founder of Wingo UI

Serban Rusu founded Wingo UI. He builds its component library, CLI and MCP server, and writes about React interfaces for phones and AI coding agents.

More from Serban
Keep reading

Related posts

All posts
Building UI with AI agents

Antigravity MCP Setup: The Right Config Path and Prompts

Antigravity MCP setup tested on November 6, 2026: where mcp_config.json lives, remote vs npx entries, reloading, and prompts that install real components.

SRSerban Rusu·Nov 6, 2026·10 min read
Building UI with AI agents

Component Library MCP: Make Agents Use Real Components

How a component library MCP server, rules files, llms.txt and a registry get Claude Code, Cursor and Codex to install real components instead of guessing.

SRSerban Rusu·Oct 9, 2026·27 min read
Comparisons and alternatives

Is shadcn Free for Commercial Use? MIT vs Paid Kits

Is shadcn free for commercial use? Yes: shadcn/ui is MIT licensed. What MIT asks of you, why paid shadcn kits have their own terms, and how to choose.

SRSerban Rusu·Nov 6, 2026·10 min read
Newsletter

Get new posts by email

New posts, product news and occasional offers from Wingo UI. We count clicks to keep it relevant.

No spam. Unsubscribe at any time.

WingoUI

Animated, configurable, mobile-first React components and blocks. Copy the source, make it yours, and let your coding agent build with it.

Product

  • Components
  • Templates
  • Pricing
  • AI agents
  • For teams
  • Theme generator

Resources

  • Docs
  • Contact
  • Programs
  • Blog
  • Changelog
  • Changelog RSS
  • llms.txt

Compare

  • Wingo UI vs paid kits
  • Wingo UI vs shadcn/ui
  • shadcn/ui alternatives
  • MUI alternatives
  • Tailwind Plus alternatives
  • Magic UI alternatives
  • Free components

Legal

  • Terms
  • Privacy
  • Refunds
  • License
  • Imprint

Component categories

  • Buttons & Actions
  • Inputs
  • Forms
  • Navigation
  • Overlays
  • Feedback
  • Data Display
  • Tables & Lists
  • Charts & Stats
  • Layout
  • Media
  • AI Kit
  • Text & Effects
  • Mobile
  • Commerce
  • Marketing Sections
  • Blocks
  • Hooks & Utilities

© 2026 Wingo UI

Wingo UI