@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,77 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
export const schema = {
|
|
3
|
+
name: "gdrive_read_file",
|
|
4
|
+
description: "Read contents of a file from Google Drive",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
fileId: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "ID of the file to read",
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
required: ["fileId"],
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
const drive = google.drive("v3");
|
|
17
|
+
export async function readFile(args) {
|
|
18
|
+
const result = await readGoogleDriveFile(args.fileId);
|
|
19
|
+
return {
|
|
20
|
+
content: [
|
|
21
|
+
{
|
|
22
|
+
type: "text",
|
|
23
|
+
text: `Contents of ${result.name}:\n\n${result.contents.text || result.contents.blob}`,
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
isError: false,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
async function readGoogleDriveFile(fileId) {
|
|
30
|
+
// First get file metadata to check mime type
|
|
31
|
+
const file = await drive.files.get({
|
|
32
|
+
fileId,
|
|
33
|
+
fields: "mimeType,name",
|
|
34
|
+
});
|
|
35
|
+
// For Google Docs/Sheets/etc we need to export
|
|
36
|
+
if (file.data.mimeType?.startsWith("application/vnd.google-apps")) {
|
|
37
|
+
let exportMimeType;
|
|
38
|
+
switch (file.data.mimeType) {
|
|
39
|
+
case "application/vnd.google-apps.document":
|
|
40
|
+
exportMimeType = "text/markdown";
|
|
41
|
+
break;
|
|
42
|
+
case "application/vnd.google-apps.spreadsheet":
|
|
43
|
+
exportMimeType = "text/csv";
|
|
44
|
+
break;
|
|
45
|
+
case "application/vnd.google-apps.presentation":
|
|
46
|
+
exportMimeType = "text/plain";
|
|
47
|
+
break;
|
|
48
|
+
case "application/vnd.google-apps.drawing":
|
|
49
|
+
exportMimeType = "image/png";
|
|
50
|
+
break;
|
|
51
|
+
default:
|
|
52
|
+
exportMimeType = "text/plain";
|
|
53
|
+
}
|
|
54
|
+
const res = await drive.files.export({ fileId, mimeType: exportMimeType }, { responseType: "text" });
|
|
55
|
+
return {
|
|
56
|
+
name: file.data.name || fileId,
|
|
57
|
+
contents: {
|
|
58
|
+
mimeType: exportMimeType,
|
|
59
|
+
text: res.data,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
// For regular files download content
|
|
64
|
+
const res = await drive.files.get({ fileId, alt: "media" }, { responseType: "arraybuffer" });
|
|
65
|
+
const mimeType = file.data.mimeType || "application/octet-stream";
|
|
66
|
+
const isText = mimeType.startsWith("text/") || mimeType === "application/json";
|
|
67
|
+
const content = Buffer.from(res.data);
|
|
68
|
+
return {
|
|
69
|
+
name: file.data.name || fileId,
|
|
70
|
+
contents: {
|
|
71
|
+
mimeType,
|
|
72
|
+
...(isText
|
|
73
|
+
? { text: content.toString("utf-8") }
|
|
74
|
+
: { blob: content.toString("base64") }),
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
export const schema = {
|
|
3
|
+
name: "gdrive_search",
|
|
4
|
+
description: "Search for files in Google Drive",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
query: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "Search query",
|
|
11
|
+
},
|
|
12
|
+
pageToken: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Token for the next page of results",
|
|
15
|
+
optional: true,
|
|
16
|
+
},
|
|
17
|
+
pageSize: {
|
|
18
|
+
type: "number",
|
|
19
|
+
description: "Number of results per page (max 100)",
|
|
20
|
+
optional: true,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
required: ["query"],
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
export async function search(args) {
|
|
27
|
+
const drive = google.drive("v3");
|
|
28
|
+
const userQuery = args.query.trim();
|
|
29
|
+
let searchQuery = "";
|
|
30
|
+
// If query is empty, list all files
|
|
31
|
+
if (!userQuery) {
|
|
32
|
+
searchQuery = "trashed = false";
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// Escape special characters in the query
|
|
36
|
+
const escapedQuery = userQuery.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
37
|
+
// Build search query with multiple conditions
|
|
38
|
+
const conditions = [];
|
|
39
|
+
// Search in title
|
|
40
|
+
conditions.push(`name contains '${escapedQuery}'`);
|
|
41
|
+
// If specific file type is mentioned in query, add mimeType condition
|
|
42
|
+
if (userQuery.toLowerCase().includes("sheet")) {
|
|
43
|
+
conditions.push("mimeType = 'application/vnd.google-sheets.spreadsheet'");
|
|
44
|
+
}
|
|
45
|
+
searchQuery = `(${conditions.join(" or ")}) and trashed = false`;
|
|
46
|
+
}
|
|
47
|
+
const res = await drive.files.list({
|
|
48
|
+
q: searchQuery,
|
|
49
|
+
pageSize: args.pageSize || 10,
|
|
50
|
+
pageToken: args.pageToken,
|
|
51
|
+
orderBy: "modifiedTime desc",
|
|
52
|
+
fields: "nextPageToken, files(id, name, mimeType, modifiedTime, size)",
|
|
53
|
+
});
|
|
54
|
+
const fileList = res.data.files
|
|
55
|
+
?.map((file) => `${file.id} ${file.name} (${file.mimeType})`)
|
|
56
|
+
.join("\n");
|
|
57
|
+
let response = `Found ${res.data.files?.length ?? 0} files:\n${fileList}`;
|
|
58
|
+
// Add pagination info if there are more results
|
|
59
|
+
if (res.data.nextPageToken) {
|
|
60
|
+
response += `\n\nMore results available. Use pageToken: ${res.data.nextPageToken}`;
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
content: [
|
|
64
|
+
{
|
|
65
|
+
type: "text",
|
|
66
|
+
text: response,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
isError: false,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
export const schema = {
|
|
3
|
+
name: "gdrive_read_file",
|
|
4
|
+
description: "Read contents of a file from Google Drive",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
fileId: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "ID of the file to read",
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
required: ["fileId"],
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
const drive = google.drive("v3");
|
|
17
|
+
export async function readFile(args) {
|
|
18
|
+
const result = await readGoogleDriveFile(args.fileId);
|
|
19
|
+
return {
|
|
20
|
+
content: [
|
|
21
|
+
{
|
|
22
|
+
type: "text",
|
|
23
|
+
text: `Contents of ${result.name}:\n\n${result.contents.text || result.contents.blob}`,
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
isError: false,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
async function readGoogleDriveFile(fileId) {
|
|
30
|
+
// First get file metadata to check mime type
|
|
31
|
+
const file = await drive.files.get({
|
|
32
|
+
fileId,
|
|
33
|
+
fields: "mimeType,name",
|
|
34
|
+
});
|
|
35
|
+
// For Google Docs/Sheets/etc we need to export
|
|
36
|
+
if (file.data.mimeType?.startsWith("application/vnd.google-apps")) {
|
|
37
|
+
let exportMimeType;
|
|
38
|
+
switch (file.data.mimeType) {
|
|
39
|
+
case "application/vnd.google-apps.document":
|
|
40
|
+
exportMimeType = "text/markdown";
|
|
41
|
+
break;
|
|
42
|
+
case "application/vnd.google-apps.spreadsheet":
|
|
43
|
+
exportMimeType = "text/csv";
|
|
44
|
+
break;
|
|
45
|
+
case "application/vnd.google-apps.presentation":
|
|
46
|
+
exportMimeType = "text/plain";
|
|
47
|
+
break;
|
|
48
|
+
case "application/vnd.google-apps.drawing":
|
|
49
|
+
exportMimeType = "image/png";
|
|
50
|
+
break;
|
|
51
|
+
default:
|
|
52
|
+
exportMimeType = "text/plain";
|
|
53
|
+
}
|
|
54
|
+
const res = await drive.files.export({ fileId, mimeType: exportMimeType }, { responseType: "text" });
|
|
55
|
+
return {
|
|
56
|
+
name: file.data.name || fileId,
|
|
57
|
+
contents: {
|
|
58
|
+
mimeType: exportMimeType,
|
|
59
|
+
text: res.data,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
// For regular files download content
|
|
64
|
+
const res = await drive.files.get({ fileId, alt: "media" }, { responseType: "arraybuffer" });
|
|
65
|
+
const mimeType = file.data.mimeType || "application/octet-stream";
|
|
66
|
+
const isText = mimeType.startsWith("text/") || mimeType === "application/json";
|
|
67
|
+
const content = Buffer.from(res.data);
|
|
68
|
+
return {
|
|
69
|
+
name: file.data.name || fileId,
|
|
70
|
+
contents: {
|
|
71
|
+
mimeType,
|
|
72
|
+
...(isText
|
|
73
|
+
? { text: content.toString("utf-8") }
|
|
74
|
+
: { blob: content.toString("base64") }),
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
export const schema = {
|
|
3
|
+
name: "gdrive_search",
|
|
4
|
+
description: "Search for files in Google Drive",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
query: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "Search query",
|
|
11
|
+
},
|
|
12
|
+
pageToken: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Token for the next page of results",
|
|
15
|
+
optional: true,
|
|
16
|
+
},
|
|
17
|
+
pageSize: {
|
|
18
|
+
type: "number",
|
|
19
|
+
description: "Number of results per page (max 100)",
|
|
20
|
+
optional: true,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
required: ["query"],
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
export async function search(args) {
|
|
27
|
+
const drive = google.drive("v3");
|
|
28
|
+
const userQuery = args.query.trim();
|
|
29
|
+
let searchQuery = "";
|
|
30
|
+
// If query is empty, list all files
|
|
31
|
+
if (!userQuery) {
|
|
32
|
+
searchQuery = "trashed = false";
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// Escape special characters in the query
|
|
36
|
+
const escapedQuery = userQuery.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
37
|
+
// Build search query with multiple conditions
|
|
38
|
+
const conditions = [];
|
|
39
|
+
// Search in title
|
|
40
|
+
conditions.push(`name contains '${escapedQuery}'`);
|
|
41
|
+
// If specific file type is mentioned in query, add mimeType condition
|
|
42
|
+
if (userQuery.toLowerCase().includes("sheet")) {
|
|
43
|
+
conditions.push("mimeType = 'application/vnd.google-sheets.spreadsheet'");
|
|
44
|
+
}
|
|
45
|
+
searchQuery = `(${conditions.join(" or ")}) and trashed = false`;
|
|
46
|
+
}
|
|
47
|
+
const res = await drive.files.list({
|
|
48
|
+
q: searchQuery,
|
|
49
|
+
pageSize: args.pageSize || 10,
|
|
50
|
+
pageToken: args.pageToken,
|
|
51
|
+
orderBy: "modifiedTime desc",
|
|
52
|
+
fields: "nextPageToken, files(id, name, mimeType, modifiedTime, size)",
|
|
53
|
+
});
|
|
54
|
+
const fileList = res.data.files
|
|
55
|
+
?.map((file) => `${file.id} ${file.name} (${file.mimeType})`)
|
|
56
|
+
.join("\n");
|
|
57
|
+
let response = `Found ${res.data.files?.length ?? 0} files:\n${fileList}`;
|
|
58
|
+
// Add pagination info if there are more results
|
|
59
|
+
if (res.data.nextPageToken) {
|
|
60
|
+
response += `\n\nMore results available. Use pageToken: ${res.data.nextPageToken}`;
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
content: [
|
|
64
|
+
{
|
|
65
|
+
type: "text",
|
|
66
|
+
text: response,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
isError: false,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
export const schema = {
|
|
3
|
+
name: "gsheets_add_bubble",
|
|
4
|
+
description: "Add a bubble chart to a spreadsheet (displays 3D data with bubble size)",
|
|
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 where the chart will be placed",
|
|
15
|
+
},
|
|
16
|
+
title: {
|
|
17
|
+
type: "string",
|
|
18
|
+
description: "Chart title (optional)",
|
|
19
|
+
},
|
|
20
|
+
dataSheetId: {
|
|
21
|
+
type: "number",
|
|
22
|
+
description: "The sheet ID containing the data",
|
|
23
|
+
},
|
|
24
|
+
dataStartRow: {
|
|
25
|
+
type: "number",
|
|
26
|
+
description: "Starting row of data range (0-based)",
|
|
27
|
+
},
|
|
28
|
+
dataEndRow: {
|
|
29
|
+
type: "number",
|
|
30
|
+
description: "Ending row of data range (exclusive, 0-based)",
|
|
31
|
+
},
|
|
32
|
+
labelsColumn: {
|
|
33
|
+
type: "number",
|
|
34
|
+
description: "Column index for labels (0-based, optional)",
|
|
35
|
+
},
|
|
36
|
+
xValuesColumn: {
|
|
37
|
+
type: "number",
|
|
38
|
+
description: "Column index for X-axis values (0-based)",
|
|
39
|
+
},
|
|
40
|
+
yValuesColumn: {
|
|
41
|
+
type: "number",
|
|
42
|
+
description: "Column index for Y-axis values (0-based)",
|
|
43
|
+
},
|
|
44
|
+
sizeColumn: {
|
|
45
|
+
type: "number",
|
|
46
|
+
description: "Column index for bubble size values (0-based)",
|
|
47
|
+
},
|
|
48
|
+
position: {
|
|
49
|
+
type: "object",
|
|
50
|
+
properties: {
|
|
51
|
+
overlayRow: {
|
|
52
|
+
type: "number",
|
|
53
|
+
description: "Row position for chart overlay (0-based)",
|
|
54
|
+
},
|
|
55
|
+
overlayColumn: {
|
|
56
|
+
type: "number",
|
|
57
|
+
description: "Column position for chart overlay (0-based)",
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
description: "Chart position (optional)",
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
required: ["spreadsheetId", "sheetId", "dataSheetId", "dataStartRow", "dataEndRow", "xValuesColumn", "yValuesColumn", "sizeColumn"],
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
export async function addBubble(args) {
|
|
67
|
+
try {
|
|
68
|
+
const sheets = google.sheets("v4");
|
|
69
|
+
const bubbleChart = {
|
|
70
|
+
legendPosition: "BOTTOM_LEGEND",
|
|
71
|
+
domain: {
|
|
72
|
+
sourceRange: {
|
|
73
|
+
sources: [
|
|
74
|
+
{
|
|
75
|
+
sheetId: args.dataSheetId,
|
|
76
|
+
startRowIndex: args.dataStartRow,
|
|
77
|
+
endRowIndex: args.dataEndRow,
|
|
78
|
+
startColumnIndex: args.xValuesColumn,
|
|
79
|
+
endColumnIndex: args.xValuesColumn + 1,
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
series: {
|
|
85
|
+
sourceRange: {
|
|
86
|
+
sources: [
|
|
87
|
+
{
|
|
88
|
+
sheetId: args.dataSheetId,
|
|
89
|
+
startRowIndex: args.dataStartRow,
|
|
90
|
+
endRowIndex: args.dataEndRow,
|
|
91
|
+
startColumnIndex: args.yValuesColumn,
|
|
92
|
+
endColumnIndex: args.yValuesColumn + 1,
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
bubbleSizes: {
|
|
98
|
+
sourceRange: {
|
|
99
|
+
sources: [
|
|
100
|
+
{
|
|
101
|
+
sheetId: args.dataSheetId,
|
|
102
|
+
startRowIndex: args.dataStartRow,
|
|
103
|
+
endRowIndex: args.dataEndRow,
|
|
104
|
+
startColumnIndex: args.sizeColumn,
|
|
105
|
+
endColumnIndex: args.sizeColumn + 1,
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
if (args.labelsColumn !== undefined) {
|
|
112
|
+
bubbleChart.bubbleLabels = {
|
|
113
|
+
sourceRange: {
|
|
114
|
+
sources: [
|
|
115
|
+
{
|
|
116
|
+
sheetId: args.dataSheetId,
|
|
117
|
+
startRowIndex: args.dataStartRow,
|
|
118
|
+
endRowIndex: args.dataEndRow,
|
|
119
|
+
startColumnIndex: args.labelsColumn,
|
|
120
|
+
endColumnIndex: args.labelsColumn + 1,
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
const chartSpec = {
|
|
127
|
+
title: args.title || "Bubble Chart",
|
|
128
|
+
bubbleChart,
|
|
129
|
+
};
|
|
130
|
+
const position = {
|
|
131
|
+
overlayPosition: {
|
|
132
|
+
anchorCell: {
|
|
133
|
+
sheetId: args.sheetId,
|
|
134
|
+
rowIndex: args.position?.overlayRow || 0,
|
|
135
|
+
columnIndex: args.position?.overlayColumn || 0,
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
const response = await sheets.spreadsheets.batchUpdate({
|
|
140
|
+
spreadsheetId: args.spreadsheetId,
|
|
141
|
+
requestBody: {
|
|
142
|
+
requests: [
|
|
143
|
+
{
|
|
144
|
+
addChart: {
|
|
145
|
+
chart: {
|
|
146
|
+
spec: chartSpec,
|
|
147
|
+
position,
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
const chartId = response.data.replies?.[0]?.addChart?.chart?.chartId;
|
|
155
|
+
return {
|
|
156
|
+
content: [
|
|
157
|
+
{
|
|
158
|
+
type: "text",
|
|
159
|
+
text: `Successfully created bubble chart. Chart ID: ${chartId}`,
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
isError: false,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
return {
|
|
167
|
+
content: [
|
|
168
|
+
{
|
|
169
|
+
type: "text",
|
|
170
|
+
text: `Error creating bubble chart: ${error.message}`,
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
isError: true,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
export const schema = {
|
|
3
|
+
name: "gsheets_add_candlestick",
|
|
4
|
+
description: "Add a candlestick chart to a spreadsheet (for financial data with open/high/low/close values)",
|
|
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 where the chart will be placed",
|
|
15
|
+
},
|
|
16
|
+
title: {
|
|
17
|
+
type: "string",
|
|
18
|
+
description: "Chart title (optional)",
|
|
19
|
+
},
|
|
20
|
+
dataSheetId: {
|
|
21
|
+
type: "number",
|
|
22
|
+
description: "The sheet ID containing the data",
|
|
23
|
+
},
|
|
24
|
+
dataStartRow: {
|
|
25
|
+
type: "number",
|
|
26
|
+
description: "Starting row of data range (0-based)",
|
|
27
|
+
},
|
|
28
|
+
dataEndRow: {
|
|
29
|
+
type: "number",
|
|
30
|
+
description: "Ending row of data range (exclusive, 0-based)",
|
|
31
|
+
},
|
|
32
|
+
domainColumn: {
|
|
33
|
+
type: "number",
|
|
34
|
+
description: "Column index for domain/labels (0-based)",
|
|
35
|
+
},
|
|
36
|
+
lowColumn: {
|
|
37
|
+
type: "number",
|
|
38
|
+
description: "Column index for low values (0-based)",
|
|
39
|
+
},
|
|
40
|
+
openColumn: {
|
|
41
|
+
type: "number",
|
|
42
|
+
description: "Column index for open values (0-based)",
|
|
43
|
+
},
|
|
44
|
+
closeColumn: {
|
|
45
|
+
type: "number",
|
|
46
|
+
description: "Column index for close values (0-based)",
|
|
47
|
+
},
|
|
48
|
+
highColumn: {
|
|
49
|
+
type: "number",
|
|
50
|
+
description: "Column index for high values (0-based)",
|
|
51
|
+
},
|
|
52
|
+
position: {
|
|
53
|
+
type: "object",
|
|
54
|
+
properties: {
|
|
55
|
+
overlayRow: {
|
|
56
|
+
type: "number",
|
|
57
|
+
description: "Row position for chart overlay (0-based)",
|
|
58
|
+
},
|
|
59
|
+
overlayColumn: {
|
|
60
|
+
type: "number",
|
|
61
|
+
description: "Column position for chart overlay (0-based)",
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
description: "Chart position (optional)",
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
required: ["spreadsheetId", "sheetId", "dataSheetId", "dataStartRow", "dataEndRow", "domainColumn", "lowColumn", "openColumn", "closeColumn", "highColumn"],
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
export async function addCandlestick(args) {
|
|
71
|
+
try {
|
|
72
|
+
const sheets = google.sheets("v4");
|
|
73
|
+
const candlestickChart = {
|
|
74
|
+
domain: {
|
|
75
|
+
sourceRange: {
|
|
76
|
+
sources: [
|
|
77
|
+
{
|
|
78
|
+
sheetId: args.dataSheetId,
|
|
79
|
+
startRowIndex: args.dataStartRow,
|
|
80
|
+
endRowIndex: args.dataEndRow,
|
|
81
|
+
startColumnIndex: args.domainColumn,
|
|
82
|
+
endColumnIndex: args.domainColumn + 1,
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
data: [
|
|
88
|
+
{
|
|
89
|
+
sourceRange: {
|
|
90
|
+
sources: [
|
|
91
|
+
{
|
|
92
|
+
sheetId: args.dataSheetId,
|
|
93
|
+
startRowIndex: args.dataStartRow,
|
|
94
|
+
endRowIndex: args.dataEndRow,
|
|
95
|
+
startColumnIndex: args.lowColumn,
|
|
96
|
+
endColumnIndex: args.lowColumn + 1,
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
sourceRange: {
|
|
103
|
+
sources: [
|
|
104
|
+
{
|
|
105
|
+
sheetId: args.dataSheetId,
|
|
106
|
+
startRowIndex: args.dataStartRow,
|
|
107
|
+
endRowIndex: args.dataEndRow,
|
|
108
|
+
startColumnIndex: args.openColumn,
|
|
109
|
+
endColumnIndex: args.openColumn + 1,
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
sourceRange: {
|
|
116
|
+
sources: [
|
|
117
|
+
{
|
|
118
|
+
sheetId: args.dataSheetId,
|
|
119
|
+
startRowIndex: args.dataStartRow,
|
|
120
|
+
endRowIndex: args.dataEndRow,
|
|
121
|
+
startColumnIndex: args.closeColumn,
|
|
122
|
+
endColumnIndex: args.closeColumn + 1,
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
sourceRange: {
|
|
129
|
+
sources: [
|
|
130
|
+
{
|
|
131
|
+
sheetId: args.dataSheetId,
|
|
132
|
+
startRowIndex: args.dataStartRow,
|
|
133
|
+
endRowIndex: args.dataEndRow,
|
|
134
|
+
startColumnIndex: args.highColumn,
|
|
135
|
+
endColumnIndex: args.highColumn + 1,
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
};
|
|
142
|
+
const chartSpec = {
|
|
143
|
+
title: args.title || "Candlestick Chart",
|
|
144
|
+
candlestickChart,
|
|
145
|
+
};
|
|
146
|
+
const position = {
|
|
147
|
+
overlayPosition: {
|
|
148
|
+
anchorCell: {
|
|
149
|
+
sheetId: args.sheetId,
|
|
150
|
+
rowIndex: args.position?.overlayRow || 0,
|
|
151
|
+
columnIndex: args.position?.overlayColumn || 0,
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
const response = await sheets.spreadsheets.batchUpdate({
|
|
156
|
+
spreadsheetId: args.spreadsheetId,
|
|
157
|
+
requestBody: {
|
|
158
|
+
requests: [
|
|
159
|
+
{
|
|
160
|
+
addChart: {
|
|
161
|
+
chart: {
|
|
162
|
+
spec: chartSpec,
|
|
163
|
+
position,
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
const chartId = response.data.replies?.[0]?.addChart?.chart?.chartId;
|
|
171
|
+
return {
|
|
172
|
+
content: [
|
|
173
|
+
{
|
|
174
|
+
type: "text",
|
|
175
|
+
text: `Successfully created candlestick chart. Chart ID: ${chartId}`,
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
isError: false,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
return {
|
|
183
|
+
content: [
|
|
184
|
+
{
|
|
185
|
+
type: "text",
|
|
186
|
+
text: `Error creating candlestick chart: ${error.message}`,
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
isError: true,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
}
|