Skip to main content
Glama
hjerkic

gmail-mcp-server

by hjerkic

Gmail MCP Server

A working example of connecting Claude to a real business tool — Gmail — the way it should be done: with proper login security, the AI only able to do what it's explicitly allowed to do, and no way for it to take an irreversible action (like sending an email) without a clear checkpoint.

The problem this solves

AI assistants like Claude are increasingly expected to do things, not just talk — search an inbox, draft a reply, flag something urgent — instead of a person copy-pasting between a chat window and their actual tools. That capability is genuinely useful, but connecting an AI assistant directly to something as sensitive as an email account raises an obvious question: what happens if it gets it wrong, or is tricked into doing something it shouldn't?

Most quick "connect my AI to my inbox" setups skip past that question — they hand over broad access and hope for the best. That's the gap this project is built to close. It's a demonstration, using a real Google account and the real Gmail API (not a mock or toy example), of what a properly scoped AI-to-business-tool integration looks like: the AI gets exactly the access it needs for the job, nothing more, and the riskiest action (sending real email) requires an explicit extra step rather than happening automatically.

Related MCP server: gmail-mcp-server

How it stays safe, in plain terms

  • A specific, limited key — not the master key. Logging in grants three narrow permissions (read mail, draft/send mail, apply labels). There is no permission to delete anything, change account settings, or touch anything outside Gmail.

  • The key is locked in a safe. Once you log in, the credentials that let Claude access your inbox are encrypted on your own computer. They're never sent anywhere else, and the encryption key lives only in a local file that's never shared or uploaded.

  • Drafting and sending are two separate, deliberate steps. Claude can prepare a reply as a draft at any time — that's harmless and reversible, the same as you starting an email and not hitting send. Actually sending it is a separate action, clearly flagged to whatever app is running Claude as a sensitive one-way step, so it isn't something that happens as a side effect of Claude just being "helpful."

  • Labels can't be used to hide or destroy mail. Claude can tag messages with custom labels you create (e.g. "Needs Reply"), but it's structurally blocked from touching Gmail's built-in Trash/Spam/Archive controls through that same feature — a subtle way "just add a label" could otherwise be misused.

The full technical breakdown — exact permissions requested, what's reversible vs. not, and what the honest residual risk is — is in SECURITY.md.

Why build this instead of using Google's own Gmail MCP integration

Google has since released its own first-party remote MCP server for Gmail. For someone who just wants Gmail-in-Claude working today, that's the faster path. This project exists for a different reason: to show, on a tool everyone recognizes, the underlying skill of building this kind of integration from scratch — the login flow, the credential storage, the tool design, the safety boundaries — for the many business tools (CRMs, ad platforms, shipping, payments, internal systems) that don't have a ready-made AI integration and need someone to build one deliberately.

See it in action

  1. One-time login: run the authorize command, sign in with Google in the browser that opens, and approve access.

  2. Ask Claude: "Search my inbox for anything from [sender] this week" — it searches, nothing else.

  3. Ask: "Check my inbox and tell me if anything looks urgent" — it pulls a fast summary of recent mail and reasons over it.

  4. Ask: "Draft a reply to that saying I'll follow up tomorrow" — a real draft appears in Gmail. Nothing has been sent.

  5. Only if you then say so, ask Claude to send it — that's the one deliberate, irreversible step in the whole flow.


Under the hood

Tools

Tool

Scope

Description

gmail_search

read

Search messages with Gmail search syntax

gmail_read_message

read

Fetch one message's full body

gmail_list_recent

read

Fast metadata/snippet fetch for periodic triage

gmail_create_draft

write

Create a draft (never sends)

gmail_send_draft

write

Send a previously created draft

gmail_apply_label

write

Attach a custom (non-system) label

