gogcli-mcp-sheets 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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +2 -2
- package/SKILL.md +2 -2
- package/dist/index.js +37 -2
- package/manifest.json +9 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/src/tools/sheets-extra.ts +37 -0
- package/tests/tools/sheets-extra.test.ts +84 -0
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"metadata": {
|
|
9
9
|
"description": "Extended Google Sheets for Claude via gogcli — auth + full Sheets support",
|
|
10
|
-
"version": "2.0.
|
|
10
|
+
"version": "2.0.12"
|
|
11
11
|
},
|
|
12
12
|
"plugins": [
|
|
13
13
|
{
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"displayName": "gogcli (Sheets)",
|
|
16
16
|
"source": "./",
|
|
17
17
|
"description": "Extended Google Sheets for Claude via gogcli — auth + full Sheets support",
|
|
18
|
-
"version": "2.0.
|
|
18
|
+
"version": "2.0.12",
|
|
19
19
|
"author": {
|
|
20
20
|
"name": "Chris Hall"
|
|
21
21
|
},
|
package/README.md
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
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
|
-
Extended Google Sheets [MCP](https://modelcontextprotocol.io) server via [gogcli](https://github.com/
|
|
6
|
+
Extended Google Sheets [MCP](https://modelcontextprotocol.io) server via [gogcli](https://github.com/openclaw/gogcli). Includes auth tools plus 22 additional dedicated Sheets tools for tab management, formatting, named ranges, and more.
|
|
7
7
|
|
|
8
8
|
## Requirements
|
|
9
9
|
|
|
10
|
-
- [gogcli](https://github.com/
|
|
10
|
+
- [gogcli](https://github.com/openclaw/gogcli) installed and authenticated
|
|
11
11
|
- Node.js 18+
|
|
12
12
|
|
|
13
13
|
```bash
|
package/SKILL.md
CHANGED
|
@@ -5,13 +5,13 @@ description: Use when the user asks to read, write, format, or manage Google She
|
|
|
5
5
|
|
|
6
6
|
# gogcli-mcp-sheets
|
|
7
7
|
|
|
8
|
-
Extended Google Sheets MCP server via [gogcli](https://github.com/
|
|
8
|
+
Extended Google Sheets MCP server via [gogcli](https://github.com/openclaw/gogcli) — 35 tools: auth + 8 base Sheets + 22 extra dedicated Sheets tools.
|
|
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/
|
|
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/
|
|
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
|
}
|
|
@@ -31309,7 +31309,7 @@ function registerSheetsTools(server2) {
|
|
|
31309
31309
|
}
|
|
31310
31310
|
|
|
31311
31311
|
// ../gogcli-mcp/src/server.ts
|
|
31312
|
-
var VERSION = true ? "2.0.
|
|
31312
|
+
var VERSION = true ? "2.0.12" : "0.0.0";
|
|
31313
31313
|
function createServer(options) {
|
|
31314
31314
|
return new McpServer({
|
|
31315
31315
|
name: options?.name ?? "gogcli",
|
|
@@ -31707,6 +31707,41 @@ function registerExtraSheetsTools(server2) {
|
|
|
31707
31707
|
}, async ({ spreadsheetId, nameOrId, account }) => {
|
|
31708
31708
|
return runOrDiagnose(["sheets", "named-ranges", "delete", spreadsheetId, nameOrId], { account });
|
|
31709
31709
|
});
|
|
31710
|
+
server2.registerTool("gog_sheets_batch_update", {
|
|
31711
|
+
description: 'Update values in multiple ranges with one Sheets API request. dataJson is a JSON array of {range, values} objects (or "@/path/to/file.json"). Atomic \u2014 either all ranges update or none do.',
|
|
31712
|
+
annotations: { destructiveHint: true },
|
|
31713
|
+
inputSchema: {
|
|
31714
|
+
spreadsheetId: external_exports.string().describe("Spreadsheet ID"),
|
|
31715
|
+
dataJson: external_exports.string().describe('Value ranges as JSON array, or @file (e.g. [{"range":"Sheet1!A1:B2","values":[["a","b"]]}])'),
|
|
31716
|
+
input: external_exports.enum(["RAW", "USER_ENTERED"]).optional().describe("Value input option (default: USER_ENTERED)"),
|
|
31717
|
+
includeValuesInResponse: external_exports.boolean().optional().describe("Include updated values in the response"),
|
|
31718
|
+
responseRender: external_exports.enum(["FORMATTED_VALUE", "UNFORMATTED_VALUE", "FORMULA"]).optional().describe("Response value render option"),
|
|
31719
|
+
responseDateTimeRender: external_exports.enum(["SERIAL_NUMBER", "FORMATTED_STRING"]).optional().describe("Response date/time render option"),
|
|
31720
|
+
account: accountParam
|
|
31721
|
+
}
|
|
31722
|
+
}, async ({ spreadsheetId, dataJson, input, includeValuesInResponse, responseRender, responseDateTimeRender, account }) => {
|
|
31723
|
+
const args = ["sheets", "batch-update", spreadsheetId, `--data-json=${dataJson}`];
|
|
31724
|
+
if (input) args.push(`--input=${input}`);
|
|
31725
|
+
if (includeValuesInResponse) args.push("--include-values-in-response");
|
|
31726
|
+
if (responseRender) args.push(`--response-render=${responseRender}`);
|
|
31727
|
+
if (responseDateTimeRender) args.push(`--response-date-time-render=${responseDateTimeRender}`);
|
|
31728
|
+
return runOrDiagnose(args, { account });
|
|
31729
|
+
});
|
|
31730
|
+
server2.registerTool("gog_sheets_reorder_tab", {
|
|
31731
|
+
description: "Move a tab to a specific 0-based position. `tab` is the tab name or numeric sheetId; `to=0` is the leftmost slot.",
|
|
31732
|
+
annotations: { destructiveHint: true },
|
|
31733
|
+
inputSchema: {
|
|
31734
|
+
spreadsheetId: external_exports.string().describe("Spreadsheet ID"),
|
|
31735
|
+
tab: external_exports.string().describe("Target tab by name or numeric sheet ID"),
|
|
31736
|
+
to: external_exports.number().int().min(0).describe("Destination final 0-based tab index"),
|
|
31737
|
+
account: accountParam
|
|
31738
|
+
}
|
|
31739
|
+
}, async ({ spreadsheetId, tab, to, account }) => {
|
|
31740
|
+
return runOrDiagnose(
|
|
31741
|
+
["sheets", "reorder-tab", spreadsheetId, `--tab=${tab}`, `--to=${to}`],
|
|
31742
|
+
{ account }
|
|
31743
|
+
);
|
|
31744
|
+
});
|
|
31710
31745
|
}
|
|
31711
31746
|
|
|
31712
31747
|
// src/index.ts
|
package/manifest.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"manifest_version": "0.3",
|
|
4
4
|
"name": "gogcli-mcp-sheets",
|
|
5
5
|
"display_name": "gogcli (Sheets)",
|
|
6
|
-
"version": "2.0.
|
|
6
|
+
"version": "2.0.12",
|
|
7
7
|
"description": "Extended Google Sheets for Claude via gogcli — auth + full Sheets support",
|
|
8
8
|
"author": {
|
|
9
9
|
"name": "Chris Hall",
|
|
@@ -199,6 +199,14 @@
|
|
|
199
199
|
{
|
|
200
200
|
"name": "gog_sheets_list_tabs",
|
|
201
201
|
"description": "List tabs in a spreadsheet (sheetId, title, index, gridProperties)"
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"name": "gog_sheets_batch_update",
|
|
205
|
+
"description": "Update values in multiple ranges atomically with one Sheets API request."
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"name": "gog_sheets_reorder_tab",
|
|
209
|
+
"description": "Move a tab to a specific 0-based position."
|
|
202
210
|
}
|
|
203
211
|
],
|
|
204
212
|
"compatibility": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gogcli-mcp-sheets",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.12",
|
|
4
4
|
"mcpName": "io.github.chrischall/gogcli-mcp-sheets",
|
|
5
5
|
"description": "Extended Google Sheets MCP server via gogcli — all base tools plus full Sheets support",
|
|
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-sheets"
|
|
9
9
|
},
|
|
10
|
-
"version": "2.0.
|
|
10
|
+
"version": "2.0.12",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "gogcli-mcp-sheets",
|
|
15
|
-
"version": "2.0.
|
|
15
|
+
"version": "2.0.12",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
},
|
|
@@ -420,4 +420,41 @@ export function registerExtraSheetsTools(server: McpServer): void {
|
|
|
420
420
|
}, async ({ spreadsheetId, nameOrId, account }) => {
|
|
421
421
|
return runOrDiagnose(['sheets', 'named-ranges', 'delete', spreadsheetId, nameOrId], { account });
|
|
422
422
|
});
|
|
423
|
+
|
|
424
|
+
server.registerTool('gog_sheets_batch_update', {
|
|
425
|
+
description: 'Update values in multiple ranges with one Sheets API request. dataJson is a JSON array of {range, values} objects (or "@/path/to/file.json"). Atomic — either all ranges update or none do.',
|
|
426
|
+
annotations: { destructiveHint: true },
|
|
427
|
+
inputSchema: {
|
|
428
|
+
spreadsheetId: z.string().describe('Spreadsheet ID'),
|
|
429
|
+
dataJson: z.string().describe('Value ranges as JSON array, or @file (e.g. [{"range":"Sheet1!A1:B2","values":[["a","b"]]}])'),
|
|
430
|
+
input: z.enum(['RAW', 'USER_ENTERED']).optional().describe('Value input option (default: USER_ENTERED)'),
|
|
431
|
+
includeValuesInResponse: z.boolean().optional().describe('Include updated values in the response'),
|
|
432
|
+
responseRender: z.enum(['FORMATTED_VALUE', 'UNFORMATTED_VALUE', 'FORMULA']).optional().describe('Response value render option'),
|
|
433
|
+
responseDateTimeRender: z.enum(['SERIAL_NUMBER', 'FORMATTED_STRING']).optional().describe('Response date/time render option'),
|
|
434
|
+
account: accountParam,
|
|
435
|
+
},
|
|
436
|
+
}, async ({ spreadsheetId, dataJson, input, includeValuesInResponse, responseRender, responseDateTimeRender, account }) => {
|
|
437
|
+
const args = ['sheets', 'batch-update', spreadsheetId, `--data-json=${dataJson}`];
|
|
438
|
+
if (input) args.push(`--input=${input}`);
|
|
439
|
+
if (includeValuesInResponse) args.push('--include-values-in-response');
|
|
440
|
+
if (responseRender) args.push(`--response-render=${responseRender}`);
|
|
441
|
+
if (responseDateTimeRender) args.push(`--response-date-time-render=${responseDateTimeRender}`);
|
|
442
|
+
return runOrDiagnose(args, { account });
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
server.registerTool('gog_sheets_reorder_tab', {
|
|
446
|
+
description: 'Move a tab to a specific 0-based position. `tab` is the tab name or numeric sheetId; `to=0` is the leftmost slot.',
|
|
447
|
+
annotations: { destructiveHint: true },
|
|
448
|
+
inputSchema: {
|
|
449
|
+
spreadsheetId: z.string().describe('Spreadsheet ID'),
|
|
450
|
+
tab: z.string().describe('Target tab by name or numeric sheet ID'),
|
|
451
|
+
to: z.number().int().min(0).describe('Destination final 0-based tab index'),
|
|
452
|
+
account: accountParam,
|
|
453
|
+
},
|
|
454
|
+
}, async ({ spreadsheetId, tab, to, account }) => {
|
|
455
|
+
return runOrDiagnose(
|
|
456
|
+
['sheets', 'reorder-tab', spreadsheetId, `--tab=${tab}`, `--to=${to}`],
|
|
457
|
+
{ account },
|
|
458
|
+
);
|
|
459
|
+
});
|
|
423
460
|
}
|
|
@@ -481,3 +481,87 @@ describe('gog_sheets_named_ranges_delete', () => {
|
|
|
481
481
|
expect(lib.runOrDiagnose).toHaveBeenCalledWith(['sheets', 'named-ranges', 'delete', 'sid', 'OldRange'], { account: undefined });
|
|
482
482
|
});
|
|
483
483
|
});
|
|
484
|
+
|
|
485
|
+
// 23. batch-update (gog 0.18.0)
|
|
486
|
+
describe('gog_sheets_batch_update', () => {
|
|
487
|
+
it('passes --data-json and required spreadsheetId', async () => {
|
|
488
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
489
|
+
const handlers = setupHandlers();
|
|
490
|
+
const data = '[{"range":"Sheet1!A1:B1","values":[["a","b"]]}]';
|
|
491
|
+
await handlers.get('gog_sheets_batch_update')!({ spreadsheetId: 'sid', dataJson: data });
|
|
492
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
493
|
+
['sheets', 'batch-update', 'sid', `--data-json=${data}`],
|
|
494
|
+
{ account: undefined },
|
|
495
|
+
);
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
it('passes optional --input, --include-values-in-response, --response-render, --response-date-time-render', async () => {
|
|
499
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
500
|
+
const handlers = setupHandlers();
|
|
501
|
+
await handlers.get('gog_sheets_batch_update')!({
|
|
502
|
+
spreadsheetId: 'sid',
|
|
503
|
+
dataJson: '[]',
|
|
504
|
+
input: 'RAW',
|
|
505
|
+
includeValuesInResponse: true,
|
|
506
|
+
responseRender: 'FORMULA',
|
|
507
|
+
responseDateTimeRender: 'FORMATTED_STRING',
|
|
508
|
+
account: 'a@b.com',
|
|
509
|
+
});
|
|
510
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
511
|
+
[
|
|
512
|
+
'sheets', 'batch-update', 'sid',
|
|
513
|
+
'--data-json=[]',
|
|
514
|
+
'--input=RAW',
|
|
515
|
+
'--include-values-in-response',
|
|
516
|
+
'--response-render=FORMULA',
|
|
517
|
+
'--response-date-time-render=FORMATTED_STRING',
|
|
518
|
+
],
|
|
519
|
+
{ account: 'a@b.com' },
|
|
520
|
+
);
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
it('omits --include-values-in-response when false', async () => {
|
|
524
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
525
|
+
const handlers = setupHandlers();
|
|
526
|
+
await handlers.get('gog_sheets_batch_update')!({
|
|
527
|
+
spreadsheetId: 'sid', dataJson: '[]', includeValuesInResponse: false,
|
|
528
|
+
});
|
|
529
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
530
|
+
['sheets', 'batch-update', 'sid', '--data-json=[]'],
|
|
531
|
+
{ account: undefined },
|
|
532
|
+
);
|
|
533
|
+
});
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
// 24. reorder-tab (gog 0.18.0)
|
|
537
|
+
describe('gog_sheets_reorder_tab', () => {
|
|
538
|
+
it('passes --tab and --to', async () => {
|
|
539
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
540
|
+
const handlers = setupHandlers();
|
|
541
|
+
await handlers.get('gog_sheets_reorder_tab')!({ spreadsheetId: 'sid', tab: 'Data', to: 2 });
|
|
542
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
543
|
+
['sheets', 'reorder-tab', 'sid', '--tab=Data', '--to=2'],
|
|
544
|
+
{ account: undefined },
|
|
545
|
+
);
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
it('sends --to=0 explicitly to reach the leftmost position', async () => {
|
|
549
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
550
|
+
const handlers = setupHandlers();
|
|
551
|
+
await handlers.get('gog_sheets_reorder_tab')!({ spreadsheetId: 'sid', tab: '123', to: 0 });
|
|
552
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
553
|
+
['sheets', 'reorder-tab', 'sid', '--tab=123', '--to=0'],
|
|
554
|
+
{ account: undefined },
|
|
555
|
+
);
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
it('forwards account', async () => {
|
|
559
|
+
vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
|
|
560
|
+
const handlers = setupHandlers();
|
|
561
|
+
await handlers.get('gog_sheets_reorder_tab')!({ spreadsheetId: 'sid', tab: 'Data', to: 1, account: 'a@b.com' });
|
|
562
|
+
expect(lib.runOrDiagnose).toHaveBeenCalledWith(
|
|
563
|
+
['sheets', 'reorder-tab', 'sid', '--tab=Data', '--to=1'],
|
|
564
|
+
{ account: 'a@b.com' },
|
|
565
|
+
);
|
|
566
|
+
});
|
|
567
|
+
});
|