gmail-sendas
Allows sending emails from Gmail send-as aliases, listing configured send-as addresses, and downloading inbound email attachments via the Gmail API.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@gmail-sendasSend an email from oberonlogistics.com to john@acme.com with subject 'Contract' and body 'Please sign.'"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
gmail-sendas
Cursor plugin (Gmail sendAs + attachments) that fills two gaps in the stock Gmail MCP:
From / sendAs — send mail as a verified Workspace alias
Attachment bytes — download inbound file data the stock connector cannot return
Keep stock Gmail MCP for inbox search, labels, and triage. This plugin is not a Gmail replacement.
File tree
.
├── .cursor-plugin/plugin.json # name, displayName, OAuth variables (no secrets)
├── mcp.json # stdio MCP; env wires ${GOOGLE_*} into Node
├── skills/gmail-sendas/SKILL.md
├── src/
│ ├── index.js # stdio entry
│ ├── server.js # MCP JSON-RPC + three tools
│ ├── gmail.js # fetch + MIME + OAuth refresh
│ └── secrets.js # creds check + redaction
├── scripts/oauth-setup.js # one-time helper; prints refresh token only
├── test/ # mocked; no live Google calls
├── assets/logo.svg
├── package.json
├── LICENSE # MIT
└── README.mdNo rules, hooks, agents, or commands.
Related MCP server: google-workspace-mcp-server
Tools
Tool | API | Returns |
|
|
|
|
|
|
|
|
|
send_as required arguments: from (sendAs alias email), to, subject, and body (plain text) and/or html. Optional: cc, bcc. The From header is set to the alias.
OAuth tokens are never returned or logged.
Data shapes
/** @typedef {{ sendAsEmail: string, displayName?: string, isPrimary?: boolean, isDefault?: boolean, verificationStatus?: string }} SendAs */
/** @typedef {{ id: string, threadId?: string }} SendResult */
/** @typedef {{ size: number, data: string, attachmentId: string, filename?: string, path?: string }} AttachmentBody */AttachmentBody.data is standard base64 of the decoded bytes (Gmail's wire format is base64url). path is present only when a disk write was requested.
Implementation choice
Zero runtime npm dependencies. Node 18+ fetch refreshes the access token and calls Gmail REST. googleapis is not used — three endpoints do not justify the install. The MCP layer is a small stdio JSON-RPC 2.0 shim (newline-delimited, plus Content-Length read for older clients) instead of @modelcontextprotocol/sdk.
Auth (Jim — one-time, local)
Sign in as the Google Workspace user who owns the sendAs aliases (the Oberon mailbox that sends as oberonlogistics.com / ogholdings.biz / oberon.group — typically the primary Workspace user). Do this on a trusted machine. Never commit tokens or paste them into git, issues, or screenshots.
1. Google Cloud project
Open Google Cloud Console.
Create or select a project.
APIs & Services → Library → enable Gmail API.
OAuth consent screen: User type Internal (Workspace). App name can be
gmail-sendas.Add scopes (minimum):
https://www.googleapis.com/auth/gmail.sendhttps://www.googleapis.com/auth/gmail.readonlyhttps://www.googleapis.com/auth/gmail.settings.basic
Credentials → Create credentials → OAuth client ID → application type Desktop app (or Web).
Add authorized redirect URI:
http://127.0.0.1:53682/oauth2callbackCopy the client ID and client secret. Leave them out of the repo.
2. Print a refresh token (stdout only)
cd /path/to/gmail-sendas-connector
export GOOGLE_CLIENT_ID='your-client-id.apps.googleusercontent.com'
export GOOGLE_CLIENT_SECRET='your-client-secret'
node scripts/oauth-setup.jsThe script prints an authorization URL on stderr. Open it, sign in as the Workspace user, and approve. On success, stdout is a single refresh token — nothing else. Copy that value.
If Google does not return a refresh token, revoke the app under Google Account → Apps with access and re-run. The helper always uses access_type=offline and prompt=consent.
Optional: OAUTH_PORT (default 53682) if that port is busy. The redirect URI in Cloud Console must match.
3. Cursor → Plugins → Configure
Install or enable this plugin, then set:
Variable | Value |
| from Cloud Console |
| from Cloud Console |
| stdout from |
mcp.json injects those ${VAR} placeholders into the Node process. The server exchanges the refresh token for a short-lived access token at runtime.
Tests (no live Google)
npm testRequires Node 18+. Coverage (all mocked):
list_send_asresponse parsingsend_asbuilds the From header andusers.messages.send{ raw }bodyget_attachmentdecodes base64url and writes a file of the expected byte lengthMissing-credential / refresh errors never echo secrets
Live demo (after Jim finishes auth)
Not run in CI. After Configure is filled:
In Cursor, ask: List my Gmail sendAs aliases. Expect verified rows for the logistics / holdings / group domains as configured on the mailbox.
Send a test: Send a short test to myself From the logistics alias (
send_aswithfrom= that*.oberonlogistics.comaddress). Confirm the message in Gmail shows the alias as From. Note the returnedidonly.Download a known inbound PDF: use stock Gmail to find a message and its
attachmentId, then Save that attachment to/tmp/rate-con.pdfviaget_attachment. Confirm the file opens and the byte length is non-zero.
From-routing (no secrets)
Logistics / carrier / dispatch →
*.oberonlogistics.comsendAsHoldings / entity →
*.ogholdings.bizsendAsDefault workspace identity →
*.oberon.groupsendAs
Always prefer list_send_as over hardcoding addresses.
Non-goals
Full Gmail replacement (filters, drafts UI, label management)
Calendar
Sending outbound file attachments (inbound download only)
Cursor Marketplace publish — owner decides later
License
MIT
Available Tools
3 toolsget_attachmentA
Download Gmail attachment bytes (GET users.me.messages.attachments). Stock Gmail MCP cannot return file bytes. Decodes base64url; writes to disk when path is set; returns size, filename, attachmentId, and standard base64.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | If set, write decoded bytes to this file (or directory) | |
| filename | No | ||
| messageId | Yes | ||
| attachmentId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
There are no annotations, so the description carries the full burden. It states that it decodes base64url, writes to disk when path is set, and returns size, filename, attachmentId, and standard base64. This is useful behavioral disclosure, though it leaves some edge behavior (e.g., directory vs file path handling, errors) unspecified.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences with no filler. It front-loads the core purpose, then adds valuable technical context about the workaround, decoding, disk writing, and return values. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no annotations, this definition is reasonably informative but still incomplete. It covers the main behavior and return fields, but leaves path semantics ambiguous ('file (or directory)'), does not explain the filename parameter, and does not address authentication or failure modes. It is adequate for basic invocation but not fully self-contained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 25%, so the description must compensate. It reinforces the path parameter behavior, but it does not explain the expected roles of messageId, attachmentId, or filename. The names are suggestive, but the description does not clarify how these inputs map to the API call or how filename interacts with path.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the verb and resource: 'Download Gmail attachment bytes' with the specific API endpoint. It is immediately obvious what the tool does even though the sibling tools (list_send_as, send_as) are unrelated. It does not explicitly differentiate from those siblings, but the explicit endpoint and comparison to 'Stock Gmail MCP' provide strong clarity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for use: use this tool when attachment bytes are needed, especially because 'Stock Gmail MCP cannot return file bytes.' It does not provide explicit exclusions or say when not to use it, but the context is sufficient to guide an agent for this Gmail attachment scenario.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_send_asA
List Gmail sendAs aliases (GET users.me.settings.sendAs). Use this plugin only for sendAs + attachment bytes. Use stock Gmail MCP for inbox search, labels, and triage.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the transparency burden. It discloses that this is a read-only GET operation, which is helpful, but it does not mention authentication requirements, pagination, rate limits, or the response shape. Adequate for a trivial list call, but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences: the first defines the action and endpoint, the second scopes usage against alternatives. There is no filler or redundant restatement of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter read-only list operation with no output schema, the description is mostly complete: it names the endpoint and gives selection guidance. It does not describe the return value shape, which would have been helpful given the absence of an output schema, but the operation's simplicity keeps the gap small.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and an empty input schema, so the description does not need to explain parameter meanings. Per the baseline for zero-parameter tools, the endpoint and listing scope provide enough context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('List'), a specific resource ('Gmail sendAs aliases'), and the exact API endpoint (GET users.me.settings.sendAs), making the tool's purpose unmistakable. It also implicitly differentiates itself from the sibling get_attachment and from stock Gmail MCP by scoping the plugin to sendAs and attachment work.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear guidance: 'Use this plugin only for sendAs + attachment bytes' and explicitly says to use 'stock Gmail MCP for inbox search, labels, and triage.' This names an alternative for other tasks, though it does not explicitly distinguish list_send_as from the closely named sibling send_as.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_asA
Send mail From a Workspace sendAs alias via users.messages.send (RFC2822 MIME raw, base64url). Required: from (alias email), to, subject, and body text and/or html. Optional: cc, bcc. Returns message id (and threadId) only — never tokens.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | ||
| to | Yes | Recipient email(s), comma-separated | |
| bcc | No | ||
| body | No | Plain-text body | |
| from | Yes | sendAs alias email; written to the From header | |
| html | No | HTML body (with or instead of body) | |
| subject | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations present, the description carries the full disclosure burden and does well: it states the encoding (RFC2822 MIME raw, base64url), the return shape (message id and threadId only), and a security-relevant guarantee ('never tokens'). It does not cover error behavior or sending limits, but the most important behavioral facts are disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences with no filler: purpose and encoding up front, then required/optional params and return behavior. Every clause earns its place, including the non-obvious 'never tokens' caveat.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter, no-annotation, no-output-schema send tool, the description supplies the full calling contract: required fields, optional fields, encoding, and return value. The main gap is error semantics (invalid alias, auth failure), but nothing an agent needs to construct a valid call is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 57%, and the description adds some meaning: it clarifies that at least one of body/html is effectively required despite the schema listing only from/to/subject as required, and it labels cc/bcc as optional. However, it mostly restates schema-provided facts (alias email for from, HTML with or instead of body) and leaves cc/bcc/subject value formats to inference.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a concrete verb+resource — 'Send mail From a Workspace sendAs alias' — and names the backing API method (users.messages.send). This clearly sets it apart from siblings list_send_as (enumerate aliases) and get_attachment (retrieve a file), so an agent can route correctly without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It enumerates the exact invocation contract: required from (alias), to, subject, and body text and/or html, with cc/bcc optional. This is clear context for calling. It stops short of explicit exclusions like 'use list_send_as to discover valid aliases first', so it doesn't quite reach a 5.
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.
3 tool updates
v1.0.0- First observed
get_attachment - First observed
list_send_as - First observed
send_as
TDQS
Scored across 3 tools
Each tool has a distinct purpose: list_send_as retrieves aliases, send_as sends email from an alias, and get_attachment downloads attachment bytes. There is no functional overlap between them.
Tool names follow a consistent verb_noun pattern (list_send_as, send_as, get_attachment). Minor deviation: send_as uses a verb+preposition rather than verb_noun, but it remains clear and predictable.
Three tools is a small but focused set for a specialized server that explicitly complements a stock Gmail MCP. The count is appropriate for the narrow scope, though it is on the lean side.
The server covers its stated domain: listing aliases, sending from an alias, and retrieving attachment bytes. It intentionally defers inbox search, labels, and triage to another MCP, so the only minor gap is lack of an update/delete operation for sendAs aliases, which is likely out of scope.
Maintenance
Related MCP Connectors
Email infrastructure for AI agents — send, receive, search, and reply to email over MCP.
Your agent needs a mailbox of its own — to receive, thread, draft and send, with attachments, without borrowing your personal inbox or your company's SMTP. **What you can ask for** • "Create an inbox for this agent and tell me its address." • "Read the new messages in this thread and draft a reply." • "Send this message with the attachment and wait for the response." • "Search this inbox for everything from that domain." • "Show delivery metrics and the events on this inbox." **How to use it** Point any MCP client at https://mcp.aisa.one/mail/mcp and sign in with OAuth — there is no key to create or paste. 49 tools: create and delete inboxes, list and read messages, raw message bodies, attachments, threads, drafts and draft attachments, send and reply, message search, inbox events, metrics, and list entries — reads and writes. **Why this rather than the source** A real inbox an agent owns, rather than an SMTP credential it borrows from a human. **It is also a door to the rest** The same login reaches 26 sources and 580+ operations. Find the contact elsewhere in the catalogue, then write to them from here — without adding a second server. **What it costs** Finding and inspecting an operation is free. Running one is billed per call at API prices, with no seat and no monthly minimum, and every call takes max_price_usd so an agent cannot overspend by accident. **Where else it reaches** https://mcp.aisa.one/sales/mcp finds the person to write to.
Manage Gmail messages, threads, labels, drafts, and settings from your workflows. Send and organiz…
Manage Gmail end-to-end: search, read, send, draft, label, and organize threads. Automate workflow…
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables interaction with Gmail through the MCP protocol, supporting sending, reading, searching, replying, forwarding, managing drafts and labels, and saving attachments.6 npm3MIT
- AlicenseNot gradedqualityCmaintenanceEnables sending emails and managing drafts in Gmail, and appending content to Google Docs, via MCP-compatible clients.1,091 npmMIT
- FlicenseNot gradedqualityCmaintenanceEnables reading, searching, sending, and drafting Gmail emails via MCP tools, with support for multiple accounts and background notifications.-
- AlicenseNot gradedqualityCmaintenanceMCP server for Gmail with full read/write coverage: search, send, reply, drafts, labels, filters, vacation responder, auto-forwarding, signature, and attachment handling (download and PDF export). Uses the Gmail API with the gmail.modify scope to prevent permanent deletion, and requires explicit confirmation for sensitive actions.MIT