google-tools-mcp 1.0.9 → 1.0.11

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # google-tools-mcp
2
2
 
3
- A unified MCP server for Google Workspace — Drive, Docs, Sheets, Gmail, Calendar, and Forms — with **152 tools** across 9 categories.
3
+ A unified MCP server for Google Workspace — Drive, Docs, Sheets, Gmail, Calendar, and Forms — with **153 tools** across 9 categories.
4
4
 
5
5
  All tools are loaded at startup so they're immediately available to your AI agent. No discovery step needed.
6
6
 
@@ -10,10 +10,10 @@ Most Google MCP servers split functionality across separate packages. This serve
10
10
 
11
11
  ## Features
12
12
 
13
- - **152 tools** across 9 categories, all available immediately
13
+ - **153 tools** across 9 categories, all available immediately
14
14
  - **Single auth token** — one OAuth flow covers Drive, Docs, Sheets, Gmail, Calendar, and Forms
15
15
  - **Lazy-loading auth** — no browser popup until your first tool call
16
- - **No lazy tool loading** — all 150 tools are registered eagerly at startup since most MCP clients (including Claude Code) don't support `notifications/tools/list_changed`
16
+ - **No lazy tool loading** — all 153 tools are registered eagerly at startup since most MCP clients (including Claude Code) don't support `notifications/tools/list_changed`
17
17
  - **Multi-profile support** — separate tokens per Google account
18
18
  - **No telemetry**
19
19
 
@@ -85,15 +85,28 @@ Add the credentials directly to your MCP configuration:
85
85
 
86
86
  #### Claude Code (recommended)
87
87
 
88
- If you used Option A or B above:
88
+ **User-scope** (available in all projects):
89
+
90
+ ```bash
91
+ claude mcp add -s user google -- npx -y google-tools-mcp
92
+ ```
93
+
94
+ **Project-scope** (available only in the current project):
89
95
 
90
96
  ```bash
91
97
  claude mcp add google -- npx -y google-tools-mcp
92
98
  ```
93
99
 
94
- Or with env vars (Option C):
100
+ With env vars (Option C):
95
101
 
96
102
  ```bash
103
+ # User-scope
104
+ claude mcp add -s user google \
105
+ -e GOOGLE_CLIENT_ID=your-client-id \
106
+ -e GOOGLE_CLIENT_SECRET=your-client-secret \
107
+ -- npx -y google-tools-mcp
108
+
109
+ # Project-scope
97
110
  claude mcp add google \
98
111
  -e GOOGLE_CLIENT_ID=your-client-id \
99
112
  -e GOOGLE_CLIENT_SECRET=your-client-secret \
@@ -105,7 +118,7 @@ claude mcp add google \
105
118
  Via the `claude` CLI:
106
119
 
107
120
  ```bash
108
- claude mcp add google \
121
+ claude mcp add -s user google \
109
122
  -e GOOGLE_MCP_PROFILE=myprofile \
110
123
  -- npx -y google-tools-mcp
