color-engine-mcp について
color-engine-mcp は、解析、変換、コントラスト検査、色域マッピング、色階生成を行うインメモリの CSS カラーツール群です。デザインや開発向けで、WCAG 2.1 に対応し、APCA の計算も選択できます。
主な機能
- 01CSS カラー形式の解析と変換
- 02WCAG 2.1 と任意の APCA コントラスト計算
- 03広色域カラーを sRGB にマッピング
- 04色階とデザイントークンの生成
- 05目標コントラストを満たす前景色の探索
活用シーン
- 01文字色と背景色のアクセシビリティ検査
- 02P3 や OKLCH の色を sRGB に変換
- 03基本色からデザインシステムの色階を作成
- 04WCAG の目標に合う文字色を探索
MCP 対応
標準的な stdio MCP サーバーとして、6 種類のカラー ツールを MCP クライアントに提供します。すべての処理はインメモリで行われ、ネットワーク通信やファイル書き込みはありません。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
6掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| input | string | はい | CSS カラー文字列。例:"tomato"、"#ff6347"、"oklch(0.6 0.18 27)"(最大 256 文字) |
詳細
color-engine MCP サーバー
CSS の色を扱う 6 種類のユーティリティを提供する Model Context Protocol(MCP)サーバーです。色の解析、変換、色域マッピング、WCAG コントラスト(オプションで APCA に対応)、色合い/陰影のランプ生成(オプションでデザイントークンを出力)、コントラスト目標値に基づく色の算出を行えます。すべてのツールはメモリ内でのみ動作し、ネットワーク I/O やファイルシステムへの書き込みは行いません。
| ツール | 用途 |
|---|---|
| parse_color | 任意の CSS カラー文字列を解析し、hex、RGB、OKLCH、色域情報に変換します |
| convert_color | 色を標準的な hex/rgb/hsl/oklch 文字列に変換します |
| contrast | WCAG 2.1 のコントラスト比と適合レベルのフラグを返します。オプションで APCA Lc にも対応します |
| gamut_map | OKLCH の知覚的な彩度低減により、広色域の色を sRGB にマッピングします |
| generate_ramp | 各色見本のコントラスト情報とデザイントークン出力に対応した、色合いから陰影へのランプを生成します |
| solve_for_contrast | 背景色に対する WCAG コントラスト目標値を満たす前景色を見つけます |
この README に記載された JSON 出力はすべて、ビルド済みサーバーから MCP Inspector CLI(
npx @modelcontextprotocol/inspector --cli)で取得した実際のレスポンスです。
インストール
Node.js >= 20 が必要です。npm パッケージには color-engine-mcp の実行ファイルが含まれているため、リポジトリのクローンやビルドは不要です。クライアントは npx 経由で起動します。tools プリミティブのみを使用する標準的な stdio MCP サーバーなので、MCP 互換クライアントであれば同じ方法で登録できます。起動コマンドをクライアントに指定すると、クライアントがプロセスを起動して管理します。
Claude Code では、次のコマンドでサーバーを登録できます。
claude mcp add color-engine -- npx -y color-engine-mcp
(既定のスコープはローカルプロジェクトです。すべてのプロジェクトに登録するには --scope user を、共有の .mcp.json に書き込むには --scope project を追加してください。)
ほとんどの JSON 設定を使用するクライアントでは、次の形式をそのまま使用できます。
{
"mcpServers": {
"color-engine": {
"command": "npx",
"args": ["-y", "color-engine-mcp"]
}
}
}
一般的なクライアントにおける設定ファイルの場所は次のとおりです。
| クライアント | 設定ファイル |
|---|---|
| Claude Code | プロジェクトルートの .mcp.json |
| Claude Desktop | claude_desktop_config.json(例:macOS の場合は ~/Library/Application Support/Claude/) |
| Cursor | .cursor/mcp.json(プロジェクトごと)または ~/.cursor/mcp.json(グローバル) |
| VS Code | .vscode/mcp.json — VS Code ではトップレベルのキー名に mcpServers ではなく servers を使用します |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
その他のクライアント(Zed、JetBrains、MCP SDK 上に構築されたカスタムエージェントなど)では、ファイルの場所と、場合によってはトップレベルのキー名が異なるだけです。各クライアントの MCP サーバー登録に関するドキュメントを参照してください。
公式 MCP Registry に io.github.aimsise/color-engine-mcp として登録されています。
接続したら、エージェントに次のようなことを尋ねてみてください。
- 「#3b82f6 から 11 段階の Tailwind ランプを生成して」
- 「背景色 #1e293b に対して、コントラスト比 4.5:1 を満たすアクセシブルなテキスト色を見つけて」
クローンしたリポジトリから実行する方法については、開発を参照してください。
色入力の処理
すべてのツールは、色文字列を共通の解析境界を通して処理するため、以下のルールが一律に適用されます。
受け付ける形式。 名前付き色、16 進数表記(#rgb、#rgba、#rrggbb、#rrggbbaa)、rgb()/rgba()、hsl()/hsla()、oklch()など、culoriで解析できるCSS色文字列を受け付けます。さらに、広色域/CSS Color 4の形式にも対応しています。
color(display-p3 r g b)lab(L a b)/lch(L C h)oklab(L a b)hwb(h w b)color(rec2020 r g b)color(a98-rgb r g b)color(xyz-d65 x y z)
sRGBの範囲外の広色域入力も問題なく解析され、inGamut: falseが返されます。
{ "input": "color(display-p3 1 0 0)" }
{
"hex": "#ff0000",
"rgb": { "r": 255, "g": 0, "b": 0 },
"oklch": { "l": 0.6485740751442981, "c": 0.2994852863383699, "h": 28.958132730803953 },
"inGamut": false
}
空白。 解析前に先頭と末尾の空白が削除されます。" #ff0000 "は#ff0000として解析されます。
CSS Color 4のチャンネル値のクランプ(従来の色空間のみ)。 16進数表記/rgb()/hsl()の入力で範囲外のチャンネル値は、CSS Color 4に従い、解析境界でクランプされます。rgb(-50 0 0)はrgb(0 0 0)とまったく同じように処理され、hsl()の彩度/明度も同様にクランプされます(色相は折り返されます)。その他のモード(oklch()、lab()、color(display-p3 …)など)ではクランプされず、色域外の値はそのまま扱われます。これにより、gamut_mapが役立ちます。
noneチャンネル。 CSS Color 4のnoneチャンネルは、6つすべてのツールで0に正規化されます。oklch(0.5 none 30)はoklch(0.5 0 30)とまったく同じように処理されます。
成分の大きさ。 解析可能な成分でも、極端に大きな値(1e6を超える値。例:oklch(0.5 1e30 30))の場合はCOMPONENT_OUT_OF_RANGEで拒否されます。2つのツール(gamut_map、solve_for_contrast)では異なる形で通知されます。詳しくはエラーコードの表を参照してください。実際の色域外の値は、この上限より桁違いに小さいため、影響を受けることはありません。
アルファの方針。 contrastとsolve_for_contrastは、半透明の色を拒否します。明示的なアルファ値が< 1の場合はすべて対象となり、rgba()/hsla()の関数形式のアルファや、4桁/8桁の16進数表記(#00000080)も含まれます。これは、半透明レイヤーの実効色が不明な背景色に依存するためで、ALPHA_UNSUPPORTEDが返されます。先に背景色と合成してください。その他のツールでは半透明の入力を受け付けますが、アルファチャンネルは単に無視されます(計算には不透明色が使われ、アルファ成分を含む出力はありません)。
長さの上限。 色文字列は、前後の空白を削除した後に256文字を超えると、INPUT_TOO_LONGで拒否されます。
ツール
parse_color
任意のCSS色文字列を解析し、16進数表記、RGB、OKLCH、色域の情報を返します。
入力スキーマ
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| input | string | はい | 任意のCSS色文字列。例:"#ff0000"、"red"、"oklch(0.6 0.2 30)" |
{ "input": "#ff0000" }に対する出力
{
"hex": "#ff0000",
"rgb": { "r": 255, "g": 0, "b": 0 },
"oklch": { "l": 0.6279553639214311, "c": 0.2576833038053608, "h": 29.233880279627854 },
"inGamut": true
}
rgbチャンネルは、sRGBにクランプされた0~255の整数値への射影であり、hexと一貫しています。色域外の入力(広色域のoklch(...)など)の場合、範囲外の生の値を返すのではなく、チャンネル値を[0, 255]にクランプします。入力がsRGBの範囲外かどうかは、inGamutフラグで確認できます。一方、oklchブロックは入力の**未加工(ロスレス、丸めなし)**のOKLCHであり、無彩色の場合、oklch.hは0になります。
convert_color
CSS の色文字列を、正規化された hex、rgb、hsl、または oklch 形式の文字列に変換します。
入力スキーマ
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| input | string | はい | 任意の CSS 色文字列 |
| to | string | はい | 対象の形式:「"hex"」、「"rgb"」、「"hsl"」、または「"oklch"」 |
{ "input": "#ff0000", "to": "oklch" } の出力
{ "result": "oklch(0.62796 0.25768 29.23)" }
色域外の入力に対する未クランプ値とクランプ値
sRGB 色域の範囲外にある色では、対象形式によって結果が異なります。
to: "oklch"は、未加工でロスレスな OKLCH の三つ組を返すため、色域外の色も忠実に往復変換できます。例:{ "input": "oklch(0.7 0.4 30)", "to": "oklch" }→"oklch(0.70000 0.40000 30.00)"。to: "hex"、"rgb"、"hsl"はすべて、sRGB にクランプされた投影から算出され、色域内で近似した値を返します。例:{ "input": "oklch(0.7 0.4 30)", "to": "rgb" }→"rgb(255, 0, 0)"。rgbの各チャンネルは[0, 255]の整数です。
(L/C は小数点以下 5 桁、H は小数点以下 2 桁で書式化されるため、sRGB 色立方体全体で hex への往復変換が正確になります。)
contrast
完全に不透明な 2 つの CSS 色文字列間の WCAG 2.1 コントラスト比を計算し、適合レベルのフラグを返します。必要に応じて APCA の Lc 値も計算できます(APCA(任意の知覚的コントラスト)を参照)。
入力スキーマ
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| a | string | はい | 1 つ目の CSS 色文字列(APCA ではテキスト/前景色として扱われます)。例:"#000000" |
| b | string | はい | 2 つ目の CSS 色文字列(APCA では背景色として扱われます)。例:"#ffffff" |
| apca | boolean | いいえ | true の場合、背景 b 上のテキスト a に対する符号付き APCA-W3 apcaLc も返します |
{ "a": "#000000", "b": "#ffffff" } の出力
{
"ratio": 21,
"aaNormal": true,
"aaLarge": true,
"aaaNormal": true,
"aaaLarge": true
}
ratio は小数点以下 2 桁の表示用の値です。4 つの適合レベルの真偽値は丸め前の比率から算出されるため、境界付近の丸め前の値が 4.4999 の場合、表示が 4.50 でも aaNormal: false になります。
WCAG 2.1 の適合レベルのしきい値:
aaNormal/aaLargeはそれぞれ比率 ≥ 4.5/≥ 3.0 が必要ですaaaNormal/aaaLargeはそれぞれ比率 ≥ 7.0/≥ 4.5 が必要です
エラー。 文字列の解析に失敗すると、パラメーター名を含むエラーが返されます。a の場合は PARSE_FAILED: could not parse the foreground color、b の場合は PARSE_FAILED: could not parse the background color です。半透明の入力では ALPHA_UNSUPPORTED が返されます(アルファのポリシーを参照)。
APCA(任意の知覚的コントラスト)
apca: true を渡すと、背景 b 上のテキスト a に対する、符号付き APCA-W3(SAPC-4g)の明度コントラスト Lc を小数点以下 2 桁に丸めた apcaLc も取得できます(APCA では WCAG 比と異なり、引数の順序が重要です)。符号は極性を示します。明るい背景に対する暗いテキストは正、暗い背景に対する明るいテキストは負です。大きさは |Lc| で比較してください。
{ "a": "#1a1a1a", "b": "#ffffff", "apca": true }
{ "ratio": 17.4, "aaNormal": true, "aaLarge": true, "aaaNormal": true, "aaaLarge": true, "apcaLc": 104.27 }
ペアの順序を逆にすると符号が反転します:{ "a": "#ffffff", "b": "#1a1a1a", "apca": true } → "apcaLc": -106.55(WCAG 比は対称なので、ratio は同じく 17.4 です)。
よく引用される APCA ガイドラインのしきい値(|Lc|):
| |Lc| | 一般的なガイドラインの用途 |
|---|---|
| 45 | 大きい文字/太字の最小値 |
| 60 | その他の本文の最小値 |
| 75 | 本文 |
| 90 | 本文に推奨される値 |
免責事項: APCA は WCAG 3 の候補手法であり、現時点では WCAG の規範的な標準ではありません。適合性を主張する場合は、WCAG 2.1 の適合レベルのフラグを使用してください。
gamut_map
知覚的な OKLCH クロマの低減により、任意の CSS カラー文字列を sRGB 色域にマッピングします。広色域の色(P3、Rec2020、任意の OKLCH)を表示可能な sRGB に変換するのに便利です。
入力スキーマ
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| input | string | はい | 任意の CSS カラー文字列。例:"oklch(0.6 0.4 30)" |
{ "input": "oklch(0.6 0.4 30)" } に対する出力
{
"hex": "#f70000",
"oklch": { "l": 0.6137129506655941, "c": 0.25183888824211537, "h": 29.233880279628004 },
"clamped": true
}
入力が sRGB 色域外にあり、マッピングが必要だった場合、clamped は true になります。返される oklch は、元の入力の OKLCH ではなく、マッピング後の色域内の結果の生の OKLCH(クロマを知覚的に低減)です。
同一性と冪等性。 sRGB 色域の内側にすでにある入力は、同一のまま返されます。clamped は false になり、hex は入力の正規形式の hex と完全に一致します(例:{ "input": "#3b82f6" } → { "hex": "#3b82f6", …, "clamped": false })。このツールは冪等でもあります。出力された hex は常に色域内にあるため、結果を再度入力すると同一性の経路を通り、同一の hex が返されます。
generate_ramp
ベースとなる CSS カラーから、ティントからシェードへのカラースケールを生成します。順序付けられたスウォッチのリストを返します。各スウォッチには hex、OKLCH、白と黒に対する WCAG コントラスト比、色域フラグが含まれます。オプションで、カラースケールをデザイントークンとして出力します(デザイントークンを参照)。
入力スキーマ
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| base | string | はい | 任意の CSS カラー文字列。例:"#3b82f6" |
| steps | integer | いいえ | スウォッチの数(2~512)。デフォルト:5 |
| lightnessMin | number | いいえ | 明度の下限(OKLCH L、0~1)。デフォルト:0.05 |
| lightnessMax | number | いいえ | 明度の上限(OKLCH L、0~1)。デフォルト:0.97 |
| deltaL | number | いいえ | 明度の合計範囲。ベースの L を中心に設定し、端点はベースの L ± deltaL/2 になります(固定範囲を上書きします) |
| tokenFormat | string | いいえ | "tailwind" または "css-variables" — 指定すると、出力に tokens 文字列が含まれます |
| tokenName | string | いいえ | 出力するトークンのベース名(英字/数字/ハイフン。英字で始まる必要があり、1~64 文字)。デフォルト:"color" |
{ "base": "#3b82f6", "steps": 5 } に対する出力(5 個のスウォッチのうち最初のものを表示)
{
"swatches": [
{
"step": 0,
"hex": "#f5f5f5",
"oklch": { "l": 0.97, "c": 0, "h": 259.81 },
"vsWhite": { "ratio": 1.09, "tier": "FAIL" },
"vsBlack": { "ratio": 19.26, "tier": "AAA" },
"inGamut": true
}
]
}
スウォッチのインデックスはゼロ始まりです。スウォッチは最も明るいもの(step: 0)から最も暗いもの(step: steps - 1)の順に並び、OKLCH の明度は厳密に減少します(上記の完全な 5 スウォッチのレスポンスでは、色域内のベース #3b82f6 が step: 2 にそのまま再登場します。カラースケールは、ベースの明度に最も近いステップを基準にします)。
各スウォッチには vsWhite / vsBlack が含まれ、それぞれ { ratio, tier } の形式です。ratio は白/黒に対する WCAG コントラスト比、tier は "AAA"(生の比率 ≥ 7.0)、"AA"(≥ 4.5)、"FAIL" のいずれかです。
表示時の丸め。 スウォッチの数値は表示用に丸められます。コントラストの ratios は小数点以下 2 桁、oklch.l/oklch.c は小数点以下 5 桁、oklch.h は小数点以下 2 桁になります。tier の分類は、丸め前の生の比率に基づきます(生の値が 6.9999 の場合、表示は 7.00 でも分類は "AA" になります)。
しきい値付近での Tier の量子化。 各スウォッチのコントラストは、表示色として基準となる 8 ビットの hex から計算されます。そのため、Tier のしきい値(3.0 / 4.5 / 7.0)との差が約 0.01 以内の場合、浮動小数点精度での計算と比べて Tier が変わることがあります。確実に余裕を持たせる必要がある場合は、しきい値を十分に上回る比率を目標にしてください(例:4.5 ではなく 4.6 を目標にします)。
検証ルール
数値の制約はツールスキーマで宣言されているため、範囲外の呼び出しはハンドラーの実行前に SDK によって拒否されます。MCP 経由では、これらの拒否は以下のツールレベルのコードではなく、SDK の検証エラーとして返されます(スキーマ層とツール層での適用を参照)。
stepsは[2, 512]の整数である必要があります。そうでない場合はSTEPS_OUT_OF_RANGEが返されます。deltaLが指定されている場合は、有限の数値で> 0である必要があります。そうでない場合はINVALID_DELTA_Lが返されます。- 解決された明度範囲は
lightnessMin < lightnessMaxを満たす必要があります(端点は最初に[0, 1]の範囲にクランプされます)。そうでない場合はINVALID_LIGHTNESS_RANGEが返されます。 - ベースカラーの OKLCH 彩度は ≤ 100 である必要があります。そうでない場合は
BASE_CHROMA_OUT_OF_RANGEが返されます。 - パースに失敗した
baseは、パースエラーコード(PARSE_FAILED、INPUT_TOO_LONG、COMPONENT_OUT_OF_RANGE、またはNON_FINITE_COMPONENTS)をそのまま返します。
ペイロードサイズ。 steps: 512 の呼び出しでは、ツールの結果に約 200 KB の JSON が含まれます(整形すると約 280 KB)。LLM のコンテキストでは、少ないステップ数(5~11)を推奨します。わずかなトークン数で、ほぼすべてのデザインシステムのユースケースに対応できます。
swatch.oklch と swatch.hex の違いについて
各スウォッチの oklch は、指定した L/彩度をクランプした投影値です(目標の明度で、sRGB 色域内に収まるよう彩度を下げた値)。これにより、ランプ全体で厳密な L の単調性が保たれます。そのため、swatch.hex から算出する厳密な OKLCH 値とはわずかに異なる場合があります(ΔL は最大で約 0.013)。これは、16 進数カラーとの厳密な往復変換よりも明度の単調性を優先する意図的なトレードオフです。表示色の正しい値は引き続き hex です。
デザイントークン
tokenFormat(および任意で tokenName)を渡すと、swatches に加えて tokens 文字列も取得できます。
- ステップ数がちょうど 11 の場合、トークンキーには標準の Tailwind スケール
50, 100, 200, …, 900, 950を使用します(最も明るいスウォッチ0が50に対応します)。 - ステップ数がそれ以外の場合、キーには 0 始まりの
stepインデックスを使用します。
tokenFormat: "tailwind" — 整形済み JSON オブジェクト文字列です。{ "base": "#3b82f6", "steps": 11, "tokenFormat": "tailwind", "tokenName": "blue" } に対する tokens の出力:
{
"blue": {
"50": "#f5f5f5",
"100": "#c1d8fe",
"200": "#8fbaff",
"300": "#629bfa",
"400": "#3b82f6",
"500": "#155ecf",
"600": "#0043ab",
"700": "#002b80",
"800": "#001750",
"900": "#000721",
"950": "#000000"
}
}
tokenFormat: "css-variables" — :root ブロックです。{ "base": "#3b82f6", "steps": 5, "tokenFormat": "css-variables", "tokenName": "brand" } に対する tokens の出力:
:root {
--brand-0: #f5f5f5;
--brand-1: #78abfe;
--brand-2: #3b82f6;
--brand-3: #002068;
--brand-4: #000000;
}
tokenName はスキーマ境界で検証されるため(/^[a-z][a-z0-9-]*$/i、1~64 文字)、CSS カスタムプロパティ名または JSON キーに常に安全に埋め込まれます。
solve_for_contrast
背景色に対して、1 つ以上の WCAG 2.1 コントラスト目標を満たす前景色を見つけます。色相と彩度を固定したまま、OKLCH の明度を二分探索します。
入力スキーマ
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| background | string | はい | 背景の CSS 色文字列 |
| target | number | いずれか | 単一の WCAG 2.1 コントラスト目標(例:4.5、7) |
| targets | number[] | いずれか | 複数のコントラスト目標(1~50 件。空の配列は拒否されます) |
| prefer | "lighter","darker","either" | いいえ | 探索方向。デフォルトは "either" |
| hue | number | いいえ | 探索中に固定する OKLCH 色相(度) |
| chroma | number | いいえ | 探索中に固定する OKLCH 彩度(≥ 0) |
hue/chroma のデフォルト — 彩度を維持するには chroma を指定してください
省略した場合、chroma のデフォルトは背景色自体の彩度になり、hue のデフォルトは背景色の色相(無彩色の背景色の場合は 0)になります。知っておくべき点は次のとおりです。
chromaを指定せずにhueを指定しても、彩度は加わりません。 無彩色の背景色(白/グレー/黒)では、デフォルトの彩度が0になるため、指定した色相にかかわらず結果は無彩色のグレーになります。#ffffffに対してtarget: 4.5を指定した場合、{ "hue": 260 }→{ "met": true, "color": "#767676", "ratio": 4.54 }(色相を指定しない場合と同じグレー)となる一方、{ "hue": 260, "chroma": 0.15 }→{ "met": true, "color": "#4075cf", "ratio": 4.5 }(青色)となります。hueを指定せずにchromaを指定すると、色相は背景色の色相(無彩色の場合は0)に固定されます。固定した彩度は、sRGB 色域に収める必要がある場合、明度に応じて減少することがあります。
target と targets の優先順位およびレスポンス形式
target(単一)または targets(配列)を指定します。両方を指定した場合は targets が優先され、単一の target は無視されます。2 つのモードでは、異なるレスポンス形式が返されます。
- 単一の
target→{ met, color, ratio }(任意のnearMissフラグを含む場合があります)。 targets配列 →{ results: [ { met, color, ratio, nearMiss? }, ... ] }。指定された目標ごとに、指定順で 1 件ずつ返されます。
登録済みの出力スキーマは、両方の形式を包含する、すべてのフィールドが任意のスーパーセットです。返されるレスポンスでは、どちらか一方の形式のフィールドだけが設定されます。
出力 { "background": "#ffffff", "target": 4.5, "prefer": "darker" } の場合
{ "met": true, "color": "#767676", "ratio": 4.54 }
出力 { "background": "#1e293b", "targets": [4.5, 7] } の場合
{
"results": [
{ "met": true, "color": "#8290a6", "ratio": 4.52 },
{ "met": true, "color": "#a6b5cc", "ratio": 7.04 }
]
}
nearMiss: true は、met が上限付近の許容範囲によって認められた場合に、単一の結果、または results 内のエントリーに現れることがあります。これは、探索した方向で達成可能な最良の実際の比率が目標を 0.03 未満下回っていることを示します。方向を指定する prefer("lighter"/"darker")を指定した場合は、一方の範囲だけが探索されるため、反対方向では目標を厳密に満たせることがあります。"either" モードでは、厳密に条件を満たす側が常に優先されるため、nearMiss が示されるのは、どちらの方向も目標を厳密には満たさない場合だけです。
エラー。 背景色を解析できない場合は、単一の target と targets のどちらの経路でも、PARSE_FAILED: could not parse the background color を含む isError が返されます。半透明の背景色の場合は ALPHA_UNSUPPORTED が返されます(アルファポリシーを参照)。
エラー処理
すべてのツールは全域的です。不正な入力や範囲外の入力によって、サーバーがクラッシュしたりスタックトレースが漏えいしたりすることはありません。失敗時、ツールはisError: trueを含むMCP結果を返します。結果にはテキストコンテンツブロックが1つだけ含まれ、そのテキストは、閉じた集合から選ばれたUPPER_SNAKE_CASE値である<CODE>を使った、統一された<CODE>: message形式に従います。メッセージは静的で安全な文字列です。生の入力、ファイルパス、スタック、ライブラリ内部情報が埋め込まれることはありません。エラー時、ツールはstructuredContentを設定しません。
エラーテキストの例:
PARSE_FAILED: could not parse the provided color string
予期しない内部障害をすべて捕捉するコードは、常に次のとおりです。
INTERNAL_ERROR: unexpected internal error
スキーマ層とツール層での制約適用
ツールのzod入力スキーマで宣言された制約は、ツールハンドラーの実行前にMCP SDKによって適用されます。ハンドラーは実行されず、結果にはstructuredContentが含まれません。MCP SDK 1.29では、この拒否はエラーフラグ付きのツール結果(isError: true)として帯域内で返されます。そのテキストはMCP error -32602: Input validation error: …で始まります。このテキストはSDKが生成するもので、上記の統一されたCODE: message形式および内部情報を含めないという保証の対象外です(この保証はツール層のエラーのみを対象とします)。今後のSDKバージョンでは、真の-32602プロトコルエラーとして返される可能性があるため、具体的な返され方や文言に依存したパターンマッチングは行わないでください。対応するツールレベルのコードは、SDKの検証を回避する直接のライブラリ呼び出し(ハンドラーまたはsrc/lib関数をインポートするコード)に対する多層防御として維持されています。スキーマで適用される制約は次のとおりです。
INPUT_TOO_LONG— すべての色文字列フィールドで.max(256)を宣言します。STEPS_OUT_OF_RANGE—stepsは整数の2..512を宣言します。INVALID_DELTA_L—deltaLは有限の> 0を宣言します。TOO_MANY_TARGETS—targetsは.max(50)を宣言します。EMPTY_TARGETS—targetsは.min(1)を宣言します(空の配列はハンドラー実行前に拒否されます)。INVALID_TARGET、INVALID_CHROMA、INVALID_HUEの根拠となる有限性および符号の制約も、同様にスキーマで宣言されています(なお、非有限の数値はJSONでは表現できません)。
エラーコード
| コード | 意味 |
|---|---|
INPUT_TOO_LONG | 色文字列が256文字の上限を超えました(DoS 対策として、解析前に適用されます。スキーマによる検証済み)。 |
PARSE_FAILED | 指定された色文字列を CSS カラーとして解析できませんでした。contrast と solve_for_contrast では、静的メッセージで失敗したパラメーターを示します:could not parse the foreground color / could not parse the background color。 |
COMPONENT_OUT_OF_RANGE | 解析可能な色成分の絶対値が異常に大きい(> 1e6)場合です。例:oklch(0.5 1e30 30)。parse_color、convert_color、contrast、generate_ramp が返します。例外: gamut_map は同じ入力を CHROMA_OUT_OF_RANGE で拒否します(彩度のガードが先に作動するため)。solve_for_contrast では、パラメーター名を示す PARSE_FAILED として報告されます。 |
ALPHA_UNSUPPORTED | contrast / solve_for_contrast に半透明の色(明示的なアルファ値が1未満。4桁/8桁の16進数を含む)が渡されました。静的メッセージ:contrast requires fully opaque colors (alpha = 1); composite the color over its backdrop first。 |
NON_FINITE_COMPONENTS | 色を解決した結果、RGB/OKLCH 成分が有限値になりませんでした(彩度のオーバーフローなど)。 |
NON_FINITE_LUMINANCE | コントラスト計算で輝度が有限値になりませんでした。 |
NON_FINITE_OKLCH_COMPONENTS | 色域マッピング中に OKLCH の明度/彩度が有限値になりませんでした。 |
NULL_OKLCH_CHANNELS | 色域マッピング中に OKLCH チャンネルが null になりました。 |
NON_FINITE_OKLCH_HUE | 色域マッピング中に有彩色の OKLCH 色相が有限値になりませんでした。 |
CHROMA_OUT_OF_RANGE | OKLCH 彩度が色域マッパーの対応上限(100)を超えました。gamut_map は oklch(0.5 1e30 30) に対して COMPONENT_OUT_OF_RANGE ではなく、このコードを返します。 |
GAMUT_MAP_COLLAPSE | 色域マッピングの結果、チャンネルが null/非有限値になりました。 |
STEPS_OUT_OF_RANGE | generate_ramp の steps が [2, 512] の範囲内の整数ではありません(スキーマによる検証済み)。 |
INVALID_LIGHTNESS_RANGE | generate_ramp の解決後に lightnessMin >= lightnessMax となりました。 |
INVALID_DELTA_L | generate_ramp の deltaL が有限の数値であり、かつ > 0 ではありません(スキーマによる検証済み)。 |
BASE_CHROMA_OUT_OF_RANGE | generate_ramp のベース OKLCH 彩度が100を超えました。 |
MISSING_BACKGROUND | solve_for_contrast が background を指定せずに呼び出されました。 |
MISSING_TARGET | solve_for_contrast が target も targets も指定せずに呼び出されました。 |
EMPTY_TARGETS | solve_for_contrast の targets が空の配列でした(.min(1) によるスキーマ検証済み)。 |
TOO_MANY_TARGETS | solve_for_contrast の targets が50件を超えました(スキーマによる検証済み)。 |
INVALID_TARGET | solve_for_contrast の target が有限の数値 >= 0 ではありません。 |
INVALID_CHROMA | solve_for_contrast の chroma が有限の数値 >= 0 ではありません。 |
INVALID_HUE | solve_for_contrast の hue が有限の数値ではありません。 |
INVALID_GEOMETRY | solve_for_contrast の解決後に、色相/彩度が有限値でない、または彩度が負の値になりました。MCP 経由では明示的な hue / chroma がスキーマで先に検証されるため、これは実質的にライブラリを直接呼び出す場合の多層防御用コードです。 |
INTERNAL_ERROR | 予期しない内部エラーを捕捉した場合に使用されます。 |
ツールのアノテーションとサーバーメタデータ
6つのツールはすべて、読み取り専用で副作用がないことを宣言する MCP ツールアノテーション(readOnlyHint: true、idempotentHint: true、destructiveHint: false、openWorldHint: false)と、人間が読める title を付けて登録されています。サーバー自体にも title("Color Engine")と、6つのツール、OKLCH 優先の設計、丸め規則、接続するクライアント向けのエラー形式を要約した instructions 文字列が登録されています(特に、比率を単に測定するのではなく、比率を満たす必要がある場合は solve_for_contrast を使うようエージェントを導きます)。各ツールの結果には structuredContent と、それに相当するプレーンテキストのコンテンツブロックの両方が含まれるため、構造化出力を利用しないクライアントでも情報を損なうことはありません。
精度とパフォーマンス
精度(すべてテストスイートで検証済みです。npm test で再現できます):
- WCAG 比は二重のオラクルで検証されます。第一原理に基づく WCAG 2.1 の輝度実装と独立した
colorjs.ioの実装を使用し、各しきい値(3.0 / 4.5 / 7.0)をまたぐ色のペアで階層分類を確認します。 - hex ↔ OKLCH の往復変換はバイト単位で完全一致します。sRGB 色域全体を対象とする、何千もの決定論的なグリッドポイントとシード付きファズサンプルで確認しています。
- APCAは、極性の両方で独立した
colorjs.ioの APCA 実装と 0.1 Lc 以内で一致します。 - gamut_mapは色域内の色をビット単位で完全一致させ、出力に対して冪等です。
パフォーマンス(1 回の呼び出しあたりの中央値、Node v25.9.0 で npm run build && npm run bench を実行して測定。参考値であり、保証値ではありません):
| 呼び出し | 中央値(ms) |
|---|---|
parse_color | 0.005 |
convert_color | 0.002 |
contrast | 0.004 |
gamut_map(色域外の入力) | 0.015 |
generate_ramp(steps=5) | 0.037 |
solve_for_contrast(単一の目標値) | 0.067 |
generate_ramp(steps=512、最悪ケース) | 3.3 |
solve_for_contrast(50 個の目標値、最悪ケース) | 2.7 |
コールドスタート(プロセス起動から initialize 応答まで)の中央値は約 135 ms です。
開発
ビルド
npm install
npm run build
コンパイル済みサーバーは dist/server.js にあります。
ソースからの実行。 npm パッケージではなくローカルのクローンを MCP クライアントに指定するには、まずビルドしてから次を使用します。
{
"mcpServers": {
"color-engine": {
"command": "node",
"args": ["/absolute/path/to/color-engine-mcp/dist/server.js"]
}
}
}
/absolute/path/to/color-engine-mcp/dist/server.js を、クローン内の dist/server.js の実際のパスに置き換えてください。
テスト
npm test
MCP Inspector CLI 統合テスト(npx @modelcontextprotocol/inspector --cli によるものを含む)を含む、テストスイート全体を実行します。pretest スクリプトは tsc を自動実行し、Inspector テストの実行前に dist/server.js が最新の状態であることを確認します。
ベンチマーク
npm run build
npm run bench
ビルド済みの dist/ ハンドラーに対して scripts/bench.mjs を実行します(各ケースでウォームアップ 20 回、計測 200 回を行い、中央値を報告します)。精度とパフォーマンスに記載した数値は、このベンチマークで得られたものです。
変更履歴
リリース履歴については、CHANGELOG.md をご覧ください。
ライセンス
MIT — LICENSE をご覧ください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。