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) => ({
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
}[c]!));
}