brand_check
Validate text, colors, fonts, and CSS against brand identity in under 50ms. Get pass/fail results with specific fixes to ensure brand compliance.
Instructions
Fast inline brand gate — check text, colors, fonts, or CSS against the compiled brand identity in under 50ms. Pass one or more inputs: text (voice violations, never-say, AI-isms), color (palette match with ΔE distance), font (typography match), css (visual anti-pattern violations). Returns pass/fail with specific fixes. Call this reflexively while generating content or code, the way you'd run a linter. Requires brand_compile to have run first. NOT for deep audits — use brand_audit_content for comprehensive scoring.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| text | No | Text to check for voice violations (never-say words, anchor term misuse, AI-isms). Example: "We leverage cutting-edge AI solutions" | |
| color | No | Hex color to check against the brand palette. Returns nearest brand color with perceptual distance (ΔE). Example: "#3b82f6" | |
| font | No | Font family name to check against brand typography. Example: "Helvetica" | |
| css | No | CSS snippet to check for visual anti-pattern violations (shadows, gradients, etc.). Example: "box-shadow: 0 2px 4px rgba(0,0,0,0.1)" |
Implementation Reference
- src/tools/brand-check.ts:41-133 (handler)Main handler for the brand_check tool. Accepts text, color, font, and/or CSS inputs, calls runBrandCheck from the engine, and builds a structured response with pass/fail, flags, and optional brand palette data.
async function handler(input: Params) { const cwd = process.cwd(); // Require at least one input if (!input.text && !input.color && !input.font && !input.css) { return buildResponse({ what_happened: "No input provided — pass at least one of: text, color, font, css", next_steps: [ 'Check text: brand_check text="We leverage AI solutions"', 'Check color: brand_check color="#3b82f6"', 'Check font: brand_check font="Helvetica"', 'Check CSS: brand_check css="box-shadow: 0 2px 4px rgba(0,0,0,0.1)"', ], data: { error: ERROR_CODES.NO_INPUT }, }); } const live = await ensureLiveFreshness(cwd); const liveIndicator = buildLiveIndicator(live); const result = await runBrandCheck(cwd, { text: input.text, color: input.color, font: input.font, css: input.css, }); if (!result) { return buildResponse({ what_happened: "No compiled brand data found — run brand_compile first", next_steps: [ "brand_check requires brand-runtime.json and interaction-policy.json", "Run brand_compile to generate them from your .brand/ data", ], data: { error: ERROR_CODES.NOT_COMPILED }, }); } // Build concise response const { pass, flags, checked } = result; if (pass && flags.length === 0) { return buildResponse({ what_happened: `Brand check passed (${checked.join(", ")})`, next_steps: [], data: { pass: true, checked, flags: [], ...(liveIndicator ? { live: liveIndicator } : {}), }, }); } // Summarize flags by type const errorCount = flags.filter((f) => f.severity === "error").length; const warnCount = flags.filter((f) => f.severity === "warning").length; const infoCount = flags.filter((f) => f.severity === "info").length; const parts: string[] = []; if (errorCount > 0) parts.push(`${errorCount} error(s)`); if (warnCount > 0) parts.push(`${warnCount} warning(s)`); if (infoCount > 0) parts.push(`${infoCount} info`); // Include palette when checking colors (helps agents self-correct) let palette: Array<{ name: string; hex: string }> | null = null; if (input.color && !pass) { palette = await getBrandPalette(cwd); } const data: Record<string, unknown> = { pass, checked, flags, }; if (palette) { data.brand_palette = palette; } if (liveIndicator) { data.live = liveIndicator; } return buildResponse({ what_happened: `Brand check ${pass ? "passed" : "failed"}: ${parts.join(", ")} (${checked.join(", ")})`, next_steps: pass ? [] : flags .filter((f) => f.fix) .slice(0, 3) .map((f) => f.fix!), data, }); } - src/tools/brand-check.ts:135-146 (registration)Registration of the 'brand_check' tool on the MCP server via server.tool(), with Zod schema paramsShape and description of its fast inline brand gate functionality.
export function register(server: McpServer) { server.tool( "brand_check", 'Fast inline brand gate — check text, colors, fonts, or CSS against the compiled brand identity in under 50ms. Pass one or more inputs: text (voice violations, never-say, AI-isms), color (palette match with ΔE distance), font (typography match), css (visual anti-pattern violations). Returns pass/fail with specific fixes. Call this reflexively while generating content or code, the way you\'d run a linter. Requires brand_compile to have run first. NOT for deep audits — use brand_audit_content for comprehensive scoring.', paramsShape, async (args) => { const parsed = safeParseParams(ParamsSchema, args); if (!parsed.success) return parsed.response; return handler(parsed.data); }, ); } - src/tools/brand-check.ts:11-36 (schema)Zod schema for brand_check inputs: text, color, font, css — all optional but at least one required.
const paramsShape = { text: z .string() .optional() .describe( 'Text to check for voice violations (never-say words, anchor term misuse, AI-isms). Example: "We leverage cutting-edge AI solutions"', ), color: z .string() .optional() .describe( 'Hex color to check against the brand palette. Returns nearest brand color with perceptual distance (ΔE). Example: "#3b82f6"', ), font: z .string() .optional() .describe( 'Font family name to check against brand typography. Example: "Helvetica"', ), css: z .string() .optional() .describe( 'CSS snippet to check for visual anti-pattern violations (shadows, gradients, etc.). Example: "box-shadow: 0 2px 4px rgba(0,0,0,0.1)"', ), }; - Core engine function runBrandCheck() that loads cached brand data and runs checkText, checkColor, checkFont, checkCss sub-functions. Also exports getBrandPalette() helper.
export async function runBrandCheck(cwd: string, input: CheckInput): Promise<CheckResult | null> { const brand = await loadCached(cwd); if (!brand) return null; const flags: CheckFlag[] = []; const checked: string[] = []; if (input.text) { checked.push("text"); flags.push(...checkText(input.text, brand)); } if (input.color) { checked.push("color"); flags.push(...checkColor(input.color, brand)); } if (input.font) { checked.push("font"); flags.push(...checkFont(input.font, brand)); } if (input.css) { checked.push("css"); flags.push(...checkCss(input.css, brand)); } return { pass: flags.every((f) => f.severity === "info"), flags, checked, }; } /** Expose brand palette for color suggestions without running a full check. */ export async function getBrandPalette(cwd: string): Promise<Array<{ name: string; hex: string }> | null> { const brand = await loadCached(cwd); if (!brand) return null; return brand.brandColors.map((c) => ({ name: c.name, hex: c.hex })); } - src/server.ts:36-97 (registration)Import and call to registerCheck(server) which registers the brand_check tool on the main MCP server.
import { register as registerCheck } from "./tools/brand-check.js"; import { register as registerPreview } from "./tools/brand-preview.js"; import { register as registerExtractVisual } from "./tools/brand-extract-visual.js"; import { register as registerExtractPdf } from "./tools/brand-extract-pdf.js"; import { register as registerResolveConflicts } from "./tools/brand-resolve-conflicts.js"; import { register as registerBrandcodeAuth } from "./tools/brand-brandcode-auth.js"; import { register as registerBrandcodeConnect } from "./tools/brand-brandcode-connect.js"; import { register as registerBrandcodeSync } from "./tools/brand-brandcode-sync.js"; import { register as registerBrandcodeStatus } from "./tools/brand-brandcode-status.js"; import { register as registerBrandcodeLive } from "./tools/brand-brandcode-live.js"; import { register as registerRepoConnect } from "./tools/brand-repo-connect.js"; import { register as registerRepoStatus } from "./tools/brand-repo-status.js"; import { register as registerEnrichSkill } from "./tools/brand-enrich-skill.js"; export function createServer(): McpServer { const server = new McpServer({ name: "brandsystem", version: getVersion(), }); // ── Entry points (register first — agents see these first) ── registerStart(server); // #1: Entry point for new brands registerStatus(server); // #2: "What can I do?" / resume point // ── Session 1: Core Identity ── registerExtractWeb(server); // Extract from website (CSS parsing) registerExtractVisual(server); // Extract from website (headless Chrome + vision) registerExtractSite(server); // Extract from website (multi-page rendered crawl) registerExtractPdf(server); // Extract from PDF guidelines registerResolveConflicts(server); // Compare and resolve source conflicts registerGenerateDesignMd(server); // Generate design-synthesis.json + DESIGN.md registerExtractFigma(server);// Extract from Figma registerSetLogo(server); // Add/replace logo manually registerCompile(server); // Generate tokens + VIM registerClarify(server); // Resolve ambiguous values registerAudit(server); // Validate .brand/ directory registerReport(server); // Generate HTML report registerInit(server); // Low-level init (prefer brand_start) // ── Session 2: Visual Identity ── registerDeepenIdentity(server); registerIngestAssets(server); registerPreflight(server); // ── Session 3: Messaging ── registerExtractMessaging(server); registerCompileMessaging(server); // ── Session 4: Content Strategy ── registerBuildPersonas(server); registerBuildJourney(server); registerBuildThemes(server); registerBuildMatrix(server); // ── Content scoring ── registerAuditContent(server); // Score content against brand identity registerCheckCompliance(server); // Binary pass/fail gate registerAuditDrift(server); // Batch drift detection // ── Runtime ── registerRuntime(server); // Read compiled brand runtime contract registerCheck(server); // Fast inline brand gate