gogcli-mcp 2.6.0 → 2.7.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.
@@ -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.6.0"
10
+ "version": "2.7.0"
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.6.0",
18
+ "version": "2.7.0",
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.6.0",
4
+ "version": "2.7.0",
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/dist/index.js CHANGED
@@ -31304,12 +31304,13 @@ function registerCalendarTools(server2) {
31304
31304
  description: external_exports.string().optional().describe("New description"),
31305
31305
  location: external_exports.string().optional().describe("New location"),
31306
31306
  attendees: external_exports.string().optional().describe("New attendee emails, comma-separated (replaces existing)"),
31307
+ attachments: external_exports.array(external_exports.string()).optional().describe("File attachment URLs (e.g. Drive links). Replaces ALL existing attachments; pass a single empty string to clear them."),
31307
31308
  withZoom: external_exports.boolean().optional().describe("Create a Zoom video conference for this event"),
31308
31309
  regenerateZoom: external_exports.boolean().optional().describe("Replace the event's existing Zoom video conference"),
31309
31310
  removeZoom: external_exports.boolean().optional().describe("Remove the event's Zoom video conference"),
31310
31311
  account: accountParam
31311
31312
  }
31312
- }, async ({ calendarId, eventId, summary, from, to, description, location, attendees, withZoom, regenerateZoom, removeZoom, account }) => {
31313
+ }, async ({ calendarId, eventId, summary, from, to, description, location, attendees, attachments, withZoom, regenerateZoom, removeZoom, account }) => {
31313
31314
  const args = ["calendar", "update", calendarId, eventId];
31314
31315
  if (summary !== void 0) args.push(`--summary=${summary}`);
31315
31316
  if (from !== void 0) args.push(`--from=${from}`);
@@ -31317,6 +31318,7 @@ function registerCalendarTools(server2) {
31317
31318
  if (description !== void 0) args.push(`--description=${description}`);
31318
31319
  if (location !== void 0) args.push(`--location=${location}`);
31319
31320
  if (attendees !== void 0) args.push(`--attendees=${attendees}`);
31321
+ if (attachments) for (const a of attachments) args.push(`--attachment=${a}`);
31320
31322
  if (withZoom) args.push("--with-zoom");
31321
31323
  if (regenerateZoom) args.push("--regenerate-zoom");
31322
31324
  if (removeZoom) args.push("--remove-zoom");
@@ -31813,11 +31815,13 @@ function registerDocsTools(server2) {
31813
31815
  docId: external_exports.string().describe("Doc ID (from the URL)"),
31814
31816
  text: external_exports.string().describe("Text content to write"),
31815
31817
  append: external_exports.boolean().optional().describe("Append to existing content instead of replacing (default: false)"),
31818
+ checkOrphans: external_exports.boolean().optional().describe("Block the write (exit code 11) if it would orphan an open comment \u2014 i.e. remove the text the comment is anchored to. Recommended for replacement writes on commented docs."),
31816
31819
  account: accountParam
31817
31820
  }
31818
- }, async ({ docId, text, append, account }) => {
31821
+ }, async ({ docId, text, append, checkOrphans, account }) => {
31819
31822
  const args = ["docs", "write", docId, `--text=${text}`];
31820
31823
  if (append) args.push("--append");
31824
+ if (checkOrphans) args.push("--check-orphans");
31821
31825
  return runOrDiagnose(args, { account });
31822
31826
  });
