@alanse/mcp-server-google-workspace 1.0.0 ā 1.0.2
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 +146 -17
- package/dist/auth.js +5 -0
- package/dist/lib/calendar-helpers.js +197 -0
- package/dist/lib/drive-helpers.js +263 -0
- package/dist/lib/gmail-helpers.js +204 -0
- package/dist/tools/calendar/acl/calendar_acl_insert.js +80 -0
- package/dist/tools/calendar/acl/calendar_acl_list.js +82 -0
- package/dist/tools/calendar/basic/calendar_create_event.js +113 -0
- package/dist/tools/calendar/basic/calendar_delete_event.js +52 -0
- package/dist/tools/calendar/basic/calendar_get_event.js +52 -0
- package/dist/tools/calendar/basic/calendar_list_events.js +86 -0
- package/dist/tools/calendar/basic/calendar_update_event.js +116 -0
- package/dist/tools/calendar/calendarlist/calendar_calendarlist_get.js +73 -0
- package/dist/tools/calendar/calendarlist/calendar_calendarlist_list.js +87 -0
- package/dist/tools/calendar/calendars/calendar_calendars_get.js +52 -0
- package/dist/tools/calendar/calendars/calendar_calendars_insert.js +66 -0
- package/dist/tools/calendar/calendars/calendar_calendars_update.js +85 -0
- package/dist/tools/calendar/colors/calendar_colors_get.js +46 -0
- package/dist/tools/calendar/events_advanced/calendar_events_instances.js +81 -0
- package/dist/tools/calendar/events_advanced/calendar_events_move.js +63 -0
- package/dist/tools/calendar/events_advanced/calendar_events_quickadd.js +52 -0
- package/dist/tools/calendar/freebusy/calendar_freebusy_query.js +69 -0
- package/dist/tools/calendar/settings/calendar_settings_list.js +81 -0
- package/dist/tools/drive/advanced/drive_empty_trash.js +56 -0
- package/dist/tools/drive/advanced/drive_export_file.js +158 -0
- package/dist/tools/drive/advanced/drive_list_revisions.js +80 -0
- package/dist/tools/drive/basic/drive_get_metadata.js +49 -0
- package/dist/tools/drive/basic/drive_list_files.js +76 -0
- package/dist/tools/drive/file/drive_copy_file.js +79 -0
- package/dist/tools/drive/file/drive_create_file.js +72 -0
- package/dist/tools/drive/file/drive_delete_file.js +48 -0
- package/dist/tools/drive/file/drive_move_file.js +79 -0
- package/dist/tools/drive/file/drive_rename_file.js +58 -0
- package/dist/tools/drive/file/drive_update_file.js +106 -0
- package/dist/tools/drive/file/drive_upload_file.js +80 -0
- package/dist/tools/drive/folder/drive_create_folder.js +67 -0
- package/dist/tools/drive/folder/drive_list_folder_contents.js +68 -0
- package/dist/tools/drive/folder/drive_move_to_folder.js +59 -0
- package/dist/tools/drive/permissions/drive_list_permissions.js +115 -0
- package/dist/tools/drive/permissions/drive_remove_permission.js +71 -0
- package/dist/tools/drive/permissions/drive_share_file.js +116 -0
- package/dist/tools/drive/permissions/drive_update_permission.js +79 -0
- package/dist/tools/gmail/basic/gmail_get_message.js +95 -0
- package/dist/tools/gmail/basic/gmail_get_thread.js +46 -0
- package/dist/tools/gmail/basic/gmail_list_labels.js +54 -0
- package/dist/tools/gmail/basic/gmail_search_messages.js +59 -0
- package/dist/tools/gmail/batch/gmail_batch_modify_labels.js +74 -0
- package/dist/tools/gmail/batch/gmail_get_messages_batch.js +120 -0
- package/dist/tools/gmail/batch/gmail_get_threads_batch.js +102 -0
- package/dist/tools/gmail/labels/gmail_manage_label.js +131 -0
- package/dist/tools/gmail/labels/gmail_modify_labels.js +65 -0
- package/dist/tools/gmail/send/gmail_draft_message.js +117 -0
- package/dist/tools/gmail/send/gmail_send_message.js +109 -0
- package/dist/tools/index.js +267 -3
- package/package.json +8 -3
- package/dist/tools/basic/gsheets_add_sheet.js +0 -65
- package/dist/tools/basic/gsheets_copy_sheet.js +0 -56
- package/dist/tools/basic/gsheets_copy_to.js +0 -113
- package/dist/tools/basic/gsheets_create_spreadsheet.js +0 -88
- package/dist/tools/basic/gsheets_delete_columns.js +0 -69
- package/dist/tools/basic/gsheets_delete_rows.js +0 -69
- package/dist/tools/basic/gsheets_delete_sheet.js +0 -56
- package/dist/tools/basic/gsheets_duplicate_sheet.js +0 -72
- package/dist/tools/basic/gsheets_insert_columns.js +0 -69
- package/dist/tools/basic/gsheets_insert_rows.js +0 -69
- package/dist/tools/basic/gsheets_list_sheets.js +0 -53
- package/dist/tools/basic/gsheets_read.js +0 -120
- package/dist/tools/basic/gsheets_rename_sheet.js +0 -64
- package/dist/tools/charts/gsheets_add_bubble.js +0 -176
- package/dist/tools/charts/gsheets_add_candlestick.js +0 -192
- package/dist/tools/charts/gsheets_add_chart.js +0 -162
- package/dist/tools/charts/gsheets_add_combo.js +0 -169
- package/dist/tools/charts/gsheets_add_histogram.js +0 -143
- package/dist/tools/charts/gsheets_add_org_chart.js +0 -160
- package/dist/tools/charts/gsheets_add_treemap.js +0 -177
- package/dist/tools/charts/gsheets_add_waterfall.js +0 -155
- package/dist/tools/charts/gsheets_delete_chart.js +0 -56
- package/dist/tools/charts/gsheets_update_chart.js +0 -118
- package/dist/tools/data/gsheets_append_data.js +0 -68
- package/dist/tools/data/gsheets_batch_clear.js +0 -53
- package/dist/tools/data/gsheets_batch_update.js +0 -81
- package/dist/tools/data/gsheets_clear_data.js +0 -53
- package/dist/tools/data/gsheets_create_filter.js +0 -81
- package/dist/tools/data/gsheets_find_replace.js +0 -124
- package/dist/tools/data/gsheets_set_data_validation.js +0 -153
- package/dist/tools/data/gsheets_sort_range.js +0 -102
- package/dist/tools/data/gsheets_update_cell.js +0 -44
- package/dist/tools/formatting/gsheets_auto_resize.js +0 -75
- package/dist/tools/formatting/gsheets_format_cells.js +0 -161
- package/dist/tools/formatting/gsheets_freeze_columns.js +0 -67
- package/dist/tools/formatting/gsheets_freeze_rows.js +0 -67
- package/dist/tools/formatting/gsheets_merge_cells.js +0 -85
- package/dist/tools/formatting/gsheets_set_number_format.js +0 -116
- package/dist/tools/formatting/gsheets_unmerge_cells.js +0 -79
- package/dist/tools/formatting/gsheets_update_borders.js +0 -212
- package/dist/tools/gdrive/gdrive_read_file.js +0 -77
- package/dist/tools/gdrive/gdrive_search.js +0 -71
- package/dist/tools/gdrive_read_file.js +0 -77
- package/dist/tools/gdrive_search.js +0 -71
- package/dist/tools/gsheets_add_bubble.js +0 -176
- package/dist/tools/gsheets_add_candlestick.js +0 -192
- package/dist/tools/gsheets_add_chart.js +0 -162
- package/dist/tools/gsheets_add_combo.js +0 -169
- package/dist/tools/gsheets_add_conditional_format.js +0 -175
- package/dist/tools/gsheets_add_histogram.js +0 -143
- package/dist/tools/gsheets_add_named_range.js +0 -87
- package/dist/tools/gsheets_add_org_chart.js +0 -160
- package/dist/tools/gsheets_add_protected_range.js +0 -127
- package/dist/tools/gsheets_add_sheet.js +0 -65
- package/dist/tools/gsheets_add_treemap.js +0 -177
- package/dist/tools/gsheets_add_waterfall.js +0 -155
- package/dist/tools/gsheets_append_data.js +0 -68
- package/dist/tools/gsheets_auto_resize.js +0 -75
- package/dist/tools/gsheets_batch_clear.js +0 -53
- package/dist/tools/gsheets_batch_update.js +0 -81
- package/dist/tools/gsheets_clear_data.js +0 -53
- package/dist/tools/gsheets_copy_sheet.js +0 -56
- package/dist/tools/gsheets_copy_to.js +0 -113
- package/dist/tools/gsheets_create_filter.js +0 -81
- package/dist/tools/gsheets_create_spreadsheet.js +0 -88
- package/dist/tools/gsheets_delete_chart.js +0 -56
- package/dist/tools/gsheets_delete_columns.js +0 -69
- package/dist/tools/gsheets_delete_named_range.js +0 -56
- package/dist/tools/gsheets_delete_protected_range.js +0 -56
- package/dist/tools/gsheets_delete_rows.js +0 -69
- package/dist/tools/gsheets_delete_sheet.js +0 -56
- package/dist/tools/gsheets_duplicate_sheet.js +0 -72
- package/dist/tools/gsheets_find_replace.js +0 -124
- package/dist/tools/gsheets_format_cells.js +0 -161
- package/dist/tools/gsheets_freeze_columns.js +0 -67
- package/dist/tools/gsheets_freeze_rows.js +0 -67
- package/dist/tools/gsheets_insert_columns.js +0 -69
- package/dist/tools/gsheets_insert_rows.js +0 -69
- package/dist/tools/gsheets_list_sheets.js +0 -53
- package/dist/tools/gsheets_merge_cells.js +0 -85
- package/dist/tools/gsheets_read.js +0 -120
- package/dist/tools/gsheets_rename_sheet.js +0 -64
- package/dist/tools/gsheets_set_data_validation.js +0 -153
- package/dist/tools/gsheets_set_number_format.js +0 -116
- package/dist/tools/gsheets_sort_range.js +0 -102
- package/dist/tools/gsheets_unmerge_cells.js +0 -79
- package/dist/tools/gsheets_update_borders.js +0 -212
- package/dist/tools/gsheets_update_cell.js +0 -44
- package/dist/tools/gsheets_update_chart.js +0 -118
- package/dist/tools/gsheets_update_named_range.js +0 -112
- package/dist/tools/gsheets_update_protected_range.js +0 -110
- package/dist/tools/protection/gsheets_add_conditional_format.js +0 -175
- package/dist/tools/protection/gsheets_add_named_range.js +0 -87
- package/dist/tools/protection/gsheets_add_protected_range.js +0 -127
- package/dist/tools/protection/gsheets_delete_named_range.js +0 -56
- package/dist/tools/protection/gsheets_delete_protected_range.js +0 -56
- package/dist/tools/protection/gsheets_update_named_range.js +0 -112
- package/dist/tools/protection/gsheets_update_protected_range.js +0 -110
- /package/dist/tools/drive/{drive_read_file.js ā basic/drive_read_file.js} +0 -0
- /package/dist/tools/drive/{drive_search.js ā basic/drive_search.js} +0 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
import { formatFileMetadata, generateDriveWebUrl, } from "../../../lib/drive-helpers.js";
|
|
4
|
+
export const schema = {
|
|
5
|
+
name: "drive_copy_file",
|
|
6
|
+
description: "Copy a file in Google Drive. Creates a duplicate of the file with optional new name and parent folder(s). Requires file ID.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
fileId: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "ID of the file to copy",
|
|
13
|
+
},
|
|
14
|
+
name: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Name for the copied file (optional, defaults to 'Copy of [original name]')",
|
|
17
|
+
optional: true,
|
|
18
|
+
},
|
|
19
|
+
parents: {
|
|
20
|
+
type: "array",
|
|
21
|
+
items: {
|
|
22
|
+
type: "string",
|
|
23
|
+
},
|
|
24
|
+
description: "Parent folder ID(s) for the copied file (optional, defaults to same location as original)",
|
|
25
|
+
optional: true,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
required: ["fileId"],
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
export async function copyFile(args) {
|
|
32
|
+
try {
|
|
33
|
+
const drive = google.drive("v3");
|
|
34
|
+
const { fileId, name, parents } = args;
|
|
35
|
+
// Get original file metadata
|
|
36
|
+
const originalFile = await drive.files.get({
|
|
37
|
+
fileId,
|
|
38
|
+
fields: "id, name, mimeType",
|
|
39
|
+
});
|
|
40
|
+
const originalName = originalFile.data.name || "Unknown";
|
|
41
|
+
// Create copy metadata
|
|
42
|
+
const copyMetadata = {};
|
|
43
|
+
if (name) {
|
|
44
|
+
copyMetadata.name = name;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
copyMetadata.name = `Copy of ${originalName}`;
|
|
48
|
+
}
|
|
49
|
+
if (parents && parents.length > 0) {
|
|
50
|
+
copyMetadata.parents = parents;
|
|
51
|
+
}
|
|
52
|
+
// Copy the file
|
|
53
|
+
const response = await drive.files.copy({
|
|
54
|
+
fileId,
|
|
55
|
+
requestBody: copyMetadata,
|
|
56
|
+
fields: "id, name, mimeType, size, modifiedTime, webViewLink, parents",
|
|
57
|
+
});
|
|
58
|
+
const copiedFile = response.data;
|
|
59
|
+
const copiedFileId = copiedFile.id || "";
|
|
60
|
+
let output = `ā
File copied successfully!\n\n`;
|
|
61
|
+
output += `š Original: ${originalName} (${fileId})\n`;
|
|
62
|
+
output += `š Copy: ${copiedFile.name} (${copiedFileId})\n\n`;
|
|
63
|
+
output += formatFileMetadata(copiedFile, true);
|
|
64
|
+
output += `\nš Web URL: ${generateDriveWebUrl(copiedFileId)}\n`;
|
|
65
|
+
return ResponseFormatter.success({
|
|
66
|
+
originalFileId: fileId,
|
|
67
|
+
originalName,
|
|
68
|
+
copiedFileId,
|
|
69
|
+
copiedName: copiedFile.name,
|
|
70
|
+
mimeType: copiedFile.mimeType,
|
|
71
|
+
size: copiedFile.size,
|
|
72
|
+
webViewLink: copiedFile.webViewLink,
|
|
73
|
+
parents: copiedFile.parents,
|
|
74
|
+
}, output);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
return ResponseFormatter.error(error);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
import { formatFileMetadata, generateDriveWebUrl, } from "../../../lib/drive-helpers.js";
|
|
4
|
+
export const schema = {
|
|
5
|
+
name: "drive_create_file",
|
|
6
|
+
description: "Create an empty file or Google Workspace document in Google Drive. Creates a file with metadata only (no content). Use drive_upload_file if you need to include content.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
name: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "File name",
|
|
13
|
+
},
|
|
14
|
+
mimeType: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "MIME type of the file (e.g., 'application/vnd.google-apps.document' for Google Docs, 'application/vnd.google-apps.spreadsheet' for Sheets)",
|
|
17
|
+
},
|
|
18
|
+
parents: {
|
|
19
|
+
type: "array",
|
|
20
|
+
items: {
|
|
21
|
+
type: "string",
|
|
22
|
+
},
|
|
23
|
+
description: "Parent folder ID(s) where the file should be created",
|
|
24
|
+
optional: true,
|
|
25
|
+
},
|
|
26
|
+
description: {
|
|
27
|
+
type: "string",
|
|
28
|
+
description: "File description",
|
|
29
|
+
optional: true,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
required: ["name", "mimeType"],
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
export async function createFile(args) {
|
|
36
|
+
try {
|
|
37
|
+
const drive = google.drive("v3");
|
|
38
|
+
const { name, mimeType, parents, description } = args;
|
|
39
|
+
// Create file metadata
|
|
40
|
+
const fileMetadata = {
|
|
41
|
+
name,
|
|
42
|
+
mimeType,
|
|
43
|
+
};
|
|
44
|
+
if (parents && parents.length > 0) {
|
|
45
|
+
fileMetadata.parents = parents;
|
|
46
|
+
}
|
|
47
|
+
if (description) {
|
|
48
|
+
fileMetadata.description = description;
|
|
49
|
+
}
|
|
50
|
+
// Create empty file
|
|
51
|
+
const response = await drive.files.create({
|
|
52
|
+
requestBody: fileMetadata,
|
|
53
|
+
fields: "id, name, mimeType, size, modifiedTime, webViewLink, parents",
|
|
54
|
+
});
|
|
55
|
+
const file = response.data;
|
|
56
|
+
const fileId = file.id || "";
|
|
57
|
+
let output = `ā
File created successfully!\n\n`;
|
|
58
|
+
output += formatFileMetadata(file, true);
|
|
59
|
+
output += `\nš Web URL: ${generateDriveWebUrl(fileId)}\n`;
|
|
60
|
+
return ResponseFormatter.success({
|
|
61
|
+
fileId,
|
|
62
|
+
name: file.name,
|
|
63
|
+
mimeType: file.mimeType,
|
|
64
|
+
size: file.size,
|
|
65
|
+
webViewLink: file.webViewLink,
|
|
66
|
+
parents: file.parents,
|
|
67
|
+
}, output);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
return ResponseFormatter.error(error);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
export const schema = {
|
|
4
|
+
name: "drive_delete_file",
|
|
5
|
+
description: "Delete a file from Google Drive. Moves the file to trash. To permanently delete, use drive_empty_trash. Requires file ID.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: "object",
|
|
8
|
+
properties: {
|
|
9
|
+
fileId: {
|
|
10
|
+
type: "string",
|
|
11
|
+
description: "ID of the file to delete",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
required: ["fileId"],
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
export async function deleteFile(args) {
|
|
18
|
+
try {
|
|
19
|
+
const drive = google.drive("v3");
|
|
20
|
+
const { fileId } = args;
|
|
21
|
+
// Get file metadata before deleting
|
|
22
|
+
const fileResponse = await drive.files.get({
|
|
23
|
+
fileId,
|
|
24
|
+
fields: "id, name, mimeType",
|
|
25
|
+
});
|
|
26
|
+
const fileName = fileResponse.data.name || "Unknown";
|
|
27
|
+
const mimeType = fileResponse.data.mimeType || "unknown";
|
|
28
|
+
// Delete the file (moves to trash)
|
|
29
|
+
await drive.files.delete({
|
|
30
|
+
fileId,
|
|
31
|
+
});
|
|
32
|
+
let output = `ā
File deleted successfully!\n\n`;
|
|
33
|
+
output += `š File Details:\n`;
|
|
34
|
+
output += ` Name: ${fileName}\n`;
|
|
35
|
+
output += ` ID: ${fileId}\n`;
|
|
36
|
+
output += ` MIME Type: ${mimeType}\n`;
|
|
37
|
+
output += `\nNote: File moved to trash. Use drive_empty_trash to permanently delete.`;
|
|
38
|
+
return ResponseFormatter.success({
|
|
39
|
+
fileId,
|
|
40
|
+
name: fileName,
|
|
41
|
+
mimeType,
|
|
42
|
+
deleted: true,
|
|
43
|
+
}, output);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
return ResponseFormatter.error(error);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
import { formatFileMetadata, generateDriveWebUrl, } from "../../../lib/drive-helpers.js";
|
|
4
|
+
export const schema = {
|
|
5
|
+
name: "drive_move_file",
|
|
6
|
+
description: "Move a file to a different folder in Google Drive. Updates the file's parent folder(s). Can optionally remove from existing parent folders. Requires file ID and new parent folder ID(s).",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
fileId: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "ID of the file to move",
|
|
13
|
+
},
|
|
14
|
+
newParents: {
|
|
15
|
+
type: "array",
|
|
16
|
+
items: {
|
|
17
|
+
type: "string",
|
|
18
|
+
},
|
|
19
|
+
description: "New parent folder ID(s) to move the file to",
|
|
20
|
+
},
|
|
21
|
+
removeParents: {
|
|
22
|
+
type: "array",
|
|
23
|
+
items: {
|
|
24
|
+
type: "string",
|
|
25
|
+
},
|
|
26
|
+
description: "Parent folder ID(s) to remove the file from (optional, if not specified, removes from all current parents)",
|
|
27
|
+
optional: true,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
required: ["fileId", "newParents"],
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
export async function moveFile(args) {
|
|
34
|
+
try {
|
|
35
|
+
const drive = google.drive("v3");
|
|
36
|
+
const { fileId, newParents, removeParents } = args;
|
|
37
|
+
// Get current file metadata
|
|
38
|
+
const fileResponse = await drive.files.get({
|
|
39
|
+
fileId,
|
|
40
|
+
fields: "id, name, parents",
|
|
41
|
+
});
|
|
42
|
+
const fileName = fileResponse.data.name || "Unknown";
|
|
43
|
+
const currentParents = fileResponse.data.parents || [];
|
|
44
|
+
// Determine which parents to remove
|
|
45
|
+
let parentsToRemove;
|
|
46
|
+
if (removeParents && removeParents.length > 0) {
|
|
47
|
+
parentsToRemove = removeParents;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
// Remove from all current parents if not specified
|
|
51
|
+
parentsToRemove = currentParents;
|
|
52
|
+
}
|
|
53
|
+
// Move the file
|
|
54
|
+
const response = await drive.files.update({
|
|
55
|
+
fileId,
|
|
56
|
+
addParents: newParents.join(","),
|
|
57
|
+
removeParents: parentsToRemove.join(","),
|
|
58
|
+
fields: "id, name, mimeType, size, modifiedTime, webViewLink, parents",
|
|
59
|
+
});
|
|
60
|
+
const movedFile = response.data;
|
|
61
|
+
let output = `ā
File moved successfully!\n\n`;
|
|
62
|
+
output += `š File: ${fileName}\n`;
|
|
63
|
+
output += ` From: ${currentParents.join(", ") || "Root"}\n`;
|
|
64
|
+
output += ` To: ${newParents.join(", ")}\n\n`;
|
|
65
|
+
output += formatFileMetadata(movedFile, true);
|
|
66
|
+
output += `\nš Web URL: ${generateDriveWebUrl(fileId)}\n`;
|
|
67
|
+
return ResponseFormatter.success({
|
|
68
|
+
fileId,
|
|
69
|
+
name: movedFile.name,
|
|
70
|
+
previousParents: currentParents,
|
|
71
|
+
newParents: movedFile.parents,
|
|
72
|
+
mimeType: movedFile.mimeType,
|
|
73
|
+
webViewLink: movedFile.webViewLink,
|
|
74
|
+
}, output);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
return ResponseFormatter.error(error);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
import { formatFileMetadata, generateDriveWebUrl, } from "../../../lib/drive-helpers.js";
|
|
4
|
+
export const schema = {
|
|
5
|
+
name: "drive_rename_file",
|
|
6
|
+
description: "Rename a file in Google Drive. Updates the file's name while keeping all other properties unchanged. Requires file ID and new name.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
fileId: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "ID of the file to rename",
|
|
13
|
+
},
|
|
14
|
+
newName: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "New name for the file",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
required: ["fileId", "newName"],
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
export async function renameFile(args) {
|
|
23
|
+
try {
|
|
24
|
+
const drive = google.drive("v3");
|
|
25
|
+
const { fileId, newName } = args;
|
|
26
|
+
// Get current file metadata
|
|
27
|
+
const fileResponse = await drive.files.get({
|
|
28
|
+
fileId,
|
|
29
|
+
fields: "id, name, mimeType",
|
|
30
|
+
});
|
|
31
|
+
const oldName = fileResponse.data.name || "Unknown";
|
|
32
|
+
// Rename the file
|
|
33
|
+
const response = await drive.files.update({
|
|
34
|
+
fileId,
|
|
35
|
+
requestBody: {
|
|
36
|
+
name: newName,
|
|
37
|
+
},
|
|
38
|
+
fields: "id, name, mimeType, size, modifiedTime, webViewLink, parents",
|
|
39
|
+
});
|
|
40
|
+
const renamedFile = response.data;
|
|
41
|
+
let output = `ā
File renamed successfully!\n\n`;
|
|
42
|
+
output += `š Old Name: ${oldName}\n`;
|
|
43
|
+
output += `š New Name: ${newName}\n\n`;
|
|
44
|
+
output += formatFileMetadata(renamedFile, true);
|
|
45
|
+
output += `\nš Web URL: ${generateDriveWebUrl(fileId)}\n`;
|
|
46
|
+
return ResponseFormatter.success({
|
|
47
|
+
fileId,
|
|
48
|
+
oldName,
|
|
49
|
+
newName: renamedFile.name,
|
|
50
|
+
mimeType: renamedFile.mimeType,
|
|
51
|
+
size: renamedFile.size,
|
|
52
|
+
webViewLink: renamedFile.webViewLink,
|
|
53
|
+
}, output);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
return ResponseFormatter.error(error);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
import { formatFileMetadata, generateDriveWebUrl, } from "../../../lib/drive-helpers.js";
|
|
4
|
+
export const schema = {
|
|
5
|
+
name: "drive_update_file",
|
|
6
|
+
description: "Update a file's metadata and/or content in Google Drive. Can update name, description, MIME type, and content. All update fields are optional - only provide the fields you want to update.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
fileId: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "ID of the file to update",
|
|
13
|
+
},
|
|
14
|
+
name: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "New file name (optional)",
|
|
17
|
+
optional: true,
|
|
18
|
+
},
|
|
19
|
+
description: {
|
|
20
|
+
type: "string",
|
|
21
|
+
description: "New file description (optional)",
|
|
22
|
+
optional: true,
|
|
23
|
+
},
|
|
24
|
+
mimeType: {
|
|
25
|
+
type: "string",
|
|
26
|
+
description: "New MIME type (optional)",
|
|
27
|
+
optional: true,
|
|
28
|
+
},
|
|
29
|
+
content: {
|
|
30
|
+
type: "string",
|
|
31
|
+
description: "New file content (base64 encoded for binary files, plain text for text files) (optional)",
|
|
32
|
+
optional: true,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
required: ["fileId"],
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
export async function updateFile(args) {
|
|
39
|
+
try {
|
|
40
|
+
const drive = google.drive("v3");
|
|
41
|
+
const { fileId, name, description, mimeType, content } = args;
|
|
42
|
+
// Get current file metadata
|
|
43
|
+
const fileResponse = await drive.files.get({
|
|
44
|
+
fileId,
|
|
45
|
+
fields: "id, name, description, mimeType",
|
|
46
|
+
});
|
|
47
|
+
const oldName = fileResponse.data.name || "Unknown";
|
|
48
|
+
const oldDescription = fileResponse.data.description || "";
|
|
49
|
+
const oldMimeType = fileResponse.data.mimeType || "unknown";
|
|
50
|
+
// Build update metadata
|
|
51
|
+
const updateMetadata = {};
|
|
52
|
+
const changes = [];
|
|
53
|
+
if (name !== undefined) {
|
|
54
|
+
updateMetadata.name = name;
|
|
55
|
+
changes.push(`Name: ${oldName} ā ${name}`);
|
|
56
|
+
}
|
|
57
|
+
if (description !== undefined) {
|
|
58
|
+
updateMetadata.description = description;
|
|
59
|
+
changes.push(`Description: ${oldDescription || "(empty)"} ā ${description}`);
|
|
60
|
+
}
|
|
61
|
+
if (mimeType !== undefined) {
|
|
62
|
+
updateMetadata.mimeType = mimeType;
|
|
63
|
+
changes.push(`MIME Type: ${oldMimeType} ā ${mimeType}`);
|
|
64
|
+
}
|
|
65
|
+
// Update the file
|
|
66
|
+
const updateParams = {
|
|
67
|
+
fileId,
|
|
68
|
+
fields: "id, name, description, mimeType, size, modifiedTime, webViewLink, parents",
|
|
69
|
+
};
|
|
70
|
+
if (Object.keys(updateMetadata).length > 0) {
|
|
71
|
+
updateParams.requestBody = updateMetadata;
|
|
72
|
+
}
|
|
73
|
+
if (content !== undefined) {
|
|
74
|
+
updateParams.media = {
|
|
75
|
+
mimeType: mimeType || oldMimeType,
|
|
76
|
+
body: content,
|
|
77
|
+
};
|
|
78
|
+
changes.push("Content: Updated");
|
|
79
|
+
}
|
|
80
|
+
const response = await drive.files.update(updateParams);
|
|
81
|
+
const updatedFile = response.data;
|
|
82
|
+
let output = `ā
File updated successfully!\n\n`;
|
|
83
|
+
if (changes.length > 0) {
|
|
84
|
+
output += `š Changes:\n`;
|
|
85
|
+
changes.forEach((change) => {
|
|
86
|
+
output += ` ⢠${change}\n`;
|
|
87
|
+
});
|
|
88
|
+
output += `\n`;
|
|
89
|
+
}
|
|
90
|
+
output += formatFileMetadata(updatedFile, true);
|
|
91
|
+
output += `\nš Web URL: ${generateDriveWebUrl(fileId)}\n`;
|
|
92
|
+
return ResponseFormatter.success({
|
|
93
|
+
fileId,
|
|
94
|
+
name: updatedFile.name,
|
|
95
|
+
description: updatedFile.description,
|
|
96
|
+
mimeType: updatedFile.mimeType,
|
|
97
|
+
size: updatedFile.size,
|
|
98
|
+
modifiedTime: updatedFile.modifiedTime,
|
|
99
|
+
webViewLink: updatedFile.webViewLink,
|
|
100
|
+
changes,
|
|
101
|
+
}, output);
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
return ResponseFormatter.error(error);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
import { formatFileMetadata, generateDriveWebUrl, } from "../../../lib/drive-helpers.js";
|
|
4
|
+
export const schema = {
|
|
5
|
+
name: "drive_upload_file",
|
|
6
|
+
description: "Upload a file to Google Drive with content. Creates a new file with the specified name, MIME type, and content. Optionally specify parent folder(s) and description.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
name: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "File name",
|
|
13
|
+
},
|
|
14
|
+
mimeType: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "MIME type of the file (e.g., 'text/plain', 'application/json', 'image/png')",
|
|
17
|
+
},
|
|
18
|
+
content: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description: "File content (base64 encoded for binary files, plain text for text files)",
|
|
21
|
+
},
|
|
22
|
+
parents: {
|
|
23
|
+
type: "array",
|
|
24
|
+
items: {
|
|
25
|
+
type: "string",
|
|
26
|
+
},
|
|
27
|
+
description: "Parent folder ID(s) where the file should be created",
|
|
28
|
+
optional: true,
|
|
29
|
+
},
|
|
30
|
+
description: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description: "File description",
|
|
33
|
+
optional: true,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
required: ["name", "mimeType", "content"],
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
export async function uploadFile(args) {
|
|
40
|
+
try {
|
|
41
|
+
const drive = google.drive("v3");
|
|
42
|
+
const { name, mimeType, content, parents, description } = args;
|
|
43
|
+
// Create file metadata
|
|
44
|
+
const fileMetadata = {
|
|
45
|
+
name,
|
|
46
|
+
mimeType,
|
|
47
|
+
};
|
|
48
|
+
if (parents && parents.length > 0) {
|
|
49
|
+
fileMetadata.parents = parents;
|
|
50
|
+
}
|
|
51
|
+
if (description) {
|
|
52
|
+
fileMetadata.description = description;
|
|
53
|
+
}
|
|
54
|
+
// Upload file with content
|
|
55
|
+
const response = await drive.files.create({
|
|
56
|
+
requestBody: fileMetadata,
|
|
57
|
+
media: {
|
|
58
|
+
mimeType,
|
|
59
|
+
body: content,
|
|
60
|
+
},
|
|
61
|
+
fields: "id, name, mimeType, size, modifiedTime, webViewLink, parents",
|
|
62
|
+
});
|
|
63
|
+
const file = response.data;
|
|
64
|
+
const fileId = file.id || "";
|
|
65
|
+
let output = `ā
File uploaded successfully!\n\n`;
|
|
66
|
+
output += formatFileMetadata(file, true);
|
|
67
|
+
output += `\nš Web URL: ${generateDriveWebUrl(fileId)}\n`;
|
|
68
|
+
return ResponseFormatter.success({
|
|
69
|
+
fileId,
|
|
70
|
+
name: file.name,
|
|
71
|
+
mimeType: file.mimeType,
|
|
72
|
+
size: file.size,
|
|
73
|
+
webViewLink: file.webViewLink,
|
|
74
|
+
parents: file.parents,
|
|
75
|
+
}, output);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
return ResponseFormatter.error(error);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
import { formatFileMetadata, generateFolderWebUrl, FOLDER_MIME_TYPE, } from "../../../lib/drive-helpers.js";
|
|
4
|
+
export const schema = {
|
|
5
|
+
name: "drive_create_folder",
|
|
6
|
+
description: "Create a new folder in Google Drive. Can optionally place the folder inside a parent folder. Returns folder ID and metadata.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
name: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Folder name",
|
|
13
|
+
},
|
|
14
|
+
parents: {
|
|
15
|
+
type: "array",
|
|
16
|
+
items: {
|
|
17
|
+
type: "string",
|
|
18
|
+
},
|
|
19
|
+
description: "Parent folder ID(s) where the folder should be created (optional)",
|
|
20
|
+
optional: true,
|
|
21
|
+
},
|
|
22
|
+
description: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: "Folder description",
|
|
25
|
+
optional: true,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
required: ["name"],
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
export async function createFolder(args) {
|
|
32
|
+
try {
|
|
33
|
+
const drive = google.drive("v3");
|
|
34
|
+
const { name, parents, description } = args;
|
|
35
|
+
// Create folder metadata
|
|
36
|
+
const folderMetadata = {
|
|
37
|
+
name,
|
|
38
|
+
mimeType: FOLDER_MIME_TYPE,
|
|
39
|
+
};
|
|
40
|
+
if (parents && parents.length > 0) {
|
|
41
|
+
folderMetadata.parents = parents;
|
|
42
|
+
}
|
|
43
|
+
if (description) {
|
|
44
|
+
folderMetadata.description = description;
|
|
45
|
+
}
|
|
46
|
+
// Create folder
|
|
47
|
+
const response = await drive.files.create({
|
|
48
|
+
requestBody: folderMetadata,
|
|
49
|
+
fields: "id, name, mimeType, modifiedTime, webViewLink, parents",
|
|
50
|
+
});
|
|
51
|
+
const folder = response.data;
|
|
52
|
+
const folderId = folder.id || "";
|
|
53
|
+
let output = `ā
Folder created successfully!\n\n`;
|
|
54
|
+
output += formatFileMetadata(folder, true);
|
|
55
|
+
output += `\nš Web URL: ${generateFolderWebUrl(folderId)}\n`;
|
|
56
|
+
return ResponseFormatter.success({
|
|
57
|
+
folderId,
|
|
58
|
+
name: folder.name,
|
|
59
|
+
mimeType: folder.mimeType,
|
|
60
|
+
webViewLink: folder.webViewLink,
|
|
61
|
+
parents: folder.parents,
|
|
62
|
+
}, output);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
return ResponseFormatter.error(error);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
import { formatFileList } from "../../../lib/drive-helpers.js";
|
|
4
|
+
export const schema = {
|
|
5
|
+
name: "drive_list_folder_contents",
|
|
6
|
+
description: "List all files and folders inside a specific folder in Google Drive. Supports pagination and sorting. Returns file IDs, names, types, and sizes.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
folderId: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "ID of the folder to list contents from",
|
|
13
|
+
},
|
|
14
|
+
pageSize: {
|
|
15
|
+
type: "number",
|
|
16
|
+
description: "Number of items to return per page (max 1000, default 100)",
|
|
17
|
+
optional: true,
|
|
18
|
+
},
|
|
19
|
+
pageToken: {
|
|
20
|
+
type: "string",
|
|
21
|
+
description: "Page token for pagination",
|
|
22
|
+
optional: true,
|
|
23
|
+
},
|
|
24
|
+
orderBy: {
|
|
25
|
+
type: "string",
|
|
26
|
+
description: "Sort order (e.g., 'name', 'modifiedTime desc', 'createdTime')",
|
|
27
|
+
optional: true,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
required: ["folderId"],
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
export async function listFolderContents(args) {
|
|
34
|
+
try {
|
|
35
|
+
const drive = google.drive("v3");
|
|
36
|
+
const { folderId, pageSize = 100, pageToken, orderBy } = args;
|
|
37
|
+
// Build query for folder contents
|
|
38
|
+
const q = `'${folderId}' in parents and trashed = false`;
|
|
39
|
+
const response = await drive.files.list({
|
|
40
|
+
q,
|
|
41
|
+
pageSize: Math.min(pageSize, 1000),
|
|
42
|
+
pageToken,
|
|
43
|
+
orderBy: orderBy || "modifiedTime desc",
|
|
44
|
+
fields: "nextPageToken, files(id, name, mimeType, size, modifiedTime, createdTime, webViewLink, parents, iconLink)",
|
|
45
|
+
});
|
|
46
|
+
const files = response.data.files || [];
|
|
47
|
+
const nextPageToken = response.data.nextPageToken;
|
|
48
|
+
let output = `š Folder Contents\n`;
|
|
49
|
+
output += `āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n`;
|
|
50
|
+
output += `Folder ID: ${folderId}\n\n`;
|
|
51
|
+
output += formatFileList(files, nextPageToken);
|
|
52
|
+
return ResponseFormatter.success({
|
|
53
|
+
folderId,
|
|
54
|
+
count: files.length,
|
|
55
|
+
files: files.map((f) => ({
|
|
56
|
+
id: f.id,
|
|
57
|
+
name: f.name,
|
|
58
|
+
mimeType: f.mimeType,
|
|
59
|
+
size: f.size,
|
|
60
|
+
modifiedTime: f.modifiedTime,
|
|
61
|
+
})),
|
|
62
|
+
nextPageToken,
|
|
63
|
+
}, output);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
return ResponseFormatter.error(error);
|
|
67
|
+
}
|
|
68
|
+
}
|