Skip to main content
Glama
arindhimar

UIWeaver MCP

by arindhimar
README.md
# UIWeaver MCP

> **An AI-powered Model Context Protocol server** that runs inside Claude Desktop.  
> Give it a prompt — get production-ready React + Tailwind UI, 3D components, real 3D model embeds, or a fully integrated frontend ↔ backend codebase.

---

## What is UIWeaver?

UIWeaver connects Claude Desktop to Google Gemini and your local filesystem. It is a **9-tool MCP server** that can:

- Generate polished React + Tailwind UI from a text description
- Analyze existing components for accessibility and quality issues
- Auto-fix those issues and return a health score
- Scan an existing React/Next.js project and analyze every file
- Preview and apply code changes to your project on disk
- Generate high-detail **CSS 3D components** (no WebGL — runs on any device)
- Search Sketchfab for real 3D models and return a ready-to-use React embed
- Connect a frontend with dummy data to a real backend API automatically

All of this is triggered by natural language inside Claude Desktop — no manual coding required.

---

## Project Structure

```
UI-Weaver/
├── run_server.py                  ← Entry point Claude Desktop calls
├── requirements.txt               ← Python dependencies
├── .env.example                   ← Template for your API key
├── README.md                      ← This file
│
└── uiweaver_mcp/                  ← Main package
    ├── __init__.py
    ├── server.py                  ← All 9 MCP tools registered here
    ├── config.py                  ← Loads GEMINI_API_KEY from .env
    ├── .env                       ← Your actual API key (never commit this)
    │
    ├── schemas/
    │   └── project.py             ← Component, Page, Project dataclasses
    │
    ├── services/
    │   ├── gemini_service.py      ← Sends prompts to Gemini, parses responses
    │   ├── analysis_service.py    ← Checks components for issues
    │   ├── refinement_service.py  ← Auto-fix loop
    │   ├── file_service.py        ← Read/write/diff files on disk
    │   ├── threed_service.py      ← CSS 3D component generation
    │   ├── model_search_service.py← Sketchfab search + React embed generation
    │   └── integration_service.py ← Frontend ↔ Backend integration
    │
    └── utils/
        └── scoring.py             ← Health score calculator
```

---

## Setup Guide

### Prerequisites

