gogcli-mcp 2.0.2 → 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.
Files changed (44) hide show
  1. package/.claude-plugin/marketplace.json +38 -0
  2. package/.claude-plugin/plugin.json +25 -0
  3. package/.mcp.json +14 -0
  4. package/.mcpbignore +27 -0
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +1334 -963
  8. package/dist/lib.d.ts +6 -0
  9. package/dist/lib.d.ts.map +1 -0
  10. package/dist/lib.js +1560 -1189
  11. package/dist/runner.d.ts +12 -0
  12. package/dist/runner.d.ts.map +1 -0
  13. package/dist/server.d.ts +7 -0
  14. package/dist/server.d.ts.map +1 -0
  15. package/dist/tools/auth.d.ts +3 -0
  16. package/dist/tools/auth.d.ts.map +1 -0
  17. package/dist/tools/calendar.d.ts +3 -0
  18. package/dist/tools/calendar.d.ts.map +1 -0
  19. package/dist/tools/contacts.d.ts +3 -0
  20. package/dist/tools/contacts.d.ts.map +1 -0
  21. package/dist/tools/docs.d.ts +3 -0
  22. package/dist/tools/docs.d.ts.map +1 -0
  23. package/dist/tools/drive.d.ts +3 -0
  24. package/dist/tools/drive.d.ts.map +1 -0
  25. package/dist/tools/gmail.d.ts +3 -0
  26. package/dist/tools/gmail.d.ts.map +1 -0
  27. package/dist/tools/sheets.d.ts +3 -0
  28. package/dist/tools/sheets.d.ts.map +1 -0
  29. package/dist/tools/tasks.d.ts +3 -0
  30. package/dist/tools/tasks.d.ts.map +1 -0
  31. package/dist/tools/utils.d.ts +14 -0
  32. package/dist/tools/utils.d.ts.map +1 -0
  33. package/manifest.json +1 -101
  34. package/package.json +4 -3
  35. package/server.json +35 -0
  36. package/src/runner.ts +4 -1
  37. package/src/tools/classroom.ts +2 -297
  38. package/src/tools/contacts.ts +1 -1
  39. package/src/tools/slides.ts +1 -108
  40. package/tests/helpers/extras-harness.ts +31 -0
  41. package/tests/runner.test.ts +30 -0
  42. package/tests/tools/calendar.test.ts +1 -0
  43. package/tests/tools/classroom.test.ts +0 -352
  44. package/tests/tools/slides.test.ts +6 -278
@@ -72,107 +72,6 @@ describe('gog_classroom_courses_get', () => {
72
72
  });
73
73
  });
74
74
 
