×A read-only Gmail connector for Claude Code

A read-only Gmail connector for Claude Code

One OAuth scope, a refresh token in the Keychain, and email the agent treats as data. Also why this site has a privacy policy.

Claude Code’s Gmail connector is signed in to a different account. I wanted my personal inbox next to it, and I didn’t want an agent able to send, delete or change anything in it. personal-gmail-mcp is a small MCP server for that. Claude Code starts it over stdio on my Mac, and it talks to Google directly with my own OAuth client.

Read-only by construction

The only scope it ever asks for is gmail.readonly. That’s the boundary, not a prompt or a line in a tool description: Google won’t let the token send, delete, label or change mail, whatever the agent is asked to do. The tools follow from it:

Tool Does
get_profile the signed-in address and the message and thread counts
search_threads Gmail search syntax, newest first, paged
get_thread every message in a thread: headers, body as text, attachments
save_attachment saves one attachment to a local folder
list_labels the account’s labels, for label: searches

save_attachment writes to ~/Downloads/personal-gmail/<message id>/ with mode 600 and never overwrites a file.

Nothing hosted in between

There’s no hosted piece of my own. The server runs locally, and sign-in is a desktop OAuth flow with PKCE and a loopback state check. The refresh token lives in the macOS Keychain, not in a file. Mail is read when I ask for it and goes into that Claude Code session, which sends it to Anthropic to answer me and keeps it in the session history on my Mac, like anything else in the session.

Email is data

Every piece of email content comes back in fields marked data_text, and the agent is told to treat those as data, never as instructions. Email is the most obvious prompt-injection channel there is. Anyone can send me one.

The 7-day sign-in, and this site

While a Google OAuth app is in Testing, Google expires its sign-in after 7 days, so every week a tool call tells me to run npm run login again. Publishing the app lifts the limit, but Google won’t let you publish without a homepage and a privacy policy on a domain you own. That’s part of why mark-web.com exists. The app’s privacy policy is here.

The tests cover MIME and HTML parsing, the OAuth URL, PKCE and the loopback state check, token refresh, the tools against a fake Gmail API, safe attachment names, and the server over stdio.

All writing