Skip to main content
Glama
elvisoliveira

gmail-mcp

README.md
# gmail-mcp

Exposes the Gmail tab open in your browser as MCP tools — no Gmail
API, no OAuth. A browser extension reads the inbox with
[InboxSDK](https://github.com/InboxSDK/InboxSDK) and acts on it by
simulating the Gmail UI; a local bridge relays commands from any MCP
client (e.g. Claude Code) to that tab.

```
MCP client (Claude)
   │ stdio
server/mcp.js        one per client session, forwards over HTTP
   │ POST /<command>  (Hono, port 8766)
server/bridge.js     single daemon
   │ WebSocket (port 8765)
extension            MV3, background ws client + content script
   │ InboxSDK / DOM
Gmail tab
```

## Tools

| Tool | What it does |
| --- | --- |
| `list_visible_emails` | Lists the thread rows currently rendered (subject, contacts, date, `thread_id`) |
| `archive_thread` | Archives a visible thread (row checkbox + toolbar button) |
| `label_thread` | Applies an existing label to a visible thread (row context menu) |

## Setup

1. **Extension**: `cd extension && npm install && npm run build`, then
   load `extension/dist/` via `chrome://extensions` → Developer mode →
   Load unpacked. Open (or reload) Gmail.
2. **Bridge**: `cd server && npm install && npm run bridge` — keep it
   running.
3. **MCP**: `claude mcp add gmail-mcp -- node <repo>/server/mcp.js`,
   then start a new session.

Test without an MCP client:

```
curl -X POST localhost:8766/list_visible_emails
curl -X POST localhost:8766/archive_thread -d '{"thread_id":"..."}'
```

## Limitations

- The Gmail tab must be open; only currently-rendered rows are
  visible to the tools.
- Actions simulate the UI: stable attributes are preferred
  (`act="7"`, roles), but `label_thread` matches menu text and
  assumes an English Gmail UI. A Gmail redesign can break actions —
  the durable alternative is the official Gmail API.
- The bridge listens on localhost without auth; anything local can
  drive your Gmail tab. Don't expose the ports.
- InboxSDK telemetry is disabled (`eventTracking` /
  `globalErrorLogging` off).

## Development

`npm run lint` / `npm run format` (Biome, 80 cols) from the repo
root. New extension feature = one file in `extension/src/features/` +
one line in `extension/src/content.js` + a tool in `server/mcp.js`.