Show raw JSON evidence
{
"checks": {
"action_safety_probe": {
"details": {
"auth_present": false,
"confirmation_signals": [],
"safeguard_count": 0,
"summary": {
"bulk_access_tools": 0,
"capability_distribution": {
"admin": 7,
"exec": 5,
"network": 4,
"other": 3,
"read": 8,
"write": 4
},
"destructive_tools": 0,
"egress_tools": 2,
"exec_tools": 5,
"high_risk_tools": 3,
"risk_distribution": {
"critical": 0,
"high": 3,
"low": 3,
"medium": 5
},
"secret_tools": 0,
"tool_count": 11
}
},
"latency_ms": null,
"status": "error"
},
"advanced_capabilities_probe": {
"details": {
"capabilities": {
"completions": false,
"elicitation": false,
"prompts": false,
"resource_links": true,
"resources": true,
"roots": false,
"sampling": false,
"structured_outputs": false
},
"enabled": [
"resource_links",
"resources"
],
"enabled_count": 2,
"initialize_capability_keys": [
"resources",
"tools"
]
},
"latency_ms": null,
"status": "warning"
},
"connector_publishability_probe": {
"details": {
"blockers": [
"action_safety",
"server_card"
],
"criteria": {
"action_safety": false,
"auth_flow": true,
"connector_replay": true,
"initialize": true,
"protocol_version": true,
"remote_transport": true,
"request_association": true,
"server_card": false,
"session_resume": true,
"step_up_auth": true,
"tool_surface": true,
"tools_list": true,
"transport_compliance": true
},
"high_risk_tools": 3,
"tool_count": 11,
"transport": "streamable-http"
},
"latency_ms": null,
"status": "warning"
},
"connector_replay_probe": {
"details": {
"added_tools": [],
"additive_output_changes": [],
"backward_compatible": true,
"output_breaks": [],
"removed_tools": [],
"required_arg_breaks": [],
"would_break_after_refresh": false
},
"latency_ms": null,
"status": "ok"
},
"determinism_probe": {
"details": {
"attempts": 2,
"baseline_signature": "2e084fcb534998468a67ca6b89ae9127fbd01293285409f21d177a8def6d8414",
"errors": [],
"matches": 2,
"stable_ratio": 1.0,
"successful": 2
},
"latency_ms": 20.62,
"status": "ok"
},
"initialize": {
"details": {
"headers": {
"content-type": "application/json"
},
"http_status": 200,
"payload": {
"id": 1,
"jsonrpc": "2.0",
"result": {
"capabilities": {
"resources": {
"listChanged": true
},
"tools": {
"listChanged": true
}
},
"protocolVersion": "2025-03-26",
"serverInfo": {
"name": "La Luer Shopping",
"version": "0.3.0"
}
}
},
"url": "https://searchshopai-mcp.fly.dev/mcp/la-luer"
},
"latency_ms": 19.49,
"status": "ok"
},
"interactive_flow_probe": {
"details": {
"oauth_supported": false,
"prompt_available": false,
"risk_hits": [],
"safe_hits": []
},
"latency_ms": null,
"status": "missing"
},
"oauth_authorization_server": {
"details": {
"reason": "no_authorization_server"
},
"latency_ms": null,
"status": "missing"
},
"oauth_protected_resource": {
"details": {
"error": "Client error '404 Not Found' for url 'https://searchshopai-mcp.fly.dev/.well-known/oauth-protected-resource'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404",
"url": "https://searchshopai-mcp.fly.dev/.well-known/oauth-protected-resource"
},
"latency_ms": 23.12,
"status": "error"
},
"official_registry_probe": {
"details": {
"direct_match": true,
"official_peer_count": 1,
"registry_identifier": "ai.searchshop.www/la-luer",
"registry_source": "official_registry"
},
"latency_ms": null,
"status": "ok"
},
"openid_configuration": {
"details": {
"reason": "no_authorization_server"
},
"latency_ms": null,
"status": "missing"
},
"probe_noise_resilience": {
"details": {
"headers": {
"content-type": "text/plain"
},
"http_status": 200,
"url": "https://searchshopai-mcp.fly.dev/robots.txt"
},
"latency_ms": 8.59,
"status": "ok"
},
"prompt_get": {
"details": {
"reason": "not_advertised"
},
"latency_ms": null,
"status": "missing"
},
"prompts_list": {
"details": {
"headers": {
"content-type": "application/json"
},
"http_status": 200,
"payload": {
"error": {
"code": -32601,
"message": "Method not found"
},
"id": 3,
"jsonrpc": "2.0"
},
"reason": "not_supported",
"url": "https://searchshopai-mcp.fly.dev/mcp/la-luer"
},
"latency_ms": 15.93,
"status": "missing"
},
"protocol_version_probe": {
"details": {
"claimed_version": "2025-03-26",
"lag_days": 244,
"latest_known_version": "2025-11-25",
"releases_behind": 2,
"validator_protocol_version": "2025-03-26"
},
"latency_ms": null,
"status": "warning"
},
"provenance_divergence_probe": {
"details": {
"direct_official_match": true,
"drift_fields": [],
"metadata_document_count": 1,
"registry_homepage": null,
"registry_repository": null,
"registry_title": null,
"registry_version": null,
"server_card_homepage": null,
"server_card_repository": null,
"server_card_title": null,
"server_card_version": null
},
"latency_ms": null,
"status": "ok"
},
"request_association_probe": {
"details": {
"reason": "no_request_association_capabilities_advertised"
},
"latency_ms": null,
"status": "missing"
},
"resource_read": {
"details": {
"headers": {
"content-type": "application/json"
},
"http_status": 200,
"payload": {
"id": 6,
"jsonrpc": "2.0",
"result": {
"contents": [
{
"_meta": {
"openai/widgetCSP": {
"connect_domains": [
"https://*.ngrok-free.dev",
"https://*.myshopify.com",
"https://cdn.shopify.com",
"https://esm.sh"
],
"redirect_domains": [
"https://*.myshopify.com",
"https://*.shopify.com"
],
"resource_domains": [
"https://esm.sh",
"https://cdn.shopify.com",
"https://*.shopify.com",
"https://*.youthtothepeople.com",
"https://*.laluer.com",
"https://*.glam-moda.com",
"https://incidecoder-content.storage.googleapis.com",
"https://media.kohlsimg.com",
"https://*.mercdn.net",
"https://*.bigcommerce.com",
"https://di2ponv0v5otw.cloudfront.net",
"https://placehold.co"
]
},
"ui": {
"csp": {
"connectDomains": [
"https://*.ngrok-free.dev",
"https://*.myshopify.com",
"https://cdn.shopify.com",
"https://esm.sh"
],
"redirectDomains": [
"https://*.myshopify.com",
"https://*.shopify.com"
],
"resourceDomains": [
"https://esm.sh",
"https://cdn.shopify.com",
"https://*.shopify.com",
"https://*.youthtothepeople.com",
"https://*.laluer.com",
"https://*.glam-moda.com",
"https://incidecoder-content.storage.googleapis.com",
"https://media.kohlsimg.com",
"https://*.mercdn.net",
"https://*.bigcommerce.com",
"https://di2ponv0v5otw.cloudfront.net",
"https://placehold.co"
]
},
"prefersBorder": true
}
},
"mimeType": "text/html;profile=mcp-app",
"text": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<meta name=\"color-scheme\" content=\"light dark\" />\n<title>La Luer</title>\n<style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n\n :root {\n --bg: #ffffff;\n --warm: #f5f1eb;\n --ink: #1a1a1a;\n --dark: #3a3632;\n --mid: #7a7470;\n --light: #b5afa5;\n --border: #e4dfd7;\n --gold: #c4a35a;\n --gold-soft: rgba(196,163,90,.12);\n --radius: 8px;\n --ease: cubic-bezier(0.22, 1, 0.36, 1);\n --foot-bg: #1a1a1a;\n }\n\n @media (prefers-color-scheme: dark) {\n :root {\n --bg: #1c1c1e;\n --warm: #2c2a27;\n --ink: #f0ece5;\n --dark: #d4cfc7;\n --mid: #9a958d;\n --light: #6a655d;\n --border: #3a3835;\n --gold: #d4b06a;\n --gold-soft: rgba(212,176,106,.15);\n --foot-bg: #0f0f0f;\n }\n }\n\n html, body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n font-size: 16px !important;\n line-height: 1.5 !important;\n background: var(--bg); color: var(--ink);\n -webkit-font-smoothing: antialiased;\n overflow-x: hidden;\n }\n\n /* \u2550\u2550\u2550 LOADING \u2550\u2550\u2550 */\n .ld{min-height:120px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px}\n .ld-dot{width:4px;height:4px;border-radius:50%;background:var(--gold);animation:pulse 1.4s ease infinite}\n @keyframes pulse{0%,100%{opacity:.15}50%{opacity:1}}\n .ld span{font-size:7px;letter-spacing:3px;text-transform:uppercase;color:var(--light)}\n\n @keyframes rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}\n .a{animation:rise .5s var(--ease) both}\n .a1{animation-delay:.05s}.a2{animation-delay:.12s}.a3{animation-delay:.2s}.a4{animation-delay:.28s}.a5{animation-delay:.36s}\n\n /* \u2550\u2550\u2550 BRAND HEADER \u2550\u2550\u2550 */\n .hdr { display:flex; align-items:center; gap:10px; padding:10px 14px; background:var(--warm); border-bottom:1px solid var(--border); }\n .hdr-logo { height:16px; opacity:.7; }\n @media (prefers-color-scheme: dark) { .hdr-logo { filter:brightness(0) invert(1); } }\n .hdr-text { flex:1; font-size:12px; color:var(--mid); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; text-align:right; }\n\n /* \u2550\u2550\u2550 RECOMMENDATION SUMMARY \u2550\u2550\u2550 */\n .summary { padding:12px 14px 10px; border-bottom:1px solid var(--border); }\n .summary-hint { font-size:13px; color:var(--dark); font-style:italic; line-height:1.5; }\n\n /* \u2550\u2550\u2550 HERO PRODUCT \u2550\u2550\u2550 */\n .hero-card { display:flex; gap:14px; padding:16px 14px; border-bottom:1px solid var(--border); background:var(--bg); }\n .hero-img { width:110px; height:110px; object-fit:cover; border-radius:var(--radius); background:var(--warm); flex-shrink:0; }\n .hero-info { flex:1; display:flex; flex-direction:column; justify-content:center; min-width:0; }\n .hero-badge { display:inline-block; align-self:flex-start; padding:2px 8px; margin-bottom:5px; background:var(--gold); color:#fff; font-size:8px; font-weight:700; text-transform:uppercase; letter-spacing:1.5px; border-radius:3px; }\n @media (prefers-color-scheme: dark) { .hero-badge { color:var(--bg); } }\n .hero-title { font-size:16px; font-weight:600; color:var(--ink); line-height:1.3; margin-bottom:3px; overflow:hidden; text-overflow:ellipsis; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; }\n .hero-desc { font-size:13px; color:var(--mid); line-height:1.4; margin-bottom:4px; overflow:hidden; text-overflow:ellipsis; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; }\n .hero-rating { font-size:12px; color:var(--light); margin-bottom:4px; }\n .hero-rating .stars { color:var(--gold); letter-spacing:1px; }\n .hero-price { font-size:17px; font-weight:600; color:var(--ink); margin-bottom:6px; }\n .hero-actions { display:flex; gap:6px; align-items:center; }\n .hero-forward { margin-top:8px; }\n .hero-forward-link { font-size:9px; color:var(--gold); cursor:pointer; background:none; border:none; text-decoration:underline; text-underline-offset:2px; font-weight:600; letter-spacing:.5px; }\n .hero-forward-link:hover { color:var(--ink); }\n .hero-for { font-size:10px; color:var(--gold); font-style:italic; margin-bottom:3px; }\n\n /* \u2550\u2550\u2550 COMPACT PRODUCT ROW \u2550\u2550\u2550 */\n .prod-row { display:flex; align-items:center; gap:10px; padding:10px 14px; border-bottom:1px solid var(--border); transition:background .2s; }\n .prod-row.in-cart { background:var(--gold-soft); }\n .prod-thumb { width:52px; height:52px; object-fit:cover; border-radius:6px; background:var(--warm); flex-shrink:0; }\n .prod-info { flex:1; min-width:0; }\n .prod-role { display:inline-block; padding:1px 6px; border:1px solid var(--border); border-radius:3px; font-size:8px; font-weight:600; color:var(--mid); text-transform:uppercase; letter-spacing:.8px; margin-bottom:3px; }\n .prod-name { font-size:14px; font-weight:500; color:var(--ink); line-height:1.3; margin-bottom:2px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }\n .prod-sub { font-size:12px; color:var(--light); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }\n .prod-right { flex-shrink:0; text-align:right; }\n .prod-price { font-size:15px; font-weight:600; color:var(--ink); margin-bottom:4px; }\n\n /* \u2550\u2550\u2550 BUTTONS \u2550\u2550\u2550 */\n .btn { padding:8px 16px; border:none; cursor:pointer; font-size:10px; font-weight:600; text-transform:uppercase; letter-spacing:1.5px; border-radius:4px; transition:opacity .2s; text-decoration:none; display:inline-block; line-height:1.3; }\n .btn:hover{opacity:.8}\n .btn-primary { background:var(--ink); color:var(--bg); }\n .btn-primary.added { background:var(--gold); color:var(--bg); }\n .btn-secondary { background:none; color:var(--mid); border:1px solid var(--border); padding:5px 12px; }\n .btn-sm { padding:8px 16px; font-size:10px; }\n\n /* \u2550\u2550\u2550 ROUTINE ACCORDION \u2550\u2550\u2550 */\n .routine-toggle { width:100%; display:flex; align-items:center; padding:10px 14px; background:none; border:none; border-bottom:1px solid var(--border); cursor:pointer; font-size:10px; font-weight:600; text-transform:uppercase; letter-spacing:1.5px; color:var(--dark); }\n .routine-toggle:hover { color:var(--ink); }\n .routine-arr { margin-left:auto; font-size:8px; transition:transform .3s var(--ease); }\n .routine-arr.open { transform:rotate(180deg); }\n .routine-body { overflow:hidden; max-height:0; opacity:0; transition:max-height .4s var(--ease), opacity .3s; }\n .routine-body.open { max-height:400px; opacity:1; }\n .routine-step { display:flex; align-items:flex-start; gap:8px; padding:8px 14px; }\n .routine-num { width:20px; height:20px; flex-shrink:0; display:flex; align-items:center; justify-content:center; border-radius:50%; background:var(--warm); font-size:10px; font-weight:600; color:var(--dark); }\n .routine-detail { flex:1; }\n .routine-role { font-size:10px; font-weight:600; color:var(--ink); text-transform:capitalize; }\n .routine-instr { font-size:10px; color:var(--mid); margin-top:1px; }\n\n /* \u2550\u2550\u2550 EDITORIAL NOTE \u2550\u2550\u2550 */\n .ed-note { padding:10px 14px; background:var(--warm); border-bottom:1px solid var(--border); }\n .ed-label { font-size:7px; font-weight:700; text-transform:uppercase; letter-spacing:2px; color:var(--gold); margin-bottom:4px; }\n .ed-text { font-size:13px; color:var(--dark); line-height:1.5; }\n\n /* \u2550\u2550\u2550 SAFETY & ALTS \u2550\u2550\u2550 */\n .safety { padding:0 14px; }\n .safety-btn { background:none; border:none; cursor:pointer; width:100%; display:flex; align-items:center; font-size:8px; font-weight:600; letter-spacing:1.5px; text-transform:uppercase; color:var(--light); padding:8px 0; }\n .safety-btn:hover { color:var(--dark); }\n .safety-arr { margin-left:auto; font-size:7px; transition:transform .3s var(--ease); }\n .safety-arr.open { transform:rotate(180deg); }\n .safety-body { overflow:hidden; max-height:0; opacity:0; transition:max-height .4s var(--ease), opacity .3s; }\n .safety-body.open { max-height:300px; opacity:1; padding-bottom:6px; }\n .safety-body li { font-size:10px; color:var(--mid); padding:2px 0 2px 10px; position:relative; line-height:1.4; list-style:none; }\n .safety-body li::before { content:'\\2022'; position:absolute; left:0; color:var(--border); }\n .alts { padding:8px 14px 10px; }\n .alts-label { font-size:7px; font-weight:700; text-transform:uppercase; letter-spacing:2px; color:var(--light); margin-bottom:6px; }\n .alt { display:inline-block; padding:6px 12px; border:1px solid var(--border); border-radius:12px; font-size:11px; color:var(--dark); margin-right:4px; margin-bottom:4px; cursor:pointer; transition:border-color .2s; }\n .alt:hover { border-color:var(--gold); }\n .alt b { font-weight:600; }\n\n /* \u2550\u2550\u2550 BROWSE ALL CTA \u2550\u2550\u2550 */\n .browse-all {\n display:block; width:calc(100% - 28px); margin:12px 14px;\n padding:12px; text-align:center; text-decoration:none;\n border:1.5px solid var(--ink); border-radius:6px;\n font-size:10px; font-weight:700; color:var(--ink);\n text-transform:uppercase; letter-spacing:2.5px;\n transition:all .2s var(--ease); cursor:pointer; background:none;\n }\n .browse-all:hover { background:var(--ink); color:var(--bg); }\n\n /* \u2550\u2550\u2550 GROUP HEADERS \u2550\u2550\u2550 */\n .group-hdr { padding:12px 14px 2px; font-size:8px; font-weight:700; text-transform:uppercase; letter-spacing:2px; color:var(--gold); border-top:4px solid var(--warm); }\n .group-sub { padding:0 14px 6px; font-size:10px; color:var(--light); font-style:italic; }\n .group-addon { opacity:.75; }\n\n /* \u2550\u2550\u2550 COMPARE \u2550\u2550\u2550 */\n .cmp-verdict { padding:12px 14px; border-bottom:1px solid var(--border); }\n .cmp-verdict-h { font-size:11px; color:var(--mid); margin-bottom:8px; }\n .cmp-verdict-line { display:flex; align-items:flex-start; gap:6px; font-size:11px; line-height:1.4; margin-bottom:4px; }\n .cmp-verdict-line.rec { color:var(--gold); font-weight:600; }\n .cmp-verdict-line:not(.rec) { color:var(--dark); }\n .cmp-verdict-dot { width:6px; height:6px; border-radius:50%; flex-shrink:0; margin-top:5px; }\n .cmp-rec-badge { display:inline-block; padding:2px 7px; background:var(--gold); color:#fff; font-size:7px; font-weight:700; text-transform:uppercase; letter-spacing:1px; border-radius:3px; margin-bottom:4px; }\n @media (prefers-color-scheme: dark) { .cmp-rec-badge { color:var(--bg); } }\n .cmp-grid { display:grid; grid-template-columns:1fr 1fr; gap:1px; background:var(--border); border-bottom:1px solid var(--border); }\n .cmp-card { background:var(--bg); padding:12px 10px; display:flex; flex-direction:column; align-items:center; text-align:center; }\n .cmp-card.rec { background:var(--gold-soft); }\n .cmp-img { width:72px; height:72px; object-fit:cover; border-radius:6px; background:var(--warm); margin-bottom:8px; }\n .cmp-name { font-size:11px; font-weight:600; color:var(--ink); line-height:1.3; margin-bottom:4px; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }\n .cmp-chips { display:flex; flex-wrap:wrap; gap:3px; justify-content:center; margin-bottom:6px; }\n .cmp-chip { padding:2px 6px; border:1px solid var(--border); border-radius:8px; font-size:7px; color:var(--mid); text-transform:uppercase; letter-spacing:.3px; }\n .cmp-price { font-size:13px; font-weight:600; color:var(--ink); margin-bottom:6px; }\n .cmp-row { display:grid; grid-template-columns:1fr 1fr; gap:1px; background:var(--border); }\n .cmp-cell { background:var(--bg); padding:6px 10px; font-size:9px; color:var(--dark); text-align:center; }\n .cmp-cell-label { background:var(--warm); padding:6px 10px; font-size:8px; font-weight:600; color:var(--mid); text-transform:uppercase; letter-spacing:1px; text-align:center; grid-column:1/-1; }\n .cmp-winner { background:var(--gold-soft); }\n .cmp-hdr { grid-column:1/-1; background:var(--warm); padding:6px 10px; text-align:center; font-size:8px; font-weight:700; color:var(--gold); text-transform:uppercase; letter-spacing:2px; }\n\n /* \u2550\u2550\u2550 FIXED CART FOOTER \u2550\u2550\u2550 */\n .cart-spacer { height:52px; }\n .cart-foot { position:fixed; bottom:0; left:0; right:0; padding:10px 14px; background:var(--foot-bg); display:flex; align-items:center; gap:10px; z-index:10; box-shadow:0 -4px 12px rgba(0,0,0,.15); }\n .cart-count { font-size:10px; color:rgba(255,255,255,.6); letter-spacing:.5px; }\n .cart-total { font-size:13px; font-weight:600; color:#fff; margin-left:auto; }\n .cart-btn { padding:7px 16px; background:var(--gold); color:var(--foot-bg); border:none; font-size:9px; font-weight:700; text-transform:uppercase; letter-spacing:2px; cursor:pointer; text-decoration:none; display:inline-block; border-radius:4px; transition:opacity .2s; }\n .cart-btn:hover { opacity:.85; }\n\n /* \u2550\u2550\u2550 CLARIFY \u2550\u2550\u2550 */\n .cfy { padding:0; }\n .cfy-banner { width:100%; height:80px; object-fit:cover; object-position:center 30%; display:block; filter:brightness(.92); }\n .cfy-body { padding:16px 14px 14px; }\n .cfy-h { font-size:17px; font-weight:600; color:var(--ink); margin-bottom:4px; }\n .cfy-sub { font-size:13px; color:var(--mid); line-height:1.5; margin-bottom:14px; }\n .cfy-section { margin-bottom:12px; }\n .cfy-label { font-size:8px; font-weight:700; text-transform:uppercase; letter-spacing:2px; color:var(--gold); margin-bottom:6px; }\n .cfy-chips { display:flex; flex-wrap:wrap; gap:5px; }\n .cfy-chip {\n padding:6px 13px; border:1px solid var(--border); border-radius:14px;\n font-size:12px; color:var(--dark); cursor:pointer;\n transition:all .2s var(--ease); background:var(--bg);\n user-select:none; -webkit-user-select:none;\n }\n .cfy-chip:hover { border-color:var(--gold); }\n .cfy-chip.sel { background:var(--gold-soft); border-color:var(--gold); color:var(--ink); font-weight:600; }\n .cfy-cta { padding:14px 14px 4px; }\n .cfy-btn {\n display:block; width:100%; padding:11px; text-align:center;\n background:var(--ink); color:var(--bg); border:none; cursor:pointer;\n font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:2px;\n border-radius:6px; transition:opacity .2s;\n }\n .cfy-btn:hover { opacity:.85; }\n .cfy-btn:disabled { opacity:.35; cursor:default; }\n .cfy-prompt { margin:10px 14px 14px; padding:10px 12px; background:var(--warm); border-radius:var(--radius); font-size:10px; color:var(--dark); line-height:1.45; text-align:center; display:none; }\n .cfy-prompt.show { display:block; }\n\n .err { padding:14px; font-size:11px; color:var(--mid); }\n</style>\n</head>\n<body>\n<div id=\"root\"><div class=\"ld\"><div class=\"ld-dot\"></div><span>Curating</span></div></div>\n\n<script type=\"module\">\nimport{h,render}from'https://esm.sh/preact@10.25.4';\nimport{useState,useCallback,useEffect,useMemo,useRef}from'https://esm.sh/preact@10.25.4/hooks';\nimport htm from'https://esm.sh/htm@3.1.1';\nconst html=htm.bind(h);\n\nconst fmt=n=>n==null?'':new Intl.NumberFormat(document.documentElement.lang||'en',{style:'currency',currency:'USD'}).format(n);\n/** Generate a WebP variant URL for Shopify CDN images. Returns null for non-Shopify URLs. */\nfunction webpUrl(src){if(!src||!/cdn\\.shopify\\.com/i.test(src))return null;return src+(src.includes('?')?'&':'?')+'format=webp';}\n/** Generate initials from a product name for image fallback. */\nfunction initials(name){if(!name)return'?';const words=name.split(/\\s+/).filter(w=>w.length>1&&!/^(the|for|and|with|of|in|a)$/i.test(w));return words.slice(0,2).map(w=>w[0].toUpperCase()).join('');}\n/** Render a <picture> with WebP source + fallback showing product initials. */\nfunction Img({src,alt,cls,onError:onErr}){\n const wp=webpUrl(src);\n const fb=e=>{\n const el=e.target;const p=el.parentElement.tagName==='PICTURE'?el.parentElement:el;\n const w=el.offsetWidth||80;const h=el.offsetHeight||80;const fs=Math.max(12,Math.min(w,h)*0.3);\n const ini=initials(alt);\n const div=document.createElement('div');\n div.className=cls||'';\n div.style.cssText=`background:var(--warm,#2a2a2a);display:flex;align-items:center;justify-content:center;font-size:${fs}px;font-weight:700;color:var(--sub,#888);letter-spacing:0.05em;width:${w}px;height:${h}px;border-radius:inherit;`;\n div.textContent=ini;\n p.replaceWith(div);\n if(onErr)onErr(e);\n };\n if(!src)return html`<div class=${cls} style=\"background:var(--warm,#2a2a2a);display:flex;align-items:center;justify-content:center;font-weight:700;color:var(--sub,#888);letter-spacing:0.05em;\">${initials(alt)}</div>`;\n if(wp)return html`<picture><source srcset=${wp} type=\"image/webp\" /><img class=${cls} src=${src} alt=${alt} onError=${fb} /></picture>`;\n return html`<img class=${cls} src=${src} alt=${alt} onError=${fb} />`;\n}\nfunction ext(u){if(typeof window.openai?.openExternal==='function')window.openai.openExternal(u);else window.open(u,'_blank','noopener');}\nfunction followUp(p){if(typeof window.openai?.sendFollowUpMessage==='function')window.openai.sendFollowUpMessage({prompt:p});}\nfunction notifyHeight(){if(typeof window.openai?.notifyIntrinsicHeight==='function')window.openai.notifyIntrinsicHeight();}\n\nfunction desc(p){\n if(p.description)return p.description;\n if(/mira|microcurrent/i.test(p.title))return'Light therapy, microcurrents & sonic pulses for smoother skin.';\n if(/cryo/i.test(p.title))return'Cooling tool to refresh, tighten & reduce pores.';\n if(/vault/i.test(p.title))return'Every tool and treatment in one curated set.';\n if(/gel|conductive/i.test(p.title))return'Essential for microcurrent & ultrasonic delivery.';\n if(/serum/i.test(p.title))return'Concentrated formula for renewal & refinement.';\n return'A thoughtful addition to your ritual.';\n}\n\nconst stars=r=>r?'\\u2605'.repeat(Math.floor(r))+(r%1>=.25?'\\u00BD':'')+'\\u2606'.repeat(5-Math.ceil(r)):'';\n\nfunction roleBadge(p,idx){\n if(p.kind==='device')return'Device';\n // Detect bundles/sets by title\n if(/vault|duo|kit|set|bundle|collection/i.test(p.title))return'Set';\n // Detect accessories by title\n if(/headband|towel|bag|case|pouch/i.test(p.title))return'Accessory';\n // Use routineRole if it's specific enough (not generic \"treatment\")\n if(p.routineRole&&!['topical','treatment'].includes(p.routineRole)){\n const r=p.routineRole;\n return r.charAt(0).toUpperCase()+r.slice(1);\n }\n // Fallback by position\n return idx===0?'Best Match':idx===1?'Companion':'Add-on';\n}\n\nconst LOGO='https://laluer.com/cdn/shop/files/big_logo.png?v=1729827237&width=600';\nconst HERO_IMG='https://cdn.shopify.com/s/files/1/0013/3310/0592/files/MIRA_hero_img_slide1_copy_2.png?v=1713225128';\nconst CONCERN_OPTS=['Aging','Dryness','Acne','Redness','Glow','Sensitivity','Texture','Dullness'];\nconst SETUP_OPTS=['One Product','Simple Routine','Device + Routine','Full Set'];\nconst BUDGET_OPTS=['Under $100','$100\\u2013$250','$250+','No Preference'];\n// Quick-route chips for clarify (moved from path switcher on every screen)\nconst QUICK_ROUTES=[\n {label:'Compare Devices',prompt:'Compare the MIRA and CryoSculpt devices side by side'},\n {label:'Starter Routine',prompt:'Recommend a simple beginner skincare routine under $150'},\n {label:'Most Popular',prompt:'Show me the most reviewed La Luer products'},\n {label:'Full Catalog',prompt:'Show me all La Luer products'},\n];\n\n// \u2500\u2500 Persistent state helpers \u2500\u2500\nfunction loadState(){\n try{const ws=window.openai?.widgetState;if(ws&&typeof ws==='object')return ws;}catch(e){}\n return{cart:{}};\n}\nfunction saveState(s){\n try{if(typeof window.openai?.setWidgetState==='function')window.openai.setWidgetState(s);}catch(e){}\n}\n\n// \u2500\u2500 Components \u2500\u2500\n\nfunction BrandHeader({headline}){\n return html`<div class=\"hdr a\">\n <img class=\"hdr-logo\" src=${LOGO} alt=\"La Luer\" />\n <div class=\"hdr-text\">${headline||'Your Curated Selection'}</div>\n </div>`;\n}\n\nfunction RecommendationSummary({hint}){\n if(!hint)return null;\n return html`<div class=\"summary a a1\">\n <div class=\"summary-hint\">${hint}</div>\n </div>`;\n}\n\nfunction HeroCard({p,cart,toggle,dom,badge,isSingle}){\n const inCart=!!cart[String(p.shopifyVariantId)];\n const forLine=p.targetConcerns?.length?p.targetConcerns.slice(0,3).map(c=>c.replace(/_/g,' ')).join(', '):null;\n return html`<div class=\"hero-card a a1\">\n <${Img} src=${p.imageUrl} alt=${p.title} cls=\"hero-img\" />\n <div class=\"hero-info\">\n <span class=\"hero-badge\">${badge||'Best Match'}</span>\n <div class=\"hero-title\">${p.title}</div>\n <div class=\"hero-desc\">${desc(p)}</div>\n ${forLine?html`<div class=\"hero-for\">Best for ${forLine}</div>`:null}\n ${p.rating?html`<div class=\"hero-rating\"><span class=\"stars\">${stars(p.rating)}</span> ${p.reviewCount?p.reviewCount+' reviews':''}</div>`:null}\n <div class=\"hero-price\">${fmt(p.price)}</div>\n <div class=\"hero-actions\">\n ${p.shopifyVariantId&&dom?html`<button class=${'btn btn-primary'+(inCart?' added':'')}\n onClick=${()=>toggle(p)}>${inCart?'\\u2713 Added':'Add to Bag'}</button>`:null}\n ${p.productUrl?html`<a class=\"btn btn-secondary\" href=${p.productUrl}\n onClick=${e=>{e.preventDefault();ext(p.productUrl);}}>View</a>`:null}\n </div>\n ${isSingle?html`<div class=\"hero-forward\">\n <button class=\"hero-forward-link\" onClick=${()=>followUp('Build me a routine that includes '+p.title)}>Build a routine with this \\u2192</button>\n </div>`:null}\n </div>\n </div>`;\n}\n\nfunction ProductRow({p,idx,cart,toggle,dom}){\n const inCart=!!cart[String(p.shopifyVariantId)];\n const role=roleBadge(p,idx+1);\n return html`<div class=${'prod-row a a'+Math.min(idx+2,5)+(inCart?' in-cart':'')}>\n <${Img} src=${p.imageUrl} alt=${p.title} cls=\"prod-thumb\" />\n <div class=\"prod-info\">\n <div class=\"prod-role\">${role}</div>\n <div class=\"prod-name\">${p.title}</div>\n <div class=\"prod-sub\">${p.targetConcerns?.length?'Best for '+p.targetConcerns.map(c=>c.replace(/_/g,' ')).join(' & '):desc(p)}</div>\n </div>\n <div class=\"prod-right\">\n <div class=\"prod-price\">${fmt(p.price)}</div>\n ${p.shopifyVariantId&&dom?html`<button class=${'btn btn-sm btn-primary'+(inCart?' added':'')}\n onClick=${()=>toggle(p)}>${inCart?'\\u2713':'Add'}</button>`:null}\n </div>\n </div>`;\n}\n\nfunction RoutineAccordion({routine}){\n const[open,setOpen]=useState(false);\n if(!routine?.length)return null;\n return html`<div>\n <button class=\"routine-toggle\" onClick=${()=>{setOpen(!open);setTimeout(notifyHeight,400);}}>\n Your Routine \\u2014 ${routine.length} step${routine.length===1?'':'s'}\n <span class=${'routine-arr'+(open?' open':'')}>\\u25BC</span>\n </button>\n <div class=${'routine-body'+(open?' open':'')}>\n ${routine.map(s=>html`<div class=\"routine-step\" key=${s.order}>\n <div class=\"routine-num\">${s.order}</div>\n <div class=\"routine-detail\">\n <div class=\"routine-role\">${s.role}</div>\n <div class=\"routine-instr\">${s.instruction}</div>\n </div>\n </div>`)}\n </div>\n </div>`;\n}\n\nfunction EditorialNote({text,isBundle}){\n if(!text)return null;\n return html`<div class=\"ed-note a a4\">\n <div class=\"ed-label\">${isBundle?\"What\\u2019s Inside\":'Why This Works'}</div>\n <div class=\"ed-text\">${text}</div>\n </div>`;\n}\n\nfunction Safety({notes}){\n const[o,so]=useState(false);\n if(!notes?.length)return null;\n return html`<div class=\"safety\">\n <button class=\"safety-btn\" onClick=${()=>{so(!o);setTimeout(notifyHeight,400);}}>Safety & Usage <span class=${'safety-arr'+(o?' open':'')}>\\u25BC</span></button>\n <div class=${'safety-body'+(o?' open':'')}><ul>${notes.map(n=>html`<li key=${n}>${n}</li>`)}</ul></div>\n </div>`;\n}\n\nfunction Alts({items}){\n if(!items?.length)return null;\n // Deduplicate alternates with the same price (engine sometimes returns identical offers with different labels)\n const seen=new Set();\n const unique=items.filter(a=>{const k=a.totalPrice;if(seen.has(k))return false;seen.add(k);return true;});\n if(!unique.length)return null;\n return html`<div class=\"alts\">\n <div class=\"alts-label\">Other Options</div>\n ${unique.map(a=>html`<span class=\"alt\" key=${a.label} style=\"cursor:pointer\"\n onClick=${()=>followUp('Recommend me the '+a.strategy+' strategy skincare routine instead')}>${a.label} <b>${fmt(a.totalPrice)}</b></span>`)}\n </div>`;\n}\n\nfunction BrowseAllCTA({show}){\n if(!show)return null;\n return html`<button class=\"browse-all a a4\" onClick=${()=>followUp('Show me all products in the catalog')}>Browse All Products</button>`;\n}\n\n// \u2500\u2500 Clarify Intake \u2500\u2500\nfunction ClarifyIntake({text}){\n const[goals,setGoals]=useState([]);\n const[setup,setSetup]=useState(null);\n const[budget,setBudget]=useState(null);\n const hasInput=goals.length>0;\n\n const toggleGoal=useCallback(g=>{\n setGoals(prev=>prev.includes(g)?prev.filter(x=>x!==g):[...prev,g]);\n },[]);\n\n const prompt=useMemo(()=>{\n if(!goals.length)return'';\n let p='I need help with '+goals.map(g=>g.toLowerCase()).join(' and ');\n if(setup)p+='. Looking for: '+setup.toLowerCase();\n if(budget&&budget!=='No Preference')p+='. Budget: '+budget.toLowerCase();\n return p+'.';\n },[goals,setup,budget]);\n\n return html`<div class=\"cfy a\">\n <img class=\"cfy-banner\" src=${HERO_IMG} alt=\"\" />\n <div class=\"cfy-body\">\n <div class=\"cfy-h\">Let\\u2019s narrow it down.</div>\n <div class=\"cfy-sub\">${text||'Tell us what you\\u2019re shopping for and we\\u2019ll curate the best place to start.'}</div>\n\n <div class=\"cfy-section\">\n <div class=\"cfy-label\">Main Goal</div>\n <div class=\"cfy-chips\">\n ${CONCERN_OPTS.map(c=>html`<span key=${c} class=${'cfy-chip'+(goals.includes(c)?' sel':'')} onClick=${()=>toggleGoal(c)}>${c}</span>`)}\n </div>\n </div>\n\n <div class=\"cfy-section\">\n <div class=\"cfy-label\">What kind of setup?</div>\n <div class=\"cfy-chips\">\n ${SETUP_OPTS.map(s=>html`<span key=${s} class=${'cfy-chip'+(setup===s?' sel':'')} onClick=${()=>setSetup(prev=>prev===s?null:s)}>${s}</span>`)}\n </div>\n </div>\n\n <div class=\"cfy-section\">\n <div class=\"cfy-label\">Budget</div>\n <div class=\"cfy-chips\">\n ${BUDGET_OPTS.map(b=>html`<span key=${b} class=${'cfy-chip'+(budget===b?' sel':'')} onClick=${()=>setBudget(prev=>prev===b?null:b)}>${b}</span>`)}\n </div>\n </div>\n\n </div>\n\n <div class=\"cfy-section\" style=\"padding:0 14px 12px\">\n <div class=\"cfy-label\">Quick Routes</div>\n <div class=\"cfy-chips\">\n ${QUICK_ROUTES.map(r=>html`<span key=${r.label} class=\"cfy-chip\" onClick=${()=>followUp(r.prompt)}>${r.label}</span>`)}\n </div>\n </div>\n\n <div class=\"cfy-cta\">\n <button class=\"cfy-btn\" disabled=${!hasInput}\n onClick=${()=>{\n if(!prompt)return;\n if(typeof window.openai?.callTool==='function'){window.openai.callTool('skincare_recommend',{query:prompt});return;}\n if(typeof window.openai?.sendFollowUpMessage==='function'){followUp(prompt);return;}\n navigator.clipboard?.writeText(prompt).catch(()=>{});\n }}>\n ${hasInput?(typeof window.openai?.callTool==='function'||typeof window.openai?.sendFollowUpMessage==='function'?'Show My Picks':'Copy Prompt to Ask'):'Select a Goal'}\n </button>\n <button class=\"browse-all\" style=\"margin-top:8px\" onClick=${()=>followUp('Show me all products in the catalog')}>Browse All Products</button>\n </div>\n\n <div class=${'cfy-prompt'+(hasInput&&typeof window.openai?.sendFollowUpMessage!=='function'&&typeof window.openai?.callTool!=='function'?' show':'')}>\n Try asking: \\u201C${prompt}\\u201D\n </div>\n </div>`;\n}\n\n// \u2500\u2500 Group products by role \u2500\u2500\nfunction groupProducts(prods){\n const groups={device:[],companion:[],addon:[]};\n for(const p of prods){\n if(p.kind==='device')groups.device.push(p);\n else if(['treatment','moisturizer','cleanser','serum','prep'].includes(p.routineRole))groups.companion.push(p);\n else groups.addon.push(p);\n }\n return groups;\n}\n\nfunction GroupedProducts({prods,cart,toggle,dom}){\n const g=useMemo(()=>groupProducts(prods),[prods]);\n const sections=[];\n if(g.device.length)sections.push({label:'Your Device',sub:null,cls:'',items:g.device});\n if(g.companion.length)sections.push({label:'Essential Companions',sub:'Start with these',cls:'',items:g.companion});\n if(g.addon.length)sections.push({label:'Optional Add-ons',sub:'Add if you want more',cls:'group-addon',items:g.addon});\n if(sections.length<=1){\n return html`${prods.map((p,i)=>html`<${ProductRow} key=${p.sku} p=${p} idx=${i} cart=${cart} toggle=${toggle} dom=${dom} />`)}`;\n }\n let idx=0;\n return html`${sections.map(s=>html`<div key=${s.label} class=${s.cls||''}>\n <div class=\"group-hdr a\">${s.label}</div>\n ${s.sub?html`<div class=\"group-sub\">${s.sub}</div>`:null}\n ${s.items.map(p=>{const i=idx++;return html`<${ProductRow} key=${p.sku} p=${p} idx=${i} cart=${cart} toggle=${toggle} dom=${dom} />`;})}\n </div>`)}`;\n}\n\n// \u2500\u2500 Compare Mode \u2500\u2500\nfunction CompareMode({prods,cart,toggle,dom}){\n if(!prods||prods.length<2)return null;\n const a=prods[0],b=prods[1];\n const aConcerns=(a.targetConcerns||[]).map(c=>c.replace(/_/g,' '));\n const bConcerns=(b.targetConcerns||[]).map(c=>c.replace(/_/g,' '));\n\n return html`<div class=\"a a1\">\n <div class=\"cmp-verdict\">\n <div class=\"cmp-verdict-h\">Choose what matches your priorities.</div>\n <div class=\"cmp-verdict-line rec\">\n <div class=\"cmp-verdict-dot\" style=\"background:var(--gold)\"></div>\n <span><b>${a.title.split(' ').slice(0,2).join(' ')}</b> \\u2014 Best for ${aConcerns.slice(0,2).join(' & ')||'comprehensive treatment'}</span>\n </div>\n <div class=\"cmp-verdict-line\">\n <div class=\"cmp-verdict-dot\" style=\"background:var(--light)\"></div>\n <span><b>${b.title.split(' ').slice(0,2).join(' ')}</b> \\u2014 Best for ${bConcerns.slice(0,2).join(' & ')||'targeted care'}</span>\n </div>\n </div>\n <div class=\"cmp-grid\">\n <div class=\"cmp-card rec\">\n <span class=\"cmp-rec-badge\">Recommended</span>\n <${Img} src=${a.imageUrl} alt=${a.title} cls=\"cmp-img\" />\n <div class=\"cmp-name\">${a.title}</div>\n <div class=\"cmp-chips\">${aConcerns.slice(0,3).map(c=>html`<span class=\"cmp-chip\" key=${c}>${c}</span>`)}</div>\n <div class=\"cmp-price\">${fmt(a.price)}</div>\n ${a.shopifyVariantId&&dom?html`<button class=${'btn btn-sm btn-primary'+(cart[String(a.shopifyVariantId)]?' added':'')}\n onClick=${()=>toggle(a)}>${cart[String(a.shopifyVariantId)]?'\\u2713 Added':'Add'}</button>`:null}\n </div>\n <div class=\"cmp-card\">\n <${Img} src=${b.imageUrl} alt=${b.title} cls=\"cmp-img\" />\n <div class=\"cmp-name\">${b.title}</div>\n <div class=\"cmp-chips\">${bConcerns.slice(0,3).map(c=>html`<span class=\"cmp-chip\" key=${c}>${c}</span>`)}</div>\n <div class=\"cmp-price\">${fmt(b.price)}</div>\n ${b.shopifyVariantId&&dom?html`<button class=${'btn btn-sm btn-primary'+(cart[String(b.shopifyVariantId)]?' added':'')}\n onClick=${()=>toggle(b)}>${cart[String(b.shopifyVariantId)]?'\\u2713 Added':'Add'}</button>`:null}\n </div>\n </div>\n <div class=\"cmp-row\"><div class=\"cmp-hdr\">Key Differences</div></div>\n <div class=\"cmp-row\"><div class=\"cmp-cell-label\">Best For</div></div>\n <div class=\"cmp-row\">\n <div class=\"cmp-cell\">${aConcerns.join(', ')||'\\u2014'}</div>\n <div class=\"cmp-cell\">${bConcerns.join(', ')||'\\u2014'}</div>\n </div>\n <div class=\"cmp-row\"><div class=\"cmp-cell-label\">Price</div></div>\n <div class=\"cmp-row\">\n <div class=${'cmp-cell'+(a.price<b.price?' cmp-winner':'')}>${fmt(a.price)}${a.price<b.price?' \\u2713':''}</div>\n <div class=${'cmp-cell'+(b.price<a.price?' cmp-winner':'')}>${fmt(b.price)}${b.price<a.price?' \\u2713':''}</div>\n </div>\n ${a.rating||b.rating?html`<div>\n <div class=\"cmp-row\"><div class=\"cmp-cell-label\">Rating</div></div>\n <div class=\"cmp-row\">\n <div class=${'cmp-cell'+((a.rating||0)>(b.rating||0)?' cmp-winner':'')}>${a.rating?a.rating+'/5':'\\u2014'}${a.reviewCount?' ('+a.reviewCount+')':''}</div>\n <div class=${'cmp-cell'+((b.rating||0)>(a.rating||0)?' cmp-winner':'')}>${b.rating?b.rating+'/5':'\\u2014'}${b.reviewCount?' ('+b.reviewCount+')':''}</div>\n </div>\n </div>`:null}\n ${prods.length>2?html`<div style=\"padding:8px 14px;\">\n ${prods.slice(2).map((p,i)=>html`<${ProductRow} key=${p.sku} p=${p} idx=${i+2} cart=${cart} toggle=${toggle} dom=${dom} />`)}\n </div>`:null}\n </div>`;\n}\n\nfunction CartFooter({cart,dom}){\n const ids=Object.keys(cart);\n // Hide footer entirely when nothing selected\n if(!ids.length)return html`<div class=\"cart-spacer\"></div>`;\n let total=0;\n for(const v of Object.values(cart))total+=v.price||0;\n const url='https://'+dom+'/cart/'+ids.map(v=>v+':1').join(',');\n return html`<div><div class=\"cart-spacer\"></div><div class=\"cart-foot\">\n <div class=\"cart-count\">${ids.length} item${ids.length===1?'':'s'} selected</div>\n <div class=\"cart-total\">${fmt(total)}</div>\n <a class=\"cart-btn\" href=${url} target=\"_blank\" rel=\"noopener\"\n onClick=${e=>{if(typeof window.openai?.openExternal==='function'){e.preventDefault();ext(url);}}}>Checkout</a>\n </div></div>`;\n}\n\n// \u2500\u2500 Main Widget \u2500\u2500\n\nfunction Widget({data}){\n const[state,setState]=useState(loadState);\n const cart=state.cart||{};\n\n const toggle=useCallback((p)=>{\n setState(prev=>{\n const c={...prev.cart};\n const vid=String(p.shopifyVariantId);\n if(c[vid])delete c[vid];\n else c[vid]={price:p.price||0,title:p.title};\n const next={...prev,cart:c};\n saveState(next);\n return next;\n });\n },[]);\n\n // Notify height after render\n useEffect(()=>{notifyHeight();},[data,state]);\n\n if(!data)return html`<div class=\"err\">No data.</div>`;\n\n // Clarify mode\n if(data.mode==='clarify')return html`<div>\n <${BrandHeader} headline=\"La Luer\" />\n <${ClarifyIntake} text=${data.clarification||data.response||null} />\n </div>`;\n\n let dom=data.storeDomain||null;\n if(!dom&&data.cart?.checkout_url){const m=data.cart.checkout_url.match(/https?:\\/\\/([^\\/]+)/);if(m)dom=m[1];}\n const prods=data.products||[];\n const hasCk=dom&&prods.some(p=>p.shopifyVariantId);\n const isBundle=prods.length===1&&/vault|duo|kit|set|bundle/i.test(prods[0]?.title||'');\n const isCompare=data.presentation?.widget_type==='comparison_cards';\n const isSingle=prods.length===1;\n const hero=prods[0];\n const rest=prods.slice(1);\n const isSearch=data.mode==='search';\n const hint=data.narration?.decision_hint||null;\n const headline=data.headline||data.narration?.recommended_summary||(isCompare?'Compare':isBundle?'Complete Set':isSearch?prods.length+' products':'Your Curated Selection');\n // Context-aware hero badge\n const heroBadge=isSearch?(hero?.reviewCount?'Most Popular':'Top Result'):isBundle?'Complete Set':isSingle?(hero?.targetConcerns?.length?'Best for '+hero.targetConcerns[0].replace(/_/g,' '):'Recommended'):'Best Match';\n const showBrowse=prods.length<6&&!isSearch;\n\n // Compare mode\n if(isCompare&&prods.length>=2){\n return html`<div>\n <${BrandHeader} headline=${headline} />\n <${RecommendationSummary} hint=${hint} />\n <${CompareMode} prods=${prods} cart=${cart} toggle=${toggle} dom=${dom} />\n <${EditorialNote} text=${data.whyThisWorks} isBundle=${false} />\n <${Safety} notes=${data.safetyNotes} />\n <${Alts} items=${data.alternates} />\n <${BrowseAllCTA} show=${showBrowse} />\n ${hasCk?html`<${CartFooter} cart=${cart} dom=${dom} />`:null}\n </div>`;\n }\n\n // Recommend mode\n return html`<div>\n <${BrandHeader} headline=${headline} />\n <${RecommendationSummary} hint=${hint} />\n ${hero?html`<${HeroCard} p=${hero} cart=${cart} toggle=${toggle} dom=${dom} badge=${heroBadge} isSingle=${isSingle} />`:null}\n ${rest.length?html`<${GroupedProducts} prods=${rest} cart=${cart} toggle=${toggle} dom=${dom} />`:null}\n <${RoutineAccordion} routine=${data.routine} />\n <${EditorialNote} text=${data.whyThisWorks} isBundle=${isBundle} />\n <${Safety} notes=${data.safetyNotes} />\n <${Alts} items=${data.alternates} />\n <${BrowseAllCTA} show=${showBrowse} />\n ${hasCk?html`<${CartFooter} cart=${cart} dom=${dom} />`:null}\n </div>`;\n}\n\n// \u2500\u2500 App Shell \u2500\u2500\n\nfunction App(){\n const[data,setData]=useState(null);\n useEffect(()=>{\n function onMsg(e){\n if(e.source!==window.parent&&e.source!==window)return;\n const m=e.data;if(!m||typeof m!=='object')return;\n if(m.method==='ui/notifications/tool-result'||m.type==='ui/notifications/tool-result'){\n const p=m.params||m;const s=p?.structuredContent||m.structuredContent;\n if(s){setData(s);return;}\n }\n if(m.type==='skincare/render'){setData(m.data);return;}\n }\n function onInit(e){\n if(e.source!==window.parent&&e.source!==window)return;\n const m=e.data;\n if(m?.type==='ui/initialize'||m?.method==='ui/initialize')\n window.parent.postMessage({jsonrpc:'2.0',method:'ui/notifications/initialized'},'*');\n }\n window.addEventListener('message',onMsg);\n window.addEventListener('message',onInit);\n window.parent.postMessage({jsonrpc:'2.0',method:'ui/notifications/initialized'},'*');\n if(typeof window.openai?.toolOutput==='object')setData(window.openai.toolOutput);\n function onG(e){\n const o=e?.detail?.globals?.toolOutput;\n if(o&&typeof o==='object')setData(o);\n else if(typeof window.openai?.toolOutput==='object')setData(window.openai.toolOutput);\n }\n window.addEventListener('openai:set_globals',onG,{passive:true});\n return()=>{window.removeEventListener('message',onMsg);window.removeEventListener('message',onInit);window.removeEventListener('openai:set_globals',onG);};\n },[]);\n if(!data)return html`<div class=\"ld\"><div class=\"ld-dot\"></div><span>Curating</span></div>`;\n return html`<${Widget} data=${data} />`;\n}\nrender(html`<${App} />`,document.getElementById('root'));\n</script>\n</body>\n</html>\n",
"uri": "ui://widget/product-card.html"
}
]
}
},
"resource_uri": "ui://widget/product-card.html",
"url": "https://searchshopai-mcp.fly.dev/mcp/la-luer"
},
"latency_ms": 15.17,
"status": "ok"
},
"resources_list": {
"details": {
"headers": {
"content-type": "application/json"
},
"http_status": 200,
"payload": {
"id": 5,
"jsonrpc": "2.0",
"result": {
"resources": [
{
"_meta": {
"openai/widgetCSP": {
"connect_domains": [
"https://*.ngrok-free.dev",
"https://*.myshopify.com",
"https://cdn.shopify.com",
"https://esm.sh"
],
"redirect_domains": [
"https://*.myshopify.com",
"https://*.shopify.com"
],
"resource_domains": [
"https://esm.sh",
"https://cdn.shopify.com",
"https://*.shopify.com",
"https://*.youthtothepeople.com",
"https://*.laluer.com",
"https://*.glam-moda.com",
"https://incidecoder-content.storage.googleapis.com",
"https://media.kohlsimg.com",
"https://*.mercdn.net",
"https://*.bigcommerce.com",
"https://di2ponv0v5otw.cloudfront.net",
"https://placehold.co"
]
},
"ui": {
"csp": {
"connectDomains": [
"https://*.ngrok-free.dev",
"https://*.myshopify.com",
"https://cdn.shopify.com",
"https://esm.sh"
],
"redirectDomains": [
"https://*.myshopify.com",
"https://*.shopify.com"
],
"resourceDomains": [
"https://esm.sh",
"https://cdn.shopify.com",
"https://*.shopify.com",
"https://*.youthtothepeople.com",
"https://*.laluer.com",
"https://*.glam-moda.com",
"https://incidecoder-content.storage.googleapis.com",
"https://media.kohlsimg.com",
"https://*.mercdn.net",
"https://*.bigcommerce.com",
"https://di2ponv0v5otw.cloudfront.net",
"https://placehold.co"
]
},
"prefersBorder": true
}
},
"mimeType": "text/html;profile=mcp-app",
"name": "product-card",
"uri": "ui://widget/product-card.html"
},
{
"mimeType": "text/html;profile=mcp-app",
"name": "debug-widget",
"uri": "ui://widget/debug.html"
}
]
}
},
"url": "https://searchshopai-mcp.fly.dev/mcp/la-luer"
},
"latency_ms": 31.4,
"status": "ok"
},
"server_card": {
"details": {
"error": "Client error '404 Not Found' for url 'https://searchshopai-mcp.fly.dev/.well-known/mcp/server-card.json'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404",
"url": "https://searchshopai-mcp.fly.dev/.well-known/mcp/server-card.json"
},
"latency_ms": 42.3,
"status": "error"
},
"session_resume_probe": {
"details": {
"protocol_version": "2025-03-26",
"reason": "no_session_id",
"resume_expected": true,
"transport": "streamable-http"
},
"latency_ms": null,
"status": "warning"
},
"step_up_auth_probe": {
"details": {
"auth_required_checks": [],
"broad_scopes": [],
"challenge_headers": [],
"minimal_scope_documented": false,
"oauth_present": false,
"scope_specificity_ratio": 0.0,
"step_up_signals": [],
"supported_scopes": []
},
"latency_ms": null,
"status": "missing"
},
"tool_snapshot_probe": {
"details": {
"added": [],
"changed_outputs": [],
"current_tool_count": 11,
"previous_tool_count": 11,
"removed": [],
"similarity": 1.0
},
"latency_ms": null,
"status": "ok"
},
"tools_list": {
"details": {
"headers": {
"content-type": "application/json"
},
"http_status": 200,
"payload": {
"id": 2,
"jsonrpc": "2.0",
"result": {
"tools": [
{
"_meta": {
"openai/outputTemplate": "ui://widget/product-card.html",
"openai/toolInvocation/invoked": "Recommendation ready.",
"openai/toolInvocation/invoking": "Finding your perfect product\u2026",
"openai/widgetCSP": {
"connect_domains": [
"https://*.ngrok-free.dev",
"https://*.myshopify.com",
"https://cdn.shopify.com",
"https://esm.sh"
],
"redirect_domains": [
"https://*.myshopify.com",
"https://*.shopify.com"
],
"resource_domains": [
"https://esm.sh",
"https://cdn.shopify.com",
"https://*.shopify.com",
"https://*.youthtothepeople.com",
"https://*.laluer.com",
"https://*.glam-moda.com",
"https://incidecoder-content.storage.googleapis.com",
"https://media.kohlsimg.com",
"https://*.mercdn.net",
"https://*.bigcommerce.com",
"https://di2ponv0v5otw.cloudfront.net",
"https://placehold.co"
]
},
"ui": {
"resourceUri": "ui://widget/product-card.html"
},
"ui/resourceUri": "ui://widget/product-card.html"
},
"annotations": {
"destructiveHint": false,
"openWorldHint": false,
"readOnlyHint": true
},
"description": "(Deprecated: use 'recommend' instead. Works identically.) Get a personalized La Luer product recommendation with ingredient-aware scoring, safety notes, and routine building. Use when the user wants advice on what to buy, needs help choosing between products, has a specific skin concern (acne, aging, dryness, sensitivity, etc.), wants a routine, or asks \"what should I use for X.\" Do not use for browsing or listing products \u2014 use search_products instead. Returns scored products with explanations, usage instructions, and Shopify checkout. This tool analyzes ingredients, irritation risk, and product compatibility \u2014 use it over search_products when the user needs guidance, not just a product list.",
"execution": {
"taskSupport": "forbidden"
},
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"brand": {
"description": "Filter to a specific brand only (e.g. 'Youth to the People', 'CeraVe', 'The Ordinary'). Use when the user asks for products from a specific brand.",
"maxLength": 100,
"type": "string"
},
"query": {
"description": "Natural language query about skin concerns (e.g. 'I have oily acne-prone skin and want something gentle under $30')",
"maxLength": 2000,
"type": "string"
},
"strategy": {
"description": "Optional offer strategy override: starter, gentle, budget, glow_safe, minimal, strong, fallback",
"maxLength": 50,
"type": "string"
}
},
"required": [
"query"
],
"type": "object"
},
"name": "skincare_recommend"
},
{
"_meta": {
"openai/outputTemplate": "ui://widget/product-card.html",
"openai/toolInvocation/invoked": "Recommendation ready.",
"openai/toolInvocation/invoking": "Finding your perfect product\u2026",
"openai/widgetCSP": {
"connect_domains": [
"https://*.ngrok-free.dev",
"https://*.myshopify.com",
"https://cdn.shopify.com",
"https://esm.sh"
],
"redirect_domains": [
"https://*.myshopify.com",
"https://*.shopify.com"
],
"resource_domains": [
"https://esm.sh",
"https://cdn.shopify.com",
"https://*.shopify.com",
"https://*.youthtothepeople.com",
"https://*.laluer.com",
"https://*.glam-moda.com",
"https://incidecoder-content.storage.googleapis.com",
"https://media.kohlsimg.com",
"https://*.mercdn.net",
"https://*.bigcommerce.com",
"https://di2ponv0v5otw.cloudfront.net",
"https://placehold.co"
]
},
"ui": {
"resourceUri": "ui://widget/product-card.html"
},
"ui/resourceUri": "ui://widget/product-card.html"
},
"annotations": {
"destructiveHint": false,
"openWorldHint": false,
"readOnlyHint": true
},
"description": "Get a personalized product recommendation with domain-expert scoring, safety notes, and transaction authority. Use when the user wants advice, has a concern, or asks what to buy. Returns scored products with checkout URLs, safety assessment, and authority state (SHOULD/CAN/SHOULDNT/ESCALATE/CANT).",
"execution": {
"taskSupport": "forbidden"
},
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"brand": {
"description": "Filter to a specific brand",
"maxLength": 100,
"type": "string"
},
"domain": {
"description": "Product domain (e.g. 'skincare', 'beauty_devices'). Auto-detected from merchant if omitted.",
"maxLength": 50,
"type": "string"
},
"query": {
"description": "Natural language query about product needs",
"maxLength": 2000,
"type": "string"
},
"strategy": {
"description": "Optional offer strategy override",
"maxLength": 50,
"type": "string"
}
},
"required": [
"query"
],
"type": "object"
},
"name": "recommend"
},
{
"_meta": {
"openai/outputTemplate": "ui://widget/product-card.html",
"openai/toolInvocation/invoked": "Cart ready.",
"openai/toolInvocation/invoking": "Building your cart\u2026",
"openai/widgetCSP": {
"connect_domains": [
"https://*.ngrok-free.dev",
"https://*.myshopify.com",
"https://cdn.shopify.com",
"https://esm.sh"
],
"redirect_domains": [
"https://*.myshopify.com",
"https://*.shopify.com"
],
"resource_domains": [
"https://esm.sh",
"https://cdn.shopify.com",
"https://*.shopify.com",
"https://*.youthtothepeople.com",
"https://*.laluer.com",
"https://*.glam-moda.com",
"https://incidecoder-content.storage.googleapis.com",
"https://media.kohlsimg.com",
"https://*.mercdn.net",
"https://*.bigcommerce.com",
"https://di2ponv0v5otw.cloudfront.net",
"https://placehold.co"
]
},
"ui": {
"resourceUri": "ui://widget/product-card.html"
},
"ui/resourceUri": "ui://widget/product-card.html"
},
"annotations": {
"destructiveHint": false,
"openWorldHint": true,
"readOnlyHint": false
},
"description": "Create a buyable shopping cart with a real checkout URL. Two modes: (1) Pass 'products' array with specific product names. (2) Pass 'query' string to auto-recommend and cart. Do not use for browsing or recommendations \u2014 use search_products or skincare_recommend first. Returns a widget with the cart items and a working checkout link.",
"execution": {
"taskSupport": "forbidden"
},
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"products": {
"description": "Specific product titles to add to the cart",
"items": {
"maxLength": 200,
"type": "string"
},
"maxItems": 20,
"type": "array"
},
"query": {
"description": "Natural language query to auto-recommend products. Only used if products array is not provided.",
"maxLength": 2000,
"type": "string"
},
"strategy": {
"description": "Optional offer strategy override when using query mode",
"maxLength": 50,
"type": "string"
}
},
"type": "object"
},
"name": "skincare_cart"
},
{
"annotations": {
"destructiveHint": false,
"openWorldHint": false,
"readOnlyHint": false
},
"description": "Report when a tool result was unhelpful, incomplete, or wrong. Call this whenever you override a recommendation, skip a cart result, or notice the engine output doesn't match what the user needs. Do not use proactively \u2014 only when you observe an actual issue. This helps improve the engine.",
"execution": {
"taskSupport": "forbidden"
},
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"description": {
"description": "What went wrong and what you expected instead",
"type": "string"
},
"expected_products": {
"description": "What products should have been recommended",
"items": {
"type": "string"
},
"type": "array"
},
"issue_type": {
"description": "Type of issue",
"enum": [
"wrong_products",
"too_few_products",
"too_expensive",
"ignored_concern",
"ignored_budget",
"bad_recommendation",
"cart_mismatch",
"missing_product",
"other"
],
"type": "string"
},
"tool_name": {
"description": "Which tool had the issue (skincare_recommend, skincare_cart, skincare_report_issue)",
"maxLength": 100,
"type": "string"
},
"user_query": {
"description": "The original user query if available",
"type": "string"
}
},
"required": [
"tool_name",
"issue_type",
"description"
],
"type": "object"
},
"name": "skincare_report_issue"
},
{
"_meta": {
"openai/outputTemplate": "ui://widget/product-card.html",
"openai/toolInvocation/invoked": "Products found.",
"openai/toolInvocation/invoking": "Searching products\u2026",
"openai/widgetCSP": {
"connect_domains": [
"https://*.ngrok-free.dev",
"https://*.myshopify.com",
"https://cdn.shopify.com",
"https://esm.sh"
],
"redirect_domains": [
"https://*.myshopify.com",
"https://*.shopify.com"
],
"resource_domains": [
"https://esm.sh",
"https://cdn.shopify.com",
"https://*.shopify.com",
"https://*.youthtothepeople.com",
"https://*.laluer.com",
"https://*.glam-moda.com",
"https://incidecoder-content.storage.googleapis.com",
"https://media.kohlsimg.com",
"https://*.mercdn.net",
"https://*.bigcommerce.com",
"https://di2ponv0v5otw.cloudfront.net",
"https://placehold.co"
]
},
"ui": {
"resourceUri": "ui://widget/product-card.html"
},
"ui/resourceUri": "ui://widget/product-card.html"
},
"annotations": {
"destructiveHint": false,
"openWorldHint": false,
"readOnlyHint": true
},
"description": "Browse and search the product catalog. Use when the user wants to see what's available, look up specific products, browse by category, compare options, or asks 'show me' / 'what do you have.' Do not use when the user needs personalized recommendations based on skin concerns \u2014 use skincare_recommend instead. Returns all matching products with prices, images, and checkout. Unlike skincare_recommend, this does not score or filter \u2014 it shows everything that matches so the user can decide.",
"execution": {
"taskSupport": "forbidden"
},
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"category": {
"description": "Filter by exact product category from the catalog (e.g. 'serum', 'treatment', 'cleanser', 'moisturizer'). Do not guess categories \u2014 only use this if the user explicitly mentions a catalog category. For general queries like 'devices' or 'bundles', use the query parameter instead.",
"type": "string"
},
"max_price": {
"description": "Filter to products at or below this price",
"type": "number"
},
"max_results": {
"description": "Maximum products to return (default 10). Only set this if the user specifies a count \u2014 e.g. 'show me 2 devices' \u2192 2. Otherwise leave it unset and the default will return all relevant matches up to 10.",
"maximum": 20,
"minimum": 1,
"type": "integer"
},
"query": {
"description": "Search query (e.g. 'vitamin c serum', 'anti-aging', 'moisturizer under $50')",
"maxLength": 500,
"type": "string"
}
},
"required": [
"query"
],
"type": "object"
},
"name": "search_products"
},
{
"_meta": {
"openai/outputTemplate": "ui://widget/product-card.html",
"openai/toolInvocation/invoked": "Product ready.",
"openai/toolInvocation/invoking": "Loading product details\u2026",
"openai/widgetCSP": {
"connect_domains": [
"https://*.ngrok-free.dev",
"https://*.myshopify.com",
"https://cdn.shopify.com",
"https://esm.sh"
],
"redirect_domains": [
"https://*.myshopify.com",
"https://*.shopify.com"
],
"resource_domains": [
"https://esm.sh",
"https://cdn.shopify.com",
"https://*.shopify.com",
"https://*.youthtothepeople.com",
"https://*.laluer.com",
"https://*.glam-moda.com",
"https://incidecoder-content.storage.googleapis.com",
"https://media.kohlsimg.com",
"https://*.mercdn.net",
"https://*.bigcommerce.com",
"https://di2ponv0v5otw.cloudfront.net",
"https://placehold.co"
]
},
"ui": {
"resourceUri": "ui://widget/product-card.html"
},
"ui/resourceUri": "ui://widget/product-card.html"
},
"annotations": {
"destructiveHint": false,
"openWorldHint": false,
"readOnlyHint": true
},
"description": "Get full details for a specific product by SKU or title. Use when the user asks about a specific product by name (e.g. 'tell me about MIRA', 'show me the serum'). Do not use for browsing or recommendations \u2014 use search_products or skincare_recommend. Returns a widget card with the product details, image, price, and checkout button.",
"execution": {
"taskSupport": "forbidden"
},
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"sku": {
"description": "Exact product SKU (e.g. 'LL-4632379916336')",
"type": "string"
},
"title": {
"description": "Product title to search for (fuzzy match)",
"type": "string"
}
},
"type": "object"
},
"name": "get_product"
},
{
"_meta": {
"openai/outputTemplate": "ui://widget/product-card.html",
"openai/toolInvocation/invoked": "Comparison ready.",
"openai/toolInvocation/invoking": "Comparing products\u2026",
"openai/widgetCSP": {
"connect_domains": [
"https://*.ngrok-free.dev",
"https://*.myshopify.com",
"https://cdn.shopify.com",
"https://esm.sh"
],
"redirect_domains": [
"https://*.myshopify.com",
"https://*.shopify.com"
],
"resource_domains": [
"https://esm.sh",
"https://cdn.shopify.com",
"https://*.shopify.com",
"https://*.youthtothepeople.com",
"https://*.laluer.com",
"https://*.glam-moda.com",
"https://incidecoder-content.storage.googleapis.com",
"https://media.kohlsimg.com",
"https://*.mercdn.net",
"https://*.bigcommerce.com",
"https://di2ponv0v5otw.cloudfront.net",
"https://placehold.co"
]
},
"ui": {
"resourceUri": "ui://widget/product-card.html"
},
"ui/resourceUri": "ui://widget/product-card.html"
},
"annotations": {
"destructiveHint": false,
"openWorldHint": false,
"readOnlyHint": true
},
"description": "Compare two or more products side by side. Use when the user asks to compare, says 'X vs Y', or wants to decide between options. Do not use for single product lookup \u2014 use get_product instead. Returns structured comparison with shared attributes, differences, tradeoffs, and a decision hint.",
"execution": {
"taskSupport": "forbidden"
},
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"products": {
"description": "Product titles or SKUs to compare (e.g. ['MIRA', 'CryoSculpt'])",
"items": {
"maxLength": 200,
"type": "string"
},
"maxItems": 5,
"minItems": 2,
"type": "array"
}
},
"required": [
"products"
],
"type": "object"
},
"name": "compare_products"
},
{
"annotations": {
"destructiveHint": false,
"openWorldHint": true,
"readOnlyHint": false
},
"description": "Create a checkout URL for one or more products. Pass variant IDs (items) and/or product URLs (product_urls). When a product URL is provided (e.g. https://laluer.com/products/mira), the tool resolves it to a variant ID automatically \u2014 no catalog import needed. Supports discount codes, cart notes, and selling plans. Do not use unless the user wants to buy \u2014 use search_products or skincare_recommend first. Returns a direct Shopify checkout link the user can click to buy.",
"execution": {
"taskSupport": "forbidden"
},
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"discount_code": {
"description": "Discount code to apply (e.g. 'WELCOME10')",
"maxLength": 50,
"type": "string"
},
"items": {
"description": "Products to add to cart by variant ID",
"items": {
"additionalProperties": false,
"properties": {
"quantity": {
"default": 1,
"description": "Quantity (default 1)",
"maximum": 10,
"minimum": 1,
"type": "integer"
},
"selling_plan_id": {
"description": "Shopify selling plan ID for subscriptions",
"type": "string"
},
"variant_id": {
"description": "Shopify variant ID (numeric or GID format)",
"type": [
"string",
"number"
]
}
},
"required": [
"variant_id"
],
"type": "object"
},
"maxItems": 20,
"type": "array"
},
"note": {
"description": "Cart note visible to the merchant",
"maxLength": 500,
"type": "string"
},
"product_urls": {
"description": "Products to add to cart by URL \u2014 resolved to variant IDs automatically",
"items": {
"additionalProperties": false,
"properties": {
"quantity": {
"default": 1,
"description": "Quantity (default 1)",
"maximum": 10,
"minimum": 1,
"type": "integer"
},
"url": {
"description": "Shopify product URL (e.g. https://store.com/products/handle)",
"format": "uri",
"type": "string"
}
},
"required": [
"url"
],
"type": "object"
},
"maxItems": 20,
"type": "array"
}
},
"type": "object"
},
"name": "create_checkout"
},
{
"annotations": {
"destructiveHint": false,
"openWorldHint": false,
"readOnlyHint": true
},
"description": "Check which products are compatible with a given product. For devices, shows required consumables (e.g., conductive gel for MIRA). For topicals, shows which devices they work with. Use when a customer asks 'what gel do I need with MIRA?' or 'does this serum work with CryoSculpt?'",
"execution": {
"taskSupport": "forbidden"
},
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"product": {
"description": "Product name or SKU to check compatibility for",
"maxLength": 200,
"type": "string"
}
},
"required": [
"product"
],
"type": "object"
},
"name": "check_compatibility"
},
{
"annotations": {
"destructiveHint": false,
"openWorldHint": false,
"readOnlyHint": true
},
"description": "Check if a product is currently available. Uses Shopify Storefront API to verify real-time stock status. Use when a customer asks 'is MIRA in stock?' or before recommending a product.",
"execution": {
"taskSupport": "forbidden"
},
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"product": {
"description": "Product name or SKU to check availability for",
"maxLength": 200,
"type": "string"
}
},
"required": [
"product"
],
"type": "object"
},
"name": "check_inventory"
},
{
"annotations": {
"destructiveHint": false,
"openWorldHint": false,
"readOnlyHint": true
},
"description": "Show available bundles, deals, and ask about discount codes. Use when a customer asks about deals, bundles, savings, or says 'do you have any discounts?' Also use when multiple items are in cart to suggest bundle savings. Always ask if the customer has a discount code.",
"execution": {
"taskSupport": "forbidden"
},
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"discount_code": {
"description": "Customer's discount code if they have one",
"maxLength": 50,
"type": "string"
}
},
"type": "object"
},
"name": "deals_discounts"
}
]
}
},
"url": "https://searchshopai-mcp.fly.dev/mcp/la-luer"
},
"latency_ms": 29.59,
"status": "ok"
},
"transport_compliance_probe": {
"details": {
"bad_protocol_error": null,
"bad_protocol_headers": {
"content-type": "application/json"
},
"bad_protocol_payload": {
"error": {
"code": -32000,
"message": "Bad Request: Unsupported protocol version: 1999-99-99 (supported versions: 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07)"
},
"id": null,
"jsonrpc": "2.0"
},
"bad_protocol_status_code": 400,
"delete_error": null,
"delete_status_code": null,
"expired_session_error": null,
"expired_session_status_code": null,
"issues": [
"missing_session_id",
"missing_protocol_header"
],
"last_event_id_visible": false,
"protocol_header_present": false,
"requested_protocol_version": "2025-03-26",
"session_id_present": false,
"transport": "streamable-http"
},
"latency_ms": 13.47,
"status": "warning"
},
"utility_coverage_probe": {
"details": {
"completions": {
"advertised": false,
"live_probe": "not_executed",
"sample_target": {
"type": "resource",
"uri": "ui://widget/product-card.html"
}
},
"initialize_capability_keys": [
"resources",
"tools"
],
"pagination": {
"metadata_signal": false,
"next_cursor_methods": [],
"supported": false
},
"tasks": {
"advertised": false,
"http_status": 200,
"probe_status": "missing"
}
},
"latency_ms": 12.58,
"status": "missing"
}
},
"failures": {
"oauth_authorization_server": {
"reason": "no_authorization_server"
},
"oauth_protected_resource": {
"error": "Client error '404 Not Found' for url 'https://searchshopai-mcp.fly.dev/.well-known/oauth-protected-resource'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404",
"url": "https://searchshopai-mcp.fly.dev/.well-known/oauth-protected-resource"
},
"openid_configuration": {
"reason": "no_authorization_server"
},
"server_card": {
"error": "Client error '404 Not Found' for url 'https://searchshopai-mcp.fly.dev/.well-known/mcp/server-card.json'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404",
"url": "https://searchshopai-mcp.fly.dev/.well-known/mcp/server-card.json"
}
},
"remote_url": "https://searchshopai-mcp.fly.dev/mcp/la-luer",
"server_card_payload": null,
"server_identifier": "ai.searchshop.www/la-luer"
}