Go-High-Level-MCP-2026-Comp.../REACT-REWRITE-PLAN.md
Jake Shore 4f2a8d6ab5 GHL MCP full update — 2026-02-06
=== DONE ===
- MCP Apps UI system added (11 apps with _meta.ui.resourceUri)
- 19 new tool modules added
- Tool count: 269 → 461 across 38 categories
- Upstream changes merged
- All tools tagged with _meta labels
- Package lock updated

=== TO-DO ===
- [ ] Fix 42 failing edge case tests (BLOCKER — Stage 11)
- [ ] Live API testing with GHL credentials
- [ ] App design approval for Stage 7→8
2026-02-06 06:27:05 -05:00

14 KiB

MCP UI Kit — React Rewrite Plan

Vision

Build a generic, reusable MCP UI component library using React + ext-apps SDK. Any MCP server (GHL, HubSpot, Salesforce, etc.) can use this component kit to render AI-generated interactive UIs. GHL is the first implementation. The library is CRM-agnostic — interactive components accept tool names as props so each server configures its own tool mappings.


Architecture

┌─────────────────────────────────────────────────────────┐
│ Goose / Claude Desktop (MCP Host)                       │
│                                                          │
│   tools/call → GHL MCP Server → GHL API                │
│        ↑           ↓                                     │
│   tools/call   structuredContent (JSON UI tree)         │
│        ↑           ↓                                     │
│   ┌─────────────────────────────────────────────┐       │
│   │  React App (iframe via ext-apps SDK)         │       │
│   │                                              │       │
│   │  useApp() hook ← ontoolresult (UI tree)     │       │
│   │       ↓                                      │       │
│   │  MCPAppProvider (React Context)              │       │
│   │    - uiTree state                            │       │
│   │    - formState (inputs, selections)          │       │
│   │    - callTool(name, args) → MCP server      │       │
│   │       ↓                                      │       │
│   │  <UITreeRenderer tree={uiTree} />            │       │
│   │    - Looks up component by type              │       │
│   │    - Renders React component with props      │       │
│   │    - Recursively renders children            │       │
│   │       ↓                                      │       │
│   │  42 Display Components (pure, CRM-agnostic)  │       │
│   │  + 8 Interactive Components (tool-configurable)│     │
│   │    - ContactPicker(searchTool="search_contacts")│    │
│   │    - InvoiceBuilder(createTool="create_invoice")│    │
│   │    - KanbanBoard(onMoveTool="update_opportunity")│   │
│   │    - EditableField(saveTool=props.saveTool)  │       │
│   └─────────────────────────────────────────────┘       │
└─────────────────────────────────────────────────────────┘

File Structure (New)

src/ui/react-app/                  # GENERIC MCP UI KIT (no GHL references)
├── package.json                   # React + ext-apps SDK deps
├── vite.config.ts                 # Vite + singlefile + React
├── tsconfig.json
├── index.html                     # Entry point
├── src/
│   ├── App.tsx                    # Root — useApp hook, MCPAppProvider
│   ├── types.ts                   # UITree, UIElement, component prop interfaces
│   ├── context/
│   │   └── MCPAppContext.tsx      # React Context — uiTree, formState, callTool
│   ├── hooks/
│   │   ├── useCallTool.ts        # Hook wrapping app.callServerTool
│   │   ├── useFormState.ts       # Shared form state management
│   │   └── useSizeReporter.ts    # Auto-report content size to host
│   ├── renderer/
│   │   ├── UITreeRenderer.tsx    # Recursive tree → React component resolver
│   │   └── registry.ts           # Component name → React component map
│   ├── components/
│   │   ├── layout/               # PageHeader, Card, SplitLayout, Section, StatsGrid
│   │   ├── data/                 # DataTable, KanbanBoard, MetricCard, StatusBadge,
│   │   │                         # Timeline, ProgressBar, KeyValueList, etc.
│   │   ├── charts/               # BarChart, LineChart, PieChart, FunnelChart, Sparkline
│   │   ├── comms/                # ChatThread, EmailPreview, TranscriptView, etc.
│   │   ├── viz/                  # CalendarView, FlowDiagram, TreeView, MediaGallery, etc.
│   │   ├── interactive/          # ContactPicker, InvoiceBuilder, EditableField, etc.
│   │   │                         # All accept tool names as PROPS (CRM-agnostic)
│   │   └── shared/               # ActionButton, Toast, Modal (React portals)
│   └── styles/
│       ├── base.css              # Reset, variables, typography
│       ├── components.css        # Component-specific styles (compact for chat)
│       └── interactive.css       # Drag/drop, modals, toasts, form styles

