.mcp-auth{display:inline-flex;align-items:center;gap:5px;font-size:11px;color:#d99a33;margin-top:5px}
.mcp-auth svg{width:12px;height:12px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.mcp-empty{font-size:12.5px;color:var(--text-muted);line-height:1.6;padding:22px 18px;text-align:center;border:1px dashed var(--border);border-radius:10px}
+ /* Connector state row: sits on its own line under the url so the button
+ never crowds the auth note (the old inline-styled button did). */
+ .mcp-state{display:flex;align-items:center;gap:10px;margin-top:8px;flex-wrap:wrap}
+ .mcp-btn{font:inherit;font-size:12px;font-weight:600;padding:5px 14px;border-radius:6px;
+ border:1px solid var(--border);background:var(--surface-3);color:var(--text);cursor:pointer;
+ transition:border-color .12s,background .12s}
+ .mcp-btn:hover:not(:disabled){border-color:var(--border-hover)}
+ .mcp-btn:disabled{opacity:.55;cursor:default}
+ .mcp-btn-primary{background:var(--accent);border-color:var(--accent);color:#fff}
+ .mcp-btn-primary:hover:not(:disabled){filter:brightness(1.08)}
+ .mcp-connected{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:600;color:#3fa45b}
+ .mcp-connected .dot{width:7px;height:7px;border-radius:50%;background:currentColor;flex:none}
.mcp-switch{position:relative;display:inline-block;width:44px;height:24px;flex-shrink:0}
.mcp-switch input{opacity:0;width:0;height:0}
.mcp-slider{position:absolute;cursor:pointer;inset:0;background:var(--surface-3);border:1px solid var(--border);border-radius:24px;transition:.2s}
@@ -1078,23 +1090,38 @@
MENU
box.innerHTML = servers.map(function(s) {
var checked = s.enabled ? 'checked' : '';
var badge = escHtml((s.transport || 'http').toUpperCase());
- var authNote = '';
- if (s.needs_auth) {
- var kind = s.auth === 'api_key' ? 'API key' : (s.auth === 'oauth' ? 'OAuth sign-in' : 'sign-in');
- authNote = '
Needs ' + kind + '
';
- }
var note = s.note ? '
' + escHtml(s.note) + '
' : '';
- // OAuth connectors get a "Sign in" button (only when enabled) that opens
- // the browser authorize flow — toggling on alone doesn't authenticate.
- var signinBtn = (s.enabled && s.needs_auth && s.auth === 'oauth') ?
- '' : '';
+ var lock = '';
+ var nm = escHtml(s.name);
+ // State machine, in the order a user actually experiences it:
+ // off → nothing (just the toggle)
+ // on + needs auth + !conn → why + how to fix it (Sign in)
+ // on + connected → Connected + a way back out (Disconnect)
+ // on + no auth needed → Connected (nothing to sign into)
+ var state = '';
+ if (s.enabled && s.needs_auth && !s.connected) {
+ var kind = s.auth === 'api_key' ? 'API key' : 'OAuth sign-in';
+ state = '