| declare function runAuth(): Promise<void>; | ||
| export { runAuth }; |
+62
| #!/usr/bin/env node | ||
| import { | ||
| getVersion | ||
| } from "./shared/chunk-f7kh3eqv.js"; | ||
| import { | ||
| __require | ||
| } from "./shared/chunk-3s189drz.js"; | ||
| // src/cli.ts | ||
| var USAGE = ` | ||
| Usage: gmcp [command] | ||
| Commands: | ||
| start Start the MCP server (default) | ||
| auth Run OAuth2 authentication flow | ||
| Options: | ||
| --help, -h Show this help message | ||
| --version, -v Show version number | ||
| Examples: | ||
| npx gmcp Start the MCP server | ||
| npx gmcp start Start the MCP server | ||
| npx gmcp auth Run OAuth2 authentication | ||
| `.trim(); | ||
| function showHelp() { | ||
| console.log(USAGE); | ||
| } | ||
| async function showVersion() { | ||
| const version = await getVersion(); | ||
| console.log(`gmcp v${version}`); | ||
| } | ||
| async function main() { | ||
| const args = process.argv.slice(2); | ||
| const command = args[0]; | ||
| if (command === "--help" || command === "-h") { | ||
| showHelp(); | ||
| return; | ||
| } | ||
| if (command === "--version" || command === "-v") { | ||
| await showVersion(); | ||
| return; | ||
| } | ||
| if (!command || command === "start") { | ||
| const { startServer } = await import("./index.js"); | ||
| await startServer(); | ||
| return; | ||
| } | ||
| if (command === "auth") { | ||
| const { runAuth } = await import("./auth-cli.js"); | ||
| await runAuth(); | ||
| return; | ||
| } | ||
| console.error(`Unknown command: ${command} | ||
| `); | ||
| showHelp(); | ||
| process.exit(1); | ||
| } | ||
| main().catch((error) => { | ||
| console.error("Fatal error:", error); | ||
| process.exit(1); | ||
| }); |
| /** | ||
| * Main server initialization | ||
| */ | ||
| declare function startServer(): Promise<void>; | ||
| export { startServer }; |
| import { createRequire } from "node:module"; | ||
| var __require = /* @__PURE__ */ createRequire(import.meta.url); | ||
| export { __require }; |
| // src/version.ts | ||
| import { readFile } from "node:fs/promises"; | ||
| import { dirname, join } from "node:path"; | ||
| import { fileURLToPath } from "node:url"; | ||
| async function findPackageJson(startDir) { | ||
| let dir = startDir; | ||
| let prevDir = ""; | ||
| while (dir !== prevDir) { | ||
| const candidate = join(dir, "package.json"); | ||
| try { | ||
| const content = await readFile(candidate, "utf8"); | ||
| const pkg = JSON.parse(content); | ||
| if (pkg.name === "gmcp") { | ||
| return candidate; | ||
| } | ||
| } catch {} | ||
| prevDir = dir; | ||
| dir = dirname(dir); | ||
| } | ||
| throw new Error("Could not find gmcp package.json"); | ||
| } | ||
| async function getVersion() { | ||
| const __dirname2 = dirname(fileURLToPath(import.meta.url)); | ||
| const packagePath = await findPackageJson(__dirname2); | ||
| const content = await readFile(packagePath, "utf8"); | ||
| const pkg = JSON.parse(content); | ||
| return pkg.version; | ||
| } | ||
| export { getVersion }; |
+21
| MIT License | ||
| Copyright (c) 2025 Johnie Hjelm | ||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. |
+5
-6
@@ -10,2 +10,3 @@ #!/usr/bin/env node | ||
| } from "./shared/chunk-n2k9eesp.js"; | ||
| import"./shared/chunk-3s189drz.js"; | ||
@@ -26,3 +27,3 @@ // src/auth-cli.ts | ||
| } | ||
| async function main() { | ||
| async function runAuth() { | ||
| console.log(`GMCP Server - OAuth2 Authentication | ||
@@ -80,6 +81,4 @@ `); | ||
| } | ||
| main().catch((error) => { | ||
| console.error("\x1B[31m%s\x1B[0m", "Fatal error:"); | ||
| console.error(error); | ||
| process.exit(1); | ||
| }); | ||
| export { | ||
| runAuth | ||
| }; |
+4
-5
| { | ||
| "name": "gmcp", | ||
| "version": "0.2.0", | ||
| "version": "0.2.1", | ||
| "description": "GMCP Server for Google Workspace with OAuth2 authentication", | ||
@@ -10,4 +10,3 @@ "module": "src/index.ts", | ||
| "bin": { | ||
| "gmcp": "dist/index.js", | ||
| "gmcp-auth": "dist/auth-cli.js" | ||
| "gmcp": "dist/cli.js" | ||
| }, | ||
@@ -24,4 +23,4 @@ "files": [ | ||
| "scripts": { | ||
| "start": "bun run src/index.ts", | ||
| "auth": "bun run src/auth-cli.ts", | ||
| "start": "bun run src/cli.ts", | ||
| "auth": "bun run src/cli.ts auth", | ||
| "build": "bunup", | ||
@@ -28,0 +27,0 @@ "prepublishOnly": "bun run build", |
+155
-117
@@ -1,138 +0,133 @@ | ||
| # GMCP | ||
| <p align="center"> | ||
| <h1 align="center">🔗<br/><code>gmcp</code></h1> | ||
| <p align="center">MCP server for Gmail and Google Calendar integration. | ||
| <br/> | ||
| by <a href="https://github.com/johnie">@johnie</a> | ||
| </p> | ||
| </p> | ||
| <br/> | ||
| MCP (Model Context Protocol) server for Google services. Provides Gmail and Google Calendar integration with 19 tools for email management and calendar operations. | ||
| <p align="center"> | ||
| <a href="https://www.npmjs.com/package/gmcp" rel="nofollow"><img src="https://img.shields.io/npm/v/gmcp.svg" alt="npm"></a> | ||
| <a href="https://hub.docker.com/r/johnie/gmcp" rel="nofollow"><img src="https://img.shields.io/docker/pulls/johnie/gmcp" alt="Docker Pulls"></a> | ||
| <a href="https://opensource.org/licenses/MIT" rel="nofollow"><img src="https://img.shields.io/github/license/johnie/gmcp" alt="License"></a> | ||
| <a href="https://github.com/johnie/gmcp" rel="nofollow"><img src="https://img.shields.io/github/stars/johnie/gmcp" alt="stars"></a> | ||
| </p> | ||
| ## Gmail Tools | ||
| <br/> | ||
| <br/> | ||
| ### Email Operations | ||
| ## Overview | ||
| | Tool | Description | | ||
| |------|-------------| | ||
| | `gmcp_gmail_search_emails` | Search emails using Gmail query syntax | | ||
| | `gmcp_gmail_get_email` | Get single email by message ID | | ||
| | `gmcp_gmail_get_thread` | Get entire conversation thread | | ||
| | `gmcp_gmail_list_attachments` | List all attachments on a message | | ||
| | `gmcp_gmail_get_attachment` | Download attachment data by ID | | ||
| | `gmcp_gmail_send_email` | Send email (preview + confirm safety) | | ||
| | `gmcp_gmail_reply` | Reply to email in thread (preview + confirm) | | ||
| | `gmcp_gmail_create_draft` | Create draft message | | ||
| GMCP is a [Model Context Protocol](https://modelcontextprotocol.io/) server that enables LLMs to interact with Gmail and Google Calendar. It provides tools for searching emails, managing labels, sending messages, and working with calendar events—all through secure OAuth2 authentication. | ||
| ### Label Management | ||
| ## Installation | ||
| | Tool | Description | | ||
| |------|-------------| | ||
| | `gmcp_gmail_list_labels` | List all Gmail labels (system + custom) | | ||
| | `gmcp_gmail_get_label` | Get label details and message counts | | ||
| | `gmcp_gmail_create_label` | Create custom label with visibility/color settings | | ||
| | `gmcp_gmail_update_label` | Update label name, visibility, or color | | ||
| | `gmcp_gmail_delete_label` | Delete custom label (system labels protected) | | ||
| | `gmcp_gmail_modify_labels` | Add/remove labels on a message | | ||
| | `gmcp_gmail_batch_modify` | Batch label operations on multiple messages | | ||
| ### NPM (Recommended) | ||
| ## Calendar Tools | ||
| ```bash | ||
| # Install globally | ||
| npm install -g gmcp | ||
| | Tool | Description | | ||
| |------|-------------| | ||
| | `gmcp_calendar_list_calendars` | List all calendars for account | | ||
| | `gmcp_calendar_list_events` | List events with filters (time range, query, calendar) | | ||
| | `gmcp_calendar_get_event` | Get single event by ID | | ||
| | `gmcp_calendar_create_event` | Create event (supports recurring events, Google Meet) | | ||
| # Or run directly | ||
| npx gmcp | ||
| bunx gmcp | ||
| ``` | ||
| ## Setup | ||
| ### Docker | ||
| ### Prerequisites | ||
| ```bash | ||
| docker pull johnie/gmcp:latest | ||
| ``` | ||
| 1. **Google Cloud Project** with Gmail API and Calendar API enabled | ||
| 2. **OAuth 2.0 Client ID** (Desktop Application type) | ||
| - Create at [Google Cloud Console](https://console.cloud.google.com/apis/credentials) | ||
| - Download credentials JSON file | ||
| ### From Source | ||
| ### Install & Configure | ||
| ```bash | ||
| # Install dependencies | ||
| git clone https://github.com/johnie/gmcp.git | ||
| cd gmcp | ||
| bun install | ||
| ``` | ||
| # Copy environment template | ||
| cp .env.example .env | ||
| ## Quick Start | ||
| # Edit .env with your paths | ||
| # GOOGLE_CREDENTIALS_PATH=/path/to/credentials.json | ||
| # GOOGLE_TOKEN_PATH=/path/to/token.json | ||
| # GOOGLE_SCOPES=gmail.readonly,calendar.readonly | ||
| ``` | ||
| ### 1. Google Cloud Setup | ||
| ### Authenticate | ||
| 1. Create a project in [Google Cloud Console](https://console.cloud.google.com/) | ||
| 2. Enable **Gmail API** and **Calendar API** | ||
| 3. Create **OAuth 2.0 Client ID** (Desktop Application type) | ||
| 4. Download the credentials JSON file | ||
| Run the OAuth flow to obtain tokens: | ||
| ### 2. Authenticate | ||
| ```bash | ||
| # If installed globally | ||
| gmcp-auth | ||
| # Or with npx | ||
| npx gmcp-auth | ||
| # Or from source | ||
| bun run auth | ||
| ``` | ||
| Follow the prompts: | ||
| 1. Visit the authorization URL in your browser | ||
| 2. Authorize the app | ||
| 3. Copy the authorization code from the redirected URL | ||
| 4. Paste it in the terminal | ||
| Follow the prompts to authorize. The browser will show "connection refused" after authorization - this is expected. Copy the `code=` parameter from the URL. | ||
| The browser will show "connection refused" after authorization - **this is expected**. Just copy the `code=` parameter from the URL. | ||
| ### 3. Run | ||
| ### Run the Server | ||
| ```bash | ||
| # Globally installed | ||
| gmcp | ||
| ```bash | ||
| # With npx | ||
| npx gmcp | ||
| # From source | ||
| bun run start | ||
| ``` | ||
| The server runs via stdio and is ready to accept MCP requests. | ||
| ## Claude Desktop Integration | ||
| ## Configuration | ||
| ### Using npx (Recommended) | ||
| ### Environment Variables | ||
| Add to `~/Library/Application Support/Claude/claude_desktop_config.json`: | ||
| | Variable | Description | | ||
| |----------|-------------| | ||
| | `GOOGLE_CREDENTIALS_PATH` | Path to OAuth2 credentials JSON from Google Cloud Console | | ||
| | `GOOGLE_TOKEN_PATH` | Path where OAuth2 tokens will be stored | | ||
| | `GOOGLE_SCOPES` | Comma-separated Gmail and Calendar API scopes (short names or full URLs) | | ||
| ```json | ||
| { | ||
| "mcpServers": { | ||
| "gmcp": { | ||
| "command": "npx", | ||
| "args": ["-y", "gmcp"], | ||
| "env": { | ||
| "GOOGLE_CREDENTIALS_PATH": "/path/to/credentials.json", | ||
| "GOOGLE_TOKEN_PATH": "/path/to/token.json", | ||
| "GOOGLE_SCOPES": "gmail.readonly,gmail.send,calendar.events" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
| ### Gmail Scopes | ||
| ### Using Docker | ||
| | Short Name | Description | Required For | | ||
| |------------|-------------|--------------| | ||
| | `gmail.readonly` | Read-only access | Search, get email, get thread, list/get attachments, list labels, get label | | ||
| | `gmail.modify` | Read, create, update, delete | Modify labels, batch modify | | ||
| | `gmail.labels` | Manage labels | Create label, update label, delete label, modify labels, batch modify | | ||
| | `gmail.send` | Send messages | Send email, reply | | ||
| | `gmail.compose` | Create drafts and send | Send email, reply, create draft | | ||
| ### Calendar Scopes | ||
| | Short Name | Description | Required For | | ||
| |------------|-------------|--------------| | ||
| | `calendar.readonly` | Read-only calendar access | List calendars, list events, get event | | ||
| | `calendar.events.readonly` | Read-only events access | List events, get event | | ||
| | `calendar.events` | Manage events | Create event, list events, get event | | ||
| | `calendar` | Full calendar access | All calendar tools | | ||
| ### Scope Examples | ||
| ```bash | ||
| # Gmail read-only | ||
| GOOGLE_SCOPES=gmail.readonly | ||
| # Gmail and Calendar read-only | ||
| GOOGLE_SCOPES=gmail.readonly,calendar.readonly | ||
| # Gmail read/send + Calendar read/create | ||
| GOOGLE_SCOPES=gmail.readonly,gmail.send,calendar.events | ||
| # Full access (all tools) | ||
| GOOGLE_SCOPES=gmail.readonly,gmail.modify,gmail.send,gmail.labels,calendar | ||
| ```json | ||
| { | ||
| "mcpServers": { | ||
| "gmcp": { | ||
| "command": "docker", | ||
| "args": [ | ||
| "run", "-i", "--rm", | ||
| "-v", "/path/to/credentials.json:/app/data/credentials.json:ro", | ||
| "-v", "/path/to/token.json:/app/data/token.json", | ||
| "-e", "GOOGLE_CREDENTIALS_PATH=/app/data/credentials.json", | ||
| "-e", "GOOGLE_TOKEN_PATH=/app/data/token.json", | ||
| "-e", "GOOGLE_SCOPES=gmail.readonly,gmail.send,calendar.events", | ||
| "johnie/gmcp:latest" | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
| ## Claude Desktop Integration | ||
| ### Using Bun (From Source) | ||
| Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS): | ||
| ```json | ||
@@ -147,3 +142,3 @@ { | ||
| "GOOGLE_TOKEN_PATH": "/path/to/token.json", | ||
| "GOOGLE_SCOPES": "gmail.readonly,gmail.send,gmail.labels,calendar.events" | ||
| "GOOGLE_SCOPES": "gmail.readonly,gmail.send,calendar.events" | ||
| } | ||
@@ -155,15 +150,64 @@ } | ||
| ## Docker | ||
| ## Tools | ||
| Run with Docker: | ||
| ### Gmail (15 tools) | ||
| | Tool | Description | | ||
| |------|-------------| | ||
| | `gmcp_gmail_search_emails` | Search with Gmail query syntax | | ||
| | `gmcp_gmail_get_email` | Get message by ID | | ||
| | `gmcp_gmail_get_thread` | Get conversation thread | | ||
| | `gmcp_gmail_list_attachments` | List attachments on message | | ||
| | `gmcp_gmail_get_attachment` | Download attachment data | | ||
| | `gmcp_gmail_send_email` | Send new email | | ||
| | `gmcp_gmail_reply` | Reply to email in thread | | ||
| | `gmcp_gmail_create_draft` | Create draft message | | ||
| | `gmcp_gmail_list_labels` | List all labels | | ||
| | `gmcp_gmail_get_label` | Get label details | | ||
| | `gmcp_gmail_create_label` | Create custom label | | ||
| | `gmcp_gmail_update_label` | Update label settings | | ||
| | `gmcp_gmail_delete_label` | Delete custom label | | ||
| | `gmcp_gmail_modify_labels` | Add/remove labels on message | | ||
| | `gmcp_gmail_batch_modify` | Batch label operations | | ||
| ### Calendar (4 tools) | ||
| | Tool | Description | | ||
| |------|-------------| | ||
| | `gmcp_calendar_list_calendars` | List all calendars | | ||
| | `gmcp_calendar_list_events` | List events with filters | | ||
| | `gmcp_calendar_get_event` | Get event by ID | | ||
| | `gmcp_calendar_create_event` | Create event (supports recurring, Google Meet) | | ||
| ## Configuration | ||
| ### Environment Variables | ||
| | Variable | Description | | ||
| |----------|-------------| | ||
| | `GOOGLE_CREDENTIALS_PATH` | Path to OAuth2 credentials JSON | | ||
| | `GOOGLE_TOKEN_PATH` | Path to store OAuth2 tokens | | ||
| | `GOOGLE_SCOPES` | Comma-separated API scopes | | ||
| ### Scopes | ||
| | Scope | Access | | ||
| |-------|--------| | ||
| | `gmail.readonly` | Read emails and labels | | ||
| | `gmail.send` | Send emails | | ||
| | `gmail.modify` | Read, modify labels | | ||
| | `gmail.labels` | Manage labels | | ||
| | `gmail.compose` | Create drafts and send | | ||
| | `calendar.readonly` | Read calendars and events | | ||
| | `calendar.events` | Manage events | | ||
| | `calendar` | Full calendar access | | ||
| **Examples:** | ||
| ```bash | ||
| docker build -t gmcp-server . | ||
| docker run -i \ | ||
| -v /path/to/credentials.json:/app/data/credentials.json:ro \ | ||
| -v /path/to/token.json:/app/data/token.json \ | ||
| -e GOOGLE_CREDENTIALS_PATH=/app/data/credentials.json \ | ||
| -e GOOGLE_TOKEN_PATH=/app/data/token.json \ | ||
| -e GOOGLE_SCOPES=gmail.readonly,gmail.labels,gmail.send,calendar.events \ | ||
| gmcp-server | ||
| # Read-only | ||
| GOOGLE_SCOPES=gmail.readonly,calendar.readonly | ||
| # Full access | ||
| GOOGLE_SCOPES=gmail.readonly,gmail.modify,gmail.send,calendar.events | ||
| ``` | ||
@@ -173,4 +217,2 @@ | ||
| Test with MCP Inspector: | ||
| ```bash | ||
@@ -180,8 +222,4 @@ bunx @modelcontextprotocol/inspector bun run start | ||
| ## Future Enhancements | ||
| Potential additions include Google Drive, Google Sheets, and other Google Workspace services. | ||
| ## License | ||
| MIT |
Sorry, the diff of this file is too big to display
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 5 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 5 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
146819
2.32%11
120%3539
2.79%222
20.65%