31823
31827
  server2.registerTool("gog_docs_find_replace", {
@@ -31984,7 +31988,7 @@ function registerGmailTools(server2) {
31984
31988
  return runOrDiagnose(args, { account });
31985
31989
  });
31986
31990
  server2.registerTool("gog_gmail_send", {
31987
- description: "Send an email.",
31991
+ description: "Send an email. When attach is used, the JSON result echoes the attached filenames and byte sizes \u2014 check it to confirm the files were found and embedded.",
31988
31992
  annotations: { destructiveHint: true },
31989
31993
  inputSchema: {
31990
31994
  to: external_exports.string().describe("Recipient(s), comma-separated"),
@@ -32326,7 +32330,7 @@ function registerTasksTools(server2) {
32326
32330
  }
32327
32331
 
32328
32332
  // src/server.ts
32329
- var VERSION = true ? "2.6.0" : "0.0.0";
32333
+ var VERSION = true ? "2.7.0" : "0.0.0";
32330
32334
  function createServer(options) {
32331
32335
  return new McpServer({
32332
32336
  name: options?.name ?? "gogcli",
package/dist/lib.js CHANGED
@@ -30859,7 +30859,7 @@ var EMPTY_COMPLETION_RESULT = {
30859
30859
  import { spawn } from "node:child_process";
30860
30860
  import { delimiter } from "node:path";
30861
30861
  var TIMEOUT_MS = 3e4;
30862
- var MIN_GOG_VERSION = "0.23.0";
30862
+ var MIN_GOG_VERSION = "0.24.0";
30863
30863
  function envOrUndefined(key) {
30864
30864
  const value = process.env[key];
30865
30865
  if (!value || value.startsWith("${")) return void 0;
@@ -31217,12 +31217,13 @@ function registerCalendarTools(server) {
31217
31217
  description: external_exports.string().optional().describe("New description"),
31218
31218
  location: external_exports.string().optional().describe("New location"),
31219
31219
  attendees: external_exports.string().optional().describe("New attendee emails, comma-separated (replaces existing)"),
31220
+ attachments: external_exports.array(external_exports.string()).optional().describe("File attachment URLs (e.g. Drive links). Replaces ALL existing attachments; pass a single empty string to clear them."),
31220
31221
  withZoom: external_exports.boolean().optional().describe("Create a Zoom video conference for this event"),
31221
31222
  regenerateZoom: external_exports.boolean().optional().describe("Replace the event's existing Zoom video conference"),
31222
31223
  removeZoom: external_exports.boolean().optional().describe("Remove the event's Zoom video conference"),
31223
31224
  account: accountParam
31224
31225
  }
31225
- }, async ({ calendarId, eventId, summary, from, to, description, location, attendees, withZoom, regenerateZoom, removeZoom, account }) => {
31226
+ }, async ({ calendarId, eventId, summary, from, to, description, location, attendees, attachments, withZoom, regenerateZoom, removeZoom, account }) => {
31226
31227
  const args = ["calendar", "update", calendarId, eventId];
31227
31228
  if (summary !== void 0) args.push(`--summary=${summary}`);
31228
31229
  if (from !== void 0) args.push(`--from=${from}`);
@@ -31230,6 +31231,7 @@ function registerCalendarTools(server) {
31230
31231
  if (description !== void 0) args.push(`--description=${description}`);
31231
31232
  if (location !== void 0) args.push(`--location=${location}`);
31232
31233
  if (attendees !== void 0) args.push(`--attendees=${attendees}`);
31234
+ if (attachments) for (const a of attachments) args.push(`--attachment=${a}`);
31233
31235
  if (withZoom) args.push("--with-zoom");
31234
31236
  if (regenerateZoom) args.push("--regenerate-zoom");
31235
31237
  if (removeZoom) args.push("--remove-zoom");
@@ -31726,11 +31728,13 @@ function registerDocsTools(server) {
31726
31728
  docId: external_exports.string().describe("Doc ID (from the URL)"),
31727
31729
  text: external_exports.string().describe("Text content to write"),
31728
31730
  append: external_exports.boolean().optional().describe("Append to existing content instead of replacing (default: false)"),
31731
+ checkOrphans: external_exports.boolean().optional().describe("Block the write (exit code 11) if it would orphan an open comment \u2014 i.e. remove the text the comment is anchored to. Recommended for replacement writes on commented docs."),
31729
31732
  account: accountParam
31730
31733
  }
31731
- }, async ({ docId, text, append, account }) => {
31734
+ }, async ({ docId, text, append, checkOrphans, account }) => {
31732
31735
  const args = ["docs", "write", docId, `--text=${text}`];
31733
31736
  if (append) args.push("--append");
31737
+ if (checkOrphans) args.push("--check-orphans");
31734
31738
  return runOrDiagnose(args, { account });
31735
31739
  });
31736
31740
  server.registerTool("gog_docs_find_replace", {
@@ -31897,7 +31901,7 @@ function registerGmailTools(server) {
31897
31901
  return runOrDiagnose(args, { account });
31898
31902
  });
31899
31903
  server.registerTool("gog_gmail_send", {
31900
- description: "Send an email.",
31904
+ description: "Send an email. When attach is used, the JSON result echoes the attached filenames and byte sizes \u2014 check it to confirm the files were found and embedded.",
31901
31905
  annotations: { destructiveHint: true },
31902
31906
  inputSchema: {
31903
31907
  to: external_exports.string().describe("Recipient(s), comma-separated"),
@@ -32239,7 +32243,7 @@ function registerTasksTools(server) {
32239
32243
  }
32240
32244
 
32241
32245
  // src/server.ts
32242
- var VERSION = true ? "2.6.0" : "0.0.0";
32246
+ var VERSION = true ? "2.7.0" : "0.0.0";
32243
32247
  function createServer(options) {
32244
32248
  return new McpServer({
32245
32249
  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.6.0",
6
+ "version": "2.7.0",
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.6.0",
3
+ "version": "2.7.0",
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.6.0",
10
+ "version": "2.7.0",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "gogcli-mcp",
15
- "version": "2.6.0",
15
+ "version": "2.7.0",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  },
package/src/runner.ts CHANGED
@@ -23,7 +23,7 @@ const TIMEOUT_MS = 30_000;
23
23
  // so the requirement change is surfaced in the release notes (see
24
24
  // .github/release.yml). This is the single source of truth for the required
25
25
  // version; keep the README/CLAUDE.md mention in sync.
26
- export const MIN_GOG_VERSION = '0.23.0';
26
+ export const MIN_GOG_VERSION = '0.24.0';
27
27
 
28
28
  // Treat unresolved .mcpb placeholders ("${user_config.gog_path}") and empty
29
29
  // strings the same as an unset env var. When an optional .mcpb user_config
@@ -75,12 +75,13 @@ export function registerCalendarTools(server: McpServer): void {
75
75
  description: z.string().optional().describe('New description'),
76
76
  location: z.string().optional().describe('New location'),
77
77
  attendees: z.string().optional().describe('New attendee emails, comma-separated (replaces existing)'),
78
+ attachments: z.array(z.string()).optional().describe('File attachment URLs (e.g. Drive links). Replaces ALL existing attachments; pass a single empty string to clear them.'),
78
79
  withZoom: z.boolean().optional().describe('Create a Zoom video conference for this event'),
79
80
  regenerateZoom: z.boolean().optional().describe('Replace the event\'s existing Zoom video conference'),
80
81
  removeZoom: z.boolean().optional().describe('Remove the event\'s Zoom video conference'),
81
82
  account: accountParam,
82
83
  },
83
- }, async ({ calendarId, eventId, summary, from, to, description, location, attendees, withZoom, regenerateZoom, removeZoom, account }) => {
84
+ }, async ({ calendarId, eventId, summary, from, to, description, location, attendees, attachments, withZoom, regenerateZoom, removeZoom, account }) => {
84
85
  const args = ['calendar', 'update', calendarId, eventId];
85
86
  if (summary !== undefined) args.push(`--summary=${summary}`);
86
87
  if (from !== undefined) args.push(`--from=${from}`);
@@ -88,6 +89,7 @@ export function registerCalendarTools(server: McpServer): void {
88
89
  if (description !== undefined) args.push(`--description=${description}`);
89
90
  if (location !== undefined) args.push(`--location=${location}`);
90
91
  if (attendees !== undefined) args.push(`--attendees=${attendees}`);
92
+ if (attachments) for (const a of attachments) args.push(`--attachment=${a}`);
91
93
  if (withZoom) args.push('--with-zoom');
92
94
  if (regenerateZoom) args.push('--regenerate-zoom');
93
95
  if (removeZoom) args.push('--remove-zoom');
package/src/tools/docs.ts CHANGED
@@ -42,11 +42,13 @@ export function registerDocsTools(server: McpServer): void {
42
42
  docId: z.string().describe('Doc ID (from the URL)'),
43
43
  text: z.string().describe('Text content to write'),
44
44
  append: z.boolean().optional().describe('Append to existing content instead of replacing (default: false)'),
45
+ checkOrphans: z.boolean().optional().describe('Block the write (exit code 11) if it would orphan an open comment — i.e. remove the text the comment is anchored to. Recommended for replacement writes on commented docs.'),
45
46
  account: accountParam,
46
47
  },
47
- }, async ({ docId, text, append, account }) => {
48
+ }, async ({ docId, text, append, checkOrphans, account }) => {
48
49
  const args = ['docs', 'write', docId, `--text=${text}`];
49
50
  if (append) args.push('--append');
51
+ if (checkOrphans) args.push('--check-orphans');
50
52
  return runOrDiagnose(args, { account });
51
53
  });
52
54
 
@@ -34,7 +34,7 @@ export function registerGmailTools(server: McpServer): void {
34
34
  });
35
35
 
36
36
  server.registerTool('gog_gmail_send', {
37
- description: 'Send an email.',
37
+ description: 'Send an email. When attach is used, the JSON result echoes the attached filenames and byte sizes — check it to confirm the files were found and embedded.',
38
38
  annotations: { destructiveHint: true },
39
39
  inputSchema: {
40
40
  to: z.string().describe('Recipient(s), comma-separated'),
@@ -155,6 +155,24 @@ describe('gog_calendar_update', () => {
155
155
  );
156
156
  });
157
157
 
158
+ // gog 0.24.0
159
+ it('passes repeatable --attachment values, and an empty string to clear', async () => {
160
+ vi.mocked(runner.run).mockResolvedValue('{}');
161
+ const handlers = setupHandlers();
162
+ await handlers.get('gog_calendar_update')!({
163
+ calendarId: 'primary', eventId: 'evt1', attachments: ['https://drive.google.com/file/d/a', 'https://x.test/b.pdf'],
164
+ });
165
+ expect(runner.run).toHaveBeenCalledWith(
166
+ ['calendar', 'update', 'primary', 'evt1', '--attachment=https://drive.google.com/file/d/a', '--attachment=https://x.test/b.pdf'],
167
+ { account: undefined },
168
+ );
169
+ await handlers.get('gog_calendar_update')!({ calendarId: 'primary', eventId: 'evt1', attachments: [''] });
170
+ expect(runner.run).toHaveBeenCalledWith(
171
+ ['calendar', 'update', 'primary', 'evt1', '--attachment='],
172
+ { account: undefined },
173
+ );
174
+ });
175
+
158
176
  it('passes all optional fields when provided', async () => {
159
177
  vi.mocked(runner.run).mockResolvedValue('{}');
160
178
  const handlers = setupHandlers();
@@ -102,6 +102,17 @@ describe('gog_docs_write', () => {
102
102
  );
103
103
  });
104
104
 
105
+ // gog 0.24.0
106
+ it('adds --check-orphans when checkOrphans is true', async () => {
107
+ vi.mocked(runner.run).mockResolvedValue('{}');
108
+ const handlers = setupHandlers();
109
+ await handlers.get('gog_docs_write')!({ docId: 'abc', text: 'Rewrite', checkOrphans: true });
110
+ expect(runner.run).toHaveBeenCalledWith(
111
+ ['docs', 'write', 'abc', '--text=Rewrite', '--check-orphans'],
112
+ { account: undefined },
113
+ );
114
+ });
115
+
105
116
  it('omits --append flag when append is false', async () => {
106
117
  vi.mocked(runner.run).mockResolvedValue('{}');
107
118
  const handlers = setupHandlers();