CONNECT APP
Build with Gmail
Communication
- OAuth
MCP
Give your agent Gmail tools
Every Gmail action is exposed as an MCP tool on Pipedream's remote server. Point a client at it with your end user's ID and Connect resolves that user's Gmail account for each tool call — you store no tokens.
// accessToken: mint a short-lived token with the Connect SDK — see the MCP guide
const transport = new StreamableHTTPClientTransport(
new URL("https://remote.mcp.pipedream.net/v3"),
{
requestInit: {
headers: {
Authorization: `Bearer ${accessToken}`,
"x-pd-project-id": "{project_id}",
"x-pd-environment": "production",
"x-pd-external-user-id": "{external_user_id}", // any stable ID for this user in your system
"x-pd-app-slug": "gmail",
},
},
},
)
const mcp = new Client({ name: "my-agent", version: "1.0.0" })
await mcp.connect(transport)
const { tools } = await mcp.listTools()
// e.g. run Add Label to Email:
const result = await mcp.callTool({
name: "gmail-add-label-to-email",
arguments: {
message: "Message",
addLabelIds: ["Labels"],
},
})# access_token: mint a short-lived token with the Connect SDK — see the MCP guide
headers = {
"Authorization": f"Bearer {access_token}",
"x-pd-project-id": "{project_id}",
"x-pd-environment": "production",
"x-pd-external-user-id": "{external_user_id}", # any stable ID for this user in your system
"x-pd-app-slug": "gmail",
}
async with streamablehttp_client("https://remote.mcp.pipedream.net/v3", headers=headers) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
# e.g. run Add Label to Email:
result = await session.call_tool("gmail-add-label-to-email", {
"message": "Message",
"addLabelIds": ["Labels"],
})API PROXY
Call the Gmail API directly
For an endpoint with no pre-built tool, the Connect proxy forwards your request to the Gmail API with the connected user's credentials attached. You store no tokens and write no refresh logic.
const resp = await pd.proxy.get({
externalUserId: "{external_user_id}", // any stable ID for this user in your system
accountId: "apn_xxxxxxx",
url: "https://www.googleapis.com/oauth2/v1/userinfo",
})
// Any allowed Gmail endpoint works here. Pipedream attaches the
// connected account's credentials to the outgoing request.# The path segment is the target URL, URL-safe base64 encoded:
# https://www.googleapis.com/oauth2/v1/userinfo
curl "https://api.pipedream.com/v1/connect/{project_id}/proxy/aHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vb2F1dGgyL3YxL3VzZXJpbmZv?external_user_id={external_user_id}&account_id=apn_xxxxxxx" \
-H "Authorization: Bearer {access_token}" \
-H "x-pd-environment: production"SDK
Run Gmail actions from your backend
Connect a user's Gmail account once, then run Add Label to Email on their behalf from your own code — TypeScript, Python, or plain HTTP.
import { PipedreamClient } from "@pipedream/sdk"
const pd = new PipedreamClient({
projectId: process.env.PIPEDREAM_PROJECT_ID!,
clientId: process.env.PIPEDREAM_CLIENT_ID!,
clientSecret: process.env.PIPEDREAM_CLIENT_SECRET!,
projectEnvironment: "production",
})
const result = await pd.actions.run({
id: "gmail-add-label-to-email",
externalUserId: "{external_user_id}", // any stable ID for this user in your system
configuredProps: {
gmail: { authProvisionId: "apn_xxxxxxx" },
message: "Message",
addLabelIds: ["Labels"],
},
})from pipedream import Pipedream
pd = Pipedream(
client_id="{oauth_client_id}",
client_secret="{oauth_client_secret}",
project_id="{project_id}",
project_environment="production",
)
result = pd.actions.run(
id="gmail-add-label-to-email",
external_user_id="{external_user_id}", # any stable ID for this user in your system
configured_props={
"gmail": {"authProvisionId": "apn_xxxxxxx"},
"message": "Message",
"addLabelIds": ["Labels"],
},
)curl -X POST https://api.pipedream.com/v1/connect/{project_id}/actions/run \
-H "Content-Type: application/json" \
-H "X-PD-Environment: production" \
-H "Authorization: Bearer {access_token}" \
-d '{
"external_user_id": "{external_user_id}",
"id": "gmail-add-label-to-email",
"configured_props": {
"gmail": { "authProvisionId": "apn_xxxxxxx" },
"message": "Message",
"addLabelIds": ["Labels"]
}
}'TOOLS
Gmail actions
On-demand operations your product or agent can configure and run on behalf of a connected user.
-
Add Label to Email
actionAdd label(s) to an email message. See the docsWritev0.0.16 -
Archive Email
actionArchive an email message. See the documentationWritev0.0.11 -
Bulk Archive Emails
actionArchive multiple emails at once. See the documentationWritev0.0.1 -
Create Draft
actionCreate an unsent draft in the authenticated Gmail account. Same parameter shape as Send Email — the difference is the message is saved to Drafts instead of being sent. For a reply-draft, passinReplyToMessageId(from Find Emails / Get Thread); the subject,References,In-Reply-To, andthreadIdare derived from the referenced message.bodyTypecontrols whetherbodyis treated as plain text (default) or HTML. To draft to yourself, pass"me"into— the action resolves it to the authenticated user's email address. No pre-call to Get Current User required. Attachments usefile-refinputs and require matchingattachmentFilenames[]entries. See the documentation.Writev0.2.3 -
Create Label
actionCreate a new user label in the authenticated Gmail mailbox and return its ID. Call this before Modify Labels whenever the label the user wants to apply doesn't yet exist — List Labels will tell you what's already there. Idempotent: if a label with the same name already exists, the action swallows the 409, looks it up by name, and returns the existing label withalreadyExisted: trueso the caller can proceed. Nested labels are expressed with/— e.g.Clients/Acmecreates or targets a sub-label underClients.coloris optional; when provided, bothtextColorandbackgroundColormust be supplied together and must come from Gmail's fixed palette. See the documentation.Writev0.1.3 -
Delete Email
actionMoves the specified message to the trash. See the documentationWritev0.0.5 -
Delete Label
actionImmediately and permanently delete a user-created label from the authenticated Gmail mailbox, removing it from every message and thread it was applied to. Only user-created labels can be deleted — Gmail's built-in system labels (INBOX,SENT,SPAM,TRASH, etc.) cannot. This deletes the label definition itself; to merely detach a label from specific messages without removing it, use Modify Labels withremoveLabelsinstead. See the documentation.Writev0.0.3 -
Download Attachment
actionDownload a Gmail message attachment to/tmpand return its path + metadata. File Stash syncs the file and exposes a presigned download URL so the caller can retrieve it. Call Find Emails (withformat: "full") or Get Thread first — attachment IDs only appear in full-format message reads; each returned message'spayload.parts[]enumerates attachments as{ body.attachmentId, filename, mimeType }. Pass the enclosing message'sidasmessageIdand the part'sbody.attachmentIdasattachmentId. Iffilenameis omitted, the action looks up the attachment's filename from the message payload. SetconvertToPdf: trueto convert image / HTML / plain-text / DOCX attachments to PDF during download; other MIME types are rejected. See the documentation.Read-onlyv0.1.3 -
Find Emails
actionSearch the user's Gmail mailbox with Gmail's native query syntax and return matching messages (headers + snippet by default; full bodies when requested). Use this tool for every "find", "search", "list my", or "show me" email intent. Theqparameter accepts the full Gmail search operator set — combine operators freely:from:alan@ingen.com is:unread newer_than:7d has:attachment subject:"DNA sequences". Common operators:from:,to:,subject:,has:attachment,filename:pdf,is:unread,is:starred,label:INBOX,newer_than:7d,older_than:1m,after:2025/01/01,before:2025/12/31,category:primary.labelIdsaccepts either raw label IDs (INBOX,STARRED) or user-visible names (Clients/Acme) — names are resolved server-side via List Labels. Each returned message carriesid,threadId,labelIds, the decodedsubject/sender/recipient/date, and asnippet. Withformat: "full"the decoded body text andpayload.parts[].body.attachmentId+filename+mimeTypeare also included — feed those into Download Attachment, or feedthreadIdinto Get Thread for the whole conversation. Setfieldson every call to name just what you need — message records are large, and a wide search returns tens of thousands of characters that crowd out the rest of the task.idandthreadIdare always returned. To BROWSE or COUNT, use["subject", "sender", "date"]. To READ or SUMMARISE — "catch me up", "what did X say about Y", "is there anything I need to reply to" — use["subject", "sender", "date", "bodyText"].bodyTextis the decoded plain-text body (HTML converted, MIME scaffolding and attachments stripped), about half the size of the rawpayload, and requesting it fetches full messages for you. Never answer a question about what an email SAYS fromsnippet— it is a fixed ~200-character prefix, so the sentence you need is usually past its end, and nothing in a snippet indicates that it was cut. Where the snippet is all you asked for and content was likely cut, the message carriessnippetTruncated: true.formatstaysmetadataunless you need the raw MIME tree for Download Attachment, in which case passformat: "full"and requestpayload. Responses are capped. Over the cap: if you namedfields, whole messages are dropped rather than your chosen fields being removed, and the note says how many of how many are shown — narrowqand retry. If you named none, messages are compacted instead so counts stay accurate.bodyTextshrinks toward a floor before anything is dropped, flagging each cut message withbodyTruncated: true. See the documentation and Gmail search operators.Read-onlyv0.3.1 -
Get Current User
actionReturns the authenticated Gmail user's name, email address, and mailbox stats (total messages and threads). Call this first when the user says 'my emails', 'my inbox', or needs identity context. Use the returnedemailAddressto identify the user's own messages in Find Emails results. See the documentation.Read-onlyv0.0.5 -
Get Send As Alias
actionGet a send as alias for the authenticated user. See the documentationRead-onlyv0.0.8 -
Get Thread
actionFetch an entire Gmail thread (conversation) by thread ID — returns every message in order with headers, decoded body text, and attachment metadata. Use this after Find Emails when the user wants the full conversation rather than a single message. Each result from Find Emails includes athreadIdyou can pass here. Withformat: full(default) each message includes decodedtext/htmlbodies and attachment metadata. Useformat: metadatato skip bodies and get only headers + labelIds — useful for large threads. Responses are capped — oversized threads fall back tometadata-level detail (or are further truncated from the tail) with a[truncated]marker so the caller knows to narrow the request. See the documentation.Read-onlyv0.2.1 -
List Labels
actionList every label in the authenticated user's mailbox (system labels likeINBOX,SENT,TRASH,STARRED,UNREADand user-created labels). Call this before Modify Labels or Find Emails when you need to target a label that the user named rather than an obvious system label — it resolves a name likeClients/Acmeto its opaque label ID. User labels are returned first, then system labels. See the documentation.Read-onlyv0.1.3 -
List Send as a Delegate Options
actionRetrieves available options for the Send as a Delegate field.Read-onlyv0.0.4 -
List Send As Aliases
actionList all send as aliases for the authenticated user. See the documentationRead-onlyv0.0.8 -
List Signature Options
actionRetrieves available options for the Signature field.Read-onlyv0.0.4 -
Modify Labels
actionAdd and/or remove labels on one or more Gmail messages in a single call. In Gmail, most inbox-state operations are label mutations under the hood, so this one tool covers archive / trash / untrash / star / unstar / mark-read / mark-unread / apply-label / remove-label.
Use this whenever the user asks you to star, unstar, flag, archive, file, sort, label, tag, categorise, move, trash, delete, restore, or mark mail as read or unread — there is no separate tool for any of those. Pair it with Find Emails to turn a description of the mail ("the invoice from billing", "everything from last week") into the
messageIdsthis tool needs. Apply it even when some messages already carry the target state: the operation is idempotent, and the user asked for an outcome, not a diff.Do NOT use this to set up filters, rules, or any automation that applies to mail that has not arrived yet. This tool labels messages that already exist, one batch at a time. Gmail filters, auto-forwarding, and the vacation responder are settings-level features with no action in this set — if the user asks to "automatically label incoming mail", "skip the inbox from now on", or "set up a rule", say so outright rather than gathering criteria you cannot act on, and point them at Gmail's own settings.
⚠️ Trashing is destructive — confirm before you do it. Adding
TRASHremoves mail from the mailbox, and nothing in this tool set can permanently delete or restore in bulk beyond untrashing. When the request would trash mail the user did not enumerate individually ("trash everything from X", "clear out this label", "delete the old ones"), first say how many messages match and what they are, and get explicit confirmation. Every other operation here is safely reversible and needs no confirmation.Common recipes (pass these in
addLabels/removeLabels):- Archive →
removeLabels: ["INBOX"] - Move to trash →
addLabels: ["TRASH"] - Untrash (restore) →
removeLabels: ["TRASH"],addLabels: ["INBOX"] - Star →
addLabels: ["STARRED"] - Unstar →
removeLabels: ["STARRED"] - Mark read →
removeLabels: ["UNREAD"] - Mark unread →
addLabels: ["UNREAD"] - Apply a user label →
addLabels: ["Clients/Acme"](pass the name or the label ID) - Apply user label AND archive →
addLabels: ["Clients/Acme"],removeLabels: ["INBOX"]
addLabelsandremoveLabelsaccept either raw label IDs (system labels likeINBOX,STARRED,UNREAD,TRASH) or user-visible label names — names are resolved via List Labels before the API call. Use Create Label first if you need to apply a brand-new label that doesn't yet exist. See the documentation.Writev0.0.4 - Archive →
-
Remove Label from Email
actionRemove label(s) from an email message. See the docsWritev0.0.14 -
Send Email
actionSend a new email OR reply to an existing thread from the authenticated Gmail account. For a fresh message, setto/subject/body; leaveinReplyToMessageIdblank. To reply to a thread, pass theidof any message in that thread asinReplyToMessageId— the tool preserves threading (References,In-Reply-To,threadId) and auto-prefixesRe:on the subject. Use Find Emails or Get Thread to locate the message ID. SetreplyAll: trueto fan-out to the originalFrom/To/Cc(minus the user's own address); otherwise only the original sender is addressed.bodyTypecontrols whetherbodyis treated as plain text (default) or HTML. To send to yourself, pass"me"into— the action resolves it to the authenticated user's email address. No pre-call to Get Current User required. Attachments: for small inline content (the common case in MCP / cloud runs), setattachmentContentto the file's text contents andattachmentFilenameto its name. For files already on disk (Pipedream workflows, File Stash), useattachments[]+attachmentFilenames[]instead. See the documentation.Writev0.3.3 -
Update Signature for Email in Organization
actionUpdate the signature for a specific email address in an organization. A Google Cloud service account with delegated domain-wide authority is required for this action. See the documentationWritev0.0.19 -
Update Signature for Primary Email Address
actionUpdate the signature for the primary email address. See the documentationWritev0.0.18
-
New Attachment Received
triggerEmit new event for each attachment in a message received. This source is capped at 100 max new messages per run.v0.2.7 -
New Email Matching Search
triggerEmit new event when an email matching the search criteria is received. This source is capped at 100 max new messages per run.v0.1.7 -
New Email Received
triggerEmit new event when a new email is received.v0.3.7 -
New Labeled Email
triggerEmit new event when a new email is labeled.v0.1.7 -
New Sent Email
triggerEmit new event for each new email sent. (Maximum of 100 events emited per execution)v0.1.7
MULTI-APP
Use Gmail with other popular apps
Most products don't stop at one integration. Pair Gmail with the other apps your users rely on, and ship use cases that span both.
- App slug
- gmail
- Authentication
- OAuth
- Categories
- Communication
- Actions
- 21
- Triggers
- 5
- API proxy
- Available
OAuth scopes
These are the scopes Pipedream's managed Gmail OAuth client requests when one of your users connects an account. Supply your own OAuth client to request a different set.
- https://www.googleapis.com/auth/gmail.labels
- https://www.googleapis.com/auth/gmail.send
- https://www.googleapis.com/auth/gmail.modify
- https://www.googleapis.com/auth/gmail.compose
- https://www.googleapis.com/auth/gmail.settings.basic