google-calendar-workspace-mcp-server 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +262 -0
  2. package/build/index.d.ts +2 -0
  3. package/build/index.integration-with-mock.d.ts +6 -0
  4. package/build/index.integration-with-mock.js +195 -0
  5. package/build/index.js +35 -0
  6. package/package.json +49 -0
  7. package/shared/calendar-client/lib/api-errors.d.ts +4 -0
  8. package/shared/calendar-client/lib/api-errors.js +25 -0
  9. package/shared/calendar-client/lib/create-event.d.ts +2 -0
  10. package/shared/calendar-client/lib/create-event.js +13 -0
  11. package/shared/calendar-client/lib/get-event.d.ts +2 -0
  12. package/shared/calendar-client/lib/get-event.js +9 -0
  13. package/shared/calendar-client/lib/list-calendars.d.ts +5 -0
  14. package/shared/calendar-client/lib/list-calendars.js +14 -0
  15. package/shared/calendar-client/lib/list-events.d.ts +10 -0
  16. package/shared/calendar-client/lib/list-events.js +24 -0
  17. package/shared/calendar-client/lib/query-freebusy.d.ts +2 -0
  18. package/shared/calendar-client/lib/query-freebusy.js +13 -0
  19. package/shared/index.d.ts +2 -0
  20. package/shared/index.js +2 -0
  21. package/shared/logging.d.ts +10 -0
  22. package/shared/logging.js +23 -0
  23. package/shared/server.d.ts +130 -0
  24. package/shared/server.js +132 -0
  25. package/shared/tools/create-event.d.ts +110 -0
  26. package/shared/tools/create-event.js +195 -0
  27. package/shared/tools/get-event.d.ts +44 -0
  28. package/shared/tools/get-event.js +154 -0
  29. package/shared/tools/list-calendars.d.ts +36 -0
  30. package/shared/tools/list-calendars.js +88 -0
  31. package/shared/tools/list-events.d.ts +79 -0
  32. package/shared/tools/list-events.js +176 -0
  33. package/shared/tools/query-freebusy.d.ts +61 -0
  34. package/shared/tools/query-freebusy.js +110 -0
  35. package/shared/tools.d.ts +3 -0
  36. package/shared/tools.js +41 -0
  37. package/shared/types.d.ts +111 -0
  38. package/shared/types.js +4 -0
