gmcp 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Johnie Hjelm
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,139 +1,134 @@
1
- # GMCP
1
+ <p align="center">
2
+ <h1 align="center">🔗<br/><code>gmcp</code></h1>
3
+ <p align="center">MCP server for Gmail and Google Calendar integration.
4
+ <br/>
5
+ by <a href="https://github.com/johnie">@johnie</a>
6
+ </p>
7
+ </p>
8
+ <br/>
2
9
 
3
- MCP (Model Context Protocol) server for Google services. Provides Gmail and Google Calendar integration with 19 tools for email management and calendar operations.
10
+ <p align="center">
11
+ <a href="https://www.npmjs.com/package/gmcp" rel="nofollow"><img src="https://img.shields.io/npm/v/gmcp.svg" alt="npm"></a>
12
+ <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>
13
+ <a href="https://opensource.org/licenses/MIT" rel="nofollow"><img src="https://img.shields.io/github/license/johnie/gmcp" alt="License"></a>
14
+ <a href="https://github.com/johnie/gmcp" rel="nofollow"><img src="https://img.shields.io/github/stars/johnie/gmcp" alt="stars"></a>
15
+ </p>
4
16
 
5
- ## Gmail Tools
17
+ <br/>
18
+ <br/>
6
19
 
7
- ### Email Operations
20
+ ## Overview
8
21
 
9
- | Tool | Description |
10
- |------|-------------|
11
- | `gmcp_gmail_search_emails` | Search emails using Gmail query syntax |
12
- | `gmcp_gmail_get_email` | Get single email by message ID |
13
- | `gmcp_gmail_get_thread` | Get entire conversation thread |
14
- | `gmcp_gmail_list_attachments` | List all attachments on a message |
15
- | `gmcp_gmail_get_attachment` | Download attachment data by ID |
16
- | `gmcp_gmail_send_email` | Send email (preview + confirm safety) |
17
- | `gmcp_gmail_reply` | Reply to email in thread (preview + confirm) |
18
- | `gmcp_gmail_create_draft` | Create draft message |
19
-
20
- ### Label Management
21
-
22
- | Tool | Description |
23
- |------|-------------|
24
- | `gmcp_gmail_list_labels` | List all Gmail labels (system + custom) |
25
- | `gmcp_gmail_get_label` | Get label details and message counts |
26
- | `gmcp_gmail_create_label` | Create custom label with visibility/color settings |
27
- | `gmcp_gmail_update_label` | Update label name, visibility, or color |
28
- | `gmcp_gmail_delete_label` | Delete custom label (system labels protected) |
29
- | `gmcp_gmail_modify_labels` | Add/remove labels on a message |
30
- | `gmcp_gmail_batch_modify` | Batch label operations on multiple messages |
31
-
32
- ## Calendar Tools
22
+ 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.
33
23
 
34
- | Tool | Description |
35
- |------|-------------|
36
- | `gmcp_calendar_list_calendars` | List all calendars for account |
37
- | `gmcp_calendar_list_events` | List events with filters (time range, query, calendar) |
38
- | `gmcp_calendar_get_event` | Get single event by ID |
39
- | `gmcp_calendar_create_event` | Create event (supports recurring events, Google Meet) |
24
+ ## Installation
40
25
 
41
- ## Setup
26
+ ### NPM (Recommended)
42
27
 
43
- ### Prerequisites
28
+ ```bash
29
+ # Install globally
30
+ npm install -g gmcp
44
31
 
45
- 1. **Google Cloud Project** with Gmail API and Calendar API enabled
46
- 2. **OAuth 2.0 Client ID** (Desktop Application type)
47
- - Create at [Google Cloud Console](https://console.cloud.google.com/apis/credentials)
48
- - Download credentials JSON file
32
+ # Or run directly
33
+ npx gmcp
34
+ bunx gmcp
35
+ ```
49
36
 
50
- ### Install & Configure
37
+ ### Docker
51
38
 
52
39
  ```bash
53
- # Install dependencies
54
- bun install
55
-
56
- # Copy environment template
57
- cp .env.example .env
58
-
59
- # Edit .env with your paths
60
- # GOOGLE_CREDENTIALS_PATH=/path/to/credentials.json
61
- # GOOGLE_TOKEN_PATH=/path/to/token.json
62
- # GOOGLE_SCOPES=gmail.readonly,calendar.readonly
40
+ docker pull johnie/gmcp:latest
63
41
  ```
