@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.
Files changed (3) hide show
  1. package/README.md +50 -4
  2. package/dist/index.js +148 -29
  3. 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: Create a draft from a PDF
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 3: Tag a draft before publish
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 4: Update an existing course safely
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 5: Add exercises to a live course
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: z12.object({
1063
- show: z12.boolean(),
1064
- description: z12.string()
1065
- }).optional(),
1066
- instructor: z12.object({
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
- "Create a new exercise directly on a live course. Use this for adding exercises after a course has already been published.",
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
- "Update an existing exercise on a live course, including questions and options.",
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classroomio/mcp",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",