{"id":51579409,"url":"https://github.com/stevesimpson418/gmail-mcp-server","last_synced_at":"2026-07-11T04:30:35.128Z","repository":{"id":349237972,"uuid":"1201116563","full_name":"stevesimpson418/gmail-mcp-server","owner":"stevesimpson418","description":"A local MCP server that gives Claude native tool-level access to Gmail","archived":false,"fork":false,"pushed_at":"2026-04-26T20:35:32.000Z","size":185,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-26T21:28:00.837Z","etag":null,"topics":["claude","fastmcp","gmail","mcp","mcp-server","model-context-protocol","python"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stevesimpson418.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-04T08:27:15.000Z","updated_at":"2026-04-26T20:35:36.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/stevesimpson418/gmail-mcp-server","commit_stats":null,"previous_names":["stevesimpson418/gmail-mcp-server"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/stevesimpson418/gmail-mcp-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stevesimpson418%2Fgmail-mcp-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stevesimpson418%2Fgmail-mcp-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stevesimpson418%2Fgmail-mcp-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stevesimpson418%2Fgmail-mcp-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stevesimpson418","download_url":"https://codeload.github.com/stevesimpson418/gmail-mcp-server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stevesimpson418%2Fgmail-mcp-server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35351424,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-11T02:00:05.354Z","response_time":104,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["claude","fastmcp","gmail","mcp","mcp-server","model-context-protocol","python"],"created_at":"2026-07-11T04:30:34.675Z","updated_at":"2026-07-11T04:30:35.119Z","avatar_url":"https://github.com/stevesimpson418.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Gmail MCP Server\n\n[![CI](https://github.com/stevesimpson418/gmail-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/stevesimpson418/gmail-mcp-server/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/stevesimpson418/gmail-mcp-server/graph/badge.svg)](https://codecov.io/gh/stevesimpson418/gmail-mcp-server)\n[![Python 3.14+](https://img.shields.io/badge/python-3.14+-blue.svg)](https://www.python.org/downloads/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA local [MCP](https://modelcontextprotocol.io/) server that gives Claude native, tool-level access\nto **Gmail**. Runs locally via stdio transport — all tokens and credentials stay on your machine.\n\n## Prerequisites\n\n- Python 3.14+\n- [uv](https://docs.astral.sh/uv/) for dependency management\n- A Google account with the Gmail API enabled\n\n## Quick Start\n\n```bash\n# Clone the repo\ngit clone https://github.com/stevesimpson418/gmail-mcp-server.git\ncd gmail-mcp-server\n\n# Install dependencies (creates .venv/ in the project directory)\nuv sync\n```\n\n\u003e **New to uv?** `uv sync` reads `pyproject.toml`, creates a `.venv/` virtualenv inside the\n\u003e project folder, and installs all dependencies into it. You don't need to activate it —\n\u003e `uv run \u003ccommand\u003e` handles that automatically.\n\n## Setting up Gmail\n\n### 1. Create a Google Cloud project\n\nGo to the [Google Cloud Console](https://console.cloud.google.com/) and create a new project\n(or select an existing one).\n\n### 2. Enable the Gmail API\n\nNavigate to **APIs \u0026 Services \u003e Library**, search for **Gmail API**, and click **Enable**.\n\n### 3. Configure the OAuth consent screen\n\nBefore creating credentials, Google requires you to configure the OAuth consent screen. Go to\n**APIs \u0026 Services \u003e OAuth consent screen** (or **Google Auth Platform** if prompted).\n\n1. Click **Get Started** (or **Configure Consent Screen**)\n2. Fill in the required fields:\n   - **App name** — a name for your own reference (e.g. \"Gmail MCP Server\")\n   - **User support email** — your email address\n3. Select an **Audience**:\n   - **Internal** — only available if you're in a Google Workspace organisation\n   - **External** — select this for personal Google accounts. The app starts in **testing\n     mode**, which is fine for personal use — you just need to add yourself as a test user\n4. **Contact information** — your email (Google uses this to notify you of project changes)\n5. Click **Save**\n\n\u003e **About testing mode:** External apps in testing mode are limited to users you explicitly\n\u003e add to the test user list. This is perfectly fine for a local MCP server — you only need\n\u003e your own account. Tokens for test users expire after 7 days, requiring re-consent. If this\n\u003e becomes inconvenient, you can publish the app (no verification needed for sensitive scopes\n\u003e used with fewer than 100 users in testing mode, but publishing removes the 7-day expiry).\n\n### 4. Add test users\n\nGo to **APIs \u0026 Services \u003e OAuth consent screen \u003e Test users** (or **Audience** in the new\nGoogle Auth Platform UI) and add your Google account email address.\n\n### 5. Add OAuth scopes\n\nGo to **APIs \u0026 Services \u003e OAuth consent screen \u003e Scopes** (or **Data Access** in the new UI)\nand add the following scope:\n\n\u003c!-- markdownlint-disable MD013 --\u003e\n\n| Scope | Why it's needed |\n|-------|----------------|\n| `https://www.googleapis.com/auth/gmail.modify` | Read messages, modify labels (archive, star, mark read/unread, apply/remove labels), manage drafts, send emails, and move messages to trash. This is the minimum single scope that covers all server operations — narrower scopes like `gmail.readonly` or `gmail.send` don't cover label modification or trash. |\n\n\u003c!-- markdownlint-enable MD013 --\u003e\n\nThis server does **not** request `mail.google.com` (full unrestricted access) — `gmail.modify`\nis scoped to read/write operations and cannot permanently delete messages.\n\n### 6. Create OAuth 2.0 credentials\n\n1. Go to **APIs \u0026 Services \u003e Credentials**\n2. Click **Create Credentials \u003e OAuth client ID**\n3. Application type: **Desktop app**\n4. Give it a name for your own reference (e.g. \"Gmail MCP — My Laptop\")\n5. Click **Create**, then **Download JSON**\n6. Save the file as `credentials/gmail_credentials.json` in this project\n\n\u003e **Security note:** The `credentials/` directory is gitignored — your credentials and tokens\n\u003e will never be committed to the repository.\n\n### 7. Run the OAuth consent flow\n\n```bash\nuv run gmail-mcp-auth\n```\n\nA browser window will open — sign in with the Google account you added as a test user and\ngrant the requested permissions. The token is saved to `credentials/token.json` and\nauto-refreshes after this.\n\nTo use custom paths:\n\n```bash\nuv run gmail-mcp-auth --credentials /path/to/creds.json --token /path/to/token.json\n```\n\n## Adding to Claude Desktop\n\nAdd the following to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS).\n\n\u003e **Tip:** Run `uv run which python` from the project directory to get the exact path for `command`.\n\n```json\n{\n  \"mcpServers\": {\n    \"gmail\": {\n      \"command\": \"/Users/you/gmail-mcp-server/.venv/bin/python\",\n      \"args\": [\"-m\", \"gmail_mcp.server\"],\n      \"env\": {\n        \"GMAIL_CREDENTIALS_PATH\": \"/Users/you/gmail-mcp-server/credentials/gmail_credentials.json\",\n        \"GMAIL_TOKEN_PATH\": \"/Users/you/gmail-mcp-server/credentials/token.json\"\n      }\n    }\n  }\n}\n```\n\nThe `env` block tells the server where to find your credentials at runtime. No `.env` file is\nneeded — the config passes these values directly.\n\nRestart Claude Desktop after saving. You should see all Gmail tools in the tools menu.\n\n## Adding to Claude Code CLI\n\nUse the `claude mcp add` command to register the server. This works from any directory.\n\n```bash\nclaude mcp add --scope user gmail-mcp-server \\\n  --transport stdio \\\n  --env GMAIL_CREDENTIALS_PATH=/path/to/gmail-mcp-server/credentials/gmail_credentials.json \\\n  --env GMAIL_TOKEN_PATH=/path/to/gmail-mcp-server/credentials/token.json \\\n  -- /path/to/gmail-mcp-server/.venv/bin/python -m gmail_mcp.server\n```\n\nReplace `/path/to/gmail-mcp-server` with the actual path where you cloned the repo.\n\n\u003e **Tip:** Run `uv run which python` from the project directory to get the exact `.venv/bin/python`\n\u003e path for the command.\n\nThe `--scope user` flag saves to `~/.claude.json` so the server is available across all projects.\nWithout it, the command defaults to local scope (tied to whatever directory you run it from).\nTo scope it to a single project instead, use `--scope project` which writes to `.mcp.json` in\nthe project root.\n\nTo verify the server is registered:\n\n```bash\nclaude mcp list\n```\n\nRestart Claude Code after adding. The Gmail tools should appear in the `/mcp` menu.\n\n\u003e **Note:** Claude Code CLI uses a different configuration from Claude Desktop. The `claude mcp add`\n\u003e command is the recommended way to register MCP servers — do not add them to\n\u003e `~/.claude/settings.json` as that file is used for permissions and hooks only.\n\n## Updating\n\nTo pull the latest version and update dependencies:\n\n```bash\ncd /path/to/gmail-mcp-server\ngit pull\nuv sync\n```\n\nRestart Claude Desktop or Claude Code CLI after updating.\n\nIf a new version changes OAuth scopes, you'll need to re-consent by running\n`uv run gmail-mcp-auth` again.\n\n## Available Tools\n\n| Tool | Description |\n|------|-------------|\n| `search_gmail(query, max_results?)` | Search messages using Gmail query syntax (e.g. `is:unread in:inbox`) |\n| `read_gmail_message(message_id)` | Read a full message including body text |\n| `read_gmail_thread(thread_id)` | Read all messages in a thread |\n| `list_gmail_labels()` | List all labels (system and user-created) |\n| `list_gmail_attachments(message_id)` | List attachments on a message |\n| `read_gmail_attachment(message_id, attachment_id, filename, mime_type)` | Read attachment content inline |\n| `archive_gmail_messages(message_ids)` | Archive messages (remove from inbox) |\n| `bulk_archive_gmail(query)` | Search and archive all matching messages in one call |\n| `apply_gmail_label(message_ids, label_name)` | Apply a label to messages |\n| `remove_gmail_label(message_ids, label_name)` | Remove a label from messages |\n| `create_gmail_label(name, text_color?, background_color?)` | Create a new label |\n| `mark_gmail_read(message_ids)` | Mark messages as read |\n| `mark_gmail_unread(message_ids)` | Mark messages as unread |\n| `star_gmail_message(message_ids)` | Star messages |\n| `mark_gmail_important(message_ids)` | Mark messages as important |\n| `create_gmail_draft(to, subject, body, thread_id?, cc?)` | Create a draft email |\n| `send_gmail(to, subject, body, cc?)` | Send an email directly |\n| `send_gmail_draft(draft_id)` | Send a previously created draft |\n| `trash_gmail_messages(message_ids)` | Move messages to trash (recoverable for 30 days) |\n\n### Usage Examples\n\n**Triage your inbox:**\n\n```text\n1. search_gmail(query=\"is:unread in:inbox\")          → see what's new\n2. read_gmail_message(message_id=\"msg_123\")           → read the full message\n3. archive_gmail_messages(message_ids=[\"msg_123\"])     → archive after reading\n```\n\n**Bulk cleanup:**\n\n```text\nbulk_archive_gmail(query=\"from:noreply@marketing.com in:inbox\")\nbulk_archive_gmail(query=\"is:unread in:inbox older_than:7d subject:newsletter\")\n```\n\n**Draft a reply:**\n\n```text\ncreate_gmail_draft(\n    to=\"alice@example.com\",\n    subject=\"Re: Meeting\",\n    body=\"Sounds good, see you then!\",\n    thread_id=\"thread_abc\"\n)\n```\n\n## Development\n\n```bash\n# Install dev dependencies\nuv sync --dev\n\n# Run tests\nuv run pytest -v\n\n# Run tests with coverage\nuv run pytest --cov=gmail_mcp --cov-report=term-missing\n\n# Lint\nuv run ruff check src/ tests/\n\n# Format\nuv run ruff format src/ tests/\n\n# Install git hooks\nlefthook install\n```\n\n### Local `.env` file\n\nWhen running the server manually outside Claude Desktop/Code (e.g., for development or\ndebugging), you can create a `.env` file in the project root so the server picks up\ncredential paths without passing environment variables:\n\n```text\nGMAIL_CREDENTIALS_PATH=credentials/gmail_credentials.json\nGMAIL_TOKEN_PATH=credentials/token.json\n```\n\nThis is only needed for local development. The Claude Desktop and Claude Code CLI configs\npass these values directly via the `env` block.\n\n### Packaging \u0026 Distribution\n\nThis server is currently distributed as source via git. To install:\n\n```bash\ngit clone https://github.com/stevesimpson418/gmail-mcp-server.git\ncd gmail-mcp-server\nuv sync\n```\n\nThis is the standard distribution model for local-stdio MCP servers today. The project is\nalready configured for wheel builds via hatchling, so future distribution options include:\n\n- **PyPI** — publish to PyPI, then install with `uv tool install gmail-mcp-server` or\n  `pip install gmail-mcp-server`. Would require adding a publish workflow to CI.\n- **uvx** — once on PyPI, `uvx gmail-mcp-server` runs the server without cloning the repo.\n  Claude Desktop/Code config would point to the uvx-managed binary instead of a local `.venv`.\n\n## Releases\n\nThis project uses [release-please](https://github.com/googleapis/release-please) for automated\nversioning and releases. The version is determined by\n[Conventional Commits](https://www.conventionalcommits.org/):\n\n- `fix:` commits bump the **patch** version (e.g. 0.1.0 → 0.1.1)\n- `feat:` commits bump the **minor** version (e.g. 0.1.1 → 0.2.0)\n- `BREAKING CHANGE` in the commit footer bumps the **major** version\n\nWhen commits land on `main`, release-please opens (or updates) a Release PR that:\n\n- Bumps the version in `pyproject.toml`\n- Updates `CHANGELOG.md` with grouped entries\n\nMerging the Release PR creates a git tag and GitHub Release automatically.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstevesimpson418%2Fgmail-mcp-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstevesimpson418%2Fgmail-mcp-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstevesimpson418%2Fgmail-mcp-server/lists"}