gogcli-mcp-calendar 2.7.1 → 2.18.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/dist/index.js +19959 -19607
- package/manifest.json +25 -1
- package/package.json +3 -2
- package/src/index.ts +7 -9
- package/src/tools/calendar-extra.ts +44 -1
- package/tests/tools/calendar-extra.test.ts +105 -41
- package/tsconfig.json +1 -1
package/manifest.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"manifest_version": "0.3",
|
|
4
4
|
"name": "gogcli-mcp-calendar",
|
|
5
5
|
"display_name": "gogcli (Calendar)",
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.18.0",
|
|
7
7
|
"description": "Extended Google Calendar for Claude via gogcli — auth + Calendar events + Meet space management",
|
|
8
8
|
"author": {
|
|
9
9
|
"name": "Chris Hall",
|
|
@@ -58,6 +58,18 @@
|
|
|
58
58
|
"name": "gog_auth_add",
|
|
59
59
|
"description": "Authorize a Google account via browser-based OAuth"
|
|
60
60
|
},
|
|
61
|
+
{
|
|
62
|
+
"name": "gog_auth_health",
|
|
63
|
+
"description": "Live per-account token health: validity, age, and pre-expiry warnings (detects invalid_grant)"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"name": "gog_auth_add_url",
|
|
67
|
+
"description": "Begin remote/headless OAuth (step 1): return a sign-in URL to open in any browser"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"name": "gog_auth_add_complete",
|
|
71
|
+
"description": "Complete remote/headless OAuth (step 2): exchange the pasted redirect URL and store the token"
|
|
72
|
+
},
|
|
61
73
|
{
|
|
62
74
|
"name": "gog_auth_list",
|
|
63
75
|
"description": "List all Google accounts stored in gogcli"
|
|
@@ -110,6 +122,10 @@
|
|
|
110
122
|
"name": "gog_calendar_search",
|
|
111
123
|
"description": "Full-text search for events with optional time filters"
|
|
112
124
|
},
|
|
125
|
+
{
|
|
126
|
+
"name": "gog_calendar_changed",
|
|
127
|
+
"description": "List most recently changed events (including cancellations) across calendars"
|
|
128
|
+
},
|
|
113
129
|
{
|
|
114
130
|
"name": "gog_calendar_freebusy",
|
|
115
131
|
"description": "Query free/busy intervals for one or more calendars"
|
|
@@ -130,6 +146,14 @@
|
|
|
130
146
|
"name": "gog_calendar_out_of_office",
|
|
131
147
|
"description": "Create an Out of Office event that auto-declines invitations"
|
|
132
148
|
},
|
|
149
|
+
{
|
|
150
|
+
"name": "gog_calendar_unsubscribe",
|
|
151
|
+
"description": "Remove a calendar from your calendar list"
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"name": "gog_calendar_delete_calendar",
|
|
155
|
+
"description": "Delete an owned secondary calendar"
|
|
156
|
+
},
|
|
133
157
|
{
|
|
134
158
|
"name": "gog_meet_create",
|
|
135
159
|
"description": "Create a Google Meet space"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gogcli-mcp-calendar",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.18.0",
|
|
4
4
|
"mcpName": "io.github.chrischall/gogcli-mcp-calendar",
|
|
5
5
|
"description": "Extended Google Calendar + Meet MCP server via gogcli — auth + Calendar events + Meet space management",
|
|
6
6
|
"author": "Claude Code (AI) <https://www.anthropic.com/claude>",
|
|
@@ -19,11 +19,12 @@
|
|
|
19
19
|
"build": "tsc --noEmit && npm run bundle",
|
|
20
20
|
"bundle": "node ../../scripts/bundle.js src/index.ts dist/index.js",
|
|
21
21
|
"typecheck": "tsc --noEmit",
|
|
22
|
-
"test": "vitest run",
|
|
22
|
+
"test": "vitest run --coverage",
|
|
23
23
|
"test:watch": "vitest",
|
|
24
24
|
"test:coverage": "vitest run --coverage"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
+
"@chrischall/mcp-utils": "^0.13.3",
|
|
27
28
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
28
29
|
"zod": "^4.4.3"
|
|
29
30
|
},
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { runMcp } from '@chrischall/mcp-utils';
|
|
3
|
+
import { VERSION, authToolsFor, registerCalendarTools } from '../../gogcli-mcp/src/lib.js';
|
|
4
4
|
import { registerExtraCalendarTools } from './tools/calendar-extra.js';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const transport = new StdioServerTransport();
|
|
12
|
-
await server.connect(transport);
|
|
6
|
+
await runMcp({
|
|
7
|
+
name: 'gogcli-calendar',
|
|
8
|
+
version: VERSION,
|
|
9
|
+
tools: [authToolsFor('calendar'), registerCalendarTools, registerExtraCalendarTools],
|
|
10
|
+
});
|
|
@@ -54,7 +54,7 @@ export function registerExtraCalendarTools(server: McpServer): void {
|
|
|
54
54
|
account: accountParam,
|
|
55
55
|
},
|
|
56
56
|
}, async ({ meetingCode, account }) => {
|
|
57
|
-
return runOrDiagnose(['meet', 'end', meetingCode], { account });
|
|
57
|
+
return runOrDiagnose(['meet', 'end', meetingCode, '--force'], { account }); // gog gates this op; without --force the runner's --no-input makes it refuse
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
server.registerTool('gog_meet_history', {
|
|
@@ -159,6 +159,27 @@ export function registerExtraCalendarTools(server: McpServer): void {
|
|
|
159
159
|
return runOrDiagnose(args, { account });
|
|
160
160
|
});
|
|
161
161
|
|
|
162
|
+
server.registerTool('gog_calendar_changed', {
|
|
163
|
+
description: 'List most recently changed events (including cancellations/deletions) across one or more calendars, ordered by last-modification time. Requires gog >= 0.31.1.',
|
|
164
|
+
annotations: { readOnlyHint: true },
|
|
165
|
+
inputSchema: {
|
|
166
|
+
calendarId: z.string().optional().describe('Calendar ID (default: primary)'),
|
|
167
|
+
calendarIds: z.string().optional().describe('Comma-separated calendar IDs, names, or indices'),
|
|
168
|
+
since: z.string().optional().describe('Lower bound for last-modification time (RFC3339, date, or Go duration like 24h, 168h; default: 720h / 30 days). Google rejects windows too far in the past (410 updatedMinTooLongAgo) — retry with a shorter duration if that happens'),
|
|
169
|
+
max: z.number().optional().describe('Max results (default: 10)'),
|
|
170
|
+
all: z.boolean().optional().describe('Fetch from all calendars'),
|
|
171
|
+
account: accountParam,
|
|
172
|
+
},
|
|
173
|
+
}, async ({ calendarId, calendarIds, since, max, all, account }) => {
|
|
174
|
+
const args = ['calendar', 'changed'];
|
|
175
|
+
if (calendarId) args.push(calendarId);
|
|
176
|
+
if (calendarIds) args.push(`--calendars=${calendarIds}`);
|
|
177
|
+
if (since) args.push(`--since=${since}`);
|
|
178
|
+
if (max !== undefined) args.push(`--max=${max}`);
|
|
179
|
+
if (all) args.push('--all');
|
|
180
|
+
return runOrDiagnose(args, { account });
|
|
181
|
+
});
|
|
182
|
+
|
|
162
183
|
server.registerTool('gog_calendar_freebusy', {
|
|
163
184
|
description: 'Query free/busy intervals for one or more calendars over a time window.',
|
|
164
185
|
annotations: { readOnlyHint: true },
|
|
@@ -245,6 +266,28 @@ export function registerExtraCalendarTools(server: McpServer): void {
|
|
|
245
266
|
return runOrDiagnose(args, { account });
|
|
246
267
|
});
|
|
247
268
|
|
|
269
|
+
server.registerTool('gog_calendar_unsubscribe', {
|
|
270
|
+
description: 'Remove a calendar from your calendar list (the underlying calendar is not deleted — you can re-subscribe). For deleting a secondary calendar you own, use gog_calendar_delete_calendar.',
|
|
271
|
+
annotations: { destructiveHint: true },
|
|
272
|
+
inputSchema: {
|
|
273
|
+
calendarId: z.string().describe('Calendar ID or alias to remove from your calendar list'),
|
|
274
|
+
account: accountParam,
|
|
275
|
+
},
|
|
276
|
+
}, async ({ calendarId, account }) => {
|
|
277
|
+
return runOrDiagnose(['calendar', 'unsubscribe', calendarId], { account });
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
server.registerTool('gog_calendar_delete_calendar', {
|
|
281
|
+
description: 'Permanently delete an owned secondary calendar and all its events. Cannot delete your primary calendar. To merely remove a calendar you do not own from your list, use gog_calendar_unsubscribe.',
|
|
282
|
+
annotations: { destructiveHint: true },
|
|
283
|
+
inputSchema: {
|
|
284
|
+
calendarId: z.string().describe('Owned secondary calendar ID or alias'),
|
|
285
|
+
account: accountParam,
|
|
286
|
+
},
|
|
287
|
+
}, async ({ calendarId, account }) => {
|
|
288
|
+
return runOrDiagnose(['calendar', 'delete-calendar', calendarId, '--force'], { account }); // gog gates this op; without --force the runner's --no-input makes it refuse
|
|
289
|
+
});
|
|
290
|
+
|
|
248
291
|
server.registerTool('gog_meet_participants', {
|
|
249
292
|
description: 'List participants from the latest (or a specific) Meet call.',
|
|
250
293
|
annotations: { readOnlyHint: true },
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
2
|
import { registerExtraCalendarTools } from '../../src/tools/calendar-extra.js';
|
|
3
3
|
import * as lib from '../../../gogcli-mcp/src/lib.js';
|
|
4
|
-
import {
|
|
4
|
+
import { createTestHarness, type TestHarness } from '@chrischall/mcp-utils/test';
|
|
5
|
+
import { rawTextResult } from '@chrischall/mcp-utils';
|
|
5
6
|
|
|
6
7
|
vi.mock('../../../gogcli-mcp/src/lib.js', async (importOriginal) => {
|
|
7
8
|
const actual = await importOriginal<typeof lib>();
|
|
@@ -11,22 +12,22 @@ vi.mock('../../../gogcli-mcp/src/lib.js', async (importOriginal) => {
|
|
|
11
12
|
};
|
|
12
13
|
});
|
|
13
14
|
|
|
14
|
-
let
|
|
15
|
+
let harness: TestHarness;
|
|
15
16
|
|
|
16
|
-
beforeEach(() => {
|
|
17
|
+
beforeEach(async () => {
|
|
17
18
|
vi.clearAllMocks();
|
|
18
|
-
vi.mocked(lib.runOrDiagnose).mockResolvedValue(
|
|
19
|
-
|
|
19
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
|
|
20
|
+
harness = await createTestHarness(registerExtraCalendarTools);
|
|
20
21
|
});
|
|
21
22
|
|
|
22
23
|
describe('gog_meet_create', () => {
|
|
23
24
|
it('calls runOrDiagnose with no flags', async () => {
|
|
24
|
-
await
|
|
25
|
+
await harness.callTool('gog_meet_create', {});
|
|
25
26
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['meet', 'create'], { account: undefined });
|
|
26
27
|
});
|
|
27
28
|
|
|
28
29
|
it('passes --access and --open when provided', async () => {
|
|
29
|
-
await
|
|
30
|
+
await harness.callTool('gog_meet_create', { access: 'open', open: true });
|
|
30
31
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
31
32
|
['meet', 'create', '--access=open', '--open'],
|
|
32
33
|
{ account: undefined },
|
|
@@ -34,21 +35,21 @@ describe('gog_meet_create', () => {
|
|
|
34
35
|
});
|
|
35
36
|
|
|
36
37
|
it('omits --open when false', async () => {
|
|
37
|
-
await
|
|
38
|
+
await harness.callTool('gog_meet_create', { open: false });
|
|
38
39
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['meet', 'create'], { account: undefined });
|
|
39
40
|
});
|
|
40
41
|
});
|
|
41
42
|
|
|
42
43
|
describe('gog_meet_get', () => {
|
|
43
44
|
it('calls runOrDiagnose with meetingCode', async () => {
|
|
44
|
-
await
|
|
45
|
+
await harness.callTool('gog_meet_get', { meetingCode: 'abc-defg-hij' });
|
|
45
46
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['meet', 'get', 'abc-defg-hij'], { account: undefined });
|
|
46
47
|
});
|
|
47
48
|
});
|
|
48
49
|
|
|
49
50
|
describe('gog_meet_update', () => {
|
|
50
51
|
it('calls runOrDiagnose with meetingCode and --access', async () => {
|
|
51
|
-
await
|
|
52
|
+
await harness.callTool('gog_meet_update', { meetingCode: 'abc-defg-hij', access: 'restricted' });
|
|
52
53
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
53
54
|
['meet', 'update', 'abc-defg-hij', '--access=restricted'],
|
|
54
55
|
{ account: undefined },
|
|
@@ -56,26 +57,26 @@ describe('gog_meet_update', () => {
|
|
|
56
57
|
});
|
|
57
58
|
|
|
58
59
|
it('omits --access when not provided', async () => {
|
|
59
|
-
await
|
|
60
|
+
await harness.callTool('gog_meet_update', { meetingCode: 'abc-defg-hij' });
|
|
60
61
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['meet', 'update', 'abc-defg-hij'], { account: undefined });
|
|
61
62
|
});
|
|
62
63
|
});
|
|
63
64
|
|
|
64
65
|
describe('gog_meet_end', () => {
|
|
65
66
|
it('calls runOrDiagnose with meetingCode', async () => {
|
|
66
|
-
await
|
|
67
|
-
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['meet', 'end', 'abc-defg-hij'], { account: undefined });
|
|
67
|
+
await harness.callTool('gog_meet_end', { meetingCode: 'abc-defg-hij' });
|
|
68
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['meet', 'end', 'abc-defg-hij', '--force'], { account: undefined });
|
|
68
69
|
});
|
|
69
70
|
});
|
|
70
71
|
|
|
71
72
|
describe('gog_meet_history', () => {
|
|
72
73
|
it('calls runOrDiagnose with meetingCode', async () => {
|
|
73
|
-
await
|
|
74
|
+
await harness.callTool('gog_meet_history', { meetingCode: 'abc-defg-hij' });
|
|
74
75
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['meet', 'history', 'abc-defg-hij'], { account: undefined });
|
|
75
76
|
});
|
|
76
77
|
|
|
77
78
|
it('passes pagination flags', async () => {
|
|
78
|
-
await
|
|
79
|
+
await harness.callTool('gog_meet_history', {
|
|
79
80
|
meetingCode: 'abc-defg-hij',
|
|
80
81
|
max: 50,
|
|
81
82
|
page: 'tok',
|
|
@@ -88,7 +89,7 @@ describe('gog_meet_history', () => {
|
|
|
88
89
|
});
|
|
89
90
|
|
|
90
91
|
it('omits --all when false', async () => {
|
|
91
|
-
await
|
|
92
|
+
await harness.callTool('gog_meet_history', { meetingCode: 'abc-defg-hij', all: false });
|
|
92
93
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['meet', 'history', 'abc-defg-hij'], { account: undefined });
|
|
93
94
|
});
|
|
94
95
|
});
|
|
@@ -97,7 +98,7 @@ describe('gog_meet_history', () => {
|
|
|
97
98
|
|
|
98
99
|
describe('gog_zoom_auth_setup', () => {
|
|
99
100
|
it('passes credentials and uses default alias when omitted', async () => {
|
|
100
|
-
await
|
|
101
|
+
await harness.callTool('gog_zoom_auth_setup', {
|
|
101
102
|
accountId: 'acct',
|
|
102
103
|
clientId: 'cid',
|
|
103
104
|
clientSecret: 'csecret',
|
|
@@ -112,7 +113,7 @@ describe('gog_zoom_auth_setup', () => {
|
|
|
112
113
|
});
|
|
113
114
|
|
|
114
115
|
it('passes --alias and --skip-validate when provided', async () => {
|
|
115
|
-
await
|
|
116
|
+
await harness.callTool('gog_zoom_auth_setup', {
|
|
116
117
|
accountId: 'acct', clientId: 'cid', clientSecret: 'csecret',
|
|
117
118
|
alias: 'work', skipValidate: true,
|
|
118
119
|
});
|
|
@@ -130,12 +131,12 @@ describe('gog_zoom_auth_setup', () => {
|
|
|
130
131
|
|
|
131
132
|
describe('gog_zoom_auth_doctor', () => {
|
|
132
133
|
it('validates default alias', async () => {
|
|
133
|
-
await
|
|
134
|
+
await harness.callTool('gog_zoom_auth_doctor', {});
|
|
134
135
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['zoom', 'auth', 'doctor'], { account: undefined });
|
|
135
136
|
});
|
|
136
137
|
|
|
137
138
|
it('passes --alias when provided', async () => {
|
|
138
|
-
await
|
|
139
|
+
await harness.callTool('gog_zoom_auth_doctor', { alias: 'work' });
|
|
139
140
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
140
141
|
['zoom', 'auth', 'doctor', '--alias=work'],
|
|
141
142
|
{ account: undefined },
|
|
@@ -147,12 +148,12 @@ describe('gog_zoom_auth_doctor', () => {
|
|
|
147
148
|
|
|
148
149
|
describe('gog_calendar_calendars', () => {
|
|
149
150
|
it('calls runOrDiagnose with no flags', async () => {
|
|
150
|
-
await
|
|
151
|
+
await harness.callTool('gog_calendar_calendars', {});
|
|
151
152
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['calendar', 'calendars'], { account: undefined });
|
|
152
153
|
});
|
|
153
154
|
|
|
154
155
|
it('passes pagination flags', async () => {
|
|
155
|
-
await
|
|
156
|
+
await harness.callTool('gog_calendar_calendars', { max: 50, page: 'tok', all: true });
|
|
156
157
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
157
158
|
['calendar', 'calendars', '--max=50', '--page=tok', '--all'],
|
|
158
159
|
{ account: undefined },
|
|
@@ -160,19 +161,19 @@ describe('gog_calendar_calendars', () => {
|
|
|
160
161
|
});
|
|
161
162
|
|
|
162
163
|
it('omits --all when false', async () => {
|
|
163
|
-
await
|
|
164
|
+
await harness.callTool('gog_calendar_calendars', { all: false });
|
|
164
165
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['calendar', 'calendars'], { account: undefined });
|
|
165
166
|
});
|
|
166
167
|
});
|
|
167
168
|
|
|
168
169
|
describe('gog_calendar_search', () => {
|
|
169
170
|
it('calls runOrDiagnose with just the query', async () => {
|
|
170
|
-
await
|
|
171
|
+
await harness.callTool('gog_calendar_search', { query: 'standup' });
|
|
171
172
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['calendar', 'search', 'standup'], { account: undefined });
|
|
172
173
|
});
|
|
173
174
|
|
|
174
175
|
it('passes all filter flags when provided', async () => {
|
|
175
|
-
await
|
|
176
|
+
await harness.callTool('gog_calendar_search', {
|
|
176
177
|
query: 'standup',
|
|
177
178
|
from: 'today',
|
|
178
179
|
to: 'tomorrow',
|
|
@@ -197,16 +198,43 @@ describe('gog_calendar_search', () => {
|
|
|
197
198
|
});
|
|
198
199
|
|
|
199
200
|
it('omits boolean flags when false', async () => {
|
|
200
|
-
await
|
|
201
|
+
await harness.callTool('gog_calendar_search', {
|
|
201
202
|
query: 'standup', today: false, tomorrow: false, week: false,
|
|
202
203
|
});
|
|
203
204
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['calendar', 'search', 'standup'], { account: undefined });
|
|
204
205
|
});
|
|
205
206
|
});
|
|
206
207
|
|
|
208
|
+
describe('gog_calendar_changed', () => {
|
|
209
|
+
it('calls runOrDiagnose with no flags by default', async () => {
|
|
210
|
+
await harness.callTool('gog_calendar_changed', {});
|
|
211
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['calendar', 'changed'], { account: undefined });
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('passes calendarId positionally and all flags', async () => {
|
|
215
|
+
await harness.callTool('gog_calendar_changed', {
|
|
216
|
+
calendarId: 'primary',
|
|
217
|
+
calendarIds: 'work,personal',
|
|
218
|
+
since: '48h',
|
|
219
|
+
max: 25,
|
|
220
|
+
all: true,
|
|
221
|
+
account: 'me@example.com',
|
|
222
|
+
});
|
|
223
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
224
|
+
['calendar', 'changed', 'primary', '--calendars=work,personal', '--since=48h', '--max=25', '--all'],
|
|
225
|
+
{ account: 'me@example.com' },
|
|
226
|
+
);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it('omits --all when false', async () => {
|
|
230
|
+
await harness.callTool('gog_calendar_changed', { all: false });
|
|
231
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['calendar', 'changed'], { account: undefined });
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
207
235
|
describe('gog_calendar_freebusy', () => {
|
|
208
236
|
it('calls runOrDiagnose with required from/to only', async () => {
|
|
209
|
-
await
|
|
237
|
+
await harness.callTool('gog_calendar_freebusy', { from: 'A', to: 'B' });
|
|
210
238
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
211
239
|
['calendar', 'freebusy', '--from=A', '--to=B'],
|
|
212
240
|
{ account: undefined },
|
|
@@ -214,7 +242,7 @@ describe('gog_calendar_freebusy', () => {
|
|
|
214
242
|
});
|
|
215
243
|
|
|
216
244
|
it('passes calendarIds and --all when provided', async () => {
|
|
217
|
-
await
|
|
245
|
+
await harness.callTool('gog_calendar_freebusy', {
|
|
218
246
|
from: 'A', to: 'B', calendarIds: 'primary,team@x.com', all: true,
|
|
219
247
|
});
|
|
220
248
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
@@ -224,7 +252,7 @@ describe('gog_calendar_freebusy', () => {
|
|
|
224
252
|
});
|
|
225
253
|
|
|
226
254
|
it('omits --all when false', async () => {
|
|
227
|
-
await
|
|
255
|
+
await harness.callTool('gog_calendar_freebusy', { from: 'A', to: 'B', all: false });
|
|
228
256
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
229
257
|
['calendar', 'freebusy', '--from=A', '--to=B'],
|
|
230
258
|
{ account: undefined },
|
|
@@ -234,19 +262,19 @@ describe('gog_calendar_freebusy', () => {
|
|
|
234
262
|
|
|
235
263
|
describe('gog_calendar_colors', () => {
|
|
236
264
|
it('calls runOrDiagnose with the colors subcommand', async () => {
|
|
237
|
-
await
|
|
265
|
+
await harness.callTool('gog_calendar_colors', {});
|
|
238
266
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['calendar', 'colors'], { account: undefined });
|
|
239
267
|
});
|
|
240
268
|
});
|
|
241
269
|
|
|
242
270
|
describe('gog_calendar_acl', () => {
|
|
243
271
|
it('calls runOrDiagnose with calendarId only', async () => {
|
|
244
|
-
await
|
|
272
|
+
await harness.callTool('gog_calendar_acl', { calendarId: 'primary' });
|
|
245
273
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['calendar', 'acl', 'primary'], { account: undefined });
|
|
246
274
|
});
|
|
247
275
|
|
|
248
276
|
it('passes pagination flags', async () => {
|
|
249
|
-
await
|
|
277
|
+
await harness.callTool('gog_calendar_acl', { calendarId: 'primary', max: 25, page: 'tok', all: true });
|
|
250
278
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
251
279
|
['calendar', 'acl', 'primary', '--max=25', '--page=tok', '--all'],
|
|
252
280
|
{ account: undefined },
|
|
@@ -254,14 +282,14 @@ describe('gog_calendar_acl', () => {
|
|
|
254
282
|
});
|
|
255
283
|
|
|
256
284
|
it('omits --all when false', async () => {
|
|
257
|
-
await
|
|
285
|
+
await harness.callTool('gog_calendar_acl', { calendarId: 'primary', all: false });
|
|
258
286
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['calendar', 'acl', 'primary'], { account: undefined });
|
|
259
287
|
});
|
|
260
288
|
});
|
|
261
289
|
|
|
262
290
|
describe('gog_calendar_move', () => {
|
|
263
291
|
it('calls runOrDiagnose with the three positionals', async () => {
|
|
264
|
-
await
|
|
292
|
+
await harness.callTool('gog_calendar_move', {
|
|
265
293
|
calendarId: 'primary', eventId: 'ev1', destinationCalendarId: 'team@x.com',
|
|
266
294
|
});
|
|
267
295
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
@@ -271,7 +299,7 @@ describe('gog_calendar_move', () => {
|
|
|
271
299
|
});
|
|
272
300
|
|
|
273
301
|
it('passes --send-updates when provided', async () => {
|
|
274
|
-
await
|
|
302
|
+
await harness.callTool('gog_calendar_move', {
|
|
275
303
|
calendarId: 'primary', eventId: 'ev1', destinationCalendarId: 'team@x.com',
|
|
276
304
|
sendUpdates: 'all',
|
|
277
305
|
});
|
|
@@ -284,7 +312,7 @@ describe('gog_calendar_move', () => {
|
|
|
284
312
|
|
|
285
313
|
describe('gog_calendar_out_of_office', () => {
|
|
286
314
|
it('calls runOrDiagnose with required from/to only', async () => {
|
|
287
|
-
await
|
|
315
|
+
await harness.callTool('gog_calendar_out_of_office', { from: '2026-06-01', to: '2026-06-05' });
|
|
288
316
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
289
317
|
['calendar', 'out-of-office', '--from=2026-06-01', '--to=2026-06-05'],
|
|
290
318
|
{ account: undefined },
|
|
@@ -292,7 +320,7 @@ describe('gog_calendar_out_of_office', () => {
|
|
|
292
320
|
});
|
|
293
321
|
|
|
294
322
|
it('passes calendarId and all optional flags when provided', async () => {
|
|
295
|
-
await
|
|
323
|
+
await harness.callTool('gog_calendar_out_of_office', {
|
|
296
324
|
from: '2026-06-01', to: '2026-06-05',
|
|
297
325
|
calendarId: 'primary',
|
|
298
326
|
summary: 'Vacation',
|
|
@@ -312,7 +340,7 @@ describe('gog_calendar_out_of_office', () => {
|
|
|
312
340
|
});
|
|
313
341
|
|
|
314
342
|
it('omits --all-day when false', async () => {
|
|
315
|
-
await
|
|
343
|
+
await harness.callTool('gog_calendar_out_of_office', { from: '2026-06-01', to: '2026-06-05', allDay: false });
|
|
316
344
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
317
345
|
['calendar', 'out-of-office', '--from=2026-06-01', '--to=2026-06-05'],
|
|
318
346
|
{ account: undefined },
|
|
@@ -322,7 +350,7 @@ describe('gog_calendar_out_of_office', () => {
|
|
|
322
350
|
|
|
323
351
|
describe('gog_meet_participants', () => {
|
|
324
352
|
it('calls runOrDiagnose with meetingCode', async () => {
|
|
325
|
-
await
|
|
353
|
+
await harness.callTool('gog_meet_participants', { meetingCode: 'abc-defg-hij' });
|
|
326
354
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
327
355
|
['meet', 'participants', 'abc-defg-hij'],
|
|
328
356
|
{ account: undefined },
|
|
@@ -330,7 +358,7 @@ describe('gog_meet_participants', () => {
|
|
|
330
358
|
});
|
|
331
359
|
|
|
332
360
|
it('passes --conference and pagination flags', async () => {
|
|
333
|
-
await
|
|
361
|
+
await harness.callTool('gog_meet_participants', {
|
|
334
362
|
meetingCode: 'abc-defg-hij',
|
|
335
363
|
conference: 'conf123',
|
|
336
364
|
max: 100,
|
|
@@ -350,10 +378,46 @@ describe('gog_meet_participants', () => {
|
|
|
350
378
|
});
|
|
351
379
|
|
|
352
380
|
it('omits --all when false', async () => {
|
|
353
|
-
await
|
|
381
|
+
await harness.callTool('gog_meet_participants', { meetingCode: 'abc-defg-hij', all: false });
|
|
354
382
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
355
383
|
['meet', 'participants', 'abc-defg-hij'],
|
|
356
384
|
{ account: undefined },
|
|
357
385
|
);
|
|
358
386
|
});
|
|
359
387
|
});
|
|
388
|
+
|
|
389
|
+
describe('gog_calendar_unsubscribe', () => {
|
|
390
|
+
it('calls runOrDiagnose with calendarId', async () => {
|
|
391
|
+
await harness.callTool('gog_calendar_unsubscribe', { calendarId: 'cal@group.calendar.google.com' });
|
|
392
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
393
|
+
['calendar', 'unsubscribe', 'cal@group.calendar.google.com'],
|
|
394
|
+
{ account: undefined },
|
|
395
|
+
);
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
it('passes account through', async () => {
|
|
399
|
+
await harness.callTool('gog_calendar_unsubscribe', { calendarId: 'cal', account: 'me@x.com' });
|
|
400
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
401
|
+
['calendar', 'unsubscribe', 'cal'],
|
|
402
|
+
{ account: 'me@x.com' },
|
|
403
|
+
);
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
describe('gog_calendar_delete_calendar', () => {
|
|
408
|
+
it('calls runOrDiagnose with calendarId', async () => {
|
|
409
|
+
await harness.callTool('gog_calendar_delete_calendar', { calendarId: 'cal' });
|
|
410
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
411
|
+
['calendar', 'delete-calendar', 'cal', '--force'],
|
|
412
|
+
{ account: undefined },
|
|
413
|
+
);
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
it('passes account through', async () => {
|
|
417
|
+
await harness.callTool('gog_calendar_delete_calendar', { calendarId: 'cal', account: 'me@x.com' });
|
|
418
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
419
|
+
['calendar', 'delete-calendar', 'cal', '--force'],
|
|
420
|
+
{ account: 'me@x.com' },
|
|
421
|
+
);
|
|
422
|
+
});
|
|
423
|
+
});
|
package/tsconfig.json
CHANGED