John Agan • Technical Leadership Interview Walkthrough
P1

The problem — brand review at AI scale

JPMC had more than 75 brand kits like this Payments example. Reviewers and designers still had to interpret that guidance manually, which made review slow and early concept work hard to scale.

Payments brand kit overview
Opening frame

The brand kit was the source of truth, but AI could not use it directly yet.

The technical question became: can we turn guideline pages, examples, and tacit brand knowledge into a structured system that helps with both compliance review and generation?

  • Primary bottleneckAgency submissions still needed slow, inconsistent manual review.
  • Secondary opportunityDesigners wanted to explore early concepts faster without drifting off brand.
  • Technical reframeThe real problem was retrieving and applying brand constraints, not just copying a visual style.
REF

Brand reference screenshots

A few examples from the Payments guideline kit, grouped by the kind of brand knowledge the system needed to understand.

Foundation

The intent and identity rules the system needed to preserve.

0.0 Strategy brand guideline screenshot

0.0 Strategy

1391:22094 · Figma source

2.0 Payments Lockup brand guideline screenshot

2.0 Payments Lockup

1391:8429 · Figma source

Rules and structure

The concrete visual rules that mattered most for retrieval, compliance checks, and citations.

3.0 Color brand guideline screenshot

3.0 Color

1391:25334 · Figma source

4.0 Typography brand guideline screenshot

4.0 Typography

1391:9721 · Figma source

5.0 Linework brand guideline screenshot

5.0 Linework

1391:14172 · Figma source

6.0 Layout brand guideline screenshot

6.0 Layout

1391:19731 · Figma source

Expression and output

Examples showing how the rules come through in imagery, icons, motion, and final applications.

8.0 Graphic Imagery brand guideline screenshot

8.0 Graphic Imagery

1391:21496 · Figma source

9.0 Iconography brand guideline screenshot

9.0 Iconography

1391:22477 · Figma source

10.0 Motion brand guideline screenshot

10.0 Motion

1391:22303 · Figma source

11.0 Application brand guideline screenshot

11.0 Application

1391:13992 · Figma source

01

Project walkthrough — the leadership arc

This opening map frames the JPMC engagement the way I would talk through it: an ambiguous AI ask, hands-on architecture, stakeholder alignment, and a concrete outcome through a brand-knowledge system.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart LR
    OPEN["Open with the client problem<br/>slow, inconsistent brand review"]

    subgraph Rubric["Technical leadership arc"]
        ROLE["My role<br/>technical lead + builder"]
        DEPTH["Technical depth<br/>Figma document tree, retrieval, MCP"]
        TRADEOFFS["Tradeoffs<br/>style transfer vs. constraint retrieval"]
        INFLUENCE["Influence<br/>brand, engineering, vendor strategy"]
        IMPACT["Impact<br/>Frontify, Adobe complementarity, handoff"]
    end

    OPEN --> ROLE
    OPEN --> DEPTH
    OPEN --> TRADEOFFS
    OPEN --> INFLUENCE
    OPEN --> IMPACT

    ROLE --> STORY["Core story<br/>I turned an ambiguous AI ask into<br/>a working reference architecture and a clearer strategic direction"]
    DEPTH --> STORY
    TRADEOFFS --> STORY
    INFLUENCE --> STORY
    IMPACT --> STORY

    class OPEN insight
    class ROLE,DEPTH,TRADEOFFS,INFLUENCE,IMPACT highlight
    class STORY contract

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412
02

Problem framing — two bottlenecks, one foundation

