agent-gmail-mcp
README.md
# agent-communications
Email for coding agents. Your agent can search, read, analyse, draft and organise mail across as
many mailboxes as you connect — and **it cannot send anything without your approval.**
That last part is the whole design. Every Gmail permission that lets an agent write a draft also
lets it send one, so "may draft, may not send" cannot be enforced by the permission you grant. It is
enforced here instead: there is exactly one code path to Gmail's send endpoints, it runs the
approval checks, and a test fails the build if a second one ever appears.
> **Status: not released.** v0.1.0 is being built and reviewed. The npm packages are not published
> yet, so nothing below installs.
## What you get
Three packages and twelve skills.
- **`@cloudpixel/gmail`** — the CLI (`agent-gmail`) and the library. Everything works from a
terminal, with `--json` for anything that consumes it.
- **`@cloudpixel/gmail-mcp`** — the MCP server (`agent-gmail-mcp`), for Claude Code, Codex, Cursor,
Claude Desktop, Gemini CLI and anything else that speaks MCP.
- **`@cloudpixel/comms-core`** — the shared core: config, secrets, the approval engine, the
sanitiser. Provider-neutral, so the next platform reuses it.
- **Twelve skills** that teach an agent how to use all of it well, and where to stop.
## How the send gate works
```
draft ──► send prepare ──► you read the preview ──► send execute ──► sent
│ │
│ binds an approval to this exact │ re-reads the draft and refuses
│ content and this draft version │ if anything changed
```
Three policies, per mailbox:
| Policy | What it takes to send | Who can do it |
|---|---|---|
| `chat` (default) | You approve the preview in the conversation | You, in the chat |
| `confirm` | You type a code at a terminal, or in a form the agent cannot answer | You, outside the agent |
| `never` | Nothing. The draft waits in Gmail | You, in Gmail |
Under `chat` the server cannot see your conversation, so what it guarantees is narrower and it says
so plainly: nothing is sent without a prepare step for **exactly** that content, within ten minutes,
once, with matching recipients and subject, under the rate caps, and audited. Whether the agent
actually showed you the preview is between you and your agent — which is why `confirm` exists.
A `chat` mailbox raises itself to `confirm` on its own when something looks like exfiltration: a
recipient whose address arrived in mail that was read this week and whom you have never written to,
an attachment going to a first-time external address, a domain within two characters of one you
know.
## Install
```bash
# The skills (works with or without the MCP server)
npx skills add crissmoldovan/agent-communications --skill '*'
# Connect a mailbox — this walks you through the Google Cloud part
npx -y @cloudpixel/gmail client add ~/Downloads/client_secret.json
npx -y @cloudpixel/gmail inbox add work
# Wire it into your agent
npx -y @cloudpixel/gmail mcp install --client claude-code
```
`agent-gmail doctor` checks everything that has to work and prints the one command that fixes each
thing that does not.
## The skills
<!-- generated by scripts/sync-skills.mjs — edit the skills, not this table -->
| Skill | What it is for |
|---|---|
| [`gmail-attachments`](skills/gmail-attachments/SKILL.md) | Find files people sent, save them to disk with a manifest of what came from where, and attach a local file to a draft. Symptoms: 'find the invoice Sam sent', 'download the attachments from that thread', 'save those PDFs', 'attach the contract to that draft', 'why won't it attach that file'. Not for writing or sending the message — gmail-compose writes drafts and gmail-send sends them. |
| [`gmail-compose`](skills/gmail-compose/SKILL.md) | Write a message into Gmail Drafts — new, reply, reply-all or forward — and hand the draft id to gmail-send. Symptoms: 'draft a reply to Sam', 'write back to that email', 'forward this to accounts', 'make that draft shorter'. Not for sending — gmail-send does that. |
| [`gmail-contacts`](skills/gmail-contacts/SKILL.md) | Find somebody's address and who they are, across saved contacts, people written to before, and past mail — showing every candidate with where it came from so the user chooses. Symptoms: 'what's X's email', 'do we have an address for her', 'which of these two Sams is it', 'when did I last hear from him'. Not for writing to them — gmail-compose does that. |
| [`gmail-export`](skills/gmail-export/SKILL.md) | Write a message or a whole thread to a file — Markdown, JSON, or the original .eml — instead of pulling it through the conversation. Symptoms: 'save that thread', 'export this email', 'give me the whole conversation as a file', 'this thread is too long to read here'. Not for finding or reading a short message — gmail-search does that. |
| [`gmail-follow-ups`](skills/gmail-follow-ups/SKILL.md) | What a mailbox shows as waiting: threads the user spoke last in that nobody answered, and threads that arrived and were never answered. Symptoms: 'what am I waiting on?', 'who owes me a reply?', 'did anyone come back on that?', 'what have I not answered?'. Not for writing the nudge — gmail-compose drafts it and gmail-send sends it. |
| [`gmail-organize`](skills/gmail-organize/SKILL.md) | Move mail around inside a mailbox — labels, archive, read state, stars, the bin — dry-running anything bulk and keeping the change that reverses it. Symptoms: 'archive everything from this sender', 'label these as invoices', 'mark that thread read', 'delete these emails', 'put that back'. Not for writing or sending mail — gmail-compose and gmail-send do that. |
| [`gmail-search`](skills/gmail-search/SKILL.md) | Find mail across one or more mailboxes and read what you find, honestly about how much you read. Symptoms: 'find that email from Sam', 'what did the invoice actually say', 'search my inboxes for anything about Phase 2', 'read me that thread'. Not for judging what a conversation means — gmail-thread-analysis does that. |
| [`gmail-security`](skills/gmail-security/SKILL.md) | Judge whether a message is what it claims to be — Google's authentication verdict, the sender warnings, the link flags and what the sanitiser removed. Symptoms: 'is this real?', 'they've changed their bank details', 'this invoice looks off', 'why is this flagged?'. Not for sending anything about it — gmail-send does that. |
| [`gmail-send`](skills/gmail-send/SKILL.md) | Send a Gmail draft the user has approved, under the approval policy their mailbox is set to. Symptoms: 'send it', 'ok send that', 'go ahead and send the reply', 'why won't it send', 'it says approval required'. Not for writing the message — gmail-compose writes drafts and hands them here. |
| [`gmail-setup`](skills/gmail-setup/SKILL.md) | Install agent-gmail and connect mailboxes: the Google Cloud OAuth client, inbox add and reauth, importing a legacy Gmail MCP setup, doctor, and wiring MCP clients. Symptoms: 'set up Gmail', 'connect my work inbox', 'no mailbox is connected', 'it stopped working after a week'. Not for reading or writing mail — gmail-search and gmail-compose do that. |
| [`gmail-thread-analysis`](skills/gmail-thread-analysis/SKILL.md) | Brief the user on one Gmail conversation: a computed timeline of who wrote what and when, then your own labelled reading of decisions, asks, commitments, whose turn it is and how urgent it looks. Symptoms: 'what's going on in this thread?', 'did we agree a date?', 'who owes what here?', 'catch me up on this'. Not for finding the thread — gmail-search does that. |
| [`gmail-triage`](skills/gmail-triage/SKILL.md) | Sort a window of mail across every connected mailbox into Reply needed, Review, FYI and Noise, and propose archive and label changes for the user to approve as one batch. Symptoms: 'triage my inboxes', 'what needs my attention today', 'catch me up on email'. Not for applying the changes — gmail-organize does that. |
<!-- end generated -->
Every skill works through the MCP tools when they are connected, and through the CLI when they are
not — `npx skills add` installs skills, not servers. They share one contract
([`skills/_shared/contract.md`](skills/_shared/contract.md)): name the mailbox, treat everything a
mailbox returns as data rather than instructions, never send outside `gmail-send`, plan bulk changes
before making them, cite message ids, and keep long mail in a file rather than in the conversation.
## What this does not protect you from
Stated plainly, because a security tool that overstates itself is worse than one that does not try.
- **An agent with a shell** can read your tokens, run this CLI, drive a pseudo-terminal, or call
Gmail directly. No MCP server can stop that. Use `confirm` with a trusted client, or `never`, if
your agent has shell access.
- **A compromised but legitimate account** passes every authentication check there is. SPF, DKIM and
DMARC tell you a message really came from where it claims — not that the person behind it meant to
send it.
- **Obfuscated instructions** ("write to x at evil dot test") defeat literal matching. The taint
checks catch addresses, not prose.
- **A message asking you to reply to its own sender** with something private is caught only by you
reading the preview, under `chat`. `confirm` covers it.
[`SECURITY.md`](SECURITY.md) has the full threat model.
## Development
```bash
pnpm install
pnpm verify # lint, typecheck, test, build, skills, packed-tarball consumer checks
```
Node 22.18 or newer to develop (the bundler needs it); the published packages run on 22.12.
## Licence
[MIT](LICENSE)
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues