Skip to main content
Glama
sksachan

Dealer Fusion MCP Server

by sksachan
README.md
# Dealer Fusion Workspace

Intelligence layer for an automotive dealership network.  
Reads CRM, DMS, CDP, and Adobe Analytics data; responds to and qualifies customers; writes back to CRM; emits PII-free OEM signals.

## Architecture

```
Dealer_Fusion_Workspace/
  dealer_fusion_mock_data_stub_v1/   — 31 JSONL data files + 11 JSON schemas
  dealer_fusion_core/                — shared DuckDB loader + privacy helper
  dealer_fusion_mcp/                 — FastMCP server  (port 4010, Bearer auth)
  dealer_fusion_explorer/
    backend/                         — FastAPI CRUD + graph API  (port 8020)
    frontend/                        — React + Vite + TypeScript  (port 5200)
  start_explorer.sh                  — stable backend start script
```

## Prerequisites

- Python 3.11+
- Node.js 18+
- npm 9+

## Quick start

```bash
# 1 — Install Python dependencies
pip install -e dealer_fusion_core/
pip install -r requirements.txt

# 2 — Terminal 1: MCP server
cd /path/to/Dealer_Fusion_Workspace
python3 -m dealer_fusion_mcp.server

# 3 — Terminal 2: Explorer backend  (use the script — limits file-watching to src dirs only)
./start_explorer.sh

# 4 — Terminal 3: Explorer frontend
cd dealer_fusion_explorer/frontend
npm install
npm run dev -- --port 5200
```

Open the Explorer UI at **http://localhost:5200**

## Services

| Service | Port | Start command |
|---|---|---|
| MCP Server | 4010 | `python3 -m dealer_fusion_mcp.server` |
| Explorer Backend | 8020 | `./start_explorer.sh` |
| Explorer Frontend | 5200 | `cd dealer_fusion_explorer/frontend && npm run dev -- --port 5200` |

## Environment variables

| Variable | Default | Description |
|---|---|---|
| `DEALER_FUSION_MCP_PORT` | `4010` | MCP server port |
| `DEALER_FUSION_MCP_TOKEN` | `dev-token` | Bearer token for all MCP requests |
| `DEALER_FUSION_DATA_DIR` | auto-resolved | Override path to `data/jsonl/` |
| `DEALER_FUSION_SCHEMAS_DIR` | auto-resolved | Override path to `schemas/` |
| `EXPLORER_API_PORT` | `8020` | Explorer backend port |

## MCP server (14 tools)

Authentication: `Authorization: Bearer dev-token`  
Protocol: MCP streamable HTTP / SSE — `POST http://localhost:4010/mcp`

### Lead & CRM
| Tool | Required args | Returns |
|---|---|---|
| `list_leads` | `limit?` | `{items, total_count}` — paginated lead list |
| `get_lead` | `lead_id` | `{lead, contact, latest_decision}` |
| `search_leads` | `query` | `{items}` — full-text match across lead fields |
| `get_customer_360` | `customer_key` | 11-section view: customer, CRM, DMS, CDP, identity graph, segments, leads, activities, appointments, deals, service history |

### Inventory & DMS
| Tool | Required args | Returns |
|---|---|---|
| `search_inventory` | `model?`, `fuel_type?`, `price_max?`, `dealer_id?`, `in_stock_only?` | `{items}` — filtered vehicle list |
| `get_dealer_inventory` | `dealer_id` | `{grouped}` — vehicles keyed by inventory status |
| `get_deal` | `deal_id` | `{deal, finance_contract, trade_in, repair_orders}` |
| `get_service_history` | `customer_key` | `{service_appointments, repair_orders}` |

### Analytics & CDP
| Tool | Required args | Returns |
|---|---|---|
| `get_customer_journey` | `customer_key` | `{events}` — merged chronological timeline (XDM + CRM + Dealer Fusion decisions) |
| `get_segment_members` | `segment_id` | `{items}` — CDP profiles in that segment |
| `get_network_kpis` | `region?`, `brand?`, `model?`, `date_from?`, `date_to?` | `{items}` — OEM KPI rows (privacy-gated, PII-free) |

### Dealer Ops
| Tool | Required args | Returns |
|---|---|---|
| `get_dealer_inbox` | `dealer_id`, `limit?` | `{items}` — leads sorted: handover-required → temperature → score |
| `get_dealer_staff` | `dealer_id` | `{items}` — staff roster with roles |
| `simulate_crm_writeback` | `lead_id`, `decision_type` | `{payload}` — CRM upsert payload (no mutation) |