This section narrows the engagement to two use cases: reviewing agency work and helping designers explore concepts faster. Both needed the same thing underneath: structured access to brand rules.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart TB
    subgraph Presented["What was presented"]
        GUIDE["Payments brand kit in Figma<br/>strategy · color · typography · layout · application"]
        REVIEWERS["Manual brand reviewers<br/>slow and inconsistent checks"]
        DESIGNERS["Internal designers<br/>days to weeks of early iteration"]
    end

    subgraph Asks["The asks"]
        A1["Can AI enforce brand guidelines?<br/>Primary: review agency submissions"]
        A2["Can AI accelerate design iterations?<br/>Bonus: generate concepts that follow rules"]
    end

    subgraph Reframe["Technical reframe"]
        I["Brand grounding = constraint problem<br/>not just style transfer"]
        R["Need: searchable, structured access<br/>to documented brand rules"]
    end

    subgraph Foundation["One foundation, two workflows"]
        F["Figma document-tree ingestion<br/>semantic chunking<br/>retrieval + citations"]
        E["Evaluative mode<br/>Does this conform?"]
        G["Generative mode<br/>Produce something that conforms"]
    end

    GUIDE --> A1
    REVIEWERS --> A1
    GUIDE --> A2
    DESIGNERS --> A2
    A1 --> I
    A2 --> I
    I --> R
    R --> F
    F --> E
    F --> G

    class A1,A2 highlight
    class I,R insight
    class F contract
    class E,G ok

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412

    linkStyle 6 stroke:#9333ea,stroke-width:2px
03

Early generation experiments — what we ruled out

This section covers the first two generation attempts. They were useful because they showed that screenshots and style transfer could get close visually, but they could not reliably follow specific brand rules.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart LR
    subgraph Attempt1["Attempt 1 · Foundation models"]
        A1["Feed Figma screenshots / PNG exports<br/>into ChatGPT, Nano Banana, etc."]
        R1["Result: generic financial-services look<br/>No payments vs. private banking grounding"]
    end

    subgraph Attempt2["Attempt 2 · LoRA on Replicate"]
        A2["Train LoRA on Figma image exports<br/>Style transfer via diffusion fine-tuning"]
        R2["Result: ~on-brand aesthetic<br/>Wrong hex codes, logo placement, typography"]
    end

    subgraph Pivot["Pivot"]
        P["Takeaway: style ≠ constraints<br/>→ retrieve the actual brand rules"]
    end

    A1 --> R1
    R1 --> A2
    A2 --> R2
    R2 --> P

    class R1 fail
    class R2 warn
    class P ok

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412

    linkStyle 0 stroke:#dc2626,stroke-width:2px
    linkStyle 3 stroke:#059669,stroke-width:2px
04

Figma export paths — what kept the structure

This section compares a few ways to get brand guidance out of Figma and explains why the raw document tree was the only path that kept the useful structure intact.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart TD
    Q["How do we turn brand guidance into structured data?<br/>Source: Figma API (JPMC brand kits)"]

    Q --> PDF
    Q --> PNG
    Q --> SVG
    Q --> JSON

    PDF["PDF export + PDF-to-text"]
    PNG["PNG raster exports"]
    SVG["SVG vector exports"]
    JSON["Raw Figma document JSON tree"]

    PDF --> PDF_FAIL["Failed: lost spatial relationships and groupings<br/>Guidance got flattened"]
    PNG --> PNG_FAIL["Failed: just pixels, no structure to retrieve"]
    SVG --> SVG_FAIL["Failed: shapes, but not enough design-system context"]
    JSON --> JSON_OK["Worked: preserved visual semantics + structural metadata<br/>→ custom Bun/TS document-tree walker"]

    JSON_OK --> SDK["Off-the-shelf Figma SDK did not cover the traversal I needed<br/>→ wrote a minimal custom SDK"]

    class PDF,PNG,SVG muted
    class PDF_FAIL,PNG_FAIL,SVG_FAIL fail
    class JSON,JSON_OK,SDK ok

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412

    linkStyle 3,4 stroke:#059669,stroke-width:2px
TREE

Figma document tree sample — raw brand-kit structure

A trimmed example from context/example-brand-ast.json. This is the technical structure behind the Figma file, and it explains why the raw tree was more useful than screenshots, PDFs, or flattened exports.

