mcp-gsheets 1.8.1 → 1.9.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/README.md +9 -0
- package/dist/index.js +483 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -360,6 +360,15 @@ npm run dev # Watch mode with auto-reload
|
|
|
360
360
|
| `sheets_unmerge_cells` | Unmerge previously merged cells in a range | `spreadsheetId`, `range` |
|
|
361
361
|
| `sheets_add_conditional_formatting` | Add a conditional formatting rule (gradient or boolean) to a range | `spreadsheetId`, `range`, `rule` |
|
|
362
362
|
|
|
363
|
+
### Native Tables
|
|
364
|
+
|
|
365
|
+
| Tool | Description | Key Parameters |
|
|
366
|
+
|------|-------------|----------------|
|
|
367
|
+
| `sheets_add_table` | Create a native Google Sheets table with typed columns and optional dropdown values | `spreadsheetId`, `sheetName`, `range`, `name`, `columns` |
|
|
368
|
+
| `sheets_update_table` | Update an existing native Google Sheets table by table ID using an explicit field mask | `spreadsheetId`, `tableId`, `fields`, `name`, `range`, `columns` |
|
|
369
|
+
| `sheets_delete_table` | Delete a native Google Sheets table by table ID | `spreadsheetId`, `tableId` |
|
|
370
|
+
| `sheets_get_tables` | Read native tables for a spreadsheet or a specific sheet | `spreadsheetId`, `sheetName` |
|
|
371
|
+
|
|
363
372
|
### Charts
|
|
364
373
|
|
|
365
374
|
| Tool | Description | Key Parameters |
|
package/dist/index.js
CHANGED
|
@@ -18319,7 +18319,7 @@ async function getSheetId(sheets, spreadsheetId, sheetName) {
|
|
|
18319
18319
|
const sheetsData = response.data.sheets || [];
|
|
18320
18320
|
if (sheetName) {
|
|
18321
18321
|
const sheet = sheetsData.find((s) => s.properties?.title === sheetName);
|
|
18322
|
-
if (
|
|
18322
|
+
if (sheet?.properties?.sheetId === void 0 || sheet.properties.sheetId === null) {
|
|
18323
18323
|
const availableSheets = sheetsData.map((s) => s.properties?.title).filter((title) => title).join(", ");
|
|
18324
18324
|
throw new Error(`Sheet "${sheetName}" not found. Available sheets: ${availableSheets}`);
|
|
18325
18325
|
}
|
|
@@ -20130,6 +20130,480 @@ async function addConditionalFormattingHandler(input) {
|
|
|
20130
20130
|
}
|
|
20131
20131
|
}
|
|
20132
20132
|
|
|
20133
|
+
// src/utils/table-helpers.ts
|
|
20134
|
+
var TABLE_COLUMN_TYPES = [
|
|
20135
|
+
"COLUMN_TYPE_UNSPECIFIED",
|
|
20136
|
+
"DOUBLE",
|
|
20137
|
+
"CURRENCY",
|
|
20138
|
+
"PERCENT",
|
|
20139
|
+
"DATE",
|
|
20140
|
+
"TIME",
|
|
20141
|
+
"DATE_TIME",
|
|
20142
|
+
"TEXT",
|
|
20143
|
+
"BOOLEAN",
|
|
20144
|
+
"DROPDOWN",
|
|
20145
|
+
"FILES_CHIP",
|
|
20146
|
+
"PEOPLE_CHIP",
|
|
20147
|
+
"FINANCE_CHIP",
|
|
20148
|
+
"PLACE_CHIP",
|
|
20149
|
+
"RATINGS_CHIP"
|
|
20150
|
+
];
|
|
20151
|
+
function resolveTableRangeInput(sheetName, range) {
|
|
20152
|
+
const extracted = extractSheetName(range);
|
|
20153
|
+
if (extracted.sheetName && extracted.sheetName !== sheetName) {
|
|
20154
|
+
throw new Error(`Range sheet "${extracted.sheetName}" does not match sheetName "${sheetName}"`);
|
|
20155
|
+
}
|
|
20156
|
+
return {
|
|
20157
|
+
sheetName: extracted.sheetName ?? sheetName,
|
|
20158
|
+
range: extracted.range
|
|
20159
|
+
};
|
|
20160
|
+
}
|
|
20161
|
+
function buildTableColumnProperties(columns) {
|
|
20162
|
+
return columns.map((column, index) => {
|
|
20163
|
+
const columnProperties = {
|
|
20164
|
+
columnIndex: index,
|
|
20165
|
+
columnName: column.name,
|
|
20166
|
+
columnType: column.columnType
|
|
20167
|
+
};
|
|
20168
|
+
if (column.dropdownValues && column.dropdownValues.length > 0) {
|
|
20169
|
+
columnProperties.dataValidationRule = {
|
|
20170
|
+
condition: {
|
|
20171
|
+
type: "ONE_OF_LIST",
|
|
20172
|
+
values: column.dropdownValues.map((value) => ({ userEnteredValue: value }))
|
|
20173
|
+
}
|
|
20174
|
+
};
|
|
20175
|
+
}
|
|
20176
|
+
return columnProperties;
|
|
20177
|
+
});
|
|
20178
|
+
}
|
|
20179
|
+
function getRangeColumnCount(range) {
|
|
20180
|
+
if (range.startColumnIndex === void 0 || range.startColumnIndex === null || range.endColumnIndex === void 0 || range.endColumnIndex === null) {
|
|
20181
|
+
return void 0;
|
|
20182
|
+
}
|
|
20183
|
+
return range.endColumnIndex - range.startColumnIndex;
|
|
20184
|
+
}
|
|
20185
|
+
function validateTableGridRange(range, rangeText) {
|
|
20186
|
+
const startRow = range.startRowIndex;
|
|
20187
|
+
const endRow = range.endRowIndex;
|
|
20188
|
+
const startColumn = range.startColumnIndex;
|
|
20189
|
+
const endColumn = range.endColumnIndex;
|
|
20190
|
+
if (startRow === void 0 || startRow === null || endRow === void 0 || endRow === null || startColumn === void 0 || startColumn === null || endColumn === void 0 || endColumn === null || startRow < 0 || startColumn < 0 || endRow <= startRow || endColumn <= startColumn) {
|
|
20191
|
+
throw new Error(`Invalid table range: ${rangeText}. Use a rectangular A1 range like "A1:D20".`);
|
|
20192
|
+
}
|
|
20193
|
+
}
|
|
20194
|
+
function validateColumnCount(range, columns, rangeText) {
|
|
20195
|
+
const columnCount = getRangeColumnCount(range);
|
|
20196
|
+
if (columnCount !== void 0 && columnCount !== columns.length) {
|
|
20197
|
+
throw new Error(
|
|
20198
|
+
`Column count mismatch: range ${rangeText} spans ${columnCount} column(s), but ${columns.length} column definition(s) were provided`
|
|
20199
|
+
);
|
|
20200
|
+
}
|
|
20201
|
+
}
|
|
20202
|
+
function rangesOverlap(first, second) {
|
|
20203
|
+
if (first.sheetId !== void 0 && first.sheetId !== null && second.sheetId !== void 0 && second.sheetId !== null && first.sheetId !== second.sheetId) {
|
|
20204
|
+
return false;
|
|
20205
|
+
}
|
|
20206
|
+
const firstStartRow = first.startRowIndex ?? 0;
|
|
20207
|
+
const firstEndRow = first.endRowIndex ?? Number.POSITIVE_INFINITY;
|
|
20208
|
+
const firstStartColumn = first.startColumnIndex ?? 0;
|
|
20209
|
+
const firstEndColumn = first.endColumnIndex ?? Number.POSITIVE_INFINITY;
|
|
20210
|
+
const secondStartRow = second.startRowIndex ?? 0;
|
|
20211
|
+
const secondEndRow = second.endRowIndex ?? Number.POSITIVE_INFINITY;
|
|
20212
|
+
const secondStartColumn = second.startColumnIndex ?? 0;
|
|
20213
|
+
const secondEndColumn = second.endColumnIndex ?? Number.POSITIVE_INFINITY;
|
|
20214
|
+
return firstStartRow < secondEndRow && firstEndRow > secondStartRow && firstStartColumn < secondEndColumn && firstEndColumn > secondStartColumn;
|
|
20215
|
+
}
|
|
20216
|
+
function ensureNoOverlappingTable(tables, range, sheetName, excludeTableId) {
|
|
20217
|
+
const overlappingTable = tables.find(
|
|
20218
|
+
(table) => table.tableId !== excludeTableId && table.range && rangesOverlap(table.range, range)
|
|
20219
|
+
);
|
|
20220
|
+
if (!overlappingTable) {
|
|
20221
|
+
return;
|
|
20222
|
+
}
|
|
20223
|
+
const existingRange = overlappingTable.range ? gridRangeToA1(overlappingTable.range) : "unknown";
|
|
20224
|
+
const requestedRange = gridRangeToA1(range);
|
|
20225
|
+
const tableLabel = overlappingTable.name || overlappingTable.tableId || "unnamed table";
|
|
20226
|
+
throw new Error(
|
|
20227
|
+
`Table range ${sheetName}!${requestedRange} overlaps existing table "${tableLabel}" (${sheetName}!${existingRange}). Choose a non-overlapping range or update/delete the existing table.`
|
|
20228
|
+
);
|
|
20229
|
+
}
|
|
20230
|
+
function formatTableForResponse(table, sheetName) {
|
|
20231
|
+
const range = table.range ? gridRangeToA1(table.range) : null;
|
|
20232
|
+
return {
|
|
20233
|
+
tableId: table.tableId ?? null,
|
|
20234
|
+
name: table.name ?? null,
|
|
20235
|
+
range: range && sheetName ? `${sheetName}!${range}` : range,
|
|
20236
|
+
gridRange: table.range ?? null,
|
|
20237
|
+
columnProperties: table.columnProperties ?? []
|
|
20238
|
+
};
|
|
20239
|
+
}
|
|
20240
|
+
|
|
20241
|
+
// src/tools/add-table.ts
|
|
20242
|
+
var columnSchema = external_exports.object({
|
|
20243
|
+
name: external_exports.string().min(1),
|
|
20244
|
+
columnType: external_exports.enum(TABLE_COLUMN_TYPES),
|
|
20245
|
+
dropdownValues: external_exports.array(external_exports.string()).optional()
|
|
20246
|
+
});
|
|
20247
|
+
var addTableInputSchema = external_exports.object({
|
|
20248
|
+
spreadsheetId: external_exports.string().min(1),
|
|
20249
|
+
sheetName: external_exports.string().min(1),
|
|
20250
|
+
range: external_exports.string().min(1),
|
|
20251
|
+
name: external_exports.string().min(1),
|
|
20252
|
+
columns: external_exports.array(columnSchema).min(1)
|
|
20253
|
+
});
|
|
20254
|
+
var addTableTool = {
|
|
20255
|
+
name: "sheets_add_table",
|
|
20256
|
+
description: "Create a native Google Sheets table with typed columns and optional dropdown values",
|
|
20257
|
+
inputSchema: {
|
|
20258
|
+
type: "object",
|
|
20259
|
+
properties: {
|
|
20260
|
+
spreadsheetId: {
|
|
20261
|
+
type: "string",
|
|
20262
|
+
description: "The ID of the spreadsheet (found in the URL after /d/)"
|
|
20263
|
+
},
|
|
20264
|
+
sheetName: {
|
|
20265
|
+
type: "string",
|
|
20266
|
+
description: "Name of the sheet (tab) where the table will be created"
|
|
20267
|
+
},
|
|
20268
|
+
range: {
|
|
20269
|
+
type: "string",
|
|
20270
|
+
description: 'A1 notation range for the table, e.g. "A1:D20" or "Sheet1!A1:D20"'
|
|
20271
|
+
},
|
|
20272
|
+
name: {
|
|
20273
|
+
type: "string",
|
|
20274
|
+
description: "Unique table name within the spreadsheet"
|
|
20275
|
+
},
|
|
20276
|
+
columns: {
|
|
20277
|
+
type: "array",
|
|
20278
|
+
description: "Column definitions for the table",
|
|
20279
|
+
items: {
|
|
20280
|
+
type: "object",
|
|
20281
|
+
properties: {
|
|
20282
|
+
name: { type: "string", description: "Column name" },
|
|
20283
|
+
columnType: {
|
|
20284
|
+
type: "string",
|
|
20285
|
+
enum: [...TABLE_COLUMN_TYPES],
|
|
20286
|
+
description: "Google Sheets table column type"
|
|
20287
|
+
},
|
|
20288
|
+
dropdownValues: {
|
|
20289
|
+
type: "array",
|
|
20290
|
+
items: { type: "string" },
|
|
20291
|
+
description: "Allowed values for DROPDOWN columns"
|
|
20292
|
+
}
|
|
20293
|
+
},
|
|
20294
|
+
required: ["name", "columnType"]
|
|
20295
|
+
}
|
|
20296
|
+
}
|
|
20297
|
+
},
|
|
20298
|
+
required: ["spreadsheetId", "sheetName", "range", "name", "columns"]
|
|
20299
|
+
}
|
|
20300
|
+
};
|
|
20301
|
+
async function addTableHandler(input) {
|
|
20302
|
+
try {
|
|
20303
|
+
const validatedInput = addTableInputSchema.parse(input);
|
|
20304
|
+
const sheets = await getAuthenticatedClient();
|
|
20305
|
+
const { sheetName, range } = resolveTableRangeInput(
|
|
20306
|
+
validatedInput.sheetName,
|
|
20307
|
+
validatedInput.range
|
|
20308
|
+
);
|
|
20309
|
+
const sheetId = await getSheetId(sheets, validatedInput.spreadsheetId, sheetName);
|
|
20310
|
+
const gridRange = parseRange(range, sheetId);
|
|
20311
|
+
validateTableGridRange(gridRange, `${sheetName}!${range}`);
|
|
20312
|
+
validateColumnCount(gridRange, validatedInput.columns, `${sheetName}!${range}`);
|
|
20313
|
+
const metadataResponse = await sheets.spreadsheets.get({
|
|
20314
|
+
spreadsheetId: validatedInput.spreadsheetId,
|
|
20315
|
+
fields: "sheets.properties.title,sheets.properties.sheetId,sheets.tables"
|
|
20316
|
+
});
|
|
20317
|
+
const sheetData = findSheetOrThrow(metadataResponse.data.sheets ?? [], sheetName);
|
|
20318
|
+
ensureNoOverlappingTable(sheetData.tables ?? [], gridRange, sheetName);
|
|
20319
|
+
const table = {
|
|
20320
|
+
name: validatedInput.name,
|
|
20321
|
+
range: gridRange,
|
|
20322
|
+
columnProperties: buildTableColumnProperties(validatedInput.columns)
|
|
20323
|
+
};
|
|
20324
|
+
const response = await sheets.spreadsheets.batchUpdate({
|
|
20325
|
+
spreadsheetId: validatedInput.spreadsheetId,
|
|
20326
|
+
requestBody: {
|
|
20327
|
+
requests: [
|
|
20328
|
+
{
|
|
20329
|
+
addTable: {
|
|
20330
|
+
table
|
|
20331
|
+
}
|
|
20332
|
+
}
|
|
20333
|
+
]
|
|
20334
|
+
}
|
|
20335
|
+
});
|
|
20336
|
+
const addedTable = response.data.replies?.[0]?.addTable?.table ?? table;
|
|
20337
|
+
return formatToolResponse(`Successfully created table "${validatedInput.name}"`, {
|
|
20338
|
+
spreadsheetId: response.data.spreadsheetId,
|
|
20339
|
+
table: formatTableForResponse(addedTable, sheetName)
|
|
20340
|
+
});
|
|
20341
|
+
} catch (error2) {
|
|
20342
|
+
return handleError(error2);
|
|
20343
|
+
}
|
|
20344
|
+
}
|
|
20345
|
+
|
|
20346
|
+
// src/tools/update-table.ts
|
|
20347
|
+
var columnSchema2 = external_exports.object({
|
|
20348
|
+
name: external_exports.string().min(1),
|
|
20349
|
+
columnType: external_exports.enum(TABLE_COLUMN_TYPES),
|
|
20350
|
+
dropdownValues: external_exports.array(external_exports.string()).optional()
|
|
20351
|
+
});
|
|
20352
|
+
var updateTableInputSchema = external_exports.object({
|
|
20353
|
+
spreadsheetId: external_exports.string().min(1),
|
|
20354
|
+
tableId: external_exports.string().min(1),
|
|
20355
|
+
fields: external_exports.string().min(1),
|
|
20356
|
+
sheetName: external_exports.string().min(1).optional(),
|
|
20357
|
+
range: external_exports.string().min(1).optional(),
|
|
20358
|
+
name: external_exports.string().min(1).optional(),
|
|
20359
|
+
columns: external_exports.array(columnSchema2).min(1).optional()
|
|
20360
|
+
}).refine((value) => value.name || value.range || value.columns, {
|
|
20361
|
+
message: "At least one of name, range, or columns must be provided"
|
|
20362
|
+
});
|
|
20363
|
+
var updateTableTool = {
|
|
20364
|
+
name: "sheets_update_table",
|
|
20365
|
+
description: "Update an existing native Google Sheets table by tableId",
|
|
20366
|
+
inputSchema: {
|
|
20367
|
+
type: "object",
|
|
20368
|
+
properties: {
|
|
20369
|
+
spreadsheetId: {
|
|
20370
|
+
type: "string",
|
|
20371
|
+
description: "The ID of the spreadsheet (found in the URL after /d/)"
|
|
20372
|
+
},
|
|
20373
|
+
tableId: {
|
|
20374
|
+
type: "string",
|
|
20375
|
+
description: "The ID of the table to update"
|
|
20376
|
+
},
|
|
20377
|
+
fields: {
|
|
20378
|
+
type: "string",
|
|
20379
|
+
description: 'Required field mask for the table update, e.g. "name", "range", "columnProperties", or "name,range"'
|
|
20380
|
+
},
|
|
20381
|
+
sheetName: {
|
|
20382
|
+
type: "string",
|
|
20383
|
+
description: "Name of the target sheet when updating the table range"
|
|
20384
|
+
},
|
|
20385
|
+
range: {
|
|
20386
|
+
type: "string",
|
|
20387
|
+
description: 'Optional new A1 notation range for the table, e.g. "A1:D20"'
|
|
20388
|
+
},
|
|
20389
|
+
name: {
|
|
20390
|
+
type: "string",
|
|
20391
|
+
description: "Optional new table name"
|
|
20392
|
+
},
|
|
20393
|
+
columns: {
|
|
20394
|
+
type: "array",
|
|
20395
|
+
description: "Optional replacement column definitions for the table",
|
|
20396
|
+
items: {
|
|
20397
|
+
type: "object",
|
|
20398
|
+
properties: {
|
|
20399
|
+
name: { type: "string", description: "Column name" },
|
|
20400
|
+
columnType: {
|
|
20401
|
+
type: "string",
|
|
20402
|
+
enum: [...TABLE_COLUMN_TYPES],
|
|
20403
|
+
description: "Google Sheets table column type"
|
|
20404
|
+
},
|
|
20405
|
+
dropdownValues: {
|
|
20406
|
+
type: "array",
|
|
20407
|
+
items: { type: "string" },
|
|
20408
|
+
description: "Allowed values for DROPDOWN columns"
|
|
20409
|
+
}
|
|
20410
|
+
},
|
|
20411
|
+
required: ["name", "columnType"]
|
|
20412
|
+
}
|
|
20413
|
+
}
|
|
20414
|
+
},
|
|
20415
|
+
required: ["spreadsheetId", "tableId", "fields"]
|
|
20416
|
+
}
|
|
20417
|
+
};
|
|
20418
|
+
async function updateTableHandler(input) {
|
|
20419
|
+
try {
|
|
20420
|
+
const validatedInput = updateTableInputSchema.parse(input);
|
|
20421
|
+
const sheets = await getAuthenticatedClient();
|
|
20422
|
+
const metadataResponse = await sheets.spreadsheets.get({
|
|
20423
|
+
spreadsheetId: validatedInput.spreadsheetId,
|
|
20424
|
+
fields: "sheets.properties.title,sheets.properties.sheetId,sheets.tables"
|
|
20425
|
+
});
|
|
20426
|
+
const allSheets = metadataResponse.data.sheets ?? [];
|
|
20427
|
+
const existingTable = allSheets.flatMap((sheet) => sheet.tables ?? []).find((table2) => table2.tableId === validatedInput.tableId);
|
|
20428
|
+
if (!existingTable) {
|
|
20429
|
+
throw new Error(`Table "${validatedInput.tableId}" not found`);
|
|
20430
|
+
}
|
|
20431
|
+
const table = {
|
|
20432
|
+
tableId: validatedInput.tableId
|
|
20433
|
+
};
|
|
20434
|
+
if (validatedInput.name) {
|
|
20435
|
+
table.name = validatedInput.name;
|
|
20436
|
+
}
|
|
20437
|
+
if (validatedInput.columns) {
|
|
20438
|
+
table.columnProperties = buildTableColumnProperties(validatedInput.columns);
|
|
20439
|
+
}
|
|
20440
|
+
let responseSheetName;
|
|
20441
|
+
if (validatedInput.range) {
|
|
20442
|
+
const extracted = extractSheetName(validatedInput.range);
|
|
20443
|
+
const sheetName = validatedInput.sheetName ?? extracted.sheetName;
|
|
20444
|
+
if (!sheetName) {
|
|
20445
|
+
throw new Error("sheetName is required when updating a table range");
|
|
20446
|
+
}
|
|
20447
|
+
const resolvedRange = resolveTableRangeInput(sheetName, validatedInput.range);
|
|
20448
|
+
responseSheetName = resolvedRange.sheetName;
|
|
20449
|
+
const sheetId = await getSheetId(
|
|
20450
|
+
sheets,
|
|
20451
|
+
validatedInput.spreadsheetId,
|
|
20452
|
+
resolvedRange.sheetName
|
|
20453
|
+
);
|
|
20454
|
+
const gridRange = parseRange(resolvedRange.range, sheetId);
|
|
20455
|
+
validateTableGridRange(gridRange, `${resolvedRange.sheetName}!${resolvedRange.range}`);
|
|
20456
|
+
if (validatedInput.columns) {
|
|
20457
|
+
validateColumnCount(
|
|
20458
|
+
gridRange,
|
|
20459
|
+
validatedInput.columns,
|
|
20460
|
+
`${resolvedRange.sheetName}!${resolvedRange.range}`
|
|
20461
|
+
);
|
|
20462
|
+
}
|
|
20463
|
+
const sheetData = findSheetOrThrow(allSheets, resolvedRange.sheetName);
|
|
20464
|
+
ensureNoOverlappingTable(
|
|
20465
|
+
sheetData.tables ?? [],
|
|
20466
|
+
gridRange,
|
|
20467
|
+
resolvedRange.sheetName,
|
|
20468
|
+
validatedInput.tableId
|
|
20469
|
+
);
|
|
20470
|
+
table.range = gridRange;
|
|
20471
|
+
}
|
|
20472
|
+
const response = await sheets.spreadsheets.batchUpdate({
|
|
20473
|
+
spreadsheetId: validatedInput.spreadsheetId,
|
|
20474
|
+
requestBody: {
|
|
20475
|
+
requests: [
|
|
20476
|
+
{
|
|
20477
|
+
updateTable: {
|
|
20478
|
+
table,
|
|
20479
|
+
fields: validatedInput.fields
|
|
20480
|
+
}
|
|
20481
|
+
}
|
|
20482
|
+
]
|
|
20483
|
+
}
|
|
20484
|
+
});
|
|
20485
|
+
return formatToolResponse(`Successfully updated table "${validatedInput.tableId}"`, {
|
|
20486
|
+
spreadsheetId: response.data.spreadsheetId,
|
|
20487
|
+
table: formatTableForResponse({ ...existingTable, ...table }, responseSheetName),
|
|
20488
|
+
fields: validatedInput.fields
|
|
20489
|
+
});
|
|
20490
|
+
} catch (error2) {
|
|
20491
|
+
return handleError(error2);
|
|
20492
|
+
}
|
|
20493
|
+
}
|
|
20494
|
+
|
|
20495
|
+
// src/tools/delete-table.ts
|
|
20496
|
+
var deleteTableInputSchema = external_exports.object({
|
|
20497
|
+
spreadsheetId: external_exports.string().min(1),
|
|
20498
|
+
tableId: external_exports.string().min(1)
|
|
20499
|
+
});
|
|
20500
|
+
var deleteTableTool = {
|
|
20501
|
+
name: "sheets_delete_table",
|
|
20502
|
+
description: "Delete a native Google Sheets table by tableId",
|
|
20503
|
+
inputSchema: {
|
|
20504
|
+
type: "object",
|
|
20505
|
+
properties: {
|
|
20506
|
+
spreadsheetId: {
|
|
20507
|
+
type: "string",
|
|
20508
|
+
description: "The ID of the spreadsheet (found in the URL after /d/)"
|
|
20509
|
+
},
|
|
20510
|
+
tableId: {
|
|
20511
|
+
type: "string",
|
|
20512
|
+
description: "The ID of the table to delete"
|
|
20513
|
+
}
|
|
20514
|
+
},
|
|
20515
|
+
required: ["spreadsheetId", "tableId"]
|
|
20516
|
+
}
|
|
20517
|
+
};
|
|
20518
|
+
async function deleteTableHandler(input) {
|
|
20519
|
+
try {
|
|
20520
|
+
const validatedInput = deleteTableInputSchema.parse(input);
|
|
20521
|
+
const sheets = await getAuthenticatedClient();
|
|
20522
|
+
const metadataResponse = await sheets.spreadsheets.get({
|
|
20523
|
+
spreadsheetId: validatedInput.spreadsheetId,
|
|
20524
|
+
fields: "sheets.tables.tableId"
|
|
20525
|
+
});
|
|
20526
|
+
const tableExists = (metadataResponse.data.sheets ?? []).flatMap((sheet) => sheet.tables ?? []).some((table) => table.tableId === validatedInput.tableId);
|
|
20527
|
+
if (!tableExists) {
|
|
20528
|
+
throw new Error(`Table "${validatedInput.tableId}" not found`);
|
|
20529
|
+
}
|
|
20530
|
+
const response = await sheets.spreadsheets.batchUpdate({
|
|
20531
|
+
spreadsheetId: validatedInput.spreadsheetId,
|
|
20532
|
+
requestBody: {
|
|
20533
|
+
requests: [
|
|
20534
|
+
{
|
|
20535
|
+
deleteTable: {
|
|
20536
|
+
tableId: validatedInput.tableId
|
|
20537
|
+
}
|
|
20538
|
+
}
|
|
20539
|
+
]
|
|
20540
|
+
}
|
|
20541
|
+
});
|
|
20542
|
+
return formatToolResponse(`Successfully deleted table "${validatedInput.tableId}"`, {
|
|
20543
|
+
spreadsheetId: response.data.spreadsheetId,
|
|
20544
|
+
tableId: validatedInput.tableId
|
|
20545
|
+
});
|
|
20546
|
+
} catch (error2) {
|
|
20547
|
+
return handleError(error2);
|
|
20548
|
+
}
|
|
20549
|
+
}
|
|
20550
|
+
|
|
20551
|
+
// src/tools/get-tables.ts
|
|
20552
|
+
var getTablesInputSchema = external_exports.object({
|
|
20553
|
+
spreadsheetId: external_exports.string().min(1),
|
|
20554
|
+
sheetName: external_exports.string().min(1).optional()
|
|
20555
|
+
});
|
|
20556
|
+
var getTablesTool = {
|
|
20557
|
+
name: "sheets_get_tables",
|
|
20558
|
+
description: "Read native Google Sheets tables for a spreadsheet or a specific sheet",
|
|
20559
|
+
inputSchema: {
|
|
20560
|
+
type: "object",
|
|
20561
|
+
properties: {
|
|
20562
|
+
spreadsheetId: {
|
|
20563
|
+
type: "string",
|
|
20564
|
+
description: "The ID of the spreadsheet (found in the URL after /d/)"
|
|
20565
|
+
},
|
|
20566
|
+
sheetName: {
|
|
20567
|
+
type: "string",
|
|
20568
|
+
description: "Optional name of the sheet (tab) to inspect"
|
|
20569
|
+
}
|
|
20570
|
+
},
|
|
20571
|
+
required: ["spreadsheetId"]
|
|
20572
|
+
}
|
|
20573
|
+
};
|
|
20574
|
+
async function getTablesHandler(input) {
|
|
20575
|
+
try {
|
|
20576
|
+
const validatedInput = getTablesInputSchema.parse(input);
|
|
20577
|
+
const sheets = await getAuthenticatedClient();
|
|
20578
|
+
const response = await sheets.spreadsheets.get({
|
|
20579
|
+
spreadsheetId: validatedInput.spreadsheetId,
|
|
20580
|
+
fields: "sheets.properties.title,sheets.properties.sheetId,sheets.tables"
|
|
20581
|
+
});
|
|
20582
|
+
const spreadsheetSheets = response.data.sheets ?? [];
|
|
20583
|
+
const targetSheets = validatedInput.sheetName ? [findSheetOrThrow(spreadsheetSheets, validatedInput.sheetName)] : spreadsheetSheets;
|
|
20584
|
+
const tables = targetSheets.flatMap((sheet) => {
|
|
20585
|
+
const sheetName = sheet.properties?.title ?? void 0;
|
|
20586
|
+
return (sheet.tables ?? []).map((table) => ({
|
|
20587
|
+
sheetName: sheetName ?? null,
|
|
20588
|
+
sheetId: sheet.properties?.sheetId ?? null,
|
|
20589
|
+
...formatTableForResponse(table, sheetName)
|
|
20590
|
+
}));
|
|
20591
|
+
});
|
|
20592
|
+
const context = validatedInput.sheetName ? ` in sheet "${validatedInput.sheetName}"` : " in spreadsheet";
|
|
20593
|
+
return formatSuccessResponse(
|
|
20594
|
+
{
|
|
20595
|
+
spreadsheetId: validatedInput.spreadsheetId,
|
|
20596
|
+
sheetName: validatedInput.sheetName,
|
|
20597
|
+
tableCount: tables.length,
|
|
20598
|
+
tables
|
|
20599
|
+
},
|
|
20600
|
+
`Found ${tables.length} table(s)${context}`
|
|
20601
|
+
);
|
|
20602
|
+
} catch (error2) {
|
|
20603
|
+
return handleError(error2);
|
|
20604
|
+
}
|
|
20605
|
+
}
|
|
20606
|
+
|
|
20133
20607
|
// src/tools/check-access.ts
|
|
20134
20608
|
var CheckAccessSchema = external_exports.object({
|
|
20135
20609
|
spreadsheetId: external_exports.string().describe("The ID of the spreadsheet to check access for")
|
|
@@ -23366,6 +23840,10 @@ var toolHandlers = /* @__PURE__ */ new Map([
|
|
|
23366
23840
|
["sheets_merge_cells", mergeCellsHandler],
|
|
23367
23841
|
["sheets_unmerge_cells", unmergeCellsHandler],
|
|
23368
23842
|
["sheets_add_conditional_formatting", addConditionalFormattingHandler],
|
|
23843
|
+
["sheets_add_table", addTableHandler],
|
|
23844
|
+
["sheets_update_table", updateTableHandler],
|
|
23845
|
+
["sheets_delete_table", deleteTableHandler],
|
|
23846
|
+
["sheets_get_tables", getTablesHandler],
|
|
23369
23847
|
// Batch operations
|
|
23370
23848
|
["sheets_batch_delete_sheets", handleBatchDeleteSheets],
|
|
23371
23849
|
["sheets_batch_format_cells", handleBatchFormatCells],
|
|
@@ -23414,6 +23892,10 @@ var allTools = [
|
|
|
23414
23892
|
mergeCellsTool,
|
|
23415
23893
|
unmergeCellsTool,
|
|
23416
23894
|
addConditionalFormattingTool,
|
|
23895
|
+
addTableTool,
|
|
23896
|
+
updateTableTool,
|
|
23897
|
+
deleteTableTool,
|
|
23898
|
+
getTablesTool,
|
|
23417
23899
|
batchDeleteSheetsTool,
|
|
23418
23900
|
batchFormatCellsTool,
|
|
23419
23901
|
createChartTool,
|