Skip to main content
Glama
README.md
# 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

A4.4/5.0

Scored across 6 tools

Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness5/5

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.

Maintenance

ActivityMaintained
ResponsivenessNo issues