{"version":3,"sources":["/home/runner/work/canvas-lms-mcp/canvas-lms-mcp/dist/chunk-VOQ5A7CA.cjs","../src/server.ts","../src/tools/errors.ts","../src/tools/health.ts","../src/tools/courses.ts","../src/tools/assignments.ts","../src/tools/submissions.ts","../src/tools/rubrics.ts","../src/tools/quizzes.ts","../src/tools/files.ts","../src/tools/users.ts","../src/tools/groups.ts","../src/tools/enrollments.ts","../src/tools/discussions.ts","../src/tools/modules.ts","../src/tools/pages.ts","../src/tools/calendar.ts","../src/tools/conversations.ts","../src/tools/peer-reviews.ts","../src/tools/accounts.ts","../src/tools/analytics.ts","../src/tools/student.ts","../src/tools/dashboard.ts","../src/tools/index.ts","../src/resources/syllabus.ts","../src/resources/assignment-description.ts","../src/resources/index.ts"],"names":["ResourceTemplate"],"mappings":"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","file":"/home/runner/work/canvas-lms-mcp/canvas-lms-mcp/dist/chunk-VOQ5A7CA.cjs","sourcesContent":[null,"import { 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: '1.0.0',\n  })\n\n  registerAllTools(server, canvas)\n  registerAllResources(server, canvas)\n\n  return { server, canvas }\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 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 courseTools(canvas: CanvasClient): ToolDefinition[] {\n  return [\n    {\n      name: 'list_courses',\n      description:\n        'List courses for the authenticated user. Optionally filter by enrollment state.',\n      inputSchema: {\n        enrollment_state: z\n          .enum(['active', 'completed', 'all'])\n          .optional()\n          .describe('Filter courses by enrollment state'),\n      },\n      annotations: {\n        readOnlyHint: true,\n        openWorldHint: true,\n      },\n      handler: async (params) => {\n        const enrollment_state = params.enrollment_state as string | undefined\n        return canvas.courses.list({ enrollment_state })\n      },\n    },\n    {\n      name: 'get_course',\n      description: 'Get details for a single course by ID, including term and total student count.',\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.courses.get(course_id)\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 { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function assignmentTools(canvas: CanvasClient): ToolDefinition[] {\n  return [\n    {\n      name: 'list_assignments',\n      description: 'List all assignments 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.assignments.list(course_id)\n      },\n    },\n    {\n      name: 'get_assignment',\n      description: 'Get details for a single assignment by ID.',\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.assignments.get(course_id, assignment_id)\n      },\n    },\n    {\n      name: 'list_assignment_groups',\n      description: 'List assignment groups (categories like Homework, Exams) 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.assignments.listGroups(course_id)\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 submissionTools(canvas: CanvasClient): ToolDefinition[] {\n  return [\n    {\n      name: 'list_submissions',\n      description: 'List all submissions 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.submissions.list(course_id, assignment_id)\n      },\n    },\n    {\n      name: 'get_submission',\n      description:\n        'Get a single submission for a specific user on an assignment, including comments.',\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.submissions.get(course_id, assignment_id, user_id)\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 { 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 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 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 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: 'Search for users in a Canvas account by name, login, or email.',\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\n          .enum(['username', 'email', 'sis_id', 'last_login'])\n          .optional()\n          .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        return canvas.users.searchUsers(\n          params.account_id as number,\n          params.search_term as string,\n          params.sort as string | undefined,\n          params.order as string | undefined,\n        )\n      },\n    },\n    {\n      name: 'list_course_users',\n      description: 'List all users in a course, optionally filtered by enrollment type.',\n      inputSchema: {\n        course_id: z.number().describe('The Canvas course ID'),\n        enrollment_type: z\n          .enum(['student', 'teacher', 'ta', 'observer', 'designer'])\n          .optional()\n          .describe('Filter by enrollment type'),\n      },\n      annotations: {\n        readOnlyHint: true,\n        openWorldHint: true,\n      },\n      handler: async (params) => {\n        return canvas.users.listCourseUsers(\n          params.course_id as number,\n          params.enrollment_type 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 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 { z } from 'zod'\nimport type { CanvasClient } from '../canvas'\nimport type { ToolDefinition } from './types'\n\nexport function enrollmentTools(canvas: CanvasClient): ToolDefinition[] {\n  return [\n    {\n      name: 'list_enrollments',\n      description: 'List all enrollments for the authenticated user across courses.',\n      inputSchema: {},\n      annotations: {\n        readOnlyHint: true,\n        openWorldHint: true,\n      },\n      handler: async () => {\n        return canvas.enrollments.list()\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 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 { 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'\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 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 { 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 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 { 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 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 type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { CanvasClient } from '../canvas'\nimport { CanvasApiError } from '../canvas/client'\nimport type { ToolDefinition } from './types'\nimport { formatError } from './errors'\nimport { healthTools } from './health'\nimport { courseTools } from './courses'\nimport { assignmentTools } from './assignments'\nimport { submissionTools } from './submissions'\nimport { rubricTools } from './rubrics'\nimport { quizTools } from './quizzes'\nimport { fileTools } from './files'\nimport { userTools } from './users'\nimport { groupTools } from './groups'\nimport { enrollmentTools } from './enrollments'\nimport { discussionTools } from './discussions'\nimport { moduleTools } from './modules'\nimport { pageTools } from './pages'\nimport { calendarTools } from './calendar'\nimport { conversationTools } from './conversations'\nimport { peerReviewTools } from './peer-reviews'\nimport { accountTools } from './accounts'\nimport { analyticsTools } from './analytics'\nimport { studentTools } from './student'\nimport { dashboardTools } from './dashboard'\n\nexport function getAllTools(canvas: CanvasClient): ToolDefinition[] {\n  return [\n    ...healthTools(canvas),\n    ...courseTools(canvas),\n    ...assignmentTools(canvas),\n    ...submissionTools(canvas),\n    ...rubricTools(canvas),\n    ...quizTools(canvas),\n    ...fileTools(canvas),\n    ...userTools(canvas),\n    ...groupTools(canvas),\n    ...enrollmentTools(canvas),\n    ...discussionTools(canvas),\n    ...moduleTools(canvas),\n    ...pageTools(canvas),\n    ...calendarTools(canvas),\n    ...conversationTools(canvas),\n    ...peerReviewTools(canvas),\n    ...accountTools(canvas),\n    ...analyticsTools(canvas),\n    ...studentTools(canvas),\n    ...dashboardTools(canvas),\n  ]\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"]}