mcp-gsheets 1.4.1 → 1.5.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.
Files changed (3) hide show
  1. package/README.md +40 -1
  2. package/dist/index.js +158 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -195,8 +195,9 @@ npm run dev # Watch mode with auto-reload
195
195
  ### Writing Data
196
196
  - `sheets_update_values` - Write to a range
197
197
  - `sheets_batch_update_values` - Write to multiple ranges
198
- - `sheets_append_values` - Append rows to a table
198
+ - `sheets_append_values` - Append rows to a table (**Note:** Default `insertDataOption` is `OVERWRITE`. To insert new rows, set `insertDataOption: 'INSERT_ROWS'`)
199
199
  - `sheets_clear_values` - Clear cell contents
200
+ - `sheets_insert_rows` - Insert new rows at specific position with optional data
200
201
 
201
202
  ### Sheet Management
202
203
  - `sheets_insert_sheet` - Add new sheet
@@ -295,6 +296,44 @@ Use `sheets_get_metadata` to list all sheets with their IDs.
295
296
  4. Check rate limits for large operations
296
297
  5. Use `sheets_check_access` to verify permissions before operations
297
298
 
299
+ ## 📘 Tool Details
300
+
301
+ ### sheets_insert_rows
302
+
303
+ Insert new rows at a specific position in a spreadsheet with optional data.
304
+
305
+ **Parameters:**
306
+ - `spreadsheetId` (required): The ID of the spreadsheet
307
+ - `range` (required): A1 notation anchor point where rows will be inserted (e.g., "Sheet1!A5")
308
+ - `rows` (optional): Number of rows to insert (default: 1)
309
+ - `position` (optional): 'BEFORE' or 'AFTER' the anchor row (default: 'BEFORE')
310
+ - `inheritFromBefore` (optional): Whether to inherit formatting from the row before (default: false)
311
+ - `values` (optional): 2D array of values to fill the newly inserted rows
312
+ - `valueInputOption` (optional): 'RAW' or 'USER_ENTERED' (default: 'USER_ENTERED')
313
+
314
+ **Examples:**
315
+
316
+ ```javascript
317
+ // Insert 1 empty row before row 5
318
+ {
319
+ "spreadsheetId": "your-spreadsheet-id",
320
+ "range": "Sheet1!A5"
321
+ }
322
+
323
+ // Insert 3 rows after row 10 with data
324
+ {
325
+ "spreadsheetId": "your-spreadsheet-id",
326
+ "range": "Sheet1!A10",
327
+ "rows": 3,
328
+ "position": "AFTER",
329
+ "values": [
330
+ ["John", "Doe", "john@example.com"],
331
+ ["Jane", "Smith", "jane@example.com"],
332
+ ["Bob", "Johnson", "bob@example.com"]
333
+ ]
334
+ }
335
+ ```
336
+
298
337
  ## 📋 Changelog
299
338
 
300
339
  See [CHANGELOG.md](CHANGELOG.md) for a list of changes in each version.
package/dist/index.js CHANGED
@@ -12624,6 +12624,14 @@ function validateSpreadsheetIdField(id) {
12624
12624
  throw new Error("Invalid spreadsheet ID format");
12625
12625
  }
12626
12626
  }
