PicassoWeb
# PicassoWeb MCP
> "Good artists copy, great artists steal." — the tool formerly known as webcopy-design-mcp.
PicassoWeb opens a website in Chromium and turns its rendered interface into everything an AI client needs to replicate it faithfully. It extracts the actual computed colors, typography, CSS variables, layout primitives, and reusable component families instead of only searching the raw source for CSS strings. Beyond the design system, it can screenshot the page, download the real assets (images, inline SVG logos/icons, fonts, video), extract the motion design (`@keyframes`, transitions, animation libraries, scroll reveals), capture JS-driven motion over time as frame strips and numeric curves, map the layout tree, clone a section to self-contained HTML + CSS + assets, crawl same-origin pages into a site-wide design system, produce a complete one-shot replication kit, and **pixel-diff a replica against the original** so an agent can iterate until the copy matches.
**Website:** [blackridder22.github.io/PicassoWeb](https://blackridder22.github.io/PicassoWeb/)
**Documentation:** [Introduction](https://blackridder22.github.io/PicassoWeb/guide/) · [Quick start](https://blackridder22.github.io/PicassoWeb/guide/quickstart.html) · [Tool reference](https://blackridder22.github.io/PicassoWeb/guide/tools.html) · [Workflows](https://blackridder22.github.io/PicassoWeb/guide/workflows.html) · [Security](https://blackridder22.github.io/PicassoWeb/guide/security.html) · [llms.txt](https://blackridder22.github.io/PicassoWeb/llms.txt)
## What it extracts
- Color palette normalized to hex, with usage counts for text, backgrounds, borders, decoration, SVG fills, and strokes.
- Font families, weights, styles, type sizes, line heights, letter spacing, and representative selectors.
- CSS custom properties classified as color, typography, spacing, radius, shadow, or other tokens.
- Common border radii, box shadows, margins, padding, and gaps.
- Component families such as buttons, inputs, cards, navigation, headers, footers, modals, tabs, accordions, badges, avatars, forms, tables, heroes, and pagination.
- Detailed inspection by CSS selector, accessible role/name, or text — including open shadow roots and same-origin frames — with computed styles, matched cascade rules, custom properties, box-model geometry, platform fonts, pseudo-elements, descendants, and interaction states.
JavaScript-rendered pages are supported. By default, the analyzer also scrolls through the page to trigger lazy-rendered sections before extraction.
## MCP tools
| Tool | Purpose |
| --- | --- |
| `analyze_site` | Analyze a live `http://` or `https://` website. |
| `analyze_html` | Render supplied HTML and optional CSS without making external requests. |
| `inspect_component` | X-ray elements selected by CSS, accessible role/name, or text, optionally inside an iframe. Returns the V1 computed-style data plus matched cascade rules, CSS variables, box-model rectangles, platform fonts, and root/descendant `:hover`, `:focus`, and `:active` changes. Playwright CSS targeting pierces open shadow roots. |
| `capture_screenshot` | Return a screenshot the client can look at: viewport, full page, or a single element by selector. Optionally saves the image to disk. |
| `extract_assets` | Download the real images, background images, inline SVG icons/logos, videos, favicons, and web fonts into a local `assets/` folder with a `manifest.json` mapping each file to where it appears. Lets a replica reuse the exact original assets instead of re-drawing them. |
| `extract_animations` | Produce a settled, static motion census: joined `@keyframes` and users, numeric timings, a one-shot WAAPI inventory, optional hover/focus transition targets, scroll-timeline detail, detected libraries/reveals, and paste-ready generated CSS. Use `capture_motion` when the motion must be recorded over time. |
| `extract_layout` | Return a breadth-first, layout-focused DOM tree with section labels, flex/grid container and item detail, scroll containers, sticky/fixed positioning, stacking contexts, clipped visible rectangles, opacity-hidden elements, and collapsed-wrapper counts. |
| `clone_section` | Return a self-contained copy of one section: cleaned HTML (scripts/handlers stripped, inline SVG preserved, media URLs absolutized), scoped CSS matching that subtree plus the `@keyframes`/`@font-face`/`:root` CSS variables it depends on, its assets, and a screenshot. With `outputDir`, assets are downloaded and URLs rewritten to relative paths so the snippet renders standalone. |
| `capture_interactions` | Find and operate interactive triggers (hamburger menus, dropdowns, modals, tabs, accordions), then capture what they reveal: selectors, bounds, HTML samples, and screenshots taken while the UI is open. Surfaces the parts of a design that never appear in a static extraction. |
| `extract_responsive` | Extract how the site adapts across screen sizes: breakpoints derived from `@media` rules, a summary of each media query (condition, rule count, sample selectors), and a layout tree captured at each requested viewport width — with an optional screenshot per width. |
| `create_replication_kit` | One-shot capture of everything, written to a folder: desktop + mobile screenshots, `assets/` with manifest, `design.json`, `layout.json` (desktop + mobile trees), `animations.json`, and a `REPLICATE.md` guide. Loads the page once, so it is much faster than calling the individual tools separately. |
| `compare_replica` | Deterministically capture original and replica, then run an anti-aliasing-tolerant YIQ diff. Returns the visual diff, noise-aware counts, worst regions attributed to elements with style deltas, optional section-aligned scores, and a `selfCheck` mode for measuring the page's own noise floor. |
| `capture_motion` | Capture how the page actually moves: a frame-strip of screenshots sampled over time after load, scroll, hover, or click, the Web Animations API inventory (`element.animate` / CSS animation / transition keyframes, timing, easing, play state), and per-frame numeric transform/opacity curves for animated elements. Catches JS-driven motion (GSAP, Framer Motion) that a static extraction cannot see. |
| `crawl_site` | Crawl same-origin pages breadth-first and merge each page's design analysis into a site-wide design system: colors, fonts, and CSS variables shared across pages versus unique to one page, plus a page inventory with section outlines. With `outputDir`, writes per-page JSON + screenshots and a `SITE.md` naming the pages worth replicating individually. |
All tools return the complete JSON result first for compatibility, plus typed MCP structured content with `result` and `guidance` (`nextTools`, warnings, cost, file behavior, and session policy). `capture_screenshot`, `clone_section`, `create_replication_kit`, `compare_replica`, `capture_interactions`, and `capture_motion` additionally return image content blocks.
### Session reuse
Read-style tools (`analyze_site`, `inspect_component`, `capture_screenshot`, `extract_assets`, `extract_animations`, `extract_layout`, `clone_section`) share a small cache of loaded pages keyed by URL + viewport. Consecutive calls against the same page skip the full navigation — typically 2–5s saved per call — and note the reuse in `warnings`. Sessions expire after 2 minutes; tools that mutate page state (`extract_responsive`, `create_replication_kit`, `compare_replica`, `capture_interactions`, `capture_motion`, `crawl_site`) always load fresh.
### Tools that write files
`extract_assets`, `create_replication_kit`, `clone_section` (with `outputDir`), `extract_responsive` (with `outputDir`), `capture_interactions` (with `outputDir`), `capture_motion` (with `outputDir`), `crawl_site` (with `outputDir`), and `capture_screenshot` (with `outputPath`) write to the local filesystem, so they are not marked read-only. Every downloaded asset URL is re-checked against the same SSRF guard as the initial navigation.
## Quick start (npx)
Requirements: Node.js 20 or newer. Add PicassoWeb to your MCP client configuration — no clone, no build:
```json
{
"mcpServers": {
"picassoweb": {
"command": "npx",
"args": ["-y", "picassoweb"]
}
}
}
```
### AI tool profiles
`full` remains the default and advertises all 14 tools. Use the focused `workflow` profile to advertise only the nine intent-level tools and reduce overlap for agents:
```json
{
"mcpServers": {
"picassoweb": {
"command": "npx",
"args": ["-y", "picassoweb", "--tools", "workflow"]
}
}
}
```
`PICASSOWEB_TOOLS=workflow` is equivalent. Both profiles receive workflow routing through MCP server instructions, decision-first tool descriptions, typed output schemas, and machine-readable cost/session metadata.
The same canonical catalog generates the [AI tool reference](docs/guide/tools.md), [llms.txt](docs/llms.txt), and packaged [PicassoWeb skill](skills/picassoweb/SKILL.md), so agent guidance stays version-matched with the server.
The first run downloads the package and a Chromium build (~130 MB, cached after that). If Chromium is already installed, point the server at it instead:
```json
{
"mcpServers": {
"picassoweb": {
"command": "npx",
"args": ["-y", "picassoweb"],
"env": { "CHROME_EXECUTABLE_PATH": "/absolute/path/to/chromium" }
}
}
}
```
## Install from source
```bash
git clone https://github.com/blackridder22/PicassoWeb.git
cd PicassoWeb
npm install # also downloads Chromium via postinstall
npm run build
```
## Connect an MCP client (from source)
Build the project, then add a stdio server to your MCP client configuration. Replace the example path with the absolute project path.
```json
{
"mcpServers": {
"picassoweb": {
"command": "node",
"args": ["/absolute/path/to/webcopy-design-mcp/dist/index.js"]
}
}
}
```
During development, the client can launch the TypeScript entry point directly:
```json
{
"mcpServers": {
"picassoweb-dev": {
"command": "npx",
"args": ["tsx", "/absolute/path/to/webcopy-design-mcp/src/index.ts"]
}
}
}
```
The MCP server communicates over standard input/output. Diagnostic messages are written only to standard error.
## Example calls
Analyze a public site:
```json
{
"url": "https://example.com",
"viewportWidth": 1440,
"viewportHeight": 900,
"maxElements": 2500,
"autoScroll": true
}
```
Inspect a component after the overview identifies a useful selector:
```json
{
"url": "https://example.com",
"selector": ".pricing-card",
"maxMatches": 5
}
```
Targeting can instead use an accessible role/name or visible text, and can be scoped to an iframe. Exactly one of `selector`, `role`, or `text` is required. Component inspection now defaults `autoScroll` to `false`; if the target is not initially attached, PicassoWeb performs one lazy-content scroll and retries automatically.
```json
{
"url": "https://example.com",
"role": "button",
"roleName": "Sign in",
"frameSelector": "iframe.checkout"
}
```
Analyze source supplied directly by an agent or another tool:
```json
{
"html": "<main><article class=\"card\"><h2>Hello</h2></article></main>",
"css": ":root{--brand:#6d5dfc}.card{padding:24px;color:var(--brand)}"
}
```
## Docker
The image uses the official Playwright runtime, so Chromium and its system libraries are already present.
```bash
docker build -t picassoweb-mcp .
```
An MCP client can launch the container as its stdio command:
```json
{
"mcpServers": {
"picassoweb": {
"command": "docker",
"args": ["run", "--rm", "-i", "picassoweb-mcp"]
}
}
}
```
## Security defaults
- Only HTTP and HTTPS URLs are accepted.
- Embedded URL credentials are rejected.
- Localhost, private IP ranges, link-local addresses, and reserved networks are blocked by default.
- Every browser request is checked, including redirects and subresources.
- `analyze_html` blocks external network requests.
- Input sizes, navigation time, DOM sampling, selector matches, CSS collection, and returned HTML are bounded.
For a trusted local development site, pass `"allowPrivateNetwork": true`. This should remain disabled when calls can be influenced by untrusted content.
`compare_replica` is the one exception with a relaxed default: `allowPrivateReplica` defaults to `true` so the replica side can point at a localhost dev server or a local file, which is the normal workflow. The original URL is still fully SSRF-guarded.
## Development
```bash
npm run typecheck
npm test
npm run build
```
The browser integration test runs when `CHROME_EXECUTABLE_PATH` is set. The remaining tests validate CSS token extraction, URL safeguards, session caching, and the exposed MCP contract without requiring a browser.
For a full end-to-end smoke test of the built server over real stdio (tool listing, extraction, session-cache speedup, interaction capture, motion sampling, crawling):
```bash
npm run build
node scripts/cold-test.mjs # defaults to https://getbootstrap.com/
node scripts/cold-test.mjs https://your-target.example
```
## Practical limitations
- Authentication, cookie consent, CAPTCHAs, and anti-bot systems are not bypassed.
- Content that appears only after a user-specific interaction may require a separate browser automation step before analysis.
- Computed styles remain available when cross-origin stylesheet rules are inaccessible. Raw CSS variables are additionally recovered from readable stylesheet responses when possible.
- Component recognition is semantic and heuristic. `inspect_component` provides the exact follow-up data when a family needs closer analysis.
- Downloaded assets are the original copyrighted files. Reuse them only where you have the right to; `extract_assets` is a copy tool, not a licensing check.
- `extract_animations` is a static census: its WAAPI data is a one-shot settled snapshot and its scroll-reveal data captures visible start/end values, not the exact JS timeline. `capture_motion` is the complementary dynamic recorder for frame strips, numeric curves, reload/entry motion, and timeline behavior over time.
- `extract_layout` reports stacking-context evidence, `z-index`, and DOM order, but does not calculate the browser's exact global paint order.
- `capture_motion` samples in real wall-clock time (interval floor 100 ms), so very fast animations yield few distinct frames — the per-frame numeric style curves still capture them. GSAP drives elements from its own ticker and never appears in the Web Animations API inventory; its motion shows up in the frame strip and the numeric curves instead.
- `crawl_site` follows `a[href]` links only (SPAs that navigate from click handlers need `capture_interactions`) and does not consult robots.txt — it is an interactive agent tool with small page caps, not a bulk crawler.
- Matched rules and forced interaction states use Chromium DevTools Protocol and are therefore Chromium-only. Elements in out-of-process frames can still return evaluate-side inspection data, but CDP-only enrichment may be omitted with a warning.
- `compare_replica` freezes declarative and WAAPI motion and stubs `requestAnimationFrame` after settling, but the rAF freeze is best-effort; canvas, video, WebGL, timers, and external data can remain nondeterministic. Run `selfCheck` first to measure that page's noise floor.
## License
MIT
TDQS
Scored across 14 tools
Each tool is clearly scoped by either target surface (remote page, offline HTML, component, section, site, replica) or evidence type (screenshot, assets, layout, animations, motion, responsive). The descriptions include explicit 'Avoid when' cross-references, so overlapping-sounding tools are easy to tell apart.
All tool names follow a consistent verb_noun snake_case pattern with coherent verb families: analyze_, inspect_, capture_, extract_, clone_, compare_, create_, crawl_. The verb consistently signals the action type and the noun signals the target or output.
14 tools is appropriate for the design-replication domain: the surface covers single-page analysis, targeted extraction, component cloning, interaction capture, responsive comparison, motion capture, site-wide crawling, and full replication. create_replication_kit consolidates the first-pass workflow, keeping the count reasonable.
The toolset provides full coverage of the design extraction and replication lifecycle: analysis, inspection, asset extraction, layout, animation, responsive behavior, interaction capture, cloning, full-package generation, and replica verification. Every tool also lists possible follow-ups, so the workflow has no dead ends.