agy-ui-mcp
A specialized MCP server that delegates frontend/UI work to Google Antigravity's agy CLI (Gemini), with a diff-gate guardrail that strictly prevents any changes to backend, API, or business logic. Designed to be driven by AI agents like Claude Code and Codex.
ui_init – Auto-detect your project stack (Vite/React, Next.js, Expo, Ionic, Flutter, etc.) and generate a starter .agy-ui-scope config file with appropriate allow/deny globs, serve commands, and scope settings — no manual config needed.
ui_implement – Run an iterative, vision-guided implementation loop that:
Screenshots the running app via Playwright (web) or simulator/emulator (native)
Prompts
agy(Gemini) to edit CSS/components toward a target designDiff-gates every change, reverting anything outside the allowed frontend scope
Re-screenshots and repeats until convergence or
max_itersis reachedReports match scores against design references, files changed, diffs, and escalations
ui_review – Perform a read-only audit of your UI that:
Serves the app and screenshots it across all configured targets (routes × devices × themes × states)
Runs axe-core accessibility (WCAG) checks on web targets and returns structured violations
Has
agycritique the UI against optional design referencesReverts any edits
agymakes, guaranteeing zero mutations to the project
Key capabilities:
Multi-platform support: Web apps, Expo Web, Ionic, Flutter Web, native iOS Simulator, and native Android Emulator
Responsive & themed captures: Multiple viewports, device emulation, dark/light mode, high-contrast, print media, RTL layouts, and component states
Diff-gate safety:
denypaths are always reverted;ambiguouspaths are reverted and flagged for human reviewDesign reference matching: Accepts image mockups or HTML/CSS demos and self-reports a 0–100 match score per iteration
Non-destructive runs: Snapshots project state before native runs so uncommitted work is fully preserved
Dry-run mode: Set
AGY_UI_DRY_RUN=1to skip all external side effects for testing/CI
Allows capturing and testing of native Android app UI screenshots via ADB and emulator, enabling iterative UI refinement with diff-gating.
Allows capturing and testing of Expo web app UI screenshots using Playwright, supporting responsive viewports and accessibility checks.
Allows capturing and testing of Flutter app UI screenshots across web, iOS, and Android platforms, with hot-reload support for iterative refinement.
Allows capturing and testing of Ionic web app UI screenshots using Playwright, similar to other web-based targets.
Allows capturing and testing of native iOS app UI screenshots using iOS Simulator and xcrun, enabling visual and accessibility critique.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@agy-ui-mcpRealign dashboard to match design mockup"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
agy-ui-mcp
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 |
| Playwright (Chromium) over the dev-server URL |
Mobile web-targets |
| Playwright (same as web) |
Native iOS |
|
|
Native Android |
|
|
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.
Related MCP server: Gemini Design MCP Server
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 |
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 blockNative iOS (
ios-sim): macOS + Xcode + a Flutter project, and a booted iOS SimulatorNative 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 | bashFrom 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-mcpFrom 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-mcpThe 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 Codescripts/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_mcpWire 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-scopeA 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 |
| Use an installed browser channel (e.g. |
| Explicit path to a Chromium-based browser executable to launch. |
| Set to a truthy value to disable the automatic |
| 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 -qLicense
MIT.
Available Tools
3 toolsui_implementA
Implement/modify UI for task via an iterative, diff-gated vision loop.
Workflow:
1. Load .agy-ui-scope and create an isolated git worktree.
2. Start the dev server (from scope.serve) inside the worktree and
wait for it to be ready.
3. Loop up to max_iters: screenshot the route across viewports,
build a vision prompt listing the shot + design-ref paths, run
agy -p in the worktree, diff-gate the result, re-screenshot.
Stop early once a round produces no new in-scope changes.
4. Collect the final diff, stop the server, clean up the worktree.
Args:
project_dir: Absolute path to the project root (must contain the scope).
task: Natural-language description of the UI change.
design_refs: Optional absolute paths to design reference images.
target_route: Optional route appended to scope.serve.url (e.g.
"/login"); defaults to the base URL.
max_iters: Maximum vision-loop iterations.
apply: When True (default), copy the in-scope changed files from the
worktree back into project_dir so the user can git diff and
review/commit them. When False, the worktree is collected and torn
down without writing anything to the project.
match_threshold: Only used when design_refs is non-empty. agy is
asked to self-report a 0-100 match score against the mockup each
round; the loop stops early once that score reaches this threshold.
Returns:
A dict with files_changed, diff, escalations, iterations,
shots_before, shots_after, warnings, applied (whether
apply was requested), applied_files (paths written to the project),
match_score (the last self-reported 0-100 score, or None when no
design refs were supplied), and match_gaps (the last reported
remaining differences, or "").
| Name | Required | Description | Default |
|---|---|---|---|
| project_dir | Yes | ||
| task | Yes | ||
| design_refs | No | ||
| target_route | No | ||
| max_iters | No | ||
| apply | No | ||
| match_threshold | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description fully discloses the iterative workflow, including creating a git worktree, starting a dev server, taking screenshots, diff-gating, and cleanup. It explains the effect of the 'apply' parameter on whether files are written back. No annotations are provided, so the description carries the full burden and meets it well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is detailed but well-structured with a summary, numbered workflow, args list, and returns section. It is front-loaded with the core purpose. While long, the complexity of the tool justifies the length. Could be slightly more concise, but very effective.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, 7 parameters, no annotations, and the presence of an output schema, the description covers all necessary aspects: purpose, workflow, parameter meanings, and return value structure. No gaps are evident.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description compensates with a dedicated 'Args:' section that explains each parameter's meaning, defaults, and behavior. For example, 'project_dir' is described as 'Absolute path to the project root (must contain the scope)' and 'match_threshold' is explained in context of design_refs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description begins with a clear verb 'Implement/modify UI' and specifies the resource 'UI for task' and method 'iterative, diff-gated vision loop'. It distinguishes from sibling tool 'ui_review' by detailing an implementation workflow rather than review.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for implementing UI changes via a vision loop, but does not explicitly contrast with sibling tool 'ui_review' or state when each should be used. No exclusion criteria or alternatives are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ui_initA
Auto-detect the stack and write a starter .agy-ui-scope config.
Zero-to-config helper for non-technical users: inspects the project's
manifests (package.json / pubspec.yaml / lockfiles), guesses the framework,
serve command, and edit-scope globs, and writes a .agy-ui-scope YAML at
the project root that the user can then tweak by hand. After this, the
ui_implement / ui_review tools run with no further setup.
Args:
project_dir: Path to the project root to scan and write into.
overwrite: When False (default) an existing .agy-ui-scope is left
untouched and status: "exists" is returned. Pass True to
regenerate it (clobbering the existing file).
Returns:
A dict describing the outcome: status (ok/exists/error),
scope_path (absolute), written (whether the file was written),
detected (framework/platform/serve/package-manager), allow and
deny globs, design_dir_found, next_steps, and warnings.
| Name | Required | Description | Default |
|---|---|---|---|
| project_dir | No | . | |
| overwrite | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It explains the write behavior, including what happens when overwrite is false (leaves existing file untouched) and true (clobbers). It describes reading project files and the return format. However, it could mention that it reads files non-destructively.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a concise summary, a paragraph explaining the purpose, then explicit Args and Returns sections. Every sentence adds value and there is no waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has an output schema but the description already lists return fields, it is fairly complete. It covers purpose, parameters, and return. It could mention potential prerequisites (e.g., existence of package.json), but not necessary for a setup tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so description compensates fully. For project_dir, it says 'Path to the project root to scan and write into.' For overwrite, it explains the behavior in detail, including the status returned when not overwriting. This adds significant meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool auto-detects the stack and writes a config file, with specific actions like inspecting manifests and guessing framework. It distinguishes itself from sibling tools (ui_implement, ui_review) by noting that after this tool, the others run with no further setup.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description says it's a 'zero-to-config helper for non-technical users' and implies usage before ui_implement/ui_review. It doesn't explicitly state when not to use it, but the context makes it clear that it's for initial setup. An explicit 'when not to use' would improve it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ui_reviewA
Serve the app, screenshot it, and have agy critique it read-only.
Any file agy edits during the critique is reverted by the diff-gate, so this tool never mutates the project.
When a11y is set (and the platform is a web target), each target is also
audited with axe-core; the violations ground agy's critique and are returned
structurally under a11y. Native platforms have no DOM, so the audit is
skipped there with a note.
Args:
project_dir: Absolute path to the project root (must contain the scope).
target_route: Optional route appended to scope.serve.url.
against_design: Optional absolute paths to design reference images to
critique against.
a11y: Run axe-core accessibility checks on web targets (default True).
Returns:
A dict with critique (agy's text), shots (captured paths),
targets (the reviewed target names), a11y (a {target: [violations]} map; empty when disabled/native), and warnings.
| Name | Required | Description | Default |
|---|---|---|---|
| project_dir | Yes | ||
| target_route | No | ||
| against_design | No | ||
| a11y | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses behavioral traits: it never mutates (edits reverted via diff-gate), a11y runs on web only, and it returns a detailed dict. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with paragraphs and a clear Args section, but a few sentences could be trimmed without losing clarity. Still concise overall.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity and presence of an output schema, the description covers inputs, behavior, edge cases (native vs web), and return structure thoroughly. No gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the description explains all four parameters clearly, including defaults (a11y) and types (against_design as paths). This adds significant meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses specific verbs ('serve, screenshot, critique') and clearly identifies the resource (app UI). It distinguishes from the sibling tool 'ui_implement' by emphasizing the read-only review nature.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use for design review without mutation, and explains a11y behavior per platform. It does not explicitly state when not to use or list alternatives, but the sibling tool 'ui_implement' provides context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
- Added
ui_init
2 tool updates
v0.1.0- First observed
ui_implement - First observed
ui_review
TDQS
Scored across 3 tools
Each tool targets a distinct phase: ui_init configures the project, ui_implement applies changes, and ui_review critiques without mutating. There is no meaningful overlap in purpose, despite sharing some arguments like project_dir and target_route.
All tools follow a consistent ui_<verb> pattern in snake_case. The verbs init, implement, and review are clear and predictable, making tool selection straightforward.
Three tools are well-scoped for the server's setup-implement-review lifecycle. Each tool earns its place, and the count is comfortably within the ideal range for a focused MCP server.
The tool surface covers the full intended workflow: initialize a scope, implement UI changes, and review the result against design and accessibility criteria. ui_init's overwrite option and ui_implement's apply flag also provide sensible config-reset and dry-run paths.
Maintenance
Related MCP Connectors
UI design from prompts, screenshots, and URLs for AI coding agents and theme tokens.
Agent-Native design tool - create and edit visual designs with agent assistance
Live React design-system APIs, patterns, and code validation so AI agents build real UI, not slop.
- FlowstepOAuthai.flowstep
Generate, inspect, and manage Flowstep UI designs directly from your AI assistant.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables AI to capture, compare, and automatically patch frontend code against reference designs, achieving pixel-perfect fidelity without manual CSS tweaking.21 npm8MIT
- FlicenseNot gradedqualityDmaintenanceGenerates frontend UI code from text descriptions, screenshots, or iterative refinement using Gemini 2.5 Flash.2-
- AlicenseNot gradedqualityDmaintenanceEnables designing, modifying, and bug reporting in web apps, sending changes to coding agents via MCP.5 npm46MIT
- AlicenseAqualityDmaintenanceLets AI agents visually inspect web elements, test CSS edits in real-time, and iterate until pixel-perfect, functioning like browser DevTools for debugging UI issues.16 npm1MIT