12627
+ function validateRangeField(range) {
12628
+ if (!range || typeof range !== "string") {
12629
+ throw new Error(ERROR_MESSAGES.RANGE_REQUIRED);
12630
+ }
12631
+ if (!validateRange(range)) {
12632
+ throw new Error(ERROR_MESSAGES.INVALID_RANGE);
12633
+ }
12634
+ }
12627
12635
  function validateSheetIdField(sheetId) {
12628
12636
  if (sheetId === void 0 || typeof sheetId !== "number") {
12629
12637
  throw new Error(ERROR_MESSAGES.SHEET_ID_REQUIRED);
@@ -12940,6 +12948,34 @@ function validateDeleteChartInput(input) {
12940
12948
  chartId: input.chartId
12941
12949
  };
12942
12950
  }
12951
+ function validateInsertRowsInput(input) {
12952
+ validateSpreadsheetIdField(input.spreadsheetId);
12953
+ validateRangeField(input.range);
12954
+ const rows = input.rows ?? 1;
12955
+ if (typeof rows !== "number" || rows <= 0) {
12956
+ throw new Error("Rows must be a positive number");
12957
+ }
12958
+ const position = input.position ?? "BEFORE";
12959
+ if (!["BEFORE", "AFTER"].includes(position)) {
12960
+ throw new Error("Position must be either BEFORE or AFTER");
12961
+ }
12962
+ const inheritFromBefore = input.inheritFromBefore ?? false;
12963
+ const valueInputOption = input.valueInputOption ?? "USER_ENTERED";
12964
+ if (input.values) {
12965
+ if (!Array.isArray(input.values) || !input.values.every((row) => Array.isArray(row))) {
12966
+ throw new Error("Values must be a 2D array");
12967
+ }
12968
+ }
12969
+ return {
12970
+ spreadsheetId: input.spreadsheetId,
12971
+ range: input.range,
12972
+ rows,
12973
+ position,
12974
+ inheritFromBefore,
12975
+ values: input.values,
12976
+ valueInputOption
12977
+ };
12978
+ }
12943
12979
 
12944
12980
  // src/utils/response-helpers.ts
12945
12981
  function createTextResponse(text) {
@@ -13162,7 +13198,7 @@ To fix this, either:
13162
13198
  // src/tools/append-values.ts
13163
13199
  var appendValuesTool = {
13164
13200
  name: "sheets_append_values",
13165
- description: "Append values to the end of a table in a Google Sheets spreadsheet",
13201
+ description: 'Append values to the end of a table in a Google Sheets spreadsheet. IMPORTANT: By default, this will OVERWRITE existing empty cells. To INSERT new rows instead, set insertDataOption to "INSERT_ROWS".',
13166
13202
  inputSchema: {
13167
13203
  type: "object",
13168
13204
  properties: {
@@ -15566,6 +15602,122 @@ async function handleInsertDate(input) {
15566
15602
  }
15567
15603
  }
15568
15604
 
15605
+ // src/tools/insert-rows.ts
15606
+ var insertRowsTool = {
15607
+ name: "sheets_insert_rows",
15608
+ description: "Insert new rows at a specific position with optional data",
15609
+ inputSchema: {
15610
+ type: "object",
15611
+ properties: {
15612
+ spreadsheetId: {
15613
+ type: "string",
15614
+ description: "The ID of the spreadsheet (found in the URL after /d/)"
15615
+ },
15616
+ range: {
15617
+ type: "string",
15618
+ description: 'The A1 notation anchor point where rows will be inserted (e.g., "Sheet1!A5")'
15619
+ },
15620
+ rows: {
15621
+ type: "number",
15622
+ description: "Number of rows to insert (default: 1)"
15623
+ },
15624
+ position: {
15625
+ type: "string",
15626
+ enum: ["BEFORE", "AFTER"],
15627
+ description: "Position relative to the anchor row (default: BEFORE)"
15628
+ },
15629
+ inheritFromBefore: {
15630
+ type: "boolean",
15631
+ description: "Whether to inherit formatting from the row before (default: false)"
15632
+ },
15633
+ values: {
15634
+ type: "array",
15635
+ items: {
15636
+ type: "array"
15637
+ },
15638
+ description: "Optional 2D array of values to fill the newly inserted rows"
15639
+ },
15640
+ valueInputOption: {
15641
+ type: "string",
15642
+ enum: ["RAW", "USER_ENTERED"],
15643
+ description: "How the input data should be interpreted (default: USER_ENTERED)"
15644
+ }
15645
+ },
15646
+ required: ["spreadsheetId", "range"]
15647
+ }
15648
+ };
15649
+ function indexToColumn(index) {
15650
+ let column = "";
15651
+ let num = index + 1;
15652
+ while (num > 0) {
15653
+ num--;
15654
+ column = String.fromCharCode(num % 26 + "A".charCodeAt(0)) + column;
15655
+ num = Math.floor(num / 26);
15656
+ }
15657
+ return column;
15658
+ }
15659
+ async function handleInsertRows(input) {
15660
+ try {
15661
+ const validatedInput = validateInsertRowsInput(input);
15662
+ const sheets = await getAuthenticatedClient();
15663
+ const { sheetName, range: cellRange } = extractSheetName(validatedInput.range);
15664
+ const sheetId = await getSheetId(sheets, validatedInput.spreadsheetId, sheetName);
15665
+ const parsedRange = parseRange(cellRange, sheetId);
15666
+ const anchorRowIndex = parsedRange.startRowIndex ?? 0;
15667
+ const anchorColumnIndex = parsedRange.startColumnIndex ?? 0;
15668
+ const startIndex = validatedInput.position === "AFTER" ? anchorRowIndex + 1 : anchorRowIndex;
15669
+ const endIndex = startIndex + validatedInput.rows;
15670
+ const insertRequest = {
15671
+ spreadsheetId: validatedInput.spreadsheetId,
15672
+ requestBody: {
15673
+ requests: [
15674
+ {
15675
+ insertDimension: {
15676
+ range: {
15677
+ sheetId,
15678
+ dimension: "ROWS",
15679
+ startIndex,
15680
+ endIndex
15681
+ },
15682
+ inheritFromBefore: validatedInput.inheritFromBefore
15683
+ }
15684
+ }
15685
+ ]
15686
+ }
15687
+ };
15688
+ await sheets.spreadsheets.batchUpdate(insertRequest);
15689
+ if (validatedInput.values && validatedInput.values.length > 0) {
15690
+ const updateStartRow = startIndex + 1;
15691
+ const updateEndRow = updateStartRow + validatedInput.values.length - 1;
15692
+ const startColumn = indexToColumn(anchorColumnIndex);
15693
+ const endColumn = indexToColumn(
15694
+ anchorColumnIndex + Math.max(...validatedInput.values.map((row) => row.length)) - 1
15695
+ );
15696
+ const updateRange = sheetName ? `'${sheetName}'!${startColumn}${updateStartRow}:${endColumn}${updateEndRow}` : `${startColumn}${updateStartRow}:${endColumn}${updateEndRow}`;
15697
+ await sheets.spreadsheets.values.update({
15698
+ spreadsheetId: validatedInput.spreadsheetId,
15699
+ range: updateRange,
15700
+ valueInputOption: validatedInput.valueInputOption,
15701
+ requestBody: {
15702
+ values: validatedInput.values
15703
+ }
15704
+ });
15705
+ const cellCount = validatedInput.values.reduce(
15706
+ (sum, row) => sum + row.length,
15707
+ 0
15708
+ );
15709
+ return formatToolResponse(
15710
+ `Inserted ${validatedInput.rows} rows ${validatedInput.position} row ${anchorRowIndex + 1} on "${sheetName || "Sheet"}" and updated ${cellCount} cells in range: ${updateRange}`
15711
+ );
15712
+ }
15713
+ return formatToolResponse(
15714
+ `Inserted ${validatedInput.rows} rows ${validatedInput.position} row ${anchorRowIndex + 1} on "${sheetName || "Sheet"}"`
15715
+ );
15716
+ } catch (error) {
15717
+ return handleError(error);
15718
+ }
15719
+ }
15720
+
15569
15721
  // src/index.ts
15570
15722
  if (process.env.NODE_ENV !== "production") {
15571
15723
  try {
@@ -15607,7 +15759,9 @@ var toolHandlers = /* @__PURE__ */ new Map([
15607
15759
  ["sheets_delete_chart", handleDeleteChart],
15608
15760
  // Link and date operations
15609
15761
  ["sheets_insert_link", handleInsertLink],
15610
- ["sheets_insert_date", handleInsertDate]
15762
+ ["sheets_insert_date", handleInsertDate],
15763
+ // Row operations
15764
+ ["sheets_insert_rows", handleInsertRows]
15611
15765
  ]);
15612
15766
  var allTools = [
15613
15767
  checkAccessTool,
@@ -15635,7 +15789,8 @@ var allTools = [
15635
15789
  updateChartTool,
15636
15790
  deleteChartTool,
15637
15791
  insertLinkTool,
15638
- insertDateTool
15792
+ insertDateTool,
15793
+ insertRowsTool
15639
15794
  ];
15640
15795
  async function main() {
15641
15796
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-gsheets",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "Model Context Protocol (MCP) server for Google Sheets API integration",
5
5
  "author": "freema",
6
6
  "license": "MIT",