google-tools-mcp 1.2.12 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +537 -276
  3. package/dist/cachedToolsList.js +52 -52
  4. package/dist/googleDocsApiHelpers.js +76 -12
  5. package/dist/helpers.js +572 -252
  6. package/dist/httpAuth.js +296 -0
  7. package/dist/index.js +162 -11
  8. package/dist/logger.js +87 -87
  9. package/dist/markdown-transformer/docsToMarkdown.js +128 -0
  10. package/dist/markdown-transformer/index.js +17 -7
  11. package/dist/markdown-transformer/markdownToDocs.js +185 -27
  12. package/dist/readTracker.js +136 -17
  13. package/dist/sessionContext.js +37 -0
  14. package/dist/setup.js +187 -9
  15. package/dist/tools/calendar/getBusy.js +64 -64
  16. package/dist/tools/calendar/getEvents.js +141 -141
  17. package/dist/tools/calendar/getFree.js +225 -225
  18. package/dist/tools/calendar/index.js +19 -19
  19. package/dist/tools/calendar/listCalendars.js +38 -38
  20. package/dist/tools/calendar/listRecurringInstances.js +83 -83
  21. package/dist/tools/calendar/manageCalendar.js +121 -121
  22. package/dist/tools/calendar/manageEvent.js +258 -258
  23. package/dist/tools/calendar/moveEvent.js +66 -66
  24. package/dist/tools/docs/addTab.js +10 -12
  25. package/dist/tools/docs/appendToGoogleDoc.js +9 -4
  26. package/dist/tools/docs/deleteRange.js +9 -4
  27. package/dist/tools/docs/findAndReplace.js +9 -4
  28. package/dist/tools/docs/formatting/applyParagraphStyle.js +4 -1
  29. package/dist/tools/docs/formatting/getFormatting.js +171 -171
  30. package/dist/tools/docs/insertImage.js +15 -2
  31. package/dist/tools/docs/insertPageBreak.js +4 -1
  32. package/dist/tools/docs/insertTable.js +4 -1
  33. package/dist/tools/docs/insertTableWithData.js +4 -1
  34. package/dist/tools/docs/modifyText.js +14 -4
  35. package/dist/tools/docs/modifyText.test.js +84 -84
  36. package/dist/tools/docs/readGoogleDoc.js +71 -11
  37. package/dist/tools/docs/renameTab.js +12 -14
  38. package/dist/tools/drafts.js +165 -165
  39. package/dist/tools/drive/createDocument.js +12 -0
  40. package/dist/tools/drive/downloadFile.js +268 -268
  41. package/dist/tools/drive/getFileInfo.js +48 -48
  42. package/dist/tools/drive/getFilePath.js +50 -50
  43. package/dist/tools/drive/listDriveFiles.js +112 -112
  44. package/dist/tools/drive/listSharedDrives.js +52 -52
  45. package/dist/tools/drive/listSharedWithMe.js +97 -97
  46. package/dist/tools/drive/uploadFile.js +111 -111
  47. package/dist/tools/extras/index.js +9 -9
  48. package/dist/tools/extras/readDriveFile.js +197 -196
  49. package/dist/tools/extras/readFile.js +84 -84
  50. package/dist/tools/extras/searchFileContents.js +81 -81
  51. package/dist/tools/forms/batchUpdateForm.js +81 -81
  52. package/dist/tools/forms/createForm.js +54 -54
  53. package/dist/tools/forms/getForm.js +118 -118
  54. package/dist/tools/forms/getFormResponse.js +45 -45
  55. package/dist/tools/forms/index.js +15 -15
  56. package/dist/tools/forms/listFormResponses.js +56 -56
  57. package/dist/tools/forms/setPublishSettings.js +59 -59
  58. package/dist/tools/gmail/drafts.js +165 -165
  59. package/dist/tools/gmail/labels.js +54 -83
  60. package/dist/tools/gmail/messages.js +444 -441
  61. package/dist/tools/gmail/settings.js +358 -528
  62. package/dist/tools/gmail/threads.js +286 -164
  63. package/dist/tools/index.js +511 -473
  64. package/dist/tools/labels.js +103 -103
  65. package/dist/tools/legacyAliases.js +426 -0
  66. package/dist/tools/maps/directions.js +72 -0
  67. package/dist/tools/maps/geocode.js +16 -0
  68. package/dist/tools/maps/index.js +15 -0
  69. package/dist/tools/maps/mapsClient.js +83 -0
  70. package/dist/tools/maps/placeDetails.js +16 -0
  71. package/dist/tools/maps/reverseGeocode.js +19 -0
  72. package/dist/tools/maps/searchNearby.js +54 -0
  73. package/dist/tools/maps/searchPlaces.js +24 -0
  74. package/dist/tools/messages.js +448 -448
  75. package/dist/tools/settings.js +528 -528
  76. package/dist/tools/slides/createPresentation.js +104 -104
  77. package/dist/tools/slides/createShape.js +92 -92
  78. package/dist/tools/slides/createTextBox.js +82 -82
  79. package/dist/tools/slides/deleteSlide.js +30 -30
  80. package/dist/tools/slides/duplicateSlide.js +37 -37
  81. package/dist/tools/slides/exportThumbnail.js +42 -42
  82. package/dist/tools/slides/formatParagraph.js +72 -72
  83. package/dist/tools/slides/formatText.js +84 -84
  84. package/dist/tools/slides/getPresentation.js +87 -87
  85. package/dist/tools/slides/index.js +33 -33
  86. package/dist/tools/slides/reorderSlides.js +41 -41
  87. package/dist/tools/slides/replaceAllText.js +46 -46
  88. package/dist/tools/slides/setBackground.js +58 -58
  89. package/dist/tools/slides/speakerNotes.js +102 -102
  90. package/dist/tools/slides/styleShape.js +111 -111
  91. package/dist/tools/slides/updatePresentation.js +128 -128
  92. package/dist/tools/threads.js +145 -145
  93. package/dist/tools/utils/appendMarkdownToGoogleDoc.js +30 -6
  94. package/dist/tools/utils/replaceDocumentWithMarkdown.js +71 -8
  95. package/dist/updateCheck.js +202 -0
  96. package/dist/workspace.js +122 -0
  97. package/package.json +82 -81
