npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ideadesignmedia/gmail-mcp

v0.1.7

Published

Private MCP server and CLI for linking multiple Gmail inboxes and operating over them

Readme

@ideadesignmedia/gmail-mcp

Private MCP server and CLI that links multiple Gmail inboxes and exposes tools over stdio. Tokens are stored in SQLite and can be encrypted-at-rest with a password. When locked, every command and the MCP server require a password to run.

  • Transport: stdio (suitable for MCP clients that launch a local command)
  • Default DB: ~/.idm/gmail-mcp/db.sqlite
  • Node requirement: >= 18.17

Run with npx (recommended)

You do not need to install anything globally. Use npx to run the CLI and server. On first run, npx will download the package; later runs use the cached copy.

Show help:

npx @ideadesignmedia/gmail-mcp --help

Add an account (loopback OAuth):

# Define or export your Google OAuth client credentials
export GOOGLE_CLIENT_ID=your_client_id
export GOOGLE_CLIENT_SECRET=your_client_secret

# Start the OAuth flow and link the Gmail account
npx -y @ideadesignmedia/gmail-mcp add \
  --client-id "$GOOGLE_CLIENT_ID" \
  --client-secret "$GOOGLE_CLIENT_SECRET"

# The CLI prints a URL; open it in your browser to consent.
# After consenting, the local callback will display "Authentication complete".

Add an account (device code flow; headless-safe):

export GOOGLE_CLIENT_ID=your_client_id
export GOOGLE_CLIENT_SECRET=your_client_secret

npx -y @ideadesignmedia/gmail-mcp add \
  --device \
  --client-id "$GOOGLE_CLIENT_ID" \
  --client-secret "$GOOGLE_CLIENT_SECRET"

Lock the database with a password:

npx -y @ideadesignmedia/gmail-mcp passwd --pass 'your-strong-pass'

Start the MCP server over stdio (for your MCP client to launch):

export GMAIL_MCP_DB_PASS='your-strong-pass'   # only required if the DB is locked
npx -y @ideadesignmedia/gmail-mcp start

Notes for npx usage:

  • -y auto-confirms the download prompt on first run.
  • You can pass --db /custom/path.sqlite to store the database elsewhere.
  • Use --read-only with start to disable write actions (send/label modify).

Quick start (end‑to‑end)

  1. Create a Google OAuth client (see "Google OAuth setup").

  2. Link one or more Gmail accounts:

export GOOGLE_CLIENT_ID=...
export GOOGLE_CLIENT_SECRET=...
npx -y @ideadesignmedia/gmail-mcp add --client-id "$GOOGLE_CLIENT_ID" --client-secret "$GOOGLE_CLIENT_SECRET"
  1. (Optional but recommended) Lock the DB with a password so tokens are encrypted at rest:
npx -y @ideadesignmedia/gmail-mcp passwd --pass 'your-strong-pass'
  1. Point your MCP client to run the server command. Most clients let you configure a command, arguments, and environment variables. An example configuration looks like:
{
  "command": "npx",
  "args": ["-y", "@ideadesignmedia/gmail-mcp", "start", "--read-only"],
  "env": { "GMAIL_MCP_DB_PASS": "your-strong-pass" }
}

Exact configuration format depends on your MCP client. The server speaks stdio.

  1. Use the tools provided by the server from your MCP client (see "MCP tools").

CLI reference

Global options (apply to all commands unless stated otherwise):

  • --db <path>: SQLite DB path (default ~/.idm/gmail-mcp/db.sqlite)
  • --pass <pass>: Database password or new password (also available via GMAIL_MCP_DB_PASS)
  • --read-only: Start server with write operations disabled (only used by start)

Commands:

# Start the MCP server over stdio
npx -y @ideadesignmedia/gmail-mcp start [--db <path>] [--pass <pass>] [--read-only]

# Link a Gmail account (loopback or device flow)
npx -y @ideadesignmedia/gmail-mcp add \
  [--db <path>] [--pass <pass>] \
  [--client-id <id>] [--client-secret <secret>] [--device] [--listen-port <port>]

# List linked accounts
npx -y @ideadesignmedia/gmail-mcp list [--db <path>] [--pass <pass>]

# Remove an account (by email or id)
npx -y @ideadesignmedia/gmail-mcp remove <email|id> [--db <path>] [--pass <pass>]

# Lock the DB, set password, or rotate existing password
npx -y @ideadesignmedia/gmail-mcp passwd [--db <path>] [--pass <new>] [--rotate] [--old-pass <old>] [--hint <text>]

Behavioral details:

  • When the DB is locked, all commands require a password (--pass or GMAIL_MCP_DB_PASS).
  • When unlocked, you can operate without a password and lock later with passwd.
  • passwd --rotate --old-pass <old> --pass <new> rotates the encryption KEK without re‑adding accounts.
  • start --read-only disables gmail-send_message and gmail-label_message tools and prevents modification APIs.

Google OAuth setup

Create a Web application OAuth client in Google Cloud Console and enable the Gmail API.