Setup

  1. Install dependencies (requires Python 3.10+; this repo uses uv):

    uv sync
  2. Set up Google OAuth and authorize an account — follow workflows/setup_google_oauth.md. Short version:

    cp .env.example .env
    python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
    # paste the output into .env as TOKEN_ENCRYPTION_KEY
    # download credentials.json from Google Cloud Console into the project root
    python -m tools.gmail_mcp.authorize personal
  3. Point Claude Desktop/Code at the server. Add to your MCP client config (e.g. claude_desktop_config.json):

    {
      "mcpServers": {
        "gmail": {
          "command": "/absolute/path/to/mcp-business-tools/.venv/bin/python",
          "args": ["-m", "tools.gmail_mcp.server"],
          "cwd": "/absolute/path/to/mcp-business-tools"
        }
      }
    }
  4. Restart Claude Desktop/Code so it picks up the new server.

Adding more accounts

See workflows/add_gmail_account.md.

Project layout

workflows/            SOPs: OAuth setup, adding accounts, inbox-summary pattern
tools/gmail_mcp/       the MCP server package
  config.py            env-driven settings, scopes
  auth.py              OAuth flow + encrypted token storage
  gmail_client.py       Gmail API wrapper functions
  server.py             MCP tool definitions
  authorize.py           one-time per-account OAuth CLI
tokens/                encrypted per-account tokens (gitignored)

Available Tools

6 tools
gmail_apply_labelA
Idempotent

Attach a custom label to a message (creating it first if needed).

Only user-created labels can be applied through this tool — system labels (TRASH, SPAM, INBOX, UNREAD, IMPORTANT, ...) are rejected, so this tool cannot be used to trash, spam, or archive a message. Returns the label id that was applied.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountNo
label_nameYes
message_idYes
create_if_missingNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, idempotentHint=true, and destructiveHint=false. The description adds meaningful context: it states the tool auto-creates labels (creating it first if needed), that system labels get rejected, and that it returns the label id applied. These add behavioral detail beyond the annotations, though the rejection specifics could be seen partly implied by the idempotentHint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences totaling roughly 50 words, all substantive. The first sentence declares purpose and auto-creation; the second explains exclusions and return value. Zero filler, front-loaded with the core action, and every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (4 params, output schema present, idempotent annotations provided), the description compactly covers the essential behavioral contract: what it does, what it rejects, auto-creation behavior, and return value. The output schema handles return structure, and the description covers the restrictions an agent needs to avoid misuse.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate for the 4 parameters. It clarifies label_name semantics (must be a user-created label, auto-created if needed) and mentions the return value. However, it doesn't explicitly address message_id format or the create_if_missing parameter behavior in detail, though the description's 'creating it first if needed' implies create_if_missing semantics. With an output schema present and this level of guidance for a moderately simple tool, a 4 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Attach a custom label to a message') with a specific verb+resource combination. It distinguishes itself from siblings by explicitly noting the scope (custom labels only, not system labels) and the auto-creation behavior, which sets it apart from other gmail tools in the sibling list.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when NOT to use this tool: system labels are rejected, so it cannot trash, spam, or archive. This is a clear exclusion criterion that prevents misuse, and it implicitly tells the agent which alternatives (sibling tools) to consider for system-label operations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

gmail_create_draftA

Create a draft email. This never sends anything.

Pass thread_id to draft a reply within an existing thread (the draft will pick up proper In-Reply-To/References headers automatically).

ParametersJSON Schema
NameRequiredDescriptionDefault
toYes
bodyYes
accountNo
subjectYes
thread_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, idempotentHint=false, destructiveHint=false, meaning the agent knows this is a non-destructive write operation (creating a draft is not destructive). The description adds the useful 'never sends anything' behavioral trait, which is valuable context beyond annotations. However, it doesn't mention persistence behavior, quota implications, or return value details beyond what the output schema provides. With annotated safety profile, a 3 is appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Extremely efficient - two short paragraphs, three sentences total. The first sentence states core purpose and the critical 'never sends' caveat. The second paragraph adds the thread_id operational detail. Zero wasted words, information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has an output schema (which handles return-value documentation) and moderate complexity with 5 params. The description covers the primary behavior (creating drafts), the non-sending guarantee, and the thread reply mechanism. Remaining gaps are minor - the account parameter is undocumented and there's no explicit statement about how the created draft becomes usable with gmail_send_draft, though this is implied by the sibling relationship. For a draft-creation tool, this is reasonably complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description carries the full burden for parameter meaning. The description explicitly explains thread_id semantics (for replies within a thread, auto-header generation), which the schema alone wouldn't convey. The required params (to, subject, body) are self-evidently named, but the optional thread_id and account parameters benefit from the explanation. The description partially compensates for the 0% coverage, though it doesn't address the account parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The verb 'Create' plus resource 'a draft email' is specific and clear. It explicitly notes 'This never sends anything', which distinguishes its scope from send operations. The sibling tool gmail_send_draft exists, and the description clearly differentiates this tool's purpose of only drafting, not sending.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use it (to create drafts that never send). It even provides guidance on the optional thread_id usage for replies within existing threads, including the benefit it provides (auto In-Reply-To/References headers). While it doesn't explicitly name gmail_send_draft as the alternative, the 'never sends anything' statement clearly signals this is the drafting counterpart and distinguishes use versus the send tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