package/README.md ADDED
@@ -0,0 +1,262 @@
1
+ # Google Calendar Workspace MCP Server
2
+
3
+ An MCP (Model Context Protocol) server for Google Calendar integration using service account authentication with domain-wide delegation. This server enables AI assistants to interact with Google Calendar to list events, create events, manage calendars, and query availability.
4
+
5
+ ## Features
6
+
7
+ - **List Events**: View calendar events within a specified time range with filtering
8
+ - **Get Event Details**: Retrieve complete information about specific events
9
+ - **Create Events**: Create new calendar events with attendees, location, and descriptions
10
+ - **List Calendars**: Discover available calendars
11
+ - **Query Free/Busy**: Check availability and find busy time slots
12
+
13
+ ## Prerequisites
14
+
15
+ 1. **Google Cloud Project** with Calendar API enabled
16
+ 2. **Service Account** with domain-wide delegation
17
+ 3. **Google Workspace Admin** access to grant calendar permissions
18
+
19
+ ## Setup
20
+
21
+ ### 1. Create a Google Cloud Service Account
22
+
23
+ 1. Go to [Google Cloud Console](https://console.cloud.google.com/)
24
+ 2. Create or select a project
25
+ 3. Enable the Google Calendar API:
26
+ - Navigate to "APIs & Services" > "Library"
27
+ - Search for "Google Calendar API"
28
+ - Click "Enable"
29
+ 4. Create a service account:
30
+ - Navigate to "IAM & Admin" > "Service Accounts"
31
+ - Click "Create Service Account"
32
+ - Provide a name and description
33
+ - Click "Create and Continue"
34
+ - Skip granting roles (not needed for domain-wide delegation)
35
+ - Click "Done"
36
+ 5. Create a key for the service account:
37
+ - Click on the created service account
38
+ - Go to "Keys" tab
39
+ - Click "Add Key" > "Create new key"
40
+ - Select "JSON" format
41
+ - Download the key file
42
+ 6. Note the service account's **Client ID** (found in the service account details)
43
+
44
+ ### 2. Enable Domain-Wide Delegation
45
+
46
+ 1. In the service account details, click "Show domain-wide delegation"
47
+ 2. Check "Enable Google Workspace Domain-wide Delegation"
48
+ 3. Save the changes
49
+ 4. Note the **Client ID** (you'll need this for the next step)
50
+
51
+ ### 3. Grant Calendar Permissions in Google Workspace Admin
52
+
53
+ 1. Go to [Google Workspace Admin Console](https://admin.google.com/)
54
+ 2. Navigate to "Security" > "Access and data control" > "API Controls"
55
+ 3. Click "Manage Domain Wide Delegation"
56
+ 4. Click "Add new"
57
+ 5. Enter the service account's **Client ID**
58
+ 6. In the "OAuth Scopes" field, add:
59
+ ```
60
+ https://www.googleapis.com/auth/calendar
61
+ ```
62
+ 7. Click "Authorize"
63
+
64
+ ### 4. Configure Environment Variables
65
+
66
+ Extract the following from your downloaded JSON key file:
67
+
68
+ - `client_email`: The service account email
69
+ - `private_key`: The private key (including `-----BEGIN PRIVATE KEY-----` and `-----END PRIVATE KEY-----`)
70
+
71
+ Set these environment variables:
72
+
73
+ ```bash
74
+ export GCAL_SERVICE_ACCOUNT_CLIENT_EMAIL="your-service-account@your-project.iam.gserviceaccount.com"
75
+ export GCAL_SERVICE_ACCOUNT_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nYour private key content\n-----END PRIVATE KEY-----"
76
+ export GCAL_IMPERSONATE_EMAIL="user@yourdomain.com"
77
+ ```
78
+
79
+ **Note**: `GCAL_IMPERSONATE_EMAIL` should be the email address of the user whose calendar you want to access.
80
+
81
+ ## Installation
82
+
83
+ ### Using NPX (Recommended)
84
+
85
+ ```bash
86
+ npx google-calendar-workspace-mcp-server
87
+ ```
88
+
89
+ ### Using NPM
90
+
91
+ ```bash
92
+ npm install -g google-calendar-workspace-mcp-server
93
+ google-calendar-workspace-mcp-server
94
+ ```
95
+
96
+ ## Usage with Claude Desktop
97
+
98
+ Add this configuration to your Claude Desktop config file:
99
+
100
+ **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
101
+ **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
102
+
103
+ ```json
104
+ {
105
+ "mcpServers": {
106
+ "google-calendar": {
107
+ "command": "npx",
108
+ "args": ["google-calendar-workspace-mcp-server"],
109
+ "env": {
110
+ "GCAL_SERVICE_ACCOUNT_CLIENT_EMAIL": "your-service-account@your-project.iam.gserviceaccount.com",
111
+ "GCAL_SERVICE_ACCOUNT_PRIVATE_KEY": "-----BEGIN PRIVATE KEY-----\nYour private key\n-----END PRIVATE KEY-----",
112
+ "GCAL_IMPERSONATE_EMAIL": "user@yourdomain.com"
113
+ }
114
+ }
115
+ }
116
+ }
117
+ ```
118
+
119
+ ## Available Tools
120
+
121
+ ### gcal_list_events
122
+
123
+ Lists events from a calendar within an optional time range.
124
+
125
+ **Parameters:**
126
+
127
+ - `calendar_id` (optional): Calendar ID (default: "primary")
128
+ - `time_min` (optional): Start time in RFC3339 format
129
+ - `time_max` (optional): End time in RFC3339 format
130
+ - `max_results` (optional): Maximum events to return (default: 10, max: 250)
131
+ - `query` (optional): Free text search query
132
+ - `single_events` (optional): Expand recurring events (default: true)
133
+ - `order_by` (optional): "startTime" or "updated"
134
+
135
+ **Example:**
136
+
137
+ ```
138
+ List my events for the next week
139
+ ```
140
+
141
+ ### gcal_get_event
142
+
143
+ Retrieves detailed information about a specific event.
144
+
145
+ **Parameters:**
146
+
147
+ - `event_id` (required): The event ID
148
+ - `calendar_id` (optional): Calendar ID (default: "primary")
149
+
150
+ **Example:**
151
+
152
+ ```
153
+ Get details for event ID abc123
154
+ ```
155
+
156
+ ### gcal_create_event
157
+
158
+ Creates a new calendar event.
159
+
160
+ **Parameters:**
161
+
162
+ - `summary` (required): Event title
163
+ - `start_datetime` OR `start_date` (required): Event start time
164
+ - `end_datetime` OR `end_date` (required): Event end time
165
+ - `description` (optional): Event description
166
+ - `location` (optional): Event location
167
+ - `attendees` (optional): Array of email addresses
168
+ - `calendar_id` (optional): Calendar ID (default: "primary")
169
+
170
+ **Example:**
171
+
172
+ ```
173
+ Create a meeting tomorrow at 2pm for 1 hour titled "Team Sync"
174
+ ```
175
+
176
+ ### gcal_list_calendars
177
+
178
+ Lists all calendars available to the authenticated user.
179
+
180
+ **Parameters:**
181
+
182
+ - `max_results` (optional): Maximum calendars to return (default: 50, max: 250)
183
+
184
+ **Example:**
185
+
186
+ ```
187
+ Show all my calendars
188
+ ```
189
+
190
+ ### gcal_query_freebusy
191
+
192
+ Queries availability information for calendars.
193
+
194
+ **Parameters:**
195
+
196
+ - `time_min` (required): Start time in RFC3339 format
197
+ - `time_max` (required): End time in RFC3339 format
198
+ - `calendar_ids` (required): Array of calendar IDs to check
199
+ - `timezone` (optional): Time zone for the query
200
+
201
+ **Example:**
202
+
203
+ ```
204
+ Check if I'm free tomorrow between 2pm and 4pm
205
+ ```
206
+
207
+ ## Development
208
+
209
+ ```bash
210
+ # Install dependencies
211
+ npm run install-all
212
+
213
+ # Build the project
214
+ npm run build
215
+
216
+ # Run in development mode
217
+ npm run dev
218
+
219
+ # Run tests
220
+ npm test
221
+
222
+ # Run integration tests
223
+ npm run test:integration
224
+
225
+ # Run all tests
226
+ npm run test:all
227
+ ```
228
+
229
+ ## Security Considerations
230
+
231
+ - **Private Key Security**: Never commit your service account private key to version control
232
+ - **Least Privilege**: Only grant the minimum required OAuth scopes
233
+ - **Key Rotation**: Regularly rotate service account keys
234
+ - **Access Logging**: Monitor service account usage in Google Cloud Console
235
+
236
+ ## Troubleshooting
237
+
238
+ ### Authentication Failed
239
+
240
+ - Verify service account credentials are correct
241
+ - Ensure domain-wide delegation is enabled
242
+ - Check that the correct OAuth scope is authorized in Admin Console
243
+ - Verify the impersonate email address is correct
244
+
245
+ ### Permission Denied
246
+
247
+ - Ensure the calendar scope (`https://www.googleapis.com/auth/calendar`) is granted in Google Workspace Admin Console
248
+ - Verify the impersonated user has access to the calendar
249
+
250
+ ### Calendar Not Found
251
+
252
+ - Check that the calendar ID is correct
253
+ - Verify the impersonated user has access to the calendar
254
+ - Use `gcal_list_calendars` to discover available calendar IDs
255
+
256
+ ## License
257
+
258
+ MIT
259
+
260
+ ## Contributing
261
+
262
+ See [CONTRIBUTING.md](../../CONTRIBUTING.md) for guidelines.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Integration test entry point with mock Google Calendar client
4
+ * Used by TestMCPClient for integration tests
5
+ */
6
+ export {};
@@ -0,0 +1,195 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Integration test entry point with mock Google Calendar client
4
+ * Used by TestMCPClient for integration tests
5
+ */
6
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
7
+ import { createMCPServer } from '../shared/index.js';
8
+ import { logServerStart } from '../shared/logging.js';
9
+ /**
10
+ * Mock Google Calendar client for integration tests
11
+ */
12
+ class MockCalendarClient {
13
+ async listEvents(calendarId, options) {
14
+ const mockEvents = [
15
+ {
16
+ id: 'event1',
17
+ summary: 'Team Standup',
18
+ description: 'Daily team sync',
19
+ start: {
20
+ dateTime: '2024-01-15T10:00:00-05:00',
21
+ timeZone: 'America/New_York',
22
+ },
23
+ end: {
24
+ dateTime: '2024-01-15T10:30:00-05:00',
25
+ timeZone: 'America/New_York',
26
+ },
27
+ status: 'confirmed',
28
+ htmlLink: 'https://calendar.google.com/event?eid=event1',
29
+ attendees: [
30
+ {
31
+ email: 'user1@example.com',
32
+ responseStatus: 'accepted',
33
+ },
34
+ {
35
+ email: 'user2@example.com',
36
+ responseStatus: 'tentative',
37
+ },
38
+ ],
39
+ },
40
+ {
41
+ id: 'event2',
42
+ summary: 'All Day Event',
43
+ start: {
44
+ date: '2024-01-16',
45
+ },
46
+ end: {
47
+ date: '2024-01-17',
48
+ },
49
+ status: 'confirmed',
50
+ htmlLink: 'https://calendar.google.com/event?eid=event2',
51
+ },
52
+ ];
53
+ const filteredEvents = options?.q
54
+ ? mockEvents.filter((e) => e.summary?.toLowerCase().includes(options.q.toLowerCase()))
55
+ : mockEvents;
56
+ return {
57
+ kind: 'calendar#events',
58
+ etag: 'mock-etag',
59
+ summary: calendarId === 'primary' ? 'Primary Calendar' : calendarId,
60
+ updated: new Date().toISOString(),
61
+ timeZone: 'America/New_York',
62
+ accessRole: 'owner',
63
+ items: filteredEvents.slice(0, options?.maxResults || 10),
64
+ };
65
+ }
66
+ async getEvent(calendarId, eventId) {
67
+ if (eventId === 'event1') {
68
+ return {
69
+ id: 'event1',
70
+ summary: 'Team Standup',
71
+ description: 'Daily team sync',
72
+ location: 'Conference Room A',
73
+ start: {
74
+ dateTime: '2024-01-15T10:00:00-05:00',
75
+ timeZone: 'America/New_York',
76
+ },
77
+ end: {
78
+ dateTime: '2024-01-15T10:30:00-05:00',
79
+ timeZone: 'America/New_York',
80
+ },
81
+ status: 'confirmed',
82
+ htmlLink: 'https://calendar.google.com/event?eid=event1',
83
+ created: '2024-01-01T00:00:00Z',
84
+ updated: '2024-01-01T00:00:00Z',
85
+ creator: {
86
+ email: 'creator@example.com',
87
+ displayName: 'Event Creator',
88
+ },
89
+ organizer: {
90
+ email: 'organizer@example.com',
91
+ displayName: 'Event Organizer',
92
+ },
93
+ attendees: [
94
+ {
95
+ email: 'user1@example.com',
96
+ displayName: 'User One',
97
+ responseStatus: 'accepted',
98
+ },
99
+ {
100
+ email: 'user2@example.com',
101
+ displayName: 'User Two',
102
+ responseStatus: 'tentative',
103
+ },
104
+ ],
105
+ reminders: {
106
+ useDefault: false,
107
+ overrides: [
108
+ {
109
+ method: 'email',
110
+ minutes: 30,
111
+ },
112
+ ],
113
+ },
114
+ };
115
+ }
116
+ throw new Error(`Event not found: ${eventId}`);
117
+ }
118
+ async createEvent(calendarId, event) {
119
+ return {
120
+ id: 'new-event-id',
121
+ summary: event.summary || 'New Event',
122
+ description: event.description,
123
+ location: event.location,
124
+ start: event.start || { dateTime: '2024-01-20T10:00:00-05:00' },
125
+ end: event.end || { dateTime: '2024-01-20T11:00:00-05:00' },
126
+ status: 'confirmed',
127
+ htmlLink: 'https://calendar.google.com/event?eid=new-event-id',
128
+ created: new Date().toISOString(),
129
+ updated: new Date().toISOString(),
130
+ attendees: event.attendees,
131
+ };
132
+ }
133
+ async listCalendars(_options) {
134
+ return {
135
+ kind: 'calendar#calendarList',
136
+ etag: 'mock-etag',
137
+ items: [
138
+ {
139
+ kind: 'calendar#calendarListEntry',
140
+ etag: 'mock-etag-1',
141
+ id: 'primary',
142
+ summary: 'Primary Calendar',
143
+ timeZone: 'America/New_York',
144
+ accessRole: 'owner',
145
+ primary: true,
146
+ selected: true,
147
+ backgroundColor: '#9fc6e7',
148
+ foregroundColor: '#000000',
149
+ },
150
+ {
151
+ kind: 'calendar#calendarListEntry',
152
+ etag: 'mock-etag-2',
153
+ id: 'work@example.com',
154
+ summary: 'Work Calendar',
155
+ description: 'Work-related events',
156
+ timeZone: 'America/New_York',
157
+ accessRole: 'writer',
158
+ selected: true,
159
+ backgroundColor: '#f83a22',
160
+ foregroundColor: '#000000',
161
+ },
162
+ ],
163
+ };
164
+ }
165
+ async queryFreebusy(request) {
166
+ return {
167
+ kind: 'calendar#freeBusy',
168
+ timeMin: request.timeMin,
169
+ timeMax: request.timeMax,
170
+ calendars: {
171
+ primary: {
172
+ busy: [
173
+ {
174
+ start: '2024-01-15T10:00:00-05:00',
175
+ end: '2024-01-15T10:30:00-05:00',
176
+ },
177
+ {
178
+ start: '2024-01-15T14:00:00-05:00',
179
+ end: '2024-01-15T15:00:00-05:00',
180
+ },
181
+ ],
182
+ },
183
+ },
184
+ };
185
+ }
186
+ }
187
+ async function main() {
188
+ const { server, registerHandlers } = createMCPServer();
189
+ // Register handlers with mock client factory
190
+ await registerHandlers(server, () => new MockCalendarClient());
191
+ const transport = new StdioServerTransport();
192
+ await server.connect(transport);
193
+ logServerStart('google-calendar-workspace-mcp-server-integration-mock');
194
+ }
195
+ main();
package/build/index.js ADDED
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { createMCPServer } from '../shared/index.js';
4
+ import { logServerStart, logError } from '../shared/logging.js';
5
+ async function main() {
6
+ // Validate required environment variables
7
+ const requiredVars = [
8
+ 'GCAL_SERVICE_ACCOUNT_CLIENT_EMAIL',
9
+ 'GCAL_SERVICE_ACCOUNT_PRIVATE_KEY',
10
+ 'GCAL_IMPERSONATE_EMAIL',
11
+ ];
12
+ const missing = requiredVars.filter((varName) => !process.env[varName]);
13
+ if (missing.length > 0) {
14
+ console.error('Error: Missing required environment variables:');
15
+ for (const varName of missing) {
16
+ console.error(` - ${varName}`);
17
+ }
18
+ console.error('\nPlease set these environment variables to use the Google Calendar MCP server.');
19
+ console.error('See README.md for setup instructions.');
20
+ process.exit(1);
21
+ }
22
+ try {
23
+ const { server, registerHandlers } = createMCPServer();
24
+ // Register handlers with default client factory
25
+ await registerHandlers(server);
26
+ const transport = new StdioServerTransport();
27
+ await server.connect(transport);
28
+ logServerStart('google-calendar-workspace-mcp-server');
29
+ }
30
+ catch (error) {
31
+ logError('server-startup', error);
32
+ process.exit(1);
33
+ }
34
+ }
35
+ main();
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "google-calendar-workspace-mcp-server",
3
+ "version": "0.0.1",
4
+ "description": "MCP server for Google Calendar integration with service account support",
5
+ "main": "build/index.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "google-calendar-workspace-mcp-server": "./build/index.js"
9
+ },
10
+ "files": [
11
+ "build/**/*.js",
12
+ "build/**/*.d.ts",
13
+ "shared/**/*.js",
14
+ "shared/**/*.d.ts",
15
+ "README.md"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc && npm run build:integration",
19
+ "build:integration": "tsc -p tsconfig.integration.json",
20
+ "start": "node build/index.js",
21
+ "dev": "tsx src/index.ts",
22
+ "predev": "cd ../shared && npm run build && cd ../local && node setup-dev.js",
23
+ "prebuild": "cd ../shared && npm run build && cd ../local && node setup-dev.js",
24
+ "prepublishOnly": "node prepare-publish.js && node ../scripts/prepare-npm-readme.js",
25
+ "lint": "eslint . --ext .ts,.tsx",
26
+ "lint:fix": "eslint . --ext .ts,.tsx --fix",
27
+ "format": "prettier --write .",
28
+ "format:check": "prettier --check .",
29
+ "stage-publish": "npm version"
30
+ },
31
+ "dependencies": {
32
+ "@modelcontextprotocol/sdk": "^1.19.1",
33
+ "google-auth-library": "^10.5.0",
34
+ "zod": "^3.24.1"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^22.10.6",
38
+ "tsx": "^4.19.4",
39
+ "typescript": "^5.7.3"
40
+ },
41
+ "keywords": [
42
+ "mcp",
43
+ "google-calendar",
44
+ "calendar",
45
+ "model-context-protocol"
46
+ ],
47
+ "author": "PulseMCP",
48
+ "license": "MIT"
49
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Structured error handling for Google Calendar API errors
3
+ */
4
+ export declare function handleApiError(status: number, operation: string, resourceId?: string): never;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Structured error handling for Google Calendar API errors
3
+ */
4
+ export function handleApiError(status, operation, resourceId) {
5
+ if (status === 401) {
6
+ throw new Error('Service account authentication failed. Verify the credentials and domain-wide delegation.');
7
+ }
8
+ if (status === 403) {
9
+ throw new Error('Permission denied. Ensure calendar scope is granted in Google Workspace Admin Console.');
10
+ }
11
+ if (status === 404) {
12
+ const resource = resourceId ? `: ${resourceId}` : '';
13
+ throw new Error(`Calendar resource not found${resource}`);
14
+ }
15
+ if (status === 429) {
16
+ throw new Error('Google Calendar API rate limit exceeded. Please try again later.');
17
+ }
18
+ if (status === 400) {
19
+ throw new Error(`Bad request while ${operation}. Check the request parameters.`);
20
+ }
21
+ if (status === 410) {
22
+ throw new Error('Calendar sync token expired. The sync state is no longer valid.');
23
+ }
24
+ throw new Error(`Google Calendar API error while ${operation}: HTTP ${status}`);
25
+ }
@@ -0,0 +1,2 @@
1
+ import type { CalendarEvent } from '../../types.js';
2
+ export declare function createEvent(baseUrl: string, headers: Record<string, string>, calendarId: string, event: Partial<CalendarEvent>): Promise<CalendarEvent>;
@@ -0,0 +1,13 @@
1
+ import { handleApiError } from './api-errors.js';
2
+ export async function createEvent(baseUrl, headers, calendarId, event) {
3
+ const url = `${baseUrl}/calendars/${encodeURIComponent(calendarId)}/events`;
4
+ const response = await fetch(url, {
5
+ method: 'POST',
6
+ headers,
7
+ body: JSON.stringify(event),
8
+ });
9
+ if (!response.ok) {
10
+ handleApiError(response.status, 'creating calendar event', calendarId);
11
+ }
12
+ return (await response.json());
13
+ }
@@ -0,0 +1,2 @@
1
+ import type { CalendarEvent } from '../../types.js';
2
+ export declare function getEvent(baseUrl: string, headers: Record<string, string>, calendarId: string, eventId: string): Promise<CalendarEvent>;
@@ -0,0 +1,9 @@
1
+ import { handleApiError } from './api-errors.js';
2
+ export async function getEvent(baseUrl, headers, calendarId, eventId) {
3
+ const url = `${baseUrl}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(eventId)}`;
4
+ const response = await fetch(url, { headers });
5
+ if (!response.ok) {
6
+ handleApiError(response.status, 'getting calendar event', eventId);
7
+ }
8
+ return (await response.json());
9
+ }
@@ -0,0 +1,5 @@
1
+ import type { CalendarList } from '../../types.js';
2
+ export declare function listCalendars(baseUrl: string, headers: Record<string, string>, options?: {
3
+ maxResults?: number;
4
+ pageToken?: string;
5
+ }): Promise<CalendarList>;
@@ -0,0 +1,14 @@
1
+ import { handleApiError } from './api-errors.js';
2
+ export async function listCalendars(baseUrl, headers, options) {
3
+ const params = new URLSearchParams();
4
+ if (options?.maxResults)
5
+ params.append('maxResults', options.maxResults.toString());
6
+ if (options?.pageToken)
7
+ params.append('pageToken', options.pageToken);
8
+ const url = `${baseUrl}/users/me/calendarList?${params}`;
9
+ const response = await fetch(url, { headers });
10
+ if (!response.ok) {
11
+ handleApiError(response.status, 'listing calendars');
12
+ }
13
+ return (await response.json());
14
+ }
@@ -0,0 +1,10 @@
1
+ import type { CalendarEventList } from '../../types.js';
2
+ export declare function listEvents(baseUrl: string, headers: Record<string, string>, calendarId: string, options?: {
3
+ timeMin?: string;
4
+ timeMax?: string;
5
+ maxResults?: number;
6
+ pageToken?: string;
7
+ q?: string;
8
+ singleEvents?: boolean;
9
+ orderBy?: string;
10
+ }): Promise<CalendarEventList>;
@@ -0,0 +1,24 @@
1
+ import { handleApiError } from './api-errors.js';
2
+ export async function listEvents(baseUrl, headers, calendarId, options) {
3
+ const params = new URLSearchParams();
4
+ if (options?.timeMin)
5
+ params.append('timeMin', options.timeMin);
6
+ if (options?.timeMax)
7
+ params.append('timeMax', options.timeMax);
8
+ if (options?.maxResults)
9
+ params.append('maxResults', options.maxResults.toString());
10
+ if (options?.pageToken)
11
+ params.append('pageToken', options.pageToken);
12
+ if (options?.q)
13
+ params.append('q', options.q);
14
+ if (options?.singleEvents !== undefined)
15
+ params.append('singleEvents', options.singleEvents.toString());
16
+ if (options?.orderBy)
17
+ params.append('orderBy', options.orderBy);
18
+ const url = `${baseUrl}/calendars/${encodeURIComponent(calendarId)}/events?${params}`;
19
+ const response = await fetch(url, { headers });
20
+ if (!response.ok) {
21
+ handleApiError(response.status, 'listing calendar events', calendarId);
22
+ }
23
+ return (await response.json());
24
+ }
@@ -0,0 +1,2 @@
1
+ import type { FreeBusyRequest, FreeBusyResponse } from '../../types.js';
2
+ export declare function queryFreebusy(baseUrl: string, headers: Record<string, string>, request: FreeBusyRequest): Promise<FreeBusyResponse>;