Skip to content
← Studio Dailiestools · ai · build

One Claude, all my inboxes

Claude's Gmail connector sees one inbox at a time. So I built a small, read-only server on my laptop that searches all of them — plus the prompt to build your own.

Envelopes in the row, highlighting one in orange.

I have more than one Gmail account, plus a few company ones, and I wanted Claude to search all of them at once. The built-in connector handles one account at a time, so I built a small MCP server that runs on my own machine. Now there are mcps people have made, but trusting anyone with your emails credentials is not a good idea. I wanted something local and secure.

What it does

Three tools, nothing else:

  • list_accounts: shows which addresses are connected
  • search_emails: searches one account or all of them, using the same search syntax as the Gmail search bar (from:, is:unread, newer_than:7d)
  • get_email: opens one message as plain text

So I can ask “find the invoice from last March” and it checks every inbox, with each result labelled by account.

Why local, why read-only

The only permission it asks Google for is gmail.readonly. It can't send, change or delete anything, even if I asked it to.

There's no hosted service or third-party database in between. Claude starts the server on my laptop, and requests go straight from my laptop to Google's API and back.

How it works

  • Each account is connected through Google's normal sign-in page. The sign-in runs on 127.0.0.1 and uses PKCE and a state check, so the login code can't be intercepted or replayed.
  • Google returns a refresh token, which is saved to tokens/<email>.json. Only my user account can read that file.
  • Claude talks to the server over stdio, so no network port is opened.
  • When I search “all”, every account is searched in parallel. If one account's token has expired, the others still return results, and the error names the account to reconnect.

The whole thing is about 400 lines of TypeScript.

Set it up yourself

  1. Create a Google Cloud project and enable the Gmail API.
  2. Set up the OAuth consent screen. Leave it in Testing mode and add each Gmail address you want to connect as a test user.
  3. Create an OAuth client ID with the type Desktop app. Download the JSON and save it as credentials.json in the project folder.
  4. Have Claude Code build the server using the prompt below.
  5. Build it and connect your accounts. Run add-account once for each account.
npm install
npm run build
npm run add-account
  1. Add it to Claude Code:
claude mcp add gmail --scope user -- node /path/to/gmail-mcp/build/index.js

The prompt

Build a local MCP server in TypeScript (Node 18+) that gives Claude
read-only access to multiple Gmail accounts.

Requirements:
- Use @modelcontextprotocol/sdk over stdio, googleapis and zod.
  Nothing hosted.
- Request only the gmail.readonly scope.
- Tools:
  - list_accounts: returns the connected email addresses.
  - search_emails(account, query, max_results): account is an address
    or "all"; query uses Gmail search syntax; max_results defaults to
    10 per account. Return account, id, threadId, from, subject, date
    and snippet.
  - get_email(account, message_id): return headers and a plain-text
    body. Strip HTML and truncate bodies at 20,000 characters.
- For "all", search the accounts in parallel and label each result by
  account. If one account fails, return the other results plus an
  error for that account.
- Add an `npm run add-account` CLI that opens the browser for Google
  sign-in. Use a loopback redirect on 127.0.0.1 with a random port,
  PKCE and a state check. Request offline access so Google returns a
  refresh token. Get the address from the Gmail profile and save the
  token to tokens/<email>.json with 600 permissions. Running the
  command again adds another account.
- Read the OAuth client from credentials.json (a Desktop app client)
  in the project root. Resolve file paths from the project root, not
  the current directory.
- If a token is expired or revoked, return an error that tells me to
  rerun add-account for that address.
- Keep stdout for MCP protocol messages only. Send all logging to
  stderr.
- Add credentials.json and tokens/ to .gitignore.
- Write a README covering the Google Cloud setup, adding accounts,
  and connecting the server to Claude Code and Claude Desktop.

Things worth knowing first

  • Tokens expire after 7 days in Testing mode. Rerun add-account when that happens, or publish the app in Google Cloud to stop it.
  • No refresh token? That happens if you've already granted access. Remove the app at myaccount.google.com/permissions and sign in again.
  • Claude Desktop can't find node? This is common with nvm. Use the full path that which node prints.
  • Never commit credentials.json or tokens/.

What I ask it

  • “Any unread emails across all my accounts from this week?”
  • “Find the flight confirmation for October and tell me the departure time.”
  • “Which account did the Figma receipt go to?”

To disconnect an account, delete its token file or revoke access in your Google account settings.

It's a small project, but now one question checks every inbox I have.