gmail_list_recentA
Read-only

Fast, compact fetch of recent inbox messages for periodic triage.

Intentionally returns metadata + snippet only (no bodies) so it's cheap to call on a schedule. This tool does not decide what's "urgent" — it hands back enough signal (subject, sender, snippet, labels like IMPORTANT/STARRED/UNREAD) for the caller to make that judgment.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryNoin:inbox newer_than:2d
accountNo
max_resultsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, covering the safety profile. The description adds useful context: it intentionally omits bodies, returns metadata+snippet only, and explicitly states it doesn't decide urgency. That adds value beyond annotations, though it doesn't detail return format specifics despite an output schema being present.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise paragraphs with clear front-loading: the first sentence states the purpose, and the second paragraph clarifies scope and philosophy. No wasted words. Could trim the philosophical note about not deciding urgency, but it does convey the tool's division of responsibility.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only, open-world list tool with 3 optional parameters and an existing output schema, the description is reasonably complete: it states what's returned (metadata+snippet, labels like IMPORTANT/STARRED/UNREAD), why it's cheap, and its intended use case. Slight gap: parameter semantics for account/max_results could be clearer, and it doesn't mention pagination, but for this tool class the coverage is strong.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the 3 parameters have no descriptions. However, the description mentions query-relevant concepts ('in:inbox newer_than:2d' default is in the schema, labels like IMPORTANT/STARRED/UNREAD are mentioned), giving the agent signal about what the query/max_results parameters control. It adds modest value but doesn't fully document each parameter's semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('fetch') + resource ('recent inbox messages') with a clear qualifier ('Fast, compact... for periodic triage'). It clearly distinguishes from sibling gmail_search by emphasizing 'recent inbox for triage' and noting it returns metadata+snippet only, differentiating it from gmail_read_message.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states this is for 'periodic triage' and periodic scheduled calls, implying the use case. It establishes the when-to-use context (cheap scheduled fetch) but doesn't explicitly name alternatives or say when NOT to use it, though the distinction from read_message/search is implied by the metadata-only framing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

gmail_read_messageB
Read-only

Fetch one message in full, including its plain-text body.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountNo
message_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, so the agent knows this is a safe read operation with no side effects. The description adds the behavior of returning the full message with plain-text body, which is useful context beyond annotations. It doesn't mention HTML body handling, attachments, or headers, which would be richer context, but with openWorldHint the agent is told not to assume completeness.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single efficient sentence with zero waste. It front-loads the verb and resource immediately. Every word earns its place, though it could arguably have added brief parameter detail without hurting structure.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has an output schema present, so return values don't need description coverage. However, with 0% schema description coverage on 2 parameters, the description leaves message_id semantics and account handling entirely to the agent's inference. For a straightforward read tool, this is adequate but not rich. openWorldHint partially mitigates completeness concerns.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the parameter-load. However, the description adds no parameter-specific explanation — it doesn't describe what message_id format is expected or what the account parameter does. With 2 params and 0% schema coverage, the description should compensate more but doesn't.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Fetch one message in full, including its plain-text body' — a specific verb (fetch) targeting a specific resource (one message) with the scope of full content including body. It doesn't explicitly differentiate from siblings like gmail_search or gmail_list_recent, but the singular-message fetch is distinct enough from those list/act tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies this is for retrieving a specific single message by ID ('one message in full'). It doesn't explicitly state when to use vs alternatives, but the sibling tools (list, search, draft/send/label) are clearly different action types, so the use case is reasonably implied. No exclusions or when-not guidance is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

