canvas-lms-mcp 1.8.0 → 1.8.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/canvas/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,SAAS,CAAA;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAuB,MAAM,SAAS,CAAA;AAEtE,qBAAa,cAAe,SAAQ,KAAK;IACvC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;gBAEJ,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAM9D;AAKD,MAAM,WAAW,oBAAqB,SAAQ,WAAW;IACvD;;;;OAIG;IACH,KAAK,CAAC,EAAE,iBAAiB,CAAA;CAC1B;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,kBAAkB,CAAQ;gBAEtB,MAAM,EAAE,kBAAkB;IAMtC,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED;;;;OAIG;IACG,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,CAAC,CAAC;IA8C5E,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAoCvE,gBAAgB,CAAC,CAAC,EACtB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,iBAAiB,GACzB,OAAO,CAAC,CAAC,EAAE,CAAC;IAqCf,OAAO,CAAC,aAAa;CAKtB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/canvas/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,SAAS,CAAA;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAuB,MAAM,SAAS,CAAA;AAEtE,qBAAa,cAAe,SAAQ,KAAK;IACvC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;gBAEJ,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAM9D;AAKD,MAAM,WAAW,oBAAqB,SAAQ,WAAW;IACvD;;;;OAIG;IACH,KAAK,CAAC,EAAE,iBAAiB,CAAA;CAC1B;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,kBAAkB,CAAQ;gBAEtB,MAAM,EAAE,kBAAkB;IAMtC,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED;;;;OAIG;IACG,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,CAAC,CAAC;IA8C5E,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAoCvE,gBAAgB,CAAC,CAAC,EACtB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,iBAAiB,GACzB,OAAO,CAAC,CAAC,EAAE,CAAC;IAqCf,OAAO,CAAC,aAAa;CAKtB"}
@@ -5,7 +5,7 @@
5
5
 
6
6
 
7
7
 
8
- var _chunkLEUI5FLWcjs = require('../chunk-LEUI5FLW.cjs');
8
+ var _chunkFMOGHWSXcjs = require('../chunk-FMOGHWSX.cjs');
9
9
 
10
10
 
11
11
 
@@ -13,5 +13,5 @@ var _chunkLEUI5FLWcjs = require('../chunk-LEUI5FLW.cjs');
13
13
 
14
14
 
15
15
 
16
- exports.CanvasApiError = _chunkLEUI5FLWcjs.CanvasApiError; exports.CanvasClient = _chunkLEUI5FLWcjs.CanvasClient; exports.CanvasHttpClient = _chunkLEUI5FLWcjs.CanvasHttpClient; exports.GeneratedUsersModule = _chunkLEUI5FLWcjs.GeneratedUsersModule; exports.appendCanvasQuery = _chunkLEUI5FLWcjs.appendCanvasQuery; exports.toCanvasQuery = _chunkLEUI5FLWcjs.toCanvasQuery;
16
+ exports.CanvasApiError = _chunkFMOGHWSXcjs.CanvasApiError; exports.CanvasClient = _chunkFMOGHWSXcjs.CanvasClient; exports.CanvasHttpClient = _chunkFMOGHWSXcjs.CanvasHttpClient; exports.GeneratedUsersModule = _chunkFMOGHWSXcjs.GeneratedUsersModule; exports.appendCanvasQuery = _chunkFMOGHWSXcjs.appendCanvasQuery; exports.toCanvasQuery = _chunkFMOGHWSXcjs.toCanvasQuery;
17
17
  //# sourceMappingURL=index.cjs.map
