gogcli-mcp 2.0.2 → 2.0.4
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 +38 -0
- package/.claude-plugin/plugin.json +25 -0
- package/.mcp.json +14 -0
- package/.mcpbignore +27 -0
- package/dist/index.js +1471 -576
- package/dist/lib.js +1801 -906
- package/manifest.json +45 -1
- package/package.json +4 -3
- package/server.json +35 -0
- package/src/tools/calendar.ts +92 -0
- package/src/tools/contacts.ts +74 -0
- package/tests/tools/calendar.test.ts +138 -0
- package/tests/tools/contacts.test.ts +100 -0
package/manifest.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"manifest_version": "0.3",
|
|
4
4
|
"name": "gogcli-mcp",
|
|
5
5
|
"display_name": "gogcli",
|
|
6
|
-
"version": "2.0.
|
|
6
|
+
"version": "2.0.4",
|
|
7
7
|
"description": "Google Sheets (and more) for Claude via gogcli — read, write, and manage spreadsheets",
|
|
8
8
|
"author": {
|
|
9
9
|
"name": "Chris Hall",
|
|
@@ -120,6 +120,30 @@
|
|
|
120
120
|
"name": "gog_calendar_run",
|
|
121
121
|
"description": "Run any gog calendar subcommand (escape hatch)"
|
|
122
122
|
},
|
|
123
|
+
{
|
|
124
|
+
"name": "gog_meet_create",
|
|
125
|
+
"description": "Create a Google Meet space"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"name": "gog_meet_get",
|
|
129
|
+
"description": "Get a Google Meet space by meeting code"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"name": "gog_meet_update",
|
|
133
|
+
"description": "Update a Google Meet space configuration"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"name": "gog_meet_end",
|
|
137
|
+
"description": "End the active conference in a Meet space"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"name": "gog_meet_history",
|
|
141
|
+
"description": "List past calls in a Meet space"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"name": "gog_meet_participants",
|
|
145
|
+
"description": "List participants from a Meet call"
|
|
146
|
+
},
|
|
123
147
|
{
|
|
124
148
|
"name": "gog_classroom_courses_list",
|
|
125
149
|
"description": "List Google Classroom courses"
|
|
@@ -380,6 +404,26 @@
|
|
|
380
404
|
"name": "gog_contacts_run",
|
|
381
405
|
"description": "Run any gog contacts subcommand (escape hatch)"
|
|
382
406
|
},
|
|
407
|
+
{
|
|
408
|
+
"name": "gog_people_me",
|
|
409
|
+
"description": "Show your own Google People profile"
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
"name": "gog_people_get",
|
|
413
|
+
"description": "Get a People profile by resource name"
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
"name": "gog_people_search",
|
|
417
|
+
"description": "Search the Google Workspace directory"
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
"name": "gog_people_relations",
|
|
421
|
+
"description": "Get relations (manager, reports) for a user"
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
"name": "gog_people_raw",
|
|
425
|
+
"description": "Dump raw Google People API JSON for a person"
|
|
426
|
+
},
|
|
383
427
|
{
|
|
384
428
|
"name": "gog_docs_info",
|
|
385
429
|
"description": "Get Google Doc metadata (title, ID, properties)"
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gogcli-mcp",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
|
+
"mcpName": "io.github.chrischall/gogcli-mcp",
|
|
4
5
|
"description": "MCP server wrapping gogcli for Google service access",
|
|
5
6
|
"author": "Claude Code (AI) <https://www.anthropic.com/claude>",
|
|
6
7
|
"repository": {
|
|
@@ -41,10 +42,10 @@
|
|
|
41
42
|
},
|
|
42
43
|
"dependencies": {
|
|
43
44
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
44
|
-
"zod": "^4.3
|
|
45
|
+
"zod": "^4.4.3"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|
|
47
|
-
"@types/node": "^25.
|
|
48
|
+
"@types/node": "^25.6.2",
|
|
48
49
|
"@vitest/coverage-v8": "^4.1.2",
|
|
49
50
|
"esbuild": "^0.28.0",
|
|
50
51
|
"typescript": "^6.0.2",
|
package/server.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
+
"name": "io.github.chrischall/gogcli-mcp",
|
|
4
|
+
"description": "Google Sheets (and more) for Claude via gogcli — read, write, and manage spreadsheets",
|
|
5
|
+
"repository": {
|
|
6
|
+
"url": "https://github.com/chrischall/gogcli-mcp",
|
|
7
|
+
"source": "github",
|
|
8
|
+
"subfolder": "packages/gogcli-mcp"
|
|
9
|
+
},
|
|
10
|
+
"version": "2.0.4",
|
|
11
|
+
"packages": [
|
|
12
|
+
{
|
|
13
|
+
"registryType": "npm",
|
|
14
|
+
"identifier": "gogcli-mcp",
|
|
15
|
+
"version": "2.0.4",
|
|
16
|
+
"transport": {
|
|
17
|
+
"type": "stdio"
|
|
18
|
+
},
|
|
19
|
+
"environmentVariables": [
|
|
20
|
+
{
|
|
21
|
+
"name": "GOG_ACCOUNT",
|
|
22
|
+
"description": "Email address of the Google account to use (matches gogcli auth)",
|
|
23
|
+
"isRequired": false,
|
|
24
|
+
"format": "string"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "GOG_PATH",
|
|
28
|
+
"description": "Override path to the gogcli binary (auto-discovered otherwise)",
|
|
29
|
+
"isRequired": false,
|
|
30
|
+
"format": "string"
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
package/src/tools/calendar.ts
CHANGED
|
@@ -125,4 +125,96 @@ export function registerCalendarTools(server: McpServer): void {
|
|
|
125
125
|
}, async ({ subcommand, args, account }) => {
|
|
126
126
|
return runOrDiagnose(['calendar', subcommand, ...args], { account });
|
|
127
127
|
});
|
|
128
|
+
|
|
129
|
+
// ─── Meet API tools ────────────────────────────────────────────
|
|
130
|
+
// Folded into the calendar wrapper because Meet spaces are the
|
|
131
|
+
// conferencing surface attached to calendar events.
|
|
132
|
+
|
|
133
|
+
server.registerTool('gog_meet_create', {
|
|
134
|
+
description: 'Create a Google Meet space and return its meeting code.',
|
|
135
|
+
inputSchema: {
|
|
136
|
+
access: z.enum(['open', 'trusted', 'restricted']).optional().describe('Access type (default: trusted)'),
|
|
137
|
+
open: z.boolean().optional().describe('Open the meeting in a browser after creation'),
|
|
138
|
+
account: accountParam,
|
|
139
|
+
},
|
|
140
|
+
}, async ({ access, open, account }) => {
|
|
141
|
+
const args = ['meet', 'create'];
|
|
142
|
+
if (access) args.push(`--access=${access}`);
|
|
143
|
+
if (open) args.push('--open');
|
|
144
|
+
return runOrDiagnose(args, { account });
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
server.registerTool('gog_meet_get', {
|
|
148
|
+
description: 'Get a Google Meet space by its meeting code.',
|
|
149
|
+
annotations: { readOnlyHint: true },
|
|
150
|
+
inputSchema: {
|
|
151
|
+
meetingCode: z.string().describe('Meeting code (e.g. abc-defg-hij)'),
|
|
152
|
+
account: accountParam,
|
|
153
|
+
},
|
|
154
|
+
}, async ({ meetingCode, account }) => {
|
|
155
|
+
return runOrDiagnose(['meet', 'get', meetingCode], { account });
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
server.registerTool('gog_meet_update', {
|
|
159
|
+
description: 'Update a Google Meet space configuration.',
|
|
160
|
+
annotations: { destructiveHint: true },
|
|
161
|
+
inputSchema: {
|
|
162
|
+
meetingCode: z.string().describe('Meeting code'),
|
|
163
|
+
access: z.enum(['open', 'trusted', 'restricted']).optional().describe('Access type'),
|
|
164
|
+
account: accountParam,
|
|
165
|
+
},
|
|
166
|
+
}, async ({ meetingCode, access, account }) => {
|
|
167
|
+
const args = ['meet', 'update', meetingCode];
|
|
168
|
+
if (access) args.push(`--access=${access}`);
|
|
169
|
+
return runOrDiagnose(args, { account });
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
server.registerTool('gog_meet_end', {
|
|
173
|
+
description: 'End the active conference in a Google Meet space.',
|
|
174
|
+
annotations: { destructiveHint: true },
|
|
175
|
+
inputSchema: {
|
|
176
|
+
meetingCode: z.string().describe('Meeting code'),
|
|
177
|
+
account: accountParam,
|
|
178
|
+
},
|
|
179
|
+
}, async ({ meetingCode, account }) => {
|
|
180
|
+
return runOrDiagnose(['meet', 'end', meetingCode], { account });
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
server.registerTool('gog_meet_history', {
|
|
184
|
+
description: 'List past calls (conferences) in a Google Meet space.',
|
|
185
|
+
annotations: { readOnlyHint: true },
|
|
186
|
+
inputSchema: {
|
|
187
|
+
meetingCode: z.string().describe('Meeting code'),
|
|
188
|
+
max: z.number().optional().describe('Max results (default: 20)'),
|
|
189
|
+
page: z.string().optional().describe('Page token'),
|
|
190
|
+
all: z.boolean().optional().describe('Fetch all pages'),
|
|
191
|
+
account: accountParam,
|
|
192
|
+
},
|
|
193
|
+
}, async ({ meetingCode, max, page, all, account }) => {
|
|
194
|
+
const args = ['meet', 'history', meetingCode];
|
|
195
|
+
if (max !== undefined) args.push(`--max=${max}`);
|
|
196
|
+
if (page) args.push(`--page=${page}`);
|
|
197
|
+
if (all) args.push('--all');
|
|
198
|
+
return runOrDiagnose(args, { account });
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
server.registerTool('gog_meet_participants', {
|
|
202
|
+
description: 'List participants from the latest (or a specific) Meet call.',
|
|
203
|
+
annotations: { readOnlyHint: true },
|
|
204
|
+
inputSchema: {
|
|
205
|
+
meetingCode: z.string().describe('Meeting code'),
|
|
206
|
+
conference: z.string().optional().describe('Specific conference ID (default: most recent)'),
|
|
207
|
+
max: z.number().optional().describe('Max results (default: 50)'),
|
|
208
|
+
page: z.string().optional().describe('Page token'),
|
|
209
|
+
all: z.boolean().optional().describe('Fetch all pages'),
|
|
210
|
+
account: accountParam,
|
|
211
|
+
},
|
|
212
|
+
}, async ({ meetingCode, conference, max, page, all, account }) => {
|
|
213
|
+
const args = ['meet', 'participants', meetingCode];
|
|
214
|
+
if (conference) args.push(`--conference=${conference}`);
|
|
215
|
+
if (max !== undefined) args.push(`--max=${max}`);
|
|
216
|
+
if (page) args.push(`--page=${page}`);
|
|
217
|
+
if (all) args.push('--all');
|
|
218
|
+
return runOrDiagnose(args, { account });
|
|
219
|
+
});
|
|
128
220
|
}
|
package/src/tools/contacts.ts
CHANGED
|
@@ -68,4 +68,78 @@ export function registerContactsTools(server: McpServer): void {
|
|
|
68
68
|
}, async ({ subcommand, args, account }) => {
|
|
69
69
|
return runOrDiagnose(['contacts', subcommand, ...args], { account });
|
|
70
70
|
});
|
|
71
|
+
|
|
72
|
+
// ─── People API tools ──────────────────────────────────────────
|
|
73
|
+
// Folded into the contacts wrapper because People is the richer API behind
|
|
74
|
+
// Google Contacts (Workspace directory search, profile fields, relations).
|
|
75
|
+
|
|
76
|
+
server.registerTool('gog_people_me', {
|
|
77
|
+
description: 'Show your own People profile (people/me).',
|
|
78
|
+
annotations: { readOnlyHint: true },
|
|
79
|
+
inputSchema: {
|
|
80
|
+
account: accountParam,
|
|
81
|
+
},
|
|
82
|
+
}, async ({ account }) => {
|
|
83
|
+
return runOrDiagnose(['people', 'me'], { account });
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
server.registerTool('gog_people_get', {
|
|
87
|
+
description: 'Get a People profile by resource name.',
|
|
88
|
+
annotations: { readOnlyHint: true },
|
|
89
|
+
inputSchema: {
|
|
90
|
+
userId: z.string().describe('Person resource name (people/...) or email'),
|
|
91
|
+
account: accountParam,
|
|
92
|
+
},
|
|
93
|
+
}, async ({ userId, account }) => {
|
|
94
|
+
return runOrDiagnose(['people', 'get', userId], { account });
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
server.registerTool('gog_people_search', {
|
|
98
|
+
description: 'Search the Google Workspace directory (covers internal users, unlike contacts search which is limited to your personal contacts).',
|
|
99
|
+
annotations: { readOnlyHint: true },
|
|
100
|
+
inputSchema: {
|
|
101
|
+
query: z.string().describe('Search query (name, email, etc.)'),
|
|
102
|
+
max: z.number().optional().describe('Max results (default: 50)'),
|
|
103
|
+
page: z.string().optional().describe('Page token'),
|
|
104
|
+
all: z.boolean().optional().describe('Fetch all pages'),
|
|
105
|
+
account: accountParam,
|
|
106
|
+
},
|
|
107
|
+
}, async ({ query, max, page, all, account }) => {
|
|
108
|
+
const args = ['people', 'search', query];
|
|
109
|
+
if (max !== undefined) args.push(`--max=${max}`);
|
|
110
|
+
if (page) args.push(`--page=${page}`);
|
|
111
|
+
if (all) args.push('--all');
|
|
112
|
+
return runOrDiagnose(args, { account });
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
server.registerTool('gog_people_relations', {
|
|
116
|
+
description: 'Get relations (manager, reports, etc.) for a user. Defaults to self when userId is omitted.',
|
|
117
|
+
annotations: { readOnlyHint: true },
|
|
118
|
+
inputSchema: {
|
|
119
|
+
userId: z.string().optional().describe('Person resource name (defaults to self when omitted)'),
|
|
120
|
+
type: z.string().optional().describe('Filter to a specific relation type (e.g. "manager")'),
|
|
121
|
+
account: accountParam,
|
|
122
|
+
},
|
|
123
|
+
}, async ({ userId, type, account }) => {
|
|
124
|
+
const args = ['people', 'relations'];
|
|
125
|
+
if (userId) args.push(userId);
|
|
126
|
+
if (type) args.push(`--type=${type}`);
|
|
127
|
+
return runOrDiagnose(args, { account });
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
server.registerTool('gog_people_raw', {
|
|
131
|
+
description: 'Dump the raw People API response as JSON (lossless; for scripting and LLM consumption).',
|
|
132
|
+
annotations: { readOnlyHint: true },
|
|
133
|
+
inputSchema: {
|
|
134
|
+
userId: z.string().describe('Person resource name (people/...) or email'),
|
|
135
|
+
personFields: z.string().optional().describe('People API personFields mask (default: broad set)'),
|
|
136
|
+
pretty: z.boolean().optional().describe('Pretty-print JSON (default: compact single-line)'),
|
|
137
|
+
account: accountParam,
|
|
138
|
+
},
|
|
139
|
+
}, async ({ userId, personFields, pretty, account }) => {
|
|
140
|
+
const args = ['people', 'raw', userId];
|
|
141
|
+
if (personFields) args.push(`--person-fields=${personFields}`);
|
|
142
|
+
if (pretty) args.push('--pretty');
|
|
143
|
+
return runOrDiagnose(args, { account });
|
|
144
|
+
});
|
|
71
145
|
}
|
|
@@ -227,3 +227,141 @@ describe('gog_calendar_run', () => {
|
|
|
227
227
|
expect(result.content[0].text).toBe('Error: Run failed');
|
|
228
228
|
});
|
|
229
229
|
});
|
|
230
|
+
|
|
231
|
+
describe('gog_meet_create', () => {
|
|
232
|
+
it('calls run with no flags', async () => {
|
|
233
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
234
|
+
const handlers = setupHandlers();
|
|
235
|
+
await handlers.get('gog_meet_create')!({});
|
|
236
|
+
expect(runner.run).toHaveBeenCalledWith(['meet', 'create'], { account: undefined });
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('passes --access and --open when provided', async () => {
|
|
240
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
241
|
+
const handlers = setupHandlers();
|
|
242
|
+
await handlers.get('gog_meet_create')!({ access: 'open', open: true });
|
|
243
|
+
expect(runner.run).toHaveBeenCalledWith(
|
|
244
|
+
['meet', 'create', '--access=open', '--open'],
|
|
245
|
+
{ account: undefined },
|
|
246
|
+
);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('omits --open when false', async () => {
|
|
250
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
251
|
+
const handlers = setupHandlers();
|
|
252
|
+
await handlers.get('gog_meet_create')!({ open: false });
|
|
253
|
+
expect(runner.run).toHaveBeenCalledWith(['meet', 'create'], { account: undefined });
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
describe('gog_meet_get', () => {
|
|
258
|
+
it('calls run with meetingCode', async () => {
|
|
259
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
260
|
+
const handlers = setupHandlers();
|
|
261
|
+
await handlers.get('gog_meet_get')!({ meetingCode: 'abc-defg-hij' });
|
|
262
|
+
expect(runner.run).toHaveBeenCalledWith(['meet', 'get', 'abc-defg-hij'], { account: undefined });
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
describe('gog_meet_update', () => {
|
|
267
|
+
it('calls run with meetingCode and --access', async () => {
|
|
268
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
269
|
+
const handlers = setupHandlers();
|
|
270
|
+
await handlers.get('gog_meet_update')!({ meetingCode: 'abc-defg-hij', access: 'restricted' });
|
|
271
|
+
expect(runner.run).toHaveBeenCalledWith(
|
|
272
|
+
['meet', 'update', 'abc-defg-hij', '--access=restricted'],
|
|
273
|
+
{ account: undefined },
|
|
274
|
+
);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it('omits --access when not provided', async () => {
|
|
278
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
279
|
+
const handlers = setupHandlers();
|
|
280
|
+
await handlers.get('gog_meet_update')!({ meetingCode: 'abc-defg-hij' });
|
|
281
|
+
expect(runner.run).toHaveBeenCalledWith(['meet', 'update', 'abc-defg-hij'], { account: undefined });
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
describe('gog_meet_end', () => {
|
|
286
|
+
it('calls run with meetingCode', async () => {
|
|
287
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
288
|
+
const handlers = setupHandlers();
|
|
289
|
+
await handlers.get('gog_meet_end')!({ meetingCode: 'abc-defg-hij' });
|
|
290
|
+
expect(runner.run).toHaveBeenCalledWith(['meet', 'end', 'abc-defg-hij'], { account: undefined });
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
describe('gog_meet_history', () => {
|
|
295
|
+
it('calls run with meetingCode', async () => {
|
|
296
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
297
|
+
const handlers = setupHandlers();
|
|
298
|
+
await handlers.get('gog_meet_history')!({ meetingCode: 'abc-defg-hij' });
|
|
299
|
+
expect(runner.run).toHaveBeenCalledWith(['meet', 'history', 'abc-defg-hij'], { account: undefined });
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
it('passes pagination flags', async () => {
|
|
303
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
304
|
+
const handlers = setupHandlers();
|
|
305
|
+
await handlers.get('gog_meet_history')!({
|
|
306
|
+
meetingCode: 'abc-defg-hij',
|
|
307
|
+
max: 50,
|
|
308
|
+
page: 'tok',
|
|
309
|
+
all: true,
|
|
310
|
+
});
|
|
311
|
+
expect(runner.run).toHaveBeenCalledWith(
|
|
312
|
+
['meet', 'history', 'abc-defg-hij', '--max=50', '--page=tok', '--all'],
|
|
313
|
+
{ account: undefined },
|
|
314
|
+
);
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it('omits --all when false', async () => {
|
|
318
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
319
|
+
const handlers = setupHandlers();
|
|
320
|
+
await handlers.get('gog_meet_history')!({ meetingCode: 'abc-defg-hij', all: false });
|
|
321
|
+
expect(runner.run).toHaveBeenCalledWith(['meet', 'history', 'abc-defg-hij'], { account: undefined });
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
describe('gog_meet_participants', () => {
|
|
326
|
+
it('calls run with meetingCode', async () => {
|
|
327
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
328
|
+
const handlers = setupHandlers();
|
|
329
|
+
await handlers.get('gog_meet_participants')!({ meetingCode: 'abc-defg-hij' });
|
|
330
|
+
expect(runner.run).toHaveBeenCalledWith(
|
|
331
|
+
['meet', 'participants', 'abc-defg-hij'],
|
|
332
|
+
{ account: undefined },
|
|
333
|
+
);
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
it('passes --conference and pagination flags', async () => {
|
|
337
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
338
|
+
const handlers = setupHandlers();
|
|
339
|
+
await handlers.get('gog_meet_participants')!({
|
|
340
|
+
meetingCode: 'abc-defg-hij',
|
|
341
|
+
conference: 'conf123',
|
|
342
|
+
max: 100,
|
|
343
|
+
page: 'tok',
|
|
344
|
+
all: true,
|
|
345
|
+
});
|
|
346
|
+
expect(runner.run).toHaveBeenCalledWith(
|
|
347
|
+
[
|
|
348
|
+
'meet', 'participants', 'abc-defg-hij',
|
|
349
|
+
'--conference=conf123',
|
|
350
|
+
'--max=100',
|
|
351
|
+
'--page=tok',
|
|
352
|
+
'--all',
|
|
353
|
+
],
|
|
354
|
+
{ account: undefined },
|
|
355
|
+
);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it('omits --all when false', async () => {
|
|
359
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
360
|
+
const handlers = setupHandlers();
|
|
361
|
+
await handlers.get('gog_meet_participants')!({ meetingCode: 'abc-defg-hij', all: false });
|
|
362
|
+
expect(runner.run).toHaveBeenCalledWith(
|
|
363
|
+
['meet', 'participants', 'abc-defg-hij'],
|
|
364
|
+
{ account: undefined },
|
|
365
|
+
);
|
|
366
|
+
});
|
|
367
|
+
});
|
|
@@ -120,3 +120,103 @@ describe('gog_contacts_run', () => {
|
|
|
120
120
|
expect(result.content[0].text).toBe('Error: Run failed');
|
|
121
121
|
});
|
|
122
122
|
});
|
|
123
|
+
|
|
124
|
+
describe('gog_people_me', () => {
|
|
125
|
+
it('calls run with people me', async () => {
|
|
126
|
+
vi.mocked(runner.run).mockResolvedValue('{"resourceName":"people/me"}');
|
|
127
|
+
const handlers = setupHandlers();
|
|
128
|
+
await handlers.get('gog_people_me')!({});
|
|
129
|
+
expect(runner.run).toHaveBeenCalledWith(['people', 'me'], { account: undefined });
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('returns error text on failure', async () => {
|
|
133
|
+
vi.mocked(runner.run).mockRejectedValue(new Error('Me failed'));
|
|
134
|
+
const handlers = setupHandlers();
|
|
135
|
+
const result = await handlers.get('gog_people_me')!({});
|
|
136
|
+
expect(result.content[0].text).toBe('Error: Me failed');
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
describe('gog_people_get', () => {
|
|
141
|
+
it('calls run with userId', async () => {
|
|
142
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
143
|
+
const handlers = setupHandlers();
|
|
144
|
+
await handlers.get('gog_people_get')!({ userId: 'people/c123' });
|
|
145
|
+
expect(runner.run).toHaveBeenCalledWith(['people', 'get', 'people/c123'], { account: undefined });
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
describe('gog_people_search', () => {
|
|
150
|
+
it('calls run with query', async () => {
|
|
151
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
152
|
+
const handlers = setupHandlers();
|
|
153
|
+
await handlers.get('gog_people_search')!({ query: 'alice' });
|
|
154
|
+
expect(runner.run).toHaveBeenCalledWith(['people', 'search', 'alice'], { account: undefined });
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('passes pagination flags', async () => {
|
|
158
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
159
|
+
const handlers = setupHandlers();
|
|
160
|
+
await handlers.get('gog_people_search')!({ query: 'alice', max: 100, page: 'tok', all: true });
|
|
161
|
+
expect(runner.run).toHaveBeenCalledWith(
|
|
162
|
+
['people', 'search', 'alice', '--max=100', '--page=tok', '--all'],
|
|
163
|
+
{ account: undefined },
|
|
164
|
+
);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('omits --all when false', async () => {
|
|
168
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
169
|
+
const handlers = setupHandlers();
|
|
170
|
+
await handlers.get('gog_people_search')!({ query: 'x', all: false });
|
|
171
|
+
expect(runner.run).toHaveBeenCalledWith(['people', 'search', 'x'], { account: undefined });
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
describe('gog_people_relations', () => {
|
|
176
|
+
it('calls run with no userId', async () => {
|
|
177
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
178
|
+
const handlers = setupHandlers();
|
|
179
|
+
await handlers.get('gog_people_relations')!({});
|
|
180
|
+
expect(runner.run).toHaveBeenCalledWith(['people', 'relations'], { account: undefined });
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('passes userId and --type when provided', async () => {
|
|
184
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
185
|
+
const handlers = setupHandlers();
|
|
186
|
+
await handlers.get('gog_people_relations')!({ userId: 'people/c123', type: 'manager' });
|
|
187
|
+
expect(runner.run).toHaveBeenCalledWith(
|
|
188
|
+
['people', 'relations', 'people/c123', '--type=manager'],
|
|
189
|
+
{ account: undefined },
|
|
190
|
+
);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
describe('gog_people_raw', () => {
|
|
195
|
+
it('calls run with userId', async () => {
|
|
196
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
197
|
+
const handlers = setupHandlers();
|
|
198
|
+
await handlers.get('gog_people_raw')!({ userId: 'people/c123' });
|
|
199
|
+
expect(runner.run).toHaveBeenCalledWith(['people', 'raw', 'people/c123'], { account: undefined });
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('passes --person-fields and --pretty when provided', async () => {
|
|
203
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
204
|
+
const handlers = setupHandlers();
|
|
205
|
+
await handlers.get('gog_people_raw')!({
|
|
206
|
+
userId: 'people/c123',
|
|
207
|
+
personFields: 'names,emailAddresses',
|
|
208
|
+
pretty: true,
|
|
209
|
+
});
|
|
210
|
+
expect(runner.run).toHaveBeenCalledWith(
|
|
211
|
+
['people', 'raw', 'people/c123', '--person-fields=names,emailAddresses', '--pretty'],
|
|
212
|
+
{ account: undefined },
|
|
213
|
+
);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('omits --pretty when false', async () => {
|
|
217
|
+
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
218
|
+
const handlers = setupHandlers();
|
|
219
|
+
await handlers.get('gog_people_raw')!({ userId: 'people/c123', pretty: false });
|
|
220
|
+
expect(runner.run).toHaveBeenCalledWith(['people', 'raw', 'people/c123'], { account: undefined });
|
|
221
|
+
});
|
|
222
|
+
});
|