Skip to main content
Glama

brand_build_matrix

Generate messaging variants for every persona and buying stage. View the matrix as a grid or edit specific variants by ID to refine core messages.

Instructions

Generate persona x journey stage messaging variants — adapted core messages for every audience at every buying stage. Mode 'generate' creates variants using persona tensions, stage mindsets, and brand perspective. Mode 'view' shows the matrix as a grid. Mode 'edit' refines a specific variant by ID. Requires personas and journey stages in strategy.yaml. Returns variant grid with status tracking (Draft/Active/Retired).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
modeNo'generate' creates messaging variants for every persona × stage; 'view' returns the matrix as a grid; 'edit' updates a specific variant by IDgenerate
variant_idNoID of the variant to edit (required for mode='edit', e.g. MV-001)
answersNoJSON string with variant fields to update: core_message, tone_shift, proof_points, status (for mode='edit')

Implementation Reference

  • Main handler function that dispatches to handleGenerate, handleView, or handleEdit based on input.mode
    async function handler(input: Params) {
      const brandDir = new BrandDir(process.cwd());
    
      if (!(await brandDir.exists())) {
        return buildResponse({
          what_happened: "No .brand/ directory found",
          next_steps: ["Run brand_start first to create a brand system"],
          data: { error: ERROR_CODES.NOT_INITIALIZED },
        });
      }
    
      switch (input.mode) {
        case "generate":
          return handleGenerate(brandDir);
    
        case "view":
          return handleView(brandDir);
    
        case "edit": {
          if (!input.variant_id) {
            return buildResponse({
              what_happened: "Missing required parameter: variant_id",
              next_steps: ["Provide variant_id (e.g. MV-001) to identify which variant to edit"],
              data: { error: ERROR_CODES.MISSING_VARIANT_ID },
            });
          }
          if (!input.answers) {
            return buildResponse({
              what_happened: "Missing required parameter: answers",
              next_steps: [
                "Provide answers as a JSON string with fields to update: core_message, tone_shift, proof_points, status",
              ],
              data: { error: ERROR_CODES.MISSING_ANSWERS },
            });
          }
          return handleEdit(brandDir, input.variant_id, input.answers);
        }
      }
    }
  • Zod schema defining params: mode (enum: generate/view/edit), variant_id (optional string), answers (optional JSON string)
    const paramsShape = {
      mode: z
        .enum(["generate", "view", "edit"])
        .default("generate")
        .describe(
          "'generate' creates messaging variants for every persona × stage; 'view' returns the matrix as a grid; 'edit' updates a specific variant by ID"
        ),
      variant_id: z
        .string()
        .optional()
        .describe("ID of the variant to edit (required for mode='edit', e.g. MV-001)"),
      answers: z
        .string()
        .optional()
        .describe(
          "JSON string with variant fields to update: core_message, tone_shift, proof_points, status (for mode='edit')"
        ),
    };
    
    const ParamsSchema = z.object(paramsShape);
    type Params = z.infer<typeof ParamsSchema>;
  • Registers the brand_build_matrix tool with McpServer, binding params schema to handler
    export function register(server: McpServer) {
      server.tool(
        "brand_build_matrix",
        "Generate persona x journey stage messaging variants — adapted core messages for every audience at every buying stage. Mode 'generate' creates variants using persona tensions, stage mindsets, and brand perspective. Mode 'view' shows the matrix as a grid. Mode 'edit' refines a specific variant by ID. Requires personas and journey stages in strategy.yaml. Returns variant grid with status tracking (Draft/Active/Retired).",
        paramsShape,
        async (args) => {
          const parsed = safeParseParams(ParamsSchema, args);
          if (!parsed.success) return parsed.response;
          return handler(parsed.data);
        }
      );
    }
  • src/server.ts:27-88 (registration)
    Import and registration call in createServer, placing it in Session 4: Content Strategy
    import { register as registerBuildMatrix } from "./tools/brand-build-matrix.js";
    import { register as registerBuildThemes } from "./tools/brand-build-themes.js";
    import { register as registerExport } from "./tools/brand-export.js";
    import { register as registerSetLogo } from "./tools/brand-set-logo.js";
    import { register as registerFeedback } from "./tools/brand-feedback.js";
    import { register as registerAuditContent } from "./tools/brand-audit-content.js";
    import { register as registerCheckCompliance } from "./tools/brand-check-compliance.js";
    import { register as registerAuditDrift } from "./tools/brand-audit-drift.js";
    import { register as registerRuntime } from "./tools/brand-runtime.js";
    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);
  • synthesizeCoreMessage - core intelligence that crafts adapted messages per persona × stage using tensions, mindsets, and brand perspective
    function synthesizeCoreMessage(
      persona: Persona,
      stage: JourneyStage,
      perspective: { worldview: string; tension: string; resolution: string; positioning: string } | null
    ): string {
      const personaLabel = persona.name || persona.role_tag;
      const tensionPhrase = persona.core_tension;
      const mindset = stage.buyer_mindset;
      const goal = stage.content_goal;
      const narrativeAngle = persona.narrative_emphasis.primary;
    
      // Build the adapted message — branch on stage.id for reliable matching
      const parts: string[] = [];
    
      if (stage.id === "first-touch") {
        // Provocative, tension-as-hook — earn the click, interrupt the scroll
        parts.push(
          `${personaLabel} feels this acutely: ${tensionPhrase}.`
        );
        if (perspective) {
          parts.push(
            `The angle here is ${perspective.worldview} — reframed for someone whose mindset is: ${mindset}.`
          );
        } else {
          parts.push(
            `At this stage, their mindset is: ${mindset}.`
          );
        }
        parts.push(
          `Content goal: ${goal}. Lead with ${narrativeAngle} to earn attention.`
        );
      } else if (stage.id === "context-and-meaning") {
        // Educational, framework-oriented — give them a lens, not a pitch
        parts.push(
          `${personaLabel} is past awareness and looking for a framework. Their tension: ${tensionPhrase}.`
        );
        if (perspective) {
          parts.push(
            `Introduce ${perspective.worldview} as the lens — help them see the problem differently. Their mindset: ${mindset}.`
          );
        } else {
          parts.push(
            `Help them reframe the problem. Their mindset: ${mindset}.`
          );
        }
        parts.push(
          `Content goal: ${goal}. Build depth through ${narrativeAngle} — teach, don't sell.`
        );
      } else if (stage.id === "validation-and-proof") {
        // Evidence-heavy, concrete outcomes, social proof
        parts.push(
          `For ${personaLabel}, the core tension is: ${tensionPhrase}.`
        );
        if (perspective) {
          parts.push(
            `At this stage they need proof that ${perspective.resolution}. Their mindset: ${mindset}.`
          );
        } else {
          parts.push(
            `At this stage they need proof. Their mindset: ${mindset}.`
          );
        }
        parts.push(
          `Content goal: ${goal}. Emphasize ${narrativeAngle} with evidence.`
        );
      } else if (stage.id === "decision-support") {
        // Direct, action-oriented — remove friction, arm the champion
        parts.push(
          `${personaLabel} is ready to decide. Their original tension — ${tensionPhrase} — needs a resolution they can defend to stakeholders.`
        );
        if (perspective) {
          parts.push(
            `Position: ${perspective.positioning}. Their mindset: ${mindset}.`
          );
        } else {
          parts.push(
            `Their mindset: ${mindset}.`
          );
        }
        parts.push(
          `Content goal: ${goal}. Use ${narrativeAngle} to close the loop.`
        );
      } else {
        // Generic fallback for custom stages
        parts.push(
          `For ${personaLabel} (${persona.seniority}), the driving tension is: ${tensionPhrase}.`
        );
        if (perspective) {
          parts.push(
            `Ground the message in: ${perspective.worldview}. Their mindset at this stage: ${mindset}.`
          );
        } else {
          parts.push(
            `Their mindset at this stage: ${mindset}.`
          );
        }
        parts.push(
          `Content goal: ${goal}. Narrative emphasis: ${narrativeAngle}.`
        );
      }
    
      return parts.join(" ");
    }