CRM-Agnostic Design Principle

  • NO component imports GHL types or references GHL tool names
  • Interactive components receive tool names via props:
    • ContactPickersearchTool="search_contacts" (GHL) or "hubspot_search_contacts" (HubSpot)
    • KanbanBoardmoveTool="update_opportunity" (GHL) or "move_deal" (Pipedrive)
    • InvoiceBuildercreateTool="create_invoice" (any billing system)
  • The MCP server's AI prompt tells Claude which tool names to use in the UI tree
  • Components call callTool(props.toolName, args) — they don't know or care what CRM is behind it

Component Inventory

Existing 42 (string → React conversion)

Layout (5): PageHeader, Card, StatsGrid, SplitLayout, Section Data Display (10): DataTable, KanbanBoard, MetricCard, StatusBadge, Timeline, ProgressBar, DetailHeader, KeyValueList, LineItemsTable, InfoBlock Navigation (3): SearchBar, FilterChips, TabGroup Actions (2): ActionButton, ActionBar Extended Data (6): CurrencyDisplay, TagList, CardGrid, AvatarGroup, StarRating, StockIndicator Communications (6): ChatThread, EmailPreview, ContentPreview, TranscriptView, AudioPlayer, ChecklistView Visualization (5): CalendarView, FlowDiagram, TreeView, MediaGallery, DuplicateCompare Charts (5): BarChart, LineChart, PieChart, FunnelChart, SparklineChart

New Interactive Components (8)

Component Purpose MCP Tools Used
ContactPicker Searchable dropdown, fetches contacts on type search_contacts
InvoiceBuilder Line items, totals, contact auto-fill create_invoice, get_contact
OpportunityEditor Inline edit deal name/value/status/stage update_opportunity
AppointmentBooker Calendar slot picker + booking form get_calendar, create_appointment
EditableField Click-to-edit any text/number field varies (generic)
SelectDropdown Generic select with async option loading varies
FormGroup Group of form fields with validation varies
AmountInput Currency-formatted number input — (local state)

Agent Team Plan

Phase 1: Foundation (Sequential — 1 agent)

Agent Alpha — Project Scaffold + App Shell

  • Create src/ui/react-app/ with package.json, vite.config, tsconfig
  • Install deps: react, react-dom, @modelcontextprotocol/ext-apps, @vitejs/plugin-react, vite-plugin-singlefile
  • Build App.tsx with useApp hook — handles ontoolresult, ontoolinput, host context
  • Build GHLContext.tsx — React context providing uiTree, formState, callTool
  • Build useCallTool.ts — wrapper around app.callServerTool with loading/error states
  • Build useFormState.ts — shared form state hook
  • Build useSizeReporter.ts — auto-measures content, sends ui/notifications/size-changed
  • Build UITreeRenderer.tsx — recursive renderer that resolves component types from registry
  • Build registry.ts — component map (stubs for now, filled by other agents)
  • Build types.ts — UITree, UIElement, all component prop interfaces
  • Build base CSS (base.css) — reset, variables, compact typography
  • Update outer build pipeline in GoHighLevel-MCP package.json to build React app
  • Output: Working scaffold that renders a loading state, connects to host via ext-apps

Phase 2: Components (Parallel — 4 agents)

Agent Bravo — Layout + Core Data Components (15) Files: components/layout/, components/data/ (first half)

  • PageHeader, Card, StatsGrid, SplitLayout, Section
  • DataTable (with clickable rows, sortable columns)
  • KanbanBoard (with FULL drag-and-drop via React state — no DOM hacking)
  • MetricCard, StatusBadge, Timeline
  • Register all in registry.ts
  • Component CSS in components.css

Agent Charlie — Data Display + Navigation + Actions (15) Files: components/data/ (second half), components/shared/

  • ProgressBar, DetailHeader, KeyValueList, LineItemsTable, InfoBlock
  • SearchBar, FilterChips, TabGroup
  • ActionButton, ActionBar
  • CurrencyDisplay, TagList, CardGrid, AvatarGroup, StarRating, StockIndicator
  • Register all in registry.ts

