Skip to main content
Glama

Gmail MCP — Gmail Access for AI Clients

15 tools for the Gmail API — search, read, draft, send, and organize — gated behind three access levels, read-only by default.

For Claude Desktop, Claude Code, and any MCP client.

by Jan Ivan Simoy


What is this?

Gmail MCP is a Model Context Protocol server that gives AI assistants structured access to a Gmail inbox — searching and reading mail, drafting replies, and, only at the highest access level, sending mail and organizing the inbox (labels, archive, trash).

Gmail has no service-account model for a personal @gmail.com inbox — there is no "share this inbox with a robot" the way there is for a Google Doc or Sheet. Every call here is authorized on behalf of a real Google account through the standard OAuth 2.0 "installed app" flow: you sign in once in a browser, this server gets a long-lived refresh token, and every call after that happens with no browser involved.

Supported platform: any MCP client on macOS, Linux, or Windows with Python 3.10+.


Related MCP server: Gmail MCP Server

Access Levels

GMAIL_ACCESS_LEVEL in .env controls what this server will actually do — independent of what the OAuth consent screen technically allows (see Authentication: that consent always grants the FULL ceiling, specifically so raising this later never sends you back to the browser).

Level

Can it change your inbox?

Tools

READONLY (default)

No. List, search, and read messages and threads.

5

BASIC

Drafts only. Create, edit, and delete drafts. Nothing is ever sent.

10

FULL

Yes. Everything in BASIC, plus sending mail as you and labeling/archiving/trashing existing messages.

15

How it is enforced

Two independent gates, so a bug in one does not defeat the other:

  1. Registration. server.register_tiered_tools() only hands the model tools whose required level the configured GMAIL_ACCESS_LEVEL meets. At READONLY the model is never told that send_message exists.

  2. Dispatch. GmailClient checks the level before building any request. A call to a level-gated method at an insufficient level raises AccessDenied and no HTTP request is made — there are tests for exactly that.

What FULL deliberately does not include

Gmail's broadest scope, https://mail.google.com/, additionally grants permanent deletion (bypassing Trash) and the ability to change account settings — forwarding rules, filters, IMAP/POP toggles. This server never requests that scope at any level. Those are account configuration changes, not "read or send mail" operations, and unlike sending or trashing a message, they are not something a person watching the inbox can easily notice and undo. There is no tool here that needs it, at any access level.

⚠️ Disclaimer — read before raising the level

Setting GMAIL_ACCESS_LEVEL to BASIC or FULL allows an AI model to act on your real Gmail account.

