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 分