Agent Delta — Comms + Viz + Charts (16) Files: components/comms/, components/viz/, components/charts/

  • ChatThread, EmailPreview, ContentPreview, TranscriptView, AudioPlayer, ChecklistView
  • CalendarView, FlowDiagram, TreeView, MediaGallery, DuplicateCompare
  • BarChart, LineChart, PieChart, FunnelChart, SparklineChart
  • All chart components use inline SVG (same approach, just JSX)
  • Register all in registry.ts

Agent Echo — Interactive Components + Forms (8) Files: components/interactive/, hooks/

  • ContactPicker — searchable dropdown, calls search_contacts on keystroke with debounce
  • InvoiceBuilder — line items table + contact selection + auto-total
  • OpportunityEditor — inline edit form for deal fields, saves via update_opportunity
  • AppointmentBooker — date/time picker + contact + calendar selection
  • EditableField — click-to-edit wrapper for any field
  • SelectDropdown — generic async select
  • FormGroup — form layout with labels + validation
  • AmountInput — formatted currency input
  • Shared: Toast component, Modal component (proper React portals)
  • Integrate with GHLContext for tool calling

Phase 3: Integration (Sequential — 1 agent)

Agent Foxtrot — Wire Everything Together

  • Merge all component registrations into registry.ts
  • Update src/apps/index.ts:
    • Add new tool definitions for interactive components (create_invoice, create_appointment)
    • Update resource handler for ui://ghl/dynamic-view to serve React build
    • Add new resource URIs if needed
  • Update src/server.ts if new tools need routing
  • Update system prompt: add new interactive component catalog entries
  • Update Goose config available_tools if needed
  • Full build: React app → singlefile HTML → server TypeScript
  • Test: verify JSON UI trees render correctly, interactive components call tools, drag-and-drop works
  • Write brief README for the new architecture

Key Technical Decisions

State Management

  • React Context (not Redux) — app is small enough, context + useReducer is perfect
  • GHLContext holds: current UITree, form values, loading states, selected entities
  • Any component can const { callTool } = useGHL() to interact with the MCP server

Tool Calling Pattern

// Any component can call MCP tools:
const { callTool, isLoading } = useCallTool();

const handleDrop = async (cardId: string, newStageId: string) => {
  await callTool('update_opportunity', {
    opportunityId: cardId,
    pipelineStageId: newStageId,
  });
};

Drag & Drop (KanbanBoard)

  • Pure React state — no global DOM event handlers
  • onDragStart, onDragOver, onDrop on React elements
  • Optimistic UI update (move card immediately, revert on error)

Dynamic Sizing

  • useSizeReporter hook — ResizeObserver on #app
  • Sends ui/notifications/size-changed on every size change
  • Caps at 600px height

CSS Strategy

  • Plain CSS files (not CSS modules, not Tailwind) — keeps bundle simple
  • Same compact sizing as current (12px base, tight padding)
  • All in styles/ directory, imported in App.tsx
  • Interactive styles (drag states, modals, toasts) in separate file

Build Pipeline

# In src/ui/react-app/
npm run build
# → Vite builds React app → vite-plugin-singlefile → single HTML file
# → Output: ../../dist/app-ui/dynamic-view.html

# In GoHighLevel-MCP root
npm run build
# → Builds React UI first, then compiles TypeScript server

Timeline Estimate

Phase Agents Est. Time Depends On
Phase 1: Foundation Alpha (1) ~20 min
Phase 2: Components Bravo, Charlie, Delta, Echo (4 parallel) ~25 min Phase 1
Phase 3: Integration Foxtrot (1) ~15 min Phase 2
Total 6 agents ~60 min

Success Criteria

  1. All 42 existing components render identically to current version
  2. JSON UI trees from Claude work without any format changes
  3. KanbanBoard drag-and-drop moves deals and persists via update_opportunity
  4. ContactPicker fetches real contacts from GHL on keystroke
  5. InvoiceBuilder creates invoices with real contact data
  6. EditableField saves changes via appropriate MCP tool
  7. Dynamic sizing works — views fit in chat
  8. Single HTML file output (vite-plugin-singlefile)
  9. ext-apps handshake completes with Goose
  10. All existing view_* tools still work alongside generate_ghl_view