{
  "name": "Encyclopedia JPMC",
  "document": {
    "id": "0:0",
    "name": "Document",
    "type": "DOCUMENT",
    "children": [
      {
        "id": "476:1227",
        "name": "JPM style guides 2",
        "type": "CANVAS",
        "children": [
          {
            "id": "487:14604",
            "name": "Payments",
            "type": "SECTION",
            "childrenCount": 218,
            "absoluteBoundingBox": {
              "x": -115553.015625,
              "y": -24706.748046875,
              "width": 38624.71875,
              "height": 52166.5703125
            },
            "children": [
              {
                "id": "1391:22094",
                "name": "0.0 Strategy",
                "type": "FRAME",
                "absoluteBoundingBox": {
                  "x": -107193,
                  "y": -19624.748046875,
                  "width": 1920,
                  "height": 1080
                }
              }
            ]
          }
        ]
      }
    ]
  }
}
The hierarchy is still there. The file keeps document, canvas, section, frame, and child relationships, so chunks can follow the design tree instead of arbitrary page boundaries.
The layout is still there. Bounding boxes preserve layout and proximity signals that disappear in PDF-to-text or generic image prompting.
The citations are stable. Figma node IDs make it possible to return an answer with a source link back to the original guideline frame.
05

Ingestion and chunking — first pass to better version

This section shows how the ingestion approach changed after the first version produced weak retrieval. The fix was to chunk around meaningful design-tree units, not whole pages.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart TB
    subgraph V1["Attempt 1 · Naive ingestion"]
        V1A["Embed raw Figma tree into ChromaDB"]
        V1B["Chunk at page level"]
        V1C["Poor retrieval — embeddings averaged signal<br/>Chunks misaligned with semantic boundaries"]
    end

    subgraph Diagnosis["What we learned"]
        D["Chunk boundaries needed to follow<br/>meaningful units in the design tree<br/>(a Figma-specific chunking problem)"]
        OBS["Observation: brand kit = visual artifacts,<br/>not Figma Components / Component Sets"]
    end

    subgraph V2["Attempt 2 · Semantic recursive descent"]
        V2A["Recurse tree until subtree fits embedding window"]
        V2B["Emit subtree as chunk; roll ancestor metadata up"]
        V2C["Key on Group nodes as cohesive visual units"]
        V2D["Dual storage per chunk:<br/>raw tree JSON + derived metadata<br/>(colors, radii, typography)"]
    end

    subgraph Ops["Incremental ops (prototype)"]
        O1["Cache document tree locally"]
        O2["Refresh on Figma last_modified"]
        O3["Re-embed changed subtrees in the prototype"]
    end

    V1A --> V1B --> V1C
    V1C --> D
    D --> V2A
    OBS -.-> D
    V2A --> V2B --> V2C --> V2D
    V2D --> Ops

    class V1C fail
    class D,OBS insight
    class V2D ok
    class O1,O2,O3 muted

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412

    linkStyle 2 stroke:#dc2626,stroke-width:2px
    linkStyle 6 stroke:#059669,stroke-width:2px
06

Chunking algorithm — the retrieval unit

This section explains the unit I used for retrieval: a design-tree subtree, sized for embedding, with parent context, raw JSON, and extracted design properties attached.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart TD
    ROOT["Figma file root"]
    ROOT --> WALK["Recursive descent"]

    WALK --> FIT{"Subtree fits<br/>embedding window?"}
    FIT -->|No| WALK
    FIT -->|Yes| EMIT["Emit chunk"]

    EMIT --> L1["Layer 1: Raw tree JSON<br/>(can rebuild the subtree)"]
    EMIT --> L2["Layer 2: Derived metadata<br/>hex tokens, border radii, typography refs"]
    EMIT --> META["Parent-path metadata<br/>(hierarchy as context, no overlap windows)"]

    L1 --> STORE["ChromaDB (local)<br/>Default text sentence-transformer on JSON"]
    L2 --> STORE
    META --> STORE

    STORE --> PROD["Production upgrade deferred:<br/>text embeddings on JSON + CLIP on rendered previews"]

    class FIT decision
    class L1,L2,META highlight
    class STORE datastore
    class PROD muted

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412
{
  "chunkId": "payments-color-primary-palette",
  "source": {
    "file": "JPMC Payments brand kit",
    "nodeId": "1391:25334",
    "path": ["Payments", "3.0 Color", "Primary palette"]
  },
  "rawTree": {
    "type": "GROUP",
    "name": "Primary palette",
    "childrenCount": 8
  },
  "metadata": {
    "colors": ["#005EB8", "#00A3E0", "#FFFFFF"],
    "usage": ["primary brand color", "supporting accent", "background"],
    "citations": ["figma://node/1391:25334"]
  },
  "retrievalText": "Payments primary palette: use JPMC blue as the main brand color, cyan as a supporting accent, and white for clean backgrounds."
}
Raw tree keeps the source reconstructible. I could always trace a chunk back to the Figma group or frame that produced it.
Metadata makes retrieval useful. Colors, typography, radii, and citation links were pulled out so the tool could answer directly instead of returning a vague blob.
Retrieval text makes it searchable. The plain-language summary gave the embedding model something closer to how designers actually ask questions.
07

