Generic Gmail & Google Docs MCP Server
This server is an MCP integration layer that exposes reusable Gmail and Google Docs tools to MCP clients without generating content itself.
Create a Gmail draft without sending it (requires to, subject, body; supports cc, bcc, htmlBody, threadId, inReplyTo).
Send an email immediately through Gmail using the same supported fields.
Append caller-supplied text to an existing Google Doc using documentId and content.
Return structured success/error envelopes with error codes like INVALID_EMAIL, DOCUMENT_NOT_FOUND, AUTHENTICATION_FAILED, and GOOGLE_API_ERROR.
Connect over stdio for Cursor, Claude Desktop, or custom agents, or over Streamable HTTP for remote orchestrators.
Use OAuth refresh-token authentication with least-privilege Gmail and Docs scopes.
It does not create documents, generate content, read/search mail, or interpret markdown; it only performs the three listed tools.
Allows creating email drafts and sending emails through Gmail, with support for to, cc, and bcc recipients.
Allows appending content to an existing Google Doc using the document ID.
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., "@Generic Gmail & Google Docs MCP ServerDraft an email to John about the project update."
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.
Generic Gmail & Google Docs MCP Server
Standalone Model Context Protocol server that exposes reusable Gmail and Google Docs tools. It is an integration layer, not an AI agent: it does not generate content, contain prompts, or depend on Cursor, Claude Desktop, or any other host.
Compatible clients:
Cursor — stdio
Claude Desktop — stdio
Custom agents — stdio or Streamable HTTP
Remote orchestrators — Streamable HTTP
See docs/problemStatement.md and docs/architecture.md.
Architecture
MCP Layer (stdio / Streamable HTTP)
↓
Tool Layer (create_email_draft, send_email, append_to_google_doc)
↓
Service Layer (validate → call → map)
↓
Google API Layer (Gmail / Docs clients)
↓
Authentication Layer (OAuth refresh token)Tool Handler → CredentialProvider → TokenStore
↓ ↓
Google OAuth Client (refresh) .env / Secret ManagerRelated MCP server: Google Workspace MCP Server
Supported MCP tools
Tool | Purpose |
| Create a Gmail draft without sending |
| Send an email through Gmail |
| Append content to an existing Google Doc |
Each tool returns a structured envelope:
{ "success": true, "message": "...", "...": "..." }or
{ "success": false, "error": { "code": "INVALID_EMAIL", "message": "..." } }Error codes: VALIDATION_ERROR, INVALID_EMAIL, DOCUMENT_NOT_FOUND, AUTHENTICATION_FAILED, GOOGLE_API_ERROR, UNKNOWN_TOOL.
Prerequisites
Node.js 20+
A Google Cloud project with Gmail API and Google Docs API enabled
An OAuth 2.0 client (Desktop or Web) whose redirect URI matches
GOOGLE_REDIRECT_URI
Google Cloud project setup
Open Google Cloud Console.
Create or select a project.
Enable Gmail API and Google Docs API.
Configure the OAuth consent screen. Add your Google account as a test user if the app is in testing.
Create OAuth credentials (Desktop app is simplest for local use).
Set the authorized redirect URI to
http://localhost:3000/oauth2callback(or your chosen URI).
Required APIs
Gmail API
Google Docs API
OAuth scopes (least privilege)
https://www.googleapis.com/auth/gmail.compose— draft and sendhttps://www.googleapis.com/auth/documents— append to an existing Doc
The server does not request gmail.readonly, gmail.modify, or full Drive access.
Environment variables
Copy .env.example to .env (never commit .env):
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_REDIRECT_URI=http://localhost:3000/oauth2callback
GOOGLE_REFRESH_TOKEN=
GOOGLE_ACCOUNT_EMAIL=himabindu.a26@gmail.com
LOG_LEVEL=infoOptional HTTP settings: MCP_HTTP_HOST, MCP_HTTP_PORT, MCP_HTTP_PATH, MCP_HTTP_TOKEN.
Obtain a refresh token once:
npm install
npm run authThe script opens a browser and asks you to choose a Google account. Pick GOOGLE_ACCOUNT_EMAIL (default himabindu.a26@gmail.com). Chrome’s currently signed-in profile is not used as From unless you select that account. The refresh token is written to .env / token.json.
Install and build
npm install
npm test
npm run buildHow to start the server
stdio (Cursor, Claude Desktop, local custom agents):
npx tsx src/index.ts
# or
npm run build && node dist/index.jsLogs go to stderr so they never mix with the MCP JSON-RPC stream on stdout.
Streamable HTTP (remote orchestrators, HTTP custom agents):
npx tsx src/index.ts --transport http --port 8787The MCP endpoint is http://127.0.0.1:8787/mcp by default. Bind stays on loopback unless you change --host. If MCP_HTTP_TOKEN is set, send Authorization: Bearer <token> or X-MCP-Token.
Railway (public Streamable HTTP — see docs/deployment-plan.md):
npm run build
npm run start:railwayRailway injects PORT. The process binds 0.0.0.0, serves GET /health, and requires MCP_HTTP_TOKEN (plus GOOGLE_* secrets). Do not upload token.json; set GOOGLE_REFRESH_TOKEN as a Railway variable.
How to connect an MCP client
Cursor
Add to .cursor/mcp.json (this repo) or Cursor MCP settings. Use stdio (a local command), not a url. A url entry makes Cursor show Google sign-in. Stdio loads .env and sends with the refresh token — no browser login.
{
"mcpServers": {
"gmail": {
"command": "node",
"args": ["${workspaceFolder}/dist/index.js"],
"envFile": "${workspaceFolder}/.env"
}
}
}Run npm run build first. Enable gmail in Settings → MCP. In chat, use the gmail send_email tool. Do not click Authenticate and do not open Gmail in the browser.
Claude Desktop
Same JSON shape in claude_desktop_config.json (mcpServers.gmail).
Custom agents
Spawn the same command with StdioClientTransport, or connect a Streamable HTTP client to http://127.0.0.1:8787/mcp.
Remote orchestrators
Start --transport http and point the orchestrator at the MCP URL. Do not expose that port on a public network without TLS and an access token.
Example tool calls
Create a draft
{
"to": ["customer@example.com"],
"subject": "Customer Feedback Summary",
"body": "Draft email content..."
}Send email
{
"to": ["customer@example.com"],
"cc": [],
"bcc": [],
"subject": "Customer Feedback Summary",
"body": "Final email content..."
}Append to a Google Doc
{
"documentId": "google-document-id",
"content": "## Customer Feedback Summary\n\nCustomers highlighted..."
}The document id is the long id in the Doc URL: https://docs.google.com/document/d/<documentId>/edit.
Testing
npm testUnit tests mock Gmail and Docs clients. They do not need network access or real Google credentials.
Security considerations
Never hardcode credentials or commit
.env,credentials.json, ortoken.json.Access and refresh tokens are never returned in MCP responses.
The logger redacts token-like fields and does not log email bodies or document content at
info.Invalid input is rejected before any Google API call.
HTTP transport defaults to loopback. Treat it as an internal capability endpoint, not a public Google proxy.
Troubleshooting
Symptom | What to check |
Server exits on startup |
|
| Re-run |
Mail sent from the wrong Gmail | The From address is the account that clicked Allow, not Chrome’s default profile. Set |
No refresh token from | Revoke the app at https://myaccount.google.com/permissions and consent again. |
| The Doc id is wrong, or the authorized account cannot access that document. |
| One of |
Cursor/Claude cannot start the server | Use |
HTTP client 401 | Set the same |
Protocol errors on stdio | Do not write logs to stdout; this server logs to stderr only. |
Future extensions
Add generic tools only (no workflow-specific names):
read_google_doc
search_google_drive
create_google_doc
update_google_doc
list_gmail_messages
search_gmail
get_gmail_thread
create_google_sheet
append_to_google_sheetRegister a new tool, add a service method, request extra OAuth scopes only if required, and mock the Google client in tests.
Available Tools
3 toolsappend_to_google_docA
Append caller-supplied text to the end of an existing Google Doc. Does not create a document, generate content, or interpret markdown. Requires documentId and content.
| Name | Required | Description | Default |
|---|---|---|---|
| content | Yes | Text to append at the end of the document. Written as supplied; markdown is not rendered. | |
| documentId | Yes | Google Doc id from the document URL (the long id after /d/). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It usefully discloses that the operation is purely additive, takes text verbatim, and does not render markdown, but says nothing about required Google OAuth scopes, behavior on an invalid or missing documentId, or whether concurrent edits are safe — meaningful gaps for a write operation.
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?
Three short sentences, front-loaded with the core action and followed immediately by the exclusions. Every clause earns its place; nothing is padding.
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 two-parameter append tool with no output schema and no annotations, the description covers the action, its scope limits, and its input requirements. Remaining omissions (auth prerequisites, error behavior, return shape) are minor at this complexity level.
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 100%, so both parameters are already fully documented, including the documentId format and the markdown caveat. The description only restates the required parameter names, adding no meaning beyond the schema — the baseline 3 applies.
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?
States a specific verb (append) and resource (text to the end of an existing Google Doc) with explicit scope. It also preempts three likely misreadings — document creation, content generation, and markdown interpretation — so an agent can tell exactly what this does and does not do.
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 'Does not create a document, generate content, or interpret markdown' clause gives clear when-not guidance, which is the useful boundary here. It stops short of naming any alternative tool to use for those excluded cases, so it is not a full when/when-not/alternatives statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_email_draftA
Create a Gmail draft without sending it. Use this when the user wants to review or edit the message first. Requires to, subject, and body. Supports optional cc, bcc, htmlBody, threadId, and inReplyTo.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | Optional CC recipients. | |
| to | Yes | Recipient email addresses. At least one is required. | |
| bcc | No | Optional BCC recipients. | |
| body | Yes | Plain-text email body. Required and must be non-empty. | |
| subject | Yes | Email subject. Required and must be non-empty. | |
| htmlBody | No | Optional HTML alternative body. | |
| threadId | No | Gmail thread id when continuing a thread. | |
| inReplyTo | No | RFC Message-ID when replying. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It does disclose the key non-destructive trait ('without sending it'), but says nothing about authorization requirements, where the draft is stored, or what happens on failure. Adequate but with clear gaps for a mutation tool.
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?
Three short sentences, front-loaded with the operation and its non-sending nature, then usage, then parameters. No filler; 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, the description does not indicate what is returned (e.g., a draft id), which an agent might want for follow-up edits. Otherwise it is complete for a create-draft tool: it covers the operation, the when-to-use, and the full parameter set.
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 100%, so the schema already documents every field including required vs optional status. The description merely restates the required and optional parameter names without adding format or constraint meaning beyond the schema. Baseline 3 is appropriate.
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?
States a specific verb and resource ('Create a Gmail draft') and immediately qualifies scope with 'without sending it,' which cleanly separates it from the sibling send_email. An agent can identify the operation 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?
'Use this when the user wants to review or edit the message first' gives a clear usage condition that implies the contrast with send_email. It stops short of explicitly naming send_email as the alternative for immediate delivery, so it is strong context rather than full when/when-not routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_emailA
Send an email immediately through Gmail. Use this only when the user wants the message delivered now, not saved as a draft. Requires to, subject, and body. Supports optional cc, bcc, htmlBody, threadId, and inReplyTo.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | Optional CC recipients. | |
| to | Yes | Recipient email addresses. At least one is required. | |
| bcc | No | Optional BCC recipients. | |
| body | Yes | Plain-text email body. Required and must be non-empty. | |
| subject | Yes | Email subject. Required and must be non-empty. | |
| htmlBody | No | Optional HTML alternative body. | |
| threadId | No | Gmail thread id when continuing a thread. | |
| inReplyTo | No | RFC Message-ID when replying. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It usefully discloses that the message is sent immediately and cannot be a draft, but says nothing about authentication requirements, irreversibility/undo, rate limits, or what the response contains.
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?
Three tight sentences, zero filler, with the core action and the draft-vs-send decision front-loaded before the parameter summary.
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 an 8-parameter mutation tool with no annotations and no output schema, the description covers the essentials an agent needs to pick and call it. It would be stronger with a note on return value (e.g. message/thread id) or failure behavior, but nothing critical 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 description coverage is 100%, so all eight parameters are already documented in the schema. The description only restates the required trio and lists the optional names, adding no format or usage detail beyond the schema baseline.
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?
States a specific verb and resource ('Send an email... through Gmail') plus the defining behavioral trait ('immediately'). It explicitly separates itself from the draft flow, so an agent can distinguish it from create_email_draft without inspecting either 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?
Gives an explicit when/when-not rule: use only when the user wants delivery now, not a saved draft. The alternative (create_email_draft) is referenced by concept rather than named, so the routing is clear but not maximally explicit.
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
append_to_google_doc - First observed
create_email_draft - First observed
send_email
TDQS
Scored across 3 tools
The three tools target clearly distinct actions: appending to a Doc, saving a Gmail draft, and sending an email immediately. The draft-vs-send descriptions explicitly disambiguate the two email tools, and the Docs tool is orthogonal.
All names use snake_case with a leading verb (append_to_google_doc, create_email_draft, send_email), which is predictable and readable. Minor deviation in pattern shape (append_to_X vs create_X_draft vs send_X) keeps it from being perfectly uniform.
Three tools is thin for a server explicitly spanning two products (Gmail and Google Docs). While each tool earns its place, the surface is borderline for the stated multi-service scope.
Major gaps: no way to read, list, or search Gmail messages, no label/thread management, and for Docs only an append operation exists with no create, read, or fetch-content capability. This creates dead ends for common workflows.
Maintenance
Related MCP Connectors
Read and edit GA4, Search Console and Google Tag Manager from any MCP client. 29 tools.
Provides tools for searching Google Workspace documentation and much more.
Email infrastructure for AI agents — send, receive, search, and reply to email over MCP.
Manage Gmail messages, threads, labels, drafts, and settings from your workflows. Send and organiz…
Related MCP Servers
- AlicenseBqualityDmaintenanceExposes Gmail (send/draft) and Google Docs (append) capabilities as tools for any MCP-compliant agent.344 npmISC
- FlicenseBqualityCmaintenanceEnables sending emails, drafting emails, and appending text to Google Docs via MCP tools.3-
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to send and draft Gmail emails and append content to Google Docs through standardized MCP tools.10 npmMIT
- AlicenseNot gradedqualityBmaintenanceEnables creating and sending Gmail drafts and appending content to Google Docs through MCP tools.334 npmMIT