@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.
Files changed (182) hide show
  1. package/README.md +250 -17
  2. package/dist/auth.js +6 -0
  3. package/dist/index.js +1 -1
  4. package/dist/lib/calendar-helpers.js +197 -0
  5. package/dist/lib/document-id-resolver.js +76 -0
  6. package/dist/lib/drive-helpers.js +263 -0
  7. package/dist/lib/gmail-helpers.js +204 -0
  8. package/dist/lib/response-formatter.js +82 -0
  9. package/dist/lib/validation.js +112 -0
  10. package/dist/tools/calendar/acl/calendar_acl_insert.js +80 -0
  11. package/dist/tools/calendar/acl/calendar_acl_list.js +82 -0
  12. package/dist/tools/calendar/basic/calendar_create_event.js +113 -0
  13. package/dist/tools/calendar/basic/calendar_delete_event.js +52 -0
  14. package/dist/tools/calendar/basic/calendar_get_event.js +52 -0
  15. package/dist/tools/calendar/basic/calendar_list_events.js +86 -0
  16. package/dist/tools/calendar/basic/calendar_update_event.js +116 -0
  17. package/dist/tools/calendar/calendarlist/calendar_calendarlist_get.js +73 -0
  18. package/dist/tools/calendar/calendarlist/calendar_calendarlist_list.js +87 -0
  19. package/dist/tools/calendar/calendars/calendar_calendars_get.js +52 -0
  20. package/dist/tools/calendar/calendars/calendar_calendars_insert.js +66 -0
  21. package/dist/tools/calendar/calendars/calendar_calendars_update.js +85 -0
  22. package/dist/tools/calendar/colors/calendar_colors_get.js +46 -0
  23. package/dist/tools/calendar/events_advanced/calendar_events_instances.js +81 -0
  24. package/dist/tools/calendar/events_advanced/calendar_events_move.js +63 -0
  25. package/dist/tools/calendar/events_advanced/calendar_events_quickadd.js +52 -0
  26. package/dist/tools/calendar/freebusy/calendar_freebusy_query.js +69 -0
  27. package/dist/tools/calendar/settings/calendar_settings_list.js +81 -0
  28. package/dist/tools/docs/basic/gdocs_create.js +37 -0
  29. package/dist/tools/docs/basic/gdocs_get_metadata.js +45 -0
  30. package/dist/tools/docs/basic/gdocs_list_documents.js +59 -0
  31. package/dist/tools/docs/basic/gdocs_read.js +62 -0
  32. package/dist/tools/docs/content/gdocs_append_text.js +57 -0
  33. package/dist/tools/docs/content/gdocs_apply_style.js +86 -0
  34. package/dist/tools/docs/content/gdocs_create_heading.js +89 -0
  35. package/dist/tools/docs/content/gdocs_create_list.js +86 -0
  36. package/dist/tools/docs/content/gdocs_delete_text.js +64 -0
  37. package/dist/tools/docs/content/gdocs_format_text.js +137 -0
  38. package/dist/tools/docs/content/gdocs_insert_text.js +62 -0
  39. package/dist/tools/docs/content/gdocs_replace_text.js +64 -0
  40. package/dist/tools/docs/content/gdocs_set_alignment.js +76 -0
  41. package/dist/tools/docs/content/gdocs_update_text.js +78 -0
  42. package/dist/tools/docs/elements/gdocs_batch_update.js +108 -0
  43. package/dist/tools/docs/elements/gdocs_create_table.js +73 -0
  44. package/dist/tools/docs/elements/gdocs_export.js +62 -0
  45. package/dist/tools/docs/elements/gdocs_insert_image.js +96 -0
  46. package/dist/tools/docs/elements/gdocs_insert_link.js +77 -0
  47. package/dist/tools/docs/elements/gdocs_insert_page_break.js +55 -0
  48. package/dist/tools/docs/elements/gdocs_insert_toc.js +71 -0
  49. package/dist/tools/docs/elements/gdocs_merge_documents.js +104 -0
  50. package/dist/tools/docs/elements/gdocs_suggest_mode.js +41 -0
  51. package/dist/tools/drive/advanced/drive_empty_trash.js +56 -0
  52. package/dist/tools/drive/advanced/drive_export_file.js +158 -0
  53. package/dist/tools/drive/advanced/drive_list_revisions.js +80 -0
  54. package/dist/tools/drive/basic/drive_get_metadata.js +49 -0
  55. package/dist/tools/drive/basic/drive_list_files.js +76 -0
  56. package/dist/tools/drive/file/drive_copy_file.js +79 -0
  57. package/dist/tools/drive/file/drive_create_file.js +72 -0
  58. package/dist/tools/drive/file/drive_delete_file.js +48 -0
  59. package/dist/tools/drive/file/drive_move_file.js +79 -0
  60. package/dist/tools/drive/file/drive_rename_file.js +58 -0
  61. package/dist/tools/drive/file/drive_update_file.js +106 -0
  62. package/dist/tools/drive/file/drive_upload_file.js +80 -0
  63. package/dist/tools/drive/folder/drive_create_folder.js +67 -0
  64. package/dist/tools/drive/folder/drive_list_folder_contents.js +68 -0
  65. package/dist/tools/drive/folder/drive_move_to_folder.js +59 -0
  66. package/dist/tools/drive/permissions/drive_list_permissions.js +115 -0
  67. package/dist/tools/drive/permissions/drive_remove_permission.js +71 -0
  68. package/dist/tools/drive/permissions/drive_share_file.js +116 -0
  69. package/dist/tools/drive/permissions/drive_update_permission.js +79 -0
  70. package/dist/tools/gmail/basic/gmail_get_message.js +95 -0
  71. package/dist/tools/gmail/basic/gmail_get_thread.js +46 -0
  72. package/dist/tools/gmail/basic/gmail_list_labels.js +54 -0
  73. package/dist/tools/gmail/basic/gmail_search_messages.js +59 -0
  74. package/dist/tools/gmail/batch/gmail_batch_modify_labels.js +74 -0
  75. package/dist/tools/gmail/batch/gmail_get_messages_batch.js +120 -0
  76. package/dist/tools/gmail/batch/gmail_get_threads_batch.js +102 -0
  77. package/dist/tools/gmail/labels/gmail_manage_label.js +131 -0
  78. package/dist/tools/gmail/labels/gmail_modify_labels.js +65 -0
  79. package/dist/tools/gmail/send/gmail_draft_message.js +117 -0
  80. package/dist/tools/gmail/send/gmail_send_message.js +109 -0
  81. package/dist/tools/index.js +386 -3
  82. package/package.json +8 -3
  83. package/dist/tools/basic/gsheets_add_sheet.js +0 -65
  84. package/dist/tools/basic/gsheets_copy_sheet.js +0 -56
  85. package/dist/tools/basic/gsheets_copy_to.js +0 -113
  86. package/dist/tools/basic/gsheets_create_spreadsheet.js +0 -88
  87. package/dist/tools/basic/gsheets_delete_columns.js +0 -69
  88. package/dist/tools/basic/gsheets_delete_rows.js +0 -69
  89. package/dist/tools/basic/gsheets_delete_sheet.js +0 -56
  90. package/dist/tools/basic/gsheets_duplicate_sheet.js +0 -72
  91. package/dist/tools/basic/gsheets_insert_columns.js +0 -69
  92. package/dist/tools/basic/gsheets_insert_rows.js +0 -69
  93. package/dist/tools/basic/gsheets_list_sheets.js +0 -53
  94. package/dist/tools/basic/gsheets_read.js +0 -120
  95. package/dist/tools/basic/gsheets_rename_sheet.js +0 -64
  96. package/dist/tools/charts/gsheets_add_bubble.js +0 -176
  97. package/dist/tools/charts/gsheets_add_candlestick.js +0 -192
  98. package/dist/tools/charts/gsheets_add_chart.js +0 -162
  99. package/dist/tools/charts/gsheets_add_combo.js +0 -169
  100. package/dist/tools/charts/gsheets_add_histogram.js +0 -143
  101. package/dist/tools/charts/gsheets_add_org_chart.js +0 -160
  102. package/dist/tools/charts/gsheets_add_treemap.js +0 -177
  103. package/dist/tools/charts/gsheets_add_waterfall.js +0 -155
  104. package/dist/tools/charts/gsheets_delete_chart.js +0 -56
  105. package/dist/tools/charts/gsheets_update_chart.js +0 -118
  106. package/dist/tools/data/gsheets_append_data.js +0 -68
  107. package/dist/tools/data/gsheets_batch_clear.js +0 -53
  108. package/dist/tools/data/gsheets_batch_update.js +0 -81
  109. package/dist/tools/data/gsheets_clear_data.js +0 -53
  110. package/dist/tools/data/gsheets_create_filter.js +0 -81
  111. package/dist/tools/data/gsheets_find_replace.js +0 -124
  112. package/dist/tools/data/gsheets_set_data_validation.js +0 -153
  113. package/dist/tools/data/gsheets_sort_range.js +0 -102
  114. package/dist/tools/data/gsheets_update_cell.js +0 -44
  115. package/dist/tools/formatting/gsheets_auto_resize.js +0 -75
  116. package/dist/tools/formatting/gsheets_format_cells.js +0 -161
  117. package/dist/tools/formatting/gsheets_freeze_columns.js +0 -67
  118. package/dist/tools/formatting/gsheets_freeze_rows.js +0 -67
  119. package/dist/tools/formatting/gsheets_merge_cells.js +0 -85
  120. package/dist/tools/formatting/gsheets_set_number_format.js +0 -116
  121. package/dist/tools/formatting/gsheets_unmerge_cells.js +0 -79
  122. package/dist/tools/formatting/gsheets_update_borders.js +0 -212
  123. package/dist/tools/gdrive/gdrive_read_file.js +0 -77
  124. package/dist/tools/gdrive/gdrive_search.js +0 -71
  125. package/dist/tools/gdrive_read_file.js +0 -77
  126. package/dist/tools/gdrive_search.js +0 -71
  127. package/dist/tools/gsheets_add_bubble.js +0 -176
  128. package/dist/tools/gsheets_add_candlestick.js +0 -192
  129. package/dist/tools/gsheets_add_chart.js +0 -162
  130. package/dist/tools/gsheets_add_combo.js +0 -169
  131. package/dist/tools/gsheets_add_conditional_format.js +0 -175
  132. package/dist/tools/gsheets_add_histogram.js +0 -143
  133. package/dist/tools/gsheets_add_named_range.js +0 -87
  134. package/dist/tools/gsheets_add_org_chart.js +0 -160
  135. package/dist/tools/gsheets_add_protected_range.js +0 -127
  136. package/dist/tools/gsheets_add_sheet.js +0 -65
  137. package/dist/tools/gsheets_add_treemap.js +0 -177
  138. package/dist/tools/gsheets_add_waterfall.js +0 -155
  139. package/dist/tools/gsheets_append_data.js +0 -68
  140. package/dist/tools/gsheets_auto_resize.js +0 -75
  141. package/dist/tools/gsheets_batch_clear.js +0 -53
  142. package/dist/tools/gsheets_batch_update.js +0 -81
  143. package/dist/tools/gsheets_clear_data.js +0 -53
  144. package/dist/tools/gsheets_copy_sheet.js +0 -56
  145. package/dist/tools/gsheets_copy_to.js +0 -113
  146. package/dist/tools/gsheets_create_filter.js +0 -81
  147. package/dist/tools/gsheets_create_spreadsheet.js +0 -88
  148. package/dist/tools/gsheets_delete_chart.js +0 -56
  149. package/dist/tools/gsheets_delete_columns.js +0 -69
  150. package/dist/tools/gsheets_delete_named_range.js +0 -56
  151. package/dist/tools/gsheets_delete_protected_range.js +0 -56
  152. package/dist/tools/gsheets_delete_rows.js +0 -69
  153. package/dist/tools/gsheets_delete_sheet.js +0 -56
  154. package/dist/tools/gsheets_duplicate_sheet.js +0 -72
  155. package/dist/tools/gsheets_find_replace.js +0 -124
  156. package/dist/tools/gsheets_format_cells.js +0 -161
  157. package/dist/tools/gsheets_freeze_columns.js +0 -67
  158. package/dist/tools/gsheets_freeze_rows.js +0 -67
  159. package/dist/tools/gsheets_insert_columns.js +0 -69
  160. package/dist/tools/gsheets_insert_rows.js +0 -69
  161. package/dist/tools/gsheets_list_sheets.js +0 -53
  162. package/dist/tools/gsheets_merge_cells.js +0 -85
  163. package/dist/tools/gsheets_read.js +0 -120
  164. package/dist/tools/gsheets_rename_sheet.js +0 -64
  165. package/dist/tools/gsheets_set_data_validation.js +0 -153
  166. package/dist/tools/gsheets_set_number_format.js +0 -116
  167. package/dist/tools/gsheets_sort_range.js +0 -102
  168. package/dist/tools/gsheets_unmerge_cells.js +0 -79
  169. package/dist/tools/gsheets_update_borders.js +0 -212
  170. package/dist/tools/gsheets_update_cell.js +0 -44
  171. package/dist/tools/gsheets_update_chart.js +0 -118
  172. package/dist/tools/gsheets_update_named_range.js +0 -112
  173. package/dist/tools/gsheets_update_protected_range.js +0 -110
  174. package/dist/tools/protection/gsheets_add_conditional_format.js +0 -175
  175. package/dist/tools/protection/gsheets_add_named_range.js +0 -87
  176. package/dist/tools/protection/gsheets_add_protected_range.js +0 -127
  177. package/dist/tools/protection/gsheets_delete_named_range.js +0 -56
  178. package/dist/tools/protection/gsheets_delete_protected_range.js +0 -56
  179. package/dist/tools/protection/gsheets_update_named_range.js +0 -112
  180. package/dist/tools/protection/gsheets_update_protected_range.js +0 -110
  181. /package/dist/tools/drive/{drive_read_file.js → basic/drive_read_file.js} +0 -0
  182. /package/dist/tools/drive/{drive_search.js → basic/drive_search.js} +0 -0