64
42
 
65
- ### Authenticate
66
-
67
- Run the OAuth flow to obtain tokens:
43
+ ### From Source
68
44
 
69
45
  ```bash
70
- bun run auth
46
+ git clone https://github.com/johnie/gmcp.git
47
+ cd gmcp
48
+ bun install
71
49
  ```
72
50
 
73
- Follow the prompts:
74
- 1. Visit the authorization URL in your browser
75
- 2. Authorize the app
76
- 3. Copy the authorization code from the redirected URL
77
- 4. Paste it in the terminal
51
+ ## Quick Start
78
52
 
79
- The browser will show "connection refused" after authorization - **this is expected**. Just copy the `code=` parameter from the URL.
53
+ ### 1. Google Cloud Setup
80
54
 
81
- ### Run the Server
55
+ 1. Create a project in [Google Cloud Console](https://console.cloud.google.com/)
56
+ 2. Enable **Gmail API** and **Calendar API**
57
+ 3. Create **OAuth 2.0 Client ID** (Desktop Application type)
58
+ 4. Download the credentials JSON file
59
+
60
+ ### 2. Authenticate
82
61
 
83
62
  ```bash
84
- bun run start
85
- ```
63
+ # If installed globally
64
+ gmcp-auth
86
65
 
87
- The server runs via stdio and is ready to accept MCP requests.
66
+ # Or with npx
67
+ npx gmcp-auth
88
68
 
89
- ## Configuration
69
+ # Or from source
70
+ bun run auth
71
+ ```
90
72
 
91
- ### Environment Variables
73
+ Follow the prompts to authorize. The browser will show "connection refused" after authorization - this is expected. Copy the `code=` parameter from the URL.
92
74
 
93
- | Variable | Description |
94
- |----------|-------------|
95
- | `GOOGLE_CREDENTIALS_PATH` | Path to OAuth2 credentials JSON from Google Cloud Console |
96
- | `GOOGLE_TOKEN_PATH` | Path where OAuth2 tokens will be stored |
97
- | `GOOGLE_SCOPES` | Comma-separated Gmail and Calendar API scopes (short names or full URLs) |
75
+ ### 3. Run
98
76
 
99
- ### Gmail Scopes
77
+ ```bash
78
+ # Globally installed
79
+ gmcp
100
80
 
101
- | Short Name | Description | Required For |
102
- |------------|-------------|--------------|
103
- | `gmail.readonly` | Read-only access | Search, get email, get thread, list/get attachments, list labels, get label |
104
- | `gmail.modify` | Read, create, update, delete | Modify labels, batch modify |
105
- | `gmail.labels` | Manage labels | Create label, update label, delete label, modify labels, batch modify |
106
- | `gmail.send` | Send messages | Send email, reply |
107
- | `gmail.compose` | Create drafts and send | Send email, reply, create draft |
81
+ # With npx
82
+ npx gmcp
108
83
 
109
- ### Calendar Scopes
84
+ # From source
85
+ bun run start
86
+ ```
110
87
 
111
- | Short Name | Description | Required For |
112
- |------------|-------------|--------------|
113
- | `calendar.readonly` | Read-only calendar access | List calendars, list events, get event |
114
- | `calendar.events.readonly` | Read-only events access | List events, get event |
115
- | `calendar.events` | Manage events | Create event, list events, get event |
116
- | `calendar` | Full calendar access | All calendar tools |
88
+ ## Claude Desktop Integration
117
89
 
118
- ### Scope Examples
90
+ ### Using npx (Recommended)
119
91
 
120
- ```bash
121
- # Gmail read-only
122
- GOOGLE_SCOPES=gmail.readonly
92
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
123
93
 
124
- # Gmail and Calendar read-only
125
- GOOGLE_SCOPES=gmail.readonly,calendar.readonly
94
+ ```json
95
+ {
96
+ "mcpServers": {
97
+ "gmcp": {
98
+ "command": "npx",
99
+ "args": ["-y", "gmcp"],
100
+ "env": {
101
+ "GOOGLE_CREDENTIALS_PATH": "/path/to/credentials.json",
102
+ "GOOGLE_TOKEN_PATH": "/path/to/token.json",
103
+ "GOOGLE_SCOPES": "gmail.readonly,gmail.send,calendar.events"
104
+ }
105
+ }
106
+ }
107
+ }
108
+ ```
126
109
 
127
- # Gmail read/send + Calendar read/create
128
- GOOGLE_SCOPES=gmail.readonly,gmail.send,calendar.events
110
+ ### Using Docker
129
111
 
130
- # Full access (all tools)
131
- GOOGLE_SCOPES=gmail.readonly,gmail.modify,gmail.send,gmail.labels,calendar
112
+ ```json
113
+ {
114
+ "mcpServers": {
115
+ "gmcp": {
116
+ "command": "docker",
117
+ "args": [
118
+ "run", "-i", "--rm",
119
+ "-v", "/path/to/credentials.json:/app/data/credentials.json:ro",
120
+ "-v", "/path/to/token.json:/app/data/token.json",
121
+ "-e", "GOOGLE_CREDENTIALS_PATH=/app/data/credentials.json",
122
+ "-e", "GOOGLE_TOKEN_PATH=/app/data/token.json",
123
+ "-e", "GOOGLE_SCOPES=gmail.readonly,gmail.send,calendar.events",
124
+ "johnie/gmcp:latest"
125
+ ]
126
+ }
127
+ }
128
+ }
132
129
  ```
133
130
 
134
- ## Claude Desktop Integration
135
-
136
- Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
131
+ ### Using Bun (From Source)
137
132
 
138
133
  ```json
139
134
  {
@@ -144,40 +139,83 @@ Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_
144
139
  "env": {
145
140
  "GOOGLE_CREDENTIALS_PATH": "/path/to/credentials.json",
146
141
  "GOOGLE_TOKEN_PATH": "/path/to/token.json",
147
- "GOOGLE_SCOPES": "gmail.readonly,gmail.send,gmail.labels,calendar.events"
142
+ "GOOGLE_SCOPES": "gmail.readonly,gmail.send,calendar.events"
148
143
  }
149
144
  }
150
145
  }
151
146
  }
152
147
  ```
153
148
 
154
- ## Docker
149
+ ## Tools
150
+
151
+ ### Gmail (15 tools)
152
+
153
+ | Tool | Description |
154
+ |------|-------------|
155
+ | `gmcp_gmail_search_emails` | Search with Gmail query syntax |
156
+ | `gmcp_gmail_get_email` | Get message by ID |
157
+ | `gmcp_gmail_get_thread` | Get conversation thread |
158
+ | `gmcp_gmail_list_attachments` | List attachments on message |
159
+ | `gmcp_gmail_get_attachment` | Download attachment data |
160
+ | `gmcp_gmail_send_email` | Send new email |
161
+ | `gmcp_gmail_reply` | Reply to email in thread |
162
+ | `gmcp_gmail_create_draft` | Create draft message |
163
+ | `gmcp_gmail_list_labels` | List all labels |
164
+ | `gmcp_gmail_get_label` | Get label details |
165
+ | `gmcp_gmail_create_label` | Create custom label |
166
+ | `gmcp_gmail_update_label` | Update label settings |
167
+ | `gmcp_gmail_delete_label` | Delete custom label |
168
+ | `gmcp_gmail_modify_labels` | Add/remove labels on message |
169
+ | `gmcp_gmail_batch_modify` | Batch label operations |
170
+
171
+ ### Calendar (4 tools)
172
+
173
+ | Tool | Description |
174
+ |------|-------------|
175
+ | `gmcp_calendar_list_calendars` | List all calendars |
176
+ | `gmcp_calendar_list_events` | List events with filters |
177
+ | `gmcp_calendar_get_event` | Get event by ID |
178
+ | `gmcp_calendar_create_event` | Create event (supports recurring, Google Meet) |
179
+
180
+ ## Configuration
155
181
 
156
- Run with Docker:
182
+ ### Environment Variables
183
+
184
+ | Variable | Description |
185
+ |----------|-------------|
186
+ | `GOOGLE_CREDENTIALS_PATH` | Path to OAuth2 credentials JSON |
187
+ | `GOOGLE_TOKEN_PATH` | Path to store OAuth2 tokens |
188
+ | `GOOGLE_SCOPES` | Comma-separated API scopes |
189
+
190
+ ### Scopes
191
+
192
+ | Scope | Access |
193
+ |-------|--------|
194
+ | `gmail.readonly` | Read emails and labels |
195
+ | `gmail.send` | Send emails |
196
+ | `gmail.modify` | Read, modify labels |
197
+ | `gmail.labels` | Manage labels |
198
+ | `gmail.compose` | Create drafts and send |
199
+ | `calendar.readonly` | Read calendars and events |
200
+ | `calendar.events` | Manage events |
201
+ | `calendar` | Full calendar access |
202
+
203
+ **Examples:**
157
204
 
158
205
  ```bash
159
- docker build -t gmcp-server .
160
- docker run -i \
161
- -v /path/to/credentials.json:/app/data/credentials.json:ro \
162
- -v /path/to/token.json:/app/data/token.json \
163
- -e GOOGLE_CREDENTIALS_PATH=/app/data/credentials.json \
164
- -e GOOGLE_TOKEN_PATH=/app/data/token.json \
165
- -e GOOGLE_SCOPES=gmail.readonly,gmail.labels,gmail.send,calendar.events \
166
- gmcp-server
206
+ # Read-only
207
+ GOOGLE_SCOPES=gmail.readonly,calendar.readonly
208
+
209
+ # Full access
210
+ GOOGLE_SCOPES=gmail.readonly,gmail.modify,gmail.send,calendar.events
167
211
  ```
168
212
 
169
213
  ## Testing
170
214
 
171
- Test with MCP Inspector:
172
-
173
215
  ```bash
174
216
  bunx @modelcontextprotocol/inspector bun run start
175
217
  ```
176
218
 
177
- ## Future Enhancements
178
-
179
- Potential additions include Google Drive, Google Sheets, and other Google Workspace services.
180
-
181
219
  ## License
182
220
 
183
221
  MIT
@@ -0,0 +1,2 @@
1
+ declare function runAuth(): Promise<void>;
2
+ export { runAuth };
package/dist/auth-cli.js CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  loadCredentials,
8
8
  saveTokens
9
9
  } from "./shared/chunk-n2k9eesp.js";
