UNPKG

automagik-genie

Version:

Self-evolving AI agent orchestration framework with Model Context Protocol support

281 lines (239 loc) 7.29 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="icon" type="image/svg+xml" href="/favicon-genie-light.svg" media="(prefers-color-scheme: light)"> <link rel="icon" type="image/svg+xml" href="/favicon-genie-dark.svg" media="(prefers-color-scheme: dark)"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Authorize Genie MCP Access</title> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Alegreya+Sans:wght@300;400;500;700;800;900&family=Manrope:wght@200;300;400;500;600;700;800&family=Chivo+Mono:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet"> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); display: flex; justify-content: center; align-items: center; min-height: 100vh; padding: 20px; } h1, h2, h3, h4, h5, h6 { font-family: 'Alegreya Sans', sans-serif; } code, pre, .monospace { font-family: 'Chivo Mono', 'Courier New', monospace; } .container { background: white; border-radius: 12px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); max-width: 480px; width: 100%; padding: 40px; } .logo { text-align: center; margin-bottom: 30px; } .logo h1 { font-size: 32px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; font-weight: 700; } .client-info { background: #f7fafc; border-left: 4px solid #667eea; padding: 16px; margin-bottom: 24px; border-radius: 4px; } .client-info h2 { font-size: 18px; color: #2d3748; margin-bottom: 8px; } .client-info p { font-size: 14px; color: #718096; margin-bottom: 4px; } .scopes { margin-bottom: 24px; } .scopes h3 { font-size: 16px; color: #2d3748; margin-bottom: 12px; } .scope-list { background: #f7fafc; border-radius: 4px; padding: 12px; } .scope-item { display: flex; align-items: center; padding: 8px 0; color: #4a5568; font-size: 14px; } .scope-item::before { content: '✓'; color: #48bb78; font-weight: bold; margin-right: 8px; } .auth-form { margin-bottom: 24px; } .buttons { display: flex; gap: 12px; } button { flex: 1; padding: 14px 24px; font-size: 16px; font-weight: 600; border: none; border-radius: 6px; cursor: pointer; transition: all 0.2s; } .btn-authorize { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; } .btn-authorize:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4); } .btn-authorize:disabled { background: #cbd5e0; cursor: not-allowed; transform: none; } .btn-deny { background: #e2e8f0; color: #4a5568; } .btn-deny:hover { background: #cbd5e0; } .error { background: #fff5f5; border-left: 4px solid #f56565; padding: 12px 16px; margin-bottom: 20px; border-radius: 4px; color: #c53030; font-size: 14px; display: none; } .error.show { display: block; } .security-note { margin-top: 24px; padding-top: 24px; border-top: 1px solid #e2e8f0; text-align: center; font-size: 12px; color: #718096; } .security-note a { color: #667eea; text-decoration: none; } .security-note a:hover { text-decoration: underline; } </style> </head> <body> <div class="container"> <div class="logo"> <h1>🧞 Genie MCP</h1> </div> <div class="client-info"> <h2 id="clientName">Loading...</h2> <p>wants to access your Genie MCP server</p> </div> <div class="scopes"> <h3>This application will be able to:</h3> <div class="scope-list" id="scopeList"> <!-- Scopes will be inserted here --> </div> </div> <div class="error" id="errorMessage"></div> <form class="auth-form" id="authForm" method="POST" action="/oauth2/authorize/consent"> <input type="hidden" name="request_id" id="requestId"> <div class="buttons"> <button type="button" class="btn-deny" onclick="denyAccess()">Deny</button> <button type="submit" class="btn-authorize" id="authorizeBtn">Authorize</button> </div> </form> <div class="security-note"> <p> 🔒 This connection uses OAuth 2.0 with PKCE for security. </p> </div> </div> <script> // Get values from data attributes (injected server-side) const container = document.querySelector('.container'); const clientName = container.dataset.clientName || 'Unknown Application'; const scopes = (container.dataset.scopes || '').split(' ').filter(s => s); // Parse URL for error parameters only const urlParams = new URLSearchParams(window.location.search); const error = urlParams.get('error'); const errorDescription = urlParams.get('error_description'); // Display client name document.getElementById('clientName').textContent = clientName; // Display scopes const scopeDescriptions = { 'mcp:read': 'Read your Genie agents and tools', 'mcp:write': 'Execute agent workflows and modify sessions' }; const scopeList = document.getElementById('scopeList'); scopes.forEach(scope => { const div = document.createElement('div'); div.className = 'scope-item'; div.textContent = scopeDescriptions[scope] || scope; scopeList.appendChild(div); }); // Show error if present if (error) { const errorEl = document.getElementById('errorMessage'); errorEl.textContent = errorDescription || 'Authorization failed. Please try again.'; errorEl.classList.add('show'); } // Form submits naturally - no JavaScript needed // OAuth redirects work best with standard form submission // Handle deny function denyAccess() { if (confirm('Are you sure you want to deny access?')) { // Get redirect info from form action (it has the query params) const form = document.getElementById('authForm'); const actionUrl = new URL(form.action, window.location.origin); const redirectUri = actionUrl.searchParams.get('redirect_uri'); const state = actionUrl.searchParams.get('state'); if (redirectUri && state) { const denyUrl = `${redirectUri}?error=access_denied&error_description=User denied authorization&state=${state}`; window.location.href = denyUrl; } } } </script> </body> </html>