canvas-lms-mcp 1.5.0 → 1.6.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.
@@ -2,10 +2,14 @@
2
2
 
3
3
 
4
4
 
5
- var _chunk6HRYCB4Ccjs = require('../chunk-6HRYCB4C.cjs');
6
5
 
7
6
 
7
+ var _chunkKEDPR66Wcjs = require('../chunk-KEDPR66W.cjs');
8
8
 
9
9
 
10
- exports.CanvasApiError = _chunk6HRYCB4Ccjs.CanvasApiError; exports.CanvasClient = _chunk6HRYCB4Ccjs.CanvasClient; exports.CanvasHttpClient = _chunk6HRYCB4Ccjs.CanvasHttpClient;
10
+
11
+
12
+
13
+
14
+ exports.CanvasApiError = _chunkKEDPR66Wcjs.CanvasApiError; exports.CanvasClient = _chunkKEDPR66Wcjs.CanvasClient; exports.CanvasHttpClient = _chunkKEDPR66Wcjs.CanvasHttpClient; exports.appendCanvasQuery = _chunkKEDPR66Wcjs.appendCanvasQuery; exports.toCanvasQuery = _chunkKEDPR66Wcjs.toCanvasQuery;
11
15
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/canvas-lms-mcp/canvas-lms-mcp/dist/canvas/index.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACF,yDAA8B;AAC9B;AACE;AACA;AACA;AACF,gLAAC","file":"/home/runner/work/canvas-lms-mcp/canvas-lms-mcp/dist/canvas/index.cjs"}
1
+ {"version":3,"sources":["/home/runner/work/canvas-lms-mcp/canvas-lms-mcp/dist/canvas/index.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACF,yDAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACF,0SAAC","file":"/home/runner/work/canvas-lms-mcp/canvas-lms-mcp/dist/canvas/index.cjs"}
@@ -1,11 +1,15 @@
1
1
  import {
2
2
  CanvasApiError,
3
3
  CanvasClient,
4
- CanvasHttpClient
5
- } from "../chunk-X7YODHAN.js";
4
+ CanvasHttpClient,
5
+ appendCanvasQuery,
6
+ toCanvasQuery
7
+ } from "../chunk-L3OHOWW5.js";
6
8
  export {
7
9
  CanvasApiError,
8
10
  CanvasClient,
9
- CanvasHttpClient
11
+ CanvasHttpClient,
12
+ appendCanvasQuery,
13
+ toCanvasQuery
10
14
  };
11
15
  //# sourceMappingURL=index.js.map
@@ -8,7 +8,7 @@ import {
8
8
  OUTCOME_ROLLUP_SORT_BY,
9
9
  OUTCOME_SORT_ORDER,
10
10
  SEARCH_CONTENT_TYPES
11
- } from "./chunk-X7YODHAN.js";
11
+ } from "./chunk-L3OHOWW5.js";
12
12
 
13
13
  // src/server.ts
