1<!doctype html> 2<html lang="en"> 3 <head> 4 <meta charset="UTF-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6
6<script> 7 // Stale-shell self-heal. 8 // 9 // The admin is a static SPA with content-hashed bundles and a catch-all 10 // rewrite (/* -> /index.html). When the app is redeployed the asset 11 // hashes change and the old bundles are removed. A browser still holding 12 // a cached index.html from a previous deploy then requests a now-missing 13 // /assets/index-<oldhash>.js; the rewrite answers it with index.html 14 // (HTTP 200, text/html), so the
14<script type="module"> receives HTML it 15 // cannot parse, React never mounts, and the user sees a blank page after 16 // a brief flash of the cached shell. index.html itself ships without a 17 // Cache-Control header (the static host exposes no header config), so 18 // browsers may keep serving the stale shell across reloads. 19 // 20 // window.__appBooted is set to true as the entry bundle starts executing 21 // (see src/main.tsx). If it never flips, the current shell failed to 22 // boot, so we reload once against a cache-busted URL to pull the live 23 // index.html + assets. The sessionStorage guard prevents reload loops 24 // when the failure is a genuine code error rather than a stale shell. 25 (function () { 26 var RELOAD_KEY = "__shellReloadAt"; 27 function recentlyReloaded() { 28 try { 29 return ( 30 Date.now() - (+sessionStorage.getItem(RELOAD_KEY) || 0) < 60000 31 ); 32 } catch (e) { 33 return false; 34 } 35 } 36 function selfHeal() { 37 if (window.__appBooted || recentlyReloaded()) return; 38 try { 39 sessionStorage.setItem(RELOAD_KEY, String(Date.now())); 40 } catch (e) {} 41 try { 42 var url = new URL(window.location.href); 43 url.searchParams.set("_r", Date.now().toString()); 44 window.location.replace(url.toString()); 45 } catch (e) { 46 window.location.reload(); 47 } 48 } 49 window.addEventListener( 50 "error", 51 function (event) { 52 var target = event && event.target; 53 if (target && target !== window && target.tagName === "SCRIPT") { 54 selfHeal(); 55 return; 56 } 57 var message = (event && event.message) || ""; 58 if ( 59 /SyntaxError|Unexpected token|expected expression|illegal char/i.test( 60 message, 61 ) 62 ) { 63 selfHeal(); 64 } 65 }, 66 true, 67 ); 68 window.addEventListener("load", function () { 69 setTimeout(function () { 70 var root = document.getElementById("root"); 71 if (!window.__appBooted && root && root.childElementCount === 0) { 72 selfHeal(); 73 } 74 }, 15000); 75 }); 76 })(); 77 </script>
77 78 <title>mcpMyAdmin</title> 79 <meta 80 name="description" 81 content="A hosted MCP server connecting Claude, ChatGPT, and Cursor to 40 databases â in your browser and on your phone, not just one laptop. Read-only by default." 82 /> 83 <meta name="robots" content="noindex" /> 84 <!-- 85 Absolute URLs below intentionally hardcode the PRODUCTION origin 86 (https://mcpmyadmin.ai): staging then canonicalizes to prod (correct 87 dedup behavior), and robots blocks staging anyway. 88 --> 89 <meta 90 property="og:title" 91 content="mcpMyAdmin â Query your database from Claude, on any device" 92 /> 93 <meta 94 property="og:description" 95 content="A hosted MCP server connecting Claude, ChatGPT, and Cursor to 40 databases â in your browser and on your phone, not just one laptop. Read-only by default." 96 /> 97 <meta property="og:type" content="website" /> 98 <meta property="og:url" content="https://mcpmyadmin.ai/" /> 99 <meta property="og:image" content="https://mcpmyadmin.ai/opengraph.jpg" /> 100 <meta name="twitter:card" content="summary_large_image" /> 101 <meta 102 name="twitter:title" 103 content="mcpMyAdmin â Query your database from Claude, on any device" 104 /> 105 <meta 106 name="twitter:description" 107 content="A hosted MCP server connecting Claude, ChatGPT, and Cursor to 40 databases â in your browser and on your phone, not just one laptop. Read-only by default." 108 /> 109 <meta name="twitter:image" content="https://mcpmyadmin.ai/opengraph.jpg" /> 110
110<script type="application/ld+json"> 111 [ 112 { 113 "@context": "https://schema.org", 114 "@type": "Organization", 115 "name": "ELEVETE LLC", 116 "alternateName": "orionOmega", 117 "url": "https://mcpmyadmin.ai/", 118 "logo": "https://mcpmyadmin.ai/icon-512.png" 119 }, 120 { 121 "@context": "https://schema.org", 122 "@type": "WebSite", 123 "name": "mcpMyAdmin", 124 "url": "https://mcpmyadmin.ai/" 125 }, 126 { 127 "@context": "https://schema.org", 128 "@type": "SoftwareApplication", 129 "name": "mcpMyAdmin", 130 "applicationCategory": "DeveloperApplication", 131 "operatingSystem": "Web", 132 "url": "https://mcpmyadmin.ai/", 133 "description": "A hosted MCP server connecting Claude, ChatGPT, and Cursor to 40 databases â in your browser and on your phone, not just one laptop. Read-only by default.", 134 "offers": { 135 "@type": "Offer", 136 "price": "5.00", 137 "priceCurrency": "USD", 138 "description": "per seat per month, free trial" 139 } 140 } 141 ] 142 </script>
142 143 <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> 144 <link rel="icon" type="image/x-icon" href="/favicon.ico" sizes="any" /> 145 <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png" /> 146 <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" /> 147 <link rel="icon" type="image/png" sizes="48x48" href="/favicon-48.png" /> 148 <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" /> 149 <link rel="manifest" href="/site.webmanifest" /> 150 <meta 151 name="theme-color" 152 content="#22272F" 153 media="(prefers-color-scheme: dark)" 154 /> 155 <meta 156 name="theme-color" 157 content="#F5F6F8" 158 media="(prefers-color-scheme: light)" 159 /> 160 <!-- 161 Resolves the appearance preference before first paint, mirroring the 162 ThemeProvider default in main.tsx: an explicit stored choice wins, 163 otherwise follow the OS. Without this a light-OS visitor gets a dark 164 frame until next-themes hydrates. Runs synchronously in <head> so the 165 class is on <html> before anything paints. 166 --> 167
167<script> 168 (function () { 169 try { 170 var stored = localStorage.getItem("theme") || "system"; 171 var resolved = 172 stored === "system" 173 ? window.matchMedia("(prefers-color-scheme: light)").matches 174 ? "light" 175 : "dark" 176 : stored; 177 document.documentElement.classList.add( 178 resolved === "light" ? "light" : "dark", 179 ); 180 } catch (e) { 181 document.documentElement.classList.add("dark"); 182 } 183 })(); 184 </script>
184 185 <link rel="preconnect" href="https://fonts.googleapis.com" /> 186 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> 187 <link 188 href="https://fonts.googleapis.com/css2?family=Inter:[email protected]&display=swap" 189 rel="stylesheet" 190 /> 191
191<script type="module" crossorigin src="/assets/index-DLG46iSl.js"></script>
191 192 <link rel="stylesheet" crossorigin href="/assets/index-BpcFk1mw.css"> 193 </head> 194 <body> 195 <div id="root"></div> 196 </body> 197</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.