@@ -5,7 +5,7 @@ import {
5
5
  GeneratedUsersModule,
6
6
  appendCanvasQuery,
7
7
  toCanvasQuery
8
- } from "../chunk-UODLH4L6.js";
8
+ } from "../chunk-NGP4KCMC.js";
9
9
  export {
10
10
  CanvasApiError,
11
11
  CanvasClient,
@@ -8,7 +8,8 @@
8
8
 
9
9
 
10
10
 
11
- var _chunkLEUI5FLWcjs = require('./chunk-LEUI5FLW.cjs');
11
+
12
+ var _chunkFMOGHWSXcjs = require('./chunk-FMOGHWSX.cjs');
12
13
 
13
14
  // src/server.ts
14
15
  var _mcpjs = require('@modelcontextprotocol/sdk/server/mcp.js');
@@ -113,7 +114,7 @@ function accountTools(canvas) {
113
114
 
114
115
  // src/tools/errors.ts
115
116
  function formatError(error) {
116
- if (error instanceof _chunkLEUI5FLWcjs.CanvasApiError) {
117
+ if (error instanceof _chunkFMOGHWSXcjs.CanvasApiError) {
117
118
  const status = error.status;
118
119
  const message = error.message;
119
120
  switch (status) {
@@ -157,7 +158,7 @@ function analyticsTools(canvas) {
157
158
  inputSchema: {
158
159
  course_id: _zod.z.number().describe("The Canvas course ID"),
159
160
  search_term: _zod.z.string().describe("The keyword or phrase to search for"),
160
- content_types: _zod.z.array(_zod.z.enum(_chunkLEUI5FLWcjs.SEARCH_CONTENT_TYPES)).optional().describe(
161
+ content_types: _zod.z.array(_zod.z.enum(_chunkFMOGHWSXcjs.SEARCH_CONTENT_TYPES)).optional().describe(
161
162
  "Content types to search. Defaults to all types: pages, discussions, assignments, announcements."
162
163
  )
163
164
  },
@@ -169,7 +170,7 @@ function analyticsTools(canvas) {
169
170
  const courseId = params.course_id;
170
171
  const searchTerm = params.search_term;
171
172
  const types = _nullishCoalesce(params.content_types, () => ( [
172
- ..._chunkLEUI5FLWcjs.SEARCH_CONTENT_TYPES
173
+ ..._chunkFMOGHWSXcjs.SEARCH_CONTENT_TYPES
173
174
  ]));
174
175
  if (types.length === 0) return { results: [] };
175
176
  const settled = await Promise.allSettled(
@@ -1459,7 +1460,7 @@ function outcomeTools(canvas) {
1459
1460
  name: "get_root_outcome_group",
1460
1461
  description: "Get the root outcome group for an account or course context.",
1461
1462
  inputSchema: {
1462
- context_type: _zod.z.enum(_chunkLEUI5FLWcjs.OUTCOME_CONTEXT_TYPES).describe("Whether to read outcomes from an account or course context."),
1463
+ context_type: _zod.z.enum(_chunkFMOGHWSXcjs.OUTCOME_CONTEXT_TYPES).describe("Whether to read outcomes from an account or course context."),
1463
1464
  context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context.")
1464
1465
  },
1465
1466
  annotations: { readOnlyHint: true, openWorldHint: true },
@@ -1472,7 +1473,7 @@ function outcomeTools(canvas) {
1472
1473
  name: "list_outcome_groups",
1473
1474
  description: "List all outcome groups for an account or course context.",
1474
1475
  inputSchema: {
1475
- context_type: _zod.z.enum(_chunkLEUI5FLWcjs.OUTCOME_CONTEXT_TYPES).describe("Whether to read outcome groups from an account or course context."),
1476
+ context_type: _zod.z.enum(_chunkFMOGHWSXcjs.OUTCOME_CONTEXT_TYPES).describe("Whether to read outcome groups from an account or course context."),
1476
1477
  context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context.")
1477
1478
  },
1478
1479
  annotations: { readOnlyHint: true, openWorldHint: true },
@@ -1485,10 +1486,10 @@ function outcomeTools(canvas) {
1485
1486
  name: "list_outcome_group_links",
1486
1487
  description: "List all outcome links in an account or course context.",
1487
1488
  inputSchema: {
1488
- context_type: _zod.z.enum(_chunkLEUI5FLWcjs.OUTCOME_CONTEXT_TYPES).describe("Whether to read outcome links from an account or course context."),
1489
+ context_type: _zod.z.enum(_chunkFMOGHWSXcjs.OUTCOME_CONTEXT_TYPES).describe("Whether to read outcome links from an account or course context."),
1489
1490
  context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context."),
1490
- outcome_style: _zod.z.enum(_chunkLEUI5FLWcjs.OUTCOME_DETAIL_LEVELS).optional().describe('Outcome detail level. Use "full" to include expanded outcome fields.'),
1491
- outcome_group_style: _zod.z.enum(_chunkLEUI5FLWcjs.OUTCOME_DETAIL_LEVELS).optional().describe(
1491
+ outcome_style: _zod.z.enum(_chunkFMOGHWSXcjs.OUTCOME_DETAIL_LEVELS).optional().describe('Outcome detail level. Use "full" to include expanded outcome fields.'),
1492
+ outcome_group_style: _zod.z.enum(_chunkFMOGHWSXcjs.OUTCOME_DETAIL_LEVELS).optional().describe(
1492
1493
  'Outcome group detail level. Use "full" to include expanded outcome group fields.'
1493
1494
  )
1494
1495
  },
@@ -1506,7 +1507,7 @@ function outcomeTools(canvas) {
1506
1507
  name: "get_outcome_group",
1507
1508
  description: "Get details for a specific outcome group in an account or course context.",
1508
1509
  inputSchema: {
1509
- context_type: _zod.z.enum(_chunkLEUI5FLWcjs.OUTCOME_CONTEXT_TYPES).describe("The outcome group context type."),
1510
+ context_type: _zod.z.enum(_chunkFMOGHWSXcjs.OUTCOME_CONTEXT_TYPES).describe("The outcome group context type."),
1510
1511
  context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context."),
1511
1512
  outcome_group_id: _zod.z.number().describe("The Canvas outcome group ID.")
1512
1513
  },
@@ -1521,10 +1522,10 @@ function outcomeTools(canvas) {
1521
1522
  name: "list_outcome_group_outcomes",
1522
1523
  description: "List the linked outcomes directly under a specific outcome group.",
1523
1524
  inputSchema: {
1524
- context_type: _zod.z.enum(_chunkLEUI5FLWcjs.OUTCOME_CONTEXT_TYPES).describe("The outcome group context type."),
1525
+ context_type: _zod.z.enum(_chunkFMOGHWSXcjs.OUTCOME_CONTEXT_TYPES).describe("The outcome group context type."),
1525
1526
  context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context."),
1526
1527
  outcome_group_id: _zod.z.number().describe("The Canvas outcome group ID."),
1527
- outcome_style: _zod.z.enum(_chunkLEUI5FLWcjs.OUTCOME_DETAIL_LEVELS).optional().describe('Outcome detail level. Use "full" to include expanded outcome fields.')
1528
+ outcome_style: _zod.z.enum(_chunkFMOGHWSXcjs.OUTCOME_DETAIL_LEVELS).optional().describe('Outcome detail level. Use "full" to include expanded outcome fields.')
1528
1529
  },
1529
1530
  annotations: { readOnlyHint: true, openWorldHint: true },
1530
1531
  handler: async (params) => canvas.outcomes.listGroupOutcomes(
@@ -1540,7 +1541,7 @@ function outcomeTools(canvas) {
1540
1541
  name: "list_outcome_group_subgroups",
1541
1542
  description: "List the immediate child outcome groups under a specific outcome group.",
1542
1543
  inputSchema: {
1543
- context_type: _zod.z.enum(_chunkLEUI5FLWcjs.OUTCOME_CONTEXT_TYPES).describe("The outcome group context type."),
1544
+ context_type: _zod.z.enum(_chunkFMOGHWSXcjs.OUTCOME_CONTEXT_TYPES).describe("The outcome group context type."),
1544
1545
  context_id: _zod.z.number().describe("The Canvas account ID or course ID for the context."),
1545
1546
  outcome_group_id: _zod.z.number().describe("The Canvas outcome group ID.")
1546
1547
  },
@@ -1601,14 +1602,14 @@ function outcomeTools(canvas) {
1601
1602
  inputSchema: {
1602
1603
  course_id: _zod.z.number().describe("The Canvas course ID."),
1603
1604
  aggregate: _zod.z.enum(["course"]).optional().describe("Aggregate all student rollups into a single course-level rollup."),
1604
- aggregate_stat: _zod.z.enum(_chunkLEUI5FLWcjs.OUTCOME_ROLLUP_AGGREGATE_STATS).optional().describe('Statistic to use when aggregate="course".'),
1605
+ aggregate_stat: _zod.z.enum(_chunkFMOGHWSXcjs.OUTCOME_ROLLUP_AGGREGATE_STATS).optional().describe('Statistic to use when aggregate="course".'),
1605
1606
  user_ids: _zod.z.array(_zod.z.union([_zod.z.number(), _zod.z.string()])).optional().describe('Optional Canvas user IDs or SIS user IDs prefixed with "sis_user_id:".'),
1606
1607
  outcome_ids: _zod.z.array(_zod.z.number()).optional().describe("Optional outcome IDs to restrict the rollups."),
1607
1608
  include_courses: _zod.z.boolean().optional().describe("Include linked course details in the response payload."),
1608
- exclude: _zod.z.array(_zod.z.enum(_chunkLEUI5FLWcjs.OUTCOME_EXCLUDE_OPTIONS)).optional().describe("Optional rollup exclusions for missing users or missing outcome results."),
1609
- sort_by: _zod.z.enum(_chunkLEUI5FLWcjs.OUTCOME_ROLLUP_SORT_BY).optional().describe("Sort rollups by student name or by a specific outcome score."),
1609
+ exclude: _zod.z.array(_zod.z.enum(_chunkFMOGHWSXcjs.OUTCOME_EXCLUDE_OPTIONS)).optional().describe("Optional rollup exclusions for missing users or missing outcome results."),
1610
+ sort_by: _zod.z.enum(_chunkFMOGHWSXcjs.OUTCOME_ROLLUP_SORT_BY).optional().describe("Sort rollups by student name or by a specific outcome score."),
1610
1611
  sort_outcome_id: _zod.z.number().optional().describe('Outcome ID to sort by when sort_by="outcome".'),
1611
- sort_order: _zod.z.enum(_chunkLEUI5FLWcjs.OUTCOME_SORT_ORDER).optional().describe("Sort order to apply when sorting rollups."),
1612
+ sort_order: _zod.z.enum(_chunkFMOGHWSXcjs.OUTCOME_SORT_ORDER).optional().describe("Sort order to apply when sorting rollups."),
1612
1613
  add_defaults: _zod.z.boolean().optional().describe("Include default mastery colors and levels when Canvas supports it.")
1613
1614
  },
1614
1615
  annotations: { readOnlyHint: true, openWorldHint: true },
@@ -1651,7 +1652,7 @@ function outcomeTools(canvas) {
1651
1652
  description: "Get mastery distribution analytics for outcomes in a course, optionally filtered by students or outcomes.",
1652
1653
  inputSchema: {
1653
1654
  course_id: _zod.z.number().describe("The Canvas course ID."),
1654
- exclude: _zod.z.array(_zod.z.enum(_chunkLEUI5FLWcjs.OUTCOME_EXCLUDE_OPTIONS)).optional().describe("Optional exclusions for missing users or missing outcome results."),
1655
+ exclude: _zod.z.array(_zod.z.enum(_chunkFMOGHWSXcjs.OUTCOME_EXCLUDE_OPTIONS)).optional().describe("Optional exclusions for missing users or missing outcome results."),
1655
1656
  outcome_ids: _zod.z.array(_zod.z.number()).optional().describe("Optional outcome IDs to restrict the distribution results."),
1656
1657
  student_ids: _zod.z.array(_zod.z.union([_zod.z.number(), _zod.z.string()])).optional().describe('Optional Canvas student IDs or SIS user IDs prefixed with "sis_user_id:".'),
1657
1658
  include_alignment_distributions: _zod.z.boolean().optional().describe("Include contributing score distributions for alignments."),
@@ -2537,7 +2538,7 @@ function registerAllTools(server, canvas) {
2537
2538
  content: [{ type: "text", text }]
2538
2539
  };
2539
2540
  } catch (error) {
2540
- if (error instanceof _chunkLEUI5FLWcjs.CanvasApiError) {
2541
+ if (error instanceof _chunkFMOGHWSXcjs.CanvasApiError) {
2541
2542
  } else {
2542
2543
  console.error(`Unexpected error in tool "${tool.name}":`, error);
2543
2544
  }
@@ -2585,7 +2586,7 @@ function registerSyllabusResource(server, canvas) {
2585
2586
  ]
2586
2587
  };
2587
2588
  } catch (error) {
2588
- if (!(error instanceof _chunkLEUI5FLWcjs.CanvasApiError)) {
2589
+ if (!(error instanceof _chunkFMOGHWSXcjs.CanvasApiError)) {
2589
2590
  console.error("Unexpected error in syllabus resource:", error);
2590
2591
  }
2591
2592
  return {
@@ -2634,7 +2635,7 @@ function registerAssignmentDescriptionResource(server, canvas) {
2634
2635
  ]
2635
2636
  };
2636
2637
  } catch (error) {
2637
- if (!(error instanceof _chunkLEUI5FLWcjs.CanvasApiError)) {
2638
+ if (!(error instanceof _chunkFMOGHWSXcjs.CanvasApiError)) {
2638
2639
  console.error("Unexpected error in assignment-description resource:", error);
2639
2640
  }
2640
2641
  return {
@@ -2653,13 +2654,13 @@ function registerAllResources(server, canvas) {
2653
2654
 
2654
2655
  // src/server.ts
2655
2656
  function createCanvasMCPServer(config) {
2656
- const canvas = new (0, _chunkLEUI5FLWcjs.CanvasClient)({
2657
+ const canvas = new (0, _chunkFMOGHWSXcjs.CanvasClient)({
2657
2658
  token: config.token,
2658
2659
  baseUrl: config.baseUrl
2659
2660
  });
2660
2661
  const server = new (0, _mcpjs.McpServer)({
2661
2662
  name: "canvas-lms-mcp",
2662
- version: "1.0.0"
2663
+ version: _chunkFMOGHWSXcjs.version
2663
2664
  });
2664
2665
  registerAllTools(server, canvas);
2665
2666
  registerAllResources(server, canvas);
@@ -2669,4 +2670,4 @@ function createCanvasMCPServer(config) {
2669
2670
 
2670
2671
 
2671
2672
  exports.createCanvasMCPServer = createCanvasMCPServer;
2672
- //# sourceMappingURL=chunk-J4ENRNED.cjs.map
2673
+ //# sourceMappingURL=chunk-3XVL5F3L.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/canvas-lms-mcp/canvas-lms-mcp/dist/chunk-3XVL5F3L.cjs","../src/server.ts","../src/tools/accounts.ts","../src/tools/analytics.ts","../src/tools/errors.ts","../src/tools/assignments.ts","../src/tools/calendar.ts","../src/tools/conversations.ts","../src/tools/courses.ts","../src/tools/dashboard.ts","../src/tools/discussions.ts","../src/tools/enrollments.ts","../src/tools/files.ts","../src/tools/gradebook-history.ts","../src/tools/groups.ts","../src/tools/health.ts","../src/tools/modules.ts","../src/tools/outcomes.ts","../src/tools/pages.ts","../src/tools/peer-reviews.ts","../src/tools/quizzes.ts","../src/tools/rubrics.ts","../src/tools/student.ts","../src/tools/submissions.ts","../src/tools/users.ts","../src/tools/catalog.ts","../src/tools/index.ts","../src/resources/syllabus.ts","../src/resources/assignment-description.ts","../src/resources/index.ts"],"names":["z","ResourceTemplate"],"mappings":"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","file":"/home/runner/work/canvas-lms-mcp/canvas-lms-mcp/dist/chunk-3XVL5F3L.cjs","sourcesContent":[null,"import { version } from '../package.json'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { CanvasClient } from './canvas'\nimport { registerAllTools } from './tools'\nimport { registerAllResources } from './resources'\n\nexport interface CanvasMCPServerConfig {\n token: string\n baseUrl: string\n}\n\nexport interface CanvasMCPServer {\n server: McpServer\n canvas: CanvasClient\n}\n\nexport function createCanvasMCPServer(config: CanvasMCPServerConfig): CanvasMCPServer {\n const canvas = new CanvasClient({\n token: config.token,\n baseUrl: config.baseUrl,\n })\n\n const server = new McpServer({\n name: 'canvas-lms-mcp',\n version,\n })\n\n registerAllTools(server, canvas)\n registerAllResources(server, canvas)\n\n return { server, canvas }\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function accountTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'get_account',\n description: 'Get details for a Canvas account by ID.',\n inputSchema: {\n account_id: z.number().describe('The Canvas account ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n return canvas.accounts.get(params.account_id as number)\n },\n },\n {\n name: 'list_accounts',\n description: 'List all accounts accessible to the authenticated user.',\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n return canvas.accounts.list()\n },\n },\n {\n name: 'list_sub_accounts',\n description: 'List sub-accounts under a given Canvas account.',\n inputSchema: {\n account_id: z.number().describe('The parent Canvas account ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n return canvas.accounts.listSubAccounts(params.account_id as number)\n },\n },\n {\n name: 'list_account_courses',\n description: 'List courses under a given Canvas account.',\n inputSchema: {\n account_id: z.number().describe('The Canvas account ID'),\n search_term: z.string().optional().describe('Search courses by name or course code'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n return canvas.accounts.listCourses(params.account_id as number, {\n search_term: params.search_term as string | undefined,\n })\n },\n },\n {\n name: 'list_account_users',\n description: 'List users in a Canvas account.',\n inputSchema: {\n account_id: z.number().describe('The Canvas account ID'),\n search_term: z.string().optional().describe('Search users by name, email, or login'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n return canvas.accounts.listUsers(params.account_id as number, {\n search_term: params.search_term as string | undefined,\n })\n },\n },\n {\n name: 'get_account_reports',\n description: 'List available report types for a Canvas account.',\n inputSchema: {\n account_id: z.number().describe('The Canvas account ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n return canvas.accounts.getReports(params.account_id as number)\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\nimport { formatError } from './errors'\nimport { SEARCH_CONTENT_TYPES } from '../canvas/analytics'\nimport type { SearchContentType } from '../canvas/analytics'\nimport type { CourseSearchResult } from '../canvas/types'\n\nexport function analyticsTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'search_course_content',\n description:\n 'Search for content within a course. Searches pages, assignments, discussions, and announcements by keyword.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n search_term: z.string().describe('The keyword or phrase to search for'),\n content_types: z\n .array(z.enum(SEARCH_CONTENT_TYPES))\n .optional()\n .describe(\n 'Content types to search. Defaults to all types: pages, discussions, assignments, announcements.',\n ),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const courseId = params.course_id as number\n const searchTerm = params.search_term as string\n const types = (params.content_types as SearchContentType[] | undefined) ?? [\n ...SEARCH_CONTENT_TYPES,\n ]\n\n if (types.length === 0) return { results: [] }\n\n const settled = await Promise.allSettled(\n types.map((type) => canvas.analytics.searchContentType(courseId, searchTerm, type)),\n )\n\n const fulfilled = settled.filter(\n (r): r is PromiseFulfilledResult<CourseSearchResult[]> => r.status === 'fulfilled',\n )\n\n if (fulfilled.length === 0) {\n const allErrors = settled\n .map((result, index) =>\n result.status === 'rejected'\n ? `${types[index]}: ${formatError(result.reason)}`\n : null,\n )\n .filter((errorLine): errorLine is string => errorLine !== null)\n throw new Error(`All content type searches failed:\\n${allErrors.join('\\n')}`)\n }\n\n const results = fulfilled.flatMap((r) => r.value)\n const warnings = settled\n .map((r, i) =>\n r.status === 'rejected' ? `${types[i]} search failed: ${formatError(r.reason)}` : null,\n )\n .filter((w): w is string => w !== null)\n\n return warnings.length > 0 ? { results, warnings } : { results }\n },\n },\n {\n name: 'get_course_analytics',\n description:\n 'Get course-level activity analytics. Returns daily page view and participation counts.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.analytics.getCourseActivity(course_id)\n },\n },\n {\n name: 'get_student_analytics',\n description:\n 'Get per-student activity analytics for a course. Returns page views, participations, and submission timeline for a specific student.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n student_id: z.number().describe('The Canvas user ID of the student'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const student_id = params.student_id as number\n return canvas.analytics.getStudentActivity(course_id, student_id)\n },\n },\n {\n name: 'get_course_activity_stream',\n description:\n 'Get a summary of recent activity in a course. Returns counts of recent events grouped by type (submissions, discussions, announcements, etc.).',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.analytics.getCourseActivityStream(course_id)\n },\n },\n ]\n}\n","import { CanvasApiError } from '../canvas/client'\n\nexport function formatError(error: unknown): string {\n if (error instanceof CanvasApiError) {\n const status = error.status\n const message = error.message\n switch (status) {\n case 401:\n return 'Canvas token is invalid or expired'\n case 403:\n return \"You don't have permission to perform this action in this course\"\n case 404:\n return 'Course/assignment/submission not found — check the ID'\n case 422:\n return `Invalid data sent to Canvas: ${message}`\n case 429:\n return 'Canvas API rate limit exceeded — wait a moment and retry'\n case 500:\n case 502:\n case 503:\n return `Canvas server error (${status}) — try again later`\n default:\n return `Canvas API error (${status}): ${message}`\n }\n }\n if (error instanceof Error) {\n if (isNetworkError(error)) {\n return 'Failed to connect to Canvas — check your base URL'\n }\n return error.message\n }\n return 'An unexpected error occurred'\n}\n\nfunction isNetworkError(error: Error): boolean {\n const msg = error.message.toLowerCase()\n return (\n msg.includes('fetch') ||\n msg.includes('enotfound') ||\n msg.includes('econnrefused') ||\n msg.includes('econnreset') ||\n msg.includes('etimedout') ||\n msg.includes('network') ||\n msg.includes('dns') ||\n msg.includes('socket') ||\n error.name === 'TypeError'\n )\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type {\n AssignmentBucket,\n AssignmentGetInclude,\n AssignmentGroupInclude,\n AssignmentListInclude,\n AssignmentOrderBy,\n GetAssignmentOptions,\n ListAssignmentGroupsOptions,\n ListAssignmentsOptions,\n} from '../canvas/assignments'\nimport type { ToolDefinition } from './types'\n\nconst ASSIGNMENT_LIST_INCLUDE = [\n 'submission',\n 'assignment_visibility',\n 'all_dates',\n 'overrides',\n 'observed_users',\n 'can_edit',\n 'score_statistics',\n] as const\n\nconst ASSIGNMENT_GET_INCLUDE = [\n 'submission',\n 'assignment_visibility',\n 'overrides',\n 'observed_users',\n 'can_edit',\n 'score_statistics',\n 'all_dates',\n] as const\n\nconst ASSIGNMENT_BUCKET = [\n 'past',\n 'overdue',\n 'undated',\n 'ungraded',\n 'unsubmitted',\n 'upcoming',\n 'future',\n] as const\n\nconst ASSIGNMENT_ORDER_BY = ['position', 'name', 'due_at'] as const\n\nconst ASSIGNMENT_GROUP_INCLUDE = [\n 'assignments',\n 'discussion_topic',\n 'all_dates',\n 'assignment_visibility',\n 'overrides',\n 'submission',\n 'observed_users',\n 'can_edit',\n 'score_statistics',\n] as const\n\nexport function assignmentTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'list_assignments',\n description:\n '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`.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n include: z\n .array(z.enum(ASSIGNMENT_LIST_INCLUDE))\n .optional()\n .describe('Extra fields to include on each assignment (Canvas include[] param)'),\n search_term: z\n .string()\n .optional()\n .describe('Partial name substring to filter assignments by'),\n bucket: z\n .enum(ASSIGNMENT_BUCKET)\n .optional()\n .describe('Only include assignments in the given bucket'),\n assignment_ids: z\n .array(z.number())\n .optional()\n .describe('Restrict to the given list of assignment IDs'),\n order_by: z.enum(ASSIGNMENT_ORDER_BY).optional().describe('Field to sort the result by'),\n override_assignment_dates: z\n .boolean()\n .optional()\n .describe(\n 'Apply assignment overrides to due/unlock/lock dates (default Canvas behavior: true)',\n ),\n needs_grading_count_by_section: z\n .boolean()\n .optional()\n .describe('Break needs_grading_count down by section'),\n post_to_sis: z\n .boolean()\n .optional()\n .describe('Filter to assignments that are/are not posted to SIS'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const opts: ListAssignmentsOptions = {}\n if (params.include !== undefined)\n opts.include = params.include as ReadonlyArray<AssignmentListInclude>\n if (params.search_term !== undefined) opts.search_term = params.search_term as string\n if (params.bucket !== undefined) opts.bucket = params.bucket as AssignmentBucket\n if (params.assignment_ids !== undefined)\n opts.assignment_ids = params.assignment_ids as ReadonlyArray<number>\n if (params.order_by !== undefined) opts.order_by = params.order_by as AssignmentOrderBy\n if (params.override_assignment_dates !== undefined)\n opts.override_assignment_dates = params.override_assignment_dates as boolean\n if (params.needs_grading_count_by_section !== undefined)\n opts.needs_grading_count_by_section = params.needs_grading_count_by_section as boolean\n if (params.post_to_sis !== undefined) opts.post_to_sis = params.post_to_sis as boolean\n return canvas.assignments.list(params.course_id as number, opts)\n },\n },\n {\n name: 'get_assignment',\n description:\n 'Get details for a single assignment by ID. Use `include` to request submission, overrides, all_dates, score_statistics, and other optional fields.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n assignment_id: z.number().describe('The Canvas assignment ID'),\n include: z\n .array(z.enum(ASSIGNMENT_GET_INCLUDE))\n .optional()\n .describe('Extra fields to include on the assignment (Canvas include[] param)'),\n override_assignment_dates: z\n .boolean()\n .optional()\n .describe('Apply assignment overrides to due/unlock/lock dates'),\n needs_grading_count_by_section: z\n .boolean()\n .optional()\n .describe('Break needs_grading_count down by section'),\n all_dates: z\n .boolean()\n .optional()\n .describe('Return all dates associated with this assignment'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const opts: GetAssignmentOptions = {}\n if (params.include !== undefined)\n opts.include = params.include as ReadonlyArray<AssignmentGetInclude>\n if (params.override_assignment_dates !== undefined)\n opts.override_assignment_dates = params.override_assignment_dates as boolean\n if (params.needs_grading_count_by_section !== undefined)\n opts.needs_grading_count_by_section = params.needs_grading_count_by_section as boolean\n if (params.all_dates !== undefined) opts.all_dates = params.all_dates as boolean\n return canvas.assignments.get(\n params.course_id as number,\n params.assignment_id as number,\n opts,\n )\n },\n },\n {\n name: 'list_assignment_groups',\n description:\n '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.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n include: z\n .array(z.enum(ASSIGNMENT_GROUP_INCLUDE))\n .optional()\n .describe('Extra fields to include (Canvas include[] param)'),\n assignment_ids: z\n .array(z.number())\n .optional()\n .describe(\n 'When combined with include=assignments, restrict nested assignments to these IDs',\n ),\n exclude_assignment_submission_types: z\n .array(z.string())\n .optional()\n .describe('Exclude assignments whose submission_types match any of these values'),\n override_assignment_dates: z\n .boolean()\n .optional()\n .describe('Apply assignment overrides to due/unlock/lock dates'),\n grading_period_id: z\n .number()\n .int()\n .optional()\n .describe('Scope to a specific grading period'),\n scope_assignments_to_student: z\n .boolean()\n .optional()\n .describe('Limit assignments to what the current student can see'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const opts: ListAssignmentGroupsOptions = {}\n if (params.include !== undefined)\n opts.include = params.include as ReadonlyArray<AssignmentGroupInclude>\n if (params.assignment_ids !== undefined)\n opts.assignment_ids = params.assignment_ids as ReadonlyArray<number>\n if (params.exclude_assignment_submission_types !== undefined)\n opts.exclude_assignment_submission_types =\n params.exclude_assignment_submission_types as ReadonlyArray<string>\n if (params.override_assignment_dates !== undefined)\n opts.override_assignment_dates = params.override_assignment_dates as boolean\n if (params.grading_period_id !== undefined)\n opts.grading_period_id = params.grading_period_id as number\n if (params.scope_assignments_to_student !== undefined)\n opts.scope_assignments_to_student = params.scope_assignments_to_student as boolean\n return canvas.assignments.listGroups(params.course_id as number, opts)\n },\n },\n {\n name: 'create_assignment',\n description: 'Create a new assignment in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n name: z.string().describe('Assignment name'),\n description: z.string().optional().describe('Assignment description (HTML supported)'),\n points_possible: z.number().optional().describe('Maximum points for this assignment'),\n due_at: z\n .string()\n .optional()\n .describe('Due date in ISO 8601 format (e.g. 2026-05-01T23:59:00Z)'),\n submission_types: z\n .array(z.string())\n .optional()\n .describe(\n 'Allowed submission types (e.g. [\"online_upload\", \"online_text_entry\", \"none\"])',\n ),\n assignment_group_id: z\n .number()\n .optional()\n .describe('ID of the assignment group to place this assignment in'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { course_id, ...rest } = params as {\n course_id: number\n name: string\n description?: string\n points_possible?: number\n due_at?: string\n submission_types?: string[]\n assignment_group_id?: number\n }\n return canvas.assignments.create(course_id, rest)\n },\n },\n {\n name: 'update_assignment',\n description: 'Update an existing assignment in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n assignment_id: z.number().describe('The Canvas assignment ID'),\n name: z.string().optional().describe('New assignment name'),\n description: z.string().optional().describe('New assignment description (HTML supported)'),\n points_possible: z.number().optional().describe('New maximum points'),\n due_at: z\n .string()\n .optional()\n .describe('New due date in ISO 8601 format (e.g. 2026-05-01T23:59:00Z)'),\n submission_types: z.array(z.string()).optional().describe('New allowed submission types'),\n assignment_group_id: z.number().optional().describe('New assignment group ID'),\n },\n annotations: {\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { course_id, assignment_id, ...rest } = params as {\n course_id: number\n assignment_id: number\n name?: string\n description?: string\n points_possible?: number\n due_at?: string\n submission_types?: string[]\n assignment_group_id?: number\n }\n return canvas.assignments.update(course_id, assignment_id, rest)\n },\n },\n {\n name: 'delete_assignment',\n description: 'Delete an assignment from a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n assignment_id: z.number().describe('The Canvas assignment ID to delete'),\n },\n annotations: {\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const assignment_id = params.assignment_id as number\n await canvas.assignments.delete(course_id, assignment_id)\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function calendarTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'list_calendar_events',\n description: 'List calendar events for a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.calendar.list(course_id)\n },\n },\n {\n name: 'create_calendar_event',\n description: 'Create a new calendar event in Canvas.',\n inputSchema: {\n context_code: z\n .string()\n .describe('Canvas context code, e.g. \"course_123\" for a course event'),\n title: z.string().describe('Event title'),\n start_at: z.string().describe('Start time in ISO 8601 format, e.g. \"2026-05-01T10:00:00Z\"'),\n end_at: z\n .string()\n .optional()\n .describe('End time in ISO 8601 format. Omit for all-day events.'),\n description: z.string().optional().describe('Event description (HTML allowed)'),\n location_name: z.string().optional().describe('Location name'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n return canvas.calendar.createEvent({\n context_code: params.context_code as string,\n title: params.title as string,\n start_at: params.start_at as string,\n end_at: params.end_at as string | undefined,\n description: params.description as string | undefined,\n location_name: params.location_name as string | undefined,\n })\n },\n },\n {\n name: 'update_calendar_event',\n description: 'Update an existing calendar event. Only provided fields are changed.',\n inputSchema: {\n event_id: z.number().describe('The Canvas calendar event ID'),\n title: z.string().optional().describe('New event title'),\n start_at: z.string().optional().describe('New start time in ISO 8601 format'),\n end_at: z.string().optional().describe('New end time in ISO 8601 format'),\n description: z.string().optional().describe('New description (HTML allowed)'),\n location_name: z.string().optional().describe('New location name'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const event_id = params.event_id as number\n return canvas.calendar.updateEvent(event_id, {\n title: params.title as string | undefined,\n start_at: params.start_at as string | undefined,\n end_at: params.end_at as string | undefined,\n description: params.description as string | undefined,\n location_name: params.location_name as string | undefined,\n })\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function conversationTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'list_conversations',\n description: 'List conversations (inbox messages) for the authenticated user.',\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n return canvas.conversations.list()\n },\n },\n {\n name: 'get_conversation',\n description: 'Get a single conversation with its full message thread.',\n inputSchema: {\n conversation_id: z.number().describe('The conversation ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n return canvas.conversations.get(params.conversation_id as number)\n },\n },\n {\n name: 'get_conversation_unread_count',\n description: 'Get the number of unread conversations for the authenticated user.',\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n return canvas.conversations.getUnreadCount()\n },\n },\n {\n name: 'send_conversation',\n description: 'Send a new conversation message to one or more recipients.',\n inputSchema: {\n recipients: z.array(z.string()).describe('Array of recipient user IDs (as strings)'),\n subject: z.string().describe('The conversation subject line'),\n body: z.string().describe('The message body'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const recipients = params.recipients as string[]\n const subject = params.subject as string\n const body = params.body as string\n return canvas.conversations.send(recipients, subject, body)\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type {\n CourseEnrollmentState,\n CourseGetInclude,\n CourseListInclude,\n CourseWorkflowState,\n GetCourseOptions,\n ListCoursesOptions,\n} from '../canvas/courses'\nimport type { ToolDefinition } from './types'\n\nconst COURSE_LIST_INCLUDE = [\n 'needs_grading_count',\n 'syllabus_body',\n 'public_description',\n 'total_scores',\n 'current_grading_period_scores',\n 'grading_periods',\n 'term',\n 'account',\n 'course_progress',\n 'sections',\n 'storage_quota_used_mb',\n 'total_students',\n 'passback_status',\n 'favorites',\n 'teachers',\n 'observed_users',\n 'tabs',\n 'course_image',\n 'banner_image',\n 'concluded',\n 'lti_context_id',\n 'post_manually',\n] as const\n\nconst COURSE_GET_INCLUDE = [...COURSE_LIST_INCLUDE, 'all_courses', 'permissions'] as const\n\nconst COURSE_WORKFLOW_STATE = ['unpublished', 'available', 'completed', 'deleted'] as const\n\nconst COURSE_ENROLLMENT_STATE = ['active', 'invited_or_pending', 'completed'] as const\n\nexport function courseTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'list_courses',\n description:\n '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’s enrollment state.',\n inputSchema: {\n enrollment_state: z\n .enum(COURSE_ENROLLMENT_STATE)\n .optional()\n .describe('Filter courses by the caller’s enrollment state'),\n state: z\n .array(z.enum(COURSE_WORKFLOW_STATE))\n .optional()\n .describe('Filter by course workflow state'),\n enrollment_role_id: z\n .number()\n .int()\n .optional()\n .describe('Filter by specific enrollment role ID'),\n include: z\n .array(z.enum(COURSE_LIST_INCLUDE))\n .optional()\n .describe('Extra fields to include on each course (Canvas include[] param)'),\n exclude_blueprint_courses: z\n .boolean()\n .optional()\n .describe('Exclude blueprint courses from the results'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const opts: ListCoursesOptions = {}\n if (params.enrollment_state !== undefined)\n opts.enrollment_state = params.enrollment_state as CourseEnrollmentState\n if (params.state !== undefined)\n opts.state = params.state as ReadonlyArray<CourseWorkflowState>\n if (params.enrollment_role_id !== undefined)\n opts.enrollment_role_id = params.enrollment_role_id as number\n if (params.include !== undefined)\n opts.include = params.include as ReadonlyArray<CourseListInclude>\n if (params.exclude_blueprint_courses !== undefined)\n opts.exclude_blueprint_courses = params.exclude_blueprint_courses as boolean\n return canvas.courses.list(opts)\n },\n },\n {\n name: 'get_course',\n description:\n '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.).',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n include: z\n .array(z.enum(COURSE_GET_INCLUDE))\n .optional()\n .describe('Extra fields to include on the course (Canvas include[] param)'),\n teacher_limit: z\n .number()\n .int()\n .optional()\n .describe('Limit on the number of teachers returned when include=teachers'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const opts: GetCourseOptions = {}\n if (params.include !== undefined)\n opts.include = params.include as ReadonlyArray<CourseGetInclude>\n if (params.teacher_limit !== undefined) opts.teacher_limit = params.teacher_limit as number\n return canvas.courses.get(params.course_id as number, opts)\n },\n },\n {\n name: 'get_syllabus',\n description: 'Get the syllabus HTML body for a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const syllabus_body = await canvas.courses.getSyllabus(course_id)\n return { course_id, syllabus_body }\n },\n },\n {\n name: 'create_course',\n description: 'Create a new course in a Canvas account. Returns the created course object.',\n inputSchema: {\n account_id: z\n .number()\n .int()\n .positive()\n .describe('The Canvas account ID to create the course in'),\n name: z.string().describe('The name of the course'),\n course_code: z.string().optional().describe('The course code (e.g. CS101)'),\n start_at: z\n .string()\n .datetime()\n .optional()\n .describe('Course start date in ISO 8601 format (e.g. 2026-01-15T00:00:00Z)'),\n end_at: z\n .string()\n .datetime()\n .optional()\n .describe('Course end date in ISO 8601 format (e.g. 2026-05-15T00:00:00Z)'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { account_id, ...courseFields } = params as {\n account_id: number\n name: string\n course_code?: string\n start_at?: string\n end_at?: string\n }\n return canvas.courses.create({ account_id, ...courseFields })\n },\n },\n {\n name: 'update_course',\n description:\n 'Update an existing course. Only provided fields are changed; omitted fields are left as-is.',\n inputSchema: {\n course_id: z.number().int().positive().describe('The Canvas course ID to update'),\n name: z.string().optional().describe('New course name'),\n course_code: z.string().optional().describe('New course code'),\n start_at: z\n .string()\n .datetime()\n .optional()\n .describe('New start date in ISO 8601 format (e.g. 2026-01-15T00:00:00Z)'),\n end_at: z\n .string()\n .datetime()\n .optional()\n .describe('New end date in ISO 8601 format (e.g. 2026-05-15T00:00:00Z)'),\n default_view: z\n .enum(['feed', 'wiki', 'modules', 'assignments', 'syllabus'])\n .optional()\n .describe('Default course home page view'),\n syllabus_body: z.string().optional().describe('HTML body for the course syllabus'),\n },\n annotations: {\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { course_id, ...fields } = params as {\n course_id: number\n name?: string\n course_code?: string\n start_at?: string\n end_at?: string\n default_view?: 'feed' | 'wiki' | 'modules' | 'assignments' | 'syllabus'\n syllabus_body?: string\n }\n return canvas.courses.update(course_id, fields)\n },\n },\n ]\n}\n","import type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function dashboardTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'get_dashboard_cards',\n description: \"Get the current user's dashboard course cards with position, color, and image.\",\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n return canvas.dashboard.getDashboardCards()\n },\n },\n {\n name: 'get_todo_items',\n description:\n \"Get the current user's to-do items, including upcoming assignments and grading tasks.\",\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n return canvas.dashboard.getTodoItems()\n },\n },\n {\n name: 'get_upcoming_events',\n description: \"Get the current user's upcoming calendar events and assignments.\",\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n return canvas.dashboard.getUpcomingEvents()\n },\n },\n {\n name: 'get_missing_submissions',\n description: 'Get assignments with missing submissions for the current user.',\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n return canvas.dashboard.getMissingSubmissions()\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function discussionTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'list_discussions',\n description: 'List all discussion topics in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.discussions.list(course_id)\n },\n },\n {\n name: 'get_discussion',\n description: 'Get details for a single discussion topic by ID.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n topic_id: z.number().describe('The Canvas discussion topic ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const topic_id = params.topic_id as number\n return canvas.discussions.get(course_id, topic_id)\n },\n },\n {\n name: 'list_announcements',\n description: 'List all announcements in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.discussions.listAnnouncements(course_id)\n },\n },\n {\n name: 'post_discussion_entry',\n description: 'Post a new entry (reply) to a discussion topic.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n topic_id: z.number().describe('The Canvas discussion topic ID'),\n message: z.string().describe('The message body (supports HTML)'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const topic_id = params.topic_id as number\n const message = params.message as string\n return canvas.discussions.postEntry(course_id, topic_id, message)\n },\n },\n {\n name: 'create_discussion',\n description: 'Create a new discussion topic in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n title: z.string().min(1).describe('Title of the discussion topic'),\n message: z.string().optional().describe('Body text of the discussion (supports HTML)'),\n discussion_type: z\n .enum(['side_comment', 'threaded'])\n .optional()\n .describe('Discussion type: side_comment (flat) or threaded'),\n published: z.boolean().optional().describe('Whether the topic is published'),\n require_initial_post: z\n .boolean()\n .optional()\n .describe('Require students to post before seeing replies'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.discussions.create(course_id, {\n title: params.title as string,\n message: params.message as string | undefined,\n discussion_type: params.discussion_type as 'side_comment' | 'threaded' | undefined,\n published: params.published as boolean | undefined,\n require_initial_post: params.require_initial_post as boolean | undefined,\n })\n },\n },\n {\n name: 'update_discussion',\n description: 'Update an existing discussion topic.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n topic_id: z.number().describe('The Canvas discussion topic ID'),\n title: z.string().optional().describe('New title for the discussion topic'),\n message: z.string().optional().describe('New body text (supports HTML)'),\n published: z.boolean().optional().describe('Publish or unpublish the topic'),\n require_initial_post: z\n .boolean()\n .optional()\n .describe('Require students to post before seeing replies'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const topic_id = params.topic_id as number\n const updateParams = {\n title: params.title as string | undefined,\n message: params.message as string | undefined,\n published: params.published as boolean | undefined,\n require_initial_post: params.require_initial_post as boolean | undefined,\n }\n if (Object.values(updateParams).every((v) => v === undefined)) {\n throw new Error('At least one field must be provided to update a discussion topic')\n }\n return canvas.discussions.update(course_id, topic_id, updateParams)\n },\n },\n {\n name: 'delete_discussion',\n description: 'Delete a discussion topic from a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n topic_id: z.number().describe('The Canvas discussion topic ID to delete'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const topic_id = params.topic_id as number\n await canvas.discussions.delete(course_id, topic_id)\n return { deleted: true, topic_id }\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type {\n EnrollmentInclude,\n EnrollmentState,\n EnrollmentType,\n ListCourseEnrollmentsOptions,\n ListUserEnrollmentsOptions,\n} from '../canvas/enrollments'\nimport type { ToolDefinition } from './types'\n\nconst ENROLLMENT_TYPE = [\n 'StudentEnrollment',\n 'TeacherEnrollment',\n 'TaEnrollment',\n 'DesignerEnrollment',\n 'ObserverEnrollment',\n] as const\n\nconst ENROLLMENT_STATE = [\n 'active',\n 'invited',\n 'creation_pending',\n 'deleted',\n 'rejected',\n 'completed',\n 'inactive',\n 'current_and_invited',\n 'current_and_future',\n 'current_and_concluded',\n] as const\n\nconst ENROLLMENT_INCLUDE = [\n 'avatar_url',\n 'group_ids',\n 'locked',\n 'observed_users',\n 'can_be_removed',\n 'uuid',\n 'current_points',\n 'grades',\n] as const\n\nexport function enrollmentTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'list_enrollments',\n description:\n 'List all enrollments for the authenticated user across courses. Optional filters and includes mirror Canvas `GET /users/self/enrollments`.',\n inputSchema: {\n type: z\n .array(z.enum(ENROLLMENT_TYPE))\n .optional()\n .describe('Filter by one or more enrollment types'),\n state: z\n .array(z.enum(ENROLLMENT_STATE))\n .optional()\n .describe('Filter by one or more enrollment states'),\n role: z\n .array(z.string())\n .optional()\n .describe('Filter by enrollment role names (as defined in the Canvas account)'),\n include: z\n .array(z.enum(ENROLLMENT_INCLUDE))\n .optional()\n .describe('Extra fields to include on each enrollment (Canvas include[] param)'),\n grading_period_id: z\n .number()\n .int()\n .optional()\n .describe('Return enrollments scoped to this grading period'),\n enrollment_term_id: z\n .number()\n .int()\n .optional()\n .describe('Limit to enrollments in the given term'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const opts: ListUserEnrollmentsOptions = {}\n if (params.type !== undefined) opts.type = params.type as ReadonlyArray<EnrollmentType>\n if (params.state !== undefined) opts.state = params.state as ReadonlyArray<EnrollmentState>\n if (params.role !== undefined) opts.role = params.role as ReadonlyArray<string>\n if (params.include !== undefined)\n opts.include = params.include as ReadonlyArray<EnrollmentInclude>\n if (params.grading_period_id !== undefined)\n opts.grading_period_id = params.grading_period_id as number\n if (params.enrollment_term_id !== undefined)\n opts.enrollment_term_id = params.enrollment_term_id as number\n return canvas.enrollments.list(opts)\n },\n },\n {\n name: 'list_course_enrollments',\n description:\n '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.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n type: z\n .array(z.enum(ENROLLMENT_TYPE))\n .optional()\n .describe('Filter by one or more enrollment types'),\n state: z.array(z.enum(ENROLLMENT_STATE)).optional().describe('Filter by enrollment states'),\n role: z.array(z.string()).optional().describe('Filter by custom role names'),\n include: z\n .array(z.enum(ENROLLMENT_INCLUDE))\n .optional()\n .describe('Extra fields to include (Canvas include[] param)'),\n user_id: z\n .union([z.number(), z.string()])\n .optional()\n .describe('Filter to a specific user (may be numeric ID or \"self\")'),\n grading_period_id: z\n .number()\n .int()\n .optional()\n .describe('Scope grade-related includes to this grading period'),\n enrollment_term_id: z\n .number()\n .int()\n .optional()\n .describe('Limit to enrollments in the given term'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const opts: ListCourseEnrollmentsOptions = {}\n if (params.type !== undefined) opts.type = params.type as ReadonlyArray<EnrollmentType>\n if (params.state !== undefined) opts.state = params.state as ReadonlyArray<EnrollmentState>\n if (params.role !== undefined) opts.role = params.role as ReadonlyArray<string>\n if (params.include !== undefined)\n opts.include = params.include as ReadonlyArray<EnrollmentInclude>\n if (params.user_id !== undefined) opts.user_id = params.user_id as number | string\n if (params.grading_period_id !== undefined)\n opts.grading_period_id = params.grading_period_id as number\n if (params.enrollment_term_id !== undefined)\n opts.enrollment_term_id = params.enrollment_term_id as number\n return canvas.enrollments.listForCourse(params.course_id as number, opts)\n },\n },\n {\n name: 'enroll_user',\n description: 'Enroll a user in a course with a specified role.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n user_id: z.number().describe('The Canvas user ID to enroll'),\n type: z\n .enum([\n 'StudentEnrollment',\n 'TeacherEnrollment',\n 'TaEnrollment',\n 'ObserverEnrollment',\n 'DesignerEnrollment',\n ])\n .describe('The enrollment type'),\n enrollment_state: z\n .enum(['active', 'invited', 'inactive'])\n .optional()\n .describe('Initial enrollment state (defaults to invited)'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n return canvas.enrollments.enroll(\n params.course_id as number,\n params.user_id as number,\n params.type as string,\n params.enrollment_state as string | undefined,\n )\n },\n },\n {\n name: 'remove_enrollment',\n description: 'Remove or conclude an enrollment from a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n enrollment_id: z.number().describe('The enrollment ID to remove'),\n task: z\n .enum(['conclude', 'delete', 'deactivate'])\n .describe('The action to perform on the enrollment'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n return canvas.enrollments.remove(\n params.course_id as number,\n params.enrollment_id as number,\n params.task as string,\n )\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function fileTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'list_files',\n description: 'List all files in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.files.list(course_id)\n },\n },\n {\n name: 'list_folders',\n description: 'List all folders in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.files.listFolders(course_id)\n },\n },\n {\n name: 'get_file',\n description: 'Get metadata for a single file by ID, including download URL.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n file_id: z.number().describe('The Canvas file ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const file_id = params.file_id as number\n return canvas.files.get(course_id, file_id)\n },\n },\n {\n name: 'upload_file',\n description:\n 'Upload a file to a course. Content must be base64-encoded. Canvas performs a multi-step upload internally.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n name: z.string().describe('File name including extension'),\n content: z.string().describe('Base64-encoded file content'),\n content_type: z.string().describe('MIME type, e.g. \"application/pdf\" or \"image/png\"'),\n parent_folder_path: z\n .string()\n .optional()\n .describe('Destination folder path within the course, e.g. \"subfolder/nested\"'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const name = params.name as string\n const content = params.content as string\n const content_type = params.content_type as string\n const parent_folder_path = params.parent_folder_path as string | undefined\n return canvas.files.upload(course_id, name, content, content_type, parent_folder_path)\n },\n },\n {\n name: 'delete_file',\n description: 'Delete a file by ID. This action is permanent.',\n inputSchema: {\n file_id: z.number().describe('The Canvas file ID'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const file_id = params.file_id as number\n return canvas.files.delete(file_id)\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function gradebookHistoryTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'list_gradebook_history_days',\n description:\n 'List the dates in a course gradebook history that contain grading activity, grouped by grader and assignment.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.gradebookHistory.listDays(course_id)\n },\n },\n {\n name: 'get_gradebook_history_day',\n description:\n 'Get the graders and assignment IDs that had gradebook activity on a specific course date.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n date: z.string().describe('The gradebook history date to inspect, in YYYY-MM-DD format'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const date = params.date as string\n return canvas.gradebookHistory.getDay(course_id, date)\n },\n },\n {\n name: 'list_gradebook_history_submissions',\n description:\n 'List versioned submission history for one grader and assignment on a specific gradebook history date.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n date: z.string().describe('The gradebook history date to inspect, in YYYY-MM-DD format'),\n grader_id: z.number().describe('The Canvas user ID of the grader'),\n assignment_id: z.number().describe('The Canvas assignment ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const date = params.date as string\n const grader_id = params.grader_id as number\n const assignment_id = params.assignment_id as number\n return canvas.gradebookHistory.listSubmissions(course_id, date, grader_id, assignment_id)\n },\n },\n {\n name: 'get_gradebook_history_feed',\n description:\n 'Get the paginated gradebook history feed for a course, optionally filtered by assignment or user and optionally sorted oldest-first.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n assignment_id: z\n .number()\n .optional()\n .describe('Optional Canvas assignment ID to filter the feed'),\n user_id: z.number().optional().describe('Optional Canvas user ID to filter the feed'),\n ascending: z\n .boolean()\n .optional()\n .describe('Set true to return the oldest gradebook history entries first'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const assignment_id = params.assignment_id as number | undefined\n const user_id = params.user_id as number | undefined\n const ascending = params.ascending as boolean | undefined\n return canvas.gradebookHistory.getFeed(course_id, { assignment_id, user_id, ascending })\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function groupTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'list_groups',\n description: 'List all groups in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.groups.list(course_id)\n },\n },\n {\n name: 'list_group_members',\n description: 'List all members of a group.',\n inputSchema: {\n group_id: z.number().describe('The Canvas group ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const group_id = params.group_id as number\n return canvas.groups.listMembers(group_id)\n },\n },\n ]\n}\n","import type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function healthTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'health_check',\n description:\n 'Check if the Canvas API is reachable and the token is valid. Returns ok/error status.',\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n await canvas.users.getProfile()\n return { status: 'ok', message: 'Canvas API is reachable' }\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function moduleTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'list_modules',\n description: 'List all modules in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.modules.list(course_id)\n },\n },\n {\n name: 'get_module',\n description: 'Get details for a single module by ID.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n module_id: z.number().describe('The Canvas module ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const module_id = params.module_id as number\n return canvas.modules.get(course_id, module_id)\n },\n },\n {\n name: 'list_module_items',\n description: 'List all items within a module.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n module_id: z.number().describe('The Canvas module ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const module_id = params.module_id as number\n return canvas.modules.listItems(course_id, module_id)\n },\n },\n {\n name: 'create_module',\n description: 'Create a new module in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n name: z.string().describe('Name of the module'),\n position: z.number().optional().describe('Position of the module in the list'),\n unlock_at: z.string().optional().describe('Date/time the module unlocks (ISO 8601)'),\n prerequisite_module_ids: z\n .array(z.number())\n .optional()\n .describe('IDs of modules that must be completed before this one'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.modules.create(course_id, {\n name: params.name as string,\n position: params.position as number | undefined,\n unlock_at: params.unlock_at as string | undefined,\n prerequisite_module_ids: params.prerequisite_module_ids as number[] | undefined,\n })\n },\n },\n {\n name: 'update_module',\n description: 'Update an existing module (rename, reposition, publish/unpublish).',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n module_id: z.number().describe('The Canvas module ID'),\n name: z.string().optional().describe('New name for the module'),\n position: z.number().optional().describe('New position in the module list'),\n published: z.boolean().optional().describe('Whether the module is published'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const module_id = params.module_id as number\n return canvas.modules.update(course_id, module_id, {\n name: params.name as string | undefined,\n position: params.position as number | undefined,\n published: params.published as boolean | undefined,\n })\n },\n },\n {\n name: 'create_module_item',\n description:\n 'Add an item (Assignment, Page, Quiz, File, Discussion, ExternalUrl, ExternalTool, SubHeader) to a module.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n module_id: z.number().describe('The Canvas module ID'),\n title: z.string().describe('Title of the module item'),\n type: z\n .enum([\n 'File',\n 'Page',\n 'Discussion',\n 'Assignment',\n 'Quiz',\n 'ExternalUrl',\n 'ExternalTool',\n 'SubHeader',\n ])\n .describe('Type of content to add'),\n content_id: z\n .number()\n .optional()\n .describe(\n 'Canvas ID of the content (required for File, Page, Discussion, Assignment, Quiz)',\n ),\n external_url: z.string().optional().describe('URL for ExternalUrl or ExternalTool items'),\n position: z.number().optional().describe('Position within the module'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const module_id = params.module_id as number\n return canvas.modules.createItem(course_id, module_id, {\n title: params.title as string,\n type: params.type as string,\n content_id: params.content_id as number | undefined,\n external_url: params.external_url as string | undefined,\n position: params.position as number | undefined,\n })\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\nimport {\n OUTCOME_CONTEXT_TYPES,\n OUTCOME_DETAIL_LEVELS,\n OUTCOME_EXCLUDE_OPTIONS,\n OUTCOME_ROLLUP_AGGREGATE_STATS,\n OUTCOME_ROLLUP_SORT_BY,\n OUTCOME_SORT_ORDER,\n} from '../canvas/outcomes'\n\nexport function outcomeTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'get_root_outcome_group',\n description: 'Get the root outcome group for an account or course context.',\n inputSchema: {\n context_type: z\n .enum(OUTCOME_CONTEXT_TYPES)\n .describe('Whether to read outcomes from an account or course context.'),\n context_id: z.number().describe('The Canvas account ID or course ID for the context.'),\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n handler: async (params) =>\n canvas.outcomes.getRootOutcomeGroup(\n params.context_type as 'account' | 'course',\n params.context_id as number,\n ),\n },\n {\n name: 'list_outcome_groups',\n description: 'List all outcome groups for an account or course context.',\n inputSchema: {\n context_type: z\n .enum(OUTCOME_CONTEXT_TYPES)\n .describe('Whether to read outcome groups from an account or course context.'),\n context_id: z.number().describe('The Canvas account ID or course ID for the context.'),\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n handler: async (params) =>\n canvas.outcomes.listOutcomeGroups(\n params.context_type as 'account' | 'course',\n params.context_id as number,\n ),\n },\n {\n name: 'list_outcome_group_links',\n description: 'List all outcome links in an account or course context.',\n inputSchema: {\n context_type: z\n .enum(OUTCOME_CONTEXT_TYPES)\n .describe('Whether to read outcome links from an account or course context.'),\n context_id: z.number().describe('The Canvas account ID or course ID for the context.'),\n outcome_style: z\n .enum(OUTCOME_DETAIL_LEVELS)\n .optional()\n .describe('Outcome detail level. Use \"full\" to include expanded outcome fields.'),\n outcome_group_style: z\n .enum(OUTCOME_DETAIL_LEVELS)\n .optional()\n .describe(\n 'Outcome group detail level. Use \"full\" to include expanded outcome group fields.',\n ),\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n handler: async (params) =>\n canvas.outcomes.listOutcomeGroupLinks(\n params.context_type as 'account' | 'course',\n params.context_id as number,\n {\n outcome_style: params.outcome_style as 'abbrev' | 'full' | undefined,\n outcome_group_style: params.outcome_group_style as 'abbrev' | 'full' | undefined,\n },\n ),\n },\n {\n name: 'get_outcome_group',\n description: 'Get details for a specific outcome group in an account or course context.',\n inputSchema: {\n context_type: z.enum(OUTCOME_CONTEXT_TYPES).describe('The outcome group context type.'),\n context_id: z.number().describe('The Canvas account ID or course ID for the context.'),\n outcome_group_id: z.number().describe('The Canvas outcome group ID.'),\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n handler: async (params) =>\n canvas.outcomes.getOutcomeGroup(\n params.context_type as 'account' | 'course',\n params.context_id as number,\n params.outcome_group_id as number,\n ),\n },\n {\n name: 'list_outcome_group_outcomes',\n description: 'List the linked outcomes directly under a specific outcome group.',\n inputSchema: {\n context_type: z.enum(OUTCOME_CONTEXT_TYPES).describe('The outcome group context type.'),\n context_id: z.number().describe('The Canvas account ID or course ID for the context.'),\n outcome_group_id: z.number().describe('The Canvas outcome group ID.'),\n outcome_style: z\n .enum(OUTCOME_DETAIL_LEVELS)\n .optional()\n .describe('Outcome detail level. Use \"full\" to include expanded outcome fields.'),\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n handler: async (params) =>\n canvas.outcomes.listGroupOutcomes(\n params.context_type as 'account' | 'course',\n params.context_id as number,\n params.outcome_group_id as number,\n {\n outcome_style: params.outcome_style as 'abbrev' | 'full' | undefined,\n },\n ),\n },\n {\n name: 'list_outcome_group_subgroups',\n description: 'List the immediate child outcome groups under a specific outcome group.',\n inputSchema: {\n context_type: z.enum(OUTCOME_CONTEXT_TYPES).describe('The outcome group context type.'),\n context_id: z.number().describe('The Canvas account ID or course ID for the context.'),\n outcome_group_id: z.number().describe('The Canvas outcome group ID.'),\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n handler: async (params) =>\n canvas.outcomes.listGroupSubgroups(\n params.context_type as 'account' | 'course',\n params.context_id as number,\n params.outcome_group_id as number,\n ),\n },\n {\n name: 'get_outcome',\n description: 'Get the full details for a specific learning outcome by ID.',\n inputSchema: {\n outcome_id: z.number().describe('The Canvas outcome ID.'),\n add_defaults: z\n .boolean()\n .optional()\n .describe('Include default mastery colors and levels when Canvas supports it.'),\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n handler: async (params) =>\n canvas.outcomes.getOutcome(params.outcome_id as number, {\n add_defaults: params.add_defaults as boolean | undefined,\n }),\n },\n {\n name: 'get_outcome_alignments',\n description:\n 'Get outcome alignments for a course, optionally filtered to a specific student or assignment.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID.'),\n student_id: z\n .number()\n .optional()\n .describe('Optional Canvas user ID of the student to filter alignments by.'),\n assignment_id: z\n .number()\n .optional()\n .describe('Optional Canvas assignment ID to filter alignments by.'),\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n handler: async (params) =>\n canvas.outcomes.getOutcomeAlignments(params.course_id as number, {\n student_id: params.student_id as number | undefined,\n assignment_id: params.assignment_id as number | undefined,\n }),\n },\n {\n name: 'get_outcome_results',\n description:\n 'Get per-student outcome results for a course, with optional outcome, student, and alignment filters.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID.'),\n user_ids: z\n .array(z.union([z.number(), z.string()]))\n .optional()\n .describe('Optional Canvas user IDs or SIS user IDs prefixed with \"sis_user_id:\".'),\n outcome_ids: z\n .array(z.number())\n .optional()\n .describe('Optional outcome IDs to restrict the results.'),\n include_alignments: z\n .boolean()\n .optional()\n .describe('Include linked alignment details in the response.'),\n include_hidden: z\n .boolean()\n .optional()\n .describe('Include hidden outcomes when Canvas supports it.'),\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n handler: async (params) =>\n canvas.outcomes.getOutcomeResults(params.course_id as number, {\n user_ids: params.user_ids as Array<number | string> | undefined,\n outcome_ids: params.outcome_ids as number[] | undefined,\n include_alignments: params.include_alignments as boolean | undefined,\n include_hidden: params.include_hidden as boolean | undefined,\n }),\n },\n {\n name: 'get_outcome_rollups',\n description:\n 'Get outcome rollups for a course, optionally aggregated or filtered by students, outcomes, and sort options.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID.'),\n aggregate: z\n .enum(['course'])\n .optional()\n .describe('Aggregate all student rollups into a single course-level rollup.'),\n aggregate_stat: z\n .enum(OUTCOME_ROLLUP_AGGREGATE_STATS)\n .optional()\n .describe('Statistic to use when aggregate=\"course\".'),\n user_ids: z\n .array(z.union([z.number(), z.string()]))\n .optional()\n .describe('Optional Canvas user IDs or SIS user IDs prefixed with \"sis_user_id:\".'),\n outcome_ids: z\n .array(z.number())\n .optional()\n .describe('Optional outcome IDs to restrict the rollups.'),\n include_courses: z\n .boolean()\n .optional()\n .describe('Include linked course details in the response payload.'),\n exclude: z\n .array(z.enum(OUTCOME_EXCLUDE_OPTIONS))\n .optional()\n .describe('Optional rollup exclusions for missing users or missing outcome results.'),\n sort_by: z\n .enum(OUTCOME_ROLLUP_SORT_BY)\n .optional()\n .describe('Sort rollups by student name or by a specific outcome score.'),\n sort_outcome_id: z\n .number()\n .optional()\n .describe('Outcome ID to sort by when sort_by=\"outcome\".'),\n sort_order: z\n .enum(OUTCOME_SORT_ORDER)\n .optional()\n .describe('Sort order to apply when sorting rollups.'),\n add_defaults: z\n .boolean()\n .optional()\n .describe('Include default mastery colors and levels when Canvas supports it.'),\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n handler: async (params) =>\n canvas.outcomes.getOutcomeRollups(params.course_id as number, {\n aggregate: params.aggregate as 'course' | undefined,\n aggregate_stat: params.aggregate_stat as 'mean' | 'median' | undefined,\n user_ids: params.user_ids as Array<number | string> | undefined,\n outcome_ids: params.outcome_ids as number[] | undefined,\n include_courses: params.include_courses as boolean | undefined,\n exclude: params.exclude as\n | Array<'missing_user_rollups' | 'missing_outcome_results'>\n | undefined,\n sort_by: params.sort_by as 'student' | 'outcome' | undefined,\n sort_outcome_id: params.sort_outcome_id as number | undefined,\n sort_order: params.sort_order as 'asc' | 'desc' | undefined,\n add_defaults: params.add_defaults as boolean | undefined,\n }),\n },\n {\n name: 'get_outcome_contributing_scores',\n description:\n 'Get assignment or quiz scores that contributed to a specific outcome for one or more students in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID.'),\n outcome_id: z.number().describe('The Canvas outcome ID.'),\n user_ids: z\n .array(z.union([z.number(), z.string()]))\n .optional()\n .describe('Optional Canvas user IDs or SIS user IDs prefixed with \"sis_user_id:\".'),\n only_assignment_alignments: z\n .boolean()\n .optional()\n .describe('Limit results to assignment alignments only.'),\n show_unpublished_assignments: z\n .boolean()\n .optional()\n .describe('Include unpublished assignments in the contributing score results.'),\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n handler: async (params) =>\n canvas.outcomes.getOutcomeContributingScores(\n params.course_id as number,\n params.outcome_id as number,\n {\n user_ids: params.user_ids as Array<number | string> | undefined,\n only_assignment_alignments: params.only_assignment_alignments as boolean | undefined,\n show_unpublished_assignments: params.show_unpublished_assignments as\n | boolean\n | undefined,\n },\n ),\n },\n {\n name: 'get_outcome_mastery_distribution',\n description:\n 'Get mastery distribution analytics for outcomes in a course, optionally filtered by students or outcomes.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID.'),\n exclude: z\n .array(z.enum(OUTCOME_EXCLUDE_OPTIONS))\n .optional()\n .describe('Optional exclusions for missing users or missing outcome results.'),\n outcome_ids: z\n .array(z.number())\n .optional()\n .describe('Optional outcome IDs to restrict the distribution results.'),\n student_ids: z\n .array(z.union([z.number(), z.string()]))\n .optional()\n .describe('Optional Canvas student IDs or SIS user IDs prefixed with \"sis_user_id:\".'),\n include_alignment_distributions: z\n .boolean()\n .optional()\n .describe('Include contributing score distributions for alignments.'),\n only_assignment_alignments: z\n .boolean()\n .optional()\n .describe('When including alignment distributions, limit them to assignments only.'),\n show_unpublished_assignments: z\n .boolean()\n .optional()\n .describe('Include unpublished assignments in alignment distributions.'),\n add_defaults: z\n .boolean()\n .optional()\n .describe('Include default mastery colors and levels when Canvas supports it.'),\n },\n annotations: { readOnlyHint: true, openWorldHint: true },\n handler: async (params) =>\n canvas.outcomes.getOutcomeMasteryDistribution(params.course_id as number, {\n exclude: params.exclude as\n | Array<'missing_user_rollups' | 'missing_outcome_results'>\n | undefined,\n outcome_ids: params.outcome_ids as number[] | undefined,\n student_ids: params.student_ids as Array<number | string> | undefined,\n include_alignment_distributions: params.include_alignment_distributions as\n | boolean\n | undefined,\n only_assignment_alignments: params.only_assignment_alignments as boolean | undefined,\n show_unpublished_assignments: params.show_unpublished_assignments as boolean | undefined,\n add_defaults: params.add_defaults as boolean | undefined,\n }),\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function pageTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'list_pages',\n description: 'List all wiki pages in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.pages.list(course_id)\n },\n },\n {\n name: 'get_page',\n description: 'Get a single wiki page by its URL slug.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n page_url: z.string().describe('The page URL slug (e.g. \"welcome-page\")'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const page_url = params.page_url as string\n return canvas.pages.get(course_id, page_url)\n },\n },\n {\n name: 'create_page',\n description: 'Create a new wiki page in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n title: z.string().describe('Title of the page'),\n body: z.string().optional().describe('HTML body content of the page'),\n published: z.boolean().optional().describe('Whether the page is published'),\n editing_roles: z\n .string()\n .optional()\n .describe('Who can edit: \"teachers\", \"students\", \"members\", or \"public\"'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.pages.create(course_id, {\n title: params.title as string,\n body: params.body as string | undefined,\n published: params.published as boolean | undefined,\n editing_roles: params.editing_roles as string | undefined,\n })\n },\n },\n {\n name: 'update_page',\n description: 'Update an existing wiki page.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n page_url: z.string().describe('The page URL slug'),\n title: z.string().optional().describe('New title for the page'),\n body: z.string().optional().describe('New HTML body content'),\n published: z.boolean().optional().describe('Whether the page is published'),\n editing_roles: z\n .string()\n .optional()\n .describe('Who can edit: \"teachers\", \"students\", \"members\", or \"public\"'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const page_url = params.page_url as string\n return canvas.pages.update(course_id, page_url, {\n title: params.title as string | undefined,\n body: params.body as string | undefined,\n published: params.published as boolean | undefined,\n editing_roles: params.editing_roles as string | undefined,\n })\n },\n },\n {\n name: 'delete_page',\n description: 'Delete a wiki page from a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n page_url: z.string().describe('The page URL slug to delete'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const page_url = params.page_url as string\n await canvas.pages.delete(course_id, page_url)\n return { deleted: true, page_url }\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function peerReviewTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'list_peer_reviews',\n description: 'List all peer reviews for an assignment in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n assignment_id: z.number().describe('The Canvas assignment ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const assignment_id = params.assignment_id as number\n return canvas.peerReviews.listForAssignment(course_id, assignment_id)\n },\n },\n {\n name: 'get_submission_peer_reviews',\n description: 'List peer reviews assigned to a specific submission.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n assignment_id: z.number().describe('The Canvas assignment ID'),\n submission_id: z.number().describe('The Canvas submission ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const assignment_id = params.assignment_id as number\n const submission_id = params.submission_id as number\n return canvas.peerReviews.listForSubmission(course_id, assignment_id, submission_id)\n },\n },\n {\n name: 'create_peer_review',\n description: 'Assign a user to peer-review a submission.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n assignment_id: z.number().describe('The Canvas assignment ID'),\n submission_id: z.number().describe('The Canvas submission ID'),\n user_id: z.number().describe('The Canvas user ID of the reviewer to assign'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const assignment_id = params.assignment_id as number\n const submission_id = params.submission_id as number\n const user_id = params.user_id as number\n return canvas.peerReviews.create(course_id, assignment_id, submission_id, user_id)\n },\n },\n {\n name: 'delete_peer_review',\n description: 'Remove a peer review assignment from a submission.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n assignment_id: z.number().describe('The Canvas assignment ID'),\n submission_id: z.number().describe('The Canvas submission ID'),\n user_id: z.number().describe('The Canvas user ID of the reviewer to remove'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const assignment_id = params.assignment_id as number\n const submission_id = params.submission_id as number\n const user_id = params.user_id as number\n await canvas.peerReviews.delete(course_id, assignment_id, submission_id, user_id)\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function quizTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'list_quizzes',\n description: 'List all quizzes in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.quizzes.list(course_id)\n },\n },\n {\n name: 'get_quiz',\n description: 'Get details for a single quiz by ID.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n quiz_id: z.number().describe('The Canvas quiz ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const quiz_id = params.quiz_id as number\n return canvas.quizzes.get(course_id, quiz_id)\n },\n },\n {\n name: 'list_quiz_submissions',\n description: 'List all submissions for a quiz.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n quiz_id: z.number().describe('The Canvas quiz ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const quiz_id = params.quiz_id as number\n return canvas.quizzes.listSubmissions(course_id, quiz_id)\n },\n },\n {\n name: 'list_quiz_questions',\n description: 'List all questions in a quiz.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n quiz_id: z.number().describe('The Canvas quiz ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const quiz_id = params.quiz_id as number\n return canvas.quizzes.listQuestions(course_id, quiz_id)\n },\n },\n {\n name: 'get_quiz_submission_answers',\n description: \"Get a student's answers for a quiz submission.\",\n inputSchema: {\n quiz_submission_id: z.number().describe('The Canvas quiz submission ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const quiz_submission_id = params.quiz_submission_id as number\n return canvas.quizzes.getSubmissionAnswers(quiz_submission_id)\n },\n },\n {\n name: 'score_quiz_question',\n description:\n 'Score a specific question in a quiz submission. Specify attempt to score a particular attempt (omit for latest). Requires grading permissions.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n quiz_id: z.number().describe('The Canvas quiz ID'),\n submission_id: z.number().describe('The Canvas quiz submission ID'),\n question_id: z.number().describe('The Canvas quiz question ID'),\n score: z.number().describe('The score to assign'),\n comment: z.string().optional().describe('Optional feedback comment'),\n attempt: z.number().optional().describe('Quiz attempt number to score (omit for latest)'),\n },\n annotations: {\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const quiz_id = params.quiz_id as number\n const submission_id = params.submission_id as number\n const question_id = params.question_id as number\n const score = params.score as number\n const comment = params.comment as string | undefined\n const attempt = params.attempt as number | undefined\n await canvas.quizzes.scoreQuestion(\n course_id,\n quiz_id,\n submission_id,\n question_id,\n score,\n comment,\n attempt,\n )\n return { success: true }\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function rubricTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'list_rubrics',\n description: 'List all rubrics in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.rubrics.list(course_id)\n },\n },\n {\n name: 'get_rubric',\n description: 'Get details for a single rubric by ID, including criteria.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n rubric_id: z.number().describe('The Canvas rubric ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const rubric_id = params.rubric_id as number\n return canvas.rubrics.get(course_id, rubric_id)\n },\n },\n {\n name: 'get_rubric_assessment',\n description: 'Get the rubric assessment for a specific student submission on an assignment.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n assignment_id: z.number().describe('The Canvas assignment ID'),\n user_id: z.number().describe('The Canvas user ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const assignment_id = params.assignment_id as number\n const user_id = params.user_id as number\n return canvas.rubrics.getAssessment(course_id, assignment_id, user_id)\n },\n },\n {\n name: 'submit_rubric_assessment',\n description: 'Submit a rubric assessment with scores and comments for each criterion.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n association_id: z.number().describe('The rubric association ID'),\n data: z\n .array(\n z.object({\n criterion_id: z.string().describe('The rubric criterion ID'),\n points: z.number().describe('Points awarded for this criterion'),\n comments: z.string().describe('Feedback comment for this criterion'),\n }),\n )\n .describe('Array of criterion assessments'),\n },\n annotations: {\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const association_id = params.association_id as number\n const data = params.data as Array<{\n criterion_id: string\n points: number\n comments: string\n }>\n return canvas.rubrics.submitAssessment(course_id, association_id, data)\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function studentTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'get_my_courses',\n description: 'List active courses for the authenticated student.',\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n return canvas.courses.list({ enrollment_state: 'active' })\n },\n },\n {\n name: 'get_my_grades',\n description:\n 'Get grade data for the authenticated student. If course_id is omitted, returns grades across all enrolled courses.',\n inputSchema: {\n course_id: z.number().optional().describe('The Canvas course ID (omit for all courses)'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number | undefined\n return canvas.enrollments.listMyGrades(course_id)\n },\n },\n {\n name: 'get_my_submissions',\n description: 'List all submissions for the authenticated student in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.submissions.listMy(course_id)\n },\n },\n {\n name: 'get_my_upcoming_assignments',\n description: 'List upcoming assignment events for the authenticated student.',\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n return canvas.users.getUpcomingAssignments()\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type {\n GetSubmissionOptions,\n ListSubmissionsOptions,\n SubmissionGetInclude,\n SubmissionListInclude,\n SubmissionWorkflowState,\n} from '../canvas/submissions'\nimport type { ToolDefinition } from './types'\n\nconst SUBMISSION_LIST_INCLUDE = [\n 'submission_history',\n 'submission_comments',\n 'rubric_assessment',\n 'assignment',\n 'visibility',\n 'course',\n 'user',\n 'group',\n 'read_status',\n 'sub_assignment_submissions',\n] as const\n\nconst SUBMISSION_GET_INCLUDE = [\n 'submission_history',\n 'submission_comments',\n 'rubric_assessment',\n 'visibility',\n 'course',\n 'user',\n 'read_status',\n] as const\n\nconst SUBMISSION_WORKFLOW_STATE = ['submitted', 'unsubmitted', 'graded', 'pending_review'] as const\n\nexport function submissionTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'list_submissions',\n description:\n '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.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n assignment_id: z.number().describe('The Canvas assignment ID'),\n include: z\n .array(z.enum(SUBMISSION_LIST_INCLUDE))\n .optional()\n .describe(\n 'Extra fields to include (Canvas include[] param). Defaults to [\"submission_comments\"] when omitted.',\n ),\n student_ids: z\n .array(z.union([z.number(), z.string()]))\n .optional()\n .describe(\n 'Restrict to submissions for these user IDs. Use \"all\" or \"self\" for shortcuts.',\n ),\n section_ids: z\n .array(z.number())\n .optional()\n .describe('Restrict to submissions in these sections'),\n grouped: z\n .boolean()\n .optional()\n .describe('Return one submission per group rather than per student'),\n workflow_state: z\n .enum(SUBMISSION_WORKFLOW_STATE)\n .optional()\n .describe('Only include submissions in this workflow state'),\n grading_period_id: z.number().int().optional().describe('Restrict to a grading period'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const opts: ListSubmissionsOptions = {}\n if (params.include !== undefined)\n opts.include = params.include as ReadonlyArray<SubmissionListInclude>\n if (params.student_ids !== undefined)\n opts.student_ids = params.student_ids as ReadonlyArray<number | string>\n if (params.section_ids !== undefined)\n opts.section_ids = params.section_ids as ReadonlyArray<number>\n if (params.grouped !== undefined) opts.grouped = params.grouped as boolean\n if (params.workflow_state !== undefined)\n opts.workflow_state = params.workflow_state as SubmissionWorkflowState\n if (params.grading_period_id !== undefined)\n opts.grading_period_id = params.grading_period_id as number\n return canvas.submissions.list(\n params.course_id as number,\n params.assignment_id as number,\n opts,\n )\n },\n },\n {\n name: 'get_submission',\n description:\n '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.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n assignment_id: z.number().describe('The Canvas assignment ID'),\n user_id: z.number().describe('The Canvas user ID'),\n include: z\n .array(z.enum(SUBMISSION_GET_INCLUDE))\n .optional()\n .describe(\n 'Extra fields to include (Canvas include[] param). Defaults to [\"submission_comments\"] when omitted.',\n ),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const opts: GetSubmissionOptions = {}\n if (params.include !== undefined)\n opts.include = params.include as ReadonlyArray<SubmissionGetInclude>\n return canvas.submissions.get(\n params.course_id as number,\n params.assignment_id as number,\n params.user_id as number,\n opts,\n )\n },\n },\n {\n name: 'grade_submission',\n description: 'Post or update a grade for a submission. Requires grading permissions.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n assignment_id: z.number().describe('The Canvas assignment ID'),\n user_id: z.number().describe('The Canvas user ID'),\n grade: z.string().describe('The grade to assign (e.g. \"95\", \"A\", \"pass\")'),\n },\n annotations: {\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const assignment_id = params.assignment_id as number\n const user_id = params.user_id as number\n const grade = params.grade as string\n return canvas.submissions.grade(course_id, assignment_id, user_id, grade)\n },\n },\n {\n name: 'comment_on_submission',\n description: 'Add a text comment to a submission.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n assignment_id: z.number().describe('The Canvas assignment ID'),\n user_id: z.number().describe('The Canvas user ID'),\n comment: z.string().describe('The comment text to add'),\n },\n annotations: {\n destructiveHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n const assignment_id = params.assignment_id as number\n const user_id = params.user_id as number\n const comment = params.comment as string\n return canvas.submissions.comment(course_id, assignment_id, user_id, comment)\n },\n },\n ]\n}\n","import { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type {\n CourseUserEnrollmentState,\n CourseUserEnrollmentType,\n CourseUserInclude,\n ListCourseUsersOptions,\n SearchUserInclude,\n SearchUsersOptions,\n UserSort,\n} from '../canvas/users'\nimport type { ToolDefinition } from './types'\n\nconst COURSE_USER_ENROLLMENT_TYPE = ['student', 'teacher', 'ta', 'observer', 'designer'] as const\nconst COURSE_USER_ENROLLMENT_STATE = [\n 'active',\n 'invited',\n 'rejected',\n 'completed',\n 'inactive',\n] as const\nconst COURSE_USER_INCLUDE = [\n 'email',\n 'enrollments',\n 'locked',\n 'avatar_url',\n 'test_student',\n 'bio',\n 'custom_links',\n 'current_grading_period_scores',\n 'uuid',\n] as const\nconst USER_SORT = ['username', 'email', 'sis_id', 'integration_id', 'last_login'] as const\nconst SEARCH_USER_INCLUDE = ['email', 'last_login', 'avatar_url', 'time_zone', 'uuid'] as const\n\nexport function userTools(canvas: CanvasClient): ToolDefinition[] {\n return [\n {\n name: 'list_students',\n description: 'List all students enrolled in a course.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const course_id = params.course_id as number\n return canvas.users.listStudents(course_id)\n },\n },\n {\n name: 'get_user',\n description: 'Get details for a single user by ID.',\n inputSchema: {\n user_id: z.number().describe('The Canvas user ID'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const user_id = params.user_id as number\n return canvas.users.get(user_id)\n },\n },\n {\n name: 'get_profile',\n description: 'Get the profile of the currently authenticated user.',\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n return canvas.users.getProfile()\n },\n },\n {\n name: 'search_users',\n description:\n '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.',\n inputSchema: {\n account_id: z.number().describe('The Canvas account ID'),\n search_term: z.string().describe('The search term (name, login, or email)'),\n sort: z.enum(USER_SORT).optional().describe('Sort field'),\n order: z.enum(['asc', 'desc']).optional().describe('Sort order'),\n include: z\n .array(z.enum(SEARCH_USER_INCLUDE))\n .optional()\n .describe('Extra fields to include on each user (Canvas include[] param)'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const opts: SearchUsersOptions = {}\n if (params.sort !== undefined) opts.sort = params.sort as UserSort\n if (params.order !== undefined) opts.order = params.order as 'asc' | 'desc'\n if (params.include !== undefined)\n opts.include = params.include as ReadonlyArray<SearchUserInclude>\n return canvas.users.searchUsers(\n params.account_id as number,\n params.search_term as string,\n opts,\n )\n },\n },\n {\n name: 'list_course_users',\n description:\n '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.',\n inputSchema: {\n course_id: z.number().describe('The Canvas course ID'),\n enrollment_type: z\n .array(z.enum(COURSE_USER_ENROLLMENT_TYPE))\n .optional()\n .describe('Filter by one or more enrollment types'),\n enrollment_state: z\n .array(z.enum(COURSE_USER_ENROLLMENT_STATE))\n .optional()\n .describe('Filter by enrollment state (e.g. active, invited)'),\n enrollment_role_id: z\n .number()\n .int()\n .optional()\n .describe('Filter by a specific enrollment role ID (overrides enrollment_type)'),\n include: z\n .array(z.enum(COURSE_USER_INCLUDE))\n .optional()\n .describe('Extra fields to include on each user (Canvas include[] param)'),\n user_ids: z\n .array(z.union([z.number(), z.string()]))\n .optional()\n .describe('Restrict the result to the given user IDs'),\n search_term: z\n .string()\n .optional()\n .describe('Partial name or full login/SIS ID to filter users by'),\n sort: z.enum(USER_SORT).optional().describe('Sort field'),\n order: z.enum(['asc', 'desc']).optional().describe('Sort order'),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const opts: ListCourseUsersOptions = {}\n if (params.enrollment_type !== undefined)\n opts.enrollment_type = params.enrollment_type as ReadonlyArray<CourseUserEnrollmentType>\n if (params.enrollment_state !== undefined)\n opts.enrollment_state =\n params.enrollment_state as ReadonlyArray<CourseUserEnrollmentState>\n if (params.enrollment_role_id !== undefined)\n opts.enrollment_role_id = params.enrollment_role_id as number\n if (params.include !== undefined)\n opts.include = params.include as ReadonlyArray<CourseUserInclude>\n if (params.user_ids !== undefined)\n opts.user_ids = params.user_ids as ReadonlyArray<number | string>\n if (params.search_term !== undefined) opts.search_term = params.search_term as string\n if (params.sort !== undefined) opts.sort = params.sort as UserSort\n if (params.order !== undefined) opts.order = params.order as 'asc' | 'desc'\n return canvas.users.listCourseUsers(params.course_id as number, opts)\n },\n },\n ]\n}\n","import type { CanvasClient } from '../canvas'\nimport { accountTools } from './accounts'\nimport { analyticsTools } from './analytics'\nimport { assignmentTools } from './assignments'\nimport { calendarTools } from './calendar'\nimport { conversationTools } from './conversations'\nimport { courseTools } from './courses'\nimport { dashboardTools } from './dashboard'\nimport { discussionTools } from './discussions'\nimport { enrollmentTools } from './enrollments'\nimport { fileTools } from './files'\nimport { gradebookHistoryTools } from './gradebook-history'\nimport { groupTools } from './groups'\nimport { healthTools } from './health'\nimport { moduleTools } from './modules'\nimport { outcomeTools } from './outcomes'\nimport { pageTools } from './pages'\nimport { peerReviewTools } from './peer-reviews'\nimport { quizTools } from './quizzes'\nimport { rubricTools } from './rubrics'\nimport { studentTools } from './student'\nimport { submissionTools } from './submissions'\nimport type { ToolAudience, ToolDefinition } from './types'\nimport { userTools } from './users'\n\nexport interface ToolDomainRegistration {\n domain: string\n defaultPrimaryAudience: ToolAudience\n getTools: (canvas: CanvasClient) => ToolDefinition[]\n}\n\nexport const toolDomainCatalog: readonly ToolDomainRegistration[] = [\n {\n domain: 'health',\n defaultPrimaryAudience: 'shared',\n getTools: healthTools,\n },\n {\n domain: 'courses',\n defaultPrimaryAudience: 'shared',\n getTools: courseTools,\n },\n {\n domain: 'assignments',\n defaultPrimaryAudience: 'educator',\n getTools: assignmentTools,\n },\n {\n domain: 'submissions',\n defaultPrimaryAudience: 'educator',\n getTools: submissionTools,\n },\n {\n domain: 'rubrics',\n defaultPrimaryAudience: 'educator',\n getTools: rubricTools,\n },\n {\n domain: 'quizzes',\n defaultPrimaryAudience: 'educator',\n getTools: quizTools,\n },\n {\n domain: 'files',\n defaultPrimaryAudience: 'shared',\n getTools: fileTools,\n },\n {\n domain: 'gradebook_history',\n defaultPrimaryAudience: 'educator',\n getTools: gradebookHistoryTools,\n },\n {\n domain: 'users',\n defaultPrimaryAudience: 'educator',\n getTools: userTools,\n },\n {\n domain: 'groups',\n defaultPrimaryAudience: 'shared',\n getTools: groupTools,\n },\n {\n domain: 'enrollments',\n defaultPrimaryAudience: 'admin',\n getTools: enrollmentTools,\n },\n {\n domain: 'discussions',\n defaultPrimaryAudience: 'shared',\n getTools: discussionTools,\n },\n {\n domain: 'modules',\n defaultPrimaryAudience: 'educator',\n getTools: moduleTools,\n },\n {\n domain: 'pages',\n defaultPrimaryAudience: 'educator',\n getTools: pageTools,\n },\n {\n domain: 'calendar',\n defaultPrimaryAudience: 'shared',\n getTools: calendarTools,\n },\n {\n domain: 'conversations',\n defaultPrimaryAudience: 'shared',\n getTools: conversationTools,\n },\n {\n domain: 'peer_reviews',\n defaultPrimaryAudience: 'shared',\n getTools: peerReviewTools,\n },\n {\n domain: 'accounts',\n defaultPrimaryAudience: 'admin',\n getTools: accountTools,\n },\n {\n domain: 'analytics',\n defaultPrimaryAudience: 'educator',\n getTools: analyticsTools,\n },\n {\n domain: 'outcomes',\n defaultPrimaryAudience: 'educator',\n getTools: outcomeTools,\n },\n {\n domain: 'student',\n defaultPrimaryAudience: 'student',\n getTools: studentTools,\n },\n {\n domain: 'dashboard',\n defaultPrimaryAudience: 'student',\n getTools: dashboardTools,\n },\n]\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { CanvasClient } from '../canvas'\nimport { CanvasApiError } from '../canvas/client'\nimport type { ToolDefinition } from './types'\nimport { toolDomainCatalog } from './catalog'\nimport { formatError } from './errors'\n\nexport function getAllTools(canvas: CanvasClient): ToolDefinition[] {\n return toolDomainCatalog.flatMap((registration) => registration.getTools(canvas))\n}\n\nexport function registerAllTools(server: McpServer, canvas: CanvasClient): void {\n const tools = getAllTools(canvas)\n for (const tool of tools) {\n server.tool(tool.name, tool.description, tool.inputSchema, tool.annotations, async (params) => {\n try {\n const result = await tool.handler(params as Record<string, unknown>)\n const text =\n result === undefined\n ? 'Operation completed successfully.'\n : JSON.stringify(result, null, 2)\n return {\n content: [{ type: 'text' as const, text }],\n }\n } catch (error) {\n if (error instanceof CanvasApiError) {\n // CanvasApiError — expected, no need to log\n } else {\n console.error(`Unexpected error in tool \"${tool.name}\":`, error)\n }\n return {\n content: [{ type: 'text' as const, text: formatError(error) }],\n isError: true,\n }\n }\n })\n }\n}\nexport { formatError } from './errors'\n","import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { CanvasClient } from '../canvas'\nimport { CanvasApiError } from '../canvas/client'\nimport { formatError } from '../tools'\n\nexport function registerSyllabusResource(server: McpServer, canvas: CanvasClient): void {\n const template = new ResourceTemplate('canvas://course/{courseId}/syllabus', {\n list: undefined,\n })\n\n server.resource(\n 'course-syllabus',\n template,\n { mimeType: 'text/html' },\n async (_uri, variables) => {\n const courseId = Number(variables.courseId)\n if (Number.isNaN(courseId)) {\n return {\n contents: [\n {\n uri: `canvas://course/${variables.courseId}/syllabus`,\n mimeType: 'text/plain',\n text: 'Invalid course ID',\n },\n ],\n }\n }\n try {\n const body = await canvas.courses.getSyllabus(courseId)\n return {\n contents: [\n {\n uri: `canvas://course/${courseId}/syllabus`,\n mimeType: 'text/html',\n text: body ?? '',\n },\n ],\n }\n } catch (error) {\n if (!(error instanceof CanvasApiError)) {\n console.error('Unexpected error in syllabus resource:', error)\n }\n return {\n contents: [\n {\n uri: `canvas://course/${courseId}/syllabus`,\n mimeType: 'text/plain',\n text: formatError(error),\n },\n ],\n }\n }\n },\n )\n}\n","import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { CanvasClient } from '../canvas'\nimport { CanvasApiError } from '../canvas/client'\nimport { formatError } from '../tools'\n\nexport function registerAssignmentDescriptionResource(\n server: McpServer,\n canvas: CanvasClient,\n): void {\n const template = new ResourceTemplate(\n 'canvas://course/{courseId}/assignment/{assignmentId}/description',\n { list: undefined },\n )\n\n server.resource(\n 'assignment-description',\n template,\n { mimeType: 'text/html' },\n async (_uri, variables) => {\n const courseId = Number(variables.courseId)\n const assignmentId = Number(variables.assignmentId)\n const uri = `canvas://course/${courseId}/assignment/${assignmentId}/description`\n if (Number.isNaN(courseId) || Number.isNaN(assignmentId)) {\n return {\n contents: [{ uri, mimeType: 'text/plain', text: 'Invalid course or assignment ID' }],\n }\n }\n try {\n const assignment = await canvas.assignments.get(courseId, assignmentId)\n return {\n contents: [\n {\n uri,\n mimeType: 'text/html',\n text: assignment.description ?? '',\n },\n ],\n }\n } catch (error) {\n if (!(error instanceof CanvasApiError)) {\n console.error('Unexpected error in assignment-description resource:', error)\n }\n return {\n contents: [{ uri, mimeType: 'text/plain', text: formatError(error) }],\n }\n }\n },\n )\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { CanvasClient } from '../canvas'\nimport { registerSyllabusResource } from './syllabus'\nimport { registerAssignmentDescriptionResource } from './assignment-description'\n\nexport function registerAllResources(server: McpServer, canvas: CanvasClient): void {\n registerSyllabusResource(server, canvas)\n registerAssignmentDescriptionResource(server, canvas)\n}\n"]}
@@ -7,8 +7,9 @@ import {
7
7
  OUTCOME_ROLLUP_AGGREGATE_STATS,
8
8
  OUTCOME_ROLLUP_SORT_BY,
9
9
  OUTCOME_SORT_ORDER,
10
- SEARCH_CONTENT_TYPES
11
- } from "./chunk-UODLH4L6.js";
10
+ SEARCH_CONTENT_TYPES,
11
+ version
12
+ } from "./chunk-NGP4KCMC.js";
12
13
 
13
14
  // src/server.ts
14
15
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -2659,7 +2660,7 @@ function createCanvasMCPServer(config) {
2659
2660
  });
2660
2661
  const server = new McpServer({
2661
2662
  name: "canvas-lms-mcp",
2662
- version: "1.0.0"
2663
+ version
2663
2664
  });
2664
2665
  registerAllTools(server, canvas);
2665
2666
  registerAllResources(server, canvas);
@@ -2669,4 +2670,4 @@ function createCanvasMCPServer(config) {
2669
2670
  export {
2670
2671
  createCanvasMCPServer
2671
2672
  };
2672
- //# sourceMappingURL=chunk-JLXP5GLN.js.map
2673
+ //# sourceMappingURL=chunk-CZHZNIP3.js.map