14
14
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -244,53 +244,148 @@ ${allErrors.join("\n")}`);
244
244
 
245
245
  // src/tools/assignments.ts
246
246
  import { z as z3 } from "zod";
247
+ var ASSIGNMENT_LIST_INCLUDE = [
248
+ "submission",
249
+ "assignment_visibility",
250
+ "all_dates",
251
+ "overrides",
252
+ "observed_users",
253
+ "can_edit",
254
+ "score_statistics"
255
+ ];
256
+ var ASSIGNMENT_GET_INCLUDE = [
257
+ "submission",
258
+ "assignment_visibility",
259
+ "overrides",
260
+ "observed_users",
261
+ "can_edit",
262
+ "score_statistics",
263
+ "all_dates"
264
+ ];
265
+ var ASSIGNMENT_BUCKET = [
266
+ "past",
267
+ "overdue",
268
+ "undated",
269
+ "ungraded",
270
+ "unsubmitted",
271
+ "upcoming",
272
+ "future"
273
+ ];
274
+ var ASSIGNMENT_ORDER_BY = ["position", "name", "due_at"];
275
+ var ASSIGNMENT_GROUP_INCLUDE = [
276
+ "assignments",
277
+ "discussion_topic",
278
+ "all_dates",
279
+ "assignment_visibility",
280
+ "overrides",
281
+ "submission",
282
+ "observed_users",
283
+ "can_edit",
284
+ "score_statistics"
285
+ ];
247
286
  function assignmentTools(canvas) {
248
287
  return [
249
288
  {
250
289
  name: "list_assignments",
251
- description: "List all assignments in a course.",
290
+ description: "List all assignments in a course. Use `include` to request submission, all_dates, overrides, score_statistics, etc. Use `bucket` to filter by past/upcoming/overdue/etc. Other filters: `search_term`, `assignment_ids`, `order_by`.",
252
291
  inputSchema: {
253
- course_id: z3.number().describe("The Canvas course ID")
292
+ course_id: z3.number().describe("The Canvas course ID"),
293
+ include: z3.array(z3.enum(ASSIGNMENT_LIST_INCLUDE)).optional().describe("Extra fields to include on each assignment (Canvas include[] param)"),
294
+ search_term: z3.string().optional().describe("Partial name substring to filter assignments by"),
295
+ bucket: z3.enum(ASSIGNMENT_BUCKET).optional().describe("Only include assignments in the given bucket"),
296
+ assignment_ids: z3.array(z3.number()).optional().describe("Restrict to the given list of assignment IDs"),
297
+ order_by: z3.enum(ASSIGNMENT_ORDER_BY).optional().describe("Field to sort the result by"),
298
+ override_assignment_dates: z3.boolean().optional().describe(
299
+ "Apply assignment overrides to due/unlock/lock dates (default Canvas behavior: true)"
300
+ ),
301
+ needs_grading_count_by_section: z3.boolean().optional().describe("Break needs_grading_count down by section"),
302
+ post_to_sis: z3.boolean().optional().describe("Filter to assignments that are/are not posted to SIS")
254
303
  },
255
304
  annotations: {
256
305
  readOnlyHint: true,
257
306
  openWorldHint: true
258
307
  },
259
308
  handler: async (params) => {
260
- const course_id = params.course_id;
261
- return canvas.assignments.list(course_id);
309
+ const opts = {};
310
+ if (params.include !== void 0)
311
+ opts.include = params.include;
312
+ if (params.search_term !== void 0) opts.search_term = params.search_term;
313
+ if (params.bucket !== void 0) opts.bucket = params.bucket;
314
+ if (params.assignment_ids !== void 0)
315
+ opts.assignment_ids = params.assignment_ids;
316
+ if (params.order_by !== void 0) opts.order_by = params.order_by;
317
+ if (params.override_assignment_dates !== void 0)
318
+ opts.override_assignment_dates = params.override_assignment_dates;
319
+ if (params.needs_grading_count_by_section !== void 0)
320
+ opts.needs_grading_count_by_section = params.needs_grading_count_by_section;
321
+ if (params.post_to_sis !== void 0) opts.post_to_sis = params.post_to_sis;
322
+ return canvas.assignments.list(params.course_id, opts);
262
323
  }
263
324
  },
264
325
  {
265
326
  name: "get_assignment",
266
- description: "Get details for a single assignment by ID.",
327
+ description: "Get details for a single assignment by ID. Use `include` to request submission, overrides, all_dates, score_statistics, and other optional fields.",
267
328
  inputSchema: {
268
329
  course_id: z3.number().describe("The Canvas course ID"),
269
- assignment_id: z3.number().describe("The Canvas assignment ID")
330
+ assignment_id: z3.number().describe("The Canvas assignment ID"),
331
+ include: z3.array(z3.enum(ASSIGNMENT_GET_INCLUDE)).optional().describe("Extra fields to include on the assignment (Canvas include[] param)"),
332
+ override_assignment_dates: z3.boolean().optional().describe("Apply assignment overrides to due/unlock/lock dates"),
333
+ needs_grading_count_by_section: z3.boolean().optional().describe("Break needs_grading_count down by section"),
334
+ all_dates: z3.boolean().optional().describe("Return all dates associated with this assignment")
270
335
  },
271
336
  annotations: {
272
337
  readOnlyHint: true,
273
338
  openWorldHint: true
274
339
  },
275
340
  handler: async (params) => {
276
- const course_id = params.course_id;
277
- const assignment_id = params.assignment_id;
278
- return canvas.assignments.get(course_id, assignment_id);
341
+ const opts = {};
342
+ if (params.include !== void 0)
343
+ opts.include = params.include;
344
+ if (params.override_assignment_dates !== void 0)
345
+ opts.override_assignment_dates = params.override_assignment_dates;
346
+ if (params.needs_grading_count_by_section !== void 0)
347
+ opts.needs_grading_count_by_section = params.needs_grading_count_by_section;
348
+ if (params.all_dates !== void 0) opts.all_dates = params.all_dates;
349
+ return canvas.assignments.get(
350
+ params.course_id,
351
+ params.assignment_id,
352
+ opts
353
+ );
279
354
  }
280
355
  },
281
356
  {
282
357
  name: "list_assignment_groups",
283
- description: "List assignment groups (categories like Homework, Exams) in a course.",
358
+ description: "List assignment groups (categories like Homework, Exams) in a course. Use `include=assignments` to nest assignments under each group; other includes add submission, overrides, score_statistics, etc.",
284
359
  inputSchema: {
285
- course_id: z3.number().describe("The Canvas course ID")
360
+ course_id: z3.number().describe("The Canvas course ID"),
361
+ include: z3.array(z3.enum(ASSIGNMENT_GROUP_INCLUDE)).optional().describe("Extra fields to include (Canvas include[] param)"),
362
+ assignment_ids: z3.array(z3.number()).optional().describe(
363
+ "When combined with include=assignments, restrict nested assignments to these IDs"
364
+ ),
365
+ exclude_assignment_submission_types: z3.array(z3.string()).optional().describe("Exclude assignments whose submission_types match any of these values"),
366
+ override_assignment_dates: z3.boolean().optional().describe("Apply assignment overrides to due/unlock/lock dates"),
367
+ grading_period_id: z3.number().int().optional().describe("Scope to a specific grading period"),
368
+ scope_assignments_to_student: z3.boolean().optional().describe("Limit assignments to what the current student can see")
286
369
  },
287
370
  annotations: {
288
371
  readOnlyHint: true,
289
372
  openWorldHint: true
290
373
  },
291
374
  handler: async (params) => {
292
- const course_id = params.course_id;
293
- return canvas.assignments.listGroups(course_id);
375
+ const opts = {};
376
+ if (params.include !== void 0)
377
+ opts.include = params.include;
378
+ if (params.assignment_ids !== void 0)
379
+ opts.assignment_ids = params.assignment_ids;
380
+ if (params.exclude_assignment_submission_types !== void 0)
381
+ opts.exclude_assignment_submission_types = params.exclude_assignment_submission_types;
382
+ if (params.override_assignment_dates !== void 0)
383
+ opts.override_assignment_dates = params.override_assignment_dates;
384
+ if (params.grading_period_id !== void 0)
385
+ opts.grading_period_id = params.grading_period_id;
386
+ if (params.scope_assignments_to_student !== void 0)
387
+ opts.scope_assignments_to_student = params.scope_assignments_to_student;
388
+ return canvas.assignments.listGroups(params.course_id, opts);
294
389
  }
295
390
  },
296
391
  {
@@ -500,36 +595,82 @@ function conversationTools(canvas) {
500
595
 
501
596
  // src/tools/courses.ts
502
597
  import { z as z6 } from "zod";
598
+ var COURSE_LIST_INCLUDE = [
599
+ "needs_grading_count",
600
+ "syllabus_body",
601
+ "public_description",
602
+ "total_scores",
603
+ "current_grading_period_scores",
604
+ "grading_periods",
605
+ "term",
606
+ "account",
607
+ "course_progress",
608
+ "sections",
609
+ "storage_quota_used_mb",
610
+ "total_students",
611
+ "passback_status",
612
+ "favorites",
613
+ "teachers",
614
+ "observed_users",
615
+ "tabs",
616
+ "course_image",
617
+ "banner_image",
618
+ "concluded",
619
+ "lti_context_id",
620
+ "post_manually"
621
+ ];
622
+ var COURSE_GET_INCLUDE = [...COURSE_LIST_INCLUDE, "all_courses", "permissions"];
623
+ var COURSE_WORKFLOW_STATE = ["unpublished", "available", "completed", "deleted"];
624
+ var COURSE_ENROLLMENT_STATE = ["active", "invited_or_pending", "completed"];
503
625
  function courseTools(canvas) {
504
626
  return [
505
627
  {
506
628
  name: "list_courses",
507
- description: "List courses for the authenticated user. Optionally filter by enrollment state.",
629
+ description: "List courses for the authenticated user. `include` adds optional fields (teachers, total_students, term, syllabus_body, etc.). `state[]` narrows by course workflow state; `enrollment_state` narrows by the caller\u2019s enrollment state.",
508
630
  inputSchema: {
509
- enrollment_state: z6.enum(["active", "completed", "all"]).optional().describe("Filter courses by enrollment state")
631
+ enrollment_state: z6.enum(COURSE_ENROLLMENT_STATE).optional().describe("Filter courses by the caller\u2019s enrollment state"),
632
+ state: z6.array(z6.enum(COURSE_WORKFLOW_STATE)).optional().describe("Filter by course workflow state"),
633
+ enrollment_role_id: z6.number().int().optional().describe("Filter by specific enrollment role ID"),
634
+ include: z6.array(z6.enum(COURSE_LIST_INCLUDE)).optional().describe("Extra fields to include on each course (Canvas include[] param)"),
635
+ exclude_blueprint_courses: z6.boolean().optional().describe("Exclude blueprint courses from the results")
510
636
  },
511
637
  annotations: {
512
638
  readOnlyHint: true,
513
639
  openWorldHint: true
514
640
  },
515
641
  handler: async (params) => {
516
- const enrollment_state = params.enrollment_state;
517
- return canvas.courses.list({ enrollment_state });
642
+ const opts = {};
643
+ if (params.enrollment_state !== void 0)
644
+ opts.enrollment_state = params.enrollment_state;
645
+ if (params.state !== void 0)
646
+ opts.state = params.state;
647
+ if (params.enrollment_role_id !== void 0)
648
+ opts.enrollment_role_id = params.enrollment_role_id;
649
+ if (params.include !== void 0)
650
+ opts.include = params.include;
651
+ if (params.exclude_blueprint_courses !== void 0)
652
+ opts.exclude_blueprint_courses = params.exclude_blueprint_courses;
653
+ return canvas.courses.list(opts);
518
654
  }
519
655
  },
520
656
  {
521
657
  name: "get_course",
522
- description: "Get details for a single course by ID, including term and total student count.",
658
+ description: "Get details for a single course. Defaults to requesting `term` and `total_students`. Pass `include` to replace the default set with custom Canvas include[] fields (teachers, permissions, syllabus_body, sections, etc.).",
523
659
  inputSchema: {
524
- course_id: z6.number().describe("The Canvas course ID")
660
+ course_id: z6.number().describe("The Canvas course ID"),
661
+ include: z6.array(z6.enum(COURSE_GET_INCLUDE)).optional().describe("Extra fields to include on the course (Canvas include[] param)"),
662
+ teacher_limit: z6.number().int().optional().describe("Limit on the number of teachers returned when include=teachers")
525
663
  },
526
664
  annotations: {
527
665
  readOnlyHint: true,
528
666
  openWorldHint: true
529
667
  },
530
668
  handler: async (params) => {
531
- const course_id = params.course_id;
532
- return canvas.courses.get(course_id);
669
+ const opts = {};
670
+ if (params.include !== void 0)
671
+ opts.include = params.include;
672
+ if (params.teacher_limit !== void 0) opts.teacher_limit = params.teacher_limit;
673
+ return canvas.courses.get(params.course_id, opts);
533
674
  }
534
675
  },
535
676
  {
@@ -795,18 +936,96 @@ function discussionTools(canvas) {
795
936
 
796
937
  // src/tools/enrollments.ts
797
938
  import { z as z8 } from "zod";
939
+ var ENROLLMENT_TYPE = [
940
+ "StudentEnrollment",
941
+ "TeacherEnrollment",
942
+ "TaEnrollment",
943
+ "DesignerEnrollment",
944
+ "ObserverEnrollment"
945
+ ];
946
+ var ENROLLMENT_STATE = [
947
+ "active",
948
+ "invited",
949
+ "creation_pending",
950
+ "deleted",
951
+ "rejected",
952
+ "completed",
953
+ "inactive",
954
+ "current_and_invited",
955
+ "current_and_future",
956
+ "current_and_concluded"
957
+ ];
958
+ var ENROLLMENT_INCLUDE = [
959
+ "avatar_url",
960
+ "group_ids",
961
+ "locked",
962
+ "observed_users",
963
+ "can_be_removed",
964
+ "uuid",
965
+ "current_points",
966
+ "grades"
967
+ ];
798
968
  function enrollmentTools(canvas) {
799
969
  return [
800
970
  {
801
971
  name: "list_enrollments",
802
- description: "List all enrollments for the authenticated user across courses.",
803
- inputSchema: {},
972
+ description: "List all enrollments for the authenticated user across courses. Optional filters and includes mirror Canvas `GET /users/self/enrollments`.",
973
+ inputSchema: {
974
+ type: z8.array(z8.enum(ENROLLMENT_TYPE)).optional().describe("Filter by one or more enrollment types"),
975
+ state: z8.array(z8.enum(ENROLLMENT_STATE)).optional().describe("Filter by one or more enrollment states"),
976
+ role: z8.array(z8.string()).optional().describe("Filter by enrollment role names (as defined in the Canvas account)"),
977
+ include: z8.array(z8.enum(ENROLLMENT_INCLUDE)).optional().describe("Extra fields to include on each enrollment (Canvas include[] param)"),
978
+ grading_period_id: z8.number().int().optional().describe("Return enrollments scoped to this grading period"),
979
+ enrollment_term_id: z8.number().int().optional().describe("Limit to enrollments in the given term")
980
+ },
804
981
  annotations: {
805
982
  readOnlyHint: true,
806
983
  openWorldHint: true
807
984
  },
808
- handler: async () => {
809
- return canvas.enrollments.list();
985
+ handler: async (params) => {
986
+ const opts = {};
987
+ if (params.type !== void 0) opts.type = params.type;
988
+ if (params.state !== void 0) opts.state = params.state;
989
+ if (params.role !== void 0) opts.role = params.role;
990
+ if (params.include !== void 0)
991
+ opts.include = params.include;
992
+ if (params.grading_period_id !== void 0)
993
+ opts.grading_period_id = params.grading_period_id;
994
+ if (params.enrollment_term_id !== void 0)
995
+ opts.enrollment_term_id = params.enrollment_term_id;
996
+ return canvas.enrollments.list(opts);
997
+ }
998
+ },
999
+ {
1000
+ name: "list_course_enrollments",
1001
+ description: "List enrollments within a specific course with Canvas filters. Use `include=grades` / `include=current_points` for richer grade data, `type[]` to limit to a role, and `user_id` to focus on a single user.",
1002
+ inputSchema: {
1003
+ course_id: z8.number().describe("The Canvas course ID"),
1004
+ type: z8.array(z8.enum(ENROLLMENT_TYPE)).optional().describe("Filter by one or more enrollment types"),
1005
+ state: z8.array(z8.enum(ENROLLMENT_STATE)).optional().describe("Filter by enrollment states"),
1006
+ role: z8.array(z8.string()).optional().describe("Filter by custom role names"),
1007
+ include: z8.array(z8.enum(ENROLLMENT_INCLUDE)).optional().describe("Extra fields to include (Canvas include[] param)"),
1008
+ user_id: z8.union([z8.number(), z8.string()]).optional().describe('Filter to a specific user (may be numeric ID or "self")'),
1009
+ grading_period_id: z8.number().int().optional().describe("Scope grade-related includes to this grading period"),
1010
+ enrollment_term_id: z8.number().int().optional().describe("Limit to enrollments in the given term")
1011
+ },
1012
+ annotations: {
1013
+ readOnlyHint: true,
1014
+ openWorldHint: true
1015
+ },
1016
+ handler: async (params) => {
1017
+ const opts = {};
1018
+ if (params.type !== void 0) opts.type = params.type;
1019
+ if (params.state !== void 0) opts.state = params.state;
1020
+ if (params.role !== void 0) opts.role = params.role;
1021
+ if (params.include !== void 0)
1022
+ opts.include = params.include;
1023
+ if (params.user_id !== void 0) opts.user_id = params.user_id;
1024
+ if (params.grading_period_id !== void 0)
1025
+ opts.grading_period_id = params.grading_period_id;
1026
+ if (params.enrollment_term_id !== void 0)
1027
+ opts.enrollment_term_id = params.enrollment_term_id;
1028
+ return canvas.enrollments.listForCourse(params.course_id, opts);
810
1029
  }
811
1030
  },
812
1031
  {
@@ -1918,42 +2137,96 @@ function studentTools(canvas) {
1918
2137
 
1919
2138
  // src/tools/submissions.ts
1920
2139
  import { z as z19 } from "zod";
2140
+ var SUBMISSION_LIST_INCLUDE = [
2141
+ "submission_history",
2142
+ "submission_comments",
2143
+ "rubric_assessment",
2144
+ "assignment",
2145
+ "visibility",
2146
+ "course",
2147
+ "user",
2148
+ "group",
2149
+ "read_status",
2150
+ "sub_assignment_submissions"
2151
+ ];
2152
+ var SUBMISSION_GET_INCLUDE = [
2153
+ "submission_history",
2154
+ "submission_comments",
2155
+ "rubric_assessment",
2156
+ "visibility",
2157
+ "course",
2158
+ "user",
2159
+ "read_status"
2160
+ ];
2161
+ var SUBMISSION_WORKFLOW_STATE = ["submitted", "unsubmitted", "graded", "pending_review"];
1921
2162
  function submissionTools(canvas) {
1922
2163
  return [
1923
2164
  {
1924
2165
  name: "list_submissions",
1925
- description: "List all submissions for an assignment in a course.",
2166
+ description: "List all submissions for an assignment. Use `include` to attach user, assignment, rubric_assessment, submission_history, or visibility. Filter with `student_ids`, `workflow_state`, or `grading_period_id`. Defaults to including submission_comments.",
1926
2167
  inputSchema: {
1927
2168
  course_id: z19.number().describe("The Canvas course ID"),
1928
- assignment_id: z19.number().describe("The Canvas assignment ID")
2169
+ assignment_id: z19.number().describe("The Canvas assignment ID"),
2170
+ include: z19.array(z19.enum(SUBMISSION_LIST_INCLUDE)).optional().describe(
2171
+ 'Extra fields to include (Canvas include[] param). Defaults to ["submission_comments"] when omitted.'
2172
+ ),
2173
+ student_ids: z19.array(z19.union([z19.number(), z19.string()])).optional().describe(
2174
+ 'Restrict to submissions for these user IDs. Use "all" or "self" for shortcuts.'
2175
+ ),
2176
+ section_ids: z19.array(z19.number()).optional().describe("Restrict to submissions in these sections"),
2177
+ grouped: z19.boolean().optional().describe("Return one submission per group rather than per student"),
2178
+ workflow_state: z19.enum(SUBMISSION_WORKFLOW_STATE).optional().describe("Only include submissions in this workflow state"),
2179
+ grading_period_id: z19.number().int().optional().describe("Restrict to a grading period")
1929
2180
  },
1930
2181
  annotations: {
1931
2182
  readOnlyHint: true,
1932
2183
  openWorldHint: true
1933
2184
  },
1934
2185
  handler: async (params) => {
1935
- const course_id = params.course_id;
1936
- const assignment_id = params.assignment_id;
1937
- return canvas.submissions.list(course_id, assignment_id);
2186
+ const opts = {};
2187
+ if (params.include !== void 0)
2188
+ opts.include = params.include;
2189
+ if (params.student_ids !== void 0)
2190
+ opts.student_ids = params.student_ids;
2191
+ if (params.section_ids !== void 0)
2192
+ opts.section_ids = params.section_ids;
2193
+ if (params.grouped !== void 0) opts.grouped = params.grouped;
2194
+ if (params.workflow_state !== void 0)
2195
+ opts.workflow_state = params.workflow_state;
2196
+ if (params.grading_period_id !== void 0)
2197
+ opts.grading_period_id = params.grading_period_id;
2198
+ return canvas.submissions.list(
2199
+ params.course_id,
2200
+ params.assignment_id,
2201
+ opts
2202
+ );
1938
2203
  }
1939
2204
  },
1940
2205
  {
1941
2206
  name: "get_submission",
1942
- description: "Get a single submission for a specific user on an assignment, including comments.",
2207
+ description: "Get a single submission for a specific user on an assignment. Defaults to including submission_comments. Pass `include` to add rubric_assessment, submission_history, visibility, course, user, or read_status.",
1943
2208
  inputSchema: {
1944
2209
  course_id: z19.number().describe("The Canvas course ID"),
1945
2210
  assignment_id: z19.number().describe("The Canvas assignment ID"),
1946
- user_id: z19.number().describe("The Canvas user ID")
2211
+ user_id: z19.number().describe("The Canvas user ID"),
2212
+ include: z19.array(z19.enum(SUBMISSION_GET_INCLUDE)).optional().describe(
2213
+ 'Extra fields to include (Canvas include[] param). Defaults to ["submission_comments"] when omitted.'
2214
+ )
1947
2215
  },
1948
2216
  annotations: {
1949
2217
  readOnlyHint: true,
1950
2218
  openWorldHint: true
1951
2219
  },
1952
2220
  handler: async (params) => {
1953
- const course_id = params.course_id;
1954
- const assignment_id = params.assignment_id;
1955
- const user_id = params.user_id;
1956
- return canvas.submissions.get(course_id, assignment_id, user_id);
2221
+ const opts = {};
2222
+ if (params.include !== void 0)
2223
+ opts.include = params.include;
2224
+ return canvas.submissions.get(
2225
+ params.course_id,
2226
+ params.assignment_id,
2227
+ params.user_id,
2228
+ opts
2229
+ );
1957
2230
  }
1958
2231
  },
1959
2232
  {
@@ -2004,6 +2277,27 @@ function submissionTools(canvas) {
2004
2277
 
2005
2278
  // src/tools/users.ts
2006
2279
  import { z as z20 } from "zod";
2280
+ var COURSE_USER_ENROLLMENT_TYPE = ["student", "teacher", "ta", "observer", "designer"];
2281
+ var COURSE_USER_ENROLLMENT_STATE = [
2282
+ "active",
2283
+ "invited",
2284
+ "rejected",
2285
+ "completed",
2286
+ "inactive"
2287
+ ];
2288
+ var COURSE_USER_INCLUDE = [
2289
+ "email",
2290
+ "enrollments",
2291
+ "locked",
2292
+ "avatar_url",
2293
+ "test_student",
2294
+ "bio",
2295
+ "custom_links",
2296
+ "current_grading_period_scores",
2297
+ "uuid"
2298
+ ];
2299
+ var USER_SORT = ["username", "email", "sis_id", "integration_id", "last_login"];
2300
+ var SEARCH_USER_INCLUDE = ["email", "last_login", "avatar_url", "time_zone", "uuid"];
2007
2301
  function userTools(canvas) {
2008
2302
  return [
2009
2303
  {
@@ -2050,42 +2344,65 @@ function userTools(canvas) {
2050
2344
  },
2051
2345
  {
2052
2346
  name: "search_users",
2053
- description: "Search for users in a Canvas account by name, login, or email.",
2347
+ description: "Search for users in a Canvas account by name, login, or email. Use `include` to request email, last_login, avatar_url, time_zone, or uuid in the response.",
2054
2348
  inputSchema: {
2055
2349
  account_id: z20.number().describe("The Canvas account ID"),
2056
2350
  search_term: z20.string().describe("The search term (name, login, or email)"),
2057
- sort: z20.enum(["username", "email", "sis_id", "last_login"]).optional().describe("Sort field"),
2058
- order: z20.enum(["asc", "desc"]).optional().describe("Sort order")
2351
+ sort: z20.enum(USER_SORT).optional().describe("Sort field"),
2352
+ order: z20.enum(["asc", "desc"]).optional().describe("Sort order"),
2353
+ include: z20.array(z20.enum(SEARCH_USER_INCLUDE)).optional().describe("Extra fields to include on each user (Canvas include[] param)")
2059
2354
  },
2060
2355
  annotations: {
2061
2356
  readOnlyHint: true,
2062
2357
  openWorldHint: true
2063
2358
  },
2064
2359
  handler: async (params) => {
2360
+ const opts = {};
2361
+ if (params.sort !== void 0) opts.sort = params.sort;
2362
+ if (params.order !== void 0) opts.order = params.order;
2363
+ if (params.include !== void 0)
2364
+ opts.include = params.include;
2065
2365
  return canvas.users.searchUsers(
2066
2366
  params.account_id,
2067
2367
  params.search_term,
2068
- params.sort,
2069
- params.order
2368
+ opts
2070
2369
  );
2071
2370
  }
2072
2371
  },
2073
2372
  {
2074
2373
  name: "list_course_users",
2075
- description: "List all users in a course, optionally filtered by enrollment type.",
2374
+ description: "List users in a course with optional Canvas filters. Use `include` to request email, enrollments, avatar_url, bio, and other fields otherwise omitted from the default response. Use `enrollment_type` / `enrollment_state` to narrow by role or status, `search_term` to filter by name/login, `user_ids` to fetch a specific subset, and `sort`/`order` to control ordering.",
2076
2375
  inputSchema: {
2077
2376
  course_id: z20.number().describe("The Canvas course ID"),
2078
- enrollment_type: z20.enum(["student", "teacher", "ta", "observer", "designer"]).optional().describe("Filter by enrollment type")
2377
+ enrollment_type: z20.array(z20.enum(COURSE_USER_ENROLLMENT_TYPE)).optional().describe("Filter by one or more enrollment types"),
2378
+ enrollment_state: z20.array(z20.enum(COURSE_USER_ENROLLMENT_STATE)).optional().describe("Filter by enrollment state (e.g. active, invited)"),
2379
+ enrollment_role_id: z20.number().int().optional().describe("Filter by a specific enrollment role ID (overrides enrollment_type)"),
2380
+ include: z20.array(z20.enum(COURSE_USER_INCLUDE)).optional().describe("Extra fields to include on each user (Canvas include[] param)"),
2381
+ user_ids: z20.array(z20.union([z20.number(), z20.string()])).optional().describe("Restrict the result to the given user IDs"),
2382
+ search_term: z20.string().optional().describe("Partial name or full login/SIS ID to filter users by"),
2383
+ sort: z20.enum(USER_SORT).optional().describe("Sort field"),
2384
+ order: z20.enum(["asc", "desc"]).optional().describe("Sort order")
2079
2385
  },
2080
2386
  annotations: {
2081
2387
  readOnlyHint: true,
2082
2388
  openWorldHint: true
2083
2389
  },
2084
2390
  handler: async (params) => {
2085
- return canvas.users.listCourseUsers(
2086
- params.course_id,
2087
- params.enrollment_type
2088
- );
2391
+ const opts = {};
2392
+ if (params.enrollment_type !== void 0)
2393
+ opts.enrollment_type = params.enrollment_type;
2394
+ if (params.enrollment_state !== void 0)
2395
+ opts.enrollment_state = params.enrollment_state;
2396
+ if (params.enrollment_role_id !== void 0)
2397
+ opts.enrollment_role_id = params.enrollment_role_id;
2398
+ if (params.include !== void 0)
2399
+ opts.include = params.include;
2400
+ if (params.user_ids !== void 0)
2401
+ opts.user_ids = params.user_ids;
2402
+ if (params.search_term !== void 0) opts.search_term = params.search_term;
2403
+ if (params.sort !== void 0) opts.sort = params.sort;
2404
+ if (params.order !== void 0) opts.order = params.order;
2405
+ return canvas.users.listCourseUsers(params.course_id, opts);
2089
2406
  }
2090
2407
  }
2091
2408
  ];
@@ -2352,4 +2669,4 @@ function createCanvasMCPServer(config) {
2352
2669
  export {
2353
2670
  createCanvasMCPServer
2354
2671
  };
2355
- //# sourceMappingURL=chunk-FNBRFPKK.js.map
2672
+ //# sourceMappingURL=chunk-2ZN5FAAL.js.map