@alanse/mcp-server-google-workspace 0.2.1 ā 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 +250 -17
- package/dist/auth.js +6 -0
- package/dist/index.js +1 -1
- package/dist/lib/calendar-helpers.js +197 -0
- package/dist/lib/document-id-resolver.js +76 -0
- package/dist/lib/drive-helpers.js +263 -0
- package/dist/lib/gmail-helpers.js +204 -0
- package/dist/lib/response-formatter.js +82 -0
- package/dist/lib/validation.js +112 -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/docs/basic/gdocs_create.js +37 -0
- package/dist/tools/docs/basic/gdocs_get_metadata.js +45 -0
- package/dist/tools/docs/basic/gdocs_list_documents.js +59 -0
- package/dist/tools/docs/basic/gdocs_read.js +62 -0
- package/dist/tools/docs/content/gdocs_append_text.js +57 -0
- package/dist/tools/docs/content/gdocs_apply_style.js +86 -0
- package/dist/tools/docs/content/gdocs_create_heading.js +89 -0
- package/dist/tools/docs/content/gdocs_create_list.js +86 -0
- package/dist/tools/docs/content/gdocs_delete_text.js +64 -0
- package/dist/tools/docs/content/gdocs_format_text.js +137 -0
- package/dist/tools/docs/content/gdocs_insert_text.js +62 -0
- package/dist/tools/docs/content/gdocs_replace_text.js +64 -0
- package/dist/tools/docs/content/gdocs_set_alignment.js +76 -0
- package/dist/tools/docs/content/gdocs_update_text.js +78 -0
- package/dist/tools/docs/elements/gdocs_batch_update.js +108 -0
- package/dist/tools/docs/elements/gdocs_create_table.js +73 -0
- package/dist/tools/docs/elements/gdocs_export.js +62 -0
- package/dist/tools/docs/elements/gdocs_insert_image.js +96 -0
- package/dist/tools/docs/elements/gdocs_insert_link.js +77 -0
- package/dist/tools/docs/elements/gdocs_insert_page_break.js +55 -0
- package/dist/tools/docs/elements/gdocs_insert_toc.js +71 -0
- package/dist/tools/docs/elements/gdocs_merge_documents.js +104 -0
- package/dist/tools/docs/elements/gdocs_suggest_mode.js +41 -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 +386 -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,80 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
import { formatRevisionList, } from "../../../lib/drive-helpers.js";
|
|
4
|
+
export const schema = {
|
|
5
|
+
name: "drive_list_revisions",
|
|
6
|
+
description: "List all revisions of a file in Google Drive. Shows revision history with timestamps and modification details. Supports pagination.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
fileId: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "ID of the file to list revisions for",
|
|
13
|
+
},
|
|
14
|
+
pageSize: {
|
|
15
|
+
type: "number",
|
|
16
|
+
description: "Maximum number of revisions to return per page (default: 10, max: 1000)",
|
|
17
|
+
optional: true,
|
|
18
|
+
},
|
|
19
|
+
pageToken: {
|
|
20
|
+
type: "string",
|
|
21
|
+
description: "Token for pagination to get the next page of results",
|
|
22
|
+
optional: true,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
required: ["fileId"],
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
export async function listRevisions(args) {
|
|
29
|
+
try {
|
|
30
|
+
const drive = google.drive("v3");
|
|
31
|
+
const { fileId, pageSize = 10, pageToken } = args;
|
|
32
|
+
// Get file metadata
|
|
33
|
+
const fileResponse = await drive.files.get({
|
|
34
|
+
fileId,
|
|
35
|
+
fields: "id, name, mimeType, size, modifiedTime, createdTime",
|
|
36
|
+
});
|
|
37
|
+
const file = fileResponse.data;
|
|
38
|
+
// List revisions
|
|
39
|
+
const revisionsResponse = await drive.revisions.list({
|
|
40
|
+
fileId,
|
|
41
|
+
pageSize: Math.min(pageSize, 1000), // Cap at 1000
|
|
42
|
+
pageToken: pageToken || undefined,
|
|
43
|
+
fields: "revisions(id, modifiedTime, lastModifyingUser, size, keepForever, originalFilename, mimeType), nextPageToken",
|
|
44
|
+
});
|
|
45
|
+
const revisions = revisionsResponse.data.revisions || [];
|
|
46
|
+
const nextPageToken = revisionsResponse.data.nextPageToken;
|
|
47
|
+
// Format output
|
|
48
|
+
let output = `š Revision History for "${file.name}"\n`;
|
|
49
|
+
output += `āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n`;
|
|
50
|
+
output += `Total Revisions: ${revisions.length}\n`;
|
|
51
|
+
if (nextPageToken) {
|
|
52
|
+
output += `(More revisions available - use nextPageToken for pagination)\n`;
|
|
53
|
+
}
|
|
54
|
+
output += `\n${formatRevisionList(revisions)}\n`;
|
|
55
|
+
// Format detailed output for each revision
|
|
56
|
+
let detailedRevisions = revisions.map((revision, index) => ({
|
|
57
|
+
index: index + 1,
|
|
58
|
+
revisionId: revision.id || "",
|
|
59
|
+
modifiedTime: revision.modifiedTime || "Unknown",
|
|
60
|
+
modifiedBy: revision.lastModifyingUser?.displayName || "Unknown",
|
|
61
|
+
modifiedByEmail: revision.lastModifyingUser?.emailAddress || "Unknown",
|
|
62
|
+
size: revision.size ? parseInt(revision.size) : 0,
|
|
63
|
+
mimeType: revision.mimeType || "Unknown",
|
|
64
|
+
keepForever: revision.keepForever || false,
|
|
65
|
+
originalFilename: revision.originalFilename || file.name,
|
|
66
|
+
}));
|
|
67
|
+
return ResponseFormatter.success({
|
|
68
|
+
fileId,
|
|
69
|
+
fileName: file.name,
|
|
70
|
+
totalRevisions: revisions.length,
|
|
71
|
+
revisions: detailedRevisions,
|
|
72
|
+
nextPageToken: nextPageToken || null,
|
|
73
|
+
hasMoreResults: !!nextPageToken,
|
|
74
|
+
pageSize,
|
|
75
|
+
}, output);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
return ResponseFormatter.error(error);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
import { formatFileMetadata } from "../../../lib/drive-helpers.js";
|
|
4
|
+
export const schema = {
|
|
5
|
+
name: "drive_get_metadata",
|
|
6
|
+
description: "Get detailed metadata for a specific file in Google Drive. Returns file ID, name, MIME type, size, created/modified times, sharing settings, and more.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
fileId: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "ID of the file to get metadata for",
|
|
13
|
+
},
|
|
14
|
+
fields: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Comma-separated list of fields to include (default: all common fields)",
|
|
17
|
+
optional: true,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
required: ["fileId"],
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
export async function getMetadata(args) {
|
|
24
|
+
try {
|
|
25
|
+
const drive = google.drive("v3");
|
|
26
|
+
const { fileId, fields } = args;
|
|
27
|
+
const defaultFields = "id, name, mimeType, size, createdTime, modifiedTime, modifiedByMe, owners, lastModifyingUser, shared, sharingUser, permissions, parents, webViewLink, webContentLink, iconLink, thumbnailLink, description, starred, trashed, explicitlyTrashed, properties, appProperties, spaces, version, teamDriveId, driveId, hasAugmentedPermissions, hasVersions, headRevisionId, copyRequiresWriterPermission, writersCanShare, folderColorRgb, originalFilename, fullFileExtension, fileExtension, md5Checksum, sha1Checksum, sha256Checksum";
|
|
28
|
+
const response = await drive.files.get({
|
|
29
|
+
fileId,
|
|
30
|
+
fields: fields || defaultFields,
|
|
31
|
+
supportsAllDrives: true,
|
|
32
|
+
});
|
|
33
|
+
const file = response.data;
|
|
34
|
+
const output = formatFileMetadata(file, true);
|
|
35
|
+
return ResponseFormatter.success({
|
|
36
|
+
fileId: file.id,
|
|
37
|
+
name: file.name,
|
|
38
|
+
mimeType: file.mimeType,
|
|
39
|
+
size: file.size,
|
|
40
|
+
createdTime: file.createdTime,
|
|
41
|
+
modifiedTime: file.modifiedTime,
|
|
42
|
+
webViewLink: file.webViewLink,
|
|
43
|
+
metadata: file,
|
|
44
|
+
}, output);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
return ResponseFormatter.error(error);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
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_files",
|
|
6
|
+
description: "List files in Google Drive. Supports filtering by query, folder, pagination, and sorting. Returns file IDs, names, types, and sizes.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
query: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Search query using Google Drive query syntax (e.g., \"name contains 'report'\")",
|
|
13
|
+
optional: true,
|
|
14
|
+
},
|
|
15
|
+
folderId: {
|
|
16
|
+
type: "string",
|
|
17
|
+
description: "Folder ID to list files from (limits search to specific folder)",
|
|
18
|
+
optional: true,
|
|
19
|
+
},
|
|
20
|
+
pageSize: {
|
|
21
|
+
type: "number",
|
|
22
|
+
description: "Number of files to return per page (max 1000, default 100)",
|
|
23
|
+
optional: true,
|
|
24
|
+
},
|
|
25
|
+
pageToken: {
|
|
26
|
+
type: "string",
|
|
27
|
+
description: "Page token for pagination",
|
|
28
|
+
optional: true,
|
|
29
|
+
},
|
|
30
|
+
orderBy: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description: "Sort order (e.g., 'name', 'modifiedTime desc', 'createdTime')",
|
|
33
|
+
optional: true,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
required: [],
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
export async function listFiles(args) {
|
|
40
|
+
try {
|
|
41
|
+
const drive = google.drive("v3");
|
|
42
|
+
const { query, folderId, pageSize = 100, pageToken, orderBy } = args;
|
|
43
|
+
// Build query
|
|
44
|
+
let q = "trashed = false";
|
|
45
|
+
if (query) {
|
|
46
|
+
q += ` and (${query})`;
|
|
47
|
+
}
|
|
48
|
+
if (folderId) {
|
|
49
|
+
q += ` and '${folderId}' in parents`;
|
|
50
|
+
}
|
|
51
|
+
const response = await drive.files.list({
|
|
52
|
+
q,
|
|
53
|
+
pageSize: Math.min(pageSize, 1000),
|
|
54
|
+
pageToken,
|
|
55
|
+
orderBy: orderBy || "modifiedTime desc",
|
|
56
|
+
fields: "nextPageToken, files(id, name, mimeType, size, modifiedTime, createdTime, webViewLink, parents, iconLink)",
|
|
57
|
+
});
|
|
58
|
+
const files = response.data.files || [];
|
|
59
|
+
const nextPageToken = response.data.nextPageToken;
|
|
60
|
+
const output = formatFileList(files, nextPageToken);
|
|
61
|
+
return ResponseFormatter.success({
|
|
62
|
+
count: files.length,
|
|
63
|
+
files: files.map((f) => ({
|
|
64
|
+
id: f.id,
|
|
65
|
+
name: f.name,
|
|
66
|
+
mimeType: f.mimeType,
|
|
67
|
+
size: f.size,
|
|
68
|
+
modifiedTime: f.modifiedTime,
|
|
69
|
+
})),
|
|
70
|
+
nextPageToken,
|
|
71
|
+
}, output);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
return ResponseFormatter.error(error);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -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
|
+
}
|