/** * Minimal Node HTTP server hosting Better Auth. * * All Better Auth routes (social sign-in, OAuth2/OIDC, DCR `/oauth2/register`, * JWKS, discovery) are served by its node handler. We add a tiny login page * (the OIDC `loginPage` target) with Google/Apple buttons, and a health check. */ import { createServer } from "node:http"; import { toNodeHandler } from "better-auth/node"; import { auth } from "./auth.js"; const PORT = Number(process.env.PORT ?? 8080); const handler = toNodeHandler(auth); function loginPage(rawSearch: string): string { // Better Auth's oauth-provider redirects here with the original, signed // authorize params in the query. After sign-in we must hand them back to the // authorize endpoint verbatim so it resumes and issues the code. If there's no // OAuth context (a stray visit), fall back to the portal. const cb = rawSearch ? "/api/auth/oauth2/authorize" + rawSearch : "/portal"; const social = (provider: string, label: string) => ` `; return ` Sign in — Intervals.icu MCP

Sign in to Intervals.icu MCP

Connect your Intervals.icu account to use it from Claude.

${auth.options.socialProviders && "google" in auth.options.socialProviders ? social("google", "Continue with Google") : ""} ${auth.options.socialProviders && "apple" in auth.options.socialProviders ? social("apple", "Continue with Apple") : ""} `; } const server = createServer((req, res) => { const url = new URL(req.url ?? "/", "http://localhost"); if (url.pathname !== "/healthz") { // Request-level trace (path only, no query — avoids logging codes/tokens). // eslint-disable-next-line no-console console.log(`[req] ${req.method} ${url.pathname}`); res.on("finish", () => console.log(`[res] ${req.method} ${url.pathname} -> ${res.statusCode}`)); } if (url.pathname === "/healthz") { res.writeHead(200, { "content-type": "application/json" }); res.end('{"status":"ok"}'); return; } if (url.pathname === "/login" && req.method === "GET") { res.writeHead(200, { "content-type": "text/html; charset=utf-8" }); res.end(loginPage(url.search)); return; } // Everything else -> Better Auth (async handler). void handler(req, res); }); server.listen(PORT, () => { // eslint-disable-next-line no-console console.log(`intervalsicu-mcp-auth listening on :${PORT}`); });