@@ -1,268 +1,268 @@
1
- import { UserError } from 'fastmcp';
2
- import { z } from 'zod';
3
- import { getDriveClient } from '../../clients.js';
4
- import * as fs from 'fs/promises';
5
- import * as path from 'path';
6
- import { Readable } from 'stream';
7
- import { pipeline } from 'stream/promises';
8
- import { createWriteStream } from 'fs';
9
-
10
- // Google Workspace MIME types and their export formats
11
- const EXPORT_FORMATS = {
12
- 'application/vnd.google-apps.document': {
13
- label: 'Google Doc',
14
- formats: {
15
- pdf: 'application/pdf',
16
- docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
17
- md: 'text/markdown',
18
- txt: 'text/plain',
19
- html: 'text/html',
20
- rtf: 'application/rtf',
21
- odt: 'application/vnd.oasis.opendocument.text',
22
- epub: 'application/epub+zip',
23
- },
24
- defaultFormat: 'pdf',
25
- extensions: {
26
- pdf: '.pdf',
27
- docx: '.docx',
28
- md: '.md',
29
- txt: '.txt',
30
- html: '.html',
31
- rtf: '.rtf',
32
- odt: '.odt',
33
- epub: '.epub',
34
- },
35
- },
36
- 'application/vnd.google-apps.spreadsheet': {
37
- label: 'Google Sheet',
38
- formats: {
39
- pdf: 'application/pdf',
40
- xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
41
- csv: 'text/csv',
42
- tsv: 'text/tab-separated-values',
43
- ods: 'application/vnd.oasis.opendocument.spreadsheet',
44
- },
45
- defaultFormat: 'xlsx',
46
- extensions: {
47
- pdf: '.pdf',
48
- xlsx: '.xlsx',
49
- csv: '.csv',
50
- tsv: '.tsv',
51
- ods: '.ods',
52
- },
53
- },
54
- 'application/vnd.google-apps.presentation': {
55
- label: 'Google Slides',
56
- formats: {
57
- pdf: 'application/pdf',
58
- pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
59
- odp: 'application/vnd.oasis.opendocument.presentation',
60
- txt: 'text/plain',
61
- },
62
- defaultFormat: 'pdf',
63
- extensions: {
64
- pdf: '.pdf',
65
- pptx: '.pptx',
66
- odp: '.odp',
67
- txt: '.txt',
68
- },
69
- },
70
- 'application/vnd.google-apps.drawing': {
71
- label: 'Google Drawing',
72
- formats: {
73
- pdf: 'application/pdf',
74
- png: 'image/png',
75
- jpg: 'image/jpeg',
76
- svg: 'image/svg+xml',
77
- },
78
- defaultFormat: 'pdf',
79
- extensions: {
80
- pdf: '.pdf',
81
- png: '.png',
82
- jpg: '.jpg',
83
- svg: '.svg',
84
- },
85
- },
86
- };
87
-
88
- // All supported export format keys
89
- const ALL_FORMAT_KEYS = [
90
- ...new Set(
91
- Object.values(EXPORT_FORMATS).flatMap((t) => Object.keys(t.formats))
92
- ),
93
- ];
94
-
95
- export function register(server) {
96
- server.addTool({
97
- name: 'downloadFile',
98
- description:
99
- 'Downloads a file from Google Drive to the local filesystem. ' +
100
- 'For Google Workspace files (Docs, Sheets, Slides, Drawings), specify an export format ' +
101
- '(e.g. pdf, docx, md, xlsx, csv, pptx). For regular files (images, PDFs, etc.), ' +
102
- 'downloads the original file directly.',
103
- parameters: z.object({
104
- fileId: z.string().describe('The ID of the file to download.'),
105
- localPath: z
106
- .string()
107
- .describe(
108
- 'The local file path to save the downloaded file to. ' +
109
- 'Can be an absolute path or relative to the current working directory. ' +
110
- 'If a directory is provided, the file will be saved with its Drive name.'
111
- ),
112
- exportFormat: z
113
- .enum(ALL_FORMAT_KEYS)
114
- .optional()
115
- .describe(
116
- 'Export format for Google Workspace files. ' +
117
- 'Docs: pdf, docx, md, txt, html, rtf, odt, epub. ' +
118
- 'Sheets: pdf, xlsx, csv, tsv, ods. ' +
119
- 'Slides: pdf, pptx, odp, txt. ' +
120
- 'Drawings: pdf, png, jpg, svg. ' +
121
- 'Ignored for non-Google files (they download as-is).'
122
- ),
123
- }),
124
- execute: async (args, { log }) => {
125
- const drive = await getDriveClient();
126
- log.info(`Downloading file: ${args.fileId}`);
127
-
128
- try {
129
- // Get file metadata first
130
- const metaResponse = await drive.files.get({
131
- fileId: args.fileId,
132
- fields: 'id,name,mimeType,size',
133
- supportsAllDrives: true,
134
- });
135
- const file = metaResponse.data;
136
- if (!file) {
137
- throw new UserError(
138
- `File with ID ${args.fileId} not found.`
139
- );
140
- }
141
-
142
- const isGoogleWorkspace =
143
- file.mimeType in EXPORT_FORMATS;
144
-
145
- // Determine export MIME type and file extension
146
- let exportMimeType = null;
147
- let fileExtension = '';
148
-
149
- if (isGoogleWorkspace) {
150
- const typeInfo = EXPORT_FORMATS[file.mimeType];
151
- const format =
152
- args.exportFormat || typeInfo.defaultFormat;
153
-
154
- if (!typeInfo.formats[format]) {
155
- const available = Object.keys(
156
- typeInfo.formats
157
- ).join(', ');
158
- throw new UserError(
159
- `Format '${format}' is not supported for ${typeInfo.label}. ` +
160
- `Available formats: ${available}`
161
- );
162
- }
163
-
164
- exportMimeType = typeInfo.formats[format];
165
- fileExtension = typeInfo.extensions[format];
166
- }
167
-
168
- // Resolve the local path
169
- let destPath = path.resolve(args.localPath);
170
-
171
- // Check if destPath is a directory
172
- let isDir = false;
173
- try {
174
- const stat = await fs.stat(destPath);
175
- isDir = stat.isDirectory();
176
- } catch {
177
- // Path doesn't exist yet — treat as a file path
178
- }
179
-
180
- if (isDir) {
181
- // Build filename from Drive name + appropriate extension
182
- let fileName = file.name;
183
- if (isGoogleWorkspace && fileExtension) {
184
- // Google Workspace files don't have extensions in their name
185
- fileName = file.name + fileExtension;
186
- }
187
- destPath = path.join(destPath, fileName);
188
- } else if (
189
- isGoogleWorkspace &&
190
- fileExtension &&
191
- !destPath.endsWith(fileExtension)
192
- ) {
193
- // Append extension if not already present
194
- destPath = destPath + fileExtension;
195
- }
196
-
197
- // Ensure parent directory exists
198
- await fs.mkdir(path.dirname(destPath), { recursive: true });
199
-
200
- // Download the file
201
- if (isGoogleWorkspace) {
202
- log.info(
203
- `Exporting ${EXPORT_FORMATS[file.mimeType].label} as ${args.exportFormat || EXPORT_FORMATS[file.mimeType].defaultFormat}`
204
- );
205
- const exportResponse = await drive.files.export(
206
- { fileId: args.fileId, mimeType: exportMimeType },
207
- { responseType: 'stream' }
208
- );
209
- await pipeline(
210
- exportResponse.data,
211
- createWriteStream(destPath)
212
- );
213
- } else {
214
- log.info(`Downloading binary file: ${file.name}`);
215
- const downloadResponse = await drive.files.get(
216
- {
217
- fileId: args.fileId,
218
- alt: 'media',
219
- supportsAllDrives: true,
220
- },
221
- { responseType: 'stream' }
222
- );
223
- await pipeline(
224
- downloadResponse.data,
225
- createWriteStream(destPath)
226
- );
227
- }
228
-
229
- // Get the final file size
230
- const stat = await fs.stat(destPath);
231
-
232
- const result = {
233
- success: true,
234
- fileName: file.name,
235
- savedTo: destPath,
236
- fileSize: stat.size,
237
- mimeType: isGoogleWorkspace
238
- ? exportMimeType
239
- : file.mimeType,
240
- };
241
-
242
- if (isGoogleWorkspace) {
243
- result.exportedAs =
244
- args.exportFormat ||
245
- EXPORT_FORMATS[file.mimeType].defaultFormat;
246
- }
247
-
248
- return JSON.stringify(result, null, 2);
249
- } catch (error) {
250
- if (error instanceof UserError) throw error;
251
- log.error(
252
- `Error downloading file: ${error.message || error}`
253
- );
254
- if (error.code === 404)
255
- throw new UserError(
256
- `File not found (ID: ${args.fileId}).`
257
- );
258
- if (error.code === 403)
259
- throw new UserError(
260
- 'Permission denied. Make sure you have access to this file.'
261
- );
262
- throw new UserError(
263
- `Failed to download file: ${error.message || 'Unknown error'}`
264
- );
265
- }
266
- },
267
- });
268
- }
1
+ import { UserError } from 'fastmcp';
2
+ import { z } from 'zod';
3
+ import { getDriveClient } from '../../clients.js';
4
+ import * as fs from 'fs/promises';
5
+ import * as path from 'path';
6
+ import { Readable } from 'stream';
7
+ import { pipeline } from 'stream/promises';
8
+ import { createWriteStream } from 'fs';
9
+
10
+ // Google Workspace MIME types and their export formats
11
+ const EXPORT_FORMATS = {
12
+ 'application/vnd.google-apps.document': {
13
+ label: 'Google Doc',
14
+ formats: {
15
+ pdf: 'application/pdf',
16
+ docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
17
+ md: 'text/markdown',
18
+ txt: 'text/plain',
19
+ html: 'text/html',
20
+ rtf: 'application/rtf',
21
+ odt: 'application/vnd.oasis.opendocument.text',
22
+ epub: 'application/epub+zip',
23
+ },
24
+ defaultFormat: 'pdf',
25
+ extensions: {
26
+ pdf: '.pdf',
27
+ docx: '.docx',
28
+ md: '.md',
29
+ txt: '.txt',
30
+ html: '.html',
31
+ rtf: '.rtf',
32
+ odt: '.odt',
33
+ epub: '.epub',
34
+ },
35
+ },
36
+ 'application/vnd.google-apps.spreadsheet': {
37
+ label: 'Google Sheet',
38
+ formats: {
39
+ pdf: 'application/pdf',
40
+ xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
41
+ csv: 'text/csv',
42
+ tsv: 'text/tab-separated-values',
43
+ ods: 'application/vnd.oasis.opendocument.spreadsheet',
44
+ },
45
+ defaultFormat: 'xlsx',
46
+ extensions: {
47
+ pdf: '.pdf',
48
+ xlsx: '.xlsx',
49
+ csv: '.csv',
50
+ tsv: '.tsv',
51
+ ods: '.ods',
52
+ },
53
+ },
54
+ 'application/vnd.google-apps.presentation': {
55
+ label: 'Google Slides',
56
+ formats: {
57
+ pdf: 'application/pdf',
58
+ pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
59
+ odp: 'application/vnd.oasis.opendocument.presentation',
60
+ txt: 'text/plain',
61
+ },
62
+ defaultFormat: 'pdf',
63
+ extensions: {
64
+ pdf: '.pdf',
65
+ pptx: '.pptx',
66
+ odp: '.odp',
67
+ txt: '.txt',
68
+ },
69
+ },
70
+ 'application/vnd.google-apps.drawing': {
71
+ label: 'Google Drawing',
72
+ formats: {
73
+ pdf: 'application/pdf',
74
+ png: 'image/png',
75
+ jpg: 'image/jpeg',
76
+ svg: 'image/svg+xml',
77
+ },
78
+ defaultFormat: 'pdf',
79
+ extensions: {
80
+ pdf: '.pdf',
81
+ png: '.png',
82
+ jpg: '.jpg',
83
+ svg: '.svg',
84
+ },
85
+ },
86
+ };
87
+
88
+ // All supported export format keys
89
+ const ALL_FORMAT_KEYS = [
90
+ ...new Set(
91
+ Object.values(EXPORT_FORMATS).flatMap((t) => Object.keys(t.formats))
92
+ ),
93
+ ];
94
+
95
+ export function register(server) {
96
+ server.addTool({
97
+ name: 'downloadFile',
98
+ description:
99
+ 'Downloads a file from Google Drive to the local filesystem. ' +
100
+ 'For Google Workspace files (Docs, Sheets, Slides, Drawings), specify an export format ' +
101
+ '(e.g. pdf, docx, md, xlsx, csv, pptx). For regular files (images, PDFs, etc.), ' +
102
+ 'downloads the original file directly.',
103
+ parameters: z.object({
104
+ fileId: z.string().describe('The ID of the file to download.'),
105
+ localPath: z
106
+ .string()
107
+ .describe(
108
+ 'The local file path to save the downloaded file to. ' +
109
+ 'Can be an absolute path or relative to the current working directory. ' +
110
+ 'If a directory is provided, the file will be saved with its Drive name.'
111
+ ),
112
+ exportFormat: z
113
+ .enum(ALL_FORMAT_KEYS)
114
+ .optional()
115
+ .describe(
116
+ 'Export format for Google Workspace files. ' +
117
+ 'Docs: pdf, docx, md, txt, html, rtf, odt, epub. ' +
118
+ 'Sheets: pdf, xlsx, csv, tsv, ods. ' +
119
+ 'Slides: pdf, pptx, odp, txt. ' +
120
+ 'Drawings: pdf, png, jpg, svg. ' +
121
+ 'Ignored for non-Google files (they download as-is).'
122
+ ),
123
+ }),
124
+ execute: async (args, { log }) => {
125
+ const drive = await getDriveClient();
126
+ log.info(`Downloading file: ${args.fileId}`);
127
+
128
+ try {
129
+ // Get file metadata first
130
+ const metaResponse = await drive.files.get({
131
+ fileId: args.fileId,
132
+ fields: 'id,name,mimeType,size',
133
+ supportsAllDrives: true,
134
+ });
135
+ const file = metaResponse.data;
136
+ if (!file) {
137
+ throw new UserError(
138
+ `File with ID ${args.fileId} not found.`
139
+ );
140
+ }
141
+
142
+ const isGoogleWorkspace =
143
+ file.mimeType in EXPORT_FORMATS;
144
+
145
+ // Determine export MIME type and file extension
146
+ let exportMimeType = null;
147
+ let fileExtension = '';
148
+
149
+ if (isGoogleWorkspace) {
150
+ const typeInfo = EXPORT_FORMATS[file.mimeType];
151
+ const format =
152
+ args.exportFormat || typeInfo.defaultFormat;
153
+
154
+ if (!typeInfo.formats[format]) {
155
+ const available = Object.keys(
156
+ typeInfo.formats
157
+ ).join(', ');
158
+ throw new UserError(
159
+ `Format '${format}' is not supported for ${typeInfo.label}. ` +
160
+ `Available formats: ${available}`
161
+ );
162
+ }
163
+
164
+ exportMimeType = typeInfo.formats[format];
165
+ fileExtension = typeInfo.extensions[format];
166
+ }
167
+
168
+ // Resolve the local path
169
+ let destPath = path.resolve(args.localPath);
170
+
171
+ // Check if destPath is a directory
172
+ let isDir = false;
173
+ try {
174
+ const stat = await fs.stat(destPath);
175
+ isDir = stat.isDirectory();
176
+ } catch {
177
+ // Path doesn't exist yet — treat as a file path
178
+ }
179
+
180
+ if (isDir) {
181
+ // Build filename from Drive name + appropriate extension
182
+ let fileName = file.name;
183
+ if (isGoogleWorkspace && fileExtension) {
184
+ // Google Workspace files don't have extensions in their name
185
+ fileName = file.name + fileExtension;
186
+ }
187
+ destPath = path.join(destPath, fileName);
188
+ } else if (
189
+ isGoogleWorkspace &&
190
+ fileExtension &&
191
+ !destPath.endsWith(fileExtension)
192
+ ) {
193
+ // Append extension if not already present
194
+ destPath = destPath + fileExtension;
195
+ }
196
+
197
+ // Ensure parent directory exists
198
+ await fs.mkdir(path.dirname(destPath), { recursive: true });
199
+
200
+ // Download the file
201
+ if (isGoogleWorkspace) {
202
+ log.info(
203
+ `Exporting ${EXPORT_FORMATS[file.mimeType].label} as ${args.exportFormat || EXPORT_FORMATS[file.mimeType].defaultFormat}`
204
+ );
205
+ const exportResponse = await drive.files.export(
206
+ { fileId: args.fileId, mimeType: exportMimeType },
207
+ { responseType: 'stream' }
208
+ );
209
+ await pipeline(
210
+ exportResponse.data,
211
+ createWriteStream(destPath)
212
+ );
213
+ } else {
214
+ log.info(`Downloading binary file: ${file.name}`);
215
+ const downloadResponse = await drive.files.get(
216
+ {
217
+ fileId: args.fileId,
218
+ alt: 'media',
219
+ supportsAllDrives: true,
220
+ },
221
+ { responseType: 'stream' }
222
+ );
223
+ await pipeline(
224
+ downloadResponse.data,
225
+ createWriteStream(destPath)
226
+ );
227
+ }
228
+
229
+ // Get the final file size
230
+ const stat = await fs.stat(destPath);
231
+
232
+ const result = {
233
+ success: true,
234
+ fileName: file.name,
235
+ savedTo: destPath,
236
+ fileSize: stat.size,
237
+ mimeType: isGoogleWorkspace
238
+ ? exportMimeType
239
+ : file.mimeType,
240
+ };
241
+
242
+ if (isGoogleWorkspace) {
243
+ result.exportedAs =
244
+ args.exportFormat ||
245
+ EXPORT_FORMATS[file.mimeType].defaultFormat;
246
+ }
247
+
248
+ return JSON.stringify(result, null, 2);
249
+ } catch (error) {
250
+ if (error instanceof UserError) throw error;
251
+ log.error(
252
+ `Error downloading file: ${error.message || error}`
253
+ );
254
+ if (error.code === 404)
255
+ throw new UserError(
256
+ `File not found (ID: ${args.fileId}).`
257
+ );
258
+ if (error.code === 403)
259
+ throw new UserError(
260
+ 'Permission denied. Make sure you have access to this file.'
261
+ );
262
+ throw new UserError(
263
+ `Failed to download file: ${error.message || 'Unknown error'}`
264
+ );
265
+ }
266
+ },
267
+ });
268
+ }
@@ -1,48 +1,48 @@
1
- import { UserError } from 'fastmcp';
2
- import { z } from 'zod';
3
- import { getDriveClient } from '../../clients.js';
4
- export function register(server) {
5
- server.addTool({
6
- name: 'getFileInfo',
7
- description: 'Gets metadata about any Drive file (document, spreadsheet, PDF, etc.) including its name, type, owner, sharing status, and modification history.',
8
- parameters: z.object({
9
- fileId: z.string().describe('The ID of the file to get information about.'),
10
- }),
11
- execute: async (args, { log }) => {
12
- const drive = await getDriveClient();
13
- log.info(`Getting info for file: ${args.fileId}`);
14
- try {
15
- const response = await drive.files.get({
16
- fileId: args.fileId,
17
- fields: 'id,name,description,mimeType,size,createdTime,modifiedTime,webViewLink,owners(displayName,emailAddress),lastModifyingUser(displayName,emailAddress),shared,parents,version',
18
- supportsAllDrives: true,
19
- });
20
- const file = response.data;
21
- if (!file) {
22
- throw new UserError(`File with ID ${args.fileId} not found.`);
23
- }
24
- const info = {
25
- id: file.id,
26
- name: file.name,
27
- mimeType: file.mimeType,
28
- createdTime: file.createdTime,
29
- modifiedTime: file.modifiedTime,
30
- owner: file.owners?.[0]?.displayName || null,
31
- lastModifyingUser: file.lastModifyingUser?.displayName || null,
32
- shared: file.shared || false,
33
- url: file.webViewLink,
34
- description: file.description || null,
35
- };
36
- return JSON.stringify(info, null, 2);
37
- }
38
- catch (error) {
39
- log.error(`Error getting file info: ${error.message || error}`);
40
- if (error.code === 404)
41
- throw new UserError(`File not found (ID: ${args.fileId}).`);
42
- if (error.code === 403)
43
- throw new UserError('Permission denied. Make sure you have access to this file.');
44
- throw new UserError(`Failed to get file info: ${error.message || 'Unknown error'}`);
45
- }
46
- },
47
- });
48
- }
1
+ import { UserError } from 'fastmcp';
2
+ import { z } from 'zod';
3
+ import { getDriveClient } from '../../clients.js';
4
+ export function register(server) {
5
+ server.addTool({
6
+ name: 'getFileInfo',
7
+ description: 'Gets metadata about any Drive file (document, spreadsheet, PDF, etc.) including its name, type, owner, sharing status, and modification history.',
8
+ parameters: z.object({
9
+ fileId: z.string().describe('The ID of the file to get information about.'),
10
+ }),
11
+ execute: async (args, { log }) => {
12
+ const drive = await getDriveClient();
13
+ log.info(`Getting info for file: ${args.fileId}`);
14
+ try {
15
+ const response = await drive.files.get({
16
+ fileId: args.fileId,
17
+ fields: 'id,name,description,mimeType,size,createdTime,modifiedTime,webViewLink,owners(displayName,emailAddress),lastModifyingUser(displayName,emailAddress),shared,parents,version',
18
+ supportsAllDrives: true,
19
+ });
20
+ const file = response.data;
21
+ if (!file) {
22
+ throw new UserError(`File with ID ${args.fileId} not found.`);
23
+ }
24
+ const info = {
25
+ id: file.id,
26
+ name: file.name,
27
+ mimeType: file.mimeType,
28
+ createdTime: file.createdTime,
29
+ modifiedTime: file.modifiedTime,
30
+ owner: file.owners?.[0]?.displayName || null,
31
+ lastModifyingUser: file.lastModifyingUser?.displayName || null,
32
+ shared: file.shared || false,
33
+ url: file.webViewLink,
34
+ description: file.description || null,
35
+ };
36
+ return JSON.stringify(info, null, 2);
37
+ }
38
+ catch (error) {
39
+ log.error(`Error getting file info: ${error.message || error}`);
40
+ if (error.code === 404)
41
+ throw new UserError(`File not found (ID: ${args.fileId}).`);
42
+ if (error.code === 403)
43
+ throw new UserError('Permission denied. Make sure you have access to this file.');
44
+ throw new UserError(`Failed to get file info: ${error.message || 'Unknown error'}`);
45
+ }
46
+ },
47
+ });
48
+ }