System architecture — stable interface, swappable internals

This section shows the reference architecture: Figma as the source of truth, a custom extraction and retrieval layer, MCP as the stable tool interface, and generation/orchestration pieces that could change later.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart TB
    subgraph Input["What enters the system"]
        FIGMA["Figma org API<br/>canonical brand kits + agency submissions<br/>same auth boundary, same source of truth"]
    end

    subgraph Foundation["Extraction foundation"]
        EXTRACT["Custom Bun/TypeScript Figma SDK<br/>document-tree walker over sections, frames, groups, text, geometry<br/>semantic recursive chunking + incremental refresh"]
    end

    subgraph Store["Brand knowledge layer"]
        KNOWLEDGE["Each chunk stores two views<br/>raw tree JSON so it can be rebuilt<br/>derived metadata for retrieval: colors, typography, radii, links<br/>ChromaDB prototype vector search"]
    end

    subgraph Contract["Tool interface"]
        MCP["MCP server<br/>search_brand_guidelines<br/>get_figma_citation<br/>analyze_compliance"]
    end

    subgraph Modes["Two workflows on the same substrate"]
        EVAL["Evaluative mode<br/>Does this submission conform?<br/>structured issues + formatted feedback"]
        GEN["Generative mode<br/>Assemble brand-grounded brief / prompt<br/>backend remains swappable"]
    end

    subgraph Evidence["Trust and verification loop"]
        TRUST["Figma deep links for verification<br/>MCP retrieval logs for diagnosis<br/>guideline-shaped responses for designers"]
    end

    subgraph Backend["Swappable backend choice"]
        COMFY["ComfyUI prototype<br/>local feasibility validation"]
        TBD["Production backend TBD<br/>Adobe Firefly · Flux · internal model"]
    end

    FIGMA --> EXTRACT --> KNOWLEDGE --> MCP
    MCP --> EVAL
    MCP --> GEN
    MCP --> TRUST
    EVAL --> TRUST
    GEN -.-> COMFY -.-> TBD

    FIGMA -.->|"submission and rule source use the same document-tree path"| EXTRACT
    KNOWLEDGE -.->|"raw tree for rebuilding, derived fields for retrieval"| MCP

    class MCP contract
    class EXTRACT highlight
    class KNOWLEDGE datastore
    class EVAL,GEN ok
    class TRUST decision
    class COMFY insight
    class TBD muted

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412
08

Same extraction path — comparing rules to submissions

This section shows the compliance idea: run the brand kit and the agency submission through the same extraction path, then compare them in the same representation.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart LR
    subgraph Rules["Rule source"]
        BK["Canonical brand kit<br/>(Figma file)"]
    end

    subgraph Artifact["Under review"]
        SUB["Agency submission<br/>(Figma file)"]
    end

    subgraph Pipeline["Same document-tree extraction pipeline"]
        W["Document-tree walker"]
    end

    subgraph Rep["Same representation"]
        R1["Brand guidance chunks<br/>+ derived properties"]
        R2["Submission properties<br/>+ structure"]
    end

    subgraph Compare["Compliance analysis tool"]
        RET["Retrieve relevant brand guidance"]
        DIFF["Compare design properties"]
        OUT["Structured issues + formatted feedback<br/>(system prompt defines violation vs. variation)"]
    end

    subgraph Trust["Trust & audit"]
        CITE["Citation tool → Figma deep link<br/>Verify in source of truth"]
    end

    BK --> W
    SUB --> W
    W --> R1
    W --> R2
    R1 --> RET
    R2 --> DIFF
    RET --> DIFF
    DIFF --> OUT
    RET --> CITE

    ANTI["Typical failure mode avoided:<br/>different representations + fragile translation layer"]
    ANTI -.-> Pipeline

    class W highlight
    class R1,R2 datastore
    class OUT ok
    class CITE contract
    class ANTI fail

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412
09