Loopback (default) flow requirements:

  • Authorized redirect URI: http://127.0.0.1:43112/oauth2/callback
  • The CLI prints the authorization URL; open it manually in your browser.
  • Scopes requested by this tool:
    • https://www.googleapis.com/auth/gmail.readonly
    • https://www.googleapis.com/auth/gmail.modify
    • https://www.googleapis.com/auth/gmail.send
    • openid, email, profile (used to fetch the account email/id on first link)

Device code flow (headless) requirements:

  • No redirect URI needed. You will be shown a verification URL and user code to enter in a browser.

Tips:

  • If you get no refresh_token, ensure access_type=offline and prompt=consent are set and you have not previously granted this client for the user. You can revoke previous grants at https://myaccount.google.com/permissions.

Environment variables

  • GMAIL_MCP_DB_PASS: Password for a locked DB (also accepted via --pass).
  • GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET: Used by add if flags are not provided.

MCP tools

The server exposes these tools. Tool names are prefixed with gmail.. Names and parameters are stable and validated with zod. Unless noted, responses mirror the Gmail REST API types.

  1. gmail-list_accounts
  • Input: {}
  • Output: { accounts: Array<{ id: string, email: string, displayName: string | null }> }
  1. gmail-search_mail
  • Input: { query: string, account?: string, limit?: number }
  • Behavior:
    • If the query contains only date operators (after:, before:, older_than:, newer_than:) or is empty: results are sorted by timestamp descending (most recent first). Across multiple accounts, they are merged and sorted together.
    • Otherwise (query includes free text or non-date operators): ordering matches Gmail’s native results per account; multi‑account queries preserve per‑account order without a global sort.
  • Output: Enriched results to reduce follow‑ups:
    • { messages: Array<{ accountId: string, accountEmail: string, messageId: string, threadId: string, subject: string | null, snippet: string, from: string | null, to: string | null, cc: string | null, bcc: string | null, timestamp: number, date: string, labels: Array<{ id: string, name: string }> }> }
    • Notes: timestamp is ms since epoch; date is ISO8601 string. Use gmail-get_message for full decoded body and attachments.
    • Query operators: Supports standard Gmail search syntax, including common operators like from:, to:, subject:, label:, in:, is: (e.g. is:unread, is:starred), has: (e.g. has:attachment), date filters before:, after:, relative older_than:/newer_than:, cc:, bcc:, filename:, size filters larger:/smaller:, boolean OR, and negation with -.
  1. gmail-get_message
  • Input: { account: string, messageId: string }
  • Output: A simplified, human-readable object:
    • { id: string, thread: string, labels: Array<{ id: string, name: string }>, timestamp: number, subject: string | null, from: string | null, to: string | null, cc: string | null, bcc: string | null, body: string, bodyType: 'text' | 'html', attachments: Array<{ filename: string, mimeType: string, size: number, attachmentId: string }> }
    • Notes: body is decoded (not base64url). Prefers text/plain when available, otherwise returns text/html. timestamp is ms since epoch.
  1. gmail-get_thread
  • Input: { account: string, threadId: string }
  • Output: A simplified thread with deduped messages ordered by time:
    • { id: string, messages: Array<SimpleMessage> }, where SimpleMessage matches gmail-get_message output.
    • Each message includes resolved label names and a timestamp field.
  1. gmail-download_attachment
  • Input: { account: string, messageId: string, attachmentId: string }
  • Output: Gmail MessagePartBody with base64url data.
  • Tip: Use gmail-get_message first to list attachments and obtain an attachmentId.
  1. gmail-label_message
  • Input: { account: string, messageId: string, add?: string[], remove?: string[] }
  • Writes: Adds/removes label IDs on a message. Disabled in --read-only mode.
  • Output: Gmail Message resource (post-modify).
  1. gmail-send_message
  • Input: { account: string, to: string, subject: string, text?: string, html?: string, replyToMessageId?: string }
  • Behavior: Builds a minimal RFC822 message (text or html) and sends via users.messages.send. Attachments and custom headers are not yet supported. replyToMessageId is currently accepted but not used to set threading headers.
  • Writes: Sends email on the selected account. Disabled in --read-only mode.
  • Output: Gmail Message resource for the sent message.

Account selection:

  • For any tool, account accepts either the account’s email or its internal id (see gmail-list_accounts).

Security model

  • Stored tokens are encrypted-at-rest when the DB is locked with passwd.
  • Losing the password means losing access to encrypted refresh tokens; there is no recovery.
  • Anyone who can launch the server or CLI with the password can access all linked inboxes.
  • No message bodies or tokens are logged.

Troubleshooting

  • Node not recent enough: ensure Node >= 18.17 (node -v).
  • No refresh token after OAuth: revoke prior grants and try again, ensuring prompt=consent and first-time approval for this client.
  • Locked DB errors: provide --pass or set GMAIL_MCP_DB_PASS for all commands, including list and remove.
  • Device flow polling errors: if you see authorization_pending or slow_down, just wait; the CLI automatically retries.

Optional: global install

You can install globally if you prefer shorter commands:

npm i -g @ideadesignmedia/gmail-mcp
gmail-mcp --help

All examples above work the same without npx once installed globally.