gogcli-mcp 2.0.10 → 2.0.12

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.
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "metadata": {
9
9
  "description": "Google Sheets (and more) for Claude via gogcli — read, write, and manage spreadsheets",
10
- "version": "2.0.10"
10
+ "version": "2.0.12"
11
11
  },
12
12
  "plugins": [
13
13
  {
@@ -15,7 +15,7 @@
15
15
  "displayName": "gogcli",
16
16
  "source": "./",
17
17
  "description": "Google Sheets (and more) for Claude via gogcli — read, write, and manage spreadsheets",
18
- "version": "2.0.10",
18
+ "version": "2.0.12",
19
19
  "author": {
20
20
  "name": "Chris Hall"
21
21
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gogcli-mcp",
3
3
  "displayName": "gogcli",
4
- "version": "2.0.10",
4
+ "version": "2.0.12",
5
5
  "description": "Google Sheets (and more) for Claude via gogcli — read, write, and manage spreadsheets",
6
6
  "author": {
7
7
  "name": "Chris Hall",
package/README.md CHANGED
@@ -3,13 +3,13 @@
3
3
  > [!WARNING]
4
4
  > **AI-developed project.** This codebase was built and is actively maintained by [Claude Code](https://www.anthropic.com/claude). Review all code and tool permissions before use.
5
5
 
6
- Base [Model Context Protocol](https://modelcontextprotocol.io) server that gives Claude access to Google Workspace via [gogcli](https://github.com/steipete/gogcli). Includes 52 tools across 8 services: Sheets, Docs, Gmail, Calendar, Drive, Tasks, Contacts, and Auth.
6
+ Base [Model Context Protocol](https://modelcontextprotocol.io) server that gives Claude access to Google Workspace via [gogcli](https://github.com/openclaw/gogcli). Includes 52 tools across 8 services: Sheets, Docs, Gmail, Calendar, Drive, Tasks, Contacts, and Auth.
7
7
 
8
8
  For extended Sheets or Docs support, see [gogcli-mcp-sheets](https://www.npmjs.com/package/gogcli-mcp-sheets) and [gogcli-mcp-docs](https://www.npmjs.com/package/gogcli-mcp-docs).
9
9
 
10
10
  ## Requirements
11
11
 
12
- - [gogcli](https://github.com/steipete/gogcli) installed and authenticated
12
+ - [gogcli](https://github.com/openclaw/gogcli) installed and authenticated
13
13
  - Node.js 18+
14
14
 
15
15
  ```bash
package/SKILL.md CHANGED
@@ -5,13 +5,13 @@ description: Use when the user asks to interact with Google Workspace services.
5
5
 
6
6
  # gogcli-mcp
7
7
 
8
- MCP server wrapping [gogcli](https://github.com/steipete/gogcli) — provides Claude with access to Google Sheets, Docs, Gmail, Calendar, Drive, Tasks, Contacts, and Auth.
8
+ MCP server wrapping [gogcli](https://github.com/openclaw/gogcli) — provides Claude with access to Google Sheets, Docs, Gmail, Calendar, Drive, Tasks, Contacts, and Auth.
9
9
 
10
10
  - **Source:** [github.com/chrischall/gogcli-mcp](https://github.com/chrischall/gogcli-mcp)
11
11
 
12
12
  ## Requirements
13
13
 
14
- - [gogcli](https://github.com/steipete/gogcli) installed and authenticated
14
+ - [gogcli](https://github.com/openclaw/gogcli) installed and authenticated
15
15
  - Node.js 18 or later
16
16
 
17
17
  ## Setup
package/dist/index.js CHANGED
@@ -31063,7 +31063,7 @@ async function run(args, options = {}) {
31063
31063
  settled = true;
31064
31064
  if (err.code === "ENOENT") {
31065
31065
  reject(new Error(
31066
- "gog executable not found. Install gogcli (https://github.com/steipete/gogcli) or set GOG_PATH in your MCP client config to the absolute binary path (run `which gog` in a terminal to find it)."
31066
+ "gog executable not found. Install gogcli (https://github.com/openclaw/gogcli) or set GOG_PATH in your MCP client config to the absolute binary path (run `which gog` in a terminal to find it)."
31067
31067
  ));
31068
31068
  return;
31069
31069
  }
@@ -31254,7 +31254,7 @@ function registerCalendarTools(server2) {
31254
31254
  return runOrDiagnose(["calendar", "event", calendarId, eventId], { account });
31255
31255
  });
31256
31256
  server2.registerTool("gog_calendar_create", {
31257
- description: "Create a calendar event.",
31257
+ description: "Create a calendar event. Set withZoom=true to attach a Zoom meeting (requires Zoom S2S OAuth setup via gog_zoom_auth_setup; the join URL + meeting ID + passcode are appended to the event description \u2014 Google rejects native conference card writes from non-Workspace-Marketplace OAuth clients).",
31258
31258
  annotations: { destructiveHint: false },
31259
31259
  inputSchema: {
31260
31260
  calendarId: external_exports.string().describe('Calendar ID (use "primary" for the default calendar)'),
@@ -31265,18 +31265,20 @@ function registerCalendarTools(server2) {
31265
31265
  location: external_exports.string().optional().describe("Event location"),
31266
31266
  attendees: external_exports.string().optional().describe("Attendee emails, comma-separated"),
31267
31267
  allDay: external_exports.boolean().optional().describe("All-day event (use date-only in from/to)"),
31268
+ withZoom: external_exports.boolean().optional().describe("Create a Zoom video conference for this event (requires Zoom S2S OAuth setup)"),
31268
31269
  account: accountParam
31269
31270
  }
31270
- }, async ({ calendarId, summary, from, to, description, location, attendees, allDay, account }) => {
31271
+ }, async ({ calendarId, summary, from, to, description, location, attendees, allDay, withZoom, account }) => {
31271
31272
  const args = ["calendar", "create", calendarId, `--summary=${summary}`, `--from=${from}`, `--to=${to}`];
31272
31273
  if (description) args.push(`--description=${description}`);
31273
31274
  if (location) args.push(`--location=${location}`);
31274
31275
  if (attendees) args.push(`--attendees=${attendees}`);
31275
31276
  if (allDay) args.push("--all-day");
31277
+ if (withZoom) args.push("--with-zoom");
31276
31278
  return runOrDiagnose(args, { account });
31277
31279
  });
31278
31280
  server2.registerTool("gog_calendar_update", {
31279
- description: "Update an existing calendar event.",
31281
+ description: "Update an existing calendar event. Zoom: withZoom adds a Zoom meeting, regenerateZoom replaces the existing one, removeZoom strips it (each are independent \u2014 use one per call).",
31280
31282
  annotations: { destructiveHint: false },
31281
31283
  inputSchema: {
31282
31284
  calendarId: external_exports.string().describe("Calendar ID"),
@@ -31287,9 +31289,12 @@ function registerCalendarTools(server2) {
31287
31289
  description: external_exports.string().optional().describe("New description"),
31288
31290
  location: external_exports.string().optional().describe("New location"),
31289
31291
  attendees: external_exports.string().optional().describe("New attendee emails, comma-separated (replaces existing)"),
31292
+ withZoom: external_exports.boolean().optional().describe("Create a Zoom video conference for this event"),
31293
+ regenerateZoom: external_exports.boolean().optional().describe("Replace the event's existing Zoom video conference"),
31294
+ removeZoom: external_exports.boolean().optional().describe("Remove the event's Zoom video conference"),
31290
31295
  account: accountParam
31291
31296
  }
31292
- }, async ({ calendarId, eventId, summary, from, to, description, location, attendees, account }) => {
31297
+ }, async ({ calendarId, eventId, summary, from, to, description, location, attendees, withZoom, regenerateZoom, removeZoom, account }) => {
31293
31298
  const args = ["calendar", "update", calendarId, eventId];
31294
31299
  if (summary !== void 0) args.push(`--summary=${summary}`);
31295
31300
  if (from !== void 0) args.push(`--from=${from}`);
@@ -31297,6 +31302,9 @@ function registerCalendarTools(server2) {
31297
31302
  if (description !== void 0) args.push(`--description=${description}`);
31298
31303
  if (location !== void 0) args.push(`--location=${location}`);
31299
31304
  if (attendees !== void 0) args.push(`--attendees=${attendees}`);
31305
+ if (withZoom) args.push("--with-zoom");
31306
+ if (regenerateZoom) args.push("--regenerate-zoom");
31307
+ if (removeZoom) args.push("--remove-zoom");
31300
31308
  return runOrDiagnose(args, { account });
31301
31309
  });
31302
31310
  server2.registerTool("gog_calendar_delete", {
@@ -32224,7 +32232,7 @@ function registerTasksTools(server2) {
32224
32232
  }
32225
32233
 
32226
32234
  // src/server.ts
32227
- var VERSION = true ? "2.0.10" : "0.0.0";
32235
+ var VERSION = true ? "2.0.12" : "0.0.0";
32228
32236
  function createServer(options) {
32229
32237
  return new McpServer({
32230
32238
  name: options?.name ?? "gogcli",
package/dist/lib.js CHANGED
@@ -30970,7 +30970,7 @@ async function run(args, options = {}) {
30970
30970
  settled = true;
30971
30971
  if (err.code === "ENOENT") {
30972
30972
  reject(new Error(
30973
- "gog executable not found. Install gogcli (https://github.com/steipete/gogcli) or set GOG_PATH in your MCP client config to the absolute binary path (run `which gog` in a terminal to find it)."
30973
+ "gog executable not found. Install gogcli (https://github.com/openclaw/gogcli) or set GOG_PATH in your MCP client config to the absolute binary path (run `which gog` in a terminal to find it)."
30974
30974
  ));
30975
30975
  return;
30976
30976
  }
@@ -31166,7 +31166,7 @@ function registerCalendarTools(server) {
31166
31166
  return runOrDiagnose(["calendar", "event", calendarId, eventId], { account });
31167
31167
  });
31168
31168
  server.registerTool("gog_calendar_create", {
31169
- description: "Create a calendar event.",
31169
+ description: "Create a calendar event. Set withZoom=true to attach a Zoom meeting (requires Zoom S2S OAuth setup via gog_zoom_auth_setup; the join URL + meeting ID + passcode are appended to the event description \u2014 Google rejects native conference card writes from non-Workspace-Marketplace OAuth clients).",
31170
31170
  annotations: { destructiveHint: false },
31171
31171
  inputSchema: {
31172
31172
  calendarId: external_exports.string().describe('Calendar ID (use "primary" for the default calendar)'),
@@ -31177,18 +31177,20 @@ function registerCalendarTools(server) {
31177
31177
  location: external_exports.string().optional().describe("Event location"),
31178
31178
  attendees: external_exports.string().optional().describe("Attendee emails, comma-separated"),
31179
31179
  allDay: external_exports.boolean().optional().describe("All-day event (use date-only in from/to)"),
31180
+ withZoom: external_exports.boolean().optional().describe("Create a Zoom video conference for this event (requires Zoom S2S OAuth setup)"),
31180
31181
  account: accountParam
31181
31182
  }
31182
- }, async ({ calendarId, summary, from, to, description, location, attendees, allDay, account }) => {
31183
+ }, async ({ calendarId, summary, from, to, description, location, attendees, allDay, withZoom, account }) => {
31183
31184
  const args = ["calendar", "create", calendarId, `--summary=${summary}`, `--from=${from}`, `--to=${to}`];
31184
31185
  if (description) args.push(`--description=${description}`);
31185
31186
  if (location) args.push(`--location=${location}`);
31186
31187
  if (attendees) args.push(`--attendees=${attendees}`);
31187
31188
  if (allDay) args.push("--all-day");
31189
+ if (withZoom) args.push("--with-zoom");
31188
31190
  return runOrDiagnose(args, { account });
31189
31191
  });
31190
31192
  server.registerTool("gog_calendar_update", {
31191
- description: "Update an existing calendar event.",
31193
+ description: "Update an existing calendar event. Zoom: withZoom adds a Zoom meeting, regenerateZoom replaces the existing one, removeZoom strips it (each are independent \u2014 use one per call).",
31192
31194
  annotations: { destructiveHint: false },
31193
31195
  inputSchema: {
31194
31196
  calendarId: external_exports.string().describe("Calendar ID"),
@@ -31199,9 +31201,12 @@ function registerCalendarTools(server) {
31199
31201
  description: external_exports.string().optional().describe("New description"),
31200
31202
  location: external_exports.string().optional().describe("New location"),
31201
31203
  attendees: external_exports.string().optional().describe("New attendee emails, comma-separated (replaces existing)"),
31204
+ withZoom: external_exports.boolean().optional().describe("Create a Zoom video conference for this event"),
31205
+ regenerateZoom: external_exports.boolean().optional().describe("Replace the event's existing Zoom video conference"),
31206
+ removeZoom: external_exports.boolean().optional().describe("Remove the event's Zoom video conference"),
31202
31207
  account: accountParam
31203
31208
  }
31204
- }, async ({ calendarId, eventId, summary, from, to, description, location, attendees, account }) => {
31209
+ }, async ({ calendarId, eventId, summary, from, to, description, location, attendees, withZoom, regenerateZoom, removeZoom, account }) => {
31205
31210
  const args = ["calendar", "update", calendarId, eventId];
31206
31211
  if (summary !== void 0) args.push(`--summary=${summary}`);
31207
31212
  if (from !== void 0) args.push(`--from=${from}`);
@@ -31209,6 +31214,9 @@ function registerCalendarTools(server) {
31209
31214
  if (description !== void 0) args.push(`--description=${description}`);
31210
31215
  if (location !== void 0) args.push(`--location=${location}`);
31211
31216
  if (attendees !== void 0) args.push(`--attendees=${attendees}`);
31217
+ if (withZoom) args.push("--with-zoom");
31218
+ if (regenerateZoom) args.push("--regenerate-zoom");
31219
+ if (removeZoom) args.push("--remove-zoom");
31212
31220
  return runOrDiagnose(args, { account });
31213
31221
  });
31214
31222
  server.registerTool("gog_calendar_delete", {
@@ -32136,7 +32144,7 @@ function registerTasksTools(server) {
32136
32144
  }
32137
32145
 
32138
32146
  // src/server.ts
32139
- var VERSION = true ? "2.0.10" : "0.0.0";
32147
+ var VERSION = true ? "2.0.12" : "0.0.0";
32140
32148
  function createServer(options) {
32141
32149
  return new McpServer({
32142
32150
  name: options?.name ?? "gogcli",
package/manifest.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "manifest_version": "0.3",
4
4
  "name": "gogcli-mcp",
5
5
  "display_name": "gogcli",
6
- "version": "2.0.10",
6
+ "version": "2.0.12",
7
7
  "description": "Google Sheets (and more) for Claude via gogcli — read, write, and manage spreadsheets",
8
8
  "author": {
9
9
  "name": "Chris Hall",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gogcli-mcp",
3
- "version": "2.0.10",
3
+ "version": "2.0.12",
4
4
  "mcpName": "io.github.chrischall/gogcli-mcp",
5
5
  "description": "MCP server wrapping gogcli for Google service access",
6
6
  "author": "Claude Code (AI) <https://www.anthropic.com/claude>",
package/server.json CHANGED
@@ -7,12 +7,12 @@
7
7
  "source": "github",
8
8
  "subfolder": "packages/gogcli-mcp"
9
9
  },
10
- "version": "2.0.10",
10
+ "version": "2.0.12",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "gogcli-mcp",
15
- "version": "2.0.10",
15
+ "version": "2.0.12",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  },
@@ -5,13 +5,13 @@ description: Use when the user asks to read, write, or manage Google Sheets. Als
5
5
 
6
6
  # gogcli-mcp
7
7
 
8
- MCP server wrapping [gogcli](https://github.com/steipete/gogcli) — provides Claude with access to Google Sheets (and a scaffold for Gmail, Calendar, Drive, and more).
8
+ MCP server wrapping [gogcli](https://github.com/openclaw/gogcli) — provides Claude with access to Google Sheets (and a scaffold for Gmail, Calendar, Drive, and more).
9
9
 
10
10
  - **Source:** [github.com/chrischall/gogcli-mcp](https://github.com/chrischall/gogcli-mcp)
11
11
 
12
12
  ## Requirements
13
13
 
14
- - [gogcli](https://github.com/steipete/gogcli) installed and authenticated (`gog --help` works in your shell)
14
+ - [gogcli](https://github.com/openclaw/gogcli) installed and authenticated (`gog --help` works in your shell)
15
15
  - Node.js 18 or later
16
16
 
17
17
  ## Setup
package/src/runner.ts CHANGED
@@ -151,7 +151,7 @@ export async function run(args: string[], options: RunOptions = {}): Promise<str
151
151
  settled = true;
152
152
  if ((err as NodeJS.ErrnoException).code === 'ENOENT') {
153
153
  reject(new Error(
154
- 'gog executable not found. Install gogcli (https://github.com/steipete/gogcli) ' +
154
+ 'gog executable not found. Install gogcli (https://github.com/openclaw/gogcli) ' +
155
155
  'or set GOG_PATH in your MCP client config to the absolute binary path ' +
156
156
  '(run `which gog` in a terminal to find it).',
157
157
  ));
@@ -39,7 +39,7 @@ export function registerCalendarTools(server: McpServer): void {
39
39
  });
40
40
 
41
41
  server.registerTool('gog_calendar_create', {
42
- description: 'Create a calendar event.',
42
+ description: 'Create a calendar event. Set withZoom=true to attach a Zoom meeting (requires Zoom S2S OAuth setup via gog_zoom_auth_setup; the join URL + meeting ID + passcode are appended to the event description — Google rejects native conference card writes from non-Workspace-Marketplace OAuth clients).',
43
43
  annotations: { destructiveHint: false },
44
44
  inputSchema: {
45
45
  calendarId: z.string().describe('Calendar ID (use "primary" for the default calendar)'),
@@ -50,19 +50,21 @@ export function registerCalendarTools(server: McpServer): void {
50
50
  location: z.string().optional().describe('Event location'),
51
51
  attendees: z.string().optional().describe('Attendee emails, comma-separated'),
52
52
  allDay: z.boolean().optional().describe('All-day event (use date-only in from/to)'),
53
+ withZoom: z.boolean().optional().describe('Create a Zoom video conference for this event (requires Zoom S2S OAuth setup)'),
53
54
  account: accountParam,
54
55
  },
55
- }, async ({ calendarId, summary, from, to, description, location, attendees, allDay, account }) => {
56
+ }, async ({ calendarId, summary, from, to, description, location, attendees, allDay, withZoom, account }) => {
56
57
  const args = ['calendar', 'create', calendarId, `--summary=${summary}`, `--from=${from}`, `--to=${to}`];
57
58
  if (description) args.push(`--description=${description}`);
58
59
  if (location) args.push(`--location=${location}`);
59
60
  if (attendees) args.push(`--attendees=${attendees}`);
60
61
  if (allDay) args.push('--all-day');
62
+ if (withZoom) args.push('--with-zoom');
61
63
  return runOrDiagnose(args, { account });
62
64
  });
63
65
 
64
66
  server.registerTool('gog_calendar_update', {
65
- description: 'Update an existing calendar event.',
67
+ description: 'Update an existing calendar event. Zoom: withZoom adds a Zoom meeting, regenerateZoom replaces the existing one, removeZoom strips it (each are independent — use one per call).',
66
68
  annotations: { destructiveHint: false },
67
69
  inputSchema: {
68
70
  calendarId: z.string().describe('Calendar ID'),
@@ -73,9 +75,12 @@ export function registerCalendarTools(server: McpServer): void {
73
75
  description: z.string().optional().describe('New description'),
74
76
  location: z.string().optional().describe('New location'),
75
77
  attendees: z.string().optional().describe('New attendee emails, comma-separated (replaces existing)'),
78
+ withZoom: z.boolean().optional().describe('Create a Zoom video conference for this event'),
79
+ regenerateZoom: z.boolean().optional().describe('Replace the event\'s existing Zoom video conference'),
80
+ removeZoom: z.boolean().optional().describe('Remove the event\'s Zoom video conference'),
76
81
  account: accountParam,
77
82
  },
78
- }, async ({ calendarId, eventId, summary, from, to, description, location, attendees, account }) => {
83
+ }, async ({ calendarId, eventId, summary, from, to, description, location, attendees, withZoom, regenerateZoom, removeZoom, account }) => {
79
84
  const args = ['calendar', 'update', calendarId, eventId];
80
85
  if (summary !== undefined) args.push(`--summary=${summary}`);
81
86
  if (from !== undefined) args.push(`--from=${from}`);
@@ -83,6 +88,9 @@ export function registerCalendarTools(server: McpServer): void {
83
88
  if (description !== undefined) args.push(`--description=${description}`);
84
89
  if (location !== undefined) args.push(`--location=${location}`);
85
90
  if (attendees !== undefined) args.push(`--attendees=${attendees}`);
91
+ if (withZoom) args.push('--with-zoom');
92
+ if (regenerateZoom) args.push('--regenerate-zoom');
93
+ if (removeZoom) args.push('--remove-zoom');
86
94
  return runOrDiagnose(args, { account });
87
95
  });
88
96
 
@@ -97,6 +97,41 @@ describe('gog_calendar_create', () => {
97
97
  );
98
98
  });
99
99
 
100
+ // gog 0.18.0: --with-zoom attaches a Zoom conference via description-mode
101
+ // integration (native conference card not supported for non-Workspace-Marketplace
102
+ // OAuth clients).
103
+ it('passes --with-zoom when withZoom is true', async () => {
104
+ vi.mocked(runner.run).mockResolvedValue('{}');
105
+ const handlers = setupHandlers();
106
+ await handlers.get('gog_calendar_create')!({
107
+ calendarId: 'primary',
108
+ summary: 'Sync',
109
+ from: '2026-04-14T09:00:00Z',
110
+ to: '2026-04-14T09:30:00Z',
111
+ withZoom: true,
112
+ });
113
+ expect(runner.run).toHaveBeenCalledWith(
114
+ [
115
+ 'calendar', 'create', 'primary',
116
+ '--summary=Sync', '--from=2026-04-14T09:00:00Z', '--to=2026-04-14T09:30:00Z',
117
+ '--with-zoom',
118
+ ],
119
+ { account: undefined },
120
+ );
121
+ });
122
+
123
+ it('omits --with-zoom when false', async () => {
124
+ vi.mocked(runner.run).mockResolvedValue('{}');
125
+ const handlers = setupHandlers();
126
+ await handlers.get('gog_calendar_create')!({
127
+ calendarId: 'primary', summary: 's', from: 'f', to: 't', withZoom: false,
128
+ });
129
+ expect(runner.run).toHaveBeenCalledWith(
130
+ ['calendar', 'create', 'primary', '--summary=s', '--from=f', '--to=t'],
131
+ { account: undefined },
132
+ );
133
+ });
134
+
100
135
  it('returns error text on failure', async () => {
101
136
  vi.mocked(runner.run).mockRejectedValue(new Error('Create failed'));
102
137
  const handlers = setupHandlers();
@@ -143,6 +178,52 @@ describe('gog_calendar_update', () => {
143
178
  );
144
179
  });
145
180
 
181
+ // gog 0.18.0 Zoom flags: with-zoom adds, regenerate-zoom replaces, remove-zoom strips.
182
+ it('passes --with-zoom / --regenerate-zoom / --remove-zoom independently', async () => {
183
+ vi.mocked(runner.run).mockResolvedValue('{}');
184
+ const handlers = setupHandlers();
185
+ await handlers.get('gog_calendar_update')!({
186
+ calendarId: 'primary', eventId: 'evt1', withZoom: true,
187
+ });
188
+ expect(runner.run).toHaveBeenCalledWith(
189
+ ['calendar', 'update', 'primary', 'evt1', '--with-zoom'],
190
+ { account: undefined },
191
+ );
192
+
193
+ vi.clearAllMocks();
194
+ vi.mocked(runner.run).mockResolvedValue('{}');
195
+ await handlers.get('gog_calendar_update')!({
196
+ calendarId: 'primary', eventId: 'evt1', regenerateZoom: true,
197
+ });
198
+ expect(runner.run).toHaveBeenCalledWith(
199
+ ['calendar', 'update', 'primary', 'evt1', '--regenerate-zoom'],
200
+ { account: undefined },
201
+ );
202
+
203
+ vi.clearAllMocks();
204
+ vi.mocked(runner.run).mockResolvedValue('{}');
205
+ await handlers.get('gog_calendar_update')!({
206
+ calendarId: 'primary', eventId: 'evt1', removeZoom: true,
207
+ });
208
+ expect(runner.run).toHaveBeenCalledWith(
209
+ ['calendar', 'update', 'primary', 'evt1', '--remove-zoom'],
210
+ { account: undefined },
211
+ );
212
+ });
213
+
214
+ it('omits zoom flags when all false', async () => {
215
+ vi.mocked(runner.run).mockResolvedValue('{}');
216
+ const handlers = setupHandlers();
217
+ await handlers.get('gog_calendar_update')!({
218
+ calendarId: 'primary', eventId: 'evt1',
219
+ withZoom: false, regenerateZoom: false, removeZoom: false,
220
+ });
221
+ expect(runner.run).toHaveBeenCalledWith(
222
+ ['calendar', 'update', 'primary', 'evt1'],
223
+ { account: undefined },
224
+ );
225
+ });
226
+
146
227
  it('returns error text on failure', async () => {
147
228
  vi.mocked(runner.run).mockRejectedValue(new Error('Update failed'));
148
229
  const handlers = setupHandlers();