MCP tools — designed for designers

This section presents the MCP tools as a designer-facing interface: structured search, Figma citations, and responses shaped like brand guidance instead of raw search results.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart TD
    IFACE["Tool response shape<br/>matches how designers ask questions"]
    PRINCIPLE["Start from how designers ask questions,<br/>then shape ingestion around that"]

    subgraph Tools["MCP tools"]
        SEARCH["Search<br/>Primary palette · secondary palette · typography rules<br/>(not raw search chunks)"]
        CITE["Citations<br/>Deep links to Figma nodes"]
        COMP["Compliance analysis<br/>same-pipeline comparison + structured feedback"]
    end

    VIS["Visual layout mirrors brand-guideline documents<br/>Not generic chatbot prose"]

    IFACE --> SEARCH
    IFACE --> COMP
    IFACE --- PRINCIPLE
    SEARCH --> CITE
    COMP --> VIS
    SEARCH --> VIS

    class IFACE,PRINCIPLE insight
    class SEARCH,COMP highlight
    class CITE contract
    class VIS ok

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412
10

Generation track — Q&A and brief mode

This section separates brand Q&A from generation brief assembly. ComfyUI was useful for validating the bonus use case, but the final generation backend did not need to be locked behind MCP.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
sequenceDiagram
    participant Designer
    participant Claude as Claude Desktop
    participant MCP as MCP Server
    participant Chroma as ChromaDB / retrieval
    participant Comfy as ComfyUI (local)

    Note over Designer,Comfy: Mode A — Q&A
    Designer->>Claude: "What are our payments brand colors?"
    Claude->>MCP: search + cite
    MCP->>Chroma: retrieve structured guidance
    Chroma-->>MCP: palette + metadata
    MCP-->>Claude: templated answer + Figma link
    Claude-->>Designer: structured response

    Note over Designer,Comfy: Mode B — Brief (manual final step)
    Designer->>Claude: "Banner concept using payments guidance"
    Claude->>MCP: retrieve brand rules
    MCP-->>Claude: assembled generation prompt
    Note right of Claude: I ran prompt through ComfyUI
    Claude->>Comfy: (out of band) validate feasibility
    Comfy-->>Designer: ~on-brand image, specific misses

    Note over MCP,Comfy: Scoped out: 3rd MCP tool for end-to-end generation
11

Evaluation — three tracks, one root cause

This section summarizes the three evaluation tracks. They pointed to the same conclusion: the pipeline worked, but some of the brand knowledge only lived in designers' heads.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart TB
    subgraph T1["Track 1 · Knowledge retrieval"]
        T1M["Regression suite from Figma ground truth<br/>Primary/secondary palette, radii, typography"]
        T1X["Cross-brand generalization<br/>Tune on one kit, query untuned kits"]
        T1R["Passed — pipeline correct"]
    end

    subgraph T2["Track 2 · Compliance review"]
        T2M["Qualitative testing with brand team<br/>Real submissions, no labeled test set"]
        T2R["Directionally working<br/>Obvious violations caught; edge-case long tail"]
    end

    subgraph T3["Track 3 · Image generation"]
        T3M["Live demo co-investigation"]
        T3R["~on-brand but specific misses each time<br/>Trace → guidance missing more often than retrieval was wrong"]
    end

    subgraph Finding["What the tests showed"]
        F["Brand = examples + tacit designer consensus<br/>Not fully documented rules"]
        D["MCP server as demo and diagnosis tool<br/>Showed gaps collaboratively in demos"]
    end

    subgraph Next["What this pointed to next"]
        N["Turn tacit knowledge into written rules<br/>(→ Frontify migration)"]
    end

    T1M --> T1R
    T1X --> T1R
    T2M --> T2R
    T3M --> T3R
    T2R --> F
    T3R --> F
    T1R -.->|"retrieval OK; rules incomplete"| F
    F --> D
    F --> N

    class T1R ok
    class T2R,T3R warn
    class F insight
    class D highlight
    class N contract

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412
12

