Agy Ui
БесплатноНе проверенDelegates frontend/UI refinement to Gemini via agy CLI, using iterative vision loops and diff-gating to realign UIs to design mockups without affecting backend
Описание
Delegates frontend/UI refinement to Gemini via agy CLI, using iterative vision loops and diff-gating to realign UIs to design mockups without affecting backend code.
README
An MCP (Model Context Protocol) server that delegates frontend / UI work to
Google Antigravity's agy CLI (Gemini) - while guaranteeing the agent
never touches backend, API, or business logic. It is designed to be shared
by Claude Code and Codex as a dedicated "FE/UI worker".
The server exposes two tools:
ui_implement- an iterative vision loop: screenshot the running app, promptagyto edit CSS/components toward the target design, diff-gate the result to revert anything out of scope, re-screenshot, and repeat until it converges (or hitsmax_iters). Edits are applied to your working tree.ui_review- serve the app, screenshot it across every target (route × device × theme × state), optionally run accessibility checks, and haveagycritique it read-only (any editagymakes is reverted).
What it can drive
| Surface | Platform values | How it's captured |
|---|---|---|
| Web apps | web (default) |
Playwright (Chromium) over the dev-server URL |
| Mobile web-targets | expo-web, ionic, flutter-web |
Playwright (same as web) |
| Native iOS | ios-sim |
flutter run on the iOS Simulator + xcrun simctl screenshots |
| Native Android | android-emu |
flutter run on an Android emulator + adb screenshots |
Across these it supports responsive viewports, device emulation, dark mode /
prefers-color-scheme, forced-colors (high contrast), print media, RTL,
component states (via pre_steps), seeded localStorage, per-target design
references, and match-score convergence when design references are provided.
Accessibility: for web targets, ui_review injects the vendored
axe-core into the page and returns
structured WCAG violations (per target), which also ground agy's critique.
Use case: realign a drifted frontend
The case this server is built for: you (or Claude Code / Codex) shipped a
full-stack project - backend and frontend both done - but the FE drifted
from, or doesn't match, the original design (screen mockups, or design tokens
with an HTML/CSS demo). You want to redo the FE to match the design without
risking the working backend. That is exactly what the diff-gate guarantees:
agy realigns the UI, and anything outside your FE allow scope (API, server,
business logic) is reverted automatically.
What it's strong at vs. where it needs help - this is an iterative refinement loop, not a from-scratch FE generator:
| Your FE today | Fit |
|---|---|
| Structure is right, styling/layout/colors/spacing/responsive is off | Great - its core job; realistically ~80-90% then human polish |
| Partly wrong (a few components / screens drifted) | Good - run it screen by screen with the matching design_ref |
| Structurally wrong (wrong component tree, missing screens, wrong layout) | Partial - it nudges existing code toward the design within scope; it does not rebuild markup from scratch. Have Claude Code/Codex scaffold the correct structure first, then use this server to drive pixel fidelity |
Fidelity is highest when you provide an HTML/CSS demo or design tokens (exact
colors/spacing/fonts) rather than an image alone (values are inferred from
pixels). Note the convergence score is agy's own visual self-assessment -
always eyeball the returned shots_before/shots_after and diff to sign off.
Workflow
- Commit your current state (a dirty tree is fine - it's snapshotted and preserved; the only requirement is a git repo with ≥1 commit).
- Drop a
.agy-ui-scopethat allows only FE files and denies the backend, declares how to serve the app, and lists one target per screen with that screen'sdesign_ref(see below). - Run
ui_implementper screen with its design ref; reviewshots_before/shots_after+diff, then iterate (max_iters). - Run
ui_review(read-only + a11y) to haveagycritique what's left and surface WCAG issues. - Human-polish the last ~10-20% and anything structural the loop can't reach within scope.
Sample config - a Vite/React app, realigned screen-by-screen against
mockups in ./design/:
model: "gemini-3.5-flash"
platform: web
# FE surface agy may edit/create.
allow:
- "src/**/*.css"
- "src/**/*.scss"
- "src/components/**"
- "src/**/*.tsx"
- "index.html"
# Backend / logic - always reverted, even if agy edits them.
deny:
- "**/api/**"
- "**/server/**"
- "**/*.server.*"
- "**/route.*"
# Sensitive entry points - reverted AND reported for a human to decide.
ambiguous:
- "src/main.tsx"
- "src/App.tsx"
- "vite.config.*"
serve:
cmd: "npm run dev"
url: "http://localhost:5173"
ready_timeout: 30
devices:
desktop: { width: 1440, height: 900 }
mobile: { name: "iPhone 13" } # full Playwright device emulation
# One capture per screen, each matched against its own design mockup.
# (targets supersedes the simple `viewports` list when present.)
targets:
- name: "home-desktop"
route: "/"
device: "desktop"
design_ref: "./design/home-desktop.png" # image OR an HTML/CSS demo render
- name: "dashboard-desktop"
route: "/dashboard"
device: "desktop"
design_ref: "./design/dashboard-desktop.png"
- name: "settings-mobile-dark"
route: "/settings"
device: "mobile"
color_scheme: "dark" # emulate prefers-color-scheme: dark
design_ref: "./design/settings-mobile-dark.png"
Then drive each screen, e.g. ui_implement(project_dir=".", task="Match this screen to its design_ref", target_route="/dashboard"). Targets
carry the per-screen mockup; target_route picks which one to work on.
Platform support
The server runs on macOS and Linux. It spawns agy (and native
flutter run) through a Unix pseudo-terminal (pty) and manages process groups
with POSIX-only calls, so native Windows is not supported - run it under
WSL2 (Windows Subsystem for Linux) instead.
| OS | Web + mobile web-targets | Native Android | Native iOS |
|---|---|---|---|
| macOS | yes | yes | yes |
| Linux | yes | yes | no (iOS needs macOS + Xcode) |
| Windows (native) | no | no | no |
| Windows via WSL2 | yes | with adb/emulator setup | no |
Notes:
- iOS always requires macOS + Xcode, regardless of host OS.
- WSL2: install the Linux build of
agy(and log in) and runplaywright install chromiuminside WSL. Web and mobile web-targets work out of the box; native Android additionally needsadb/emulator wiring (e.g. connecting to a Windows-side emulator over TCP, or running the emulator inside WSL2). - A native-Windows port would require replacing the
ptylayer with ConPTY (e.g.pywinpty) and the POSIX process-group calls; it is not implemented.
How it works
- PTY spawn.
agyis run asagy -p "<prompt>"through a Python pseudo-terminal (pty.openpty+subprocess.Popen), becauseagydrops its stdout when attached to a non-TTY pipe. Output is captured from the PTY master; ANSI escapes and carriage returns are stripped. - Subscription auth.
agyauthenticates via your existing Gemini subscription/login - noGEMINI_API_KEYis passed by this server. - Diff-gate (the real guardrail). Scope is not enforced inside
agy. Web runs happen in a throwaway git worktree; after each turn the server classifies every changed path against your scope (deny > ambiguous > allow > default-deny) and reverts anything not allowed (ambiguous paths are reverted and reported as escalations). A staged edit is restored from the baseline, not the index, so it cannot slip through. - Vision loop. The orchestrator (this server) screenshots to files with
Playwright, embeds those paths in the prompt (
agyopens them with its ownread_filetool - there is no image flag), letsagyedit, applies the diff-gate, re-screenshots, and loops. - Native runs. Native platforms run in place (no worktree, to reuse the
build cache).
flutter runis launched under a PTY and hot-reloaded (r) between iterations - with an automatic hot-restart (R) fallback when a reload produces no visual change. A graceful quit (q) lets Flutter release its lockfile cleanly. - In-place safety (snapshot-restore). Before a native run, the server
snapshots your project's current state into a dangling git baseline commit
(without touching your index/HEAD/worktree) and records your pre-existing
untracked files. The diff-gate and reverts compare against that baseline, so
only
agy's edits are gated/undone and your uncommitted work is preserved exactly - you do not need to commit or stash first. The only hard requirement is that the project is a git repo with at least one commit; if it isn't, the tool returns a structured{"status": "blocked", ...}result explaining how to fix it (e.g.git init) instead of running unprotected.
Requirements
- Python ≥ 3.10
- The
agyCLI, installed and logged in (subscription auth) - Playwright Chromium for web/a11y captures - auto-installed on first use
(or set
AGY_UI_CHROME_CHANNEL=chrometo reuse an already-installed Chrome); not needed for native-only use .agy-ui-scopeis optional - it is auto-detected from your stack when absent. Runui_initto generate one, and seetemplates/agy-ui.rule.mdfor the recommended agent rule block- Native iOS (
ios-sim): macOS + Xcode + a Flutter project, and a booted iOS Simulator - Native Android (
android-emu): the Android SDK platform-tools (adb) and an AVD; the adapter can auto-launch the AVD by name (emulator -avd <name>)
Install
One-liner (easiest)
Runs a self-contained installer straight from the internet (no clone needed). It installs the server, tries to install Chromium, and offers to register with Claude Code:
curl -fsSL https://raw.githubusercontent.com/qdzsh/agy-ui-mcp/main/scripts/bootstrap.sh | bash
From PyPI (recommended)
# 1. Install the server (gives you an `agy-ui-mcp` command on PATH)
pipx install agy-ui-mcp
# or: uv tool install agy-ui-mcp
# 2. Register it with Claude Code
claude mcp add agy-ui --scope user -- agy-ui-mcp
From GitHub (latest main)
To install the latest unreleased changes straight from the repo:
pipx install git+https://github.com/qdzsh/agy-ui-mcp
# or: uv tool install git+https://github.com/qdzsh/agy-ui-mcp
The Chromium browser auto-installs on first use, so there is no manual
playwright install chromium step. (To reuse an already-installed Chrome and
skip the download, set AGY_UI_CHROME_CHANNEL=chrome.)
From a clone (one command)
git clone https://github.com/qdzsh/agy-ui-mcp.git && cd agy-ui-mcp
./scripts/install.sh # installs the package + Chromium, and offers to
# register with Claude Code
scripts/install.sh is interactive and idempotent; re-run it any time.
Zero-config quick start
You do not need a .agy-ui-scope file to get going - the server
auto-detects your stack (Vite/React, Next.js, Expo, Ionic, CRA, Flutter-web, or
generic web) and synthesizes a scope on the fly. The minimal flow:
Install (any option above).
Log into
agyonce (subscription auth - no API key).Drop a mockup image into your project, e.g.
./design/home.png.Ask the agent to match it by calling:
ui_implement(project_dir=".", task="Match the running home screen to this mockup", design_refs=["./design/home.png"], target_route="/")
That is enough for the loop to run with zero config files. When you want to
customize the scope (allow/deny globs, per-screen targets, serve command),
call ui_init(project_dir=".") once to detect your stack and write a real,
inspectable .agy-ui-scope you can edit (it never overwrites an existing one
unless overwrite=True). See templates/agy-ui.rule.md for a copy-paste rule
block that teaches your agent how to use this MCP correctly.
The Chromium browser auto-installs on first use (a one-time download; no
manual playwright install chromium step). Set AGY_UI_CHROME_CHANNEL=chrome
to reuse an already-installed Chrome and skip that download entirely.
Wire into Claude Code
# If installed as a console script (pipx / uv tool / pip):
claude mcp add agy-ui --scope user -- agy-ui-mcp
# Or run the module directly (e.g. from an editable/venv install):
claude mcp add agy-ui --scope user -- python -m agy_ui_mcp
Wire into Codex
Add to ~/.codex/config.toml:
[mcp_servers.agy-ui]
command = "agy-ui-mcp" # or: command = "python", args = ["-m", "agy_ui_mcp"]
Configure a project
A .agy-ui-scope file is optional - without one the server auto-detects your
stack and synthesizes a scope (see "Zero-config quick start" above). Add a real
file only when you want to customize the allow/deny globs, serve command, or
per-screen targets. The easiest way is ui_init(project_dir="."), which
detects your stack and writes a starter .agy-ui-scope you can then edit.
Alternatively, copy the fully annotated template and edit it for your stack:
cp .agy-ui-scope.example /path/to/your/app/.agy-ui-scope
A minimal web scope:
# platform: web # default; also expo-web / ionic / flutter-web / ios-sim / android-emu
allow:
- "src/**/*.css"
- "src/components/**"
deny:
- "src/api/**" # backend - agy edits here are always reverted
- "**/*.server.*"
ambiguous:
- "src/main.tsx" # reverted AND reported for a human to decide
serve:
cmd: "npm run dev"
url: "http://localhost:5173"
ready_timeout: 30
viewports: [1440, 768, 390]
model: "gemini-3.5-flash"
A native (iOS) scope uses targets + a device registry instead of viewports:
platform: ios-sim
serve:
cmd: "flutter run -d <simulator-udid>" # argv-split (no shell) for native
url: ""
ready_timeout: 600 # first Xcode/gradle build is slow
allow: ["lib/main.dart"]
deny: ["lib/data.dart"]
devices:
sim: { name: "iPhone 17" } # or udid: "..."
targets:
- { name: order-mobile, device: sim }
model: "gemini-3.5-flash"
See .agy-ui-scope.example for the full set of options (per-target
design_ref, theme, rtl, color_scheme, forced_colors, media,
full_page, local_storage, pre_steps, serve.reload_cmd, etc.).
Tool reference
Zero-config: every tool works with no
.agy-ui-scopepresent - the server auto-detects your stack (Vite/React, Next.js, Expo, Ionic, CRA, Flutter-web, or generic web) and synthesizes a scope for the run.
ui_init(project_dir=".", overwrite=False) -> detects your stack and writes a
starter .agy-ui-scope (never clobbers an existing one unless overwrite=True).
Returns status (ok/exists/error), scope_path, written,
detected ({framework, platform, serve_cmd, serve_url, package_manager}),
allow, deny, design_dir_found, next_steps, and warnings.
ui_implement(project_dir, task, design_refs=None, target_route=None, max_iters=4, apply=True, match_threshold=90) → returns files_changed,
diff, escalations, iterations, shots_before/shots_after, targets,
applied/applied_files, match_score, match_gaps, warnings. When apply
is true the surviving in-scope edits are written to your working tree.
ui_review(project_dir, target_route=None, against_design=None, a11y=True)
→ returns critique, shots, targets, a11y ({target: [violations]}),
warnings. Read-only.
Both may instead return {"status": "blocked", "blocked_reason": "...", ...}
when a native/in-place run can't be made safe (non-git or no commit yet) - the
blocked_reason tells you exactly what to do.
Notes & limitations
- Native needs a git repo + ≥1 commit. This is by design (the in-place safety snapshot). A dirty working tree is fine and is preserved; only a non-git or commit-less project is refused (with a clear message). Web runs use an isolated worktree and also require git.
- Playwright Chromium auto-installs. Web and a11y features need a Chromium
browser; the server installs it automatically on first use (a one-time
download, with a short stderr notice). Set
AGY_UI_CHROME_CHANNEL=chrometo reuse an installed Chrome/Edge and skip the download, orAGY_UI_NO_BROWSER_AUTOINSTALL=1to opt out. Native-only use needs no browser. - Native serve command is argv-split (
shlex.split, no shell) so the PTY can deliverr/R/qkeystrokes toflutterdirectly - shell features (&&, env-var expansion,cd) inserve.cmdwon't work for native. - First native build can take minutes (Xcode / Gradle). Set
serve.ready_timeoutgenerously (e.g. 300-600s). - Flutter scaffolding. If
flutter runreports a missingios/orandroid/project, regenerate it withflutter create --platforms=ios .(orandroid).
Environment variables
| Variable | Effect |
|---|---|
AGY_UI_CHROME_CHANNEL |
Use an installed browser channel (e.g. chrome or msedge) instead of Playwright's bundled Chromium. Skips the one-time Chromium download. |
AGY_UI_CHROME_EXECUTABLE |
Explicit path to a Chromium-based browser executable to launch. |
AGY_UI_NO_BROWSER_AUTOINSTALL |
Set to a truthy value to disable the automatic playwright install chromium on first use. |
AGY_UI_DRY_RUN |
Skip every external side effect and return a stub payload (see below). |
Offline / dry runs
Set AGY_UI_DRY_RUN=1 to make the tools skip every external side effect
(spawning agy, launching Playwright, running git, starting a dev server) and
return a stub payload. The package imports and the scope/diff-gate logic
unit-test without agy, Playwright browsers, or a running dev server.
pip install -e ".[dev]" && python -m pytest -q
License
MIT.
Установка Agy Ui
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/qdzsh/agy-ui-mcpFAQ
Agy Ui MCP бесплатный?
Да, Agy Ui MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для Agy Ui?
Нет, Agy Ui работает без API-ключей и переменных окружения.
Agy Ui — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить Agy Ui в Claude Desktop, Claude Code или Cursor?
Открой Agy Ui на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectCompare Agy Ui with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
