Multiple Google accounts (Gmail, Calendar, Drive, Contacts, Tasks) in one Claude connector.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
π‘ Paste the JSON block into your client's configuration file under mcpServers, then restart the application.
A remote MCP server that gives Claude access to several Google accounts at once β Gmail, Calendar, Drive, Contacts and Tasks. Claude's built-in Google connectors each hold exactly one account; connecting a second replaces the first. This holds as many as you link, and every search tool fans out across all of them in a single call.
You run it yourself. It holds your Google tokens in your own database, encrypted, and talks to Google directly β nothing passes through a third party.
Node and Postgres, four tables, and no dependencies beyond Express, pg and
jsonwebtoken. Document text extraction β PDF, Word, Excel, PowerPoint,
OpenDocument β uses only Node's standard library.
Status: running in production against real mailboxes, with 435 automated checks. Built for one person's needs and published because the one-account limit is not unique to them. Treat it as working software with a small user base, not as a hardened product.
Then deploy it somewhere with a public HTTPS URL (Railway, Fly, Render, a VPS β anything that runs Node and reaches Postgres) and follow Setup.
| Method | Path | Description |
|---|---|---|
| POST | /mcp | MCP Streamable HTTP endpoint (Bearer auth) |
| GET | /mcp/oauth/authorize | Consent screen β operator password |
| POST | /mcp/oauth/token | Token + refresh grants |
| POST | /mcp/oauth/register | RFC 7591 dynamic client registration |
| GET | /.well-known/oauth-protected-resource | RFC 9728 discovery |
| GET | /.well-known/oauth-authorization-server | RFC 8414 discovery |
| GET | /gmail/connect | Link an account (repeat per account) |
| POST | /gmail/unlink | Unlink one, revoking the grant at Google |
Every tool takes an optional account. On a search, omitting it fans the call
out across every linked account and merges the results β the thing no
single-account connector can do. On a write it names the one account to act on,
so "create this event" is never ambiguous about whose calendar it lands in.
| Area | Tools | Notes |
|---|---|---|
| Accounts | list_accounts | Which accounts are linked, with token health |
| Search | search_messages, search_threads | Gmail query syntax, merged and date-sorted across accounts. search_threads returns one row per conversation β subject, every participant, message and unread counts, last activity β for "where does my thread with X stand" without pulling bodies |
| Read | get_message, get_thread, get_attachment | Bodies flattened to text and capped at 60 KB; attachment metadata included. get_attachment extracts text from PDF, Word, Excel, PowerPoint and OpenDocument attachments, so an emailed contract or invoice is readable directly; anything else comes back base64 (2 MB cap) |
| Send | send_message, reply_to_message, forward_message | Replies thread via In-Reply-To/References; forwards carry attachments (10 MB cap, skipped ones named) |
| Drafts | create_draft, list_drafts, get_draft, update_draft, send_draft, delete_draft | create_draft with reply_to_message_id drafts an in-thread reply for review β the safe path for AI-written mail |
| Labels | modify_labels, list_labels, create_label, update_label, delete_label | modify_labels takes message_id or thread_id; removing INBOX archives |
| Trash & spam | trash_message, untrash_message, mark_spam | All take message_id or thread_id; trash is recoverable for 30 days; mark_spam with unmark: true restores |
| Area | Tools | Notes |
|---|---|---|
| Read | list_calendars, list_events, search_events, get_event | list_events merges every linked calendar into one timeline, defaulting to the next 7 days; recurring series are expanded into actual occurrences, so a weekly standup appears on each day it happens |
| Write | create_event, update_event, delete_event | Times are ISO 8601; a bare YYYY-MM-DD means all-day. update_event patches β unmentioned fields keep their value. Attendees are not emailed unless send_updates says so |
| Repeats | create_event, update_event, delete_event | repeat: "weekly" (with repeat_count or repeat_until) covers the ordinary cases; recurrence takes full RFC 5545 rules. On a repeating event, scope chooses one occurrence or the whole series β see below |
| RSVP | respond_to_event | accepted / declined / tentative, as the account that was invited; notifies the organiser by default |
| Scheduling | suggest_time | Free slots across every linked calendar at once β busy anywhere means busy. Returns whole gaps rather than chopping a 3-hour opening into six half-hour slots |
| Area | Tools | Notes |
|---|---|---|
| Find | search_files, list_recent_files, get_file_metadata, list_shared_drives | Text search over names and contents, with optional raw Drive query syntax in filter. Covers My Drive and every shared drive at once; drive_id narrows to one. Trashed files excluded unless you ask for them |
| Read | read_file_content, download_file_content | Docs, Sheets and Slides exported (Sheets as CSV); PDF, Word, Excel, PowerPoint and OpenDocument extracted to text; ocr: true routes scans and images through Google's own conversion; include_comments returns the comment threads. download_file_content takes export_as β turn a Doc into a PDF or docx, a Sheet into xlsx. Text caps at 60 KB, binaries at 2 MB base64 |
| Write | create_file, update_file, copy_file | Text via content, binary via content_base64. convert_to makes Drive convert the upload into an editable Doc, Sheet or Slides β or a folder. update_file renames, moves and describes; overwriting contents additionally needs replace_content: true. On a file you do not own it edits a private copy β see below |
| Comment | comment_on_file | Leave a comment on a draft, or reply to a thread β the review path that changes nothing in the document |
| Sharing | get_file_permissions, share_file, unshare_file | Shares with one named person at reader/commenter/writer. Domain-wide and public-link sharing are off unless DRIVE_ALLOW_PUBLIC_SHARING=true, and then still need confirm_public. unshare_file withdraws access β by person, by domain, or by removing the public link |
| Remove | trash_file, untrash_file | Trash and restore, within the 30-day window β see the scope note below |
| Area | Tools | Notes |
|---|---|---|
| Contacts | search_contacts, list_contacts | Read-only. Searches saved contacts and people the account has corresponded with, so "email Ann" resolves to an address instead of a guess |
| Tasks | list_task_lists, list_tasks, create_task, update_task, delete_task | list_id defaults to the account's first list. update_task with completed: true ticks a task off; false reopens it. Google Tasks has no trash, so delete_task is permanent |
read_file_content and get_attachment both return text for PDF, Word, Excel,
PowerPoint and OpenDocument files, using only Node's standard library β no
parsing dependency to vendor, audit or keep current.
| Format | How | Notes |
|---|---|---|
| .docx / .odt | ZIP + XML | Paragraphs, tabs and line breaks preserved; styles and revision marks dropped |
| .xlsx / .ods | ZIP + XML | One CSV block per sheet, named from the workbook relationships. Cells are placed by column letter, so a gap stays a gap |
| .pptx / .odp | ZIP + XML | One block per slide, in presentation order |
| Content-stream parsing | Flate, ASCII85 and ASCIIHex filter chains; literal, hex and octal strings; positioning operators become line breaks |
Where it stops, and what happens then. Two kinds of PDF have no text to extract: a scan, which is a picture of a page, and one whose fonts are CID-keyed or subset, where the bytes in the content stream are glyph numbers that need the font's own tables to become letters. Both would decode into confident-looking nonsense, so the result is scored for readability and refused rather than returned β the refusal names the cause and points at the fix.
That fix is ocr: true on read_file_content, which copies the file as a Google
Doc (Drive runs OCR during that conversion), exports the text, and deletes the
copy in a finally block. It reads scans, photographs and images. Two things
worth knowing: it is the one place this server writes to Drive during a read, and
that delete is the only permanent delete in the whole server β its target is a
file created seconds earlier by that same call, never anything the user put
there. If the cleanup itself fails, the result says so and names the file.
Extraction is capped at 60 KB like every other body, with the cut flagged.
A shared drive is owned by an organisation rather than by a person, which is
where a company's actual documents live. Drive's own default hides them: a
files.list without corpora=allDrives searches only My Drive and files shared
directly with the account, and a request naming a file inside a shared drive
comes back 404 File not found unless it carries supportsAllDrives β an error
that reads as a wrong id rather than as a missing capability.
No reviews yet β be the first to share how this listing worked for you.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/grounders-mcp)<a href="https://allmcps.com/mcp/grounders-mcp"><img src="https://allmcps.com/api/badge/grounders-mcp?style=directory" alt="Grounders MCP on AllMCPs" /></a>