Mastra migration — when a framework helped

This section covers the move from flat MCP handlers to Mastra workflows. Once the fetch, walk, chunk, retrieve, and format flow repeated across tools, the extra structure became worth it.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
stateDiagram-v2
    [*] --> Phase1: MCP tools in flux

    state Phase1 {
        [*] --> FlatHandlers
        FlatHandlers: Anthropic TS MCP library
        FlatHandlers: Flat tool handlers, fast iteration
    }

    Phase1 --> Decision: Tool surface became clearer

    state Decision {
        [*] --> CostCheck
        CostCheck: Duplicated fetch/walk/chunk/retrieve/format
        CostCheck: Ad-hoc orchestration, harder testing
    }

    Decision --> Phase2: Workflow complexity now worth the framework

    state Phase2 {
        [*] --> MastraHost
        MastraHost: Mastra workflows host orchestration
        MastraHost: MCP server = stable external interface
    }

    Phase2 --> [*]
13

Engagement timeline

This section places the work on a six- to eight-week calendar, connecting discovery, experiments, architecture buildout, evaluation demos, and handoff.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart LR
    subgraph Calendar["~6–8 weeks calendar · ~2–3 weeks active engineering"]
        direction LR
        D1["Discovery sessions"]
        D2["Early generation experiments<br/>(2 things we ruled out)"]
        D3["Figma export attempts<br/>+ chunking v1 → v2"]
        D4["MCP server v1"]
        D5["Mastra migration + ComfyUI track"]
        D6["Evaluation & demos"]
        D7["Handoff: reference implementation"]
    end

    D1 --> D2 --> D3 --> D4 --> D5 --> D6 --> D7

    class D1 muted
    class D2 fail
    class D3,D4 highlight
    class D5 insight
    class D6 warn
    class D7 ok

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412

    linkStyle 0,1,2,3,4,5 stroke:#6366f1,stroke-width:2px
14

Brand kit progression

This section shows how scope expanded from one brand kit to three and then five, proving generalization without trying to hard-code all seventy-five kits.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart LR
    subgraph Brands["Brand kit scope"]
        B1["1 kit<br/>Deep pipeline development"]
        B2["3 kits<br/>Generalization testing"]
        B3["5 kits<br/>Handoff baseline"]
        B4["75 kits total<br/>Architecture shown generalizable"]
    end

    B1 --> B2 --> B3 --> B4

    class B1 highlight
    class B2 insight
    class B3 contract
    class B4 ok

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412

    linkStyle 0,1,2 stroke:#6366f1,stroke-width:2px
15

Outcomes

This section connects the prototype to client outcomes: the Frontify direction, a clearer Adobe strategy, a reproducible reference implementation, and a sharper diagnosis of the real brand bottleneck.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart TB
    ENG["Feasibility engagement"]

    ENG --> O1["Outcome 1: Frontify selected<br/>Turn tacit rules into written brand rules"]
    ENG --> O2["Outcome 2: Adobe complementarity<br/>Vendor generation + owned MCP retrieval/compliance"]
    ENG --> O3["Outcome 3: Follow-on trust signal<br/>Client confidence in the direction"]

    ENG --> DEL["Deliverable: Reference implementation<br/>Repo · findings · how to run it<br/>Chroma · MCP+Mastra · ComfyUI workflow"]

    FIND["Diagnostic finding"] --> O1
    FIND2["Pipeline correct; rules incomplete"] --> O1

    class DEL contract
    class O1 highlight
    class O2,O3 muted
    class FIND,FIND2 insight

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412
16

Layered lesson — keep the interface stable

