@classroomio/mcp 0.0.5 → 0.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/README.md +50 -4
- package/dist/index.js +148 -29
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,6 +43,7 @@ Current tools:
|
|
|
43
43
|
|
|
44
44
|
- `list_org_courses`
|
|
45
45
|
- `get_course_structure`
|
|
46
|
+
- `update_course_landing_page`
|
|
46
47
|
- `create_course_draft`
|
|
47
48
|
- `create_course_draft_from_course`
|
|
48
49
|
- `get_course_draft`
|
|
@@ -215,7 +216,37 @@ Result:
|
|
|
215
216
|
- publish returns the live `courseId` and public `courseUrl`
|
|
216
217
|
- publish can optionally set a random Unsplash-derived course cover
|
|
217
218
|
|
|
218
|
-
### Flow 2:
|
|
219
|
+
### Flow 2: Update a landing page with AI-generated copy and media
|
|
220
|
+
|
|
221
|
+
User says:
|
|
222
|
+
|
|
223
|
+
```text
|
|
224
|
+
Rewrite this course landing page to feel more premium, generate a new cover image, and add three believable reviews.
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Expected tool sequence:
|
|
228
|
+
|
|
229
|
+
1. Agent calls `list_org_courses` if it needs to resolve the course ID by name first.
|
|
230
|
+
2. Agent calls `update_course_landing_page`.
|
|
231
|
+
|
|
232
|
+
What the landing-page tool can update:
|
|
233
|
+
|
|
234
|
+
- title
|
|
235
|
+
- short description
|
|
236
|
+
- overview
|
|
237
|
+
- requirements
|
|
238
|
+
- goals
|
|
239
|
+
- pricing fields
|
|
240
|
+
- instructor section
|
|
241
|
+
- reviews
|
|
242
|
+
- landing page image
|
|
243
|
+
|
|
244
|
+
The tool can either:
|
|
245
|
+
|
|
246
|
+
- use an explicit `imageUrl`
|
|
247
|
+
- or generate a random Unsplash-based image with `generateImage` and `imageQuery`
|
|
248
|
+
|
|
249
|
+
### Flow 3: Create a draft from a PDF
|
|
219
250
|
|
|
220
251
|
User says:
|
|
221
252
|
|
|
@@ -238,7 +269,7 @@ Important:
|
|
|
238
269
|
- the PDF does not need to be uploaded to MCP
|
|
239
270
|
- the MCP package only receives structured JSON
|
|
240
271
|
|
|
241
|
-
### Flow
|
|
272
|
+
### Flow 4: Tag a draft before publish
|
|
242
273
|
|
|
243
274
|
User says:
|
|
244
275
|
|
|
@@ -258,7 +289,7 @@ Result:
|
|
|
258
289
|
- publish ensures the tags exist in ClassroomIO
|
|
259
290
|
- publish assigns those tags to the live course
|
|
260
291
|
|
|
261
|
-
### Flow
|
|
292
|
+
### Flow 5: Update an existing course safely
|
|
262
293
|
|
|
263
294
|
User says:
|
|
264
295
|
|
|
@@ -286,7 +317,7 @@ What this publish does today:
|
|
|
286
317
|
- upserts lesson language content
|
|
287
318
|
- merges draft tags into the existing course
|
|
288
319
|
|
|
289
|
-
### Flow
|
|
320
|
+
### Flow 6: Add exercises to a live course
|
|
290
321
|
|
|
291
322
|
User says:
|
|
292
323
|
|
|
@@ -351,6 +382,21 @@ Exercise tools use the live course directly:
|
|
|
351
382
|
- `create_course_exercise_from_template`
|
|
352
383
|
- `update_course_exercise`
|
|
353
384
|
|
|
385
|
+
Supported `questionTypeId` values for exercise payloads:
|
|
386
|
+
|
|
387
|
+
- `1` `RADIO` - Single answer
|
|
388
|
+
- `2` `CHECKBOX` - Multiple answers
|
|
389
|
+
- `3` `TEXTAREA` - Paragraph
|
|
390
|
+
- `4` `TRUE_FALSE` - True/False
|
|
391
|
+
- `5` `SHORT_ANSWER` - Short answer
|
|
392
|
+
- `6` `NUMERIC` - Numeric answer
|
|
393
|
+
- `7` `FILL_BLANK` - Fill in the blank
|
|
394
|
+
- `8` `FILE_UPLOAD` - File upload
|
|
395
|
+
- `9` `MATCHING` - Matching
|
|
396
|
+
- `10` `ORDERING` - Ordering
|
|
397
|
+
- `11` `HOTSPOT` - Hotspot
|
|
398
|
+
- `12` `LINK` - Links
|
|
399
|
+
|
|
354
400
|
## Operational Notes
|
|
355
401
|
|
|
356
402
|
- `create_course_draft_from_course` may add warnings if a live course uses legacy lesson notes instead of localized lesson content
|
package/dist/index.js
CHANGED
|
@@ -35,6 +35,12 @@ var ClassroomIoApiClient = class {
|
|
|
35
35
|
method: "GET"
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
|
+
async updateCourseLandingPage(courseId, payload) {
|
|
39
|
+
return this.request(`/course/${courseId}/landing-page`, {
|
|
40
|
+
method: "PUT",
|
|
41
|
+
body: payload
|
|
42
|
+
});
|
|
43
|
+
}
|
|
38
44
|
async getCourseDraft(draftId) {
|
|
39
45
|
return this.request(`/organization/course-import/drafts/${draftId}`, {
|
|
40
46
|
method: "GET"
|
|
@@ -443,6 +449,7 @@ var ZOrganizationApiKeyScope = z10.enum([
|
|
|
443
449
|
"course_import:draft:update",
|
|
444
450
|
"course_import:draft:publish",
|
|
445
451
|
"course:read",
|
|
452
|
+
"course:write",
|
|
446
453
|
"course:tag:write",
|
|
447
454
|
"course:exercise:read",
|
|
448
455
|
"course:exercise:write",
|
|
@@ -1051,6 +1058,33 @@ var ZCourseCreate = z12.object({
|
|
|
1051
1058
|
type: z12.enum(["LIVE_CLASS", "SELF_PACED"]),
|
|
1052
1059
|
organizationId: z12.string().min(1)
|
|
1053
1060
|
});
|
|
1061
|
+
var ZCourseReward = z12.object({
|
|
1062
|
+
show: z12.boolean(),
|
|
1063
|
+
description: z12.string()
|
|
1064
|
+
});
|
|
1065
|
+
var ZCourseInstructor = z12.object({
|
|
1066
|
+
name: z12.string(),
|
|
1067
|
+
role: z12.string(),
|
|
1068
|
+
coursesNo: z12.number(),
|
|
1069
|
+
description: z12.string(),
|
|
1070
|
+
imgUrl: z12.string()
|
|
1071
|
+
});
|
|
1072
|
+
var ZCourseCertificate = z12.object({
|
|
1073
|
+
templateUrl: z12.string()
|
|
1074
|
+
});
|
|
1075
|
+
var ZCourseReview = z12.object({
|
|
1076
|
+
id: z12.number(),
|
|
1077
|
+
hide: z12.boolean(),
|
|
1078
|
+
name: z12.string(),
|
|
1079
|
+
avatar_url: z12.string(),
|
|
1080
|
+
rating: z12.number(),
|
|
1081
|
+
created_at: z12.number(),
|
|
1082
|
+
description: z12.string()
|
|
1083
|
+
});
|
|
1084
|
+
var ZCourseLessonTabsOrder = z12.array(z12.object({
|
|
1085
|
+
id: z12.union([z12.literal(1), z12.literal(2), z12.literal(3), z12.literal(4)]),
|
|
1086
|
+
name: z12.string()
|
|
1087
|
+
}));
|
|
1054
1088
|
var ZCourseMetadata = z12.object({
|
|
1055
1089
|
requirements: z12.string().optional(),
|
|
1056
1090
|
description: z12.string().optional(),
|
|
@@ -1059,39 +1093,36 @@ var ZCourseMetadata = z12.object({
|
|
|
1059
1093
|
showDiscount: z12.boolean().optional(),
|
|
1060
1094
|
discount: z12.number().optional(),
|
|
1061
1095
|
paymentLink: z12.string().optional(),
|
|
1062
|
-
reward:
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
name: z12.string(),
|
|
1068
|
-
role: z12.string(),
|
|
1069
|
-
coursesNo: z12.number(),
|
|
1070
|
-
description: z12.string(),
|
|
1071
|
-
imgUrl: z12.string()
|
|
1072
|
-
}).optional(),
|
|
1073
|
-
certificate: z12.object({
|
|
1074
|
-
templateUrl: z12.string()
|
|
1075
|
-
}).optional(),
|
|
1076
|
-
reviews: z12.array(z12.object({
|
|
1077
|
-
id: z12.number(),
|
|
1078
|
-
hide: z12.boolean(),
|
|
1079
|
-
name: z12.string(),
|
|
1080
|
-
avatar_url: z12.string(),
|
|
1081
|
-
rating: z12.number(),
|
|
1082
|
-
created_at: z12.number(),
|
|
1083
|
-
description: z12.string()
|
|
1084
|
-
})).optional(),
|
|
1085
|
-
lessonTabsOrder: z12.array(z12.object({
|
|
1086
|
-
id: z12.union([z12.literal(1), z12.literal(2), z12.literal(3), z12.literal(4)]),
|
|
1087
|
-
name: z12.string()
|
|
1088
|
-
})).optional(),
|
|
1096
|
+
reward: ZCourseReward.optional(),
|
|
1097
|
+
instructor: ZCourseInstructor.optional(),
|
|
1098
|
+
certificate: ZCourseCertificate.optional(),
|
|
1099
|
+
reviews: z12.array(ZCourseReview).optional(),
|
|
1100
|
+
lessonTabsOrder: ZCourseLessonTabsOrder.optional(),
|
|
1089
1101
|
grading: z12.boolean().optional(),
|
|
1090
1102
|
lessonDownload: z12.boolean().optional(),
|
|
1091
1103
|
allowNewStudent: z12.boolean(),
|
|
1092
1104
|
sectionDisplay: z12.record(z12.string(), z12.boolean()).optional(),
|
|
1093
1105
|
isContentGroupingEnabled: z12.boolean().optional()
|
|
1094
1106
|
});
|
|
1107
|
+
var ZCourseLandingPageMetadataUpdate = z12.object({
|
|
1108
|
+
requirements: z12.string().optional(),
|
|
1109
|
+
description: z12.string().optional(),
|
|
1110
|
+
goals: z12.string().optional(),
|
|
1111
|
+
videoUrl: z12.string().optional(),
|
|
1112
|
+
showDiscount: z12.boolean().optional(),
|
|
1113
|
+
discount: z12.number().optional(),
|
|
1114
|
+
paymentLink: z12.string().optional(),
|
|
1115
|
+
reward: ZCourseReward.partial().optional(),
|
|
1116
|
+
instructor: ZCourseInstructor.partial().optional(),
|
|
1117
|
+
certificate: ZCourseCertificate.partial().optional(),
|
|
1118
|
+
reviews: z12.array(ZCourseReview).optional(),
|
|
1119
|
+
lessonTabsOrder: ZCourseLessonTabsOrder.optional(),
|
|
1120
|
+
grading: z12.boolean().optional(),
|
|
1121
|
+
lessonDownload: z12.boolean().optional(),
|
|
1122
|
+
allowNewStudent: z12.boolean().optional(),
|
|
1123
|
+
sectionDisplay: z12.record(z12.string(), z12.boolean()).optional(),
|
|
1124
|
+
isContentGroupingEnabled: z12.boolean().optional()
|
|
1125
|
+
});
|
|
1095
1126
|
var ZCourseUpdate = z12.object({
|
|
1096
1127
|
title: z12.string().min(1).optional(),
|
|
1097
1128
|
description: z12.string().min(1).optional(),
|
|
@@ -1101,6 +1132,8 @@ var ZCourseUpdate = z12.object({
|
|
|
1101
1132
|
isPublished: z12.boolean().optional(),
|
|
1102
1133
|
overview: z12.string().optional(),
|
|
1103
1134
|
metadata: ZCourseMetadata.optional(),
|
|
1135
|
+
cost: z12.number().int().min(0).optional(),
|
|
1136
|
+
currency: z12.enum(["NGN", "USD"]).optional(),
|
|
1104
1137
|
isCertificateDownloadable: z12.boolean().optional(),
|
|
1105
1138
|
certificateTheme: z12.string().optional(),
|
|
1106
1139
|
tagIds: z12.array(z12.uuid()).max(100).optional()
|
|
@@ -1108,6 +1141,17 @@ var ZCourseUpdate = z12.object({
|
|
|
1108
1141
|
var ZCourseUpdateParam = z12.object({
|
|
1109
1142
|
courseId: z12.string().min(1)
|
|
1110
1143
|
});
|
|
1144
|
+
var ZCourseLandingPageUpdate = z12.object({
|
|
1145
|
+
title: z12.string().min(1).optional(),
|
|
1146
|
+
description: z12.string().min(1).optional(),
|
|
1147
|
+
overview: z12.string().optional(),
|
|
1148
|
+
cost: z12.number().int().min(0).optional(),
|
|
1149
|
+
currency: z12.enum(["NGN", "USD"]).optional(),
|
|
1150
|
+
imageUrl: z12.string().url().optional(),
|
|
1151
|
+
generateImage: z12.boolean().optional(),
|
|
1152
|
+
imageQuery: z12.string().min(1).max(120).optional(),
|
|
1153
|
+
metadata: ZCourseLandingPageMetadataUpdate.optional()
|
|
1154
|
+
});
|
|
1111
1155
|
var ZCourseDeleteParam = z12.object({
|
|
1112
1156
|
courseId: z12.string().min(1)
|
|
1113
1157
|
});
|
|
@@ -1259,6 +1303,66 @@ var ZCourseImportDraftPublishToCourse = ZCourseImportDraftPublish.extend({
|
|
|
1259
1303
|
courseId: z13.string().min(1)
|
|
1260
1304
|
});
|
|
1261
1305
|
|
|
1306
|
+
// ../utils/dist/validation/course/section.js
|
|
1307
|
+
import * as z14 from "zod";
|
|
1308
|
+
var ZCourseSectionCreate = z14.object({
|
|
1309
|
+
title: z14.string().min(1),
|
|
1310
|
+
courseId: z14.string().min(1),
|
|
1311
|
+
order: z14.number().int().min(0).optional()
|
|
1312
|
+
});
|
|
1313
|
+
var ZCourseSectionUpdate = z14.object({
|
|
1314
|
+
title: z14.string().min(1).optional(),
|
|
1315
|
+
order: z14.number().int().min(0).optional()
|
|
1316
|
+
});
|
|
1317
|
+
var ZCourseSectionPromoteUngrouped = z14.object({
|
|
1318
|
+
title: z14.string().min(1)
|
|
1319
|
+
});
|
|
1320
|
+
var ZCourseSectionGetParam = z14.object({
|
|
1321
|
+
sectionId: z14.string().min(1)
|
|
1322
|
+
});
|
|
1323
|
+
var ZCourseSectionReorder = z14.object({
|
|
1324
|
+
sections: z14.array(z14.object({
|
|
1325
|
+
id: z14.string().min(1),
|
|
1326
|
+
order: z14.number().int().min(0)
|
|
1327
|
+
})).min(1)
|
|
1328
|
+
});
|
|
1329
|
+
|
|
1330
|
+
// ../utils/dist/validation/course/invite.js
|
|
1331
|
+
import * as z15 from "zod";
|
|
1332
|
+
var ZCourseInviteParam = z15.object({
|
|
1333
|
+
courseId: z15.string().min(1)
|
|
1334
|
+
});
|
|
1335
|
+
var ZCourseInviteRevokeParam = z15.object({
|
|
1336
|
+
courseId: z15.string().min(1),
|
|
1337
|
+
inviteId: z15.string().uuid()
|
|
1338
|
+
});
|
|
1339
|
+
var ZCourseInviteAuditParam = z15.object({
|
|
1340
|
+
courseId: z15.string().min(1),
|
|
1341
|
+
inviteId: z15.string().uuid()
|
|
1342
|
+
});
|
|
1343
|
+
var ZCourseInviteTokenParam = z15.object({
|
|
1344
|
+
token: z15.string().min(1)
|
|
1345
|
+
});
|
|
1346
|
+
var ZCreatePublicCourseInviteLink = z15.object({
|
|
1347
|
+
courseId: z15.uuid()
|
|
1348
|
+
});
|
|
1349
|
+
var ZCourseInvitePreset = z15.enum(["ONE_TIME_24H", "MULTI_USE_7D", "MULTI_USE_30D", "CUSTOM"]);
|
|
1350
|
+
var ZCreateCourseInvite = z15.object({
|
|
1351
|
+
preset: ZCourseInvitePreset.default("MULTI_USE_30D"),
|
|
1352
|
+
expiresAt: z15.string().min(1).optional(),
|
|
1353
|
+
maxUses: z15.number().int().min(1).max(1e3).optional(),
|
|
1354
|
+
allowedEmails: z15.array(z15.string().email()).max(100).optional(),
|
|
1355
|
+
allowedDomains: z15.array(z15.string().min(1)).max(100).optional(),
|
|
1356
|
+
recipientEmails: z15.array(z15.string().email()).max(500).optional(),
|
|
1357
|
+
recipientCsv: z15.string().max(25e3).optional(),
|
|
1358
|
+
sendEmail: z15.boolean().default(false),
|
|
1359
|
+
metadata: z15.record(z15.string(), z15.unknown()).optional()
|
|
1360
|
+
}).refine((data) => {
|
|
1361
|
+
const hasEmails = (data.recipientEmails?.length ?? 0) > 0;
|
|
1362
|
+
const hasCsv = typeof data.recipientCsv === "string" && data.recipientCsv.trim().length > 0;
|
|
1363
|
+
return hasEmails || hasCsv;
|
|
1364
|
+
}, { message: "recipientEmails or recipientCsv is required", path: ["recipientEmails"] });
|
|
1365
|
+
|
|
1262
1366
|
// src/tools/course-drafts.ts
|
|
1263
1367
|
var ZUpdateCourseDraftToolInput = ZCourseImportDraftUpdate.extend({
|
|
1264
1368
|
draftId: ZCourseImportDraftGetParam.shape.draftId
|
|
@@ -1284,6 +1388,9 @@ var ZUpdateCourseExerciseToolInput = ZExerciseUpdate.extend({
|
|
|
1284
1388
|
courseId: ZCourseImportCourseParam.shape.courseId,
|
|
1285
1389
|
exerciseId: ZExerciseGetParam.shape.exerciseId
|
|
1286
1390
|
});
|
|
1391
|
+
var ZUpdateCourseLandingPageToolInput = ZCourseLandingPageUpdate.extend({
|
|
1392
|
+
courseId: ZCourseImportCourseParam.shape.courseId
|
|
1393
|
+
});
|
|
1287
1394
|
var ZPublishCourseDraftToolInput = ZCourseImportDraftPublish.extend({
|
|
1288
1395
|
draftId: ZCourseImportDraftGetParam.shape.draftId
|
|
1289
1396
|
});
|
|
@@ -1302,9 +1409,11 @@ var getCourseExerciseShape = ZGetCourseExerciseToolInput.shape;
|
|
|
1302
1409
|
var createCourseExerciseShape = ZCreateCourseExerciseToolInput.shape;
|
|
1303
1410
|
var createCourseExerciseFromTemplateShape = ZCreateCourseExerciseFromTemplateToolInput.shape;
|
|
1304
1411
|
var updateCourseExerciseShape = ZUpdateCourseExerciseToolInput.shape;
|
|
1412
|
+
var updateCourseLandingPageShape = ZUpdateCourseLandingPageToolInput.shape;
|
|
1305
1413
|
var publishCourseDraftShape = ZPublishCourseDraftToolInput.shape;
|
|
1306
1414
|
var publishCourseDraftToExistingCourseShape = ZPublishCourseDraftToExistingCourseToolInput.shape;
|
|
1307
1415
|
var tagCoursesShape = ZAutomationCourseTagAssignment.shape;
|
|
1416
|
+
var SUPPORTED_QUESTION_TYPES_GUIDE = "Supported questionTypeId values: RADIO=1 (Single answer), CHECKBOX=2 (Multiple answers), TEXTAREA=3 (Paragraph), TRUE_FALSE=4 (True/False), SHORT_ANSWER=5 (Short answer), NUMERIC=6 (Numeric answer), FILL_BLANK=7 (Fill in the blank), FILE_UPLOAD=8 (File upload), MATCHING=9 (Matching), ORDERING=10 (Ordering), HOTSPOT=11 (Hotspot), LINK=12 (Links). Use the numeric ids in exercise payloads.";
|
|
1308
1417
|
function registerCourseDraftTools(server, apiClient) {
|
|
1309
1418
|
server.tool(
|
|
1310
1419
|
"list_org_courses",
|
|
@@ -1326,6 +1435,16 @@ function registerCourseDraftTools(server, apiClient) {
|
|
|
1326
1435
|
return jsonContent(result);
|
|
1327
1436
|
}
|
|
1328
1437
|
);
|
|
1438
|
+
server.tool(
|
|
1439
|
+
"update_course_landing_page",
|
|
1440
|
+
"Update landing-page-facing course fields on a live course, including headline copy, overview, requirements, goals, pricing, reviews, instructor information, and the course image. Use imageUrl to set an explicit cover image, or set generateImage/imageQuery to fetch a random Unsplash-based image.",
|
|
1441
|
+
updateCourseLandingPageShape,
|
|
1442
|
+
async (args) => {
|
|
1443
|
+
const { courseId, ...payload } = ZUpdateCourseLandingPageToolInput.parse(args);
|
|
1444
|
+
const result = await apiClient.updateCourseLandingPage(courseId, payload);
|
|
1445
|
+
return jsonContent(result);
|
|
1446
|
+
}
|
|
1447
|
+
);
|
|
1329
1448
|
server.tool(
|
|
1330
1449
|
"create_course_draft",
|
|
1331
1450
|
"Create a new unpublished course draft from structured course JSON. Use this before the first publish.",
|
|
@@ -1378,7 +1497,7 @@ function registerCourseDraftTools(server, apiClient) {
|
|
|
1378
1497
|
);
|
|
1379
1498
|
server.tool(
|
|
1380
1499
|
"create_course_exercise",
|
|
1381
|
-
|
|
1500
|
+
`Create a new exercise directly on a live course. Use this for adding exercises after a course has already been published. ${SUPPORTED_QUESTION_TYPES_GUIDE}`,
|
|
1382
1501
|
createCourseExerciseShape,
|
|
1383
1502
|
async (args) => {
|
|
1384
1503
|
const { courseId, ...payload } = ZCreateCourseExerciseToolInput.parse(args);
|
|
@@ -1398,7 +1517,7 @@ function registerCourseDraftTools(server, apiClient) {
|
|
|
1398
1517
|
);
|
|
1399
1518
|
server.tool(
|
|
1400
1519
|
"update_course_exercise",
|
|
1401
|
-
|
|
1520
|
+
`Update an existing exercise on a live course, including questions and options. ${SUPPORTED_QUESTION_TYPES_GUIDE}`,
|
|
1402
1521
|
updateCourseExerciseShape,
|
|
1403
1522
|
async (args) => {
|
|
1404
1523
|
const { courseId, exerciseId, ...payload } = ZUpdateCourseExerciseToolInput.parse(args);
|