Are you the author? Sign in to claim
MCP server + CLI for AI-powered design fidelity — compare Figma designs or screenshots against rendered UI. 90% mutation
AI-Powered Design Fidelity — MCP Server & CLI
"comparison" — pronounced "key-AHS"
A developer-first MCP server (also runnable as a CLI) that compares Figma designs against rendered UI components and surfaces an AI-powered semantic diff. Plugs into Claude Code, Cursor, Codex CLI, and any other MCP-compatible client.
Unlike pixel-diff tools, kiyas uses vision AI to understand what is different and why it matters — outputting actionable, human-readable feedback like:
Just describe the component by name. kiyas finds it in your codebase, screenshots it, and compares it against the Figma design.
Prefer an app over a terminal? There's also a desktop app.
A native macOS app for running the same comparisons point-and-click — built for designers and anyone who'd rather not touch a terminal. Pick a project, paste a Figma link (or drop in a screenshot), describe the component, and get the full report in-app. It uses the same engine and the same subscription-based auth: AI calls go through the Claude Code or Codex CLI on your machine, never an API key.
⬇ Download the latest release (Apple Silicon)
.dmg, drag Kiyas to Applications.xattr -dr com.apple.quarantine /Applications/Kiyas.app).Highlights: project sidebar with dev-server detection, capture preview + crop before comparing, built-in terminal, full dark mode, and a Liquid Glass icon on macOS 26.
To build from source instead:
git clone https://github.com/saiffmirza/kiyas && cd kiyas
npm install
npm run desktop # dev mode
# or package a .app/.dmg:
cd apps/desktop && npx electron-builder --mac
┌─────────────────────┐
│ kiyas │
│ (MCP server / CLI) │
│ │
│ figma / design img │
│ + target/component │
└──────────┬───────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌──────────────┐ ┌───────────┐ ┌─────────────┐
│ 1. Auth │ │ 2. Design │ │ 3. Resolve │
│ │ │ Capture │ │ Component │
│ Verify │ │ │ │ │
│ Claude Code │ │ Figma API │ │ AI agent │
│ or Codex CLI │ │ PNG export│ │ searches │
│ is installed │ │ — or your │ │ codebase, │
│ & signed in │ │ own image │ │ finds URL + │
│ │ │ (--design)│ │ CSS selector│
└──────┬───────┘ └─────┬─────┘ └──────┬──────┘
│ │ │
│ ▼ ▼
│ ┌────────────┐ ┌────────────┐
│ │ Figma │ │ Playwright │
│ │ design │ │ screenshot │
│ │ (PNG) │ │ (PNG) │
│ └─────┬──────┘ └─────┬──────┘
│ │ │
│ └───────┬───────┘
│ ▼
│ ┌──────────────────────┐
└─────────►│ 4. Vision AI Compare │
│ │
│ Both images sent to │
│ Claude Code CLI with │
│ a structured prompt │
│ │
│ Returns JSON array │
│ of discrepancies │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ 5. HTML Report │
│ │
│ Side-by-side images │
│ Severity badges │
│ Interactive filters │
│ HIGH / MEDIUM / LOW │
│ │
│ file:// link in │
│ terminal output │
└──────────────────────┘
Step-by-step:
--scale), and fetches node metadata (colors, fonts, spacing). Or skip Figma entirely: pass --design <path-or-url> with your own design image and no Figma token is needed.kiyas exposes its comparison engine as an MCP server over stdio. Three tools, all with Zod-typed input schemas:
| Tool | Description | Required input |
|---|---|---|
compare | Run a fresh design-vs-implementation comparison; returns reportId + summary | (figma or designImage) + (target or component) |
get_diff_report | Fetch a stored report's HTML or JSON content | reportId |
list_issues | List discrepancies from a stored report, optionally filtered by severity | reportId |
Reports are persisted under .kiyas/reports/<reportId>/ in your project directory, so the same reportId stays valid across calls and across CLI/MCP usage.
npm install -g kiyas-cli
npx playwright install chromium
Claude Code
claude mcp add kiyas -- npx -y kiyas-cli@latest mcp
# with a Figma token (only needed for Figma-URL comparisons):
claude mcp add kiyas -e FIGMA_ACCESS_TOKEN=figd_xxx -- npx -y kiyas-cli@latest mcp
kiyas is also listed in the official MCP Registry as io.github.saiffmirza/kiyas, so registry-aware clients can install it directly from their MCP catalog.
Cursor — edit ~/.cursor/mcp.json:
{
"mcpServers": {
"kiyas": {
"command": "npx",
"args": ["kiyas-cli@latest", "mcp"]
}
}
}
Codex CLI — edit ~/.codex/config.toml:
[mcp_servers.kiyas]
command = "npx"
args = ["kiyas-cli@latest", "mcp"]
The configs above use kiyas-cli@latest so npx picks up new releases on every launch — the tradeoff is a registry check per start, and launches can fail offline. If you'd rather pin a version (kiyas-cli@1.3.1) or use a global install, that's safe too: kiyas checks npm once at startup (non-blocking) and logs a notice to stderr when a newer version is available.
The compare tool needs Figma access only when you pass a figma URL. Three ways to provide it:
1. Pass your token via the server config (recommended):
claude mcp add kiyas -e FIGMA_ACCESS_TOKEN=<your-token> -- npx -y kiyas-cli@latest mcp
or in .mcp.json / mcp.json / config.toml, add an env block:
{
"mcpServers": {
"kiyas": {
"command": "npx",
"args": ["kiyas-cli@latest", "mcp"],
"env": { "FIGMA_ACCESS_TOKEN": "your-token" }
}
}
}
2. A .kiyasrc file in the project root or home directory: { "figmaAccessToken": "..." }
3. No token at all — pair with the Figma MCP server. If the agent already has Figma's own MCP server connected, it can export the frame as an image itself and pass the file path (or image URL) as designImage instead of a figma URL. kiyas never touches the Figma API in this mode:
Export node 1:234 from the Figma file as a PNG, then use kiyas to compare it against the primary button on the login page.
If a figma URL is used with no token configured, the tool fails fast with these instructions rather than hanging.
Once connected, you can ask the agent things like:
Compare the Figma frame at
<url>against the primary button on the login page, then list only the high-severity issues.
The agent will call compare to produce a reportId, then list_issues with severity: "high" against that ID.
--figma; comparing against a local screenshot with --design requires no tokennpm install -g kiyas-cli
npx playwright install chromium
kiyas setup
This walks you through:
.env# Describe the component by name — kiyas finds it automatically
kiyas --figma "https://www.figma.com/design/abc123/Design?node-id=1:234" \
--component "eventHeader on the redemption screen"
# Or provide a direct URL if you already know it
kiyas --figma "https://www.figma.com/design/abc123/Design?node-id=1:234" \
--target "http://localhost:3000/redemption" \
--selector ".event-header"
# Save the report to a specific path
kiyas --figma "https://www.figma.com/design/abc123/Design?node-id=1:234" \
--component "primary button" \
--output report.html
# Output as JSON (for CI pipelines)
kiyas --figma "https://www.figma.com/design/abc123/Design?node-id=1:234" \
--component "primary button" \
--format json
# Compare against a design screenshot instead of Figma (no Figma token needed)
kiyas --design ./design.png \
--component "primary button" \
--output report.html
# Use OpenAI instead of Claude
kiyas --figma "https://www.figma.com/design/abc123/Design?node-id=1:234" \
--component "nav bar" \
--model openai
| Flag | Description | Required |
|---|---|---|
--figma <url> | Figma frame/component URL | Yes** |
--design <path> | Design image (local path or URL) instead of Figma | Yes** |
--component <description> | Natural-language description of the component to find | Yes* |
--target <url> | Direct URL of the rendered component (skips AI lookup) | Yes* |
--dev-server <url> | Dev server base URL (default: auto-detect 3000/5173/8080/4200) | No |
--model <provider> | AI provider: claude (default) or openai | No |
--output <path> | Path to save the report (default: kiyas-report-<timestamp>.html) | No |
--format <type> | Output format: html (default) or json | No |
--viewport <size> | Viewport size for screenshot (default: 1280x720) | No |
--scale <n> | Render scale for both Figma export and screenshot. Default adaptive: 2 for component-sized captures (selector, or viewport ≤ 1000px), 1 for large full-page captures | No |
--no-full-page | Capture only the viewport instead of the full scrollable page | No |
--selector <css> | CSS selector to screenshot a specific element | No |
--wait <ms> | Time in ms to wait before screenshot (for animations/loading) | No |
--auth-state <path> | Playwright storageState JSON for authenticated screenshots | No |
--config <path> | Path to a JSON config file for batch comparisons | No |
--threshold <level> | Severity filter: all, medium, high (default: all) | No |
*Provide either --component or --target. When using --component, kiyas uses AI to find the component in your codebase and resolve it to a URL.
**Provide either --figma or --design. With --design, the Figma export is skipped entirely and no Figma token is required.
Most real designs live behind a login. kiyas accepts a Playwright storageState JSON file (cookies + localStorage) and reuses it for the screenshot session — the same format Playwright tests use, so any auth-state file your tests already produce works as-is.
# 1. Record a session — log in, then close the browser. Playwright writes auth.json.
npx playwright codegen --save-storage=auth.json https://app.example.com
# 2. Use it for kiyas screenshots
kiyas \
--figma "https://www.figma.com/design/.../?node-id=1:234" \
--target "https://app.example.com/dashboard" \
--auth-state ./auth.json
The MCP compare tool exposes the same option as authState — pass the path and the agent screenshots authenticated views with no further setup.
kiyas leverages your existing AI subscriptions — no separate API keys needed. It delegates all AI calls to the Claude Code or Codex CLI, which handle their own authentication.
Claude (default): Requires Claude Code installed and signed in with a Pro, Max, or Team subscription. kiyas spawns the claude CLI for AI calls, so usage counts against your existing subscription quota.
# Install Claude Code if you haven't already
npm install -g @anthropic-ai/claude-code
# Sign in
claude auth login
OpenAI (alternative): Requires Codex installed and signed in. Use --model openai to select it.
codex auth login
If no CLI is found, kiyas prompts you to install and sign in:
Claude Code is not installed or not signed in.
kiyas uses your existing Claude Code subscription — no API keys needed.
To fix this, either:
1. Install and sign into Claude Code:
npm install -g @anthropic-ai/claude-code
claude auth login
2. Or switch kiyas to use OpenAI instead:
kiyas set model openai
(requires signing into Codex: codex auth login)
Figma: Requires a personal access token with File content → Read only scope. Run kiyas setup to configure it, or set FIGMA_ACCESS_TOKEN in .env manually.
kiyas is a harness around vision AI, and a harness is only useful if its results are consistent. What it controls:
claude --model / codex -m) instead of drifting with CLI defaults. Configure with kiyas set claudeModel <id> / kiyas set codexModel <id>.CLAUDE.md/AGENTS.md, hooks, and MCP servers can't influence the output.--component description was resolved, so any two reports can be meaningfully compared.--runs 3 runs the comparison three times concurrently and keeps only majority-vote findings, each tagged with a confidence score. Higher consistency at N× cost; off by default.npm run eval (repo only, not shipped) runs a golden eval set: fixture pages with known injected CSS mutations plus zero-mutation pairs, scored deterministically for recall, precision, severity agreement, false-positive floor, and run-to-run stability. Prompt and pipeline changes are validated against it.For teams running repeated comparisons, create a kiyas.config.json:
{
"figmaAccessToken": "env:FIGMA_ACCESS_TOKEN",
"model": "claude",
"viewport": "1280x720",
"comparisons": [
{
"name": "Primary Button",
"figma": "https://www.figma.com/design/abc123/Design?node-id=1:234",
"target": "primary button on the login page"
},
{
"name": "Event Card",
"figma": "https://www.figma.com/design/abc123/Design?node-id=5:678",
"target": "http://localhost:6006/iframe.html?id=card--event",
"selector": ".event-card"
}
]
}
The target field accepts both component descriptions (resolved by AI) and direct URLs. Each comparison takes either figma (a URL) or design (a local image path) as its design source. Run with:
kiyas --config ./kiyas.config.json
kiyas/ (npm workspaces monorepo)
├── packages/
│ ├── core/ # @kiyas/core — the engine (private, bundled into the CLI)
│ │ └── src/
│ │ ├── index.ts # Public API barrel (runComparison, resolveComponent, …)
│ │ ├── config.ts # Config file loading + Figma token resolution
│ │ ├── settings.ts # Persisted user settings
│ │ ├── auth/
│ │ │ ├── index.ts # Auth resolver (picks best available auth)
│ │ │ ├── claude-oauth.ts # Verify Claude Code CLI is available
│ │ │ └── openai-auth.ts # Verify Codex CLI is available
│ │ ├── resolve/
│ │ │ └── component.ts # AI agent: finds component in codebase → URL + selector
│ │ ├── capture/
│ │ │ ├── figma.ts # Figma REST API: export frame as PNG + metadata
│ │ │ └── playwright.ts # Playwright: headless screenshot of rendered component
│ │ ├── compare/
│ │ │ ├── index.ts # Orchestrator: sends images to vision AI
│ │ │ ├── pipeline.ts # Pure runComparison() + report persistence (shared by CLI + MCP)
│ │ │ ├── claude.ts # Claude comparison via Claude Code CLI
│ │ │ ├── openai.ts # OpenAI comparison via Codex CLI
│ │ │ └── prompt.ts # The comparison prompt (shared across providers)
│ │ ├── report/
│ │ │ └── html.ts # Generate self-contained HTML report with embedded images
│ │ └── utils/
│ │ ├── parse-figma-url.ts # Extract file key + node ID from Figma URL
│ │ └── logger.ts # Minimal logging utility
│ └── cli/ # kiyas-cli — the published npm package
│ ├── src/
│ │ ├── index.ts # CLI entry point (argument parsing, orchestration)
│ │ ├── setup.ts # Interactive first-time setup
│ │ └── mcp/
│ │ ├── server.ts # MCP server bootstrap (stdio transport)
│ │ └── tools.ts # Zod schemas + handlers (compare, get_diff_report, list_issues)
│ ├── package.json
│ └── tsup.config.ts
├── apps/
│ └── desktop/ # @kiyas/desktop — Electron app (macOS)
│ ├── src/
│ │ ├── main/ # Main process: IPC, capture flow, pty terminal
│ │ ├── preload/ # Typed context bridge (window.kiyas)
│ │ └── renderer/ # React UI (cream/navy/gold theme, dark mode)
│ ├── build/kiyas.icon # Icon Composer bundle (Liquid Glass icon source)
│ ├── scripts/gen-icon.mjs # Renders all icon variants from the Farisi kāf
│ └── electron-builder.yml
├── eval/ # Golden eval set + scoring harness
├── .env.example
├── .kiyasrc.example
├── package.json # Workspace root
└── tsconfig.json
| Layer | Tool |
|---|---|
| Runtime | Node.js (TypeScript) |
| MCP | @modelcontextprotocol/sdk, Zod (stdio transport) |
| Screenshot capture | Playwright (headless Chromium) |
| Figma export | Figma REST API |
| AI comparison | Claude Code CLI or Codex CLI (vision) |
| Component resolution | Claude Code CLI / Codex CLI (agent) |
| Output | HTML (default), JSON |
| Desktop app | Electron, electron-vite, React, node-pty + xterm |
| Build | tsup, electron-builder |
| Package manager | npm |
MIT
Browser automation using accessibility snapshots instead of screenshots
Run Claude Code as an MCP server so any agent can delegate coding tasks to it
Google's universal MCP server supporting PostgreSQL, MySQL, MongoDB, Redis, and 10+ databases
Official GitHub integration for repos, issues, PRs, and CI/CD workflows