At FULL, that includes sending email from your address with no human click in between. A sent message cannot be recalled — the recipient has it the instant the tool call succeeds. FULL can also trash and relabel existing mail (recoverable via Trash for ~30 days, but not instant, and not something you'll necessarily notice happened).

AI models make mistakes. They misread instructions, act on ambiguous requests, and can be influenced by content they read — including the content of an email they were asked to read before replying to it. A model with FULL access to your Gmail account can send messages as you to anyone, about anything.

If you raise this setting above READONLY, you do so entirely at your own risk and you are solely responsible for anything sent, deleted, or reorganized as a result. The author and contributors accept no liability. This software is provided "as is", without warranty of any kind, as set out in the MIT License.

Recommended: leave it at READONLY for searching and reading. Raise to BASIC if you want drafts prepared for your own review and send. Raise to FULL only for a session that specifically needs to send or reorganize mail on your behalf, and only if you are comfortable with that.


Tools

Level

Tools

What you can do

READONLY

5

Get the account profile, list labels, search messages (Gmail's own search syntax), read a message, read a whole thread

BASIC

5

List/get/create/update/delete drafts

FULL

5

Send a draft, compose-and-send directly, add/remove labels, trash, untrash

Tool

Level

Description

get_profile

READONLY

The authorized account's address and message/thread totals

list_labels

READONLY

Every label (system + user), with the IDs other tools need

search_messages

READONLY

Gmail search syntax (from:, subject:, after:, is:unread, label:, boolean operators) — returns extracted plain-text bodies, not just snippets

get_message

READONLY

One message in full: headers, labels, plain-text body

get_thread

READONLY

An entire conversation as an ordered list of messages

list_drafts

BASIC

List drafts on the account

get_draft

BASIC

One draft in full

create_draft

BASIC

Create a draft — optionally as a reply within an existing thread

update_draft

BASIC

Replace a draft's content

delete_draft

BASIC

Delete a draft (never touches sent mail)

send_draft

FULL

Send an existing draft as-is — irreversible

send_message

FULL

Compose and send immediately, no draft step — irreversible

modify_message_labels

FULL

Add/remove labels — archive, mark read/unread, star

trash_message

FULL

Move to Trash — reversible for ~30 days

untrash_message

FULL

Restore out of Trash

Every message- and thread-reading tool returns the extracted plain-text body inline, not just a snippet — the same approach used in wordpress-mcp and google-cloud-services-mcp for reading a Doc: try the clean structured form first, fall back to a best-effort plain-text conversion for HTML-only mail.


Requirements

Requirement

Version

Python

3.10 or later

Google Cloud project

with the Gmail API enabled

OAuth 2.0 Client ID

type "Desktop app"


Authentication

Gmail has no service-account option for a personal inbox (that only exists for a paid Google Workspace domain with admin-configured domain-wide delegation). Setup here is a one-time OAuth consent instead:

  1. In Google Cloud Console, create or select a project and enable the Gmail API (APIs & Services → Library → search "Gmail API" → Enable).

  2. Configure the OAuth consent screen (APIs & Services → OAuth consent screen). Choose External, keep it in Testing mode, and add the Google account you'll use as a test user. Testing mode is enough for your own account — you do not need Google's app-verification review for a single-user tool like this one.

  3. Create an OAuth 2.0 Client ID of type Desktop app (APIs & Services → Credentials → Create Credentials → OAuth client ID → Desktop app). Note its Client ID and Client Secret.

  4. Run the one-time consent flow:

    ./.venv/bin/gmail-mcp-authorize

    It asks for the Client ID and Secret from step 3 (or reads GMAIL_CLIENT_ID/ GMAIL_CLIENT_SECRET from your environment if already set), opens your browser to Google's sign-in and consent screen, and prints GMAIL_CLIENT_ID, GMAIL_CLIENT_SECRET, and GMAIL_REFRESH_TOKEN — put all three in .env.

    This always requests the FULL scope ceiling (read + drafts + send/organize), regardless of what GMAIL_ACCESS_LEVEL you'll actually run at. That's deliberate: GMAIL_ACCESS_LEVEL is a second, independent gate on top (see Access Levels) — raising it later is an .env edit, not a trip back to this step.

  5. If you ever need to revoke access entirely, do it at myaccount.google.com/permissions — that invalidates the refresh token immediately, and gmail-mcp-authorize gets you a new one.


Installation

git clone git@github.com:jimsimoy/gmail-mcp.git
cd gmail-mcp
python3 -m venv .venv && ./.venv/bin/pip install -e ".[dev]"
cp .env.example .env
# then follow Authentication above to fill in .env

Verify before wiring up a client

./.venv/bin/python -m pytest -q      # no credentials or network needed
./.venv/bin/gmail-mcp                # starts the stdio server; prints the tool count to stderr

Client Setup

{
  "mcpServers": {
    "gmail": {
      "command": "/path/to/gmail-mcp/.venv/bin/python",
      "args": ["-m", "gmail_mcp"],
      "env": {
        "GMAIL_CLIENT_ID": "your-client-id.apps.googleusercontent.com",
        "GMAIL_CLIENT_SECRET": "your-client-secret",
        "GMAIL_REFRESH_TOKEN": "your-refresh-token",
        "GMAIL_ACCESS_LEVEL": "READONLY"
      }
    }
  }
}

With uv:

{
  "mcpServers": {
    "gmail": {
      "command": "uv",
      "args": ["--directory", "/path/to/gmail-mcp", "run", "gmail-mcp"],
      "env": {
        "GMAIL_CLIENT_ID": "your-client-id.apps.googleusercontent.com",
        "GMAIL_CLIENT_SECRET": "your-client-secret",
        "GMAIL_REFRESH_TOKEN": "your-refresh-token",
        "GMAIL_ACCESS_LEVEL": "READONLY"
      }
    }
  }
}

Restart your MCP client after saving.


Usage Examples

Find something from years ago, without knowing the exact wording:

"Search my Gmail for anything from IdeaSpace Foundation around July 2016."

search_messages(query="from:ideaspacefoundation.org after:2016/06/01 before:2016/08/01")

Draft a reply for you to review and send yourself (safe at BASIC):

"Draft a reply to the latest message in this thread saying I can make the Tuesday slot."

create_draft(to=..., subject="Re: ...", body_text=..., thread_id=..., in_reply_to=...) — the draft sits in Gmail's Drafts folder until you send it.

Let it send directly (needs FULL, and means what it says):

"Send that reply now."

send_draft(draft_id=...) — no further confirmation step inside this server. If you want a human checkpoint before anything goes out, stay at BASIC and send from the Gmail app yourself.


Security

This project is meant to be read before it is run. The design notes that matter:

  • Read-only by default, enforced twice. At READONLY — the default — nothing that changes your inbox is even registered as a tool, and GmailClient refuses the underlying operation independently if it's somehow reached anyway. Tests cover both gates, including that a denied call never reaches the network.

  • The OAuth scope is a second, outer fence. Even if GMAIL_ACCESS_LEVEL were somehow bypassed, the access token itself is scoped by what you granted during consent — and this server never requests https://mail.google.com/, the one scope that permits permanent deletion and account settings changes, at any level.

  • Refresh tokens and client secrets are environment-only. .env, .env.* (except .env.example), and token.json are gitignored. Every credential is stripped from any error message this server produces, including Gmail's own error bodies.

  • A pre-push scan runs before every commit and push (git-guard.sh, invoked by git-commit.sh/git-push-current.sh) — it specifically pattern-matches Google OAuth client IDs, client secrets, and refresh/access token formats, on top of the generic credential patterns used across this author's other MCP servers. This repo is private, but the scan runs regardless — see the comment at the top of git-guard.sh for why "it's private" is not treated as a sufficient control on its own.

  • Sending is never retried. A send_message/send_draft call that times out or fails ambiguously is not silently replayed — a duplicate send is worse than a visible error.

  • Three runtime dependencies, no vendor SDK. mcp, httpx, python-dotenv. Gmail's REST API is called directly; there is no google-api-python-client dependency to audit.

  • No telemetry. This server makes no network call other than the Gmail API request a tool asks for, and the OAuth token refresh that requires.

Your refresh token carries whatever scope you granted at consent (the FULL ceiling, by design — see Authentication). Revoke it at myaccount.google.com/permissions if it is ever exposed, then run gmail-mcp-authorize again for a new one.


Project Structure

gmail-mcp/
├── src/gmail_mcp/
│   ├── access.py        # AccessLevel enum, per-level Gmail scopes, the require() gate
│   ├── auth.py           # Refresh token -> short-lived access token
│   ├── authorize.py       # One-time interactive browser consent flow (gmail-mcp-authorize)
│   ├── client.py           # Gmail REST wrapper: MIME building, message parsing, dispatch gate
│   ├── config.py            # .env loading into a Settings dataclass
│   └── server.py              # MCP tool definitions and tiered registration
├── tests/
│   ├── test_access.py                # Both enforcement gates
│   ├── test_message_parsing.py       # MIME/text-extraction pure-function tests
│   └── test_rate_limiting.py         # Retry-on-rate-limit and per-item fetch pacing
├── .env.example
└── pyproject.toml

Development

./.venv/bin/pip install -e ".[dev]"
./.venv/bin/python -m pytest -q

51 tests, run entirely offline against httpx.MockTransport and a fake token provider — no real Gmail account or network access is needed to verify the access-level gates, the MIME/parsing logic, or the rate-limit backoff and pacing (see AGENTS.md — this was hit for real once, not added speculatively).


License

MIT — see LICENSE.

Available Tools

5 tools
get_messageB
Read-onlyIdempotent

Get one message in full: headers, labels, and its plain-text body.

ParametersJSON Schema
NameRequiredDescriptionDefault
message_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.3/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false, so the safety profile is covered. The description adds that the body is returned as plain text, which is mild extra context, but says nothing about permissions, missing-message behavior, or why a full fetch differs from search results.

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?

A single front-loaded sentence naming the verb, cardinality ('one'), and return contents. No padding.

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?

An output schema exists, so return values need no elaboration, and annotations cover safety. However, the description never positions the tool against the sibling tools that also retrieve or enumerate messages, leaving selection ambiguity.

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% and the description says nothing about message_id, but there is only one required parameter with a self-explanatory name. That keeps it at the baseline rather than penalizing heavily — no format or provenance hints are added.

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 gives a specific verb and resource (get one message) and enumerates the returned parts: headers, labels, and plain-text body. It does not explicitly distinguish itself from siblings like get_thread or search_messages, so it stops short of a 5.

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

Usage Guidelines2/5

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

There is no guidance on when to use this versus get_thread or search_messages, nor any prerequisites (e.g., an ID must come from search_messages). Usage is only implied by the verb 'get'.

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

get_profileA
Read-onlyIdempotent

Get the authorized Gmail account's address and message/thread totals.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is fully covered. The description adds only that the result contains the account address plus message/thread totals, which is largely restated by the existing output schema.

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?

A single sentence that front-loads the action and the returned data with no filler. Nothing is padded or repeated.

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?

For a zero-parameter, read-only profile tool with an output schema covering the return shape and annotations covering the safety profile, the description supplies everything an agent needs to call it correctly.

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?

The tool takes zero parameters, so the baseline of 4 applies. The description correctly signals there is nothing to configure by describing a fixed, account-scoped lookup.

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?

States a specific verb ('Get') and a precisely scoped resource (the authorized Gmail account's address and message/thread totals). This is clearly distinguishable from the sibling list/search/get-message/get-thread tools, none of which return account-level profile data.

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?

Usage is implied rather than stated: the description makes clear this is the account-identity/totals lookup, but it never says when to prefer it or notes that no parameters or filters are accepted. No alternatives or exclusions are named.

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

get_threadB
Read-onlyIdempotent

Get an entire conversation thread as an ordered list of messages.

ParametersJSON Schema
NameRequiredDescriptionDefault
thread_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint, so the safety profile is covered. The description adds one genuine behavioral detail beyond the annotations — that results are returned as an ordered list — but says nothing about pagination, limits, or behavior on a missing thread.

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?

A single front-loaded sentence with no filler; the verb, resource, and return shape all appear immediately.

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?

An output schema exists (so return values needn't be described) and annotations cover the safety profile, making the description nearly sufficient. The only real gap is the undocumented thread_id parameter.

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

Parameters2/5

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

Schema description coverage is 0% for the single required thread_id parameter, so the description carries the full burden — but it says nothing about the id's format, where it comes from, or what happens if it's invalid.

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?

States a specific verb (get) and resource (an entire conversation thread) plus the return shape (ordered list of messages). It implicitly distinguishes itself from get_message and search_messages by scoping to a whole thread, though it never names those siblings explicitly.

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

Usage Guidelines2/5

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

No when-to-use, when-not-to-use, or alternative is given. An agent must infer that this is the tool for retrieving a full thread versus a single message, with no explicit routing guidance.

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

list_labelsA
Read-onlyIdempotent

List every label on this account (system labels like INBOX/SENT/TRASH plus user labels), with their IDs.

Label IDs from here are what modify_message_labels and search_messages' label_ids argument expect.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds genuinely useful behavior context: the result is a complete enumeration including system labels, and its IDs are the currency expected by other tools — a cross-tool contract not captured in structured fields.

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 sentences, front-loaded with what is returned, followed by the interoperability note. No filler or restated boilerplate.

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?

The scope of labels, the presence of IDs, and the downstream consumers of those IDs are all covered; since an output schema exists, return-value formatting need not be explained. Nothing an agent needs in order to call this correctly is missing.

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?

The tool takes zero parameters, so per the rubric the baseline is 4. There is nothing for the description to clarify about argument syntax.

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?

States a specific verb (list) and resource (labels) with explicit scope: every label on the account, system plus user, with IDs. An agent can immediately distinguish this from message- or thread-oriented siblings like get_message and get_thread.

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?

It explains the downstream purpose of the returned IDs — they feed modify_message_labels and search_messages' label_ids argument — which tells the agent why and when to call it. It does not name an explicit alternative for enumerating labels, but no plausible sibling competes for that job.

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

search_messagesA
Read-onlyIdempotent

Search messages using Gmail's own search syntax.

query accepts exactly what you'd type into the Gmail search box: from:, to:, subject:, after:YYYY/MM/DD, before:YYYY/MM/DD, has:attachment, is:unread, is:starred, label:name, and boolean operators (OR, -exclude, quoted "exact phrases"). Leave query empty to list recent mail instead. Each result includes the extracted plain-text body, not just a snippet.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryNo
label_idsNo
page_tokenNo
max_resultsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent and non-destructive, so the safety profile is covered. The description adds genuinely non-obvious behavior: results include the extracted plain-text body rather than just a snippet, which shapes how the agent should treat the output.

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 purpose and the query-syntax contract are front-loaded, and every clause adds usable information (syntax examples, empty-query fallback, body extraction) with no filler.

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?

An output schema exists, so return values need no explanation, and the safety profile is annotation-covered. The one gap is pagination semantics for page_token, which the description never addresses for a result-capped search.

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 parameter meaning, and it documents only `query` (with extensive syntax help). label_ids, page_token and max_results remain undocumented in both places, so the coverage gap is only partly compensated.

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?

States a specific verb (search) and resource (messages) and immediately scopes it to Gmail's own query syntax, which distinguishes it from the ID-based siblings get_message and get_thread.

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?

Gives clear context for the main input, including the fallback behavior ('Leave query empty to list recent mail instead'), which tells the agent how to enumerate rather than search. It does not name siblings or state when to prefer get_message/get_thread, so it stops short of full routing guidance.

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.

  1. 5 tool updatesv0.1.0
    • First observedget_message
    • First observedget_profile
    • First observedget_thread
    • First observedlist_labels
    • First observedsearch_messages

TDQS

A3.7/5.0

Scored across 5 tools

Disambiguation4/5

The five tools cover distinct operations: account info (get_profile), label enumeration (list_labels), search (search_messages), single-message retrieval (get_message), and thread retrieval (get_thread). The only wrinkle is that list_labels' description points at a modify_message_labels tool that does not exist, which could send an agent hunting for a phantom tool.

Naming Consistency5/5

Every tool follows a clean verb_noun snake_case pattern (get_profile, list_labels, search_messages, get_message, get_thread). No mixed conventions or stray casing.

Tool Count4/5

Five tools is a coherent, tightly scoped read-only surface with no redundant entries. It is on the lean side for a full Gmail integration, but nothing feels padded or wasteful.

Completeness2/5

The surface is read-only: no send, draft, reply, trash, archive, or label-modification operations, and Gmail's primary action (sending mail) is entirely absent. Worse, list_labels references a modify_message_labels tool that is not exposed, a dead end an agent will hit.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to interact with Gmail through OAuth2 authentication, allowing users to list, search, read emails, and create drafts with a safety-first design that prevents accidental sends by default.
    62 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to manage Gmail through natural language interactions, including sending, reading, searching emails, and managing labels with auto authentication support.
    13,749 npm
    1
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to manage Gmail through natural language, including sending, reading, searching, labeling emails, managing attachments, and performing thread operations.
    3
    MIT