Behavior4/5

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

The description discloses all three modes' behaviors and the return format ('Returns variant grid with status tracking (Draft/Active/Retired)'). With no annotations, it covers safety (read/edit/generate) and dependencies, though it could mention persistence for edits.

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

Conciseness5/5

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

The description is concise with 5 sentences, each serving a clear purpose: mode overview, three mode-specific sentences, dependency, and output description. No redundancy or unnecessary details.

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 3 parameters, no output schema, and no annotations, the description fully equips an AI agent: it covers all modes, prerequisites, return value with status tracking, and parameter specifics. No gaps remain for correct invocation.

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

Parameters5/5

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

Schema coverage is 100%, and the description adds significant meaning: it explains the purpose of each mode, the format of 'answers' JSON, and the prerequisite. It also describes the output format, which is absent from the schema, providing critical context for invocation.

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 states exactly what the tool does: 'Generate persona x journey stage messaging variants' with three clear modes. It distinguishes from siblings like brand_build_personas and brand_build_themes by focusing on the matrix generation across persona and stage.

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

Usage Guidelines4/5

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

The description explains each mode's purpose and the prerequisite ('Requires personas and journey stages in strategy.yaml'). It implies when to use each mode (generate, view, edit) but does not explicitly state when not to use it or mention alternatives, which is less critical given the distinct sibling set.

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