gmail_send_draftA
Destructive

Send a previously created draft. This is a real, irreversible send.

There is no tool to send arbitrary text directly — a draft must be created first via gmail_create_draft.

ParametersJSON Schema
NameRequiredDescriptionDefault
accountNo
draft_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description explicitly flags 'real, irreversible send,' which adds meaningful warning beyond the destructiveHint=true annotation. It clarifies the irreversibility consequence, though it could add returning message ID or delivery confirmation context, but with the destructiveHint annotation present the bar is already well met.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short, tightly scoped sentences. Front-loaded with the core action, immediately followed by the key warning, then necessary workflow guidance. Zero filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple (2 params, 1 required) and has an output schema, so the burden is reduced. The description covers the core action, the irreversible consequence, and the prerequisite workflow, giving the agent everything needed to safely invoke it. Minor gap: no explicit mention of error cases (e.g., sending an already-sent draft), but this is acceptable for a simple operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It does not document the draft_id parameter format or the account parameter at all. However, draft_id is self-explanatory and required; account is nullable with a default, and its semantics are intuitive given the Gmail domain. Baseline 3 applies as schema documents the parameters structurally.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clear verb+resource: 'Send a previously created draft.' Explicitly notes irreversibility. Strongly distinguishes from siblings by explaining there is no alternative that sends arbitrary text directly, differentiating from gmail_create_draft.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states the prerequisite workflow — a draft must be created via gmail_create_draft first, and that there is no tool for sending arbitrary text. This directly addresses when to use this tool and references the sibling alternative, making selection unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 6 tool updatesv0.1.0
    • First observedgmail_apply_label
    • First observedgmail_create_draft
    • First observedgmail_list_recent
    • First observedgmail_read_message
    • First observedgmail_search
    • First observedgmail_send_draft

TDQS

A3.9/5.0
Disambiguation4/5

Tools are mostly distinct: read/list/search handle retrieval with clear differences in scope, create_draft/send_draft separate drafting from sending, and apply_label handles labeling. One slight overlap exists between gmail_list_recent and gmail_search (both return compact metadata + snippets), though their intended use cases differ enough to disambiguate.

Naming Consistency5/5

All tools follow a consistent gmail_verb_noun pattern (gmail_read_message, gmail_list_recent, gmail_create_draft, gmail_send_draft, gmail_apply_label, gmail_search). Naming is uniform, clear, and predictable throughout.

Tool Count5/5

Six tools are well-scoped for a Gmail integration server. Each tool covers a distinct core Gmail operation (read, list, draft, send, label, search) without bloat or overlap, falling comfortably within the ideal 3-15 range.

Completeness3/5

Core read, list, search, draft, send, and label workflows are covered, but there are notable gaps: no update/modify message tools (trash, archive, mark read/unread), no delete draft tool, and no task to list or manage threads as a whole. The label tool explicitly rejects system labels, meaning agents cannot archive or trash messages at all, which is a significant dead end for common email workflows.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    A minimal MCP server that enables Claude to search, read, and manage Gmail messages and threads using official Google API libraries. It supports actions like sending emails, creating drafts, replying to threads, and managing labels through secure OAuth2 authentication.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    A secure MCP server that enables Claude to read, search, send, reply, forward, and manage Gmail messages and labels through natural language commands.
    215
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    A custom MCP server that gives Claude full Gmail control — send directly, read, reply, search, label, and delete emails.
    215
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that provides Claude with access to your Gmail, featuring a full OAuth 2.1 authorization server with dynamic client registration and tools to list, read, search, send, reply, draft, archive, trash, manage labels, and download attachments.
    205
    1
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hjerkic/gmail-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server