A local Model Context Protocol (MCP) server that gives Claude read/write access to your Hey.com inbox via reverse-engineered web APIs.
mcp-hey has two moving parts: a Bun/TypeScript MCP server that exposes Hey tools over stdio, and a small Python helper that uses the system webview to capture session cookies at login. Everything runs locally — no cloud relay, no credentials stored, just session cookies on disk.
Heads up — unofficial API. Hey.com does not publish a public API; mcp-hey reverse-engineers its web endpoints and pairs them with browser-identical HTTP requests. Things can break without notice. The current documented surface lives in
docs/API.md.
- Read emails from Imbox, Feed, Paper Trail, Set Aside, and Reply Later
- Send and reply to email threads
- Search emails across boxes
- Organise mail (set aside, reply later, screen in/out, bubble up)
- Local SQLite cache for faster repeated reads and full-text search
- Lightweight — around 30 MB idle memory
- Browser-identical headers and TLS posture to avoid detection
- Runs entirely on your machine; stdio transport with no network exposure
- Bun 1.1 or later
- Python 3.10 or later (plus UV if you want to follow the Python tooling in
CLAUDE.md) - A Hey.com account
- Platform: developed and tested on macOS and Linux. Windows users will likely need WSL — pywebview's Windows backend is not currently exercised.
-
Clone this repository
git clone https://github.com/Sealjay/mcp-hey.git cd mcp-hey -
Install dependencies
bun install pip install -r auth/requirements.txt
-
First run — authenticate
bun run dev
The Python auth helper opens a system webview pointed at Hey.com. Log in as normal; the helper captures session cookies to
data/hey-cookies.json(permissions locked to600) and exits. The Bun process then keeps running as the MCP server waiting on stdio — pressCtrl+Conce auth has completed; your configured MCP client will launch its own instance from here on. Subsequent runs reuse the stored session until it expires.
All three clients use the same command/args shape. On macOS, you'll almost certainly need the absolute path to bun — see macOS: bun PATH below.
The quickest route is the CLI:
claude mcp add --transport stdio hey --scope user -- bun run /absolute/path/to/mcp-hey/src/index.tsThe server is available immediately in the current session.
Alternatively, add to .mcp.json at your project root (or ~/.claude.json for a user-scoped server):
{
"mcpServers": {
"hey": {
"type": "stdio",
"command": "bun",
"args": ["run", "/absolute/path/to/mcp-hey/src/index.ts"]
}
}
}If you edit the file directly, restart the Claude Code session to pick it up.
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
{
"mcpServers": {
"hey": {
"command": "bun",
"args": ["run", "/absolute/path/to/mcp-hey/src/index.ts"]
}
}
}Restart Claude Desktop. You should see hey listed as an available integration.
Add to ~/.cursor/mcp.json:
{
"mcpServers": {
"hey": {
"command": "bun",
"args": ["run", "/absolute/path/to/mcp-hey/src/index.ts"]
}
}
}Restart Cursor.
GUI apps (Claude Desktop, Cursor) and shells launched by Claude Code don't always inherit the PATH from your interactive terminal, so a Homebrew-installed bun may fail with spawn bun ENOENT or simply never connect. Fix by using the absolute path to bun in command:
- Apple Silicon Homebrew —
/opt/homebrew/bin/bun - Intel Homebrew —
/usr/local/bin/bun - Manual install — run
which bunin your terminal to find it
Example:
{
"mcpServers": {
"hey": {
"command": "/opt/homebrew/bin/bun",
"args": ["run", "/absolute/path/to/mcp-hey/src/index.ts"]
}
}
}| Component | Description |
|---|---|
| MCP server | Bun/TypeScript, stdio transport, ~30 MB idle memory |
| Auth helper | Python/pywebview, spawns on-demand for login via system webview |
| Cache | Local SQLite store for messages, threads, and search index |
| Communication | File-based session sharing via data/hey-cookies.json |
- MCP client (Claude Desktop / Cursor) launches
bun run src/index.tsover stdio. - On startup the server validates
data/hey-cookies.json. If missing or expired it spawnsauth/hey-auth.py, which opens Hey in a system webview and writes fresh cookies. - Tool calls hit Hey.com directly with browser-realistic headers; responses are parsed (HTML via
node-html-parser) and cached in SQLite. - Write operations fetch a fresh CSRF token before submitting.
mcp-hey/
src/
index.ts # MCP server entry point
hey-client.ts # HTTP client with cookie injection
session.ts # Session management and validation
errors.ts # Error classes and sanitisation
cache/ # SQLite cache (db, schema, messages, search)
tools/ # MCP tool implementations
read.ts # Reading and listing
send.ts # Send, reply, forward
organise.ts # Triage, labels, bubble up, etc.
http-helpers.ts # Shared CSRF retry and endpoint fallback
__tests__/ # Test suites
auth/
hey-auth.py # Python auth helper (pywebview)
requirements.txt
data/
hey-cookies.json # Session storage (gitignored, chmod 600)
docs/
API.md # Hey.com API surface documentation
TOOLS.md # MCP tool reference (41 tools)
41 tools grouped by function. See docs/TOOLS.md for parameters, return shapes, and error behaviour.
| Category | Tools |
|---|---|
| Read | hey_list_imbox, hey_imbox_summary, hey_list_feed, hey_list_paper_trail, hey_list_set_aside, hey_list_reply_later, hey_list_screener, hey_list_trash, hey_list_spam, hey_list_drafts, hey_read_email |
| Labels & Collections | hey_list_labels, hey_list_label_emails, hey_add_label, hey_remove_label, hey_list_collections, hey_list_collection_emails, hey_add_to_collection, hey_remove_from_collection |
| Send | hey_send_email, hey_reply, hey_forward |
| Triage | hey_set_aside, hey_unset_aside, hey_reply_later, hey_remove_reply_later, hey_mark_unseen, hey_trash, hey_restore, hey_spam, hey_not_spam, hey_ignore_thread, hey_unignore_thread |
| Bubble up | hey_bubble_up, hey_bubble_up_if_no_reply, hey_pop_bubble |
| Screener | hey_screen_in, hey_screen_in_by_id, hey_screen_out |
| Search | hey_search |
| Cache | hey_cache_status |
- No credentials are ever stored — only session cookies, written with
600permissions. - Authentication happens entirely inside Hey's own login page (system webview).
- All data stays on your machine. No telemetry is emitted by this project.
- MCP uses stdio transport — the server never opens a network listener.
- Session validity is checked on startup and before sensitive operations.
See SECURITY.md for how to report vulnerabilities.
- Prompt-injection risk: as with many MCP servers, this one is subject to the lethal trifecta. A malicious email arriving in your inbox could attempt to instruct Claude to exfiltrate other messages. Treat the tool surface accordingly and review risky actions before approving them.
- Unofficial API: Hey.com's frontend can change without notice and break things. Expect occasional breakage and check
docs/API.mdfor known deltas. - No real-time notifications: polling only.
- Attachment uploads are not yet supported.
- Single account per MCP server instance.
- Account risk: aggressive or abnormal access patterns could in theory trigger Hey's anti-abuse systems. The server respects
x-ratelimitheaders and backs off exponentially, but there are no guarantees.
- Auth webview does not open — confirm Python 3.10+ is on
PATHandpip install -r auth/requirements.txtsucceeded. On Linux ensure a webview backend is available (python -c "import webview"should not error). 401/403responses after weeks of use — your Hey session has expired. Deletedata/hey-cookies.jsonand runbun run devagain to re-auth.- Rate limits (
429) — the client respectsx-ratelimitheaders and backs off. If you see sustained 429s, reduce concurrent tool use or wait a few minutes. - MCP client can't launch the server —
argsmust be an absolute path, not relative. Ifbunitself fails withspawn bun ENOENT, see macOS:bunPATH. - Cookie name changed — Hey has renamed session cookies before (e.g.
_hey_session→session_token, seeCLAUDE.mdfor the log). If auth silently fails after a Hey update, capture fresh cookies and compare.
Contributions welcome via pull request. Please:
- Use conventional commits (
feat,fix,docs,refactor,test,perf,cicd,revert,WIP). - Run
bun run formatandbun run lintbefore pushing. - Ensure
bun testpasses. - Update
docs/API.mdif you discover or change any Hey.com API behaviour.
See CLAUDE.md for the full development workflow.
MIT Licence — see LICENCE.