Rnv Color Mcp

io.github.RNVizion由 GitHub 帳號 RNVizion 發布v1.3.0更新於 Oct 26, 2026

A complete color workflow over MCP: mix, convert, harmonize, measure, place, and remember palettes.

已驗證Streamable HTTP可網頁執行開發者工具媒體與設計

概覽

AI 產生的概覽

遠端 MCP 伺服器,用於色彩工作流程:混色、格式轉換、配色和諧、色差與對比度檢查,並可儲存與讀取具名調色盤。

可以做什麼
  • 依權重混合最多 12 種顏色,支援 rgb、hsv、lab、paint、ryb、cmy 等模式
  • 在 hex、rgb、hsv、hsl、lab 之間轉換顏色
  • 在保留色相與彩度的前提下設定明度,並產生互補、三角、類似等配色方案
  • 計算感知色差(Delta-E)與 WCAG 對比度,並給出 AA/AAA 通過結果
  • 儲存、列出與讀取具名調色盤,重新啟動後仍可保留
  • 對文字執行精確的大小寫轉換
適用情境
適合對話需要精確顏色數值而非模型估算的情況:建立或調整品牌色盤、檢查文字可及性、推導明暗配對,或從基色產生配色方案。
執行需求
無需安裝,是可透過網址連線的託管遠端端點,公開部署不啟用身分驗證。自行部署需要 Python 及所列相依套件;調色盤持久保存需要 HF_TOKEN 與可寫入的 Hugging Face Dataset,分範圍授權需要 RNV_AUTH 相關變數。
安裝前請注意
公開端點處於開放狀態,任何取得網址的人都能儲存調色盤;未設定 HF_TOKEN 的副本所儲存的內容會在容器重新啟動後遺失。設定後調色盤會寫入 Hugging Face Dataset,儲存的名稱與顏色會留在伺服器端。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Rnv Color Mcp,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

交給代理程式安裝

把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。

閱讀 https://sourceweft.com/mcp/io.github.RNVizion%2Frnv-color-mcp/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。

檢視代理程式所依據的安裝指南

其他 MCP 客戶端

把它新增到你客戶端的 mcpServers 設定中。

{
  "mcpServers": {
    "rnv-color": {
      "type": "http",
      "url": "https://rnvizion-rnv-color-mcp.hf.space/mcp"
    }
  }
}

README


title: RNV Color MCP emoji: 🎨 colorFrom: gray colorTo: yellow sdk: docker app_port: 7860 pinned: false short_description: Color workflow MCP server

RNV Color MCP

[rnv-color-mcp MCP server] [Mentioned in Awesome MCP Servers] [tests]

A remote MCP server for a complete color workflow: mix, convert, harmonize, and remember palettes, called in plain language by Claude (or any MCP client), and by anything else that speaks MCP.

Why this exists

The color logic already lived in my desktop suite: a mixer, a palette manager, a picker. Instead of rebuilding it for every new project, I lifted the engine out once and exposed it as a single server. A Claude conversation calls it today; a fashion design app will call the same backend tomorrow. Build the engine once, let both consume it.

Underneath, it's a small thesis about working with LLMs: a model is great at deciding what you want and terrible at exact arithmetic. So the model picks the tool and the intent, and the tool owns the precise values. The server resolves or it refuses; it never guesses a color.

What it does