This section distills the architecture lesson: keep the interface stable, because retrieval, workflows, generation models, and prompts will keep changing behind it.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart TB
    subgraph Layers["Stable interface / changing implementation at every layer"]
        L1["MCP server ↔ Mastra workflows"]
        L2["Brand knowledge interface ↔ generation backend"]
        L3["Compliance feedback format ↔ system prompt"]
        L4["Tool response shape ↔ ingestion + chunking"]
    end

    LESSON["Whatever sits behind the interface will change<br/>Human craft · retrieval · agent framework · diffusion model<br/>The interface is what needs to last"]

    L1 --> LESSON
    L2 --> LESSON
    L3 --> LESSON
    L4 --> LESSON

    class L1,L2,L3,L4 highlight
    class LESSON contract

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412
17

Personal contribution — what I built

This section makes technical ownership explicit: the custom Figma SDK, document-tree walker, chunking algorithm, metadata extraction, MCP tools, evaluation, and handoff materials.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart TB
    ME["My direct contribution<br/>technical lead who personally built the prototype"]

    subgraph Built["Code / systems I personally wrote"]
        SDK["Minimal Figma SDK<br/>file fetch, traversal, node search, enums"]
        WALKER["Document-tree walker + semantic grouping<br/>preserve structure and metadata"]
        CHUNKER["Recursive chunking pipeline<br/>raw tree + derived metadata"]
        MCP["Custom MCP server<br/>search, citations, compliance analysis"]
        EVAL["Retrieval regression suite<br/>known-answer queries + cross-brand tests"]
        HANDOFF["Reference implementation<br/>repo, findings, how to run it"]
    end

    subgraph Integrated["Systems I integrated"]
        FIGMA["Figma org API"]
        CHROMA["ChromaDB"]
        MASTRA["Mastra workflows"]
        COMFY["ComfyUI validation track"]
    end

    ME --> SDK --> WALKER --> CHUNKER --> MCP --> EVAL --> HANDOFF
    WALKER --> FIGMA
    CHUNKER --> CHROMA
    MCP --> MASTRA
    MCP -.->|"generation prompt path"| COMFY

    class ME insight
    class SDK,WALKER,CHUNKER,MCP,EVAL,HANDOFF contract
    class FIGMA,CHROMA,MASTRA,COMFY datastore

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412
18

Cross-functional influence — moving the conversation

This section maps how the prototype helped align brand, program, engineering, and vendor-strategy stakeholders by shifting the conversation from model choice to which rules were actually written down.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart TB
    AMBIG["Ambiguous mandate<br/>find meaningful AI uses for brand"]

    subgraph Stakeholders["People / groups I worked with"]
        BRAND["Head of Brand + brand designers<br/>source of craft knowledge"]
        PM["Program manager<br/>scope, cadence, demos"]
        ENG["JPMC engineering<br/>future production owner"]
        STRAT["Adobe / vendor strategy<br/>avoid blocking owned workflows"]
    end

    subgraph Moves["Leadership moves"]
        LISTEN["Discovery sessions<br/>understand bottlenecks and constraints"]
        PROVE["Working instrument<br/>let demos expose real gaps"]
        REFRAME["Reframe disagreement<br/>from 'which model?' to 'which rules are written down?'"]
        HANDOFF["Reference implementation<br/>make the path reproducible for teams not in the room"]
    end

    subgraph Shift["Outcome of influence"]
        FRONTIFY["Brand-management migration<br/>write down tacit rules"]
        ADOBE["Adobe complementarity<br/>vendor generation + owned MCP retrieval"]
        TRUST["Trust transferred to source of truth<br/>Figma citations + auditability"]
    end

    AMBIG --> BRAND
    AMBIG --> PM
    AMBIG --> ENG
    AMBIG --> STRAT

    BRAND --> LISTEN --> PROVE --> REFRAME
    PM --> PROVE
    ENG --> HANDOFF
    STRAT --> ADOBE
    REFRAME --> FRONTIFY
    PROVE --> TRUST
    HANDOFF --> TRUST

    class AMBIG insight
    class LISTEN,PROVE,REFRAME,HANDOFF highlight
    class FRONTIFY,ADOBE,TRUST contract
    class BRAND,PM,ENG,STRAT muted

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412
19

