An MCP server that captures, catalogs, and retrieves premium UI animations from live websites using Playwright. Build a personal library of scroll-triggered animations, transitions, and interactive components that AI agents can reference when building interfaces.
- Node.js 22.5+ — required for the built-in
node:sqlitemodule (node --versionto check) - npm 10+
git clone https://github.com/bdredz/design-intelligence-mcp.git
cd design-intelligence-mcp
npm install
npx playwright install chromium
npm run buildThe server runs via stdio — MCP clients spawn it directly. No separate process needed.
Edit ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"design-intelligence": {
"command": "node",
"args": ["/absolute/path/to/design-intelligence-mcp/dist/index.js"]
}
}
}Restart Claude Desktop after saving.
claude mcp add design-intelligence node /absolute/path/to/design-intelligence-mcp/dist/index.jsEdit ~/.codex/config.toml:
[mcp_servers.design-intelligence]
command = "node"
args = ["/absolute/path/to/design-intelligence-mcp/dist/index.js"]Edit ~/Library/Application Support/Antigravity/User/settings.json — add a top-level mcpServers key:
{
"mcpServers": {
"design-intelligence": {
"command": "node",
"args": ["/absolute/path/to/design-intelligence-mcp/dist/index.js"]
}
}
}| Variable | Default | Description |
|---|---|---|
DI_DB_PATH |
./design-library.db |
SQLite database location |
TRANSPORT |
stdio |
stdio or http |
PORT |
3100 |
HTTP port (when TRANSPORT=http) |
To share one library across projects, pass an absolute path:
"env": { "DI_DB_PATH": "/Users/you/design-library.db" }┌─────────────────────────────────────────────────────────┐
│ MCP Tools Layer │
│ di_scroll_capture → di_extract_animations → │
│ di_catalog_component → di_search_library │
│ di_capture_and_catalog (full pipeline) │
│ di_delete_component | di_library_stats │
├─────────────────────────────────────────────────────────┤
│ Services Layer │
│ browser.ts (Playwright scroll + JS injection) │
│ database.ts (SQLite CRUD + search) │
│ markdown.ts (Structured doc generation) │
├─────────────────────────────────────────────────────────┤
│ Data Layer │
│ SQLite: components, tags, component_tags │
│ File: design-library.db │
└─────────────────────────────────────────────────────────┘
design-intelligence-mcp-server/
├── package.json
├── tsconfig.json
├── README.md
├── src/
│ ├── index.ts # Main entry — server init + tool registration
│ ├── types.ts # All TypeScript interfaces and types
│ ├── constants.ts # Shared configuration constants
│ ├── schemas/
│ │ └── index.ts # Zod validation schemas for all tool inputs
│ ├── tools/
│ │ └── index.ts # Tool handler implementations
│ ├── services/
│ │ ├── browser.ts # Playwright scroll capture + animation detection
│ │ ├── database.ts # SQLite database operations
│ │ └── markdown.ts # Component documentation generator
│ └── utils/ # (Future) shared utilities
└── dist/ # Compiled JavaScript output
npm install
npx playwright install chromium
npm run build| Env Variable | Default | Description |
|---|---|---|
DI_DB_PATH |
./design-library.db |
SQLite database file path |
TRANSPORT |
stdio |
Transport mode: stdio or http |
PORT |
3100 |
HTTP port (when TRANSPORT=http) |
Add to your MCP settings:
{
"mcpServers": {
"design-intelligence": {
"command": "node",
"args": ["/path/to/design-intelligence-mcp-server/dist/index.js"],
"env": {
"DI_DB_PATH": "/path/to/your/design-library.db"
}
}
}
}TRANSPORT=http PORT=3100 node dist/index.jsPurpose: Navigate to a URL, scroll the page, detect all animation events. When to use: First step — reconnaissance of a site's animations. Returns: Animation events, detected libraries, optional screenshots.
Purpose: Extract structured component data (HTML, CSS, JS) for animated elements. When to use: After scroll capture, to get implementable code for specific components. Returns: Array of ExtractedComponent objects.
Purpose: Save a component to the library with ratings, tags, and markdown docs. When to use: When you've extracted a component worth saving. Returns: Confirmation + full markdown documentation.
Purpose: Search and retrieve saved components. When to use: When building sites and need animation patterns. Returns: Matching components with documentation and code.
Purpose: Full pipeline in one call — capture, extract, catalog. When to use: Quick library building from inspiration sites. Returns: Summary of all captured components.
Purpose: Remove a component from the library.
Purpose: View library statistics (counts by category, library, etc.).
User: "Capture all premium animations from cosmos.so"
→ di_capture_and_catalog(url="https://www.cosmos.so/", custom_tags=["inspiration", "premium"])
User: "Now do the same for Intercom's suite page"
→ di_capture_and_catalog(url="https://www.intercom.com/suite", custom_tags=["saas", "enterprise"])
User: "Show me what's in my library"
→ di_library_stats()
User: "I need a premium hero animation for a plumber website"
→ di_search_library(category="hero", min_premium_feel=4, min_reusability=3)
→ Returns: Markdown with HTML/CSS/JS code ready to adapt
User: "Find scroll-triggered text reveals that use GSAP"
→ di_search_library(library="gsap-scrolltrigger", category="text-reveal")
Build and test each piece in this order:
-
Database service (
services/database.ts) — Already functional. Test: init DB, save/search/delete. -
Markdown service (
services/markdown.ts) — Already functional. Test: pass mock ExtractedComponent, verify output. -
Browser service (
services/browser.ts) — This is the hardest part. Build incrementally:- a.
launchBrowser()/closeBrowser()— Basic Playwright lifecycle - b.
detectAnimationLibraries()— Page evaluation for library detection - c.
injectAnimationObservers()— THE CORE — JS injection for mutation/intersection/animation events - d.
performScrollCapture()— Orchestration of scroll + event collection - e.
extractElementDetails()— Per-element HTML/CSS/JS extraction
- a.
-
Tool handlers (
tools/index.ts) — Wire up services to MCP responses. The helper functions (inferLibrary, inferCategory, etc.) are heuristic and should be refined with real data. -
Main entry (
index.ts) — Already functional. Tool registrations are complete.
Challenge 1: Smooth Scroll Libraries
Sites using Lenis/Locomotive intercept normal scroll. Solution: Use window.scrollTo({ top: y, behavior: 'instant' }) instead of page.mouse.wheel().
Challenge 2: GSAP Timeline Hook
Not all GSAP versions expose globalTimeline.getChildren(). Wrap in try/catch and fall back to MutationObserver detection.
Challenge 3: Cross-Origin Stylesheets
document.styleSheets throws on cross-origin CSS. Always wrap in try/catch.
Challenge 4: React/Next.js Hydration
Some sites show loading states until React hydrates. The wait_for_load_ms parameter addresses this — default 5000ms, increase for heavy SPAs.
Challenge 5: Bot Detection
Some sites block headless browsers. The custom user agent helps, but some sites need Playwright's --disable-blink-features=AutomationControlled flag.
Test with these sites (increasing complexity):
- Simple AOS site — Any site using
data-aosattributes - GSAP + ScrollTrigger — https://gsap.com/showcase/
- Lenis smooth scroll — https://lenis.darkroom.engineering/
- Framer Motion — https://www.framer.com/motion/
- Premium production — https://www.cosmos.so/, https://dovetail.com/, https://www.intercom.com/suite
- Visual diff screenshots — Before/after animation state comparison
- Video capture — Record scroll as MP4 for visual reference
- Component playground — Serve extracted components in an isolated HTML preview
- Supabase migration — Move from SQLite to Supabase for team sharing
- Integration with Hydrate Website Template skill — Query library during site generation