75
- describe('gog_classroom_courses_create', () => {
76
- it('calls run with required name only', async () => {
77
- await handlers.get('gog_classroom_courses_create')!({ name: 'Math 101' });
78
- expect(runner.run).toHaveBeenCalledWith(
79
- ['classroom', 'courses', 'create', '--name=Math 101'],
80
- { account: undefined },
81
- );
82
- });
83
-
84
- it('passes all optional flags', async () => {
85
- await handlers.get('gog_classroom_courses_create')!({
86
- name: 'Math 101',
87
- owner: 'me',
88
- section: 'Section A',
89
- descriptionHeading: 'Welcome',
90
- description: 'Algebra',
91
- room: 'R101',
92
- state: 'ACTIVE',
93
- });
94
- expect(runner.run).toHaveBeenCalledWith(
95
- ['classroom', 'courses', 'create', '--name=Math 101', '--owner=me', '--section=Section A', '--description-heading=Welcome', '--description=Algebra', '--room=R101', '--state=ACTIVE'],
96
- { account: undefined },
97
- );
98
- });
99
-
100
- it('returns error text on failure', async () => {
101
- vi.mocked(runner.run).mockRejectedValue(new Error('Create failed'));
102
- const result = await handlers.get('gog_classroom_courses_create')!({ name: 'X' });
103
- expect(result.content[0].text).toBe('Error: Create failed');
104
- });
105
- });
106
-
107
- describe('gog_classroom_courses_update', () => {
108
- it('calls run with courseId only', async () => {
109
- await handlers.get('gog_classroom_courses_update')!({ courseId: 'c1' });
110
- expect(runner.run).toHaveBeenCalledWith(['classroom', 'courses', 'update', 'c1'], { account: undefined });
111
- });
112
-
113
- it('passes all optional flags', async () => {
114
- await handlers.get('gog_classroom_courses_update')!({
115
- courseId: 'c1',
116
- name: 'New Name',
117
- owner: 'me',
118
- section: 'B',
119
- descriptionHeading: 'Heading',
120
- description: 'Desc',
121
- room: 'R2',
122
- state: 'ARCHIVED',
123
- });
124
- expect(runner.run).toHaveBeenCalledWith(
125
- ['classroom', 'courses', 'update', 'c1', '--name=New Name', '--owner=me', '--section=B', '--description-heading=Heading', '--description=Desc', '--room=R2', '--state=ARCHIVED'],
126
- { account: undefined },
127
- );
128
- });
129
-
130
- it('returns error text on failure', async () => {
131
- vi.mocked(runner.run).mockRejectedValue(new Error('Update failed'));
132
- const result = await handlers.get('gog_classroom_courses_update')!({ courseId: 'bad' });
133
- expect(result.content[0].text).toBe('Error: Update failed');
134
- });
135
- });
136
-
137
- describe('gog_classroom_courses_delete', () => {
138
- it('calls run with courseId', async () => {
139
- await handlers.get('gog_classroom_courses_delete')!({ courseId: 'c1' });
140
- expect(runner.run).toHaveBeenCalledWith(['classroom', 'courses', 'delete', 'c1'], { account: undefined });
141
- });
142
-
143
- it('returns error text on failure', async () => {
144
- vi.mocked(runner.run).mockRejectedValue(new Error('Delete failed'));
145
- const result = await handlers.get('gog_classroom_courses_delete')!({ courseId: 'bad' });
146
- expect(result.content[0].text).toBe('Error: Delete failed');
147
- });
148
- });
149
-
150
- describe('gog_classroom_courses_archive', () => {
151
- it('calls run with courseId', async () => {
152
- await handlers.get('gog_classroom_courses_archive')!({ courseId: 'c1' });
153
- expect(runner.run).toHaveBeenCalledWith(['classroom', 'courses', 'archive', 'c1'], { account: undefined });
154
- });
155
-
156
- it('returns error text on failure', async () => {
157
- vi.mocked(runner.run).mockRejectedValue(new Error('Archive failed'));
158
- const result = await handlers.get('gog_classroom_courses_archive')!({ courseId: 'x' });
159
- expect(result.content[0].text).toBe('Error: Archive failed');
160
- });
161
- });
162
-
163
- describe('gog_classroom_courses_unarchive', () => {
164
- it('calls run with courseId', async () => {
165
- await handlers.get('gog_classroom_courses_unarchive')!({ courseId: 'c1' });
166
- expect(runner.run).toHaveBeenCalledWith(['classroom', 'courses', 'unarchive', 'c1'], { account: undefined });
167
- });
168
-
169
- it('returns error text on failure', async () => {
170
- vi.mocked(runner.run).mockRejectedValue(new Error('Unarchive failed'));
171
- const result = await handlers.get('gog_classroom_courses_unarchive')!({ courseId: 'x' });
172
- expect(result.content[0].text).toBe('Error: Unarchive failed');
173
- });
174
- });
175
-
176
75
  describe('gog_classroom_students_list', () => {
177
76
  it('calls run with courseId only', async () => {
178
77
  await handlers.get('gog_classroom_students_list')!({ courseId: 'c1' });
@@ -212,40 +111,6 @@ describe('gog_classroom_students_get', () => {
212
111
  });
213
112
  });
214
113
 
215
- describe('gog_classroom_students_add', () => {
216
- it('calls run with courseId and userId', async () => {
217
- await handlers.get('gog_classroom_students_add')!({ courseId: 'c1', userId: 'u1' });
218
- expect(runner.run).toHaveBeenCalledWith(['classroom', 'students', 'add', 'c1', 'u1'], { account: undefined });
219
- });
220
-
221
- it('passes --enrollment-code when provided', async () => {
222
- await handlers.get('gog_classroom_students_add')!({ courseId: 'c1', userId: 'u1', enrollmentCode: 'abc123' });
223
- expect(runner.run).toHaveBeenCalledWith(
224
- ['classroom', 'students', 'add', 'c1', 'u1', '--enrollment-code=abc123'],
225
- { account: undefined },
226
- );
227
- });
228
-
229
- it('returns error text on failure', async () => {
230
- vi.mocked(runner.run).mockRejectedValue(new Error('Add failed'));
231
- const result = await handlers.get('gog_classroom_students_add')!({ courseId: 'c1', userId: 'u1' });
232
- expect(result.content[0].text).toBe('Error: Add failed');
233
- });
234
- });
235
-
236
- describe('gog_classroom_students_remove', () => {
237
- it('calls run with courseId and userId', async () => {
238
- await handlers.get('gog_classroom_students_remove')!({ courseId: 'c1', userId: 'u1' });
239
- expect(runner.run).toHaveBeenCalledWith(['classroom', 'students', 'remove', 'c1', 'u1'], { account: undefined });
240
- });
241
-
242
- it('returns error text on failure', async () => {
243
- vi.mocked(runner.run).mockRejectedValue(new Error('Remove failed'));
244
- const result = await handlers.get('gog_classroom_students_remove')!({ courseId: 'c1', userId: 'u1' });
245
- expect(result.content[0].text).toBe('Error: Remove failed');
246
- });
247
- });
248
-
249
114
  describe('gog_classroom_teachers_list', () => {
250
115
  it('calls run with courseId only', async () => {
251
116
  await handlers.get('gog_classroom_teachers_list')!({ courseId: 'c1' });
@@ -285,32 +150,6 @@ describe('gog_classroom_teachers_get', () => {
285
150
  });
286
151
  });
287
152
 
288
- describe('gog_classroom_teachers_add', () => {
289
- it('calls run with courseId and userId', async () => {
290
- await handlers.get('gog_classroom_teachers_add')!({ courseId: 'c1', userId: 'u1' });
291
- expect(runner.run).toHaveBeenCalledWith(['classroom', 'teachers', 'add', 'c1', 'u1'], { account: undefined });
292
- });
293
-
294
- it('returns error text on failure', async () => {
295
- vi.mocked(runner.run).mockRejectedValue(new Error('Add failed'));
296
- const result = await handlers.get('gog_classroom_teachers_add')!({ courseId: 'c1', userId: 'u1' });
297
- expect(result.content[0].text).toBe('Error: Add failed');
298
- });
299
- });
300
-
301
- describe('gog_classroom_teachers_remove', () => {
302
- it('calls run with courseId and userId', async () => {
303
- await handlers.get('gog_classroom_teachers_remove')!({ courseId: 'c1', userId: 'u1' });
304
- expect(runner.run).toHaveBeenCalledWith(['classroom', 'teachers', 'remove', 'c1', 'u1'], { account: undefined });
305
- });
306
-
307
- it('returns error text on failure', async () => {
308
- vi.mocked(runner.run).mockRejectedValue(new Error('Remove failed'));
309
- const result = await handlers.get('gog_classroom_teachers_remove')!({ courseId: 'c1', userId: 'u1' });
310
- expect(result.content[0].text).toBe('Error: Remove failed');
311
- });
312
- });
313
-
314
153
  describe('gog_classroom_roster', () => {
315
154
  it('calls run with courseId only', async () => {
316
155
  await handlers.get('gog_classroom_roster')!({ courseId: 'c1' });
@@ -385,89 +224,6 @@ describe('gog_classroom_coursework_get', () => {
385
224
  });
386
225
  });
387
226
 
388
- describe('gog_classroom_coursework_create', () => {
389
- it('calls run with required title only', async () => {
390
- await handlers.get('gog_classroom_coursework_create')!({ courseId: 'c1', title: 'HW1' });
391
- expect(runner.run).toHaveBeenCalledWith(
392
- ['classroom', 'coursework', 'create', 'c1', '--title=HW1'],
393
- { account: undefined },
394
- );
395
- });
396
-
397
- it('passes all optional flags', async () => {
398
- await handlers.get('gog_classroom_coursework_create')!({
399
- courseId: 'c1',
400
- title: 'HW1',
401
- description: 'Chapter 1',
402
- type: 'ASSIGNMENT',
403
- state: 'PUBLISHED',
404
- maxPoints: 100,
405
- due: '2026-05-01T23:59',
406
- dueDate: '2026-05-01',
407
- dueTime: '23:59',
408
- scheduled: '2026-04-30T12:00',
409
- topic: 't1',
410
- });
411
- expect(runner.run).toHaveBeenCalledWith(
412
- ['classroom', 'coursework', 'create', 'c1', '--title=HW1', '--description=Chapter 1', '--type=ASSIGNMENT', '--state=PUBLISHED', '--max-points=100', '--due=2026-05-01T23:59', '--due-date=2026-05-01', '--due-time=23:59', '--scheduled=2026-04-30T12:00', '--topic=t1'],
413
- { account: undefined },
414
- );
415
- });
416
-
417
- it('returns error text on failure', async () => {
418
- vi.mocked(runner.run).mockRejectedValue(new Error('Create failed'));
419
- const result = await handlers.get('gog_classroom_coursework_create')!({ courseId: 'c1', title: 'HW1' });
420
- expect(result.content[0].text).toBe('Error: Create failed');
421
- });
422
- });
423
-
424
- describe('gog_classroom_coursework_update', () => {
425
- it('calls run with ids only', async () => {
426
- await handlers.get('gog_classroom_coursework_update')!({ courseId: 'c1', courseworkId: 'w1' });
427
- expect(runner.run).toHaveBeenCalledWith(['classroom', 'coursework', 'update', 'c1', 'w1'], { account: undefined });
428
- });
429
-
430
- it('passes all optional flags', async () => {
431
- await handlers.get('gog_classroom_coursework_update')!({
432
- courseId: 'c1',
433
- courseworkId: 'w1',
434
- title: 'New Title',
435
- description: 'Desc',
436
- type: 'SHORT_ANSWER_QUESTION',
437
- state: 'DRAFT',
438
- maxPoints: 50,
439
- due: '2026-05-01T23:59',
440
- dueDate: '2026-05-01',
441
- dueTime: '23:59',
442
- scheduled: '2026-04-30T12:00',
443
- topic: 't1',
444
- });
445
- expect(runner.run).toHaveBeenCalledWith(
446
- ['classroom', 'coursework', 'update', 'c1', 'w1', '--title=New Title', '--description=Desc', '--type=SHORT_ANSWER_QUESTION', '--state=DRAFT', '--max-points=50', '--due=2026-05-01T23:59', '--due-date=2026-05-01', '--due-time=23:59', '--scheduled=2026-04-30T12:00', '--topic=t1'],
447
- { account: undefined },
448
- );
449
- });
450
-
451
- it('returns error text on failure', async () => {
452
- vi.mocked(runner.run).mockRejectedValue(new Error('Update failed'));
453
- const result = await handlers.get('gog_classroom_coursework_update')!({ courseId: 'c1', courseworkId: 'w1' });
454
- expect(result.content[0].text).toBe('Error: Update failed');
455
- });
456
- });
457
-
458
- describe('gog_classroom_coursework_delete', () => {
459
- it('calls run with ids', async () => {
460
- await handlers.get('gog_classroom_coursework_delete')!({ courseId: 'c1', courseworkId: 'w1' });
461
- expect(runner.run).toHaveBeenCalledWith(['classroom', 'coursework', 'delete', 'c1', 'w1'], { account: undefined });
462
- });
463
-
464
- it('returns error text on failure', async () => {
465
- vi.mocked(runner.run).mockRejectedValue(new Error('Delete failed'));
466
- const result = await handlers.get('gog_classroom_coursework_delete')!({ courseId: 'c1', courseworkId: 'w1' });
467
- expect(result.content[0].text).toBe('Error: Delete failed');
468
- });
469
- });
470
-
471
227
  describe('gog_classroom_submissions_list', () => {
472
228
  it('calls run with ids only', async () => {
473
229
  await handlers.get('gog_classroom_submissions_list')!({ courseId: 'c1', courseworkId: 'w1' });
@@ -639,40 +395,6 @@ describe('gog_classroom_announcements_create', () => {
639
395
  });
640
396
  });
641
397
 
642
- describe('gog_classroom_announcements_update', () => {
643
- it('calls run with ids only', async () => {
644
- await handlers.get('gog_classroom_announcements_update')!({ courseId: 'c1', announcementId: 'a1' });
645
- expect(runner.run).toHaveBeenCalledWith(['classroom', 'announcements', 'update', 'c1', 'a1'], { account: undefined });
646
- });
647
-
648
- it('passes all optional flags', async () => {
649
- await handlers.get('gog_classroom_announcements_update')!({ courseId: 'c1', announcementId: 'a1', text: 'edited', state: 'PUBLISHED', scheduled: '2026-05-01T12:00' });
650
- expect(runner.run).toHaveBeenCalledWith(
651
- ['classroom', 'announcements', 'update', 'c1', 'a1', '--text=edited', '--state=PUBLISHED', '--scheduled=2026-05-01T12:00'],
652
- { account: undefined },
653
- );
654
- });
655
-
656
- it('returns error text on failure', async () => {
657
- vi.mocked(runner.run).mockRejectedValue(new Error('Update failed'));
658
- const result = await handlers.get('gog_classroom_announcements_update')!({ courseId: 'c1', announcementId: 'a1' });
659
- expect(result.content[0].text).toBe('Error: Update failed');
660
- });
661
- });
662
-
663
- describe('gog_classroom_announcements_delete', () => {
664
- it('calls run with ids', async () => {
665
- await handlers.get('gog_classroom_announcements_delete')!({ courseId: 'c1', announcementId: 'a1' });
666
- expect(runner.run).toHaveBeenCalledWith(['classroom', 'announcements', 'delete', 'c1', 'a1'], { account: undefined });
667
- });
668
-
669
- it('returns error text on failure', async () => {
670
- vi.mocked(runner.run).mockRejectedValue(new Error('Delete failed'));
671
- const result = await handlers.get('gog_classroom_announcements_delete')!({ courseId: 'c1', announcementId: 'a1' });
672
- expect(result.content[0].text).toBe('Error: Delete failed');
673
- });
674
- });
675
-
676
398
  describe('gog_classroom_topics_list', () => {
677
399
  it('calls run with courseId only', async () => {
678
400
  await handlers.get('gog_classroom_topics_list')!({ courseId: 'c1' });
@@ -712,51 +434,6 @@ describe('gog_classroom_topics_get', () => {
712
434
  });
713
435
  });
714
436
 
715
- describe('gog_classroom_topics_create', () => {
716
- it('calls run with courseId and name', async () => {
717
- await handlers.get('gog_classroom_topics_create')!({ courseId: 'c1', name: 'Week 1' });
718
- expect(runner.run).toHaveBeenCalledWith(
719
- ['classroom', 'topics', 'create', 'c1', '--name=Week 1'],
720
- { account: undefined },
721
- );
722
- });
723
-
724
- it('returns error text on failure', async () => {
725
- vi.mocked(runner.run).mockRejectedValue(new Error('Create failed'));
726
- const result = await handlers.get('gog_classroom_topics_create')!({ courseId: 'c1', name: 'x' });
727
- expect(result.content[0].text).toBe('Error: Create failed');
728
- });
729
- });
730
-
731
- describe('gog_classroom_topics_update', () => {
732
- it('calls run with ids and name', async () => {
733
- await handlers.get('gog_classroom_topics_update')!({ courseId: 'c1', topicId: 't1', name: 'Week 2' });
734
- expect(runner.run).toHaveBeenCalledWith(
735
- ['classroom', 'topics', 'update', 'c1', 't1', '--name=Week 2'],
736
- { account: undefined },
737
- );
738
- });
739
-
740
- it('returns error text on failure', async () => {
741
- vi.mocked(runner.run).mockRejectedValue(new Error('Update failed'));
742
- const result = await handlers.get('gog_classroom_topics_update')!({ courseId: 'c1', topicId: 't1', name: 'x' });
743
- expect(result.content[0].text).toBe('Error: Update failed');
744
- });
745
- });
746
-
747
- describe('gog_classroom_topics_delete', () => {
748
- it('calls run with ids', async () => {
749
- await handlers.get('gog_classroom_topics_delete')!({ courseId: 'c1', topicId: 't1' });
750
- expect(runner.run).toHaveBeenCalledWith(['classroom', 'topics', 'delete', 'c1', 't1'], { account: undefined });
751
- });
752
-
753
- it('returns error text on failure', async () => {
754
- vi.mocked(runner.run).mockRejectedValue(new Error('Delete failed'));
755
- const result = await handlers.get('gog_classroom_topics_delete')!({ courseId: 'c1', topicId: 't1' });
756
- expect(result.content[0].text).toBe('Error: Delete failed');
757
- });
758
- });
759
-
760
437
  describe('gog_classroom_invitations_list', () => {
761
438
  it('calls run with no flags', async () => {
762
439
  await handlers.get('gog_classroom_invitations_list')!({});
@@ -796,22 +473,6 @@ describe('gog_classroom_invitations_get', () => {
796
473
  });
797
474
  });
798
475
 
799
- describe('gog_classroom_invitations_create', () => {
800
- it('calls run with courseId, userId, role', async () => {
801
- await handlers.get('gog_classroom_invitations_create')!({ courseId: 'c1', userId: 'u1', role: 'STUDENT' });
802
- expect(runner.run).toHaveBeenCalledWith(
803
- ['classroom', 'invitations', 'create', 'c1', 'u1', '--role=STUDENT'],
804
- { account: undefined },
805
- );
806
- });
807
-
808
- it('returns error text on failure', async () => {
809
- vi.mocked(runner.run).mockRejectedValue(new Error('Create failed'));
810
- const result = await handlers.get('gog_classroom_invitations_create')!({ courseId: 'c1', userId: 'u1', role: 'TEACHER' });
811
- expect(result.content[0].text).toBe('Error: Create failed');
812
- });
813
- });
814
-
815
476
  describe('gog_classroom_invitations_accept', () => {
816
477
  it('calls run with invitationId', async () => {
817
478
  await handlers.get('gog_classroom_invitations_accept')!({ invitationId: 'i1' });
@@ -825,19 +486,6 @@ describe('gog_classroom_invitations_accept', () => {
825
486
  });
826
487
  });
827
488
 
828
- describe('gog_classroom_invitations_delete', () => {
829
- it('calls run with invitationId', async () => {
830
- await handlers.get('gog_classroom_invitations_delete')!({ invitationId: 'i1' });
831
- expect(runner.run).toHaveBeenCalledWith(['classroom', 'invitations', 'delete', 'i1'], { account: undefined });
832
- });
833
-
834
- it('returns error text on failure', async () => {
835
- vi.mocked(runner.run).mockRejectedValue(new Error('Delete failed'));
836
- const result = await handlers.get('gog_classroom_invitations_delete')!({ invitationId: 'bad' });
837
- expect(result.content[0].text).toBe('Error: Delete failed');
838
- });
839
- });
840
-
841
489
  describe('gog_classroom_profile_get', () => {
842
490
  it('calls run with no userId (self)', async () => {
843
491
  await handlers.get('gog_classroom_profile_get')!({});