@coretext-ai/qa-gsuite-f47ac10b-58cc-4372-a567-0e02b2c3d479
Version:
MCP server with GSuite (Contacts, Drive, Gmail, Calendar) integration
624 lines • 28.3 kB
JavaScript
import { Logger } from '../services/logger.js';
export class GoogleCalendarTools {
constructor(client) {
this.initialized = false;
this.client = client;
// Get logger from client if available, otherwise create fallback
this.logger = client.logger || new Logger({
logLevel: 'ERROR',
component: 'tools',
enableConsole: true,
enableShipping: false,
serverName: ''
});
}
async ensureInitialized() {
if (!this.initialized) {
// Log tools initialization now that client is ready
this.logger.info('TOOLS_INIT', 'Tools instance initialization started', {
integration: 'google-calendar',
isOAuth: true
});
this.logger.info('CLIENT_INITIALIZATION', 'Starting client initialization', {
isOAuth: true
});
await this.client.initialize();
this.initialized = true;
this.logger.info('CLIENT_INITIALIZATION', 'Client initialization completed', {
initialized: this.initialized
});
}
}
getToolDefinitions() {
return [
{
name: 'google-calendar_list_calendars',
description: 'Returns the calendars on the user's calendar list',
inputSchema: {
type: 'object',
properties: {
maxResults: {
type: 'number',
description: 'Maximum number of entries returned (default 100, max 250)'
},
minAccessRole: {
type: 'string',
description: 'The minimum access role for the user in the returned entries (freeBusyReader, reader, writer, owner)'
},
pageToken: {
type: 'string',
description: 'Token specifying which result page to return'
},
showDeleted: {
type: 'boolean',
description: 'Whether to include deleted calendar list entries in the result'
},
showHidden: {
type: 'boolean',
description: 'Whether to show hidden entries'
},
},
required: []
}
},
{
name: 'google-calendar_get_calendar',
description: 'Returns metadata for a calendar',
inputSchema: {
type: 'object',
properties: {
calendarId: {
type: 'string',
description: 'Calendar identifier. Use 'primary' for the primary calendar'
},
},
required: ['calendarId']
}
},
{
name: 'google-calendar_create_calendar',
description: 'Creates a secondary calendar',
inputSchema: {
type: 'object',
properties: {
summary: {
type: 'string',
description: 'Title of the calendar'
},
description: {
type: 'string',
description: 'Description of the calendar'
},
location: {
type: 'string',
description: 'Geographic location of the calendar'
},
timeZone: {
type: 'string',
description: 'The time zone of the calendar (e.g., 'America/New_York')'
},
},
required: ['summary',]
}
},
{
name: 'google-calendar_update_calendar',
description: 'Updates metadata for a calendar',
inputSchema: {
type: 'object',
properties: {
calendarId: {
type: 'string',
description: 'Calendar identifier'
},
summary: {
type: 'string',
description: 'Title of the calendar'
},
description: {
type: 'string',
description: 'Description of the calendar'
},
location: {
type: 'string',
description: 'Geographic location of the calendar'
},
timeZone: {
type: 'string',
description: 'The time zone of the calendar'
},
},
required: ['calendarId',]
}
},
{
name: 'google-calendar_delete_calendar',
description: 'Deletes a secondary calendar',
inputSchema: {
type: 'object',
properties: {
calendarId: {
type: 'string',
description: 'Calendar identifier'
},
},
required: ['calendarId']
}
},
{
name: 'google-calendar_list_events',
description: 'Returns events on the specified calendar',
inputSchema: {
type: 'object',
properties: {
calendarId: {
type: 'string',
description: 'Calendar identifier. Use 'primary' for the primary calendar'
},
maxResults: {
type: 'number',
description: 'Maximum number of events returned (default 250, max 2500)'
},
orderBy: {
type: 'string',
description: 'Order by the start time or last modification time (startTime, updated)'
},
pageToken: {
type: 'string',
description: 'Token specifying which result page to return'
},
q: {
type: 'string',
description: 'Free text search terms to find events'
},
showDeleted: {
type: 'boolean',
description: 'Whether to include deleted events'
},
singleEvents: {
type: 'boolean',
description: 'Whether to expand recurring events into instances'
},
timeMax: {
type: 'string',
description: 'Upper bound for event's start time (RFC3339 timestamp)'
},
timeMin: {
type: 'string',
description: 'Lower bound for event's end time (RFC3339 timestamp)'
},
timeZone: {
type: 'string',
description: 'Time zone used in the response'
},
},
required: ['calendarId',]
}
},
{
name: 'google-calendar_get_event',
description: 'Returns an event',
inputSchema: {
type: 'object',
properties: {
calendarId: {
type: 'string',
description: 'Calendar identifier. Use 'primary' for the primary calendar'
},
eventId: {
type: 'string',
description: 'Event identifier'
},
timeZone: {
type: 'string',
description: 'Time zone used in the response'
},
},
required: ['calendarId', 'eventId',]
}
},
{
name: 'google-calendar_create_event',
description: 'Creates an event',
inputSchema: {
type: 'object',
properties: {
calendarId: {
type: 'string',
description: 'Calendar identifier. Use 'primary' for the primary calendar'
},
summary: {
type: 'string',
description: 'Title of the event'
},
description: {
type: 'string',
description: 'Description of the event'
},
location: {
type: 'string',
description: 'Geographic location of the event'
},
start: {
type: 'object',
description: 'Start time of the event. Use 'date' for all-day events or 'dateTime' with timeZone'
},
end: {
type: 'object',
description: 'End time of the event. Use 'date' for all-day events or 'dateTime' with timeZone'
},
attendees: {
type: 'array',
description: 'List of attendees with email addresses'
},
reminders: {
type: 'object',
description: 'Information about the event's reminders'
},
recurrence: {
type: 'array',
description: 'List of RRULE, EXRULE, RDATE and EXDATE lines for recurring event'
},
sendNotifications: {
type: 'boolean',
description: 'Whether to send notifications about the creation of the new event'
},
sendUpdates: {
type: 'string',
description: 'Whether to send notifications to attendees (all, externalOnly, none)'
},
},
required: ['calendarId', 'summary', 'start', 'end',]
}
},
{
name: 'google-calendar_update_event',
description: 'Updates an event',
inputSchema: {
type: 'object',
properties: {
calendarId: {
type: 'string',
description: 'Calendar identifier. Use 'primary' for the primary calendar'
},
eventId: {
type: 'string',
description: 'Event identifier'
},
summary: {
type: 'string',
description: 'Title of the event'
},
description: {
type: 'string',
description: 'Description of the event'
},
location: {
type: 'string',
description: 'Geographic location of the event'
},
start: {
type: 'object',
description: 'Start time of the event'
},
end: {
type: 'object',
description: 'End time of the event'
},
attendees: {
type: 'array',
description: 'List of attendees'
},
sendNotifications: {
type: 'boolean',
description: 'Whether to send notifications about the update'
},
sendUpdates: {
type: 'string',
description: 'Whether to send notifications to attendees (all, externalOnly, none)'
},
},
required: ['calendarId', 'eventId',]
}
},
{
name: 'google-calendar_delete_event',
description: 'Deletes an event',
inputSchema: {
type: 'object',
properties: {
calendarId: {
type: 'string',
description: 'Calendar identifier. Use 'primary' for the primary calendar'
},
eventId: {
type: 'string',
description: 'Event identifier'
},
sendNotifications: {
type: 'boolean',
description: 'Whether to send notifications about the deletion'
},
sendUpdates: {
type: 'string',
description: 'Whether to send notifications to attendees (all, externalOnly, none)'
},
},
required: ['calendarId', 'eventId',]
}
},
{
name: 'google-calendar_quick_add',
description: 'Creates an event based on a simple text string',
inputSchema: {
type: 'object',
properties: {
calendarId: {
type: 'string',
description: 'Calendar identifier. Use 'primary' for the primary calendar'
},
text: {
type: 'string',
description: 'The text describing the event to be created (e.g., 'Meeting at Somewhere on June 3rd 10am-10:25am')'
},
sendNotifications: {
type: 'boolean',
description: 'Whether to send notifications about the creation of the event'
},
sendUpdates: {
type: 'string',
description: 'Whether to send notifications to attendees (all, externalOnly, none)'
},
},
required: ['calendarId', 'text',]
}
},
{
name: 'google-calendar_get_free_busy',
description: 'Returns free/busy information for a set of calendars',
inputSchema: {
type: 'object',
properties: {
timeMin: {
type: 'string',
description: 'The start of the interval (RFC3339 timestamp)'
},
timeMax: {
type: 'string',
description: 'The end of the interval (RFC3339 timestamp)'
},
timeZone: {
type: 'string',
description: 'Time zone used in the response (default UTC)'
},
items: {
type: 'array',
description: 'List of calendars and groups to query. Each item should have an 'id' field'
},
},
required: ['timeMin', 'timeMax', 'items']
}
},
{
name: 'google-calendar_list_acl',
description: 'Returns the rules in the access control list for the calendar',
inputSchema: {
type: 'object',
properties: {
calendarId: {
type: 'string',
description: 'Calendar identifier. Use 'primary' for the primary calendar'
},
maxResults: {
type: 'number',
description: 'Maximum number of entries returned (default 100, max 250)'
},
pageToken: {
type: 'string',
description: 'Token specifying which result page to return'
},
showDeleted: {
type: 'boolean',
description: 'Whether to include deleted ACLs in the result'
},
},
required: ['calendarId',]
}
},
{
name: 'google-calendar_create_acl',
description: 'Creates an access control rule',
inputSchema: {
type: 'object',
properties: {
calendarId: {
type: 'string',
description: 'Calendar identifier. Use 'primary' for the primary calendar'
},
role: {
type: 'string',
description: 'The role assigned to the scope (none, freeBusyReader, reader, writer, owner)'
},
scope: {
type: 'object',
description: 'The scope of the rule. Must include 'type' (user, group, domain, public) and 'value' (email or domain)'
},
sendNotifications: {
type: 'boolean',
description: 'Whether to send notifications about the sharing'
},
},
required: ['calendarId', 'role', 'scope',]
}
}
];
}
canHandle(toolName) {
const supportedTools = [
'google-calendar_list_calendars',
'google-calendar_get_calendar',
'google-calendar_create_calendar',
'google-calendar_update_calendar',
'google-calendar_delete_calendar',
'google-calendar_list_events',
'google-calendar_get_event',
'google-calendar_create_event',
'google-calendar_update_event',
'google-calendar_delete_event',
'google-calendar_quick_add',
'google-calendar_get_free_busy',
'google-calendar_list_acl',
'google-calendar_create_acl'
];
return supportedTools.includes(toolName);
}
async executeTool(name, args) {
const startTime = Date.now();
this.logger.logToolStart(name, args);
await this.ensureInitialized();
// Validate tool is supported
if (!this.canHandle(name)) {
this.logger.error('TOOL_ERROR', 'Unknown tool requested', {
tool: name,
supportedTools: ['google-calendar_list_calendars', 'google-calendar_get_calendar', 'google-calendar_create_calendar', 'google-calendar_update_calendar', 'google-calendar_delete_calendar', 'google-calendar_list_events', 'google-calendar_get_event', 'google-calendar_create_event', 'google-calendar_update_event', 'google-calendar_delete_event', 'google-calendar_quick_add', 'google-calendar_get_free_busy', 'google-calendar_list_acl', 'google-calendar_create_acl']
});
throw new Error(`Unknown tool: ${name}`);
}
// Validate required parameters
this.logger.debug('PARAM_VALIDATION', 'Validating tool parameters', {
tool: name,
providedArgs: Object.keys(args || {})
});
try {
let result;
switch (name) {
case 'google-calendar_list_calendars':
this.logger.debug('TOOL_EXECUTE', 'Calling client method', {
tool: 'google-calendar_list_calendars',
clientMethod: 'listCalendars'
});
result = await this.client.listCalendars(args);
break;
case 'google-calendar_get_calendar':
this.logger.debug('TOOL_EXECUTE', 'Calling client method', {
tool: 'google-calendar_get_calendar',
clientMethod: 'getCalendar'
});
result = await this.client.getCalendar(args);
break;
case 'google-calendar_create_calendar':
this.logger.debug('TOOL_EXECUTE', 'Calling client method', {
tool: 'google-calendar_create_calendar',
clientMethod: 'createCalendar'
});
result = await this.client.createCalendar(args);
break;
case 'google-calendar_update_calendar':
this.logger.debug('TOOL_EXECUTE', 'Calling client method', {
tool: 'google-calendar_update_calendar',
clientMethod: 'updateCalendar'
});
result = await this.client.updateCalendar(args);
break;
case 'google-calendar_delete_calendar':
this.logger.debug('TOOL_EXECUTE', 'Calling client method', {
tool: 'google-calendar_delete_calendar',
clientMethod: 'deleteCalendar'
});
result = await this.client.deleteCalendar(args);
break;
case 'google-calendar_list_events':
this.logger.debug('TOOL_EXECUTE', 'Calling client method', {
tool: 'google-calendar_list_events',
clientMethod: 'listEvents'
});
result = await this.client.listEvents(args);
break;
case 'google-calendar_get_event':
this.logger.debug('TOOL_EXECUTE', 'Calling client method', {
tool: 'google-calendar_get_event',
clientMethod: 'getEvent'
});
result = await this.client.getEvent(args);
break;
case 'google-calendar_create_event':
this.logger.debug('TOOL_EXECUTE', 'Calling client method', {
tool: 'google-calendar_create_event',
clientMethod: 'createEvent'
});
result = await this.client.createEvent(args);
break;
case 'google-calendar_update_event':
this.logger.debug('TOOL_EXECUTE', 'Calling client method', {
tool: 'google-calendar_update_event',
clientMethod: 'updateEvent'
});
result = await this.client.updateEvent(args);
break;
case 'google-calendar_delete_event':
this.logger.debug('TOOL_EXECUTE', 'Calling client method', {
tool: 'google-calendar_delete_event',
clientMethod: 'deleteEvent'
});
result = await this.client.deleteEvent(args);
break;
case 'google-calendar_quick_add':
this.logger.debug('TOOL_EXECUTE', 'Calling client method', {
tool: 'google-calendar_quick_add',
clientMethod: 'quickAdd'
});
result = await this.client.quickAdd(args);
break;
case 'google-calendar_get_free_busy':
this.logger.debug('TOOL_EXECUTE', 'Calling client method', {
tool: 'google-calendar_get_free_busy',
clientMethod: 'getFreeBusy'
});
result = await this.client.getFreeBusy(args);
break;
case 'google-calendar_list_acl':
this.logger.debug('TOOL_EXECUTE', 'Calling client method', {
tool: 'google-calendar_list_acl',
clientMethod: 'listAcl'
});
result = await this.client.listAcl(args);
break;
case 'google-calendar_create_acl':
this.logger.debug('TOOL_EXECUTE', 'Calling client method', {
tool: 'google-calendar_create_acl',
clientMethod: 'createAcl'
});
result = await this.client.createAcl(args);
break;
default:
throw new Error(`Unknown tool: ${name}`);
}
const duration = Date.now() - startTime;
this.logger.logToolSuccess(name, duration, result);
// Format the result for MCP (OAuth templates only)
return {
content: [
{
type: 'text',
text: typeof result === 'string' ? result : JSON.stringify(result, null, 2)
}
]
};
}
catch (error) {
const duration = Date.now() - startTime;
const errorMessage = error instanceof Error ? error.message : String(error);
this.logger.logToolError(name, error, duration, args);
return {
content: [
{
type: 'text',
text: `Error: ${errorMessage}`
}
],
isError: true
};
}
}
}
//# sourceMappingURL=google-calendar-tools.js.map