Skip to main content
Glama
login-ui.ts7.31 kB
export function generateLoginPage(params: Record<string, string | undefined>, error?: string): string { const hiddenInputs = Object.entries(params) .filter(([, v]) => v !== undefined) .map(([k, v]) => `<input type="hidden" name="${htmlEscape(k)}" value="${htmlEscape(v!)}" />`) .join('\n'); const errorMessage = error ? ` <div class="alert alert-error"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 16 16"> <path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/> </svg> <span>${htmlEscape(error)}</span> </div> ` : ''; return `<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Umbrella MCP Authentication</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 20px; } .login-container { background: white; border-radius: 20px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); overflow: hidden; width: 100%; max-width: 400px; } .login-header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 40px 30px; text-align: center; color: white; } .logo { width: 120px; height: 80px; background: white; border-radius: 15px; margin: 0 auto 20px; display: flex; align-items: center; justify-content: center; padding: 10px; } .logo img { max-width: 100%; max-height: 100%; object-fit: contain; } .login-header h1 { font-size: 24px; font-weight: 600; margin-bottom: 10px; } .login-header p { font-size: 14px; opacity: 0.9; } .login-form { padding: 40px 30px; } .form-group { margin-bottom: 25px; } .form-group label { display: block; margin-bottom: 8px; color: #374151; font-size: 14px; font-weight: 500; } .form-group input { width: 100%; padding: 12px 16px; border: 2px solid #e5e7eb; border-radius: 10px; font-size: 15px; transition: all 0.3s ease; background: #f9fafb; } .form-group input:focus { outline: none; border-color: #667eea; background: white; } .form-group input::placeholder { color: #9ca3af; } .submit-btn { width: 100%; padding: 14px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border: none; border-radius: 10px; color: white; font-size: 16px; font-weight: 600; cursor: pointer; transition: transform 0.2s ease, box-shadow 0.2s ease; margin-top: 10px; } .submit-btn:hover { transform: translateY(-2px); box-shadow: 0 10px 20px rgba(102, 126, 234, 0.4); } .submit-btn:active { transform: translateY(0); } .alert { padding: 12px 16px; border-radius: 10px; margin-bottom: 20px; display: flex; align-items: center; gap: 10px; font-size: 14px; } .alert-error { background: #fee; color: #dc2626; border: 1px solid #fca5a5; } .forgot-password { text-align: center; margin-top: 20px; } .forgot-password a { color: #667eea; text-decoration: none; font-size: 14px; font-weight: 500; } .forgot-password a:hover { text-decoration: underline; } .mcp-badge { background: rgba(102, 126, 234, 0.1); color: #667eea; padding: 4px 8px; border-radius: 4px; font-size: 12px; font-weight: 600; display: inline-block; margin-top: 5px; } @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .login-container { animation: fadeIn 0.5s ease-out; } </style> </head> <body> <div class="login-container"> <div class="login-header"> <div class="logo"> <img src="/assets/umbrella-logo.svg" alt="Umbrella Logo" /> </div> <h1>Umbrella Cost Management</h1> <p>Sign in to continue</p> <span class="mcp-badge">MCP AUTHENTICATION</span> </div> <div class="login-form"> ${errorMessage} <form method="POST" action="/login"> ${hiddenInputs} <div class="form-group"> <label for="username">Email Address</label> <input type="email" id="username" name="username" placeholder="you@company.com" required autocomplete="email" /> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" id="password" name="password" placeholder="Enter your password" required autocomplete="current-password" /> </div> <button type="submit" class="submit-btn">Sign In</button> </form> <div class="forgot-password"> <a href="https://umbrellacost.io/forgot_password" target="_blank">Forgot your password?</a> </div> </div> </div> </body> </html>`; } function htmlEscape(str: string): string { return String(str).replace(/[&<>"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]!)); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/daviddraiumbrella/invoice-monitoring'

If you have feedback or need assistance with the MCP directory API, please join our Discord server