Kroma MCP
# Kroma MCP — `@kromamcp/server`
> A completely **stateless**, internet-connected [Model Context Protocol](https://modelcontextprotocol.io) server for **UI/UX design inspiration**, **live component discovery**, and **modern web micro-effects**.
Kroma turns your AI assistant into a design scout. Ask for "a glassmorphic pricing card in React", "a grainy mesh gradient hero as CSS", "hand-drawn rocket icons", or "OG image inspiration for a dev tool" and Kroma resolves it **live** from the best design galleries, component libraries, gradient generators, icon sets, and code playgrounds on the internet — no local database, no cache, no stored files.
Every request is resolved in real time via the [Serper](https://serper.dev) API (Google Search / Images / Scrape).
---
## ✨ Highlights
- **Completely stateless** — zero databases, zero local caches, zero file storage. Every answer is fetched fresh.
- **Real-time internet resolution** — live queries against curated design galleries, component docs, and code repos.
- **Multi-tenant & zero-config** — connect and go. Keys resolve per-request from the environment or a tool argument.
- **Two transports** — `stdio` for desktop/IDE hosts, and Streamable **HTTP + SSE** for remote hosting.
- **10 specialized tools** — UI inspiration, graphic & brand inspiration, components, effects/shaders, backgrounds & gradients, icons & logos, site scraping, open web search, source discovery, and engineering-blueprint generation.
- **Smart source routing** — every curated source is tagged, so asking for a *mesh gradient as CSS* or an *OG image* hits only the handful of sources that actually serve it.
---
## 🔑 Prerequisites
1. **Node.js ≥ 18**
2. **A Serper API key** — grab a free one at **[serper.dev](https://serper.dev)** (2,500 free credits to start).
Set it as an environment variable:
```bash
export SERPER_API_KEY="your_serper_key_here"
```
> You can also pass a per-call `api_key` argument to any tool — it takes precedence over the env var. This is what makes Kroma multi-tenant: different callers can bring their own key.
---
## 🚀 Quickstart (npx)
No install required — run the latest published version directly:
```bash
SERPER_API_KEY=your_key npx -y @kromamcp/server
```
That starts the server on **stdio**, ready for any MCP host.
---
## 🧰 The Tools
| Tool | What it does |
| --- | --- |
| `kroma_find_ui_inspiration` | Searches live galleries (Mobbin, Godly, Awwwards, Dribbble, Lapa Ninja, Minimal Gallery, Land-book, Saaspo, Inspora, Behance…) via **Google Images** for visual UI/UX inspiration. |
| `kroma_find_graphic_inspiration` | Mood-boards the artifacts that **aren't a web page** — social posts, pitch decks, OG images, logos, footers, branding, print. `asset` routes straight to the specialist gallery: posts.design, Deck.gallery, OGFolio, Logoinspo, Footer.design. |
| `kroma_find_component_code` | Searches component libraries & docs (shadcn/ui, Magic UI, Aceternity, Uiverse, Tailwind, Radix, Headless UI, Flowbite, daisyUI, beUI Pro, GitHub…) for copy-paste **React / Vue / Svelte** components. |
| `kroma_find_effects_and_shaders` | Discovers **GLSL/canvas shaders, Framer Motion variants, GSAP scroll timelines, glassmorphism, glowing borders, Three.js** and more from CodePen, Shadertoy, Codrops, GitHub, and blogs. |
| `kroma_find_backgrounds_and_gradients` | Finds **gradients, grain/noise textures, mesh & animated backgrounds, patterns, and color palettes** from asset libraries and live generators — Grainient, Backgrounds Supply, Pryzm, ColorFlow, zoxilsi studio, Gradientool, CSS Gradient, Tabbied, Ramps, beUI Pro. Returns results **plus the matched generators with direct URLs**. |
| `kroma_find_icons_and_logos` | Searches icon sets and brand-mark libraries — Koboyo (**133,000+ free hand-drawn SVGs**), Logoinspo (1,200+ curated logos), SVGL, Simple Icons, Lucide, Phosphor, Tabler, Heroicons, Hugeicons, Iconify, Streamline, Noun Project. |
| `kroma_scrape_site_design` | Scrapes any live URL and extracts **layout, typography outline, fonts, color palette, and CSS/framework fingerprints** (Tailwind, Radix, Framer, Next.js…). |
| `kroma_search_design_web` | General-purpose design/front-end **web search**, optionally scoped to specific domains. For anything the specialized tools don't cover. |
| `kroma_list_sources` | Lists all six curated source registries so the agent can discover exact `sources` names and routing `tags`. **Runs offline — no API key needed.** |
| `kroma_generate_blueprint` | Generates a full **engineering blueprint (`.md`)** for a larger project — overview, architecture, stack, data model, milestones, testing, plus optional **live** design/component/effect references. Returns the Markdown for you to save (stateless — writes no files). |
### Example tool arguments
```jsonc
// kroma_find_ui_inspiration
{ "query": "fintech dashboard dark mode", "sources": ["Mobbin", "Awwwards"], "num": 12 }
// kroma_find_component_code
{ "component": "command palette", "framework": "react", "keywords": "tailwind accessible" }
// kroma_find_effects_and_shaders
{ "effect": "animated glowing border", "category": "glow", "framework": "react" }
// kroma_find_graphic_inspiration
{ "query": "developer tool launch announcement", "asset": "social-post", "num": 12 }
{ "query": "seed round pitch deck", "asset": "deck" }
{ "query": "dark OG image with product screenshot", "asset": "og-image" }
// kroma_find_backgrounds_and_gradients
{ "look": "dark purple hero backdrop", "style": "mesh", "format": "css" }
{ "look": "warm grainy noise texture", "style": "grainy", "include_previews": true }
{ "look": "accessible brand color ramp", "style": "palette", "format": "code" }
// kroma_find_icons_and_logos
{ "query": "rocket deploy", "kind": "icon", "style": "hand-drawn", "free_only": true }
{ "query": "minimal fintech symbol", "kind": "logo" }
// kroma_scrape_site_design
{ "url": "https://linear.app", "include_markdown": true }
// kroma_search_design_web
{ "query": "design tokens naming conventions", "sites": ["web.dev", "smashingmagazine.com"] }
// kroma_generate_blueprint
{ "project": "Fintech onboarding dashboard", "kind": "dashboard", "stack": ["Next.js", "TypeScript", "Postgres"], "goals": ["Reduce drop-off", "SOC2-ready"], "depth": "deep" }
```
Every tool returns both a readable JSON text block **and** `structuredContent`. Errors come back as graceful `isError` results (with an `auth` / `request` / `unknown` `kind`) instead of crashing the session.
### Honest results
Google silently drops the `site:` operator when the scoped domains have a thin search index — and several of the best galleries (Deck.gallery, OGFolio, Footer.design, Ramps) are recent single-page apps with almost nothing indexed. So the three routing tools tell you exactly what you got:
| Field | Meaning |
| --- | --- |
| `curatedSource` | Per result: the curated source it actually came from, or `null` if it's off-registry. Curated hits are sorted first. |
| `curatedCount` | How many of the returned results genuinely came from the curated set. |
| `widened` | `true` if the narrow route returned nothing and Kroma retried across the full registry. |
| `hint` | Set only when `curatedCount` is 0 — names the gallery URLs to open or pass to `kroma_scrape_site_design`, which reads these SPAs reliably even when Google can't. |
`generators` / `galleries` / `libraries` always carry the matched sources with direct URLs. For a single-page generator like ColorFlow or Pryzm, **that URL is the answer** — there's no article to find.
---
## 🖥️ Client Setup
### Claude Desktop
Edit the config file:
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"kroma": {
"command": "npx",
"args": ["-y", "@kromamcp/server"],
"env": {
"SERPER_API_KEY": "your_serper_key_here"
}
}
}
}
```
Restart Claude Desktop. You'll see the Kroma tools appear under the tools menu.
### Cursor
Add to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project):
```json
{
"mcpServers": {
"kroma": {
"command": "npx",
"args": ["-y", "@kromamcp/server"],
"env": { "SERPER_API_KEY": "your_serper_key_here" }
}
}
}
```
### Windsurf
Add to `~/.codeium/windsurf/mcp_config.json`:
```json
{
"mcpServers": {
"kroma": {
"command": "npx",
"args": ["-y", "@kromamcp/server"],
"env": { "SERPER_API_KEY": "your_serper_key_here" }
}
}
}
```
### Roo Code
In the Roo Code MCP settings (`mcp_settings.json`), add:
```json
{
"mcpServers": {
"kroma": {
"command": "npx",
"args": ["-y", "@kromamcp/server"],
"env": { "SERPER_API_KEY": "your_serper_key_here" },
"alwaysAllow": [
"kroma_find_ui_inspiration",
"kroma_find_graphic_inspiration",
"kroma_find_component_code",
"kroma_find_effects_and_shaders",
"kroma_find_backgrounds_and_gradients",
"kroma_find_icons_and_logos",
"kroma_scrape_site_design",
"kroma_search_design_web",
"kroma_list_sources",
"kroma_generate_blueprint"
]
}
}
}
```
---
## 🌐 Remote Hosting (HTTP + SSE)
For a shared, always-on deployment, run Kroma over HTTP:
```bash
SERPER_API_KEY=your_key npx -y @kromamcp/server --transport http --port 3000
# or: KROMA_TRANSPORT=http PORT=3000 npx -y @kromamcp/server
```
This exposes:
| Path | Method | Purpose |
| --- | --- | --- |
| `/mcp` | POST / GET / DELETE | **Streamable HTTP** transport (modern, recommended) |
| `/sse` | GET | **Legacy SSE** stream (Cursor / Windsurf compatibility) |
| `/messages?sessionId=…` | POST | SSE message channel |
| `/health` | GET | Liveness probe → `{ "ok": true }` |
### Connecting a client to the SSE endpoint
Hosts that support a URL/SSE endpoint (e.g. Cursor, Windsurf) can point at:
```json
{
"mcpServers": {
"kroma": {
"url": "https://your-host.example.com/sse"
}
}
}
```
Or the Streamable HTTP endpoint:
```json
{
"mcpServers": {
"kroma": {
"url": "https://your-host.example.com/mcp"
}
}
}
```
> When self-hosting, provide `SERPER_API_KEY` in the server's environment, **or** have each caller pass an `api_key` tool argument for true multi-tenant, bring-your-own-key operation.
---
## ⚙️ Configuration
| Variable | Default | Description |
| --- | --- | --- |
| `SERPER_API_KEY` | — | **Required** (unless passing `api_key` per call). Your Serper key. |
| `SERPER_TIMEOUT_MS` | `20000` | Per-request timeout in milliseconds. |
| `KROMA_TRANSPORT` | `stdio` | `stdio` or `http`. |
| `PORT` / `KROMA_PORT` | `3000` | HTTP port (http transport). |
| `KROMA_HOST` | `0.0.0.0` | HTTP bind host (http transport). |
CLI flags: `--transport <stdio|http>`, `--http`, `--port <n>`, `--host <h>`, `--help`, `--version`.
---
## 🛠️ Local Development
```bash
git clone <this-repo>
cd kroma-mcp
npm install
npm run build # compile TypeScript → dist/
npm start # run the compiled server (stdio)
npm run dev # tsc --watch
npm run typecheck # type-check without emitting
```
### Project layout
```
src/
index.ts # entry point + stdio/http transports
services/serper.ts # stateless Serper API gateway (search/images/scrape)
lib/
sources.ts # curated source registries + query builders
response.ts # MCP result helpers + error guard
tools/
find-ui-inspiration.ts
find-graphic-inspiration.ts
find-component-code.ts
find-effects-and-shaders.ts
find-backgrounds-and-gradients.ts
find-icons-and-logos.ts
scrape-site-design.ts
search-design-web.ts
list-sources.ts
generate-blueprint.ts
```
### Adding a source
Every source is a `CuratedSource` in `src/lib/sources.ts`:
```ts
{
name: "Grainient",
domain: "grainient.supply",
note: "1,000+ grainy, smooth, and animated gradients plus AI backgrounds and a shader tool",
tags: ["grainy", "animated", "mesh", "ai", "shader", "image"],
}
```
Drop it into the right registry (`INSPIRATION_SOURCES`, `COMPONENT_SOURCES`, `EFFECT_SOURCES`, `GRAPHIC_SOURCES`, `BACKGROUND_SOURCES`, `ICON_SOURCES`) and it's live — `kroma_list_sources` reads the arrays directly and the search tools build `site:` queries from them. `name` is what callers pass in `sources`; `tags` are what the `asset` / `style` / `format` / `kind` filters match against.
### Architecture principles
- **Stateless by construction.** No module holds user data between requests; HTTP sessions live only in-memory for the process lifetime and store no personal data.
- **Dynamic key resolution.** `resolveApiKey(explicit?)` prefers an explicit `api_key` argument, then `SERPER_API_KEY`. Nothing is persisted.
- **Graceful failure.** Network errors, timeouts, and auth failures become typed, readable tool errors — never uncaught throws.
- **Widening fallbacks.** Source filters never return an empty set: an unrecognised name or an over-narrow tag combination widens back to the parent registry, so a bad argument degrades into a broader search instead of zero results.
---
## 📄 License
[MIT](./LICENSE) © 2026 Kroma MCP
TDQS
Scored across 6 tools
Each tool targets a distinct purpose: finding visual inspiration, scraping site metadata, general web search, listing sources, finding components, and finding effects. The overlap between find_ui_inspiration and search_design_web is minimal and clearly differentiated by scope.
All tool names follow the consistent pattern 'kroma_<verb>_<noun>' in snake_case. Verbs are varied but always action-oriented, and the nouns clearly indicate the resource type, making the naming predictable and readable.
With 6 tools, the server is well-scoped for design discovery and analysis. Each tool covers a distinct aspect of the workflow without redundancy, and the count is neither too thin nor overwhelming.
The tool set covers the full lifecycle implied by the domain: finding inspiration, scraping live sites, searching the web, listing available sources, and locating components and effects. There are no obvious missing operations for the server's stated purpose.