gogcli-mcp 4.2.5 → 4.4.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/dist/index.js +1340 -262
- package/dist/lib.js +1381 -260
- package/manifest.json +9 -2
- package/package.json +2 -2
- package/server.json +2 -2
- package/src/arg-guard.ts +68 -0
- package/src/argv.ts +27 -0
- package/src/attachment-root.ts +111 -0
- package/src/attachments.ts +1 -0
- package/src/blob-upload.ts +4 -2
- package/src/dispatch-confirmation.ts +277 -0
- package/src/file-roots.ts +66 -0
- package/src/gmail-dispatch-guard.ts +70 -30
- package/src/gmail-results.ts +21 -2
- package/src/lib.ts +15 -0
- package/src/run-path-guard.ts +118 -0
- package/src/runner.ts +86 -18
- package/src/send-confirm-token.ts +167 -0
- package/src/tools/api.ts +60 -7
- package/src/tools/appscript.ts +12 -8
- package/src/tools/auth.ts +13 -3
- package/src/tools/calendar.ts +178 -15
- package/src/tools/chat.ts +94 -18
- package/src/tools/classroom.ts +110 -28
- package/src/tools/contacts.ts +5 -3
- package/src/tools/docs.ts +8 -6
- package/src/tools/drive.ts +96 -20
- package/src/tools/gmail.ts +175 -24
- package/src/tools/sheets.ts +10 -8
- package/src/tools/slides.ts +14 -9
- package/src/tools/tasks.ts +7 -5
- package/src/tools/utils.ts +52 -6
- package/tests/arg-guard.test.ts +80 -0
- package/tests/attachment-root.test.ts +130 -0
- package/tests/attachments.test.ts +8 -0
- package/tests/blob-upload.test.ts +4 -3
- package/tests/file-roots.test.ts +101 -0
- package/tests/gmail-dispatch-guard.test.ts +270 -11
- package/tests/gmail-results.test.ts +35 -1
- package/tests/run-path-guard.test.ts +142 -0
- package/tests/runner.test.ts +136 -0
- package/tests/send-confirm-token.test.ts +200 -0
- package/tests/tools/api.test.ts +74 -8
- package/tests/tools/appscript.test.ts +34 -8
- package/tests/tools/auth.test.ts +44 -17
- package/tests/tools/calendar.test.ts +33 -28
- package/tests/tools/chat.test.ts +50 -21
- package/tests/tools/classroom.test.ts +43 -39
- package/tests/tools/contacts.test.ts +3 -2
- package/tests/tools/dispatch-gates.test.ts +396 -0
- package/tests/tools/docs.test.ts +44 -15
- package/tests/tools/drive.test.ts +110 -20
- package/tests/tools/gmail-confirm-token.test.ts +274 -0
- package/tests/tools/gmail.test.ts +227 -29
- package/tests/tools/run-tool-examples.test.ts +69 -0
- package/tests/tools/run-vets.test.ts +131 -0
- package/tests/tools/sheets.test.ts +16 -15
- package/tests/tools/slides.test.ts +47 -11
- package/tests/tools/tasks.test.ts +7 -6
- package/tests/tools/utils.test.ts +32 -31
- package/vitest.config.ts +5 -0
|
@@ -2,10 +2,14 @@ import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
|
2
2
|
import { registerClassroomTools } from '../../src/tools/classroom.js';
|
|
3
3
|
import * as runner from '../../src/runner.js';
|
|
4
4
|
import { createTestHarness, type TestHarness } from '@chrischall/mcp-utils/test';
|
|
5
|
+
import { pos } from '../../src/argv.js';
|
|
5
6
|
|
|
6
7
|
vi.mock('../../src/runner.js');
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
// The dispatch rail asks before guest-visible / outbound calls; this client accepts.
|
|
10
|
+
const setupHandlers = () => createTestHarness(registerClassroomTools, {
|
|
11
|
+
elicitation: async () => ({ action: 'accept', content: { confirmed: true } }),
|
|
12
|
+
});
|
|
9
13
|
|
|
10
14
|
let harness: TestHarness;
|
|
11
15
|
|
|
@@ -51,7 +55,7 @@ describe('gog_classroom_courses_list', () => {
|
|
|
51
55
|
describe('gog_classroom_courses_get', () => {
|
|
52
56
|
it('calls run with courseId', async () => {
|
|
53
57
|
await harness.callTool('gog_classroom_courses_get', { courseId: 'c1' });
|
|
54
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'courses', 'get', 'c1'], { account: undefined });
|
|
58
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'courses', 'get', pos('c1')], { account: undefined });
|
|
55
59
|
});
|
|
56
60
|
|
|
57
61
|
it('returns error text on failure', async () => {
|
|
@@ -64,20 +68,20 @@ describe('gog_classroom_courses_get', () => {
|
|
|
64
68
|
describe('gog_classroom_students_list', () => {
|
|
65
69
|
it('calls run with courseId only', async () => {
|
|
66
70
|
await harness.callTool('gog_classroom_students_list', { courseId: 'c1' });
|
|
67
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'students', 'list', 'c1'], { account: undefined });
|
|
71
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'students', 'list', pos('c1')], { account: undefined });
|
|
68
72
|
});
|
|
69
73
|
|
|
70
74
|
it('passes all listing flags', async () => {
|
|
71
75
|
await harness.callTool('gog_classroom_students_list', { courseId: 'c1', max: 20, page: 'tok', all: true });
|
|
72
76
|
expect(runner.run).toHaveBeenCalledWith(
|
|
73
|
-
['classroom', 'students', 'list', 'c1', '--max=20', '--page=tok', '--all'],
|
|
77
|
+
['classroom', 'students', 'list', pos('c1'), '--max=20', '--page=tok', '--all'],
|
|
74
78
|
{ account: undefined },
|
|
75
79
|
);
|
|
76
80
|
});
|
|
77
81
|
|
|
78
82
|
it('omits --all when false', async () => {
|
|
79
83
|
await harness.callTool('gog_classroom_students_list', { courseId: 'c1', all: false });
|
|
80
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'students', 'list', 'c1'], { account: undefined });
|
|
84
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'students', 'list', pos('c1')], { account: undefined });
|
|
81
85
|
});
|
|
82
86
|
|
|
83
87
|
it('returns error text on failure', async () => {
|
|
@@ -90,7 +94,7 @@ describe('gog_classroom_students_list', () => {
|
|
|
90
94
|
describe('gog_classroom_students_get', () => {
|
|
91
95
|
it('calls run with courseId and userId', async () => {
|
|
92
96
|
await harness.callTool('gog_classroom_students_get', { courseId: 'c1', userId: 'u1' });
|
|
93
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'students', 'get', 'c1', 'u1'], { account: undefined });
|
|
97
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'students', 'get', pos('c1'), pos('u1')], { account: undefined });
|
|
94
98
|
});
|
|
95
99
|
|
|
96
100
|
it('returns error text on failure', async () => {
|
|
@@ -103,20 +107,20 @@ describe('gog_classroom_students_get', () => {
|
|
|
103
107
|
describe('gog_classroom_teachers_list', () => {
|
|
104
108
|
it('calls run with courseId only', async () => {
|
|
105
109
|
await harness.callTool('gog_classroom_teachers_list', { courseId: 'c1' });
|
|
106
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'teachers', 'list', 'c1'], { account: undefined });
|
|
110
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'teachers', 'list', pos('c1')], { account: undefined });
|
|
107
111
|
});
|
|
108
112
|
|
|
109
113
|
it('passes all listing flags', async () => {
|
|
110
114
|
await harness.callTool('gog_classroom_teachers_list', { courseId: 'c1', max: 20, page: 'tok', all: true });
|
|
111
115
|
expect(runner.run).toHaveBeenCalledWith(
|
|
112
|
-
['classroom', 'teachers', 'list', 'c1', '--max=20', '--page=tok', '--all'],
|
|
116
|
+
['classroom', 'teachers', 'list', pos('c1'), '--max=20', '--page=tok', '--all'],
|
|
113
117
|
{ account: undefined },
|
|
114
118
|
);
|
|
115
119
|
});
|
|
116
120
|
|
|
117
121
|
it('omits --all when false', async () => {
|
|
118
122
|
await harness.callTool('gog_classroom_teachers_list', { courseId: 'c1', all: false });
|
|
119
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'teachers', 'list', 'c1'], { account: undefined });
|
|
123
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'teachers', 'list', pos('c1')], { account: undefined });
|
|
120
124
|
});
|
|
121
125
|
|
|
122
126
|
it('returns error text on failure', async () => {
|
|
@@ -129,7 +133,7 @@ describe('gog_classroom_teachers_list', () => {
|
|
|
129
133
|
describe('gog_classroom_teachers_get', () => {
|
|
130
134
|
it('calls run with courseId and userId', async () => {
|
|
131
135
|
await harness.callTool('gog_classroom_teachers_get', { courseId: 'c1', userId: 'u1' });
|
|
132
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'teachers', 'get', 'c1', 'u1'], { account: undefined });
|
|
136
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'teachers', 'get', pos('c1'), pos('u1')], { account: undefined });
|
|
133
137
|
});
|
|
134
138
|
|
|
135
139
|
it('returns error text on failure', async () => {
|
|
@@ -142,20 +146,20 @@ describe('gog_classroom_teachers_get', () => {
|
|
|
142
146
|
describe('gog_classroom_roster', () => {
|
|
143
147
|
it('calls run with courseId only', async () => {
|
|
144
148
|
await harness.callTool('gog_classroom_roster', { courseId: 'c1' });
|
|
145
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'roster', 'c1'], { account: undefined });
|
|
149
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'roster', pos('c1')], { account: undefined });
|
|
146
150
|
});
|
|
147
151
|
|
|
148
152
|
it('passes all flags', async () => {
|
|
149
153
|
await harness.callTool('gog_classroom_roster', { courseId: 'c1', students: true, teachers: true, max: 50, page: 'tok', all: true });
|
|
150
154
|
expect(runner.run).toHaveBeenCalledWith(
|
|
151
|
-
['classroom', 'roster', 'c1', '--students', '--teachers', '--max=50', '--page=tok', '--all'],
|
|
155
|
+
['classroom', 'roster', pos('c1'), '--students', '--teachers', '--max=50', '--page=tok', '--all'],
|
|
152
156
|
{ account: undefined },
|
|
153
157
|
);
|
|
154
158
|
});
|
|
155
159
|
|
|
156
160
|
it('omits boolean flags when false', async () => {
|
|
157
161
|
await harness.callTool('gog_classroom_roster', { courseId: 'c1', students: false, teachers: false, all: false });
|
|
158
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'roster', 'c1'], { account: undefined });
|
|
162
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'roster', pos('c1')], { account: undefined });
|
|
159
163
|
});
|
|
160
164
|
|
|
161
165
|
it('returns error text on failure', async () => {
|
|
@@ -168,7 +172,7 @@ describe('gog_classroom_roster', () => {
|
|
|
168
172
|
describe('gog_classroom_coursework_list', () => {
|
|
169
173
|
it('calls run with courseId only', async () => {
|
|
170
174
|
await harness.callTool('gog_classroom_coursework_list', { courseId: 'c1' });
|
|
171
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'coursework', 'list', 'c1'], { account: undefined });
|
|
175
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'coursework', 'list', pos('c1')], { account: undefined });
|
|
172
176
|
});
|
|
173
177
|
|
|
174
178
|
it('passes all listing flags', async () => {
|
|
@@ -183,14 +187,14 @@ describe('gog_classroom_coursework_list', () => {
|
|
|
183
187
|
scanPages: 5,
|
|
184
188
|
});
|
|
185
189
|
expect(runner.run).toHaveBeenCalledWith(
|
|
186
|
-
['classroom', 'coursework', 'list', 'c1', '--state=PUBLISHED', '--topic=t1', '--order-by=updateTime desc', '--max=50', '--page=tok', '--all', '--scan-pages=5'],
|
|
190
|
+
['classroom', 'coursework', 'list', pos('c1'), '--state=PUBLISHED', '--topic=t1', '--order-by=updateTime desc', '--max=50', '--page=tok', '--all', '--scan-pages=5'],
|
|
187
191
|
{ account: undefined },
|
|
188
192
|
);
|
|
189
193
|
});
|
|
190
194
|
|
|
191
195
|
it('omits --all when false', async () => {
|
|
192
196
|
await harness.callTool('gog_classroom_coursework_list', { courseId: 'c1', all: false });
|
|
193
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'coursework', 'list', 'c1'], { account: undefined });
|
|
197
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'coursework', 'list', pos('c1')], { account: undefined });
|
|
194
198
|
});
|
|
195
199
|
|
|
196
200
|
it('returns error text on failure', async () => {
|
|
@@ -203,7 +207,7 @@ describe('gog_classroom_coursework_list', () => {
|
|
|
203
207
|
describe('gog_classroom_coursework_get', () => {
|
|
204
208
|
it('calls run with courseId and courseworkId', async () => {
|
|
205
209
|
await harness.callTool('gog_classroom_coursework_get', { courseId: 'c1', courseworkId: 'w1' });
|
|
206
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'coursework', 'get', 'c1', 'w1'], { account: undefined });
|
|
210
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'coursework', 'get', pos('c1'), pos('w1')], { account: undefined });
|
|
207
211
|
});
|
|
208
212
|
|
|
209
213
|
it('returns error text on failure', async () => {
|
|
@@ -216,7 +220,7 @@ describe('gog_classroom_coursework_get', () => {
|
|
|
216
220
|
describe('gog_classroom_submissions_list', () => {
|
|
217
221
|
it('calls run with ids only', async () => {
|
|
218
222
|
await harness.callTool('gog_classroom_submissions_list', { courseId: 'c1', courseworkId: 'w1' });
|
|
219
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'submissions', 'list', 'c1', 'w1'], { account: undefined });
|
|
223
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'submissions', 'list', pos('c1'), pos('w1')], { account: undefined });
|
|
220
224
|
});
|
|
221
225
|
|
|
222
226
|
it('passes all listing flags', async () => {
|
|
@@ -231,14 +235,14 @@ describe('gog_classroom_submissions_list', () => {
|
|
|
231
235
|
all: true,
|
|
232
236
|
});
|
|
233
237
|
expect(runner.run).toHaveBeenCalledWith(
|
|
234
|
-
['classroom', 'submissions', 'list', 'c1', 'w1', '--state=TURNED_IN', '--late=late', '--user=u1', '--max=20', '--page=tok', '--all'],
|
|
238
|
+
['classroom', 'submissions', 'list', pos('c1'), pos('w1'), '--state=TURNED_IN', '--late=late', '--user=u1', '--max=20', '--page=tok', '--all'],
|
|
235
239
|
{ account: undefined },
|
|
236
240
|
);
|
|
237
241
|
});
|
|
238
242
|
|
|
239
243
|
it('omits --all when false', async () => {
|
|
240
244
|
await harness.callTool('gog_classroom_submissions_list', { courseId: 'c1', courseworkId: 'w1', all: false });
|
|
241
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'submissions', 'list', 'c1', 'w1'], { account: undefined });
|
|
245
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'submissions', 'list', pos('c1'), pos('w1')], { account: undefined });
|
|
242
246
|
});
|
|
243
247
|
|
|
244
248
|
it('returns error text on failure', async () => {
|
|
@@ -251,7 +255,7 @@ describe('gog_classroom_submissions_list', () => {
|
|
|
251
255
|
describe('gog_classroom_submissions_get', () => {
|
|
252
256
|
it('calls run with all three ids', async () => {
|
|
253
257
|
await harness.callTool('gog_classroom_submissions_get', { courseId: 'c1', courseworkId: 'w1', submissionId: 's1' });
|
|
254
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'submissions', 'get', 'c1', 'w1', 's1'], { account: undefined });
|
|
258
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'submissions', 'get', pos('c1'), pos('w1'), pos('s1')], { account: undefined });
|
|
255
259
|
});
|
|
256
260
|
|
|
257
261
|
it('returns error text on failure', async () => {
|
|
@@ -264,13 +268,13 @@ describe('gog_classroom_submissions_get', () => {
|
|
|
264
268
|
describe('gog_classroom_submissions_grade', () => {
|
|
265
269
|
it('calls run with ids only', async () => {
|
|
266
270
|
await harness.callTool('gog_classroom_submissions_grade', { courseId: 'c1', courseworkId: 'w1', submissionId: 's1' });
|
|
267
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'submissions', 'grade', 'c1', 'w1', 's1'], { account: undefined });
|
|
271
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'submissions', 'grade', pos('c1'), pos('w1'), pos('s1')], { account: undefined });
|
|
268
272
|
});
|
|
269
273
|
|
|
270
274
|
it('passes --draft and --assigned when provided', async () => {
|
|
271
275
|
await harness.callTool('gog_classroom_submissions_grade', { courseId: 'c1', courseworkId: 'w1', submissionId: 's1', draft: '90', assigned: '95' });
|
|
272
276
|
expect(runner.run).toHaveBeenCalledWith(
|
|
273
|
-
['classroom', 'submissions', 'grade', 'c1', 'w1', 's1', '--draft=90', '--assigned=95'],
|
|
277
|
+
['classroom', 'submissions', 'grade', pos('c1'), pos('w1'), pos('s1'), '--draft=90', '--assigned=95'],
|
|
274
278
|
{ account: undefined },
|
|
275
279
|
);
|
|
276
280
|
});
|
|
@@ -285,7 +289,7 @@ describe('gog_classroom_submissions_grade', () => {
|
|
|
285
289
|
describe('gog_classroom_submissions_return', () => {
|
|
286
290
|
it('calls run with ids', async () => {
|
|
287
291
|
await harness.callTool('gog_classroom_submissions_return', { courseId: 'c1', courseworkId: 'w1', submissionId: 's1' });
|
|
288
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'submissions', 'return', 'c1', 'w1', 's1'], { account: undefined });
|
|
292
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'submissions', 'return', pos('c1'), pos('w1'), pos('s1')], { account: undefined });
|
|
289
293
|
});
|
|
290
294
|
|
|
291
295
|
it('returns error text on failure', async () => {
|
|
@@ -298,7 +302,7 @@ describe('gog_classroom_submissions_return', () => {
|
|
|
298
302
|
describe('gog_classroom_submissions_turn_in', () => {
|
|
299
303
|
it('calls run with ids', async () => {
|
|
300
304
|
await harness.callTool('gog_classroom_submissions_turn_in', { courseId: 'c1', courseworkId: 'w1', submissionId: 's1' });
|
|
301
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'submissions', 'turn-in', 'c1', 'w1', 's1'], { account: undefined });
|
|
305
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'submissions', 'turn-in', pos('c1'), pos('w1'), pos('s1')], { account: undefined });
|
|
302
306
|
});
|
|
303
307
|
|
|
304
308
|
it('returns error text on failure', async () => {
|
|
@@ -311,7 +315,7 @@ describe('gog_classroom_submissions_turn_in', () => {
|
|
|
311
315
|
describe('gog_classroom_submissions_reclaim', () => {
|
|
312
316
|
it('calls run with ids', async () => {
|
|
313
317
|
await harness.callTool('gog_classroom_submissions_reclaim', { courseId: 'c1', courseworkId: 'w1', submissionId: 's1' });
|
|
314
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'submissions', 'reclaim', 'c1', 'w1', 's1'], { account: undefined });
|
|
318
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'submissions', 'reclaim', pos('c1'), pos('w1'), pos('s1')], { account: undefined });
|
|
315
319
|
});
|
|
316
320
|
|
|
317
321
|
it('returns error text on failure', async () => {
|
|
@@ -324,20 +328,20 @@ describe('gog_classroom_submissions_reclaim', () => {
|
|
|
324
328
|
describe('gog_classroom_announcements_list', () => {
|
|
325
329
|
it('calls run with courseId only', async () => {
|
|
326
330
|
await harness.callTool('gog_classroom_announcements_list', { courseId: 'c1' });
|
|
327
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'announcements', 'list', 'c1'], { account: undefined });
|
|
331
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'announcements', 'list', pos('c1')], { account: undefined });
|
|
328
332
|
});
|
|
329
333
|
|
|
330
334
|
it('passes all listing flags', async () => {
|
|
331
335
|
await harness.callTool('gog_classroom_announcements_list', { courseId: 'c1', state: 'PUBLISHED', orderBy: 'updateTime desc', max: 20, page: 'tok', all: true });
|
|
332
336
|
expect(runner.run).toHaveBeenCalledWith(
|
|
333
|
-
['classroom', 'announcements', 'list', 'c1', '--state=PUBLISHED', '--order-by=updateTime desc', '--max=20', '--page=tok', '--all'],
|
|
337
|
+
['classroom', 'announcements', 'list', pos('c1'), '--state=PUBLISHED', '--order-by=updateTime desc', '--max=20', '--page=tok', '--all'],
|
|
334
338
|
{ account: undefined },
|
|
335
339
|
);
|
|
336
340
|
});
|
|
337
341
|
|
|
338
342
|
it('omits --all when false', async () => {
|
|
339
343
|
await harness.callTool('gog_classroom_announcements_list', { courseId: 'c1', all: false });
|
|
340
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'announcements', 'list', 'c1'], { account: undefined });
|
|
344
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'announcements', 'list', pos('c1')], { account: undefined });
|
|
341
345
|
});
|
|
342
346
|
|
|
343
347
|
it('returns error text on failure', async () => {
|
|
@@ -350,7 +354,7 @@ describe('gog_classroom_announcements_list', () => {
|
|
|
350
354
|
describe('gog_classroom_announcements_get', () => {
|
|
351
355
|
it('calls run with ids', async () => {
|
|
352
356
|
await harness.callTool('gog_classroom_announcements_get', { courseId: 'c1', announcementId: 'a1' });
|
|
353
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'announcements', 'get', 'c1', 'a1'], { account: undefined });
|
|
357
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'announcements', 'get', pos('c1'), pos('a1')], { account: undefined });
|
|
354
358
|
});
|
|
355
359
|
|
|
356
360
|
it('returns error text on failure', async () => {
|
|
@@ -364,7 +368,7 @@ describe('gog_classroom_announcements_create', () => {
|
|
|
364
368
|
it('calls run with required text only', async () => {
|
|
365
369
|
await harness.callTool('gog_classroom_announcements_create', { courseId: 'c1', text: 'Hi' });
|
|
366
370
|
expect(runner.run).toHaveBeenCalledWith(
|
|
367
|
-
['classroom', 'announcements', 'create', 'c1', '--text=Hi'],
|
|
371
|
+
['classroom', 'announcements', 'create', pos('c1'), '--text=Hi'],
|
|
368
372
|
{ account: undefined },
|
|
369
373
|
);
|
|
370
374
|
});
|
|
@@ -372,7 +376,7 @@ describe('gog_classroom_announcements_create', () => {
|
|
|
372
376
|
it('passes all optional flags', async () => {
|
|
373
377
|
await harness.callTool('gog_classroom_announcements_create', { courseId: 'c1', text: 'Hi', state: 'DRAFT', scheduled: '2026-05-01T12:00' });
|
|
374
378
|
expect(runner.run).toHaveBeenCalledWith(
|
|
375
|
-
['classroom', 'announcements', 'create', 'c1', '--text=Hi', '--state=DRAFT', '--scheduled=2026-05-01T12:00'],
|
|
379
|
+
['classroom', 'announcements', 'create', pos('c1'), '--text=Hi', '--state=DRAFT', '--scheduled=2026-05-01T12:00'],
|
|
376
380
|
{ account: undefined },
|
|
377
381
|
);
|
|
378
382
|
});
|
|
@@ -387,20 +391,20 @@ describe('gog_classroom_announcements_create', () => {
|
|
|
387
391
|
describe('gog_classroom_topics_list', () => {
|
|
388
392
|
it('calls run with courseId only', async () => {
|
|
389
393
|
await harness.callTool('gog_classroom_topics_list', { courseId: 'c1' });
|
|
390
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'topics', 'list', 'c1'], { account: undefined });
|
|
394
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'topics', 'list', pos('c1')], { account: undefined });
|
|
391
395
|
});
|
|
392
396
|
|
|
393
397
|
it('passes all listing flags', async () => {
|
|
394
398
|
await harness.callTool('gog_classroom_topics_list', { courseId: 'c1', max: 20, page: 'tok', all: true });
|
|
395
399
|
expect(runner.run).toHaveBeenCalledWith(
|
|
396
|
-
['classroom', 'topics', 'list', 'c1', '--max=20', '--page=tok', '--all'],
|
|
400
|
+
['classroom', 'topics', 'list', pos('c1'), '--max=20', '--page=tok', '--all'],
|
|
397
401
|
{ account: undefined },
|
|
398
402
|
);
|
|
399
403
|
});
|
|
400
404
|
|
|
401
405
|
it('omits --all when false', async () => {
|
|
402
406
|
await harness.callTool('gog_classroom_topics_list', { courseId: 'c1', all: false });
|
|
403
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'topics', 'list', 'c1'], { account: undefined });
|
|
407
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'topics', 'list', pos('c1')], { account: undefined });
|
|
404
408
|
});
|
|
405
409
|
|
|
406
410
|
it('returns error text on failure', async () => {
|
|
@@ -413,7 +417,7 @@ describe('gog_classroom_topics_list', () => {
|
|
|
413
417
|
describe('gog_classroom_topics_get', () => {
|
|
414
418
|
it('calls run with ids', async () => {
|
|
415
419
|
await harness.callTool('gog_classroom_topics_get', { courseId: 'c1', topicId: 't1' });
|
|
416
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'topics', 'get', 'c1', 't1'], { account: undefined });
|
|
420
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'topics', 'get', pos('c1'), pos('t1')], { account: undefined });
|
|
417
421
|
});
|
|
418
422
|
|
|
419
423
|
it('returns error text on failure', async () => {
|
|
@@ -452,7 +456,7 @@ describe('gog_classroom_invitations_list', () => {
|
|
|
452
456
|
describe('gog_classroom_invitations_get', () => {
|
|
453
457
|
it('calls run with invitationId', async () => {
|
|
454
458
|
await harness.callTool('gog_classroom_invitations_get', { invitationId: 'i1' });
|
|
455
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'invitations', 'get', 'i1'], { account: undefined });
|
|
459
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'invitations', 'get', pos('i1')], { account: undefined });
|
|
456
460
|
});
|
|
457
461
|
|
|
458
462
|
it('returns error text on failure', async () => {
|
|
@@ -465,7 +469,7 @@ describe('gog_classroom_invitations_get', () => {
|
|
|
465
469
|
describe('gog_classroom_invitations_accept', () => {
|
|
466
470
|
it('calls run with invitationId', async () => {
|
|
467
471
|
await harness.callTool('gog_classroom_invitations_accept', { invitationId: 'i1' });
|
|
468
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'invitations', 'accept', 'i1'], { account: undefined });
|
|
472
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'invitations', 'accept', pos('i1')], { account: undefined });
|
|
469
473
|
});
|
|
470
474
|
|
|
471
475
|
it('returns error text on failure', async () => {
|
|
@@ -483,7 +487,7 @@ describe('gog_classroom_profile_get', () => {
|
|
|
483
487
|
|
|
484
488
|
it('passes userId when provided', async () => {
|
|
485
489
|
await harness.callTool('gog_classroom_profile_get', { userId: 'u1' });
|
|
486
|
-
expect(runner.run).toHaveBeenCalledWith(['classroom', 'profile', 'get', 'u1'], { account: undefined });
|
|
490
|
+
expect(runner.run).toHaveBeenCalledWith(['classroom', 'profile', 'get', pos('u1')], { account: undefined });
|
|
487
491
|
});
|
|
488
492
|
|
|
489
493
|
it('returns error text on failure', async () => {
|
|
@@ -2,6 +2,7 @@ import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
|
2
2
|
import { registerContactsTools } from '../../src/tools/contacts.js';
|
|
3
3
|
import * as runner from '../../src/runner.js';
|
|
4
4
|
import { createTestHarness } from '@chrischall/mcp-utils/test';
|
|
5
|
+
import { pos } from '../../src/argv.js';
|
|
5
6
|
|
|
6
7
|
vi.mock('../../src/runner.js');
|
|
7
8
|
|
|
@@ -14,7 +15,7 @@ describe('gog_contacts_search', () => {
|
|
|
14
15
|
vi.mocked(runner.run).mockResolvedValue('{"connections":[]}');
|
|
15
16
|
const harness = await setupHandlers();
|
|
16
17
|
await harness.callTool('gog_contacts_search', { query: 'alice' });
|
|
17
|
-
expect(runner.run).toHaveBeenCalledWith(['contacts', 'search', 'alice'], { account: undefined });
|
|
18
|
+
expect(runner.run).toHaveBeenCalledWith(['contacts', 'search', pos('alice')], { account: undefined });
|
|
18
19
|
});
|
|
19
20
|
|
|
20
21
|
it('returns error text on failure', async () => {
|
|
@@ -46,7 +47,7 @@ describe('gog_contacts_get', () => {
|
|
|
46
47
|
vi.mocked(runner.run).mockResolvedValue('{"resourceName":"people/c123"}');
|
|
47
48
|
const harness = await setupHandlers();
|
|
48
49
|
await harness.callTool('gog_contacts_get', { resourceName: 'people/c123' });
|
|
49
|
-
expect(runner.run).toHaveBeenCalledWith(['contacts', 'get', 'people/c123'], { account: undefined });
|
|
50
|
+
expect(runner.run).toHaveBeenCalledWith(['contacts', 'get', pos('people/c123')], { account: undefined });
|
|
50
51
|
});
|
|
51
52
|
|
|
52
53
|
it('returns error text on failure', async () => {
|