package/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # MCP Server - Google Workspace
2
2
 
3
- **The most comprehensive MCP server for Google Workspace** - Complete programmatic control over Sheets, Drive, and future Docs, Calendar, Forms integration.
3
+ **The most comprehensive MCP server for Google Workspace** - Complete programmatic control over Sheets, Docs, Drive, Gmail, Calendar, and future Forms integration.
4
4
 
5
- 🚀 **Current Status**: 59 tools (Drive: 2, Sheets: 57)
6
- 📅 **Roadmap**: Google Docs, Calendar, Forms, Gmail, Slides
5
+ 🚀 **Current Status**: 130 tools (Drive: 21, Sheets: 57, Docs: 23, Gmail: 11, Calendar: 18)
6
+ 📅 **Roadmap**: Forms, Slides
7
7
 
8
8
  Extended implementation by Alanse inc.
9
9
 
@@ -11,14 +11,124 @@ Extended implementation by Alanse inc.
11
11
 
12
12
  ## 🚀 Features
13
13
 
14
- ### 📊 Extended Google Sheets API Implementation
14
+ ### 📊 Extended Google Workspace API Implementation
15
15
 
16
- **59 Total Tools** = 2 GDrive + **57 Google Sheets** operations
16
+ **130 Total Tools** = **21 Google Drive** + **57 Google Sheets** + **23 Google Docs** + **11 Gmail** + **18 Calendar** operations
17
17
 
