Code Snippet Server

by ngeojiajun
Verified
  • scripts
import { google } from "googleapis"; import { OAuth2Client } from "google-auth-library"; import * as fs from "fs/promises"; import * as path from "path"; import * as http from "http"; import { fileURLToPath } from "url"; import { IncomingMessage, ServerResponse } from "http"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const CREDENTIALS_PATH = path.join( __dirname, "../credentials/google-credentials.json" ); const TOKEN_PATH = path.join(__dirname, "../credentials/google-token.json"); const CALLBACK_PORT = 3333; const CALLBACK_PATH = "/oauth2callback"; interface GoogleCredentials { installed: { client_id: string; client_secret: string; redirect_uris: string[]; }; } interface AuthCallbackResult { code: string; server: http.Server; } type AuthCallbackResolve = (value: AuthCallbackResult) => void; type AuthCallbackReject = (reason: Error) => void; async function handleAuthCallback( req: IncomingMessage, res: ServerResponse, resolve: AuthCallbackResolve, reject: AuthCallbackReject, server: http.Server ): Promise<void> { try { if (!req.url) { throw new Error("No URL in request"); } const url = new URL(req.url, `http://localhost:${CALLBACK_PORT}`); if (url.pathname !== CALLBACK_PATH) { return; } const code = url.searchParams.get("code"); if (!code) { throw new Error("No authorization code received"); } res.writeHead(200, { "Content-Type": "text/html" }); res.end(` <html> <body> <h1>Authentication successful!</h1> <p>You can close this window and return to the terminal.</p> <script>window.close()</script> </body> </html> `); resolve({ code, server }); } catch (error) { const err = error instanceof Error ? error : new Error(String(error)); console.error("Callback error:", err.message); res.writeHead(400, { "Content-Type": "text/plain" }); res.end("Authentication failed"); reject(err); } } async function waitForCallback(oAuth2Client: OAuth2Client): Promise<string> { return new Promise<string>((resolve, reject) => { const server = http.createServer((req, res) => { handleAuthCallback( req, res, ({ code }) => { server.close(); resolve(code); }, (error) => { server.close(); reject(error); }, server ).catch(reject); }); server.listen(CALLBACK_PORT, () => { const address = server.address(); if (!address || typeof address === "string") { reject(new Error("Failed to get server address")); return; } console.log(`Callback server listening on port ${address.port}`); }); server.on("error", (error: Error) => { console.error("Server error:", error.message); reject(error); }); }); } async function openBrowser(url: string): Promise<void> { const start = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open"; const { exec } = await import("child_process"); return new Promise<void>((resolve, reject) => { exec(`${start} "${url}"`, (error) => { if (error) { console.warn("Failed to open browser automatically:", error.message); console.log("Please open this URL manually:", url); } resolve(); }); }); } async function authenticate(): Promise<void> { try { // Check if credentials exist try { await fs.access(CREDENTIALS_PATH); } catch { throw new Error( "Google credentials not found. Please download OAuth 2.0 credentials from Google Cloud Console " + "and save them as credentials/google-credentials.json" ); } // Read and parse credentials const credentialsData = await fs.readFile(CREDENTIALS_PATH, "utf-8"); const credentials = JSON.parse(credentialsData) as GoogleCredentials; const { client_secret, client_id } = credentials.installed; // Create OAuth2 client const redirect_uri = `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH}`; const oAuth2Client = new google.auth.OAuth2( client_id, client_secret, redirect_uri ); // Generate auth URL with all necessary scopes const authUrl = oAuth2Client.generateAuthUrl({ access_type: "offline", scope: [ // Gmail scopes "https://www.googleapis.com/auth/gmail.readonly", "https://www.googleapis.com/auth/gmail.send", "https://www.googleapis.com/auth/gmail.compose", "https://www.googleapis.com/auth/gmail.modify", "https://www.googleapis.com/auth/gmail.labels", // Calendar scopes "https://www.googleapis.com/auth/calendar.readonly", "https://www.googleapis.com/auth/calendar.events.readonly", // Drive scope "https://www.googleapis.com/auth/drive.readonly", ], }); // Start authentication process console.log("\nšŸ” Starting Google Authentication"); console.log("1. Opening your browser to complete authentication..."); await openBrowser(authUrl); // Wait for the OAuth2 callback console.log("2. Waiting for authentication...\n"); const code = await waitForCallback(oAuth2Client); // Exchange code for tokens const response = await oAuth2Client.getToken(code); const tokens = response.tokens; if (!tokens) { throw new Error("Failed to get tokens from Google"); } // Save the tokens await fs.writeFile(TOKEN_PATH, JSON.stringify(tokens, null, 2)); console.log("\nāœ… Authentication successful!"); console.log("Token stored in:", TOKEN_PATH); console.log("\nYou can now start/restart the MCP server."); process.exit(0); } catch (error) { console.error( "\nāŒ Authentication failed:", error instanceof Error ? error.message : error ); process.exit(1); } } authenticate().catch((error) => { console.error("Fatal error:", error); process.exit(1); });