Skip to main content
Glama

Google Calendar MCP

import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { OAuth2Client } from "google-auth-library"; import { BaseToolHandler } from "./BaseToolHandler.js"; import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js"; import { GetCurrentTimeInput } from "../../tools/registry.js"; export class GetCurrentTimeHandler extends BaseToolHandler { async runTool(args: any, _oauth2Client: OAuth2Client): Promise<CallToolResult> { // Validate arguments using schema const validArgs = args as GetCurrentTimeInput; const now = new Date(); // If no timezone provided, return UTC and system timezone info // This is safer for HTTP mode where server timezone may not match user const requestedTimeZone = validArgs.timeZone; const systemTimeZone = this.getSystemTimeZone(); let result: any; if (requestedTimeZone) { // Validate the timezone if (!this.isValidTimeZone(requestedTimeZone)) { throw new McpError( ErrorCode.InvalidRequest, `Invalid timezone: ${requestedTimeZone}. Use IANA timezone format like 'America/Los_Angeles' or 'UTC'.` ); } result = { currentTime: { utc: now.toISOString(), timestamp: now.getTime(), requestedTimeZone: { timeZone: requestedTimeZone, rfc3339: this.formatDateInTimeZone(now, requestedTimeZone), humanReadable: this.formatHumanReadable(now, requestedTimeZone), offset: this.getTimezoneOffset(now, requestedTimeZone) } } }; } else { // No timezone requested - provide UTC and system info for reference result = { currentTime: { utc: now.toISOString(), timestamp: now.getTime(), systemTimeZone: { timeZone: systemTimeZone, rfc3339: this.formatDateInTimeZone(now, systemTimeZone), humanReadable: this.formatHumanReadable(now, systemTimeZone), offset: this.getTimezoneOffset(now, systemTimeZone) }, note: "System timezone shown. For HTTP mode, specify timeZone parameter for user's local time." } }; } return { content: [{ type: "text", text: JSON.stringify(result, null, 2), }], }; } private getSystemTimeZone(): string { try { return Intl.DateTimeFormat().resolvedOptions().timeZone; } catch { return 'UTC'; // Fallback to UTC if system timezone detection fails } } private isValidTimeZone(timeZone: string): boolean { try { Intl.DateTimeFormat(undefined, { timeZone }); return true; } catch { return false; } } private formatDateInTimeZone(date: Date, timeZone: string): string { const offset = this.getTimezoneOffset(date, timeZone); // Remove milliseconds from ISO string for proper RFC3339 format const isoString = date.toISOString().replace(/\.\d{3}Z$/, ''); return isoString + offset; } private formatHumanReadable(date: Date, timeZone: string): string { const formatter = new Intl.DateTimeFormat('en-US', { timeZone: timeZone, weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit', timeZoneName: 'long' }); return formatter.format(date); } private getTimezoneOffset(_date: Date, timeZone: string): string { try { const offsetMinutes = this.getTimezoneOffsetMinutes(timeZone); if (offsetMinutes === 0) { return 'Z'; } const offsetHours = Math.floor(Math.abs(offsetMinutes) / 60); const offsetMins = Math.abs(offsetMinutes) % 60; const sign = offsetMinutes >= 0 ? '+' : '-'; return `${sign}${offsetHours.toString().padStart(2, '0')}:${offsetMins.toString().padStart(2, '0')}`; } catch { return 'Z'; // Fallback to UTC if offset calculation fails } } private getTimezoneOffsetMinutes(timeZone: string): number { // Use the timezone offset from a date's time representation in different zones const date = new Date(); // Get local time for the target timezone const targetTimeString = new Intl.DateTimeFormat('sv-SE', { timeZone: timeZone, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }).format(date); // Get UTC time string const utcTimeString = new Intl.DateTimeFormat('sv-SE', { timeZone: 'UTC', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }).format(date); // Parse both times and calculate difference const targetTime = new Date(targetTimeString.replace(' ', 'T') + 'Z').getTime(); const utcTimeParsed = new Date(utcTimeString.replace(' ', 'T') + 'Z').getTime(); return (targetTime - utcTimeParsed) / (1000 * 60); } }

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/nspady/google-calendar-mcp'

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