MCP tradeoffs — what belongs in the contract

This section clarifies MCP's role: it is a strong tool contract for portability, structure, and citations, but orchestration, lifecycle concerns, and generation backends still need separate design decisions.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': '"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif', 'fontSize': '15px', 'primaryColor': '#eef2ff', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#4338ca', 'secondaryColor': '#f8fafc', 'secondaryTextColor': '#334155', 'secondaryBorderColor': '#94a3b8', 'tertiaryColor': '#ffffff', 'tertiaryTextColor': '#1e293b', 'tertiaryBorderColor': '#cbd5e1', 'lineColor': '#64748b', 'textColor': '#0f172a', 'mainBkg': '#ffffff', 'nodeBorder': '#6366f1', 'clusterBkg': '#f8fafc', 'clusterBorder': '#cbd5e1', 'titleColor': '#0f172a', 'edgeLabelBackground': '#ffffff', 'nodeTextColor': '#1e293b', 'actorBkg': '#eef2ff', 'actorBorder': '#4338ca', 'actorTextColor': '#0f172a', 'signalColor': '#64748b', 'labelBoxBkgColor': '#eef2ff', 'labelBoxBorderColor': '#4338ca', 'labelTextColor': '#0f172a', 'loopTextColor': '#475569', 'noteBkgColor': '#fffbeb', 'noteBorderColor': '#d97706', 'noteTextColor': '#78350f' }, 'flowchart': { 'htmlLabels': true, 'curve': 'basis', 'padding': 18, 'nodeSpacing': 55, 'rankSpacing': 65, 'diagramPadding': 24, 'useMaxWidth': true }, 'sequence': { 'actorMargin': 60, 'boxMargin': 12, 'messageMargin': 40, 'mirrorActors': false, 'useMaxWidth': true }, 'state': { 'useMaxWidth': true }}}%%
flowchart LR
    Q["Build decision<br/>What belongs in the MCP contract?"]

    subgraph MCPGood["MCP handles well"]
        TOOLS["Tool boundary<br/>search, cite, analyze"]
        HOSTS["Host portability<br/>Claude Desktop now, other MCP hosts later"]
        TRACE["Traceability<br/>structured outputs + Figma citations"]
    end

    subgraph MCPLimits["MCP does not solve"]
        ORCH["Complex orchestration<br/>needs workflow layer"]
        STATE["Production state / eval / auth lifecycle<br/>still app concerns"]
        GEN["Image generation backend choice<br/>should remain swappable"]
    end

    subgraph Decisions["Resulting architecture decisions"]
        MASTRA["Use Mastra behind MCP<br/>after tool flows stabilized"]
        NO_GEN_TOOL["Keep ComfyUI outside MCP<br/>avoid freezing backend choice"]
        CONTRACT["Treat MCP as contract<br/>not the whole application"]
    end

    Q --> TOOLS
    Q --> HOSTS
    Q --> TRACE
    Q --> ORCH
    Q --> STATE
    Q --> GEN

    ORCH --> MASTRA
    GEN --> NO_GEN_TOOL
    TOOLS --> CONTRACT
    HOSTS --> CONTRACT
    TRACE --> CONTRACT

    class Q insight
    class TOOLS,HOSTS,TRACE ok
    class ORCH,STATE,GEN warn
    class MASTRA,NO_GEN_TOOL,CONTRACT contract

    classDef fail fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b
    classDef warn fill:#fffbeb,stroke:#d97706,stroke-width:2px,color:#92400e
    classDef ok fill:#ecfdf5,stroke:#059669,stroke-width:2px,color:#065f46
    classDef highlight fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af
    classDef contract fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#166534
    classDef insight fill:#faf5ff,stroke:#9333ea,stroke-width:2px,color:#6b21a8
    classDef datastore fill:#f5f3ff,stroke:#7c3aed,stroke-width:2px,color:#5b21b6
    classDef muted fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    classDef decision fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412