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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/index.js +8 -4
- package/dist/lib.js +9 -5
- package/manifest.json +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/src/runner.ts +1 -1
- package/src/tools/calendar.ts +3 -1
- package/src/tools/docs.ts +3 -1
- package/src/tools/gmail.ts +1 -1
- package/tests/tools/calendar.test.ts +18 -0
- package/tests/tools/docs.test.ts +11 -0
|
@@ -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.
|
|
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.
|
|
18
|
+
"version": "2.7.0",
|
|
19
19
|
"author": {
|
|
20
20
|
"name": "Chris Hall"
|
|
21
21
|
},
|
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.
|
|
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.
|
|
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.
|
|
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
|
+
"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
package/server.json
CHANGED
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"source": "github",
|
|
8
8
|
"subfolder": "packages/gogcli-mcp"
|
|
9
9
|
},
|
|
10
|
-
"version": "2.
|
|
10
|
+
"version": "2.7.0",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "gogcli-mcp",
|
|
15
|
-
"version": "2.
|
|
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.
|
|
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
|
package/src/tools/calendar.ts
CHANGED
|
@@ -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
|
|
package/src/tools/gmail.ts
CHANGED
|
@@ -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();
|
package/tests/tools/docs.test.ts
CHANGED
|
@@ -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();
|