gmcp 0.2.0 → 0.3.0
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 +21 -0
- package/README.md +170 -118
- package/dist/auth-cli.d.ts +2 -0
- package/dist/auth-cli.js +24 -30
- package/dist/cli.js +57 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +11 -11
- package/dist/shared/chunk-3s189drz.js +4 -0
- package/dist/shared/chunk-f7kh3eqv.js +30 -0
- package/package.json +7 -5
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,182 +1,234 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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://github.com/johnie/gmcp" rel="nofollow"><img src="https://img.shields.io/github/stars/johnie/gmcp" alt="stars"></a>
|
|
14
|
+
</p>
|
|
4
15
|
|
|
5
|
-
|
|
16
|
+
<br/>
|
|
17
|
+
<br/>
|
|
6
18
|
|
|
7
|
-
|
|
19
|
+
## Overview
|
|
8
20
|
|
|
9
|
-
|
|
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 |
|
|
21
|
+
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.
|
|
19
22
|
|
|
20
|
-
|
|
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 |
|
|
23
|
+
## Installation
|
|
31
24
|
|
|
32
|
-
|
|
25
|
+
### NPM (Recommended)
|
|
33
26
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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) |
|
|
40
|
-
|
|
41
|
-
## Setup
|
|
42
|
-
|
|
43
|
-
### Prerequisites
|
|
27
|
+
```bash
|
|
28
|
+
# Install globally
|
|
29
|
+
npm install -g gmcp
|
|
44
30
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
31
|
+
# Or run directly
|
|
32
|
+
npx gmcp
|
|
33
|
+
bunx gmcp
|
|
34
|
+
```
|
|
49
35
|
|
|
50
|
-
###
|
|
36
|
+
### Docker
|
|
51
37
|
|
|
52
38
|
```bash
|
|
53
|
-
|
|
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
|
|
39
|
+
docker pull johnie/gmcp:latest
|
|
63
40
|
```
|
|
64
41
|
|
|
65
|
-
###
|
|
66
|
-
|
|
67
|
-
Run the OAuth flow to obtain tokens:
|
|
42
|
+
### From Source
|
|
68
43
|
|
|
69
44
|
```bash
|
|
70
|
-
|
|
45
|
+
git clone https://github.com/johnie/gmcp.git
|
|
46
|
+
cd gmcp
|
|
47
|
+
bun install
|
|
71
48
|
```
|
|
72
49
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
3. Copy the authorization code from the redirected URL
|
|
77
|
-
4. Paste it in the terminal
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
### 1. Google Cloud Setup
|
|
78
53
|
|
|
79
|
-
|
|
54
|
+
1. Create a project in [Google Cloud Console](https://console.cloud.google.com/)
|
|
55
|
+
2. Enable **Gmail API** and **Calendar API**
|
|
56
|
+
3. Create **OAuth 2.0 Client ID** (Desktop Application type)
|
|
57
|
+
4. Download the credentials JSON file
|
|
80
58
|
|
|
81
|
-
###
|
|
59
|
+
### 2. Authenticate
|
|
82
60
|
|
|
83
61
|
```bash
|
|
84
|
-
|
|
85
|
-
|
|
62
|
+
# If installed globally
|
|
63
|
+
gmcp auth
|
|
86
64
|
|
|
87
|
-
|
|
65
|
+
# Or with npx
|
|
66
|
+
npx gmcp auth
|
|
88
67
|
|
|
89
|
-
|
|
68
|
+
# Or from source
|
|
69
|
+
bun run auth
|
|
70
|
+
```
|
|
90
71
|
|
|
91
|
-
|
|
72
|
+
Follow the prompts to authorize. The browser will show "connection refused" after authorization - this is expected. Copy the `code=` parameter from the URL.
|
|
92
73
|
|
|
93
|
-
|
|
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) |
|
|
74
|
+
### 3. Run
|
|
98
75
|
|
|
99
|
-
|
|
76
|
+
```bash
|
|
77
|
+
# Globally installed
|
|
78
|
+
gmcp start
|
|
79
|
+
# or just: gmcp
|
|
100
80
|
|
|
101
|
-
|
|
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 start
|
|
108
83
|
|
|
109
|
-
|
|
84
|
+
# From source
|
|
85
|
+
bun run start
|
|
86
|
+
```
|
|
110
87
|
|
|
111
|
-
|
|
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
|
-
###
|
|
90
|
+
### Using npx (Recommended)
|
|
119
91
|
|
|
120
|
-
|
|
121
|
-
# Gmail read-only
|
|
122
|
-
GOOGLE_SCOPES=gmail.readonly
|
|
92
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
123
93
|
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
128
|
-
GOOGLE_SCOPES=gmail.readonly,gmail.send,calendar.events
|
|
110
|
+
### Using Docker
|
|
129
111
|
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
|
|
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
|
{
|
|
140
135
|
"mcpServers": {
|
|
141
136
|
"gmcp": {
|
|
142
137
|
"command": "bun",
|
|
143
|
-
"args": ["run", "/path/to/gmcp/src/
|
|
138
|
+
"args": ["run", "/path/to/gmcp/src/cli.ts"],
|
|
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,
|
|
142
|
+
"GOOGLE_SCOPES": "gmail.readonly,gmail.send,calendar.events"
|
|
148
143
|
}
|
|
149
144
|
}
|
|
150
145
|
}
|
|
151
146
|
}
|
|
152
147
|
```
|
|
153
148
|
|
|
154
|
-
##
|
|
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)
|
|
155
172
|
|
|
156
|
-
|
|
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
|
|
181
|
+
|
|
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
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
+
## CLI Reference
|
|
170
214
|
|
|
171
|
-
|
|
215
|
+
```
|
|
216
|
+
gmcp [command]
|
|
172
217
|
|
|
173
|
-
|
|
174
|
-
|
|
218
|
+
Commands:
|
|
219
|
+
start Start MCP server (default)
|
|
220
|
+
auth Run OAuth2 authentication flow
|
|
221
|
+
|
|
222
|
+
Options:
|
|
223
|
+
--help, -h Show usage
|
|
224
|
+
--version, -v Show version
|
|
175
225
|
```
|
|
176
226
|
|
|
177
|
-
##
|
|
227
|
+
## Testing
|
|
178
228
|
|
|
179
|
-
|
|
229
|
+
```bash
|
|
230
|
+
bunx @modelcontextprotocol/inspector bun run start
|
|
231
|
+
```
|
|
180
232
|
|
|
181
233
|
## License
|
|
182
234
|
|
package/dist/auth-cli.js
CHANGED
|
@@ -7,22 +7,12 @@ 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
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
input: process.stdin,
|
|
16
|
-
output: process.stdout
|
|
17
|
-
});
|
|
18
|
-
return new Promise((resolve) => {
|
|
19
|
-
rl.on("line", (line) => {
|
|
20
|
-
rl.close();
|
|
21
|
-
resolve(line.trim());
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
async function main() {
|
|
13
|
+
import { input } from "@inquirer/prompts";
|
|
14
|
+
import kleur from "kleur";
|
|
15
|
+
async function runAuth() {
|
|
26
16
|
console.log(`GMCP Server - OAuth2 Authentication
|
|
27
17
|
`);
|
|
28
18
|
const { credentialsPath, tokenPath, scopes } = getEnvConfig();
|
|
@@ -38,7 +28,7 @@ async function main() {
|
|
|
38
28
|
========================================`);
|
|
39
29
|
console.log("STEP 1: Visit this URL to authorize:");
|
|
40
30
|
console.log("========================================");
|
|
41
|
-
console.log(
|
|
31
|
+
console.log(kleur.cyan(authUrl));
|
|
42
32
|
console.log(`
|
|
43
33
|
========================================`);
|
|
44
34
|
console.log("STEP 2: After authorizing:");
|
|
@@ -53,30 +43,34 @@ Copy the entire code after "code=" (the long string before "&scope")`);
|
|
|
53
43
|
console.log(`
|
|
54
44
|
========================================`);
|
|
55
45
|
console.log("STEP 3: Paste the authorization code below:");
|
|
56
|
-
console.log(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
46
|
+
console.log(`========================================
|
|
47
|
+
`);
|
|
48
|
+
const code = await input({
|
|
49
|
+
message: "Authorization code:",
|
|
50
|
+
required: true,
|
|
51
|
+
validate: (value) => {
|
|
52
|
+
if (value.length < 10) {
|
|
53
|
+
return "Authorization code appears too short";
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
62
58
|
console.log(`
|
|
63
59
|
Exchanging authorization code for tokens...`);
|
|
64
60
|
try {
|
|
65
61
|
const tokens = await getTokensFromCode(oauth2Client, code);
|
|
66
62
|
await saveTokens(tokenPath, tokens);
|
|
67
|
-
console.log(
|
|
68
|
-
Success! Tokens saved to
|
|
63
|
+
console.log(kleur.green(`
|
|
64
|
+
Success! Tokens saved to ${tokenPath}`));
|
|
69
65
|
console.log(`
|
|
70
66
|
You can now run the MCP server with: npx gmcp`);
|
|
71
67
|
} catch (error) {
|
|
72
|
-
console.error(
|
|
73
|
-
Error exchanging code for tokens:`);
|
|
68
|
+
console.error(kleur.red(`
|
|
69
|
+
Error exchanging code for tokens:`));
|
|
74
70
|
console.error(error);
|
|
75
71
|
process.exit(1);
|
|
76
72
|
}
|
|
77
73
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
process.exit(1);
|
|
82
|
-
});
|
|
74
|
+
export {
|
|
75
|
+
runAuth
|
|
76
|
+
};
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
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
|
+
import { run } from "@stricli/core";
|
|
11
|
+
|
|
12
|
+
// src/cli/app.ts
|
|
13
|
+
import { buildApplication, buildRouteMap } from "@stricli/core";
|
|
14
|
+
|
|
15
|
+
// src/cli/commands/auth.ts
|
|
16
|
+
import { buildCommand } from "@stricli/core";
|
|
17
|
+
var authCommand = buildCommand({
|
|
18
|
+
func: async () => {
|
|
19
|
+
const { runAuth } = await import("./auth-cli.js");
|
|
20
|
+
await runAuth();
|
|
21
|
+
},
|
|
22
|
+
parameters: {},
|
|
23
|
+
docs: { brief: "Run OAuth2 authentication flow" }
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// src/cli/commands/start.ts
|
|
27
|
+
import { buildCommand as buildCommand2 } from "@stricli/core";
|
|
28
|
+
var startCommand = buildCommand2({
|
|
29
|
+
func: async () => {
|
|
30
|
+
const { startServer } = await import("./index.js");
|
|
31
|
+
await startServer();
|
|
32
|
+
},
|
|
33
|
+
parameters: {},
|
|
34
|
+
docs: { brief: "Start the MCP server" }
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// src/cli/app.ts
|
|
38
|
+
var routes = buildRouteMap({
|
|
39
|
+
routes: {
|
|
40
|
+
start: startCommand,
|
|
41
|
+
auth: authCommand
|
|
42
|
+
},
|
|
43
|
+
docs: { brief: "GMCP - Gmail and Calendar MCP Server" }
|
|
44
|
+
});
|
|
45
|
+
async function createApp() {
|
|
46
|
+
const version = await getVersion();
|
|
47
|
+
return buildApplication(routes, {
|
|
48
|
+
name: "gmcp",
|
|
49
|
+
versionInfo: { currentVersion: version }
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// src/cli.ts
|
|
54
|
+
var app = await createApp();
|
|
55
|
+
var args = process.argv.slice(2);
|
|
56
|
+
var effectiveArgs = args.length === 0 ? ["start"] : args;
|
|
57
|
+
await run(app, effectiveArgs, { process });
|
package/dist/index.d.ts
ADDED
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
|
|
3200
|
+
async function startServer() {
|
|
3197
3201
|
const logger = createLogger();
|
|
3198
|
-
|
|
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
|
|
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
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
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,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.
|
|
3
|
+
"version": "0.3.0",
|
|
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/
|
|
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/
|
|
24
|
-
"auth": "bun run src/
|
|
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",
|
|
@@ -45,9 +44,12 @@
|
|
|
45
44
|
"anthropic"
|
|
46
45
|
],
|
|
47
46
|
"dependencies": {
|
|
47
|
+
"@inquirer/prompts": "^8.2.0",
|
|
48
48
|
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
49
|
+
"@stricli/core": "^1.2.5",
|
|
49
50
|
"googleapis": "^170.1.0",
|
|
50
51
|
"json2md": "^2.0.3",
|
|
52
|
+
"kleur": "^4.1.5",
|
|
51
53
|
"pino": "^9.7.0",
|
|
52
54
|
"pino-pretty": "^13.0.0",
|
|
53
55
|
"zod": "^4.3.6"
|