`decision_type` must be one of: `acknowledge_and_escalate` · `acknowledge_and_nurture` · `suppress_marketing_or_privacy_only` · `merge_duplicate_then_update_owner`

## Explorer API (`http://localhost:8020`)

```
GET  /api/entities                              — all 31 entity types with record counts
GET  /api/{entity}/list?page=&limit=&search=    — paginated, searchable table
GET  /api/{entity}/{id}                         — single record
POST /api/{entity}                              — create record
PUT  /api/{entity}/{id}                         — update record
DELETE /api/{entity}/{id}                       — soft-delete (sets deleted_at)
GET  /api/customers/{customer_key}/golden-record — force-graph payload for Golden Record view
GET  /api/search?q=                             — cross-entity full-text search
GET  /api/schema                                — all 31 tables with columns, row counts, and FK relationships
GET  /health                                    — health check
```

## Explorer UI views

| Tab | Description |
|---|---|
| **Entity Browser** | Browse, search, edit, and soft-delete records across all 31 tables |
| **Golden Record** | Search by name / email / CUST_XXXXX ID → interactive force-graph of linked entities |
| **Dealer Inbox** | Live lead triage view sorted by urgency: handover → temperature → score |
| **KPI Dashboard** | OEM network KPIs with dealer filter and trend charts |
| **Schema** | ERD-style force-graph of all 31 tables with FK edges, domain colour-coding, and column explorer |

## Data model

31 tables across 8 domains — all joined on `customer_key`.

| Domain | Tables |
|---|---|
| Core | `customers`, `households`, `dealers`, `staff`, `vehicles_inventory`, `inventory_price_changes` |
| CRM | `crm_leads`, `crm_contacts`, `crm_activities`, `crm_opportunities`, `crm_appointments`, `crm_tasks` |
| DMS | `dms_customers`, `dms_deals`, `dms_finance_contracts`, `dms_repair_orders`, `dms_service_appointments`, `dms_trade_ins` |
| CDP | `cdp_profiles`, `cdp_segment_memberships`, `cdp_identity_graph` |
| Adobe | `adobe_xdm_events`, `adobe_analytics_hits` |
| Dealer Fusion | `dealer_fusion_decisions` |
| Reference | `journey_stage_reference`, `campaign_reference`, `segment_reference`, `vehicle_reference`, `scenario_reference`, `scenario_coverage_matrix` |
| OEM | `oem_network_kpi_daily` |

Key joins: `customers.customer_key` → CRM, DMS, CDP, Adobe, and Dealer Fusion tables. See `dealer_fusion_mock_data_stub_v1/DATA_DICTIONARY.md` for the full relationship map.

## Tests

```bash
# Python — MCP server + Explorer backend
python3 -m pytest dealer_fusion_mcp/tests/ dealer_fusion_explorer/backend/tests/ -v

# Frontend — Vitest
cd dealer_fusion_explorer/frontend && npx vitest run
```

## MCP smoke test

```bash
# Quick connectivity check using the MCP JSON-RPC protocol
python3 - << 'EOF'
import requests, json
r = requests.post("http://localhost:4010/mcp",
    headers={"Authorization": "Bearer dev-token",
             "Content-Type": "application/json",
             "Accept": "application/json, text/event-stream"},
    json={"jsonrpc":"2.0","id":1,"method":"initialize","params":{
        "protocolVersion":"2024-11-05","capabilities":{},
        "clientInfo":{"name":"test","version":"1"}}},
    stream=True, timeout=10)
sid = r.headers.get("mcp-session-id")
for line in r.iter_lines():
    line = line.decode() if isinstance(line, bytes) else line
    if line.startswith("data:"):
        d = json.loads(line[5:])
        print("Server:", d["result"]["serverInfo"])
        print("Session:", sid)
        break
EOF
```

## PS brand design tokens (Explorer UI)

```css
--ps-bg-primary:     #0A0B0D
--ps-bg-surface:     #141518
--ps-bg-elevated:    #1E2025
--ps-text-primary:   #FFFFFF
--ps-text-secondary: #9CA3AF
--ps-accent:         #E63312
--ps-border:         rgba(255,255,255,0.10)
```