ToolWhat it does
mix_colorsBlend up to 12 colors. Modes: rgb, hsv, lab (digital) and paint (Kubelka-Munk pigment physics), ryb (artist's wheel), cmy (subtractive).
convert_colorConvert between hex, rgb, hsv, hsl, lab.
place_lightnessHold a color's hue and chroma; set its lightness. One hue at two L* values is a light/dark pair. Refuses out-of-gamut rather than clamping, and reports the 8-bit quantization error.
generate_harmonycomplementary, analogous, triadic, split-complementary, tetradic/square, monochromatic, compound.
color_differencePerceptual difference (Delta-E, CIEDE2000 or CIE76) between two colors.
contrast_checkWCAG contrast ratio plus AA/AAA pass/fail for accessible text.
transform_text11 exact case transforms (UPPERCASE, camelCase, snake_case, …).
save_palette / list_palettes / get_paletteName a palette, recall it later. Persists across restarts.

Every color input accepts a hex (#d2bc93), a CSS name (red), an RNV brand name (brand gold, near-black), or a saved-palette reference (Spring line, or Spring line:2 for its second swatch). Brand names win over CSS names on collision (gold, blue, teal); css:blue forces the universal one.

Connect in 30 seconds

This is a hosted server, so there's nothing to install. In Claude: Settings → Connectors → Add custom connector, then paste:

https://rnvizion-rnv-color-mcp.hf.space/mcp

Leave auth blank, add it, then toggle it on in a chat with the + menu.

Try it

Once connected, just talk:

"Save a palette named Spring line: near-black and brand gold." "Pull my Spring line palette and give me three complementary accents for outerwear." "Mix crimson and royalblue like real pigment."

The first call saves; the second composes get_palette → generate_harmony; the third runs the Kubelka-Munk paint model, so the blend darkens the way mixed pigment actually does, not the way averaged light does.

Authentication

The server implements OAuth 2.1 resource-server authentication with enforced per-tool scopes; the public endpoint runs with it disabled, so connecting by URL works with no setup.

When enabled (RNV_AUTH=1 plus a key source), the server validates bearer tokens against issuer, audience, expiry, and signature; serves RFC 9728 protected resource metadata at /.well-known/oauth-protected-resource/mcp; returns a spec-compliant WWW-Authenticate challenge on 401; and enforces two scopes: read covers every read-only tool, write covers save_palette, the only tool that mutates anything. A token without the write scope does not see save_palette in its tool list at all; out-of-scope tools are hidden rather than refused, so nothing leaks about what exists behind a scope you lack.

Enforcement is covered by the test suite, run in CI on every push (status badge at the top of this file), spanning the token-validation matrix (missing, malformed, wrong issuer, wrong audience, expired, valid) and end-to-end scope enforcement over real HTTP. The suite mints its own keys and requires no credentials. Beyond auth, it pins parts of the engine: the brand vocabulary mirror; the contrast, difference and placement contract; selector and input refusals; color-name resolution; what the mix modes compute; the hsv and hsl conversions; the palette write path; store durability. Harmony and text outputs are exercised by the smoke scripts and are not yet under regression test.

Moving from the self-issued development key to a real identity provider is configuration, not code: point RNV_AUTH_JWKS_URI at the provider's JWKS endpoint and set the issuer and audience to match.

VariablePurpose
RNV_AUTHThe switch. 1 / true / yes / on enables auth; unset means off.
RNV_AUTH_JWKS_URIA provider's JWKS endpoint. Use this or RNV_AUTH_PUBLIC_KEY.
RNV_AUTH_PUBLIC_KEYA static PEM public key, for development against a self-issued keypair.
RNV_AUTH_ISSUERExpected token issuer; also advertised as the authorization server.
RNV_AUTH_AUDIENCEExpected token audience. Bound to the /mcp path.
RNV_AUTH_BASE_URLServer base URL, without /mcp.

With RNV_AUTH on and no key source set, the server refuses to start rather than coming up unprotected.

Run it yourself

bash
pip install -r requirements.txtpython server.py                  # Streamable HTTP on $PORT (default 7860)
pip install -r tests/requirements-dev.txtpython -m pytest                  # the suite; needs no credentialspython tests/server_test.py       # smoke: exercises every tool in-process

Set HF_TOKEN to write palettes through to a private Hugging Face Dataset for durable storage. The suite and both smoke scripts ignore HF_TOKEN and use a throwaway store, so they can never write to a real Dataset.

Running a copy?

The code is MIT-licensed; you're free to rebuild, host, and modify it, and I'd rather you did than didn't. What a license can't carry is the environment.

Some capabilities depend on how a deployment is configured, not on the code alone:

  • Palette persistence needs HF_TOKEN and a writable Dataset. Without it, saves land in the container's local working copy and vanish with it; save_palette returns durable: false with a durable_reason naming the step that stopped it.
  • Scoped authorization needs RNV_AUTH and a configured issuer. Unset, the server runs open — which is correct for a public demo and wrong for anything else.
  • Anything that fetches needs outbound network access.

A rebuild missing one of those usually doesn't fail loudly; it returns success and drops the result. That is worse than an outage, because an outage tells you.

So: if you're running a copy and something behaves oddly, check the environment before you check the code, and check against the canonical deployment before you file anything.

Canonical endpoint: https://rnvizion-rnv-color-mcp.hf.space/mcp Canonical source: https://github.com/RNVizion/rnv-color-mcp

A copy served from another URL may be older, modified, or differently configured. That's fine and allowed; it just isn't this.

The tools resolve or refuse; they don't guess. A copy can only keep that promise if the ground under it was checked first.

Notes

  • Brand colors are mirrored, not owned. The vocabulary lives in engine/brand_vocab.py, mirrored from engine/brand.py in RNVizion/rnv-brand and corrected when drift is detected against it. It is carried locally on purpose: resolve_color is the hot path, and a fetch there would have to answer what happens when it fails — fail closed and the server refuses every color, fall back and the local copy is needed anyway, guess and the promise above is already broken. Identifiers match upstream's since the register retired local names on 2026-08-17; the check compares values. A scheduled job compares the mirror with upstream daily and gates nothing. The register and its reasoning live in BRAND_COLORS.md, in rnv-brand.
  • Engine is dependency-free. The color math, harmony, and text logic are pure standard library, lifted Qt-free from the desktop apps. Only the server layer needs fastmcp.
  • Honest by design. An unknown color name is refused, not guessed. An unverifiable token is refused, with a reason. Same principle at both layers.

Stack

Python · FastMCP (Streamable HTTP) · Hugging Face Spaces (Docker) · huggingface_hub for durable palette storage.


Built by Christian "RNVizion" Smith.

來源:README.md,提交 3c3f7d3

工具

10

mix_colors

Blend up to 12 colors into one. Each color may be a hex (#d2bc93), a CSS name (red), an RNV brand name (brand gold, near-black), or a saved-palette reference (Spring line, or 'Spring line:2' for its 2nd swatch). Optional integer weights bias the blend (defaults to equal). mode selects the model: rgb/hsv/lab are digital blends (lab is perceptual and the default, best for on-screen color); paint mixes pigments via Kubelka-Munk physics (colors darken like real paint, use it for physical-media matching); ryb is the artist's color wheel; cmy is subtractive like printer inks. Returns hex and rgb. Reach for paint when BLENDING brand colors into a new one, and lab when SAMPLING between them: lab returns the point between its ingredients, which is right for finding a midpoint; paint models mixing them as pigments, which makes a different color. RNV's #00b0a0 was blended in paint; the same ingredients at the same weights in lab give #9cc1a5, 15.94 away and far closer to the brand gold it exists to be distinguishable from. paint and cmy work per RGB channel, so an ingredient with an empty channel (pure digital primaries such as #0000ff or #ffff00) dominates that channel: at equal weights yellow + css:blue comes out black in paint and near-black (#070707) in cmy, where ryb gives green. Weight shifts this in cmy and hardly in paint: white + css:blue at 10:1 is #8484ff in cmy and #0202fe in paint. For pigment-like results use pigment-like colors, or ryb for idealized primaries. Brand names win over CSS names on collision: 'blue' is RNV blue, css:blue is #0000ff. Read-only and deterministic: it computes a result and stores nothing, so it is safe to call repeatedly with no side effects. Use to combine multiple colors into a single blend; to convert one color between formats use convert_color, and to measure how far apart two colors are use color_difference.

輸入參數modecolors必填weights

convert_color

Convert a color between formats. Input accepts a hex, CSS name, RNV brand name, or saved-palette reference. With `to` set to one of hex/rgb/hsv/hsl/lab, returns just that format; leave `to` out to get all of them. hsv and hsl are fractions from 0 to 1, hue included (multiply hue by 360 for degrees). Read-only and deterministic, with no side effects. Use for format conversion of a single color; to blend several colors into one use mix_colors, and to compare two colors use color_difference.

輸入參數tocolor必填

place_lightness

Hold a color's hue and chroma and set its lightness, returning one result per requested L*. color accepts a hex, CSS name, RNV brand name, or saved-palette reference; lightness is a list of L* values in 0-100. This is the operation behind a LIGHT/DARK PAIR: one hue at two lightnesses, with a and b held exactly, which is how a color that works on a dark ground gets a partner that works on a light one. Use it when you need the same color at a different lightness; use mix_colors when you need a different color. Returns the source color's LAB, and for each placement the hex, the achieved LAB, and the quantization error per axis -- 8-bit hex cannot store a and b to the precision LAB expresses, so two placements of one hue differ by a few hundredths on both axes however exactly the input held them. That is the storage format, not the operation, and it is reported rather than hidden. Read-only and deterministic. Refuses rather than clamps: not every (L*, a, b) exists in sRGB, and a lightness too far from a chromatic color's range is rejected with the reason instead of being silently moved to the nearest color that fits.

輸入參數color必填lightness必填

generate_harmony

Generate a color harmony from a base color. base accepts a hex, CSS name, RNV brand name, or saved-palette reference (e.g. 'Spring line:2'). scheme is one of: complementary, analogous, triadic, split-complementary, tetradic (a.k.a. square), monochromatic, compound. Returns a list of hex colors. Read-only and deterministic: it derives the colors from the base and stores nothing, so it has no side effects and is safe to call repeatedly. Use to expand one base color into a related set; to blend existing colors into a single color use mix_colors, and to persist a set you like use save_palette.

輸入參數base必填scheme必填

color_difference

Perceptual difference (Delta-E) between two colors. color1 and color2 accept a hex, CSS name, RNV brand name, or saved-palette reference. method is 'ciede2000' (default, modern standard) or 'cie76'. A value near 1.0 is the threshold the eye can just notice; larger means more different. Returns the value and a plain-language interpretation. Read-only and deterministic, with no side effects. Use ciede2000 for accuracy and pick cie76 only to match a legacy system; to test whether text is legible on a background (not raw difference) use contrast_check instead.

輸入參數color1必填color2必填method

contrast_check

WCAG contrast ratio between a foreground and background color, for accessibility. Both accept a hex, CSS name, RNV brand name, or saved-palette reference. Returns the ratio (1.0-21.0) plus pass/fail for AA and AAA at normal and large text sizes and for UI components. Read-only and deterministic, with no side effects. Use this for legibility and accessibility checks; to measure raw perceptual difference between two colors rather than readability use color_difference instead.

輸入參數background必填foreground必填

transform_text

Apply an exact, deterministic text transformation. operation is one of: UPPERCASE, lowercase, 'Title Case', 'Sentence case', camelCase, PascalCase, snake_case, CONSTANT_CASE, kebab-case, dot.case, 'iNVERTED cASE'. Read-only and deterministic: it returns the transformed string and changes nothing, safe to call repeatedly. Use whenever exact, reproducible case formatting matters rather than rewriting the text by hand or guessing the casing.

輸入參數text必填operation必填

save_palette

Persist a named color palette for later retrieval with get_palette or list_palettes. Each entry in colors accepts what every other tool accepts: a hex (#d2bc93), a CSS name (red), an RNV brand name (brand gold), or a saved-palette reference ('Spring line:2'); each is resolved and stored as normalized hex, and an unknown token refuses the whole save naming its position. Optional notes are stored as the palette's description. Author is recorded as RNVizion. The name is refused, with the reason, if it is an RNV brand name, a CSS color name, a 'css:' form, a hex literal, or contains ':' -- a palette resolves ahead of brand and CSS names, so such a name would redefine a color for every caller. This WRITES to the palette store and is the only tool here that does. Reusing an existing name overwrites that palette: save and update are the same call (an upsert), there is no separate update operation. Returns a `durable` flag: true if the palette reached durable storage (the HF Dataset) and will survive a restart, false if it saved to the local working copy only (which is lost on rebuild), with `durable_reason` naming the step that stopped it. Use when the user wants to keep a set of colors under a name for reuse across sessions, such as a brand or launch palette; to read a palette back use get_palette, and to see what already exists use list_palettes. The saved name can then be passed to mix_colors, convert_color, and generate_harmony as a palette reference.

輸入參數name必填notescolors必填

list_palettes

List every saved palette as name + colors. Read-only; no side effects. Use to discover what palettes exist or to find a name before calling get_palette; to fetch one palette's full detail use get_palette, and to create or overwrite one use save_palette.

無需輸入參數。

get_palette

Retrieve one saved palette by name, returning its colors and metadata. Returns null if no palette by that name exists. Read-only; no side effects. Use when you already know the palette name; to list available names first use list_palettes, and to create or update a palette use save_palette.

輸入參數name必填

版本歷史

2
  1. v1.3.0最新Sep 28, 2026
  2. v1.2.0Sep 16, 2026

評分

已滿足適用檢查項的 100%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通必需25 分
  • 已宣告認證方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分