18
18
  #### Tool Categories
19
19
 
20
- **Google Drive Operations (2 tools)**
21
- - Search & File Management
20
+ **Google Drive Operations (21 tools)**
21
+
22
+ #### Basic Operations (4 tools)
23
+
24
+ - Search Files (Advanced Query Support)
25
+ - Read File Contents
26
+ - List Files (Filter, Pagination, Sorting)
27
+ - Get File Metadata
28
+
29
+ #### File Operations (7 tools)
30
+
31
+ - Upload File
32
+ - Create File
33
+ - Delete File (Move to Trash)
34
+ - Copy File
35
+ - Move File
36
+ - Rename File
37
+ - Update File Content
38
+
39
+ #### Folder Management (3 tools)
40
+
41
+ - Create Folder
42
+ - List Folder Contents
43
+ - Move File to Folder
44
+
45
+ #### Permissions Management (4 tools)
46
+
47
+ - Share File (User/Group/Domain/Anyone)
48
+ - List File Permissions
49
+ - Update Permission Role
50
+ - Remove Permission
51
+
52
+ #### Advanced Operations (3 tools)
53
+
54
+ - Export File (Google Workspace Docs to PDF/DOCX/etc)
55
+ - List File Revisions
56
+ - Empty Trash
57
+
58
+ **Gmail Operations (11 tools)**
59
+
60
+ #### Basic Operations (4 tools)
61
+
62
+ - List Labels, Search Messages, Get Message, Get Thread
63
+
64
+ #### Label Management (2 tools)
65
+
66
+ - Modify Labels (Add/Remove), Manage Labels (Create/Update/Delete)
67
+
68
+ #### Send Operations (2 tools)
69
+
70
+ - Send Message (Plain/HTML with CC/BCC), Draft Message
71
+
72
+ #### Batch Operations (3 tools)
73
+
74
+ - Get Messages Batch, Get Threads Batch, Batch Modify Labels
75
+
76
+ **Google Calendar Operations (18 tools)**
77
+
78
+ #### Basic Event Operations (5 tools)
79
+
80
+ - List Events (Time range, search, pagination)
81
+ - Get Event (Full event details)
82
+ - Create Event (Title, time, location, attendees, Google Meet)
83
+ - Update Event (Modify any event properties)
84
+ - Delete Event (Remove with notifications)
85
+
86
+ #### Advanced Event Operations (3 tools)
87
+
88
+ - Quick Add Event (Natural language: "Meeting tomorrow at 2pm")
89
+ - List Event Instances (Recurring event occurrences)
90
+ - Move Event (Transfer between calendars)
91
+
92
+ #### Calendar List Operations (2 tools)
93
+
94
+ - List Calendars (User's calendar list with access roles)
95
+ - Get Calendar from List (Detailed calendar information)
96
+
97
+ #### Calendar Management (3 tools)
98
+
99
+ - Create Calendar (New secondary calendar)
100
+ - Get Calendar Metadata (Calendar details and settings)
101
+ - Update Calendar (Modify title, description, timezone)
102
+
103
+ #### Access Control (2 tools)
104
+
105
+ - List ACL Rules (View sharing settings)
106
+ - Add ACL Rule (Share calendar with users/groups/domains)
107
+
108
+ #### Utility Operations (3 tools)
109
+
110
+ - Get Color Palette (Available calendar/event colors)
111
+ - Query Free/Busy (Check availability across calendars)
112
+ - List Settings (User's Calendar preferences)
113
+
114
+ **Google Docs Operations (23 tools)**
115
+
116
+ **Basic Operations (4 tools)**
117
+ - Create, Read, Get Metadata, List Documents
118
+
119
+ **Content & Formatting (10 tools)**
120
+ - Insert/Update/Delete/Replace/Append Text
121
+ - Format Text (Bold, Italic, Font, Color)
122
+ - Create Headings (H1-H6)
123
+ - Create Lists (Bulleted/Numbered)
124
+ - Set Paragraph Alignment & Apply Styles
125
+
126
+ **Elements & Advanced (9 tools)**
127
+ - Insert Images, Tables, Page Breaks, Links
128
+ - Insert Table of Contents
129
+ - Batch Update Operations
130
+ - Merge Documents, Export to PDF/DOCX/HTML
131
+ - Suggestion Mode
22
132
 
23
133
  **Sheet Management (13 tools)**
24
134
  - Create, Read, List, Add, Delete, Rename Sheets
@@ -72,8 +182,11 @@ The server provides access to Google Drive files:
72
182
  1. [Create a new Google Cloud project](https://console.cloud.google.com/projectcreate)
73
183
  2. [Enable the Google Drive API](https://console.cloud.google.com/workspace-api/products)
74
184
  3. [Configure an OAuth consent screen](https://console.cloud.google.com/apis/credentials/consent) ("internal" is fine for testing)
75
- 4. Add OAuth scopes `https://www.googleapis.com/auth/drive.readonly`, `https://www.googleapis.com/auth/spreadsheets`
76
- 5. In order to allow interaction with sheets and docs you will also need to enable the [Google Sheets API](https://console.cloud.google.com/apis/api/sheets.googleapis.com/) and [Google Docs API](https://console.cloud.google.com/marketplace/product/google/docs.googleapis.com) in your workspaces Enabled API and Services section.
185
+ 4. Add OAuth scopes:
186
+ - `https://www.googleapis.com/auth/drive` (for Drive file operations - read & write)
187
+ - `https://www.googleapis.com/auth/spreadsheets` (for Sheets operations)
188
+ - `https://www.googleapis.com/auth/gmail.modify` (for Gmail operations)
189
+ 5. In order to allow interaction with sheets and docs you will also need to enable the [Google Sheets API](https://console.cloud.google.com/apis/api/sheets.googleapis.com/), [Google Docs API](https://console.cloud.google.com/marketplace/product/google/docs.googleapis.com), and [Gmail API](https://console.cloud.google.com/apis/api/gmail.googleapis.com) in your workspaces Enabled API and Services section.
77
190
  6. [Create an OAuth Client ID](https://console.cloud.google.com/apis/credentials/oauthclient) for application type "Desktop App"
78
191
  7. Download the JSON file of your client's OAuth keys
79
192
  8. Rename the key file to `gcp-oauth.keys.json` and place into the path you specify with `GWORKSPACE_CREDS_DIR` (i.e. `/Users/username/.config/mcp-google-workspace`)
@@ -133,27 +246,147 @@ Replace `<YOUR_CLIENT_ID>`, `<YOUR_CLIENT_SECRET>`, and `/path/to/config/directo
133
246
 
134
247
  ## 📈 Project Status
135
248
 
136
- ✅ **Phase 1-12 Complete** (2026-01-06)
137
- - **59 Tools Implemented** (57 Sheets + 2 GDrive)
138
- - **155 Tests** (100% Pass Rate)
249
+ ✅ **Complete** (2026-01-06)
250
+
251
+ - **112 Tools Implemented** (21 Drive + 57 Sheets + 23 Docs + 11 Gmail)
252
+ - **268+ Tests** (100% Pass Rate)
139
253
  - **Production Ready**
140
254
 
141
255
  ## 🗺️ Roadmap
142
256
 
143
- ### Current: Google Sheets & Drive
257
+ ### Completed
144
258
 
145
- - ✅ **Google Drive**: 2 tools (Search, Read)
259
+ - ✅ **Google Drive**: 21 tools (File operations, folder management, permissions, advanced features)
146
260
  - ✅ **Google Sheets**: 57 tools (Complete API coverage)
261
+ - ✅ **Google Docs**: 23 tools (Document creation, editing, formatting, elements)
262
+ - ✅ **Gmail**: 11 tools (Labels, search, send, batch operations)
147
263
 
148
264
  ### Coming Soon
149
265
 
150
- - 📝 **Google Docs**: Document creation, editing, formatting (~15-20 tools)
151
266
  - 📅 **Google Calendar**: Event management, scheduling (~10-15 tools)
152
267
  - 📋 **Google Forms**: Form creation, response management (~10-15 tools)
153
- - 📧 **Gmail**: Email operations, thread management (~10-15 tools)
154
268
  - 🎬 **Google Slides**: Presentation creation, editing (~15-20 tools)
155
269
 
156
- **Goal**: 100+ tools covering the entire Google Workspace ecosystem
270
+ **Goal**: 150+ tools covering the entire Google Workspace ecosystem
271
+
272
+ ## 🛠️ Development
273
+
274
+ ### Prerequisites
275
+
276
+ - Node.js 20 or higher
277
+ - npm or pnpm
278
+ - Google Cloud Platform account with OAuth credentials
279
+
280
+ ### Local Development
281
+
282
+ ```bash
283
+ # Clone the repository
284
+ git clone https://github.com/alanse-inc/mcp-server-google-workspace.git
285
+ cd mcp-server-google-workspace
286
+
287
+ # Install dependencies
288
+ npm install
289
+
290
+ # Build the project
291
+ npm run build
292
+
293
+ # Run tests
294
+ npm test
295
+
296
+ # Watch mode for development
297
+ npm run watch
298
+ ```
299
+
300
+ ### Testing
301
+
302
+ The project uses [Vitest](https://vitest.dev/) for unit testing:
303
+
304
+ ```bash
305
+ # Run all tests
306
+ npm test
307
+
308
+ # Watch mode
309
+ npm run test:watch
310
+
311
+ # UI mode
312
+ npm run test:ui
313
+
314
+ # Coverage report
315
+ npm run test:coverage
316
+ ```
317
+
318
+ ### Interactive Testing with MCP Inspector
319
+
320
+ [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) is the official debugging tool for MCP servers. It provides an interactive interface to test all 130 tools in real-time.
321
+
322
+ **Launch Inspector:**
323
+
324
+ ```bash
325
+ npm run inspect
326
+ ```
327
+
328
+ This opens a browser interface where you can:
329
+
330
+ - 🔍 **Browse all 130 tools** - View complete tool schemas and descriptions
331
+ - ⚡ **Test tools interactively** - Execute any tool with custom parameters
332
+ - 📊 **Monitor responses** - See real-time responses and error messages
333
+ - 🐛 **Debug issues** - View server logs and notifications
334
+ - 🧪 **Test edge cases** - Try invalid inputs and concurrent operations
335
+
336
+ **Example workflow:**
337
+
338
+ 1. Start the inspector: `npm run inspect`
339
+ 2. Navigate to the **Tools** tab
340
+ 3. Select a tool (e.g., `calendar_create_event`)
341
+ 4. Fill in the parameters (summary, startTime, endTime)
342
+ 5. Click **Execute** to test the tool
343
+ 6. View the response and verify the behavior
344
+
345
+ **Recommended for:**
346
+
347
+ - Testing new Calendar API tools
348
+ - Verifying OAuth authentication flow
349
+ - Debugging API errors and edge cases
350
+ - Exploring available tools before integration
351
+
352
+ ### Release Process
353
+
354
+ This project uses [release-please](https://github.com/googleapis/release-please) for automated releases.
355
+
356
+ **How it works:**
357
+
358
+ 1. Follow [Conventional Commits](https://www.conventionalcommits.org/) specification for commit messages
359
+ 2. When commits are merged to `main`, release-please creates/updates a release PR
360
+ 3. Merging the release PR triggers:
361
+ - CHANGELOG.md update
362
+ - Version bump in package.json
363
+ - GitHub Release creation
364
+ - npm package publication
365
+
366
+ **Commit message format:**
367
+
368
+ ```text
369
+ feat: add new feature
370
+ fix: fix a bug
371
+ docs: update documentation
372
+ chore: update dependencies
373
+ refactor: code refactoring
374
+ test: add tests
375
+ ```
376
+
377
+ **Example workflow:**
378
+
379
+ ```bash
380
+ # Make changes
381
+ git checkout -b feature/new-tool
382
+ # ... make changes ...
383
+ git commit -m "feat: add gdocs_insert_table tool"
384
+ git push origin feature/new-tool
385
+
386
+ # Create PR and merge to main
387
+ # → release-please creates a release PR automatically
388
+ # → Merge the release PR to publish
389
+ ```
157
390
 
158
391
  ## 📄 License
159
392
 
package/dist/auth.js CHANGED
@@ -5,6 +5,12 @@ import path from "path";
5
5
  export const SCOPES = [
6
6
  "https://www.googleapis.com/auth/drive.readonly",
7
7
  "https://www.googleapis.com/auth/spreadsheets",
8
+ "https://www.googleapis.com/auth/documents",
9
+ "https://www.googleapis.com/auth/gmail.readonly",
10
+ "https://www.googleapis.com/auth/gmail.send",
11
+ "https://www.googleapis.com/auth/gmail.modify",
12
+ "https://www.googleapis.com/auth/gmail.labels",
13
+ "https://www.googleapis.com/auth/calendar",
8
14
  ];
9
15
  // Get credentials directory from environment variable or use default
10
16
  const CREDS_DIR = process.env.GWORKSPACE_CREDS_DIR ||
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import { tools } from "./tools/index.js";
9
9
  const drive = google.drive("v3");
10
10
  const server = new Server({
11
11
  name: "@alanse/mcp-server-google-workspace",
12
- version: "0.2.1",
12
+ version: "0.2.2",
13
13
  }, {
14
14
  capabilities: {
15
15
  resources: {
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Google Calendar Helper Functions
3
+ *
4
+ * Utilities for Google Calendar API operations including:
5
+ * - Event formatting and display
6
+ * - Date/time parsing and formatting
7
+ * - Calendar URL generation
8
+ * - Free/busy data formatting
9
+ * - Attendee and recurrence handling
10
+ */
11
+ /**
12
+ * Format a single calendar event for display
13
+ */
14
+ export function formatEvent(event, calendarId = "primary") {
15
+ const lines = [];
16
+ // Event ID and status
17
+ lines.push(`Event ID: ${event.id}`);
18
+ if (event.status) {
19
+ lines.push(`Status: ${event.status}`);
20
+ }
21
+ // Summary (title)
22
+ if (event.summary) {
23
+ lines.push(`Title: ${event.summary}`);
24
+ }
25
+ // Date and time
26
+ const { startFormatted, endFormatted } = formatDateTime(event);
27
+ lines.push(`Start: ${startFormatted}`);
28
+ lines.push(`End: ${endFormatted}`);
29
+ // Location
30
+ if (event.location) {
31
+ lines.push(`Location: ${event.location}`);
32
+ }
33
+ // Description
34
+ if (event.description) {
35
+ const desc = event.description.length > 200
36
+ ? event.description.substring(0, 200) + "..."
37
+ : event.description;
38
+ lines.push(`Description: ${desc}`);
39
+ }
40
+ // Attendees
41
+ if (event.attendees && event.attendees.length > 0) {
42
+ lines.push(`Attendees (${event.attendees.length}):`);
43
+ event.attendees.forEach((attendee) => {
44
+ const status = attendee.responseStatus || "needsAction";
45
+ const organizer = attendee.organizer ? " (organizer)" : "";
46
+ lines.push(` - ${attendee.email} [${status}]${organizer}`);
47
+ });
48
+ }
49
+ // Recurrence
50
+ if (event.recurrence && event.recurrence.length > 0) {
51
+ lines.push(`Recurrence: ${event.recurrence.join(", ")}`);
52
+ }
53
+ // Web link
54
+ if (event.htmlLink) {
55
+ lines.push(`Link: ${event.htmlLink}`);
56
+ }
57
+ // Conference data (Google Meet, Zoom, etc.)
58
+ if (event.conferenceData?.entryPoints) {
59
+ const meetLink = event.conferenceData.entryPoints.find((ep) => ep.entryPointType === "video");
60
+ if (meetLink?.uri) {
61
+ lines.push(`Meeting Link: ${meetLink.uri}`);
62
+ }
63
+ }
64
+ return lines.join("\n");
65
+ }
66
+ /**
67
+ * Format a list of calendar events
68
+ */
69
+ export function formatEventList(events, calendarId = "primary") {
70
+ if (!events || events.length === 0) {
71
+ return "No events found.";
72
+ }
73
+ const lines = [];
74
+ lines.push(`Found ${events.length} event(s):\n`);
75
+ events.forEach((event, index) => {
76
+ lines.push(`[${index + 1}] ${event.summary || "(No title)"}`);
77
+ const { startFormatted } = formatDateTime(event);
78
+ lines.push(` Time: ${startFormatted}`);
79
+ if (event.location) {
80
+ lines.push(` Location: ${event.location}`);
81
+ }
82
+ if (event.attendees) {
83
+ lines.push(` Attendees: ${event.attendees.length}`);
84
+ }
85
+ lines.push(` ID: ${event.id}`);
86
+ lines.push("");
87
+ });
88
+ return lines.join("\n");
89
+ }
90
+ /**
91
+ * Format event date/time for display
92
+ */
93
+ export function formatDateTime(event) {
94
+ let startFormatted = "Unknown";
95
+ let endFormatted = "Unknown";
96
+ let isAllDay = false;
97
+ // Check if all-day event
98
+ if (event.start?.date) {
99
+ startFormatted = event.start.date;
100
+ endFormatted = event.end?.date || event.start.date;
101
+ isAllDay = true;
102
+ }
103
+ else if (event.start?.dateTime) {
104
+ const startDate = new Date(event.start.dateTime);
105
+ const endDate = event.end?.dateTime ? new Date(event.end.dateTime) : startDate;
106
+ const options = {
107
+ year: "numeric",
108
+ month: "short",
109
+ day: "numeric",
110
+ hour: "2-digit",
111
+ minute: "2-digit",
112
+ timeZoneName: "short",
113
+ };
114
+ startFormatted = startDate.toLocaleString("en-US", options);
115
+ endFormatted = endDate.toLocaleString("en-US", options);
116
+ }
117
+ return { startFormatted, endFormatted, isAllDay };
118
+ }
119
+ /**
120
+ * Generate Google Calendar web URL for an event
121
+ */
122
+ export function generateCalendarWebUrl(eventId, calendarId = "primary") {
123
+ const encodedCalendarId = encodeURIComponent(calendarId);
124
+ const encodedEventId = encodeURIComponent(eventId);
125
+ return `https://calendar.google.com/calendar/u/0/r/eventedit/${encodedEventId}?calendarId=${encodedCalendarId}`;
126
+ }
127
+ /**
128
+ * Format free/busy query response
129
+ */
130
+ export function formatFreeBusyResponse(response) {
131
+ const lines = [];
132
+ if (!response.calendars) {
133
+ return "No calendar data available.";
134
+ }
135
+ Object.entries(response.calendars).forEach(([calendarId, calendarData]) => {
136
+ lines.push(`\nCalendar: ${calendarId}`);
137
+ if (calendarData.errors && calendarData.errors.length > 0) {
138
+ lines.push(" Errors:");
139
+ calendarData.errors.forEach((error) => {
140
+ lines.push(` - ${error.reason}: ${error.domain}`);
141
+ });
142
+ }
143
+ if (calendarData.busy && calendarData.busy.length > 0) {
144
+ lines.push(` Busy periods (${calendarData.busy.length}):`);
145
+ calendarData.busy.forEach((period, index) => {
146
+ const start = period.start ? new Date(period.start).toLocaleString() : "Unknown";
147
+ const end = period.end ? new Date(period.end).toLocaleString() : "Unknown";
148
+ lines.push(` ${index + 1}. ${start} - ${end}`);
149
+ });
150
+ }
151
+ else {
152
+ lines.push(" No busy periods - calendar is free!");
153
+ }
154
+ });
155
+ return lines.join("\n");
156
+ }
157
+ /**
158
+ * Parse ISO 8601 datetime or date string to appropriate format for Calendar API
159
+ */
160
+ export function parseDateTime(dateTimeStr) {
161
+ // Check if it's a date-only string (YYYY-MM-DD)
162
+ if (/^\d{4}-\d{2}-\d{2}$/.test(dateTimeStr)) {
163
+ return { date: dateTimeStr };
164
+ }
165
+ // Otherwise, treat as datetime
166
+ return { dateTime: dateTimeStr };
167
+ }
168
+ /**
169
+ * Format attendee list for API request
170
+ */
171
+ export function formatAttendees(emails) {
172
+ return emails.map((email) => ({
173
+ email: email.trim(),
174
+ }));
175
+ }
176
+ /**
177
+ * Validate event time range
178
+ */
179
+ export function validateTimeRange(startTime, endTime) {
180
+ try {
181
+ const start = new Date(startTime);
182
+ const end = new Date(endTime);
183
+ if (isNaN(start.getTime())) {
184
+ return { valid: false, error: "Invalid start time format" };
185
+ }
186
+ if (isNaN(end.getTime())) {
187
+ return { valid: false, error: "Invalid end time format" };
188
+ }
189
+ if (end <= start) {
190
+ return { valid: false, error: "End time must be after start time" };
191
+ }
192
+ return { valid: true };
193
+ }
194
+ catch (error) {
195
+ return { valid: false, error: "Error parsing time range" };
196
+ }
197
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * DocumentIdResolver - Resolves various document ID formats across Google Workspace
3
+ *
4
+ * Supports:
5
+ * - Direct document IDs
6
+ * - Full Google Workspace URLs (Docs, Sheets, Slides, Drive)
7
+ * - Service type detection
8
+ */
9
+ export class DocumentIdResolver {
10
+ static URL_PATTERNS = {
11
+ docs: /docs\.google\.com\/document\/d\/([a-zA-Z0-9-_]+)/,
12
+ sheets: /docs\.google\.com\/spreadsheets\/d\/([a-zA-Z0-9-_]+)/,
13
+ slides: /docs\.google\.com\/presentation\/d\/([a-zA-Z0-9-_]+)/,
14
+ drive: /drive\.google\.com\/file\/d\/([a-zA-Z0-9-_]+)/,
15
+ };
16
+ static ID_PATTERN = /^[a-zA-Z0-9-_]{25,}$/;
17
+ /**
18
+ * Resolve a document reference from ID or URL
19
+ */
20
+ static resolve(input) {
21
+ // Try URL extraction first
22
+ const fromUrl = this.extractFromUrl(input);
23
+ if (fromUrl) {
24
+ return { id: fromUrl.id, type: fromUrl.type, url: input };
25
+ }
26
+ // Validate as direct ID
27
+ if (this.validate(input)) {
28
+ return { id: input, type: "unknown" };
29
+ }
30
+ throw new Error(`Invalid document reference: ${input}. Expected a Google Workspace URL or document ID.`);
31
+ }
32
+ /**
33
+ * Extract document ID from Google Workspace URL
34
+ */
35
+ static extractFromUrl(url) {
36
+ for (const [type, pattern] of Object.entries(this.URL_PATTERNS)) {
37
+ const match = url.match(pattern);
38
+ if (match) {
39
+ return {
40
+ id: match[1],
41
+ type: type,
42
+ };
43
+ }
44
+ }
45
+ return null;
46
+ }
47
+ /**
48
+ * Validate document ID format
49
+ */
50
+ static validate(id, type) {
51
+ if (!this.ID_PATTERN.test(id)) {
52
+ return false;
53
+ }
54
+ // Additional type-specific validation could go here
55
+ return true;
56
+ }
57
+ /**
58
+ * Get service type from URL or ID
59
+ */
60
+ static getServiceType(input) {
61
+ const ref = this.resolve(input);
62
+ return ref.type;
63
+ }
64
+ /**
65
+ * Create a Google Workspace URL from document ID and type
66
+ */
67
+ static createUrl(documentId, type) {
68
+ const urlTemplates = {
69
+ docs: `https://docs.google.com/document/d/${documentId}/edit`,
70
+ sheets: `https://docs.google.com/spreadsheets/d/${documentId}/edit`,
71
+ slides: `https://docs.google.com/presentation/d/${documentId}/edit`,
72
+ drive: `https://drive.google.com/file/d/${documentId}/view`,
73
+ };
74
+ return urlTemplates[type];
75
+ }
76
+ }