gogcli-mcp-calendar 2.0.6

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/manifest.json ADDED
@@ -0,0 +1,140 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/anthropics/dxt/main/dist/mcpb-manifest.schema.json",
3
+ "manifest_version": "0.3",
4
+ "name": "gogcli-mcp-calendar",
5
+ "display_name": "gogcli (Calendar)",
6
+ "version": "2.0.6",
7
+ "description": "Extended Google Calendar for Claude via gogcli — auth + Calendar events + Meet space management",
8
+ "author": {
9
+ "name": "Chris Hall",
10
+ "email": "chris.c.hall@gmail.com",
11
+ "url": "https://github.com/chrischall"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/chrischall/gogcli-mcp"
16
+ },
17
+ "homepage": "https://github.com/chrischall/gogcli-mcp",
18
+ "support": "https://github.com/chrischall/gogcli-mcp/issues",
19
+ "license": "MIT",
20
+ "keywords": [
21
+ "google",
22
+ "calendar",
23
+ "meet",
24
+ "meetings",
25
+ "gogcli",
26
+ "gog"
27
+ ],
28
+ "server": {
29
+ "type": "node",
30
+ "entry_point": "dist/index.js",
31
+ "mcp_config": {
32
+ "command": "node",
33
+ "args": [
34
+ "${__dirname}/dist/index.js"
35
+ ],
36
+ "env": {
37
+ "GOG_ACCOUNT": "${user_config.gog_account}",
38
+ "GOG_PATH": "${user_config.gog_path}"
39
+ }
40
+ }
41
+ },
42
+ "user_config": {
43
+ "gog_account": {
44
+ "type": "string",
45
+ "title": "Google Account",
46
+ "description": "Default Google account email (optional — uses gogcli's configured default if omitted)",
47
+ "required": false
48
+ },
49
+ "gog_path": {
50
+ "type": "string",
51
+ "title": "gog Executable Path",
52
+ "description": "Path to the gog executable (optional — defaults to 'gog' on your PATH)",
53
+ "required": false
54
+ }
55
+ },
56
+ "tools": [
57
+ {
58
+ "name": "gog_auth_add",
59
+ "description": "Authorize a Google account via browser-based OAuth"
60
+ },
61
+ {
62
+ "name": "gog_auth_list",
63
+ "description": "List all Google accounts stored in gogcli"
64
+ },
65
+ {
66
+ "name": "gog_auth_status",
67
+ "description": "Show gogcli auth configuration"
68
+ },
69
+ {
70
+ "name": "gog_auth_services",
71
+ "description": "List Google services and OAuth scopes supported by gogcli"
72
+ },
73
+ {
74
+ "name": "gog_auth_run",
75
+ "description": "Run any gog auth subcommand (escape hatch)"
76
+ },
77
+ {
78
+ "name": "gog_calendar_events",
79
+ "description": "List calendar events with optional filters"
80
+ },
81
+ {
82
+ "name": "gog_calendar_get",
83
+ "description": "Get a specific calendar event"
84
+ },
85
+ {
86
+ "name": "gog_calendar_create",
87
+ "description": "Create a calendar event"
88
+ },
89
+ {
90
+ "name": "gog_calendar_update",
91
+ "description": "Update an existing calendar event"
92
+ },
93
+ {
94
+ "name": "gog_calendar_delete",
95
+ "description": "Delete a calendar event"
96
+ },
97
+ {
98
+ "name": "gog_calendar_respond",
99
+ "description": "Respond to a calendar event invitation"
100
+ },
101
+ {
102
+ "name": "gog_calendar_run",
103
+ "description": "Run any gog calendar subcommand (escape hatch)"
104
+ },
105
+ {
106
+ "name": "gog_meet_create",
107
+ "description": "Create a Google Meet space"
108
+ },
109
+ {
110
+ "name": "gog_meet_get",
111
+ "description": "Get a Google Meet space by meeting code"
112
+ },
113
+ {
114
+ "name": "gog_meet_update",
115
+ "description": "Update a Google Meet space configuration"
116
+ },
117
+ {
118
+ "name": "gog_meet_end",
119
+ "description": "End the active conference in a Meet space"
120
+ },
121
+ {
122
+ "name": "gog_meet_history",
123
+ "description": "List past calls in a Meet space"
124
+ },
125
+ {
126
+ "name": "gog_meet_participants",
127
+ "description": "List participants from a Meet call"
128
+ }
129
+ ],
130
+ "compatibility": {
131
+ "platforms": [
132
+ "darwin",
133
+ "linux",
134
+ "win32"
135
+ ],
136
+ "runtimes": {
137
+ "node": ">=18.0.0"
138
+ }
139
+ }
140
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "gogcli-mcp-calendar",
3
+ "version": "2.0.6",
4
+ "mcpName": "io.github.chrischall/gogcli-mcp-calendar",
5
+ "description": "Extended Google Calendar + Meet MCP server via gogcli — auth + Calendar events + Meet space management",
6
+ "author": "Claude Code (AI) <https://www.anthropic.com/claude>",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/chrischall/gogcli-mcp"
10
+ },
11
+ "type": "module",
12
+ "bin": {
13
+ "gogcli-mcp-calendar": "dist/index.js"
14
+ },
15
+ "exports": {
16
+ ".": "./dist/index.js"
17
+ },
18
+ "scripts": {
19
+ "build": "tsc --noEmit && npm run bundle",
20
+ "bundle": "node ../../scripts/bundle.js src/index.ts dist/index.js",
21
+ "typecheck": "tsc --noEmit",
22
+ "test": "vitest run",
23
+ "test:watch": "vitest",
24
+ "test:coverage": "vitest run --coverage"
25
+ },
26
+ "dependencies": {
27
+ "@modelcontextprotocol/sdk": "^1.29.0",
28
+ "zod": "^4.4.3"
29
+ },
30
+ "license": "MIT",
31
+ "keywords": [
32
+ "mcp",
33
+ "model-context-protocol",
34
+ "claude",
35
+ "ai",
36
+ "google",
37
+ "gogcli",
38
+ "calendar",
39
+ "meet",
40
+ "meetings"
41
+ ]
42
+ }
package/src/index.ts ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { createServer, registerAuthTools, registerCalendarTools } from '../../gogcli-mcp/src/lib.js';
4
+ import { registerExtraCalendarTools } from './tools/calendar-extra.js';
5
+
6
+ const server = createServer({ name: 'gogcli-calendar' });
7
+ registerAuthTools(server);
8
+ registerCalendarTools(server);
9
+ registerExtraCalendarTools(server);
10
+
11
+ const transport = new StdioServerTransport();
12
+ await server.connect(transport);
@@ -0,0 +1,99 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { z } from 'zod';
3
+ import { accountParam, runOrDiagnose } from '../../../gogcli-mcp/src/lib.js';
4
+
5
+ const meetAccess = z.enum(['open', 'trusted', 'restricted']);
6
+
7
+ export function registerExtraCalendarTools(server: McpServer): void {
8
+ // ─── Meet API tools ────────────────────────────────────────────
9
+ // Meet spaces are the conferencing surface attached to calendar events,
10
+ // so they live in the calendar sub-package.
11
+
12
+ server.registerTool('gog_meet_create', {
13
+ description: 'Create a Google Meet space and return its meeting code.',
14
+ inputSchema: {
15
+ access: meetAccess.optional().describe('Access type (default: trusted)'),
16
+ open: z.boolean().optional().describe('Open the meeting in a browser after creation'),
17
+ account: accountParam,
18
+ },
19
+ }, async ({ access, open, account }) => {
20
+ const args = ['meet', 'create'];
21
+ if (access) args.push(`--access=${access}`);
22
+ if (open) args.push('--open');
23
+ return runOrDiagnose(args, { account });
24
+ });
25
+
26
+ server.registerTool('gog_meet_get', {
27
+ description: 'Get a Google Meet space by its meeting code.',
28
+ annotations: { readOnlyHint: true },
29
+ inputSchema: {
30
+ meetingCode: z.string().describe('Meeting code (e.g. abc-defg-hij)'),
31
+ account: accountParam,
32
+ },
33
+ }, async ({ meetingCode, account }) => {
34
+ return runOrDiagnose(['meet', 'get', meetingCode], { account });
35
+ });
36
+
37
+ server.registerTool('gog_meet_update', {
38
+ description: 'Update a Google Meet space configuration.',
39
+ annotations: { destructiveHint: true },
40
+ inputSchema: {
41
+ meetingCode: z.string().describe('Meeting code'),
42
+ access: meetAccess.optional().describe('Access type'),
43
+ account: accountParam,
44
+ },
45
+ }, async ({ meetingCode, access, account }) => {
46
+ const args = ['meet', 'update', meetingCode];
47
+ if (access) args.push(`--access=${access}`);
48
+ return runOrDiagnose(args, { account });
49
+ });
50
+
51
+ server.registerTool('gog_meet_end', {
52
+ description: 'End the active conference in a Google Meet space.',
53
+ annotations: { destructiveHint: true },
54
+ inputSchema: {
55
+ meetingCode: z.string().describe('Meeting code'),
56
+ account: accountParam,
57
+ },
58
+ }, async ({ meetingCode, account }) => {
59
+ return runOrDiagnose(['meet', 'end', meetingCode], { account });
60
+ });
61
+
62
+ server.registerTool('gog_meet_history', {
63
+ description: 'List past calls (conferences) in a Google Meet space.',
64
+ annotations: { readOnlyHint: true },
65
+ inputSchema: {
66
+ meetingCode: z.string().describe('Meeting code'),
67
+ max: z.number().optional().describe('Max results (default: 20)'),
68
+ page: z.string().optional().describe('Page token'),
69
+ all: z.boolean().optional().describe('Fetch all pages'),
70
+ account: accountParam,
71
+ },
72
+ }, async ({ meetingCode, max, page, all, account }) => {
73
+ const args = ['meet', 'history', meetingCode];
74
+ if (max !== undefined) args.push(`--max=${max}`);
75
+ if (page) args.push(`--page=${page}`);
76
+ if (all) args.push('--all');
77
+ return runOrDiagnose(args, { account });
78
+ });
79
+
80
+ server.registerTool('gog_meet_participants', {
81
+ description: 'List participants from the latest (or a specific) Meet call.',
82
+ annotations: { readOnlyHint: true },
83
+ inputSchema: {
84
+ meetingCode: z.string().describe('Meeting code'),
85
+ conference: z.string().optional().describe('Specific conference ID (default: most recent)'),
86
+ max: z.number().optional().describe('Max results (default: 50)'),
87
+ page: z.string().optional().describe('Page token'),
88
+ all: z.boolean().optional().describe('Fetch all pages'),
89
+ account: accountParam,
90
+ },
91
+ }, async ({ meetingCode, conference, max, page, all, account }) => {
92
+ const args = ['meet', 'participants', meetingCode];
93
+ if (conference) args.push(`--conference=${conference}`);
94
+ if (max !== undefined) args.push(`--max=${max}`);
95
+ if (page) args.push(`--page=${page}`);
96
+ if (all) args.push('--all');
97
+ return runOrDiagnose(args, { account });
98
+ });
99
+ }
@@ -0,0 +1,132 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { registerExtraCalendarTools } from '../../src/tools/calendar-extra.js';
3
+ import * as lib from '../../../gogcli-mcp/src/lib.js';
4
+ import { setupExtrasHandlers, toText, type ToolHandler } from '../../../gogcli-mcp/tests/helpers/extras-harness.js';
5
+
6
+ vi.mock('../../../gogcli-mcp/src/lib.js', async (importOriginal) => {
7
+ const actual = await importOriginal<typeof lib>();
8
+ return {
9
+ ...actual,
10
+ runOrDiagnose: vi.fn(),
11
+ };
12
+ });
13
+
14
+ let handlers: Map<string, ToolHandler>;
15
+
16
+ beforeEach(() => {
17
+ vi.clearAllMocks();
18
+ vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
19
+ handlers = setupExtrasHandlers(registerExtraCalendarTools);
20
+ });
21
+
22
+ describe('gog_meet_create', () => {
23
+ it('calls runOrDiagnose with no flags', async () => {
24
+ await handlers.get('gog_meet_create')!({});
25
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(['meet', 'create'], { account: undefined });
26
+ });
27
+
28
+ it('passes --access and --open when provided', async () => {
29
+ await handlers.get('gog_meet_create')!({ access: 'open', open: true });
30
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
31
+ ['meet', 'create', '--access=open', '--open'],
32
+ { account: undefined },
33
+ );
34
+ });
35
+
36
+ it('omits --open when false', async () => {
37
+ await handlers.get('gog_meet_create')!({ open: false });
38
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(['meet', 'create'], { account: undefined });
39
+ });
40
+ });
41
+
42
+ describe('gog_meet_get', () => {
43
+ it('calls runOrDiagnose with meetingCode', async () => {
44
+ await handlers.get('gog_meet_get')!({ meetingCode: 'abc-defg-hij' });
45
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(['meet', 'get', 'abc-defg-hij'], { account: undefined });
46
+ });
47
+ });
48
+
49
+ describe('gog_meet_update', () => {
50
+ it('calls runOrDiagnose with meetingCode and --access', async () => {
51
+ await handlers.get('gog_meet_update')!({ meetingCode: 'abc-defg-hij', access: 'restricted' });
52
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
53
+ ['meet', 'update', 'abc-defg-hij', '--access=restricted'],
54
+ { account: undefined },
55
+ );
56
+ });
57
+
58
+ it('omits --access when not provided', async () => {
59
+ await handlers.get('gog_meet_update')!({ meetingCode: 'abc-defg-hij' });
60
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(['meet', 'update', 'abc-defg-hij'], { account: undefined });
61
+ });
62
+ });
63
+
64
+ describe('gog_meet_end', () => {
65
+ it('calls runOrDiagnose with meetingCode', async () => {
66
+ await handlers.get('gog_meet_end')!({ meetingCode: 'abc-defg-hij' });
67
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(['meet', 'end', 'abc-defg-hij'], { account: undefined });
68
+ });
69
+ });
70
+
71
+ describe('gog_meet_history', () => {
72
+ it('calls runOrDiagnose with meetingCode', async () => {
73
+ await handlers.get('gog_meet_history')!({ meetingCode: 'abc-defg-hij' });
74
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(['meet', 'history', 'abc-defg-hij'], { account: undefined });
75
+ });
76
+
77
+ it('passes pagination flags', async () => {
78
+ await handlers.get('gog_meet_history')!({
79
+ meetingCode: 'abc-defg-hij',
80
+ max: 50,
81
+ page: 'tok',
82
+ all: true,
83
+ });
84
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
85
+ ['meet', 'history', 'abc-defg-hij', '--max=50', '--page=tok', '--all'],
86
+ { account: undefined },
87
+ );
88
+ });
89
+
90
+ it('omits --all when false', async () => {
91
+ await handlers.get('gog_meet_history')!({ meetingCode: 'abc-defg-hij', all: false });
92
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(['meet', 'history', 'abc-defg-hij'], { account: undefined });
93
+ });
94
+ });
95
+
96
+ describe('gog_meet_participants', () => {
97
+ it('calls runOrDiagnose with meetingCode', async () => {
98
+ await handlers.get('gog_meet_participants')!({ meetingCode: 'abc-defg-hij' });
99
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
100
+ ['meet', 'participants', 'abc-defg-hij'],
101
+ { account: undefined },
102
+ );
103
+ });
104
+
105
+ it('passes --conference and pagination flags', async () => {
106
+ await handlers.get('gog_meet_participants')!({
107
+ meetingCode: 'abc-defg-hij',
108
+ conference: 'conf123',
109
+ max: 100,
110
+ page: 'tok',
111
+ all: true,
112
+ });
113
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
114
+ [
115
+ 'meet', 'participants', 'abc-defg-hij',
116
+ '--conference=conf123',
117
+ '--max=100',
118
+ '--page=tok',
119
+ '--all',
120
+ ],
121
+ { account: undefined },
122
+ );
123
+ });
124
+
125
+ it('omits --all when false', async () => {
126
+ await handlers.get('gog_meet_participants')!({ meetingCode: 'abc-defg-hij', all: false });
127
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
128
+ ['meet', 'participants', 'abc-defg-hij'],
129
+ { account: undefined },
130
+ );
131
+ });
132
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "../"
6
+ },
7
+ "include": ["src/**/*", "../gogcli-mcp/src/**/*"],
8
+ "exclude": ["node_modules", "dist"]
9
+ }
@@ -0,0 +1,17 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ coverage: {
6
+ provider: 'v8',
7
+ include: ['src/**/*.ts'],
8
+ exclude: ['src/index.ts'],
9
+ thresholds: {
10
+ lines: 100,
11
+ functions: 100,
12
+ branches: 100,
13
+ statements: 100,
14
+ },
15
+ },
16
+ },
17
+ });