10
+ import"./shared/chunk-3s189drz.js";
10
11
 
11
12
  // src/auth-cli.ts
12
13
  import { createInterface } from "node:readline";
@@ -22,7 +23,7 @@ function readLine() {
22
23
  });
23
24
  });
24
25
  }
25
- async function main() {
26
+ async function runAuth() {
26
27
  console.log(`GMCP Server - OAuth2 Authentication
27
28
  `);
28
29
  const { credentialsPath, tokenPath, scopes } = getEnvConfig();
@@ -75,8 +76,6 @@ Error exchanging code for tokens:`);
75
76
  process.exit(1);
76
77
  }
77
78
  }
78
- main().catch((error) => {
79
- console.error("\x1B[31m%s\x1B[0m", "Fatal error:");
80
- console.error(error);
81
- process.exit(1);
82
- });
79
+ export {
80
+ runAuth
81
+ };
package/dist/cli.js ADDED
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ getVersion
4
+ } from "./shared/chunk-f7kh3eqv.js";
5
+ import {
6
+ __require
7
+ } from "./shared/chunk-3s189drz.js";
8
+
9
+ // src/cli.ts
10
+ var USAGE = `
11
+ Usage: gmcp [command]
12
+
13
+ Commands:
14
+ start Start the MCP server (default)
15
+ auth Run OAuth2 authentication flow
16
+
17
+ Options:
18
+ --help, -h Show this help message
19
+ --version, -v Show version number
20
+
21
+ Examples:
22
+ npx gmcp Start the MCP server
23
+ npx gmcp start Start the MCP server
24
+ npx gmcp auth Run OAuth2 authentication
25
+ `.trim();
26
+ function showHelp() {
27
+ console.log(USAGE);
28
+ }
29
+ async function showVersion() {
30
+ const version = await getVersion();
31
+ console.log(`gmcp v${version}`);
32
+ }
33
+ async function main() {
34
+ const args = process.argv.slice(2);
35
+ const command = args[0];
36
+ if (command === "--help" || command === "-h") {
37
+ showHelp();
38
+ return;
39
+ }
40
+ if (command === "--version" || command === "-v") {
41
+ await showVersion();
42
+ return;
43
+ }
44
+ if (!command || command === "start") {
45
+ const { startServer } = await import("./index.js");
46
+ await startServer();
47
+ return;
48
+ }
49
+ if (command === "auth") {
50
+ const { runAuth } = await import("./auth-cli.js");
51
+ await runAuth();
52
+ return;
53
+ }
54
+ console.error(`Unknown command: ${command}
55
+ `);
56
+ showHelp();
57
+ process.exit(1);
58
+ }
59
+ main().catch((error) => {
60
+ console.error("Fatal error:", error);
61
+ process.exit(1);
62
+ });
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Main server initialization
3
+ */
4
+ declare function startServer(): Promise<void>;
5
+ export { startServer };
package/dist/index.js CHANGED
@@ -1,9 +1,13 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ getVersion
4
+ } from "./shared/chunk-f7kh3eqv.js";
2
5
  import {
3
6
  createAuthenticatedClient,
4
7
  getEnvConfig,
5
8
  getHeader
6
9
  } from "./shared/chunk-n2k9eesp.js";
10
+ import"./shared/chunk-3s189drz.js";
7
11
 
8
12
  // src/index.ts
9
13
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -3193,9 +3197,10 @@ This tool modifies label properties. System labels (INBOX, SENT, etc.) can only
3193
3197
  - Requires \`gmail.labels\` or \`gmail.modify\` scope`;
3194
3198
 
3195
3199
  // src/index.ts
3196
- async function main() {
3200
+ async function startServer() {
3197
3201
  const logger = createLogger();
3198
- logger.info({ version: "1.0.0" }, "GMCP Server starting");
3202
+ const version = await getVersion();
3203
+ logger.info({ version }, "GMCP Server starting");
3199
3204
  const { credentialsPath, tokenPath, scopes } = getEnvConfig();
3200
3205
  logger.info({
3201
3206
  credentialsPath,
@@ -3210,7 +3215,7 @@ async function main() {
3210
3215
  logger.info("Gmail and Calendar clients initialized");
3211
3216
  const server = new McpServer({
3212
3217
  name: "gmcp-server",
3213
- version: "1.0.0"
3218
+ version
3214
3219
  });
3215
3220
  const tools = [
3216
3221
  {
@@ -3381,11 +3386,6 @@ async function main() {
3381
3386
  logger.info("MCP server connected via stdio");
3382
3387
  logger.info("Ready to accept requests");
3383
3388
  }
3384
- main().catch((error) => {
3385
- const logger = createLogger();
3386
- logger.error({
3387
- error: error instanceof Error ? error.message : String(error),
3388
- stack: error instanceof Error ? error.stack : undefined
3389
- }, "Fatal error");
3390
- process.exit(1);
3391
- });
3389
+ export {
3390
+ startServer
3391
+ };
@@ -0,0 +1,4 @@
1
+ import { createRequire } from "node:module";
2
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
+
4
+ export { __require };
@@ -0,0 +1,30 @@
1
+ // src/version.ts
2
+ import { readFile } from "node:fs/promises";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ async function findPackageJson(startDir) {
6
+ let dir = startDir;
7
+ let prevDir = "";
8
+ while (dir !== prevDir) {
9
+ const candidate = join(dir, "package.json");
10
+ try {
11
+ const content = await readFile(candidate, "utf8");
12
+ const pkg = JSON.parse(content);
13
+ if (pkg.name === "gmcp") {
14
+ return candidate;
15
+ }
16
+ } catch {}
17
+ prevDir = dir;
18
+ dir = dirname(dir);
19
+ }
20
+ throw new Error("Could not find gmcp package.json");
21
+ }
22
+ async function getVersion() {
23
+ const __dirname2 = dirname(fileURLToPath(import.meta.url));
24
+ const packagePath = await findPackageJson(__dirname2);
25
+ const content = await readFile(packagePath, "utf8");
26
+ const pkg = JSON.parse(content);
27
+ return pkg.version;
28
+ }
29
+
30
+ export { getVersion };
package/package.json CHANGED
@@ -1,14 +1,13 @@
1
1
  {
2
2
  "name": "gmcp",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "GMCP Server for Google Workspace with OAuth2 authentication",
5
5
  "module": "src/index.ts",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "type": "module",
9
9
  "bin": {
10
- "gmcp": "dist/index.js",
11
- "gmcp-auth": "dist/auth-cli.js"
10
+ "gmcp": "dist/cli.js"
12
11
  },
13
12
  "files": [
14
13
  "dist"
@@ -20,8 +19,8 @@
20
19
  }
21
20
  },
22
21
  "scripts": {
23
- "start": "bun run src/index.ts",
24
- "auth": "bun run src/auth-cli.ts",
22
+ "start": "bun run src/cli.ts",
23
+ "auth": "bun run src/cli.ts auth",
25
24
  "build": "bunup",
26
25
  "prepublishOnly": "bun run build",
27
26
  "prepare": "lefthook install",