111
124
  ```
@@ -169,10 +182,10 @@ This stores tokens in `~/.config/google-tools-mcp/work/` instead of the default
169
182
 
170
183
  ## Tool Categories
171
184
 
172
- ### `files` (17 tools)
185
+ ### `files` (18 tools)
173
186
  Google Drive file management and content reading.
174
187
 
175
- `listDriveFiles`, `searchDocuments`, `getFileInfo`, `createFolder`, `listFolderContents`, `getFolderInfo`, `moveFile`, `copyFile`, `renameFile`, `deleteFile`, `createDocument`, `createDocumentFromTemplate`, `listSharedDrives`, `listSharedWithMe`, `downloadFile`, `readFile`, `searchFileContents`
188
+ `listDriveFiles`, `searchDocuments`, `getFileInfo`, `getFilePath`, `createFolder`, `listFolderContents`, `getFolderInfo`, `moveFile`, `copyFile`, `renameFile`, `deleteFile`, `createDocument`, `createDocumentFromTemplate`, `listSharedDrives`, `listSharedWithMe`, `downloadFile`, `readFile`, `searchFileContents`
176
189
 
177
190
  ### `documents` (22 tools)
178
191
  Google Docs read/write/format with markdown support.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  // google-tools-mcp — Combined Google Workspace MCP server
3
3
  //
4
4
  // All tool categories (Drive, Docs, Sheets, Gmail, Calendar) are loaded at
@@ -69,6 +69,11 @@ export function register(server) {
69
69
  .array(z.string())
70
70
  .optional()
71
71
  .describe('RRULE recurrence rules (e.g. ["RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR"]). Only for create.'),
72
+ send_updates: z
73
+ .enum(['all', 'externalOnly', 'none'])
74
+ .optional()
75
+ .default('all')
76
+ .describe('Who to send email notifications to: "all" = all attendees (default), "externalOnly" = non-Google Calendar attendees only, "none" = no emails.'),
72
77
  }),
73
78
  execute: async (args, { log }) => {
74
79
  const calendar = await getCalendarClient();
@@ -80,6 +85,7 @@ export function register(server) {
80
85
  await calendar.events.delete({
81
86
  calendarId: args.calendar_id,
82
87
  eventId: args.event_id,
88
+ sendUpdates: args.send_updates,
83
89
  });
84
90
  return JSON.stringify({ success: true, message: `Event ${args.event_id} deleted.` });
85
91
  }
@@ -96,6 +102,7 @@ export function register(server) {
96
102
  calendarId: args.calendar_id,
97
103
  requestBody: eventBody,
98
104
  conferenceDataVersion: args.add_google_meet ? 1 : 0,
105
+ sendUpdates: args.send_updates,
99
106
  };
100
107
 
101
108
  const response = await calendar.events.insert(params);
@@ -119,6 +126,7 @@ export function register(server) {
119
126
  eventId: args.event_id,
120
127
  requestBody: eventBody,
121
128
  conferenceDataVersion: args.add_google_meet !== undefined ? 1 : 0,
129
+ sendUpdates: args.send_updates,
122
130
  };
123
131
 
124
132
  const response = await calendar.events.update(params);
@@ -17,6 +17,11 @@ export function register(server) {
17
17
  destination_calendar_id: z
18
18
  .string()
19
19
  .describe('Calendar ID to move the event to.'),
20
+ send_updates: z
21
+ .enum(['all', 'externalOnly', 'none'])
22
+ .optional()
23
+ .default('all')
24
+ .describe('Who to send email notifications to: "all" = all attendees (default), "externalOnly" = non-Google Calendar attendees only, "none" = no emails.'),
20
25
  }),
21
26
  execute: async (args, { log }) => {
22
27
  const calendar = await getCalendarClient();
@@ -29,6 +34,7 @@ export function register(server) {
29
34
  calendarId: args.source_calendar_id,
30
35
  eventId: args.event_id,
31
36
  destination: args.destination_calendar_id,
37
+ sendUpdates: args.send_updates,
32
38
  });
33
39
 
34
40
  const event = response.data;
@@ -7,13 +7,13 @@ import { docsJsonToMarkdown } from '../../markdown-transformer/index.js';
7
7
  export function register(server) {
8
8
  server.addTool({
9
9
  name: 'readDocument',
10
- description: "Reads the content of a Google Document. Returns plain text by default. Use format='markdown' to get formatted content suitable for editing and re-uploading with replaceDocumentWithMarkdown, or format='json' for the raw document structure.",
10
+ description: "Reads the content of a Google Document. Returns markdown by default (formatted content suitable for editing and re-uploading with replaceDocumentWithMarkdown). Use format='text' for plain text, or format='json' for the raw document structure.",
11
11
  parameters: DocumentIdParameter.extend({
12
12
  format: z
13
13
  .enum(['text', 'json', 'markdown'])
14
14
  .optional()
15
- .default('text')
16
- .describe("Output format: 'text' (plain text), 'json' (raw API structure, complex), 'markdown' (experimental conversion)."),
15
+ .default('markdown')
16
+ .describe("Output format: 'markdown' (formatted content), 'text' (plain text), 'json' (raw API structure, complex)."),
17
17
  maxLength: z
18
18
  .number()
19
19
  .optional()
@@ -0,0 +1,50 @@
1
+ import { UserError } from 'fastmcp';
2
+ import { z } from 'zod';
3
+ import { getDriveClient } from '../../clients.js';
4
+
5
+ export function register(server) {
6
+ server.addTool({
7
+ name: 'getFilePath',
8
+ description: 'Returns the full folder path of a Drive file from root to the file itself (e.g. "My Drive/Projects/Docs/report.pdf"). Walks up the parent chain to reconstruct the complete path.',
9
+ parameters: z.object({
10
+ fileId: z.string().describe('The ID of the file or folder to get the path for.'),
11
+ }),
12
+ execute: async (args, { log }) => {
13
+ const drive = await getDriveClient();
14
+ log.info(`Getting full path for file: ${args.fileId}`);
15
+ try {
16
+ const pathParts = [];
17
+ let currentId = args.fileId;
18
+
19
+ while (currentId) {
20
+ const response = await drive.files.get({
21
+ fileId: currentId,
22
+ fields: 'id,name,parents',
23
+ supportsAllDrives: true,
24
+ });
25
+ const file = response.data;
26
+ if (!file) break;
27
+
28
+ pathParts.unshift(file.name);
29
+
30
+ if (file.parents && file.parents.length > 0) {
31
+ currentId = file.parents[0];
32
+ } else {
33
+ break;
34
+ }
35
+ }
36
+
37
+ const fullPath = pathParts.join('/');
38
+
39
+ return JSON.stringify({ fileId: args.fileId, path: fullPath }, null, 2);
40
+ } catch (error) {
41
+ log.error(`Error getting file path: ${error.message || error}`);
42
+ if (error.code === 404)
43
+ throw new UserError(`File not found (ID: ${args.fileId}).`);
44
+ if (error.code === 403)
45
+ throw new UserError('Permission denied. Make sure you have access to this file.');
46
+ throw new UserError(`Failed to get file path: ${error.message || 'Unknown error'}`);
47
+ }
48
+ },
49
+ });
50
+ }
@@ -13,6 +13,7 @@ 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
  import { register as downloadFile } from './downloadFile.js';
16
+ import { register as getFilePath } from './getFilePath.js';
16
17
  export function registerDriveTools(server) {
17
18
  listDriveFiles(server);
18
19
  searchGoogleDocs(server);
@@ -29,4 +30,5 @@ export function registerDriveTools(server) {
29
30
  listSharedDrives(server);
30
31
  listSharedWithMe(server);
31
32
  downloadFile(server);
33
+ getFilePath(server);
32
34
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "google-tools-mcp",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "Combined Google Workspace MCP server (Drive, Docs, Sheets, Gmail) with lazy-loaded tool categories",
5
5
  "type": "module",
6
6
  "bin": {