| Requirement | Version | Notes |
|---|---|---|
| Python | 3.10+ | [python.org](https://www.python.org/downloads/) |
| Claude Desktop | Latest | [claude.ai/download](https://claude.ai/download) |
| Gemini API Key | — | Free at [aistudio.google.com](https://aistudio.google.com/app/apikey) |

---

### Step 1 — Clone / download the project

```
UI-Weaver/
```

Make sure the folder is at a path with no spaces, or quote it everywhere.

---

### Step 2 — Install dependencies

Open a terminal in the `UI-Weaver` folder:

```powershell
# Windows
pip install -r requirements.txt

# macOS / Linux
pip3 install -r requirements.txt
```

Verify the key packages installed:

```powershell
python -c "import mcp; import google.genai; print('OK')"
```

---

### Step 3 — Add your Gemini API key

1. Get a free key at [https://aistudio.google.com/app/apikey](https://aistudio.google.com/app/apikey)
2. Copy `.env.example` to `uiweaver_mcp/.env`
3. Open `uiweaver_mcp/.env` and replace the placeholder:

```env
GEMINI_API_KEY=AIzaSy...your_real_key_here
```

---

### Step 4 — Register UIWeaver in Claude Desktop

Open (or create) this file:

- **Windows:** `C:\Users\<you>\AppData\Roaming\Claude\claude_desktop_config.json`
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`

Paste this (update the paths to match your system):

```json
{
  "mcpServers": {
    "UIWeaver": {
      "command": "C:\\Users\\<you>\\AppData\\Local\\Programs\\Python\\Python310\\python.exe",
      "args": ["C:\\Users\\<you>\\Documents\\UI-Weaver\\run_server.py"],
      "env": {
        "GEMINI_API_KEY": "AIzaSy...your_real_key_here"
      }
    }
  }
}
```

> **macOS / Linux** — use forward slashes and the output of `which python3`:
> ```json
> {
>   "mcpServers": {
>     "UIWeaver": {
>       "command": "/usr/bin/python3",
>       "args": ["/Users/<you>/Documents/UI-Weaver/run_server.py"],
>       "env": { "GEMINI_API_KEY": "AIzaSy..." }
>     }
>   }
> }
> ```

---

### Step 5 — Restart Claude Desktop

Fully quit and reopen Claude Desktop. Open a new conversation and look for the **hammer icon** (🔨) in the bottom of the chat input. Click it — you should see **UIWeaver** listed with 9 tools.

---

### Verify everything works

In Claude Desktop, type exactly:

```
Use generate_ui_tool to make a simple button component
```

If it responds with a React component with Tailwind classes, everything is working.

---

## The 9 Tools — Reference + Example Prompts

---

### 1. `generate_ui_tool`

**What it does:** Generates a complete React + Tailwind CSS project from a text description. Produces proper TypeScript functional components with interfaces, JSX, Tailwind classes, accessibility attributes — ready to paste into any Next.js or Vite project.

**Key behavior:**
- Runs 2 refinement iterations automatically
- Returns a health score (0–100) based on accessibility and code quality
- Each component starts with `import React` and uses `export default function`

**Example prompts:**

```
Use generate_ui_tool to create a SaaS pricing page with three tiers 
(Starter $9/mo, Pro $29/mo, Enterprise custom), a feature comparison 
table below, and a FAQ section. Dark navy background, violet accent.
```

```
Use generate_ui_tool to build a job board listing page with filters 
on the left sidebar (role type, location, salary range), job cards 
in the main area showing company logo placeholder, title, location, 
salary, and an Apply button. Clean minimal design.
```

```
Use generate_ui_tool to make a user profile settings page with tabs 
for General, Security, Notifications, and Billing. Each tab has a 
form with save button. Slate background, white cards.
```

**Output shape:**
```json
{
  "title": "...",
  "health_score": 94,
  "components": [
    { "name": "PricingCard", "code": "import React..." }
  ],
  "pages": [...],
  "styles": { "primaryColor": "#7c3aed" }
}
```

---

### 2. `analyze_ui_tool`

**What it does:** Takes a single component's code as a string and returns a list of issues with severity levels, plus a health score.

**Issue types detected:**
| Type | Severity | Trigger |
|---|---|---|
| Missing aria attribute | High | No `aria-` attribute found |
| Component too large | Medium | Code > 2000 characters |
| No Tailwind classes | Low | No `className` or `tailwind` keyword |

**Example prompts:**

```
Use analyze_ui_tool on this component code:
[paste your component code here]
```

```
I have a React button component — use analyze_ui_tool to check it 
for accessibility issues. Here's the code: [paste code]
```

**Output shape:**
```json
{
  "health_score": 70,
  "issues": [
    { "type": "missing_aria", "severity": "high", "component": "Button", "description": "..." }
  ]
}
```

---

### 3. `refine_ui_tool`

**What it does:** Takes component code, runs analysis, auto-fixes every issue it finds, and returns the improved code. Loops up to 3 times until no issues remain or iterations are exhausted.

**Auto-fixes applied:**
- Injects `aria-label="auto-fixed"` into the first JSX tag if aria is missing
- Truncates code that exceeds safe length limits

**Example prompts:**

```
Use refine_ui_tool to fix this component: [paste code]
```

```
My Navbar component has accessibility issues. Use refine_ui_tool 
to auto-fix it: [paste code]
```

**Output shape:**
```json
{
  "health_score": 100,
  "iterations": 2,
  "issues_remaining": 0,
  "components": [
    { "name": "Navbar", "code": "import React..." }
  ]
}
```

---

### 4. `scan_project`

**What it does:** Walks an entire React/Next.js project folder, reads every `.tsx/.jsx/.ts/.js` file (skipping `node_modules`, `.next`, `dist`), runs analysis on each one, and returns a full health report.

**Example prompts:**

```
Use scan_project on C:\Users\Arin\my-nextjs-app to give me a 
health report of all my components
```

```
Scan my frontend project at /Users/arin/projects/dashboard using 
scan_project and tell me which files have the most issues
```

**Output shape:**
```json
{
  "folder": "...",
  "total_files": 24,
  "health_score": 81,
  "total_issues": 7,
  "files": [
    { "name": "Sidebar.tsx", "path": "src/components/Sidebar.tsx", "issues": [...] }
  ]
}
```

---

### 5. `preview_changes`

**What it does:** Shows a line-by-line diff of what would change in a specific file **without writing anything to disk**. Always use this before `apply_changes`.

**Example prompts:**

```
Use preview_changes on my project at C:\my-app, component name 
"Sidebar", with this new code: [paste updated code]
```

```
Before writing anything, use preview_changes to show me the diff 
for Header.tsx in C:\projects\my-site with this updated version: 
[paste code]
```

**Output shape:**
```json
{
  "status": "update",
  "file": "src/components/Sidebar.tsx",
  "full_path": "C:/my-app/src/components/Sidebar.tsx",
  "diff": "+ import { useState } from 'react';\n- const items = [{id:1...}]...",
  "original_size": 1240,
  "new_size": 890
}
```

---

### 6. `apply_changes`

**What it does:** Writes updated component code to disk. Creates directories if they don't exist. Always run `preview_changes` first.

**Example prompts:**

```
The diff looks good. Use apply_changes to write it — 
full_file_path is C:\my-app\src\components\Sidebar.tsx, 
here's the new code: [paste code]
```

```
Apply the changes using apply_changes to 
C:\projects\dashboard\src\pages\index.tsx with this code: [paste]
```

**Output shape:**
```json
{
  "status": "success",
  "file": "C:/my-app/src/components/Sidebar.tsx",
  "bytes_written": 3241,
  "message": "File written successfully"
}
```

---

### 7. `generate_3d_tool`

**What it does:** Generates a high-detail CSS 3D React component using `perspective`, `transform-style: preserve-3d`, and `translateZ`. **No Three.js, no WebGL** — runs at 60fps on integrated graphics and budget laptops.

**Available 3D techniques:**

| Technique | Description |
|---|---|
| `tilt-card` | Card tilts in 3D as the mouse moves over it |
| `flip-card` | Hover/click reveals the back face |
| `depth-layers` | Multiple `translateZ` layers create parallax depth |
| `floating` | Element bobs in 3D space with a CSS keyframe loop |
| `isometric` | CSS-only isometric cube with shaded faces |
| `depth-extrusion` | Stacked `box-shadow` values simulate 3D extrusion |

**Example prompts:**

```
Use generate_3d_tool to make an interactive tilt card showing 
monthly revenue $48,291 with a floating +12% growth badge. 
Dark slate background, violet glow accent.
```

```
Use generate_3d_tool to create a 3D flip card — front shows 
a team member photo placeholder, name, and role. Back shows 
their 3 skills and a "Contact" button. Dark glassmorphism style.
```

```
Use generate_3d_tool to build an isometric stats display with 
3 cubes showing Users, Revenue, and Uptime metrics. Each cube 
has a different height based on the value. Emerald and amber theme.
```

```
Use generate_3d_tool to make a floating product card for wireless 
headphones. The card levitates, has depth layers showing the product 
details, with a subtle glow shadow underneath.
```

**Output shape:**
```json
{
  "title": "Revenue Tilt Card",
  "technique": "tilt-card",
  "dependencies": ["react"],
  "performance": "60fps on integrated graphics",
  "quality_report": { "health_score": 100, "issues": [] },
  "components": [
    { "name": "RevenueTiltCard", "code": "import React, { useState }..." }
  ],
  "usage": "<RevenueTiltCard />"
}
```

---

### 8. `search_and_embed_3d`

**What it does:** Searches Sketchfab's public database of millions of free 3D models, finds the best match, and generates two ready-to-use React components for it.

**Two component options generated:**

| Option | How it works | Setup needed |
|---|---|---|
| `iframe_embed` | Embeds Sketchfab's viewer — works immediately | Nothing |
| `model_viewer` | Google's `<model-viewer>` — just the model, no Sketchfab UI | Download `.glb` + `npm install @google/model-viewer` |

**Example prompts:**

```
Use search_and_embed_3d to find a 3D model of a raspberry pi board
```

```
Use search_and_embed_3d to find a wooden office chair 3D model
```

```
Use search_and_embed_3d to find an astronaut helmet 3D model, pick=1
```

```
Use search_and_embed_3d for a sports car model — I want to embed 
it on a product landing page
```

**Output shape:**
```json
{
  "model_found": {
    "name": "Raspberry Pi cam v2.1",
    "author": "F2A",
    "license": "CC Attribution",
    "likes": 85,
    "sketchfab_page": "https://sketchfab.com/...",
    "download_page": "https://sketchfab.com/...#download"
  },
  "components": {
    "iframe_embed": { "code": "import React..." },
    "model_viewer":  { "code": "import React...", "setup_steps": [...] }
  },
  "recommendation": "Start with iframe_embed..."
}
```

> **Tip:** If the first result isn't what you want, add `pick=1` or `pick=2` to get the next result.

---

### 9. `integrate_frontend_backend`

**What it does:** The most powerful tool. Give it:
1. Your frontend folder (React/Next.js with hardcoded dummy data)
2. Your backend folder (Express/FastAPI/Flask/Django)
3. Your API spec (plain text or OpenAPI JSON)

It auto-detects backend routes, finds every frontend file with dummy/hardcoded data, and uses Gemini to rewrite each file — replacing fake data with real `fetch()` calls, adding TypeScript interfaces, loading skeletons, and error handling.

**Backend frameworks supported:** Express, Fastify, FastAPI, Flask, Django

**Dummy data patterns it detects:**
- `const items = [{id: 1, name: "John"}, ...]`
- `useState([{...hardcoded objects...}])`
- Strings containing `placeholder`, `dummy`, `mock`, `fake`
- Comments like `// TODO: replace with API call`

**Transformations applied per file:**
- Replaces hardcoded arrays with `useState<Type[]>([])`
- Adds `useEffect` with `fetch()` to the correct endpoint
- Adds `const [loading, setLoading] = useState(true)`
- Adds `const [error, setError] = useState<string | null>(null)`
- Adds loading skeleton (animated pulse)
- Adds error banner
- Adds TypeScript interfaces matching API response shapes
- Uses `process.env.NEXT_PUBLIC_API_URL` as base URL

**Recommended workflow — always dry run first:**

**Step 1 — Dry run (default):**
```
Use integrate_frontend_backend with:
  frontend_folder = C:\my-app\frontend
  backend_folder  = C:\my-app\backend
  api_spec        = "GET /api/users → returns [{id, name, email, role}]
                     POST /api/users → body {name, email}, returns created user
                     DELETE /api/users/:id → returns {success: true}
                     GET /api/products → returns [{id, title, price, stock}]"
```

**Step 2 — Review the diffs** in the response. Each file shows exactly what lines change.

**Step 3 — Apply when satisfied:**
```
Use integrate_frontend_backend with the same folders and spec 
but apply=true
```

**With OpenAPI JSON:**
```
Use integrate_frontend_backend. frontend_folder = C:\my-app\frontend, 
backend_folder = C:\my-app\backend, api_spec = [paste your full 
OpenAPI/Swagger JSON here]
```

**With a separate output folder (keeps originals untouched):**
```
Use integrate_frontend_backend with apply=true and 
output_folder = C:\my-app\frontend-integrated
```

**Output shape:**
```json
{
  "status": "dry_run",
  "summary": {
    "backend_framework": "fastapi",
    "routes_found": 12,
    "files_with_dummy_data": 5,
    "files_integrated": 5,
    "errors": []
  },
  "backend_routes": [
    { "method": "GET", "path": "/api/users", "file": "routers/users.py" }
  ],
  "integrations": [
    {
      "file": "src/pages/users.tsx",
      "changes_summary": [
        "Replaced hardcoded users array with useState<User[]>([])",
        "Added useEffect fetching GET /api/users",
        "Added User TypeScript interface",
        "Added loading skeleton",
        "Added error banner"
      ],
      "api_calls_added": [
        { "method": "GET", "endpoint": "/api/users", "trigger": "on component mount" }
      ],
      "env_vars_needed": ["NEXT_PUBLIC_API_URL=http://localhost:8000"],
      "diff": "+ const [users, setUsers] = useState<User[]>([]);\n- const users = [{id:1..."
    }
  ]
}
```

---

## Typical Workflows

### Build a new UI from scratch
```
1. Use generate_ui_tool to create [your UI description]
2. Use refine_ui_tool on any component that needs improvement
3. Use apply_changes to write the components to your project
```

### Audit an existing project
```
1. Use scan_project on [your project folder]
2. For each file with issues, use refine_ui_tool to fix it
3. Use preview_changes to review → apply_changes to write
```

### Add a 3D section to a landing page
```
1. Use generate_3d_tool to create [your 3D component description]
2. Use apply_changes to write it to your components folder
3. Import it into your page
```

### Embed a product's real 3D model
```
1. Use search_and_embed_3d to find [product name] 3D model
2. Use the iframe_embed component immediately, or:
3. Download the .glb → use the model_viewer component for production
```

### Connect dummy frontend to real backend
```
1. Use integrate_frontend_backend (dry run) to preview all changes
2. Review all diffs carefully
3. Use integrate_frontend_backend with apply=true to write
4. Add the .env vars listed in the output
5. Restart your dev server and test in the browser
```

---

## Troubleshooting

### UIWeaver doesn't appear in Claude Desktop

1. Open `claude_desktop_config.json` and check for JSON syntax errors (missing comma, extra bracket)
2. Make sure `python.exe` path is correct — run it in a terminal to verify
3. Fully quit Claude Desktop (system tray → Quit, not just close window) and reopen
4. In a terminal, run `python run_server.py` directly — if it errors, fix that first

### "No module named 'uiweaver_mcp'" error

The `run_server.py` wrapper handles this automatically by adding the project root to `sys.path`. If you see this error, make sure Claude Desktop is calling `run_server.py` — not `server.py` directly.

### "GEMINI_API_KEY not set" error

Check two places:
- `uiweaver_mcp/.env` has `GEMINI_API_KEY=your_key`
- `claude_desktop_config.json` `"env"` block also has the key

Either location works. The `env` block in the config takes priority.

### Gemini returns HTML instead of React components

In your Claude prompt, be explicit: say **"Use generate_ui_tool"** and include **"React component"** in your description. Example:

```
Use generate_ui_tool to create a React component for a login form
```

### `scan_project` finds no files

Make sure the folder path uses forward slashes or escaped backslashes, and that the path points to the **project root** (the folder containing `src/` or `pages/`), not a subfolder.

### `integrate_frontend_backend` finds no dummy data

The scanner looks for specific patterns. If your data doesn't match, manually identify the files and use `generate_ui_tool` + `apply_changes` to rewrite them manually.

---

## Tech Stack

| Layer | Technology |
|---|---|
| MCP Framework | `mcp` 1.6.0 (FastMCP, stdio transport) |
| AI Model | Google Gemini 2.0 Flash |
| Language | Python 3.10+ |
| Claude Desktop | MCP client (calls UIWeaver's tools) |
| 3D Models | Sketchfab public API + Google model-viewer |
| Output format | React + TypeScript + Tailwind CSS |

---

## License

MIT — use it, fork it, build on it.

---

*Built with UIWeaver itself.*