@alanse/mcp-server-google-workspace 0.2.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/LICENSE +21 -0
- package/README.md +173 -0
- package/dist/auth.js +135 -0
- package/dist/index.js +116 -0
- package/dist/tools/basic/gsheets_add_sheet.js +65 -0
- package/dist/tools/basic/gsheets_copy_sheet.js +56 -0
- package/dist/tools/basic/gsheets_copy_to.js +113 -0
- package/dist/tools/basic/gsheets_create_spreadsheet.js +88 -0
- package/dist/tools/basic/gsheets_delete_columns.js +69 -0
- package/dist/tools/basic/gsheets_delete_rows.js +69 -0
- package/dist/tools/basic/gsheets_delete_sheet.js +56 -0
- package/dist/tools/basic/gsheets_duplicate_sheet.js +72 -0
- package/dist/tools/basic/gsheets_insert_columns.js +69 -0
- package/dist/tools/basic/gsheets_insert_rows.js +69 -0
- package/dist/tools/basic/gsheets_list_sheets.js +53 -0
- package/dist/tools/basic/gsheets_read.js +120 -0
- package/dist/tools/basic/gsheets_rename_sheet.js +64 -0
- package/dist/tools/charts/gsheets_add_bubble.js +176 -0
- package/dist/tools/charts/gsheets_add_candlestick.js +192 -0
- package/dist/tools/charts/gsheets_add_chart.js +162 -0
- package/dist/tools/charts/gsheets_add_combo.js +169 -0
- package/dist/tools/charts/gsheets_add_histogram.js +143 -0
- package/dist/tools/charts/gsheets_add_org_chart.js +160 -0
- package/dist/tools/charts/gsheets_add_treemap.js +177 -0
- package/dist/tools/charts/gsheets_add_waterfall.js +155 -0
- package/dist/tools/charts/gsheets_delete_chart.js +56 -0
- package/dist/tools/charts/gsheets_update_chart.js +118 -0
- package/dist/tools/data/gsheets_append_data.js +68 -0
- package/dist/tools/data/gsheets_batch_clear.js +53 -0
- package/dist/tools/data/gsheets_batch_update.js +81 -0
- package/dist/tools/data/gsheets_clear_data.js +53 -0
- package/dist/tools/data/gsheets_create_filter.js +81 -0
- package/dist/tools/data/gsheets_find_replace.js +124 -0
- package/dist/tools/data/gsheets_set_data_validation.js +153 -0
- package/dist/tools/data/gsheets_sort_range.js +102 -0
- package/dist/tools/data/gsheets_update_cell.js +44 -0
- package/dist/tools/formatting/gsheets_auto_resize.js +75 -0
- package/dist/tools/formatting/gsheets_format_cells.js +161 -0
- package/dist/tools/formatting/gsheets_freeze_columns.js +67 -0
- package/dist/tools/formatting/gsheets_freeze_rows.js +67 -0
- package/dist/tools/formatting/gsheets_merge_cells.js +85 -0
- package/dist/tools/formatting/gsheets_set_number_format.js +116 -0
- package/dist/tools/formatting/gsheets_unmerge_cells.js +79 -0
- package/dist/tools/formatting/gsheets_update_borders.js +212 -0
- package/dist/tools/gdrive/gdrive_read_file.js +77 -0
- package/dist/tools/gdrive/gdrive_search.js +71 -0
- package/dist/tools/gdrive_read_file.js +77 -0
- package/dist/tools/gdrive_search.js +71 -0
- package/dist/tools/gsheets_add_bubble.js +176 -0
- package/dist/tools/gsheets_add_candlestick.js +192 -0
- package/dist/tools/gsheets_add_chart.js +162 -0
- package/dist/tools/gsheets_add_combo.js +169 -0
- package/dist/tools/gsheets_add_conditional_format.js +175 -0
- package/dist/tools/gsheets_add_histogram.js +143 -0
- package/dist/tools/gsheets_add_named_range.js +87 -0
- package/dist/tools/gsheets_add_org_chart.js +160 -0
- package/dist/tools/gsheets_add_protected_range.js +127 -0
- package/dist/tools/gsheets_add_sheet.js +65 -0
- package/dist/tools/gsheets_add_treemap.js +177 -0
- package/dist/tools/gsheets_add_waterfall.js +155 -0
- package/dist/tools/gsheets_append_data.js +68 -0
- package/dist/tools/gsheets_auto_resize.js +75 -0
- package/dist/tools/gsheets_batch_clear.js +53 -0
- package/dist/tools/gsheets_batch_update.js +81 -0
- package/dist/tools/gsheets_clear_data.js +53 -0
- package/dist/tools/gsheets_copy_sheet.js +56 -0
- package/dist/tools/gsheets_copy_to.js +113 -0
- package/dist/tools/gsheets_create_filter.js +81 -0
- package/dist/tools/gsheets_create_spreadsheet.js +88 -0
- package/dist/tools/gsheets_delete_chart.js +56 -0
- package/dist/tools/gsheets_delete_columns.js +69 -0
- package/dist/tools/gsheets_delete_named_range.js +56 -0
- package/dist/tools/gsheets_delete_protected_range.js +56 -0
- package/dist/tools/gsheets_delete_rows.js +69 -0
- package/dist/tools/gsheets_delete_sheet.js +56 -0
- package/dist/tools/gsheets_duplicate_sheet.js +72 -0
- package/dist/tools/gsheets_find_replace.js +124 -0
- package/dist/tools/gsheets_format_cells.js +161 -0
- package/dist/tools/gsheets_freeze_columns.js +67 -0
- package/dist/tools/gsheets_freeze_rows.js +67 -0
- package/dist/tools/gsheets_insert_columns.js +69 -0
- package/dist/tools/gsheets_insert_rows.js +69 -0
- package/dist/tools/gsheets_list_sheets.js +53 -0
- package/dist/tools/gsheets_merge_cells.js +85 -0
- package/dist/tools/gsheets_read.js +120 -0
- package/dist/tools/gsheets_rename_sheet.js +64 -0
- package/dist/tools/gsheets_set_data_validation.js +153 -0
- package/dist/tools/gsheets_set_number_format.js +116 -0
- package/dist/tools/gsheets_sort_range.js +102 -0
- package/dist/tools/gsheets_unmerge_cells.js +79 -0
- package/dist/tools/gsheets_update_borders.js +212 -0
- package/dist/tools/gsheets_update_cell.js +44 -0
- package/dist/tools/gsheets_update_chart.js +118 -0
- package/dist/tools/gsheets_update_named_range.js +112 -0
- package/dist/tools/gsheets_update_protected_range.js +110 -0
- package/dist/tools/index.js +294 -0
- package/dist/tools/protection/gsheets_add_conditional_format.js +175 -0
- package/dist/tools/protection/gsheets_add_named_range.js +87 -0
- package/dist/tools/protection/gsheets_add_protected_range.js +127 -0
- package/dist/tools/protection/gsheets_delete_named_range.js +56 -0
- package/dist/tools/protection/gsheets_delete_protected_range.js +56 -0
- package/dist/tools/protection/gsheets_update_named_range.js +112 -0
- package/dist/tools/protection/gsheets_update_protected_range.js +110 -0
- package/dist/tools/sheets/advanced/gsheets_add_dimension_group.js +75 -0
- package/dist/tools/sheets/advanced/gsheets_add_filter_view.js +86 -0
- package/dist/tools/sheets/advanced/gsheets_add_pivot_table.js +188 -0
- package/dist/tools/sheets/advanced/gsheets_create_developer_metadata.js +121 -0
- package/dist/tools/sheets/advanced/gsheets_delete_developer_metadata.js +61 -0
- package/dist/tools/sheets/advanced/gsheets_delete_dimension_group.js +75 -0
- package/dist/tools/sheets/advanced/gsheets_update_developer_metadata.js +94 -0
- package/dist/tools/sheets/advanced/gsheets_update_dimension_group.js +83 -0
- package/dist/tools/sheets/basic/gsheets_add_sheet.js +65 -0
- package/dist/tools/sheets/basic/gsheets_copy_sheet.js +56 -0
- package/dist/tools/sheets/basic/gsheets_copy_to.js +113 -0
- package/dist/tools/sheets/basic/gsheets_create_spreadsheet.js +88 -0
- package/dist/tools/sheets/basic/gsheets_delete_columns.js +69 -0
- package/dist/tools/sheets/basic/gsheets_delete_rows.js +69 -0
- package/dist/tools/sheets/basic/gsheets_delete_sheet.js +56 -0
- package/dist/tools/sheets/basic/gsheets_duplicate_sheet.js +72 -0
- package/dist/tools/sheets/basic/gsheets_insert_columns.js +69 -0
- package/dist/tools/sheets/basic/gsheets_insert_rows.js +69 -0
- package/dist/tools/sheets/basic/gsheets_list_sheets.js +53 -0
- package/dist/tools/sheets/basic/gsheets_read.js +120 -0
- package/dist/tools/sheets/basic/gsheets_rename_sheet.js +64 -0
- package/dist/tools/sheets/charts/gsheets_add_bubble.js +176 -0
- package/dist/tools/sheets/charts/gsheets_add_candlestick.js +192 -0
- package/dist/tools/sheets/charts/gsheets_add_chart.js +162 -0
- package/dist/tools/sheets/charts/gsheets_add_combo.js +169 -0
- package/dist/tools/sheets/charts/gsheets_add_histogram.js +143 -0
- package/dist/tools/sheets/charts/gsheets_add_org_chart.js +160 -0
- package/dist/tools/sheets/charts/gsheets_add_treemap.js +177 -0
- package/dist/tools/sheets/charts/gsheets_add_waterfall.js +155 -0
- package/dist/tools/sheets/charts/gsheets_delete_chart.js +56 -0
- package/dist/tools/sheets/charts/gsheets_update_chart.js +118 -0
- package/dist/tools/sheets/data/gsheets_append_data.js +68 -0
- package/dist/tools/sheets/data/gsheets_batch_clear.js +53 -0
- package/dist/tools/sheets/data/gsheets_batch_update.js +81 -0
- package/dist/tools/sheets/data/gsheets_clear_data.js +53 -0
- package/dist/tools/sheets/data/gsheets_create_filter.js +81 -0
- package/dist/tools/sheets/data/gsheets_find_replace.js +124 -0
- package/dist/tools/sheets/data/gsheets_set_data_validation.js +153 -0
- package/dist/tools/sheets/data/gsheets_sort_range.js +102 -0
- package/dist/tools/sheets/data/gsheets_update_cell.js +44 -0
- package/dist/tools/sheets/formatting/gsheets_auto_resize.js +75 -0
- package/dist/tools/sheets/formatting/gsheets_format_cells.js +161 -0
- package/dist/tools/sheets/formatting/gsheets_freeze_columns.js +67 -0
- package/dist/tools/sheets/formatting/gsheets_freeze_rows.js +67 -0
- package/dist/tools/sheets/formatting/gsheets_merge_cells.js +85 -0
- package/dist/tools/sheets/formatting/gsheets_set_number_format.js +116 -0
- package/dist/tools/sheets/formatting/gsheets_unmerge_cells.js +79 -0
- package/dist/tools/sheets/formatting/gsheets_update_borders.js +212 -0
- package/dist/tools/sheets/protection/gsheets_add_conditional_format.js +175 -0
- package/dist/tools/sheets/protection/gsheets_add_named_range.js +87 -0
- package/dist/tools/sheets/protection/gsheets_add_protected_range.js +127 -0
- package/dist/tools/sheets/protection/gsheets_delete_named_range.js +56 -0
- package/dist/tools/sheets/protection/gsheets_delete_protected_range.js +56 -0
- package/dist/tools/sheets/protection/gsheets_update_named_range.js +112 -0
- package/dist/tools/sheets/protection/gsheets_update_protected_range.js +110 -0
- package/dist/tools/types.js +1 -0
- package/dist/vitest.config.js +18 -0
- package/package.json +57 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
export const schema = {
|
|
3
|
+
name: "gsheets_merge_cells",
|
|
4
|
+
description: "Merge cells in a Google Spreadsheet",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
spreadsheetId: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "The ID of the spreadsheet",
|
|
11
|
+
},
|
|
12
|
+
sheetId: {
|
|
13
|
+
type: "number",
|
|
14
|
+
description: "The ID of the sheet",
|
|
15
|
+
},
|
|
16
|
+
startRow: {
|
|
17
|
+
type: "number",
|
|
18
|
+
description: "Starting row index (0-based)",
|
|
19
|
+
},
|
|
20
|
+
endRow: {
|
|
21
|
+
type: "number",
|
|
22
|
+
description: "Ending row index (exclusive, 0-based)",
|
|
23
|
+
},
|
|
24
|
+
startColumn: {
|
|
25
|
+
type: "number",
|
|
26
|
+
description: "Starting column index (0-based)",
|
|
27
|
+
},
|
|
28
|
+
endColumn: {
|
|
29
|
+
type: "number",
|
|
30
|
+
description: "Ending column index (exclusive, 0-based)",
|
|
31
|
+
},
|
|
32
|
+
mergeType: {
|
|
33
|
+
type: "string",
|
|
34
|
+
enum: ["MERGE_ALL", "MERGE_COLUMNS", "MERGE_ROWS"],
|
|
35
|
+
description: "How to merge cells: MERGE_ALL (all cells), MERGE_COLUMNS (merge columns), MERGE_ROWS (merge rows)",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
required: ["spreadsheetId", "sheetId", "startRow", "endRow", "startColumn", "endColumn"],
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
export async function mergeCells(args) {
|
|
42
|
+
try {
|
|
43
|
+
const sheets = google.sheets("v4");
|
|
44
|
+
await sheets.spreadsheets.batchUpdate({
|
|
45
|
+
spreadsheetId: args.spreadsheetId,
|
|
46
|
+
requestBody: {
|
|
47
|
+
requests: [
|
|
48
|
+
{
|
|
49
|
+
mergeCells: {
|
|
50
|
+
range: {
|
|
51
|
+
sheetId: args.sheetId,
|
|
52
|
+
startRowIndex: args.startRow,
|
|
53
|
+
endRowIndex: args.endRow,
|
|
54
|
+
startColumnIndex: args.startColumn,
|
|
55
|
+
endColumnIndex: args.endColumn,
|
|
56
|
+
},
|
|
57
|
+
mergeType: args.mergeType || "MERGE_ALL",
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
const rangeStr = `R${args.startRow}C${args.startColumn}:R${args.endRow - 1}C${args.endColumn - 1}`;
|
|
64
|
+
return {
|
|
65
|
+
content: [
|
|
66
|
+
{
|
|
67
|
+
type: "text",
|
|
68
|
+
text: `Successfully merged cells in range ${rangeStr} using ${args.mergeType || "MERGE_ALL"} mode`,
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
isError: false,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
return {
|
|
76
|
+
content: [
|
|
77
|
+
{
|
|
78
|
+
type: "text",
|
|
79
|
+
text: `Error merging cells: ${error.message}`,
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
isError: true,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
export const schema = {
|
|
3
|
+
name: "gsheets_read",
|
|
4
|
+
description: "Read data from a Google Spreadsheet with flexible options for ranges and formatting",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
spreadsheetId: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "The ID of the spreadsheet to read",
|
|
11
|
+
},
|
|
12
|
+
ranges: {
|
|
13
|
+
type: "array",
|
|
14
|
+
items: {
|
|
15
|
+
type: "string",
|
|
16
|
+
},
|
|
17
|
+
description: "Optional array of A1 notation ranges like ['Sheet1!A1:B10']. If not provided, reads entire sheet.",
|
|
18
|
+
},
|
|
19
|
+
sheetId: {
|
|
20
|
+
type: "number",
|
|
21
|
+
description: "Optional specific sheet ID to read. If not provided with ranges, reads first sheet.",
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
required: ["spreadsheetId"],
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
const sheets = google.sheets("v4");
|
|
28
|
+
function getA1Notation(row, col) {
|
|
29
|
+
let a1 = "";
|
|
30
|
+
while (col > 0) {
|
|
31
|
+
col--;
|
|
32
|
+
a1 = String.fromCharCode(65 + (col % 26)) + a1;
|
|
33
|
+
col = Math.floor(col / 26);
|
|
34
|
+
}
|
|
35
|
+
return `${a1}${row + 1}`;
|
|
36
|
+
}
|
|
37
|
+
async function processSheetData(response) {
|
|
38
|
+
const results = [];
|
|
39
|
+
// Handle both single and multiple ranges
|
|
40
|
+
const valueRanges = response.data.valueRanges || [response.data];
|
|
41
|
+
for (const range of valueRanges) {
|
|
42
|
+
const values = range.values || [];
|
|
43
|
+
if (values.length === 0)
|
|
44
|
+
continue;
|
|
45
|
+
// Extract sheet name from range
|
|
46
|
+
const rangeParts = range.range?.split("!") || [];
|
|
47
|
+
const sheetName = rangeParts[0]?.replace(/'/g, "") || "Sheet1";
|
|
48
|
+
// Process data with cell locations
|
|
49
|
+
const processedValues = values.map((row, rowIndex) => row.map((cell, colIndex) => ({
|
|
50
|
+
value: cell,
|
|
51
|
+
location: `${sheetName}!${getA1Notation(rowIndex, colIndex + 1)}`,
|
|
52
|
+
})));
|
|
53
|
+
// Process headers with locations
|
|
54
|
+
const columnHeaders = processedValues[0];
|
|
55
|
+
const data = processedValues.slice(1);
|
|
56
|
+
results.push({
|
|
57
|
+
sheetName,
|
|
58
|
+
data,
|
|
59
|
+
totalRows: values.length,
|
|
60
|
+
totalColumns: columnHeaders.length,
|
|
61
|
+
columnHeaders,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return results;
|
|
65
|
+
}
|
|
66
|
+
export async function readSheet(args) {
|
|
67
|
+
try {
|
|
68
|
+
let response;
|
|
69
|
+
if (args.ranges) {
|
|
70
|
+
// Read specific ranges
|
|
71
|
+
response = await sheets.spreadsheets.values.batchGet({
|
|
72
|
+
spreadsheetId: args.spreadsheetId,
|
|
73
|
+
ranges: args.ranges,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
else if (args.sheetId !== undefined) {
|
|
77
|
+
// Get sheet name from sheet ID first
|
|
78
|
+
const metadata = await sheets.spreadsheets.get({
|
|
79
|
+
spreadsheetId: args.spreadsheetId,
|
|
80
|
+
fields: "sheets.properties",
|
|
81
|
+
});
|
|
82
|
+
const sheet = metadata.data.sheets?.find((s) => s.properties?.sheetId === args.sheetId);
|
|
83
|
+
if (!sheet?.properties?.title) {
|
|
84
|
+
throw new Error(`Sheet ID ${args.sheetId} not found`);
|
|
85
|
+
}
|
|
86
|
+
response = await sheets.spreadsheets.values.get({
|
|
87
|
+
spreadsheetId: args.spreadsheetId,
|
|
88
|
+
range: sheet.properties.title,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
// Read first sheet by default
|
|
93
|
+
response = await sheets.spreadsheets.values.get({
|
|
94
|
+
spreadsheetId: args.spreadsheetId,
|
|
95
|
+
range: "A:ZZ", // Read all possible columns
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
const processedData = await processSheetData(response);
|
|
99
|
+
return {
|
|
100
|
+
content: [
|
|
101
|
+
{
|
|
102
|
+
type: "text",
|
|
103
|
+
text: JSON.stringify(processedData, null, 2),
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
isError: false,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
return {
|
|
111
|
+
content: [
|
|
112
|
+
{
|
|
113
|
+
type: "text",
|
|
114
|
+
text: `Error reading spreadsheet: ${error.message}`,
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
isError: true,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
export const schema = {
|
|
3
|
+
name: "gsheets_rename_sheet",
|
|
4
|
+
description: "Rename a sheet in a Google Spreadsheet",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
spreadsheetId: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "The ID of the spreadsheet",
|
|
11
|
+
},
|
|
12
|
+
sheetId: {
|
|
13
|
+
type: "number",
|
|
14
|
+
description: "The ID of the sheet to rename",
|
|
15
|
+
},
|
|
16
|
+
newTitle: {
|
|
17
|
+
type: "string",
|
|
18
|
+
description: "The new title for the sheet",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
required: ["spreadsheetId", "sheetId", "newTitle"],
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
export async function renameSheet(args) {
|
|
25
|
+
try {
|
|
26
|
+
const sheets = google.sheets("v4");
|
|
27
|
+
await sheets.spreadsheets.batchUpdate({
|
|
28
|
+
spreadsheetId: args.spreadsheetId,
|
|
29
|
+
requestBody: {
|
|
30
|
+
requests: [
|
|
31
|
+
{
|
|
32
|
+
updateSheetProperties: {
|
|
33
|
+
properties: {
|
|
34
|
+
sheetId: args.sheetId,
|
|
35
|
+
title: args.newTitle,
|
|
36
|
+
},
|
|
37
|
+
fields: "title",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
return {
|
|
44
|
+
content: [
|
|
45
|
+
{
|
|
46
|
+
type: "text",
|
|
47
|
+
text: `Successfully renamed sheet ${args.sheetId} to "${args.newTitle}"`,
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
isError: false,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
return {
|
|
55
|
+
content: [
|
|
56
|
+
{
|
|
57
|
+
type: "text",
|
|
58
|
+
text: `Error renaming sheet: ${error.message}`,
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
isError: true,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
export const schema = {
|
|
3
|
+
name: "gsheets_set_data_validation",
|
|
4
|
+
description: "Set data validation rules for cells (dropdowns, number ranges, etc.)",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
spreadsheetId: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "The ID of the spreadsheet",
|
|
11
|
+
},
|
|
12
|
+
sheetId: {
|
|
13
|
+
type: "number",
|
|
14
|
+
description: "The ID of the sheet",
|
|
15
|
+
},
|
|
16
|
+
startRow: {
|
|
17
|
+
type: "number",
|
|
18
|
+
description: "Starting row index (0-based)",
|
|
19
|
+
},
|
|
20
|
+
endRow: {
|
|
21
|
+
type: "number",
|
|
22
|
+
description: "Ending row index (exclusive, 0-based)",
|
|
23
|
+
},
|
|
24
|
+
startColumn: {
|
|
25
|
+
type: "number",
|
|
26
|
+
description: "Starting column index (0-based)",
|
|
27
|
+
},
|
|
28
|
+
endColumn: {
|
|
29
|
+
type: "number",
|
|
30
|
+
description: "Ending column index (exclusive, 0-based)",
|
|
31
|
+
},
|
|
32
|
+
validation: {
|
|
33
|
+
type: "object",
|
|
34
|
+
properties: {
|
|
35
|
+
type: {
|
|
36
|
+
type: "string",
|
|
37
|
+
enum: ["ONE_OF_LIST", "ONE_OF_RANGE", "NUMBER_GREATER", "NUMBER_LESS", "NUMBER_BETWEEN", "DATE_AFTER", "DATE_BEFORE", "CUSTOM_FORMULA"],
|
|
38
|
+
description: "The type of data validation",
|
|
39
|
+
},
|
|
40
|
+
values: {
|
|
41
|
+
type: "array",
|
|
42
|
+
items: { type: "string" },
|
|
43
|
+
description: "List of valid values (for ONE_OF_LIST)",
|
|
44
|
+
},
|
|
45
|
+
minValue: {
|
|
46
|
+
type: "string",
|
|
47
|
+
description: "Minimum value (for NUMBER_BETWEEN, NUMBER_GREATER)",
|
|
48
|
+
},
|
|
49
|
+
maxValue: {
|
|
50
|
+
type: "string",
|
|
51
|
+
description: "Maximum value (for NUMBER_BETWEEN, NUMBER_LESS)",
|
|
52
|
+
},
|
|
53
|
+
formula: {
|
|
54
|
+
type: "string",
|
|
55
|
+
description: "Custom formula (for CUSTOM_FORMULA)",
|
|
56
|
+
},
|
|
57
|
+
strict: {
|
|
58
|
+
type: "boolean",
|
|
59
|
+
description: "Whether to reject input when validation fails (default: true)",
|
|
60
|
+
},
|
|
61
|
+
showCustomUi: {
|
|
62
|
+
type: "boolean",
|
|
63
|
+
description: "Show dropdown for list validation (default: true)",
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
required: ["type"],
|
|
67
|
+
description: "Data validation settings",
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
required: ["spreadsheetId", "sheetId", "startRow", "endRow", "startColumn", "endColumn", "validation"],
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
export async function setDataValidation(args) {
|
|
74
|
+
try {
|
|
75
|
+
const sheets = google.sheets("v4");
|
|
76
|
+
const condition = {};
|
|
77
|
+
switch (args.validation.type) {
|
|
78
|
+
case "ONE_OF_LIST":
|
|
79
|
+
if (!args.validation.values || args.validation.values.length === 0) {
|
|
80
|
+
throw new Error("values array is required for ONE_OF_LIST validation");
|
|
81
|
+
}
|
|
82
|
+
condition.type = "ONE_OF_LIST";
|
|
83
|
+
condition.values = args.validation.values.map(v => ({ userEnteredValue: v }));
|
|
84
|
+
break;
|
|
85
|
+
case "NUMBER_GREATER":
|
|
86
|
+
condition.type = "NUMBER_GREATER";
|
|
87
|
+
condition.values = [{ userEnteredValue: args.validation.minValue }];
|
|
88
|
+
break;
|
|
89
|
+
case "NUMBER_LESS":
|
|
90
|
+
condition.type = "NUMBER_LESS";
|
|
91
|
+
condition.values = [{ userEnteredValue: args.validation.maxValue }];
|
|
92
|
+
break;
|
|
93
|
+
case "NUMBER_BETWEEN":
|
|
94
|
+
condition.type = "NUMBER_BETWEEN";
|
|
95
|
+
condition.values = [
|
|
96
|
+
{ userEnteredValue: args.validation.minValue },
|
|
97
|
+
{ userEnteredValue: args.validation.maxValue },
|
|
98
|
+
];
|
|
99
|
+
break;
|
|
100
|
+
case "CUSTOM_FORMULA":
|
|
101
|
+
condition.type = "CUSTOM_FORMULA";
|
|
102
|
+
condition.values = [{ userEnteredValue: args.validation.formula }];
|
|
103
|
+
break;
|
|
104
|
+
default:
|
|
105
|
+
condition.type = args.validation.type;
|
|
106
|
+
}
|
|
107
|
+
const rule = {
|
|
108
|
+
condition,
|
|
109
|
+
strict: args.validation.strict !== false,
|
|
110
|
+
showCustomUi: args.validation.showCustomUi !== false,
|
|
111
|
+
};
|
|
112
|
+
await sheets.spreadsheets.batchUpdate({
|
|
113
|
+
spreadsheetId: args.spreadsheetId,
|
|
114
|
+
requestBody: {
|
|
115
|
+
requests: [
|
|
116
|
+
{
|
|
117
|
+
setDataValidation: {
|
|
118
|
+
range: {
|
|
119
|
+
sheetId: args.sheetId,
|
|
120
|
+
startRowIndex: args.startRow,
|
|
121
|
+
endRowIndex: args.endRow,
|
|
122
|
+
startColumnIndex: args.startColumn,
|
|
123
|
+
endColumnIndex: args.endColumn,
|
|
124
|
+
},
|
|
125
|
+
rule,
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
const rangeStr = `R${args.startRow}C${args.startColumn}:R${args.endRow - 1}C${args.endColumn - 1}`;
|
|
132
|
+
return {
|
|
133
|
+
content: [
|
|
134
|
+
{
|
|
135
|
+
type: "text",
|
|
136
|
+
text: `Successfully set data validation (${args.validation.type}) for range ${rangeStr}`,
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
isError: false,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
return {
|
|
144
|
+
content: [
|
|
145
|
+
{
|
|
146
|
+
type: "text",
|
|
147
|
+
text: `Error setting data validation: ${error.message}`,
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
isError: true,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
export const schema = {
|
|
3
|
+
name: "gsheets_set_number_format",
|
|
4
|
+
description: "Set number format for cells (currency, percentage, date, etc.)",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
spreadsheetId: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "The ID of the spreadsheet",
|
|
11
|
+
},
|
|
12
|
+
sheetId: {
|
|
13
|
+
type: "number",
|
|
14
|
+
description: "The ID of the sheet",
|
|
15
|
+
},
|
|
16
|
+
startRow: {
|
|
17
|
+
type: "number",
|
|
18
|
+
description: "Starting row index (0-based)",
|
|
19
|
+
},
|
|
20
|
+
endRow: {
|
|
21
|
+
type: "number",
|
|
22
|
+
description: "Ending row index (exclusive, 0-based)",
|
|
23
|
+
},
|
|
24
|
+
startColumn: {
|
|
25
|
+
type: "number",
|
|
26
|
+
description: "Starting column index (0-based)",
|
|
27
|
+
},
|
|
28
|
+
endColumn: {
|
|
29
|
+
type: "number",
|
|
30
|
+
description: "Ending column index (exclusive, 0-based)",
|
|
31
|
+
},
|
|
32
|
+
numberFormat: {
|
|
33
|
+
type: "object",
|
|
34
|
+
properties: {
|
|
35
|
+
type: {
|
|
36
|
+
type: "string",
|
|
37
|
+
enum: ["NUMBER", "CURRENCY", "PERCENT", "DATE", "TIME", "DATE_TIME", "SCIENTIFIC", "TEXT"],
|
|
38
|
+
description: "The type of number format",
|
|
39
|
+
},
|
|
40
|
+
pattern: {
|
|
41
|
+
type: "string",
|
|
42
|
+
description: "Custom format pattern (optional, e.g., '$#,##0.00', '0.00%', 'yyyy-mm-dd')",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
required: ["type"],
|
|
46
|
+
description: "Number format settings",
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
required: ["spreadsheetId", "sheetId", "startRow", "endRow", "startColumn", "endColumn", "numberFormat"],
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
export async function setNumberFormat(args) {
|
|
53
|
+
try {
|
|
54
|
+
const sheets = google.sheets("v4");
|
|
55
|
+
// Default patterns for common types
|
|
56
|
+
const defaultPatterns = {
|
|
57
|
+
NUMBER: "#,##0.00",
|
|
58
|
+
CURRENCY: "$#,##0.00",
|
|
59
|
+
PERCENT: "0.00%",
|
|
60
|
+
DATE: "yyyy-mm-dd",
|
|
61
|
+
TIME: "h:mm:ss",
|
|
62
|
+
DATE_TIME: "yyyy-mm-dd h:mm:ss",
|
|
63
|
+
SCIENTIFIC: "0.00E+00",
|
|
64
|
+
TEXT: "@",
|
|
65
|
+
};
|
|
66
|
+
const pattern = args.numberFormat.pattern || defaultPatterns[args.numberFormat.type];
|
|
67
|
+
await sheets.spreadsheets.batchUpdate({
|
|
68
|
+
spreadsheetId: args.spreadsheetId,
|
|
69
|
+
requestBody: {
|
|
70
|
+
requests: [
|
|
71
|
+
{
|
|
72
|
+
repeatCell: {
|
|
73
|
+
range: {
|
|
74
|
+
sheetId: args.sheetId,
|
|
75
|
+
startRowIndex: args.startRow,
|
|
76
|
+
endRowIndex: args.endRow,
|
|
77
|
+
startColumnIndex: args.startColumn,
|
|
78
|
+
endColumnIndex: args.endColumn,
|
|
79
|
+
},
|
|
80
|
+
cell: {
|
|
81
|
+
userEnteredFormat: {
|
|
82
|
+
numberFormat: {
|
|
83
|
+
type: args.numberFormat.type,
|
|
84
|
+
pattern: pattern,
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
fields: "userEnteredFormat.numberFormat",
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
const rangeStr = `R${args.startRow}C${args.startColumn}:R${args.endRow - 1}C${args.endColumn - 1}`;
|
|
95
|
+
return {
|
|
96
|
+
content: [
|
|
97
|
+
{
|
|
98
|
+
type: "text",
|
|
99
|
+
text: `Successfully set number format to ${args.numberFormat.type} (pattern: ${pattern}) for range ${rangeStr}`,
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
isError: false,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
return {
|
|
107
|
+
content: [
|
|
108
|
+
{
|
|
109
|
+
type: "text",
|
|
110
|
+
text: `Error setting number format: ${error.message}`,
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
isError: true,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
export const schema = {
|
|
3
|
+
name: "gsheets_sort_range",
|
|
4
|
+
description: "Sort a range of data in a Google Spreadsheet",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
spreadsheetId: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "The ID of the spreadsheet",
|
|
11
|
+
},
|
|
12
|
+
sheetId: {
|
|
13
|
+
type: "number",
|
|
14
|
+
description: "The ID of the sheet",
|
|
15
|
+
},
|
|
16
|
+
startRow: {
|
|
17
|
+
type: "number",
|
|
18
|
+
description: "Starting row index (0-based)",
|
|
19
|
+
},
|
|
20
|
+
endRow: {
|
|
21
|
+
type: "number",
|
|
22
|
+
description: "Ending row index (exclusive, 0-based)",
|
|
23
|
+
},
|
|
24
|
+
startColumn: {
|
|
25
|
+
type: "number",
|
|
26
|
+
description: "Starting column index (0-based)",
|
|
27
|
+
},
|
|
28
|
+
endColumn: {
|
|
29
|
+
type: "number",
|
|
30
|
+
description: "Ending column index (exclusive, 0-based)",
|
|
31
|
+
},
|
|
32
|
+
sortSpecs: {
|
|
33
|
+
type: "array",
|
|
34
|
+
items: {
|
|
35
|
+
type: "object",
|
|
36
|
+
properties: {
|
|
37
|
+
dimensionIndex: {
|
|
38
|
+
type: "number",
|
|
39
|
+
description: "Column index to sort by (0-based)",
|
|
40
|
+
},
|
|
41
|
+
sortOrder: {
|
|
42
|
+
type: "string",
|
|
43
|
+
enum: ["ASCENDING", "DESCENDING"],
|
|
44
|
+
description: "Sort order",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
required: ["dimensionIndex", "sortOrder"],
|
|
48
|
+
},
|
|
49
|
+
description: "Sort specifications (multiple for multi-level sorting)",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
required: ["spreadsheetId", "sheetId", "startRow", "endRow", "startColumn", "endColumn", "sortSpecs"],
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
export async function sortRange(args) {
|
|
56
|
+
try {
|
|
57
|
+
const sheets = google.sheets("v4");
|
|
58
|
+
await sheets.spreadsheets.batchUpdate({
|
|
59
|
+
spreadsheetId: args.spreadsheetId,
|
|
60
|
+
requestBody: {
|
|
61
|
+
requests: [
|
|
62
|
+
{
|
|
63
|
+
sortRange: {
|
|
64
|
+
range: {
|
|
65
|
+
sheetId: args.sheetId,
|
|
66
|
+
startRowIndex: args.startRow,
|
|
67
|
+
endRowIndex: args.endRow,
|
|
68
|
+
startColumnIndex: args.startColumn,
|
|
69
|
+
endColumnIndex: args.endColumn,
|
|
70
|
+
},
|
|
71
|
+
sortSpecs: args.sortSpecs,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
const rangeStr = `R${args.startRow}C${args.startColumn}:R${args.endRow - 1}C${args.endColumn - 1}`;
|
|
78
|
+
const sortDesc = args.sortSpecs
|
|
79
|
+
.map((spec) => `column ${spec.dimensionIndex} (${spec.sortOrder})`)
|
|
80
|
+
.join(", ");
|
|
81
|
+
return {
|
|
82
|
+
content: [
|
|
83
|
+
{
|
|
84
|
+
type: "text",
|
|
85
|
+
text: `Successfully sorted range ${rangeStr} by ${sortDesc}`,
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
isError: false,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
return {
|
|
93
|
+
content: [
|
|
94
|
+
{
|
|
95
|
+
type: "text",
|
|
96
|
+
text: `Error sorting range: ${error.message}`,
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
isError: true,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|