@pipeworx/mcp-google_calendar 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +39 -0
- package/package.json +20 -0
- package/server.json +18 -0
- package/src/index.ts +196 -0
- package/tsconfig.json +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Pipeworx
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# mcp-google_calendar
|
|
2
|
+
|
|
3
|
+
Google Calendar MCP Pack
|
|
4
|
+
|
|
5
|
+
Part of the [Pipeworx](https://pipeworx.io) open MCP gateway.
|
|
6
|
+
|
|
7
|
+
## Tools
|
|
8
|
+
|
|
9
|
+
| Tool | Description |
|
|
10
|
+
|------|-------------|
|
|
11
|
+
| `gcal_list_events` | List events from a Google Calendar. Optionally filter by time range. Returns event summaries, times, attendees, and locations. |
|
|
12
|
+
| `gcal_get_event` | Get a specific Google Calendar event by ID. Returns full event details including summary, description, start/end times, attendees, location, and conferencing info. |
|
|
13
|
+
| `gcal_create_event` | Create a new event on a Google Calendar. Specify summary, start/end times, and optional description, location, and attendees. |
|
|
14
|
+
| `gcal_list_calendars` | List all calendars accessible by the authenticated user. Returns calendar IDs, summaries, time zones, and access roles. |
|
|
15
|
+
| `gcal_search_events` | Search for events across a calendar using a text query. Matches against event summary, description, location, and attendees. |
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
Add to your MCP client config:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"mcpServers": {
|
|
24
|
+
"google_calendar": {
|
|
25
|
+
"url": "https://gateway.pipeworx.io/google_calendar/mcp"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or use the CLI:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx pipeworx use google_calendar
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## License
|
|
38
|
+
|
|
39
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pipeworx/mcp-google_calendar",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Google Calendar MCP Pack",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.ts",
|
|
7
|
+
"types": "src/index.ts",
|
|
8
|
+
"keywords": ["mcp", "mcp-server", "model-context-protocol", "pipeworx", "google_calendar"],
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/pipeworx-io/mcp-google_calendar"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"typecheck": "tsc --noEmit"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"typescript": "^5.7.0"
|
|
19
|
+
}
|
|
20
|
+
}
|
package/server.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
+
"name": "io.github.pipeworx-io/google_calendar",
|
|
4
|
+
"title": "google_calendar",
|
|
5
|
+
"description": "Google Calendar MCP Pack",
|
|
6
|
+
"version": "0.1.0",
|
|
7
|
+
"websiteUrl": "https://pipeworx.io/packs/google_calendar",
|
|
8
|
+
"repository": {
|
|
9
|
+
"url": "https://github.com/pipeworx-io/mcp-google_calendar",
|
|
10
|
+
"source": "github"
|
|
11
|
+
},
|
|
12
|
+
"remotes": [
|
|
13
|
+
{
|
|
14
|
+
"type": "streamable-http",
|
|
15
|
+
"url": "https://gateway.pipeworx.io/google_calendar/mcp"
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
interface McpToolDefinition {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: 'object';
|
|
6
|
+
properties: Record<string, unknown>;
|
|
7
|
+
required?: string[];
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface McpToolExport {
|
|
12
|
+
tools: McpToolDefinition[];
|
|
13
|
+
callTool: (name: string, args: Record<string, unknown>) => Promise<unknown>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Google Calendar MCP Pack
|
|
18
|
+
*
|
|
19
|
+
* Requires OAuth connection — gateway injects credentials via _context.google_calendar.
|
|
20
|
+
* Tools: list events, get event, create event, list calendars, search events.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
interface CalendarContext {
|
|
25
|
+
google_calendar?: { accessToken: string };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const API = 'https://www.googleapis.com/calendar/v3';
|
|
29
|
+
|
|
30
|
+
async function gFetch(ctx: CalendarContext, url: string, options: RequestInit = {}) {
|
|
31
|
+
if (!ctx.google_calendar) {
|
|
32
|
+
return { error: 'connection_required', message: 'Connect your Google account at https://pipeworx.io/account' };
|
|
33
|
+
}
|
|
34
|
+
const res = await fetch(url, {
|
|
35
|
+
...options,
|
|
36
|
+
headers: {
|
|
37
|
+
Authorization: `Bearer ${ctx.google_calendar.accessToken}`,
|
|
38
|
+
'Content-Type': 'application/json',
|
|
39
|
+
...(options.headers ?? {}),
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
if (!res.ok) {
|
|
43
|
+
const text = await res.text();
|
|
44
|
+
throw new Error(`Google Calendar API error (${res.status}): ${text}`);
|
|
45
|
+
}
|
|
46
|
+
return res.json();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const tools: McpToolExport['tools'] = [
|
|
50
|
+
{
|
|
51
|
+
name: 'gcal_list_events',
|
|
52
|
+
description: 'List events from a Google Calendar. Optionally filter by time range. Returns event summaries, times, attendees, and locations.',
|
|
53
|
+
inputSchema: {
|
|
54
|
+
type: 'object' as const,
|
|
55
|
+
properties: {
|
|
56
|
+
calendar_id: { type: 'string', description: 'Calendar ID (default: "primary" for the user\'s main calendar)' },
|
|
57
|
+
time_min: { type: 'string', description: 'Lower bound (inclusive) for event start time as RFC3339 timestamp (e.g., "2024-01-01T00:00:00Z")' },
|
|
58
|
+
time_max: { type: 'string', description: 'Upper bound (exclusive) for event end time as RFC3339 timestamp' },
|
|
59
|
+
max_results: { type: 'number', description: 'Maximum number of events to return (default 10, max 250)' },
|
|
60
|
+
order_by: { type: 'string', enum: ['startTime', 'updated'], description: 'Sort order (default: startTime). startTime requires singleEvents=true.' },
|
|
61
|
+
},
|
|
62
|
+
required: [],
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'gcal_get_event',
|
|
67
|
+
description: 'Get a specific Google Calendar event by ID. Returns full event details including summary, description, start/end times, attendees, location, and conferencing info.',
|
|
68
|
+
inputSchema: {
|
|
69
|
+
type: 'object' as const,
|
|
70
|
+
properties: {
|
|
71
|
+
calendar_id: { type: 'string', description: 'Calendar ID (default: "primary")' },
|
|
72
|
+
event_id: { type: 'string', description: 'The ID of the event to retrieve' },
|
|
73
|
+
},
|
|
74
|
+
required: ['event_id'],
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'gcal_create_event',
|
|
79
|
+
description: 'Create a new event on a Google Calendar. Specify summary, start/end times, and optional description, location, and attendees.',
|
|
80
|
+
inputSchema: {
|
|
81
|
+
type: 'object' as const,
|
|
82
|
+
properties: {
|
|
83
|
+
calendar_id: { type: 'string', description: 'Calendar ID (default: "primary")' },
|
|
84
|
+
summary: { type: 'string', description: 'Title of the event' },
|
|
85
|
+
start: { type: 'string', description: 'Start time as RFC3339 timestamp (e.g., "2024-06-15T10:00:00-07:00") or date for all-day events ("2024-06-15")' },
|
|
86
|
+
end: { type: 'string', description: 'End time as RFC3339 timestamp or date for all-day events' },
|
|
87
|
+
description: { type: 'string', description: 'Description or notes for the event' },
|
|
88
|
+
location: { type: 'string', description: 'Location of the event' },
|
|
89
|
+
attendees: {
|
|
90
|
+
type: 'array',
|
|
91
|
+
description: 'List of attendee email addresses',
|
|
92
|
+
items: { type: 'string' },
|
|
93
|
+
},
|
|
94
|
+
time_zone: { type: 'string', description: 'Time zone (e.g., "America/Los_Angeles"). Defaults to calendar\'s time zone.' },
|
|
95
|
+
},
|
|
96
|
+
required: ['summary', 'start', 'end'],
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: 'gcal_list_calendars',
|
|
101
|
+
description: 'List all calendars accessible by the authenticated user. Returns calendar IDs, summaries, time zones, and access roles.',
|
|
102
|
+
inputSchema: {
|
|
103
|
+
type: 'object' as const,
|
|
104
|
+
properties: {},
|
|
105
|
+
required: [],
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'gcal_search_events',
|
|
110
|
+
description: 'Search for events across a calendar using a text query. Matches against event summary, description, location, and attendees.',
|
|
111
|
+
inputSchema: {
|
|
112
|
+
type: 'object' as const,
|
|
113
|
+
properties: {
|
|
114
|
+
calendar_id: { type: 'string', description: 'Calendar ID (default: "primary")' },
|
|
115
|
+
query: { type: 'string', description: 'Free-text search query to match against event fields' },
|
|
116
|
+
time_min: { type: 'string', description: 'Lower bound for event start time as RFC3339 timestamp' },
|
|
117
|
+
time_max: { type: 'string', description: 'Upper bound for event end time as RFC3339 timestamp' },
|
|
118
|
+
max_results: { type: 'number', description: 'Maximum number of events to return (default 10, max 250)' },
|
|
119
|
+
},
|
|
120
|
+
required: ['query'],
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
async function callTool(name: string, args: Record<string, unknown>): Promise<unknown> {
|
|
126
|
+
const context = (args._context ?? {}) as CalendarContext;
|
|
127
|
+
delete args._context;
|
|
128
|
+
|
|
129
|
+
switch (name) {
|
|
130
|
+
case 'gcal_list_events': {
|
|
131
|
+
const calendarId = (args.calendar_id as string) ?? 'primary';
|
|
132
|
+
const maxResults = Math.min(250, Math.max(1, (args.max_results as number) ?? 10));
|
|
133
|
+
const params = new URLSearchParams({
|
|
134
|
+
maxResults: String(maxResults),
|
|
135
|
+
singleEvents: 'true',
|
|
136
|
+
orderBy: (args.order_by as string) ?? 'startTime',
|
|
137
|
+
});
|
|
138
|
+
if (args.time_min) params.set('timeMin', args.time_min as string);
|
|
139
|
+
if (args.time_max) params.set('timeMax', args.time_max as string);
|
|
140
|
+
return gFetch(context, `${API}/calendars/${encodeURIComponent(calendarId)}/events?${params}`);
|
|
141
|
+
}
|
|
142
|
+
case 'gcal_get_event': {
|
|
143
|
+
const calendarId = (args.calendar_id as string) ?? 'primary';
|
|
144
|
+
const eventId = args.event_id as string;
|
|
145
|
+
return gFetch(context, `${API}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(eventId)}`);
|
|
146
|
+
}
|
|
147
|
+
case 'gcal_create_event': {
|
|
148
|
+
const calendarId = (args.calendar_id as string) ?? 'primary';
|
|
149
|
+
const { summary, start, end, description, location, attendees, time_zone } = args as {
|
|
150
|
+
summary: string; start: string; end: string; description?: string; location?: string;
|
|
151
|
+
attendees?: string[]; time_zone?: string;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const isAllDay = !start.includes('T');
|
|
155
|
+
const event: Record<string, unknown> = { summary };
|
|
156
|
+
|
|
157
|
+
if (isAllDay) {
|
|
158
|
+
event.start = { date: start };
|
|
159
|
+
event.end = { date: end };
|
|
160
|
+
} else {
|
|
161
|
+
event.start = { dateTime: start, timeZone: time_zone };
|
|
162
|
+
event.end = { dateTime: end, timeZone: time_zone };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (description) event.description = description;
|
|
166
|
+
if (location) event.location = location;
|
|
167
|
+
if (attendees?.length) event.attendees = attendees.map((email) => ({ email }));
|
|
168
|
+
|
|
169
|
+
return gFetch(context, `${API}/calendars/${encodeURIComponent(calendarId)}/events`, {
|
|
170
|
+
method: 'POST',
|
|
171
|
+
body: JSON.stringify(event),
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
case 'gcal_list_calendars': {
|
|
175
|
+
return gFetch(context, `${API}/users/me/calendarList`);
|
|
176
|
+
}
|
|
177
|
+
case 'gcal_search_events': {
|
|
178
|
+
const calendarId = (args.calendar_id as string) ?? 'primary';
|
|
179
|
+
const query = args.query as string;
|
|
180
|
+
const maxResults = Math.min(250, Math.max(1, (args.max_results as number) ?? 10));
|
|
181
|
+
const params = new URLSearchParams({
|
|
182
|
+
q: query,
|
|
183
|
+
maxResults: String(maxResults),
|
|
184
|
+
singleEvents: 'true',
|
|
185
|
+
orderBy: 'startTime',
|
|
186
|
+
});
|
|
187
|
+
if (args.time_min) params.set('timeMin', args.time_min as string);
|
|
188
|
+
if (args.time_max) params.set('timeMax', args.time_max as string);
|
|
189
|
+
return gFetch(context, `${API}/calendars/${encodeURIComponent(calendarId)}/events?${params}`);
|
|
190
|
+
}
|
|
191
|
+
default:
|
|
192
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export default { tools, callTool, meter: { credits: 10 }, provider: 'google_calendar' } satisfies McpToolExport;
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"outDir": "dist",
|
|
10
|
+
"rootDir": "src",
|
|
11
|
+
"declaration": true
|
|
12
|
+
},
|
|
13
|
+
"include": ["src"]
|
|
14
|
+
}
|