Skip to main content
Glama

brand_compile

Compiles brand identity from extracted data into DTCG tokens, runtime contracts, and enforceable policies for AI agents.

Instructions

Generate DTCG design tokens, design-synthesis.json, DESIGN.md, brand runtime, and interaction policy from extracted brand data. Transforms core-identity.yaml into tokens.json, brand-runtime.json (single-document brand contract for AI agents), and interaction-policy.json (enforceable rules). When Session 2+ data exists, also generates visual-identity-manifest.md and system-integration.md. Use after brand_extract_web, brand_extract_site, brand_extract_visual, or brand_extract_figma. Returns token counts, clarification items, and file list.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The tool 'brand_compile' is registered as an MCP tool via server.tool() with a descriptive description explaining it generates DTCG design tokens, design-synthesis.json, DESIGN.md, brand runtime, and interaction policy from extracted brand data.
    export function register(server: McpServer) {
      server.tool(
        "brand_compile",
        "Generate DTCG design tokens, design-synthesis.json, DESIGN.md, brand runtime, and interaction policy from extracted brand data. Transforms core-identity.yaml into tokens.json, brand-runtime.json (single-document brand contract for AI agents), and interaction-policy.json (enforceable rules). When Session 2+ data exists, also generates visual-identity-manifest.md and system-integration.md. Use after brand_extract_web, brand_extract_site, brand_extract_visual, or brand_extract_figma. Returns token counts, clarification items, and file list.",
        async () => handler(server)
      );
    }
  • The main handler function that implements the brand_compile tool logic. It reads and validates .brand/ config and core identity files, generates DTCG design tokens, checks for clarification items (low confidence colors, fonts, missing logo, unknown color roles), generates Visual Identity Manifest and System Integration Guide if Session 2 data exists, compiles brand runtime and interaction policy, invalidates check cache, and returns a structured response with next steps and conversation guidance.
    async function handler(server: McpServer) {
      const brandDir = new BrandDir(process.cwd());
    
      if (!(await brandDir.exists())) {
        return buildResponse({
          what_happened: "No .brand/ directory found",
          next_steps: [
            "Run brand_init first to create the .brand/ directory",
            "If this keeps happening, run brand_feedback to report the issue.",
          ],
          data: { error: ERROR_CODES.NOT_INITIALIZED },
        });
      }
    
      // Read and validate all source files upfront, collecting all errors
      const validationErrors: string[] = [];
    
      let config;
      try {
        config = await brandDir.readConfig();
      } catch (err) {
        if (err && typeof err === "object" && "issues" in err) {
          const issues = (err as { issues: Array<{ path: (string | number)[]; message: string }> }).issues;
          for (const issue of issues) {
            validationErrors.push(`brand.config.yaml: ${issue.path.join(".")} — ${issue.message}`);
          }
        } else {
          validationErrors.push(`brand.config.yaml: ${(err as Error).message}`);
        }
      }
    
      let identity;
      try {
        identity = await brandDir.readCoreIdentity();
      } catch (err) {
        if (err && typeof err === "object" && "issues" in err) {
          const issues = (err as { issues: Array<{ path: (string | number)[]; message: string }> }).issues;
          for (const issue of issues) {
            validationErrors.push(`core-identity.yaml: ${issue.path.join(".")} — ${issue.message}`);
          }
        } else {
          validationErrors.push(`core-identity.yaml: ${(err as Error).message}`);
        }
      }
    
      if (validationErrors.length > 0) {
        return buildResponse({
          what_happened: `${validationErrors.length} schema validation error(s) found — fix all before recompiling`,
          next_steps: [
            "Fix the errors listed below in your .brand/ YAML files, then run brand_compile again",
            "Or run brand_start to re-extract from scratch with the current schema",
          ],
          data: {
            error: ERROR_CODES.VALIDATION_FAILED,
            validation_errors: validationErrors,
          },
        });
      }
    
      // TypeScript narrowing — both are defined if we got past validation
      config = config!;
      identity = identity!;
    
      const designArtifacts = await generateAndPersistDesignArtifacts(brandDir, { overwrite: true });
    
      const tokens = compileDTCG(identity, config.client_name, designArtifacts.synthesis);
      await brandDir.writeTokens(tokens);
    
      const clarifications: ClarificationItem[] = [];
      let itemId = 0;
    
      if (!identity.colors.some((c) => c.role === "primary")) {
        clarifications.push({
          id: `clarify-${++itemId}`,
          field: "colors.primary",
          question: "No primary brand color identified. Which color is your primary brand color?",
          source: "compilation",
          priority: "high",
        });
      }
    
      for (const color of identity.colors) {
        if (needsClarification(color.confidence)) {
          clarifications.push({
            id: `clarify-${++itemId}`,
            field: `colors.${color.role}`,
            question: `Color ${color.value} (${color.name}) has low confidence. Is this correct and what role does it play?`,
            source: color.source,
            priority: "medium",
          });
        }
      }
    
      if (identity.typography.length === 0) {
        clarifications.push({
          id: `clarify-${++itemId}`,
          field: "typography",
          question: "No fonts detected. What font family does your brand use?",
          source: "compilation",
          priority: "high",
        });
      }
    
      for (const typo of identity.typography) {
        if (needsClarification(typo.confidence)) {
          clarifications.push({
            id: `clarify-${++itemId}`,
            field: `typography.${typo.family}`,
            question: `Font "${typo.family}" has low confidence. Is this your brand font?`,
            source: typo.source,
            priority: "medium",
          });
        }
      }
    
      if (identity.logo.length === 0) {
        clarifications.push({
          id: `clarify-${++itemId}`,
          field: "logo",
          question: "No logo detected. Provide your logo as SVG for best results.",
          source: "compilation",
          priority: "high",
        });
      }
    
      const unknownColors = identity.colors.filter((c) => c.role === "unknown");
      if (unknownColors.length > 0) {
        clarifications.push({
          id: `clarify-${++itemId}`,
          field: "colors.roles",
          question: `${unknownColors.length} color(s) have no assigned role: ${unknownColors.map((c) => c.value).join(", ")}. What role does each play?`,
          source: "compilation",
          priority: "medium",
        });
      }
    
      await brandDir.writeClarifications({ schema_version: SCHEMA_VERSION, items: clarifications });
    
      const brandTokens = tokens.brand as Record<string, unknown>;
      const colorTokenCount = Object.keys((brandTokens.color as Record<string, unknown>) || {}).length;
      const typoTokenCount = Object.keys((brandTokens.typography as Record<string, unknown>) || {}).length;
    
      const filesWritten: string[] = ["tokens.json", "needs-clarification.yaml", ...designArtifacts.files_written];
      const nextSteps: string[] = [];
    
      if (clarifications.length > 0) {
        nextSteps.push(`${clarifications.length} item(s) need clarification — walk the user through brand_clarify for each one`);
      } else {
        nextSteps.push("No clarification items — system is clean");
        nextSteps.push("Run brand_report to generate the portable brand identity report");
      }
      nextSteps.push("DESIGN.md and design-synthesis.json are refreshed — use them as the agent-facing design brief and structured synthesis layer");
    
      // --- Read optional session data (graceful on schema errors) ---
      const hasVisual = await brandDir.hasVisualIdentity();
      const hasMessaging = await brandDir.hasMessaging();
      const hasStrategy = await brandDir.hasStrategy();
      const schemaWarnings: string[] = [];
    
      let visual = null;
      if (hasVisual) {
        try { visual = await brandDir.readVisualIdentity(); }
        catch (err) {
          const msg = err && typeof err === "object" && "issues" in err
            ? (err as { issues: Array<{ path: (string | number)[]; message: string }> }).issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")
            : (err as Error).message;
          schemaWarnings.push(`visual-identity.yaml skipped (schema error): ${msg}`);
        }
      }
    
      let messaging = null;
      if (hasMessaging) {
        try { messaging = await brandDir.readMessaging(); }
        catch (err) {
          const msg = err && typeof err === "object" && "issues" in err
            ? (err as { issues: Array<{ path: (string | number)[]; message: string }> }).issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")
            : (err as Error).message;
          schemaWarnings.push(`messaging.yaml skipped (schema error): ${msg}`);
        }
      }
    
      let strategy = null;
      if (hasStrategy) {
        try { strategy = await brandDir.readStrategy(); }
        catch (err) {
          const msg = err && typeof err === "object" && "issues" in err
            ? (err as { issues: Array<{ path: (string | number)[]; message: string }> }).issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")
            : (err as Error).message;
          schemaWarnings.push(`content-strategy.yaml skipped (schema error): ${msg}`);
        }
      }
    
      // --- Session 2: VIM generation if visual-identity.yaml exists ---
      if (visual) {
        const vimMarkdown = generateVIM(config, identity, visual);
        await brandDir.writeMarkdown("visual-identity-manifest.md", vimMarkdown);
        filesWritten.push("visual-identity-manifest.md");
    
        const integrationMarkdown = generateSystemIntegration(config, identity, visual, messaging);
        await brandDir.writeMarkdown("system-integration.md", integrationMarkdown);
        filesWritten.push("system-integration.md");
    
        if (config.session < 2) {
          config.session = 2;
          await brandDir.writeConfig(config);
        }
    
        nextSteps.push(
          "Visual Identity Manifest written — share visual-identity-manifest.md with your team",
          "System Integration Guide written — paste the quick-setup block into CLAUDE.md or .cursorrules"
        );
    
        if (!messaging) {
          nextSteps.push("Ready for Session 3: run brand_extract_messaging to audit your voice, then brand_compile_messaging to define perspective + voice + brand story");
        }
      }
    
      // --- Runtime + Interaction Policy compilation ---
      const runtime = compileRuntime(config, identity, visual, messaging, strategy);
      await brandDir.writeRuntime(runtime);
      filesWritten.push("brand-runtime.json");
    
      const policy = compileInteractionPolicy(config.schema_version, visual, messaging, strategy);
      await brandDir.writePolicy(policy);
      filesWritten.push("interaction-policy.json");
    
      // Invalidate brand_check cache so subsequent checks use fresh data
      invalidateCheckCache();
    
      // Notify subscribed resource clients that runtime + policy have changed
      server.sendResourceListChanged();
    
      // Session transition guidance
      let conversationGuide: { instruction: string; conditionals?: Record<string, string> } | null = null;
      if (hasVisual && !hasMessaging) {
        conversationGuide = {
          instruction: [
            "Session 2 (Visual Identity) is complete. Now transition to Session 3.",
            "Tell the user: 'Your visual identity is locked in — composition, patterns, signature moves, and anti-patterns. Now let's capture how your brand *sounds*. This is where output goes from color-correct to distinctively yours.'",
            "Suggest: 'I can start by auditing what your brand currently sounds like on your website. Want me to run that analysis?'",
            "If yes: run brand_extract_messaging. If they want to skip the audit: run brand_compile_messaging directly.",
          ].join("\n"),
        };
      } else if (!hasVisual && clarifications.length === 0) {
        conversationGuide = {
          instruction: [
            "Session 1 is complete. Your brand-runtime.json is compiled and ready to use — any agent you give it to will produce on-brand content with the right colors, fonts, and logo.",
            "",
            "Before moving on, mention what Session 2 unlocks:",
            "'Right now your brand runtime has identity (colors, fonts, logo). Session 2 adds *visual rules* — composition guidelines, anti-patterns your agents will reject, illustration direction, and signature moves. It makes your brand-runtime dramatically more useful because agents won't just use the right colors, they'll use them *the right way*.'",
            "",
            "Then ask: 'Want to go deeper, or is this enough for now?'",
            "If yes: run brand_deepen_identity.",
            "If no: that's fine. The Session 1 runtime is already valuable.",
          ].join("\n"),
        };
      } else if (!hasVisual && clarifications.length > 0) {
        conversationGuide = {
          instruction: [
            "Session 1 compiled successfully but some values need confirmation.",
            `There are ${clarifications.length} clarification items (${clarifications.filter((c) => c.priority === "high").length} high priority).`,
            "",
            "Present the high-priority items to the user for quick confirmation. Use brand_clarify to resolve each one.",
            "After clarifications are resolved, recompile with brand_compile to update the runtime.",
            "",
            "Meanwhile, mention what Session 2 adds to the runtime:",
            "'Session 2 captures visual rules — composition, anti-patterns, illustration style. Your sub-agents will know not just *what* colors to use, but *how* to use them. Want to do that after we confirm these values?'",
          ].join("\n"),
        };
      }
    
      return buildResponse({
        what_happened: hasVisual
          ? `Compiled brand system + Visual Identity Manifest for "${config.client_name}"`
          : `Compiled brand system for "${config.client_name}"`,
        next_steps: nextSteps,
        data: {
          files_written: filesWritten,
          tokens: { colors: colorTokenCount, typography: typoTokenCount, total: colorTokenCount + typoTokenCount },
          clarifications: {
            total: clarifications.length,
            high_priority: clarifications.filter((c) => c.priority === "high").length,
            items: clarifications.map((c) => `[${c.priority}] ${c.question}`),
          },
          runtime_compiled: true,
          design_synthesis_generated: true,
          design_synthesis_source: designArtifacts.source_used,
          ...(schemaWarnings.length > 0 && { schema_warnings: schemaWarnings }),
          agent_tip: "Load .brand/brand-runtime.json into any sub-agent's context. It replaces 200-400 tokens of per-prompt brand boilerplate with a single file. First output will be on-brand.",
          ...(hasVisual && { vim_generated: true }),
          ...(conversationGuide && { conversation_guide: conversationGuide }),
        },
      });
    }
  • src/server.ts:12-12 (registration)
    The brand_compile tool is imported and registered in the main server via registerCompile(server) call at line 69.
    import { register as registerCompile } from "./tools/brand-compile.js";
  • src/server.ts:69-69 (registration)
    registerCompile(server) is called to register the brand_compile tool as part of Session 1: Core Identity tools.
    registerCompile(server);     // Generate tokens + VIM
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It discloses inputs, outputs (including conditional generation for Session 2+ data), and return values. However, it does not mention potential side effects like file overwriting or required permissions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single dense paragraph that conveys multiple pieces of information efficiently. It front-loads the main purpose but could benefit from slight structuring (e.g., bullet points for outputs). Nonetheless, no wasted sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has no output schema, the description explains return values (token counts, clarification items, file list). It also covers conditional behavior based on session data. This is sufficiently complete for a complex tool with many outputs.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has no parameters (0 params, 100% coverage). With no parameters to describe, the baseline is 4. The description does not add parameter info but does not need to.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: generating multiple design artifacts (DTCG tokens, design-synthesis.json, DESIGN.md, brand runtime, interaction policy) from extracted brand data. It uses specific verbs and resource names, making it easily distinguishable from siblings like brand_compile_messaging.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use the tool: 'Use after brand_extract_web, brand_extract_site, brand_extract_visual, or brand_extract_figma.' This provides clear context and prerequisites, and the sibling list implies alternatives for other scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Brandcode-Studio/brandsystem-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server