gogcli-mcp-drive 2.7.1 → 2.18.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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -0
- package/SKILL.md +1 -0
- package/dist/index.js +20051 -19610
- package/manifest.json +29 -1
- package/package.json +3 -2
- package/server.json +2 -2
- package/src/index.ts +7 -9
- package/src/tools/drive-extra.ts +37 -4
- package/tests/tools/drive-extra.test.ts +127 -69
- package/tsconfig.json +1 -1
package/manifest.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"manifest_version": "0.3",
|
|
4
4
|
"name": "gogcli-mcp-drive",
|
|
5
5
|
"display_name": "gogcli (Drive)",
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.18.0",
|
|
7
7
|
"description": "Extended Google Drive for Claude via gogcli — auth + full Drive support (upload, download, permissions, comments, shared drives)",
|
|
8
8
|
"author": {
|
|
9
9
|
"name": "Chris Hall",
|
|
@@ -61,6 +61,18 @@
|
|
|
61
61
|
"name": "gog_auth_add",
|
|
62
62
|
"description": "Authorize a Google account via browser-based OAuth"
|
|
63
63
|
},
|
|
64
|
+
{
|
|
65
|
+
"name": "gog_auth_health",
|
|
66
|
+
"description": "Live per-account token health: validity, age, and pre-expiry warnings (detects invalid_grant)"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "gog_auth_add_url",
|
|
70
|
+
"description": "Begin remote/headless OAuth (step 1): return a sign-in URL to open in any browser"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"name": "gog_auth_add_complete",
|
|
74
|
+
"description": "Complete remote/headless OAuth (step 2): exchange the pasted redirect URL and store the token"
|
|
75
|
+
},
|
|
64
76
|
{
|
|
65
77
|
"name": "gog_auth_list",
|
|
66
78
|
"description": "List all Google accounts stored in gogcli"
|
|
@@ -85,6 +97,14 @@
|
|
|
85
97
|
"name": "gog_drive_search",
|
|
86
98
|
"description": "Full-text search across Drive"
|
|
87
99
|
},
|
|
100
|
+
{
|
|
101
|
+
"name": "gog_drive_extract_text",
|
|
102
|
+
"description": "Extract readable text from a Drive PDF/image/doc (OCR-converts, returns text; no host FS)"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"name": "gog_drive_read_bytes",
|
|
106
|
+
"description": "Fetch a Drive file's raw bytes as a base64 resource (local stdio only; connector returns text-only notice)"
|
|
107
|
+
},
|
|
88
108
|
{
|
|
89
109
|
"name": "gog_drive_get",
|
|
90
110
|
"description": "Get file metadata"
|
|
@@ -121,6 +141,10 @@
|
|
|
121
141
|
"name": "gog_drive_upload",
|
|
122
142
|
"description": "Upload a local file, optionally replacing an existing file or converting to Google format"
|
|
123
143
|
},
|
|
144
|
+
{
|
|
145
|
+
"name": "gog_drive_sync_push",
|
|
146
|
+
"description": "Recursively push a local directory's contents into a Drive folder (additive; no remote deletes)"
|
|
147
|
+
},
|
|
124
148
|
{
|
|
125
149
|
"name": "gog_drive_copy",
|
|
126
150
|
"description": "Copy a file to a new file"
|
|
@@ -197,6 +221,10 @@
|
|
|
197
221
|
"name": "gog_drive_revisions_get",
|
|
198
222
|
"description": "Get one revision of a file by revision ID"
|
|
199
223
|
},
|
|
224
|
+
{
|
|
225
|
+
"name": "gog_drive_shortcut_create",
|
|
226
|
+
"description": "Create a Drive shortcut to a file or folder in a destination folder"
|
|
227
|
+
},
|
|
200
228
|
{
|
|
201
229
|
"name": "gog_drive_labels_list",
|
|
202
230
|
"description": "List Drive label schemas"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gogcli-mcp-drive",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.18.0",
|
|
4
4
|
"mcpName": "io.github.chrischall/gogcli-mcp-drive",
|
|
5
5
|
"description": "Extended Google Drive MCP server via gogcli — auth + full Drive support (upload/download/permissions/comments/shared drives)",
|
|
6
6
|
"author": "Claude Code (AI) <https://www.anthropic.com/claude>",
|
|
@@ -19,11 +19,12 @@
|
|
|
19
19
|
"build": "tsc --noEmit && npm run bundle",
|
|
20
20
|
"bundle": "node ../../scripts/bundle.js src/index.ts dist/index.js",
|
|
21
21
|
"typecheck": "tsc --noEmit",
|
|
22
|
-
"test": "vitest run",
|
|
22
|
+
"test": "vitest run --coverage",
|
|
23
23
|
"test:watch": "vitest",
|
|
24
24
|
"test:coverage": "vitest run --coverage"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
+
"@chrischall/mcp-utils": "^0.13.3",
|
|
27
28
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
28
29
|
"zod": "^4.4.3"
|
|
29
30
|
},
|
package/server.json
CHANGED
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"source": "github",
|
|
8
8
|
"subfolder": "packages/gogcli-mcp-drive"
|
|
9
9
|
},
|
|
10
|
-
"version": "2.
|
|
10
|
+
"version": "2.18.0",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "gogcli-mcp-drive",
|
|
15
|
-
"version": "2.
|
|
15
|
+
"version": "2.18.0",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
},
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { runMcp } from '@chrischall/mcp-utils';
|
|
3
|
+
import { VERSION, authToolsFor, registerDriveTools } from '../../gogcli-mcp/src/lib.js';
|
|
4
4
|
import { registerExtraDriveTools } from './tools/drive-extra.js';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const transport = new StdioServerTransport();
|
|
12
|
-
await server.connect(transport);
|
|
6
|
+
await runMcp({
|
|
7
|
+
name: 'gogcli-drive',
|
|
8
|
+
version: VERSION,
|
|
9
|
+
tools: [authToolsFor('drive,driveactivity,drivelabels'), registerDriveTools, registerExtraDriveTools],
|
|
10
|
+
});
|
package/src/tools/drive-extra.ts
CHANGED
|
@@ -10,12 +10,14 @@ export function registerExtraDriveTools(server: McpServer): void {
|
|
|
10
10
|
fileId: z.string().describe('File ID to download'),
|
|
11
11
|
out: z.string().optional().describe('Output file path (default: gogcli config dir)'),
|
|
12
12
|
format: z.string().optional().describe('Export format for Google Docs: pdf, csv, xlsx, pptx, txt, png, docx, md (default: inferred)'),
|
|
13
|
+
overwrite: z.boolean().optional().describe('Overwrite the output file if it already exists (gog refuses otherwise)'),
|
|
13
14
|
account: accountParam,
|
|
14
15
|
},
|
|
15
|
-
}, async ({ fileId, out, format, account }) => {
|
|
16
|
+
}, async ({ fileId, out, format, overwrite, account }) => {
|
|
16
17
|
const args = ['drive', 'download', fileId];
|
|
17
18
|
if (out) args.push(`--out=${out}`);
|
|
18
19
|
if (format) args.push(`--format=${format}`);
|
|
20
|
+
if (overwrite) args.push('--overwrite');
|
|
19
21
|
return runOrDiagnose(args, { account });
|
|
20
22
|
});
|
|
21
23
|
|
|
@@ -45,6 +47,23 @@ export function registerExtraDriveTools(server: McpServer): void {
|
|
|
45
47
|
return runOrDiagnose(args, { account });
|
|
46
48
|
});
|
|
47
49
|
|
|
50
|
+
server.registerTool('gog_drive_sync_push', {
|
|
51
|
+
description: 'Recursively push a local directory\'s contents into an existing Drive folder — uploads new files, updates changed ones (matched by name + MD5), and creates missing subfolders. One-way and additive: it never deletes anything on Drive. Use dryRun to preview the planned actions first.',
|
|
52
|
+
annotations: { destructiveHint: true },
|
|
53
|
+
inputSchema: {
|
|
54
|
+
localPath: z.string().describe('Local directory to push (its contents are mirrored into the parent folder)'),
|
|
55
|
+
parent: z.string().describe('Existing destination Drive folder ID'),
|
|
56
|
+
dryRun: z.boolean().optional().describe('Preview the planned actions without making any changes'),
|
|
57
|
+
allDrives: z.boolean().optional().describe('Include shared drives (default: true; set false for My Drive only)'),
|
|
58
|
+
account: accountParam,
|
|
59
|
+
},
|
|
60
|
+
}, async ({ localPath, parent, dryRun, allDrives, account }) => {
|
|
61
|
+
const args = ['drive', 'sync', 'push', localPath, `--parent=${parent}`];
|
|
62
|
+
if (dryRun) args.push('--dry-run');
|
|
63
|
+
if (allDrives === false) args.push('--no-all-drives');
|
|
64
|
+
return runOrDiagnose(args, { account });
|
|
65
|
+
});
|
|
66
|
+
|
|
48
67
|
server.registerTool('gog_drive_copy', {
|
|
49
68
|
description: 'Copy a Drive file to a new file with the given name.',
|
|
50
69
|
inputSchema: {
|
|
@@ -95,7 +114,7 @@ export function registerExtraDriveTools(server: McpServer): void {
|
|
|
95
114
|
account: accountParam,
|
|
96
115
|
},
|
|
97
116
|
}, async ({ fileId, permissionId, account }) => {
|
|
98
|
-
return runOrDiagnose(['drive', 'unshare', fileId, permissionId], { account });
|
|
117
|
+
return runOrDiagnose(['drive', 'unshare', fileId, permissionId, '--force'], { account }); // gog gates this op; without --force the runner's --no-input makes it refuse
|
|
99
118
|
});
|
|
100
119
|
|
|
101
120
|
server.registerTool('gog_drive_drives_list', {
|
|
@@ -180,7 +199,7 @@ export function registerExtraDriveTools(server: McpServer): void {
|
|
|
180
199
|
account: accountParam,
|
|
181
200
|
},
|
|
182
201
|
}, async ({ fileId, commentId, account }) => {
|
|
183
|
-
return runOrDiagnose(['drive', 'comments', 'delete', fileId, commentId], { account });
|
|
202
|
+
return runOrDiagnose(['drive', 'comments', 'delete', fileId, commentId, '--force'], { account }); // gog gates this op; without --force the runner's --no-input makes it refuse
|
|
184
203
|
});
|
|
185
204
|
|
|
186
205
|
server.registerTool('gog_drive_comments_reply', {
|
|
@@ -327,6 +346,20 @@ export function registerExtraDriveTools(server: McpServer): void {
|
|
|
327
346
|
return runOrDiagnose(['drive', 'revisions', 'get', fileId, revisionId], { account });
|
|
328
347
|
});
|
|
329
348
|
|
|
349
|
+
server.registerTool('gog_drive_shortcut_create', {
|
|
350
|
+
description: 'Create a Drive shortcut to a file or folder inside a destination folder. Shortcuts are classified distinctly in listing/tree output and are never followed by tree scans.',
|
|
351
|
+
inputSchema: {
|
|
352
|
+
targetId: z.string().describe('File or folder ID the shortcut points to'),
|
|
353
|
+
parent: z.string().describe('Destination folder ID for the shortcut'),
|
|
354
|
+
name: z.string().optional().describe('Shortcut name (default: the target\'s name)'),
|
|
355
|
+
account: accountParam,
|
|
356
|
+
},
|
|
357
|
+
}, async ({ targetId, parent, name, account }) => {
|
|
358
|
+
const args = ['drive', 'shortcut', 'create', targetId, `--parent=${parent}`];
|
|
359
|
+
if (name) args.push(`--name=${name}`);
|
|
360
|
+
return runOrDiagnose(args, { account });
|
|
361
|
+
});
|
|
362
|
+
|
|
330
363
|
server.registerTool('gog_drive_labels_list', {
|
|
331
364
|
description: 'List Drive label schemas available to the account.',
|
|
332
365
|
annotations: { readOnlyHint: true },
|
|
@@ -417,7 +450,7 @@ export function registerExtraDriveTools(server: McpServer): void {
|
|
|
417
450
|
account: accountParam,
|
|
418
451
|
},
|
|
419
452
|
}, async ({ fileId, labelId, account }) => {
|
|
420
|
-
return runOrDiagnose(['drive', 'labels', 'file', 'remove', fileId, labelId], { account });
|
|
453
|
+
return runOrDiagnose(['drive', 'labels', 'file', 'remove', fileId, labelId, '--force'], { account }); // gog gates this op; without --force the runner's --no-input makes it refuse
|
|
421
454
|
});
|
|
422
455
|
|
|
423
456
|
server.registerTool('gog_drive_activity', {
|