google-tools-mcp 1.0.3 → 1.0.4

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.
@@ -1,6 +1,4 @@
1
- import { register as applyTextStyle } from './applyTextStyle.js';
2
1
  import { register as applyParagraphStyle } from './applyParagraphStyle.js';
3
2
  export function registerFormattingTools(server) {
4
- applyTextStyle(server);
5
3
  applyParagraphStyle(server);
6
4
  }
@@ -4,7 +4,6 @@ import { register as listDocumentTabs } from './listDocumentTabs.js';
4
4
  import { register as renameTab } from './renameTab.js';
5
5
  import { register as addTab } from './addTab.js';
6
6
  import { register as appendToGoogleDoc } from './appendToGoogleDoc.js';
7
- import { register as insertText } from './insertText.js';
8
7
  import { register as deleteRange } from './deleteRange.js';
9
8
  import { register as modifyText } from './modifyText.js';
10
9
  import { register as findAndReplace } from './findAndReplace.js';
@@ -23,7 +22,6 @@ export function registerDocsTools(server) {
23
22
  renameTab(server);
24
23
  addTab(server);
25
24
  appendToGoogleDoc(server);
26
- insertText(server);
27
25
  deleteRange(server);
28
26
  modifyText(server);
29
27
  findAndReplace(server);
@@ -0,0 +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,6 +1,6 @@
1
- import { register as listGoogleDocs } from './listGoogleDocs.js';
1
+ import { register as listDriveFiles } from './listDriveFiles.js';
2
2
  import { register as searchGoogleDocs } from './searchGoogleDocs.js';
3
- import { register as getDocumentInfo } from './getDocumentInfo.js';
3
+ import { register as getFileInfo } from './getFileInfo.js';
4
4
  import { register as createFolder } from './createFolder.js';
5
5
  import { register as listFolderContents } from './listFolderContents.js';
6
6
  import { register as getFolderInfo } from './getFolderInfo.js';
@@ -13,9 +13,9 @@ import { register as createFromTemplate } from './createFromTemplate.js';
13
13
  import { register as listSharedDrives } from './listSharedDrives.js';
14
14
  import { register as listSharedWithMe } from './listSharedWithMe.js';
15
15
  export function registerDriveTools(server) {
16
- listGoogleDocs(server);
16
+ listDriveFiles(server);
17
17
  searchGoogleDocs(server);
18
- getDocumentInfo(server);
18
+ getFileInfo(server);
19
19
  createFolder(server);
20
20
  listFolderContents(server);
21
21
  getFolderInfo(server);
@@ -0,0 +1,106 @@
1
+ import { UserError } from 'fastmcp';
2
+ import { z } from 'zod';
3
+ import { getDriveClient } from '../../clients.js';
4
+
5
+ const MIME_TYPES = {
6
+ document: 'application/vnd.google-apps.document',
7
+ spreadsheet: 'application/vnd.google-apps.spreadsheet',
8
+ presentation: 'application/vnd.google-apps.presentation',
9
+ form: 'application/vnd.google-apps.form',
10
+ pdf: 'application/pdf',
11
+ };
12
+
13
+ export function register(server) {
14
+ server.addTool({
15
+ name: 'listDriveFiles',
16
+ description:
17
+ 'Lists files in your Drive, optionally filtered by type (document, spreadsheet, presentation, form, pdf), name/content query, or modification date.',
18
+ parameters: z.object({
19
+ fileType: z
20
+ .enum(['document', 'spreadsheet', 'presentation', 'form', 'pdf', 'all'])
21
+ .optional()
22
+ .default('all')
23
+ .describe('Filter by file type. Defaults to all types.'),
24
+ maxResults: z
25
+ .number()
26
+ .int()
27
+ .min(1)
28
+ .max(100)
29
+ .optional()
30
+ .default(20)
31
+ .describe('Maximum number of files to return (1-100).'),
32
+ query: z
33
+ .string()
34
+ .optional()
35
+ .describe('Search query to filter files by name or content.'),
36
+ orderBy: z
37
+ .enum(['name', 'modifiedTime', 'createdTime'])
38
+ .optional()
39
+ .default('modifiedTime')
40
+ .describe('Sort order for results.'),
41
+ modifiedAfter: z
42
+ .string()
43
+ .optional()
44
+ .describe(
45
+ 'Only return files modified after this date (ISO 8601 format, e.g., "2024-01-01").'
46
+ ),
47
+ }),
48
+ execute: async (args, { log }) => {
49
+ const drive = await getDriveClient();
50
+ log.info(
51
+ `Listing Drive files. Type: ${args.fileType}, Query: ${args.query || 'none'}, Max: ${args.maxResults}, Order: ${args.orderBy}`
52
+ );
53
+ try {
54
+ let queryParts = ['trashed=false'];
55
+
56
+ // Filter by mime type
57
+ if (args.fileType !== 'all') {
58
+ queryParts.push(`mimeType='${MIME_TYPES[args.fileType]}'`);
59
+ } else {
60
+ // Exclude folders from "all" results
61
+ queryParts.push("mimeType!='application/vnd.google-apps.folder'");
62
+ }
63
+
64
+ if (args.query) {
65
+ queryParts.push(
66
+ `(name contains '${args.query}' or fullText contains '${args.query}')`
67
+ );
68
+ }
69
+
70
+ if (args.modifiedAfter) {
71
+ const cutoffDate = new Date(args.modifiedAfter).toISOString();
72
+ queryParts.push(`modifiedTime > '${cutoffDate}'`);
73
+ }
74
+
75
+ const response = await drive.files.list({
76
+ q: queryParts.join(' and '),
77
+ pageSize: args.maxResults,
78
+ orderBy: args.orderBy === 'name' ? 'name' : args.orderBy,
79
+ fields: 'files(id,name,mimeType,modifiedTime,createdTime,size,webViewLink,owners(displayName,emailAddress))',
80
+ supportsAllDrives: true,
81
+ includeItemsFromAllDrives: true,
82
+ });
83
+
84
+ const files = (response.data.files || []).map((file) => ({
85
+ id: file.id,
86
+ name: file.name,
87
+ mimeType: file.mimeType,
88
+ modifiedTime: file.modifiedTime,
89
+ owner: file.owners?.[0]?.displayName || null,
90
+ url: file.webViewLink,
91
+ }));
92
+
93
+ return JSON.stringify({ files }, null, 2);
94
+ } catch (error) {
95
+ log.error(`Error listing Drive files: ${error.message || error}`);
96
+ if (error.code === 403)
97
+ throw new UserError(
98
+ 'Permission denied. Make sure you have granted Google Drive access to the application.'
99
+ );
100
+ throw new UserError(
101
+ `Failed to list files: ${error.message || 'Unknown error'}`
102
+ );
103
+ }
104
+ },
105
+ });
106
+ }
@@ -6,7 +6,6 @@ import { register as clearSpreadsheetRange } from './clearSpreadsheetRange.js';
6
6
  import { register as getSpreadsheetInfo } from './getSpreadsheetInfo.js';
7
7
  import { register as addSpreadsheetSheet } from './addSpreadsheetSheet.js';
8
8
  import { register as createSpreadsheet } from './createSpreadsheet.js';
9
- import { register as listGoogleSheets } from './listGoogleSheets.js';
10
9
  import { register as deleteSheet } from './deleteSheet.js';
11
10
  import { register as renameSheet } from './renameSheet.js';
12
11
  import { register as duplicateSheet } from './duplicateSheet.js';
@@ -39,7 +38,6 @@ export function registerSheetsTools(server) {
39
38
  getSpreadsheetInfo(server);
40
39
  addSpreadsheetSheet(server);
41
40
  createSpreadsheet(server);
42
- listGoogleSheets(server);
43
41
  deleteSheet(server);
44
42
  renameSheet(server);
45
43
  duplicateSheet(server);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "google-tools-mcp",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Combined Google Workspace MCP server (Drive, Docs, Sheets, Gmail) with lazy-loaded tool categories",
5
5
  "type": "module",
6
6
  "bin": {