batch-update-emails
Modify multiple emails labels/status. Returns: empty on success (no response body). Use when: bulk operations on many emails. Limit: 1000 IDs per request. For single: use update-email.
Read and change Google Calendar, Contacts and Gmail on one authorization — create events, edit contacts, send mail and relabel in bulk.
LABSCO SUMMARY
Because Calendar, Contacts and Gmail come through the same authorization, a request like "find a time with her and send the invite" does not cross a tool boundary — free/busy answers the first half and event creation the second. Two details are worth knowing before you plan around it: recurring events take an explicit scope, so an edit can hit one occurrence or the whole series on purpose, and Gmail search returns ids rather than content, so reading is always a second call.
A Google Workspace server covering three services through a single OAuth flow, with write access across all of them rather than read-only views.
A Google Cloud project of your own with the Calendar and People APIs enabled and an OAuth consent screen configured — External user type, with your own address added as a test user while it is in test mode. Create OAuth 2.0 credentials of type Desktop app; then either set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET directly, or point GOOGLE_OAUTH_CREDENTIALS at the downloaded JSON file. The redirect URI has to match http://localhost:3000/oauth2callback exactly. Run it with npx -y mcp-google over stdio, from the npm package mcp-google, currently 2.3.0. On first run a browser opens for you to grant Calendar, Contacts and Gmail permissions; the tokens are then stored with 0600 permissions and refreshed automatically, and GOOGLE_CALENDAR_MCP_TOKEN_PATH moves where they live.
One command plus credentials — npx mcp-google, then supply credentials
USE CASES
Check free/busy across the calendars involved, then create the event.
Update the event with the scope set to that single instance, leaving the rest of the series alone.
Search Gmail for the thread, then read the message in full with its headers and attachments.
Send with the message you are replying to named, so it lands in the same conversation.
Find the label id, then apply it across up to 1000 messages in a single batch update.
Look the person up, then update the fields that changed.
Counted once with only startup setup. Other versions, modes or optional credentials may expose a different list.
batch-update-emailsModify multiple emails labels/status. Returns: empty on success (no response body). Use when: bulk operations on many emails. Limit: 1000 IDs per request. For single: use update-email.
create-contactCreate new contact. Returns: created contact with resourceName, etag, metadata. Use when: adding new person to contacts. Note: returns new resourceName for future operations.
create-draftCreate unsent email draft. Returns: draft id and message. Use when: composing email for later editing/sending. Not for immediate send - use send-email instead.
create-eventCreate calendar event. Returns: created event with id, htmlLink, start, end, status. Use when: scheduling new appointments/meetings. Note: supports recurring events via recurrence.
create-labelCreate custom label. Returns: new label with id, name, type='user'. Use when: organizing emails with new categories. Note: can't create system labels.
delete-contactRemove contact permanently. Returns: empty on success. Use when: deleting person from contacts. Note: permanent deletion, use resourceName from list/get.
delete-emailMove email to trash or delete permanently. Returns: success status. Use when: removing emails. Default: trash (recoverable). Set permanent=true for unrecoverable deletion.
delete-eventRemove event from calendar. Returns: empty on success. Use when: canceling appointments. Note: permanent deletion, not recoverable.
delete-labelRemove custom label. Returns: empty on success. Use when: cleaning up unused labels. Note: can't delete system labels, emails keep label reference.
get-contactRetrieve one contact by resourceName. Returns: full contact with all requested fields. Use when: viewing detailed contact info. Note: resourceName format is 'people/c[ID]'.
get-emailRetrieve one email by messageId. Returns: full message with headers, body (plain/html), attachments metadata. Use when: reading email content after list-emails. Note: messageId from list-emails required.
get-freebusyCheck calendar availability. Returns: busy time blocks per calendar. Use when: finding available slots, scheduling across calendars. Note: only shows busy/free, not event details.
list-calendarsList user calendars. Returns: array of calendar objects with id, summary, accessRole, backgroundColor, primary. Use when: showing available calendars or finding calendar ID. Note: 'primary' for main calendar.
list-colorsGet color palette. Returns: event colors (1-11) and calendar colors with hex values. Use when: displaying color options for event/calendar styling. Note: colorId is string.
list-contactsList Google Contacts. Returns: array with resourceName, names, emailAddresses, phoneNumbers per contact. Use when: viewing contact list, searching by name. Note: use personFields to limit data.
list-emailsSearch emails in Gmail. Returns: array with id, threadId only (no content/labels). Use when: finding emails to get IDs for other operations. Note: retrieve full content with get-email per ID.
list-eventsList calendar events. Returns: array of event objects with id, summary, start, end, status, recurrence. Use when: viewing schedule, finding events. Note: supports batch (up to 50 calendars).
list-labelsList Gmail labels. Returns: array with id, name, type (system/user). Use when: showing folder structure, finding label IDs. Note: includes system labels like INBOX, SENT.
search-eventsSearch events by text. Returns: filtered array of events matching query in summary/description/location. Use when: finding specific events by keyword. Note: single calendar only.
send-draftSend saved draft. Returns: sent message with id, threadId, labelIds. Use when: sending previously created draft. Note: draft is deleted after sending.
send-emailSend new email or reply. Returns: sent message id and threadId. Use when: composing new email or replying to thread. For replies: provide replyToMessageId.
update-contactModify existing contact. Returns: updated contact with new etag. Use when: changing contact details. Note: requires updatePersonFields to specify what to update.
update-draftModify existing draft. Returns: updated draft with id, message. Use when: editing unsent draft content. Note: replaces entire draft content.
update-emailModify single email labels/status. Returns: updated message with new labelIds. Use when: marking one email read/unread/starred. For multiple: use batch-update-emails. Labels: UNREAD, STARRED, IMPORTANT, INBOX.
update-eventModify existing event. Returns: updated event with id, summary, start, end. Use when: rescheduling, changing details. Note: supports recurring event scopes (single/all/future).
update-labelModify label properties. Returns: updated label. Use when: renaming labels, changing visibility. Note: can't modify system labels.
BEFORE YOU INSTALL
26 tools when we connected. Setup lists only the Google Calendar and People APIs; the Gmail API must be enabled too, or all thirteen Gmail tools fail when called.
Both documented setups run the server on your machine.
CONTEXT COST
Rated by the size of the 26 tool definitions that ride along on every turn, not by how many there are
INSTALLATION
npx mcp-google{
"mcpServers": {
"google-workspace": {
"command": "npx",
"args": [
"-y",
"mcp-google"
],
"env": {
"GOOGLE_CLIENT_ID": "<YOUR_CLIENT_ID>.apps.googleusercontent.com",
"GOOGLE_CLIENT_SECRET": "<YOUR_GOOGLE_CLIENT_SECRET>"
}
}
}
}{
"mcpServers": {
"google-workspace": {
"command": "npx",
"args": [
"-y",
"mcp-google"
],
"env": {
"GOOGLE_OAUTH_CREDENTIALS": "<YOUR_PATH_TO_DOWNLOADED>/credentials.json"
}
}
}
}