Skip to main content
Glama

Google Drive MCP Server

by ducla5
credential-manager.ts4.55 kB
import fs from 'fs/promises'; import path from 'path'; import { AuthCredentials } from '../types/auth.js'; /** * Secure credential management for Google Drive authentication * Handles loading, validation, and secure storage of credentials */ export class CredentialManager { private credentialsPath: string; private credentials: AuthCredentials | null = null; constructor(credentialsPath: string = './config/credentials.json') { this.credentialsPath = credentialsPath; } /** * Load credentials from file or environment variables */ async loadCredentials(): Promise<AuthCredentials> { // Try environment variables first (more secure for production) const envCredentials = this.loadFromEnvironment(); if (envCredentials) { this.credentials = envCredentials; return envCredentials; } // Fallback to file-based credentials try { const credentialsData = await fs.readFile(this.credentialsPath, 'utf-8'); const fileCredentials = JSON.parse(credentialsData); this.validateCredentials(fileCredentials); this.credentials = fileCredentials; return fileCredentials; } catch (error) { throw new Error(`Failed to load credentials: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Load credentials from environment variables */ private loadFromEnvironment(): AuthCredentials | null { const clientId = process.env.GOOGLE_CLIENT_ID; const clientSecret = process.env.GOOGLE_CLIENT_SECRET; const redirectUri = process.env.GOOGLE_REDIRECT_URI; if (!clientId || !clientSecret || !redirectUri) { return null; } const credentials: AuthCredentials = { clientId, clientSecret, redirectUri }; // Only add optional tokens if they exist if (process.env.GOOGLE_REFRESH_TOKEN) { credentials.refreshToken = process.env.GOOGLE_REFRESH_TOKEN; } if (process.env.GOOGLE_ACCESS_TOKEN) { credentials.accessToken = process.env.GOOGLE_ACCESS_TOKEN; } return credentials; } /** * Validate credentials structure and required fields */ private validateCredentials(credentials: any): void { if (!credentials || typeof credentials !== 'object') { throw new Error('Invalid credentials format'); } const required = ['clientId', 'clientSecret', 'redirectUri']; const missing = required.filter(field => !credentials[field]); if (missing.length > 0) { throw new Error(`Missing required credential fields: ${missing.join(', ')}`); } // Validate format of fields if (typeof credentials.clientId !== 'string' || !credentials.clientId.trim()) { throw new Error('Invalid clientId format'); } if (typeof credentials.clientSecret !== 'string' || !credentials.clientSecret.trim()) { throw new Error('Invalid clientSecret format'); } if (typeof credentials.redirectUri !== 'string' || !this.isValidUrl(credentials.redirectUri)) { throw new Error('Invalid redirectUri format'); } } /** * Validate URL format */ private isValidUrl(url: string): boolean { try { new URL(url); return true; } catch { return false; } } /** * Get current credentials */ getCredentials(): AuthCredentials { if (!this.credentials) { throw new Error('Credentials not loaded. Call loadCredentials() first.'); } return this.credentials; } /** * Create sample credentials file for setup */ async createSampleCredentialsFile(): Promise<void> { const sampleCredentials = { clientId: "your-google-client-id.apps.googleusercontent.com", clientSecret: "your-google-client-secret", redirectUri: "http://localhost:8080/callback", refreshToken: "optional-refresh-token", accessToken: "optional-access-token" }; const credentialsDir = path.dirname(this.credentialsPath); await fs.mkdir(credentialsDir, { recursive: true }); await fs.writeFile( this.credentialsPath, JSON.stringify(sampleCredentials, null, 2), { mode: 0o600 } // Restrict file permissions ); console.log(`Sample credentials file created at: ${this.credentialsPath}`); console.log('Please update it with your actual Google OAuth credentials.'); } /** * Check if credentials file exists */ async credentialsExist(): Promise<boolean> { try { await fs.access(this.credentialsPath); return true; } catch { return false; } } }

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/ducla5/gdriver-mcp'

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