coolors-mcp
by x51xxx
README.md
# Coolors MCP
A Model Context Protocol (MCP) server that gives AI assistants real color tools: perceptual color descriptions, WCAG 2.x and APCA contrast checks with exact fixes, Material Design 3 themes built on Google's HCT, palettes and gradients, color-vision-deficiency checks, CSS theme matching and refactoring, image color extraction, and DESIGN.md audits.
- **31 tools**, all read-only and local: no API keys, no network access, stdio transport.
- **Documentation:** <https://x51xxx.github.io/coolors-mcp/>
- **Changelog:** [CHANGELOG.md](CHANGELOG.md)
## Features
- **Colors an agent can "see"**: `describe_color` turns a hex code into a name, temperature, lightness/vividness, OKLCH/HCT/HSL/RGB values, the best text color and likely UI roles.
- **Contrast without guessing**: WCAG 2.x ratio and APCA Lc (matches `apca-w3` 0.1.9) side by side; `fix_contrast` finds the closest same-hue color that meets AA, AAA, UI or an APCA target.
- **Google's HCT**: the CAM16-based HCT from [`@material/material-color-utilities`](https://github.com/material-foundation/material-color-utilities) drives Material themes, tonal palettes and scales, state colors, harmonization and dislike detection.
- **Material Design 3**: light and dark schemes, tonal palettes, harmonization, and CSS custom properties from one source color.
- **UI palettes**: a contrast-checked light + dark 60-30-10 UI token set, semantic (primary/secondary/tertiary + status) palettes, Tailwind-style tonal scales, interaction-state colors and a palette cohesion score.
- **Palettes and gradients**: color-harmony palettes (HCT, OKLCH, RYB or HSL wheel), palettes with locked colors, gradients interpolated in OKLCH, OKLab, Lab, LCh, HCT, HSL or RGB, and color-blind-safe categorical palettes for charts.
- **Color-vision deficiency**: simulation of 7 deficiency types (Machado et al. 2009 matrices in linear sRGB for the protan, deutan and tritan types; achromatopsia as a grey of equal luminance) and pairwise collision audits of palettes.
- **Distance metrics**: ΔE2000, ΔE94, ΔE76, Euclidean RGB and weighted RGB.
- **CSS theme matching**: map hard-coded colors to your theme's custom properties, and rewrite a stylesheet to use them.
- **Images**: dominant colors with Celebi quantization, and a Material theme from an image.
- **Dislike analysis**: detect and fix "bile zone" dark yellow-greens.
- **Export**: CSS custom properties, SCSS, Tailwind config, W3C design tokens, JSON, or a DESIGN.md `colors:` block.
- **DESIGN.md audits**: contrast, color-blind collisions, duplicates and broken references in a [DESIGN.md](https://github.com/google-labs-code/design.md) file.
## Installation
Requires **Node.js 20 or newer** and an MCP client. The package runs with `npx`, so there is nothing to install first.
### Claude Code
```bash
claude mcp add coolors -- npx -y @trishchuk/coolors-mcp
```
Run `/mcp` in Claude Code to check that `coolors` is connected.
### Claude Desktop, Cursor and other MCP clients
Add the server to the client's MCP configuration (for Claude Desktop, `claude_desktop_config.json`), then restart the client:
```json
{
"mcpServers": {
"coolors": {
"command": "npx",
"args": ["-y", "@trishchuk/coolors-mcp"]
}
}
}
```
### Global install
```bash
npm install -g @trishchuk/coolors-mcp
claude mcp add coolors -- coolors-mcp
```
In JSON configs, use `"command": "coolors-mcp"` with no `args`.
### From source
```bash
git clone https://github.com/x51xxx/coolors-mcp.git
cd coolors-mcp
pnpm install
pnpm run build
```
Then point your client at the built server: `"command": "node"`, `"args": ["/absolute/path/to/coolors-mcp/dist/bin/server.js"]`.
The server has no configuration options or environment variables. The metadata for the official MCP Registry (`io.github.x51xxx/coolors-mcp`) is in [`server.json`](server.json); the registry listing goes live with the next npm release.
More setup detail: [Installation](https://x51xxx.github.io/coolors-mcp/installation) · [Troubleshooting](https://x51xxx.github.io/coolors-mcp/resources/troubleshooting)
## Quick example
Ask your assistant _"Is #6366f1 readable on white? Fix it if not."_ It calls `check_contrast`:
```json
{ "foreground": "#6366f1", "background": "#ffffff" }
```
```text
## WCAG 2.x luminance ratio
Contrast Ratio: 4.47:1
- AA (normal text): ✗ Fail (need 4.5:1)
- AA (large text): ✓ Pass (need 3:1)
- AAA (normal text): ✗ Fail (need 7:1)
- AAA (large text): ✗ Fail (need 4.5:1)
## Agent Guidance
- **Nearest AA fix (hue-preserving)**: foreground `#6365f0` on `#ffffff` → 4.52:1 (APCA Lc 70.9, ΔE=0.4)
```
## Tools
All 31 tools, grouped as in the [tools reference](https://x51xxx.github.io/coolors-mcp/tools/README). Every tool takes colors as strings in any [supported format](#supported-color-formats).
### Agent tools ([docs](https://x51xxx.github.io/coolors-mcp/tools/agent-tools))
| Tool | What it does |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `describe_color` | Describes up to 20 colors in human terms: name, temperature, lightness and vividness, OKLCH/HCT/HSL/RGB, readable text color, UI roles, pitfalls. |
| `fix_contrast` | Finds the closest same-hue color that meets `aa`, `aaa`, `aa-large`, `ui`, `apca-body`, `apca-content` or `apca-large`. Adjusts foreground, background or either. |
| `design_ui_palette` | Builds a contrast-checked light + dark UI token set (60-30-10) from one brand color, as a report, CSS, JSON or W3C tokens. |
| `audit_ui_colors` | Audits up to 100 foreground/background pairs and 64 swatches: WCAG, APCA, CVD contrast drops, vibration and disliked colors, with fixes. |
| `generate_categorical_palette` | Generates 2–12 chart or tag colors that stay distinct for normal vision and protan/deutan/tritan viewers. |
```json
{ "foreground": "#9e9e9e", "background": "#ffffff", "target": "aa" }
```
`fix_contrast` returns:
```text
# Accessible Contrast Solution (aa)
- **Status**: ✓ Target achieved
- **Adjusted**: foreground (ΔE2000 shift = 14.12)
- **Before**: `#9e9e9e` on `#ffffff` → 2.68:1 (APCA Lc 52.1)
- **After**: `#767677` on `#ffffff` → **4.54:1** (APCA Lc **71.5**)
```
### Color operations ([docs](https://x51xxx.github.io/coolors-mcp/tools/color-operations))
| Tool | What it does |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `convert_color` | Converts a color to `hex`, `rgb`, `hsl`, `lab`, `hct`, `oklab` or `oklch`. |
| `color_distance` | Perceptual distance between two colors: `deltaE2000` (default), `deltaE94`, `deltaE76`, `euclidean` or `weighted`. |
| `check_contrast` | WCAG 2.x ratio, APCA Lc or both, with CVD warnings and the nearest same-hue AA fix when a pair fails. |
| `adjust_color` | `lighten`, `darken`, `saturate`, `desaturate`, `hue-shift`, `tint`, `shade`, `grayscale`, `invert` or `mix`, in OKLCH (default), HCT or HSL. |
| Call | Result |
| ------------------------------------------------------------------------------------------- | -------------------------------------------- |
| `convert_color` `{"color": "#6750a4", "to": "hct"}` | `hct(299.0, 47.9, 40.1)` |
| `convert_color` `{"color": "rebeccapurple", "to": "oklch"}` | `oklch(44.0% 0.1603 303.4)` |
| `color_distance` `{"color1": "#6750a4", "color2": "#7f67be"}` | `Distance between #6750a4 and #7f67be: 8.80` |
| `adjust_color` `{"color": "#6750a4", "operation": "lighten", "amount": 10}` | `#846ec5` |
| `adjust_color` `{"color": "#6750a4", "operation": "mix", "with": "#ff6b6b", "amount": 0.5}` | `#b1648e` |
### Accessibility ([docs](https://x51xxx.github.io/coolors-mcp/tools/accessibility))
| Tool | What it does |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `simulate_color_blindness` | Shows how up to 64 colors look under protanopia, deuteranopia, tritanopia, the three anomalies and achromatopsia. |
| `check_palette_accessibility` | Flags palette pairs whose ΔE2000 falls below a threshold (default 10) under each deficiency type. |
`check_contrast` (above) covers text/background pairs. With `"algorithm": "both"`, black on white gives `Contrast Ratio: 21.00:1` and `Lc: 106.0 (dark text on light bg)`.
### Palettes ([docs](https://x51xxx.github.io/coolors-mcp/tools/palettes))
| Tool | What it does |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `generate_palette` | Color-harmony palette (monochromatic, analogous, complementary, split-complementary, triadic, tetradic, square, compound, shades-and-tints), 3–12 colors. |
| `generate_palette_with_locks` | Palette of 2–20 colors that keeps your locked colors, in `harmony`, `contrast` or `gradient` mode. |
| `generate_gradient` | Gradient of `steps` total colors (every input color is kept) as an array, hex list or CSS `linear-gradient`/`radial-gradient`. |
| `export_palette` | Exports up to 256 colors as `css`, `scss`, `tailwind`, `tokens` (W3C), `json` or `design-md`. |
```json
{
"colors": ["#6750a4", "#ff6b6b"],
"steps": 5,
"interpolation": "oklch",
"format": "css-linear"
}
```
`generate_gradient` returns:
```text
linear-gradient(90deg, #6750a4 0.0%, #9153a9 25.0%, #ba57a1 50.0%, #e05d8c 75.0%, #ff6b6b 100.0%)
```
`export_palette` with `"format": "design-md"` writes a `colors:` block for a DESIGN.md front matter:
```json
{
"colors": ["#6750a4", "#625b71", "#7e5260"],
"format": "design-md",
"names": ["primary", "secondary", "tertiary"]
}
```
```yaml
colors:
primary: "#6750a4"
secondary: "#625b71"
tertiary: "#7e5260"
```
### Visual cohesion ([docs](https://x51xxx.github.io/coolors-mcp/tools/cohesion))
| Tool | What it does |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `generate_tonal_scale` | Tailwind-style 50–950 scale (or custom stops) from a seed color; stop 50 is HCT tone 95, 500 is tone 50, 950 is tone 5. Includes CSS variables. |
| `generate_state_colors` | Hover, active, pressed, focus, disabled and selected colors from a base color, for light or dark surfaces. |
| `analyze_palette_consistency` | Scores tonal step uniformity, chroma cohesion and hue harmony, with an overall 0–100 cohesion score. |
| `generate_semantic_palette` | Primary, secondary, tertiary and success/warning/error/info colors with matched tone and chroma. |
`analyze_palette_consistency` with `{"colors": ["#6750a4", "#7f67be", "#a48dc8", "#ff0000"]}` scores the palette 75/100 and reports `Likely outlier: #ff0000 (chroma 113 vs avg 61).`
### Material Design 3 ([docs](https://x51xxx.github.io/coolors-mcp/tools/material-design))
| Tool | What it does |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `generate_material_theme` | Light and dark Material 3 schemes (primary, secondary, tertiary, error, surface roles) from a source color. |
| `harmonize_colors` | For 2–10 colors: `harmonize` shifts each hue toward the first color, `blend` mixes them into one, `temperature` warms or cools them. |
| `generate_tonal_palette` | Material tonal palette for the standard tones or your own list of tones (0–100). |
`generate_material_theme` with `{"sourceColor": "#6750a4"}` returns, among others, `primary: #6750a4`, `primaryContainer: #e9ddff` and `onPrimaryContainer: #22005d` for the light scheme, and `primary: #cfbcff` and `onPrimary: #381e72` for the dark scheme.
### CSS theme matching ([docs](https://x51xxx.github.io/coolors-mcp/tools/theme-matching))
| Tool | What it does |
| -------------------------- | --------------------------------------------------------------------------------------------------- |
| `match_theme_color` | Finds the theme custom property closest to a color, with a confidence score. |
| `match_theme_colors_batch` | The same for up to 50 colors. |
| `refactor_css_with_theme` | Rewrites hard-coded colors in declaration values to `var(--…)` references, with an optional report. |
| `generate_theme_css` | Material tonal palettes and light-theme role mappings as CSS custom properties. |
```json
{
"css": ".button { background: #6850a0; color: #fffbfe; }",
"themeCSS": ":root { --color-primary: #6750a4; --color-surface: #fffbfe; --color-on-surface: #1c1b1f; }"
}
```
`refactor_css_with_theme` rewrites the rule to:
```text
.button { background: /* #6850a0 */ var(--color-primary); color: /* #fffbfe */ var(--color-surface); }
```
### Images and color psychology ([docs](https://x51xxx.github.io/coolors-mcp/tools/image-extraction))
| Tool | What it does |
| --------------------------- | ----------------------------------------------------------------------------------------------- |
| `extract_image_colors` | Dominant colors of an RGBA image (Celebi quantization) as JSON, CSS or a palette. |
| `generate_theme_from_image` | A Material 3 theme seeded from an image's colors. |
| `analyze_color_likability` | Checks whether a color is a universally disliked dark yellow-green and returns a fixed version. |
| `fix_disliked_colors_batch` | Checks up to 100 colors and returns liked versions. |
Images are passed as raw pixels: `{"imageData": {"width": 4, "height": 4, "data": [103, 80, 164, 255, …]}}`, a flat RGBA array of `width × height × 4` integers. `analyze_color_likability` with `{"color": "#6b6b00"}` reports the color as disliked and suggests `#b0b048`.
### DESIGN.md ([docs](https://x51xxx.github.io/coolors-mcp/tools/design-md))
| Tool | What it does |
| ----------------- | ---------------------------------------------------------------------------------------------------------------- |
| `audit_design_md` | Audits the color tokens of a [DESIGN.md](https://github.com/google-labs-code/design.md) file and suggests fixes. |
It reads the YAML front matter and ` ```yaml ` blocks, and checks WCAG and APCA contrast for pairs declared in `components` (`backgroundColor`/`textColor`) and pairs inferred from token names (`on-X` ↔ `X`, text ↔ surface tokens). It also reports color-blind collisions between accent and status colors, exact and near-duplicate tokens, disliked colors, broken `{colors.x}` references and a missing `primary`. Failing pairs get a same-hue fix. Values the auditor cannot evaluate (`hwb()`, `lab()`, `lch()`, `color()`, `color-mix()`, `transparent`) are listed, never guessed.
```json
{
"designMd": "---\nname: Acme\ncolors:\n primary: \"#cc785c\"\n on-primary: \"#ffffff\"\n---\n",
"textThreshold": 4.5,
"cvdThreshold": 10
}
```
```text
…
| `on-primary` #ffffff | `primary` #cc785c | inferred · on-X ↔ X | 3.28:1 | 4.5:1 (text) | -65.3 | ✗ | on-primary → `#262829` (4.52:1) |
…
```
Claude Code does not load DESIGN.md on its own: reference it as `@DESIGN.md` from your `CLAUDE.md`.
## Supported color formats
Every color parameter accepts:
| Format | Examples |
| --------------------- | ---------------------------------------------------------------- |
| Hex | `#639`, `#6750a4`, `#6750a4ff` (alpha is ignored), bare `6750a4` |
| CSS named colors | `rebeccapurple`, `white` |
| `rgb()` / `rgba()` | `rgb(103, 80, 164)`, `rgb(103 80 164)`, `rgb(40% 31% 64%)` |
| `hsl()` / `hsla()` | `hsl(256, 34%, 48%)`, `hsl(256 34% 48%)` |
| `oklch()` / `oklab()` | `oklch(49.6% 0.1305 293.7)`, `oklab(0.496 0.03 -0.12)` |
| `hct()` | `hct(299, 47.9, 40.1)` |
`rgb()` channels are clamped to 0–255 as in CSS, `hsl()` hues wrap around. Not supported: `hwb()`, `lab()`, `lch()`, `color()`, `color-mix()` and `transparent`. Invalid hex such as `#ggg` or `#12345` is rejected. `convert_color` can output `lab(…)`, but that output is not accepted back as input.
## Errors and limits
Errors come back as normal tool results with `isError: true` and a message the model can read and act on:
- Unparseable color: `Invalid color format: nope`
- Wrong type, missing parameter or a value over a limit: `Invalid arguments for tool 'convert_color': color: Invalid input: expected string, received number`
- Tool-specific checks, for example `steps (3) must be at least the number of input colors (4)` from `generate_gradient`.
Calling a tool name that does not exist is a JSON-RPC protocol error, not a tool result.
Main input limits (the [tools reference](https://x51xxx.github.io/coolors-mcp/tools/README) lists all of them):
| Input | Limit |
| ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| `describe_color` colors | 20 |
| `simulate_color_blindness`, `check_palette_accessibility`, `analyze_palette_consistency` colors | 64 |
| `generate_gradient` colors / steps | 32 / 3–100 |
| `audit_ui_colors` pairs / swatches | 100 / 64 |
| `fix_disliked_colors_batch` colors | 100 |
| `export_palette` colors | 256 |
| `themeCSS` | 200 000 characters |
| `css` (`refactor_css_with_theme`), `designMd` | 500 000 characters |
| `imageData` | 65 536 pixels (e.g. 256×256), `data.length` = `width × height × 4` |
## How it works
- **HCT** is Google's CAM16-based color space from `@material/material-color-utilities`: hue and chroma come from CAM16, tone is CIE L\*. For example, `#6750a4` is `hct(299.0, 47.9, 40.1)`. See [HCT](https://x51xxx.github.io/coolors-mcp/concepts/hct).
- **Theme matching** scores each theme variable by HCT distance (60%), semantic role for the usage context (20%) and tone suitability (20%). See [Theme matching](https://x51xxx.github.io/coolors-mcp/concepts/theme-matching).
- **Theme parsing** reads `--name: value;` custom properties anywhere in `themeCSS`, light and dark blocks alike. Only opaque colors count; `var()` aliases are not resolved.
- **Refactoring** only touches colors inside declaration values. Selectors, comments, strings, `url(…)`, custom-property definitions and translucent colors are left alone; translucent colors get a warning.
## Development
This project uses [pnpm](https://pnpm.io). Install it with `npm i -g pnpm` or `corepack enable`.
```bash
pnpm install # install dependencies
pnpm run build # build to dist/
pnpm test # run the test suite
pnpm run lint # prettier --check, eslint, tsc --noEmit
pnpm run format # prettier --write, eslint --fix
pnpm run docs:dev # documentation site
```
To try the tools interactively, run the built server under the MCP Inspector:
```bash
npx @modelcontextprotocol/inspector node dist/bin/server.js
```
Source layout:
```
src/
├── bin/server.ts # MCP server entry: registers all tools
├── tools/ # one file per tool group
├── color/ # conversions, HCT, APCA, CVD simulation, metrics, quantization, DESIGN.md parsing
└── theme/ # CSS theme parsing, matching and refactoring
```
## Contributing
Contributions are welcome. Before opening a pull request, make sure `pnpm test` and `pnpm run lint` pass.
## License
MIT © [Taras Trishchuk](https://trishchuk.com)
## Credits
- Built on the [Model Context Protocol](https://modelcontextprotocol.io/) TypeScript SDK.
- HCT, Material color schemes and the Celebi quantizer come from or follow Google's [Material Color Utilities](https://github.com/material-foundation/material-color-utilities).
- APCA contrast follows [`apca-w3`](https://github.com/Myndex/apca-w3); color-vision simulation for the protan, deutan and tritan types uses the matrices of Machado, Oliveira and Fernandes (2009).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo recent community issues