google-tools-mcp 1.2.8 → 1.2.9

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.
@@ -0,0 +1,66 @@
1
+ import { UserError } from 'fastmcp';
2
+ import { z } from 'zod';
3
+ import { getSheetsClient } from '../../clients.js';
4
+ import * as SheetsHelpers from '../../googleSheetsApiHelpers.js';
5
+ export function register(server) {
6
+ server.addTool({
7
+ name: 'deleteColumns',
8
+ description: 'Deletes one or more columns from a Google Sheet. Columns are 1-based. Multiple ranges are processed right-to-left to avoid index shifting.',
9
+ parameters: z.object({
10
+ spreadsheetId: z
11
+ .string()
12
+ .describe('The spreadsheet ID — the long string between /d/ and /edit in a Google Sheets URL.'),
13
+ sheetName: z
14
+ .string()
15
+ .optional()
16
+ .describe('Name of the sheet/tab. Defaults to the first sheet if not provided.'),
17
+ columns: z
18
+ .array(z.object({
19
+ startIndex: z
20
+ .number()
21
+ .int()
22
+ .min(1)
23
+ .describe('1-based column number of the first column to delete (inclusive).'),
24
+ endIndex: z
25
+ .number()
26
+ .int()
27
+ .min(1)
28
+ .describe('1-based column number of the last column to delete (inclusive).'),
29
+ }))
30
+ .min(1)
31
+ .describe('Array of column ranges to delete. Each entry is {startIndex, endIndex} using 1-based column numbers.'),
32
+ }),
33
+ execute: async (args, { log }) => {
34
+ const sheets = await getSheetsClient();
35
+ log.info(`Deleting columns in spreadsheet ${args.spreadsheetId}`);
36
+ try {
37
+ const sheetId = await SheetsHelpers.resolveSheetId(sheets, args.spreadsheetId, args.sheetName);
38
+ // Sort descending so right-to-left deletion avoids index shifting
39
+ const sorted = [...args.columns].sort((a, b) => b.startIndex - a.startIndex);
40
+ const requests = sorted.map(({ startIndex, endIndex }) => ({
41
+ deleteDimension: {
42
+ range: {
43
+ sheetId,
44
+ dimension: 'COLUMNS',
45
+ startIndex: startIndex - 1,
46
+ endIndex: endIndex,
47
+ },
48
+ },
49
+ }));
50
+ await sheets.spreadsheets.batchUpdate({
51
+ spreadsheetId: args.spreadsheetId,
52
+ requestBody: { requests },
53
+ });
54
+ const sheetUrl = `https://docs.google.com/spreadsheets/d/${args.spreadsheetId}/edit`;
55
+ const totalCols = args.columns.reduce((sum, { startIndex, endIndex }) => sum + (endIndex - startIndex + 1), 0);
56
+ return `${sheetUrl}\nSuccessfully deleted ${totalCols} column(s) across ${args.columns.length} range(s).`;
57
+ }
58
+ catch (error) {
59
+ log.error(`Error deleting columns: ${error.message || error}`);
60
+ if (error instanceof UserError)
61
+ throw error;
62
+ throw new UserError(`Failed to delete columns: ${error.message || 'Unknown error'}`);
63
+ }
64
+ },
65
+ });
66
+ }
@@ -29,6 +29,7 @@ import { register as updateTableRange } from './updateTableRange.js';
29
29
  import { register as appendTableRows } from './appendTableRows.js';
30
30
  import { register as insertChart } from './insertChart.js';
31
31
  import { register as deleteChart } from './deleteChart.js';
32
+ import { register as deleteColumns } from './deleteColumns.js';
32
33
  export function registerSheetsTools(server) {
33
34
  readSpreadsheet(server);
34
35
  writeSpreadsheet(server);
@@ -61,4 +62,5 @@ export function registerSheetsTools(server) {
61
62
  appendTableRows(server);
62
63
  insertChart(server);
63
64
  deleteChart(server);
65
+ deleteColumns(server);
64
66
  }
@@ -39,8 +39,9 @@ export function register(server) {
39
39
  };
40
40
  // deleteDimensionGroup removes one level at a time; call repeatedly until no groups remain
41
41
  let removed = 0;
42
- // eslint-disable-next-line no-constant-condition
43
- while (true) {
42
+ const MAX_UNGROUP_ITERATIONS = 500;
43
+ let iteration = 0;
44
+ while (iteration++ < MAX_UNGROUP_ITERATIONS) {
44
45
  try {
45
46
  await sheets.spreadsheets.batchUpdate({
46
47
  spreadsheetId: args.spreadsheetId,
@@ -53,6 +54,9 @@ export function register(server) {
53
54
  break;
54
55
  }
55
56
  }
57
+ if (iteration >= MAX_UNGROUP_ITERATIONS) {
58
+ logger.warn(`ungroupAllRows: hit safety cap of ${MAX_UNGROUP_ITERATIONS} iterations — some groups may remain.`);
59
+ }
56
60
  const sheetUrl = `https://docs.google.com/spreadsheets/d/${args.spreadsheetId}/edit`;
57
61
  return `${sheetUrl}\nSuccessfully removed all row groups (${removed} level(s) cleared).`;
58
62
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "google-tools-mcp",
3
- "version": "1.2.8",
3
+ "version": "1.2.9",
4
4
  "description": "The easiest MCP server for Google Workspace — Drive, Docs, Sheets, Gmail, Calendar, and Forms. 153 tools with one-click browser auth. Read Word docs, PDFs, and spreadsheets straight from Drive.",
5
5
  "type": "module",
6
6
  "bin": {