@mtgibbs/canvas-lms-mcp 0.2.2 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/src/api/courses.d.ts +4 -0
- package/esm/src/api/courses.d.ts.map +1 -1
- package/esm/src/api/courses.js +34 -7
- package/esm/src/mcp/tools/get-courses.d.ts.map +1 -1
- package/esm/src/mcp/tools/get-courses.js +8 -3
- package/esm/src/mcp/tools/get-due-this-week.js +1 -1
- package/esm/src/mcp/tools/get-missing-assignments.d.ts.map +1 -1
- package/esm/src/mcp/tools/get-missing-assignments.js +8 -3
- package/esm/src/mcp/tools/get-recent-grades.js +1 -1
- package/esm/src/mcp/tools/get-stats.js +1 -1
- package/esm/src/mcp/tools/get-todo.js +1 -1
- package/esm/src/mcp/tools/get-unsubmitted-past-due.js +1 -1
- package/esm/src/mcp/tools/get-upcoming-assignments.d.ts.map +1 -1
- package/esm/src/mcp/tools/get-upcoming-assignments.js +1 -1
- package/esm/src/mcp/tools/list-assignments.d.ts.map +1 -1
- package/esm/src/mcp/tools/list-assignments.js +1 -1
- package/manifest.json +1 -1
- package/package.json +1 -1
package/esm/src/api/courses.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export declare function listCourseEnrollments(courseId: number, options?: {
|
|
|
17
17
|
type?: string[];
|
|
18
18
|
state?: string[];
|
|
19
19
|
userId?: number | string;
|
|
20
|
+
include?: string[];
|
|
20
21
|
}): Promise<Enrollment[]>;
|
|
21
22
|
/**
|
|
22
23
|
* Get enrollment with grades for a specific user in a course
|
|
@@ -25,6 +26,9 @@ export declare function getUserEnrollment(courseId: number, userId: number | str
|
|
|
25
26
|
/**
|
|
26
27
|
* List courses with grades for a user (observer or self)
|
|
27
28
|
* Enriches course data with enrollment/grade information
|
|
29
|
+
*
|
|
30
|
+
* For observer accounts querying a specific student, this fetches
|
|
31
|
+
* the student's enrollment separately to get their actual grades.
|
|
28
32
|
*/
|
|
29
33
|
export declare function listCoursesWithGrades(userId?: string | number): Promise<(Course & {
|
|
30
34
|
enrollment?: Enrollment;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"courses.d.ts","sourceRoot":"","sources":["../../../src/src/api/courses.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAEjF;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmB3E;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG3D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IACR,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"courses.d.ts","sourceRoot":"","sources":["../../../src/src/api/courses.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAEjF;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmB3E;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG3D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IACR,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,GACA,OAAO,CAAC,UAAU,EAAE,CAAC,CAmBvB;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GAAG,MAAM,GACtB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAO5B;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,GAAE,MAAM,GAAG,MAAe,GAC/B,OAAO,CAAC,CAAC,MAAM,GAAG;IAAE,UAAU,CAAC,EAAE,UAAU,CAAA;CAAE,CAAC,EAAE,CAAC,CAmDnD"}
|
package/esm/src/api/courses.js
CHANGED
|
@@ -34,7 +34,10 @@ export function getCourse(courseId) {
|
|
|
34
34
|
*/
|
|
35
35
|
export function listCourseEnrollments(courseId, options) {
|
|
36
36
|
const client = getClient();
|
|
37
|
-
const params = {
|
|
37
|
+
const params = {
|
|
38
|
+
// Always include grades when fetching enrollments
|
|
39
|
+
include: options?.include || ["grades"],
|
|
40
|
+
};
|
|
38
41
|
if (options?.type) {
|
|
39
42
|
params.type = options.type;
|
|
40
43
|
}
|
|
@@ -59,6 +62,9 @@ export async function getUserEnrollment(courseId, userId) {
|
|
|
59
62
|
/**
|
|
60
63
|
* List courses with grades for a user (observer or self)
|
|
61
64
|
* Enriches course data with enrollment/grade information
|
|
65
|
+
*
|
|
66
|
+
* For observer accounts querying a specific student, this fetches
|
|
67
|
+
* the student's enrollment separately to get their actual grades.
|
|
62
68
|
*/
|
|
63
69
|
export async function listCoursesWithGrades(userId = "self") {
|
|
64
70
|
// Get all active courses with enrollments included
|
|
@@ -67,14 +73,35 @@ export async function listCoursesWithGrades(userId = "self") {
|
|
|
67
73
|
include: ["enrollments", "term"],
|
|
68
74
|
state: ["available"],
|
|
69
75
|
});
|
|
70
|
-
//
|
|
76
|
+
// If querying for a specific student (not "self"), we need to fetch
|
|
77
|
+
// the student's enrollment separately since the courses endpoint
|
|
78
|
+
// only returns the observer's enrollment for parent accounts
|
|
79
|
+
const isObserverQuery = userId !== "self" && !isNaN(Number(userId));
|
|
80
|
+
if (isObserverQuery) {
|
|
81
|
+
// Fetch student enrollments with grades in parallel
|
|
82
|
+
const enrollmentPromises = courses.map(async (course) => {
|
|
83
|
+
try {
|
|
84
|
+
const enrollments = await listCourseEnrollments(course.id, {
|
|
85
|
+
userId: Number(userId),
|
|
86
|
+
type: ["StudentEnrollment"],
|
|
87
|
+
});
|
|
88
|
+
return { courseId: course.id, enrollment: enrollments[0] || null };
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return { courseId: course.id, enrollment: null };
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
const enrollmentResults = await Promise.all(enrollmentPromises);
|
|
95
|
+
const enrollmentMap = new Map(enrollmentResults.map((r) => [r.courseId, r.enrollment]));
|
|
96
|
+
return courses.map((course) => ({
|
|
97
|
+
...course,
|
|
98
|
+
enrollment: enrollmentMap.get(course.id) || undefined,
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
// For "self" queries, use the enrollment from the courses response
|
|
71
102
|
const coursesWithGrades = courses.map((course) => {
|
|
72
|
-
// Find the enrollment for this user (or observed user)
|
|
73
103
|
const enrollment = course.enrollments?.find((e) => {
|
|
74
|
-
|
|
75
|
-
return e.type === "StudentEnrollment" || e.type === "ObserverEnrollment";
|
|
76
|
-
}
|
|
77
|
-
return e.user_id === Number(userId) || e.observed_user?.id === Number(userId);
|
|
104
|
+
return e.type === "StudentEnrollment" || e.type === "ObserverEnrollment";
|
|
78
105
|
});
|
|
79
106
|
return {
|
|
80
107
|
...course,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-courses.d.ts","sourceRoot":"","sources":["../../../../src/src/mcp/tools/get-courses.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"get-courses.d.ts","sourceRoot":"","sources":["../../../../src/src/mcp/tools/get-courses.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,eAAO,MAAM,MAAM;;CAKlB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,OAAO,MAAM,CAWxD,CAAC"}
|
|
@@ -4,17 +4,22 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { getCourses } from "../../services/index.js";
|
|
7
|
+
import { getEffectiveStudentId } from "../../api/users.js";
|
|
7
8
|
import { jsonResponse } from "../types.js";
|
|
8
9
|
export const schema = {
|
|
9
|
-
student_id: z
|
|
10
|
+
student_id: z
|
|
11
|
+
.string()
|
|
12
|
+
.optional()
|
|
13
|
+
.describe("Student ID (uses configured CANVAS_STUDENT_ID if not provided)"),
|
|
10
14
|
};
|
|
11
15
|
export const getCoursesTool = {
|
|
12
16
|
name: "get_courses",
|
|
13
|
-
description: "List all active courses
|
|
17
|
+
description: "List all active courses with current cumulative grades (score percentages). Use this to get an overview of the student's course load and overall academic standing. For observer/parent accounts, this fetches the observed student's grades, not the observer's. Returns course name, code, and current score percentage.",
|
|
14
18
|
schema,
|
|
15
19
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
16
20
|
handler: async ({ student_id }) => {
|
|
17
|
-
const
|
|
21
|
+
const effectiveStudentId = await getEffectiveStudentId(student_id);
|
|
22
|
+
const courses = await getCourses({ studentId: String(effectiveStudentId) });
|
|
18
23
|
return jsonResponse(courses);
|
|
19
24
|
},
|
|
20
25
|
};
|
|
@@ -24,7 +24,7 @@ export const schema = {
|
|
|
24
24
|
};
|
|
25
25
|
export const getDueThisWeekTool = {
|
|
26
26
|
name: "get_due_this_week",
|
|
27
|
-
description: "Get all assignments due in the next N days across ALL courses for
|
|
27
|
+
description: "Get all assignments due in the next N days across ALL courses at once. This is the recommended tool for questions like 'what's due this week?' or 'what homework do I have?'. Returns assignment name, course, due date, points, and whether it's been submitted. By default hides already-graded items to focus on pending work.",
|
|
28
28
|
schema,
|
|
29
29
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
30
30
|
handler: async ({ student_id, days, hide_graded }) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-missing-assignments.d.ts","sourceRoot":"","sources":["../../../../src/src/mcp/tools/get-missing-assignments.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"get-missing-assignments.d.ts","sourceRoot":"","sources":["../../../../src/src/mcp/tools/get-missing-assignments.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,eAAO,MAAM,MAAM;;;CAMlB,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,cAAc,CAAC,OAAO,MAAM,CAenE,CAAC"}
|
|
@@ -4,19 +4,24 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { getMissingAssignments } from "../../services/index.js";
|
|
7
|
+
import { getEffectiveStudentId } from "../../api/users.js";
|
|
7
8
|
import { jsonResponse } from "../types.js";
|
|
8
9
|
export const schema = {
|
|
9
|
-
student_id: z
|
|
10
|
+
student_id: z
|
|
11
|
+
.string()
|
|
12
|
+
.optional()
|
|
13
|
+
.describe("Student ID (uses configured CANVAS_STUDENT_ID if not provided)"),
|
|
10
14
|
course_id: z.number().optional().describe("Filter by specific course ID"),
|
|
11
15
|
};
|
|
12
16
|
export const getMissingAssignmentsTool = {
|
|
13
17
|
name: "get_missing_assignments",
|
|
14
|
-
description: "Get missing assignments for
|
|
18
|
+
description: "Get assignments that Canvas has officially flagged as 'missing'. These are past-due assignments where the teacher has marked them missing. NOTE: This may not catch all unsubmitted work - use get_unsubmitted_past_due for assignments that are past due but not yet flagged by the teacher. Use both tools together for a complete picture of outstanding work.",
|
|
15
19
|
schema,
|
|
16
20
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
17
21
|
handler: async ({ student_id, course_id }) => {
|
|
22
|
+
const effectiveStudentId = await getEffectiveStudentId(student_id);
|
|
18
23
|
const missing = await getMissingAssignments({
|
|
19
|
-
studentId:
|
|
24
|
+
studentId: String(effectiveStudentId),
|
|
20
25
|
courseId: course_id,
|
|
21
26
|
});
|
|
22
27
|
return jsonResponse(missing);
|
|
@@ -27,7 +27,7 @@ export const schema = {
|
|
|
27
27
|
};
|
|
28
28
|
export const getRecentGradesTool = {
|
|
29
29
|
name: "get_recent_grades",
|
|
30
|
-
description: "Get recently graded assignments with scores.
|
|
30
|
+
description: "Get recently graded assignments with scores from the last N days (default 14). Shows assignment name, course, score, points possible, and percentage. Use below_percentage to filter for low grades (e.g., below_percentage=70 to find grades under 70%). Useful for questions like 'how did I do on recent tests?' or 'any bad grades lately?'",
|
|
31
31
|
schema,
|
|
32
32
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
33
33
|
handler: async ({ student_id, days, below_percentage, course_id }) => {
|
|
@@ -19,7 +19,7 @@ export const schema = {
|
|
|
19
19
|
};
|
|
20
20
|
export const getStatsTool = {
|
|
21
21
|
name: "get_stats",
|
|
22
|
-
description: "Get late and missing assignment statistics by course,
|
|
22
|
+
description: "Get late and missing assignment statistics aggregated by course. Shows total assignments, late count, missing count, and percentages for each course. Use this to identify problem courses or answer questions like 'which class has the most missing work?' or 'how many late assignments do I have?'",
|
|
23
23
|
schema,
|
|
24
24
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
25
25
|
handler: async ({ student_id, hide_empty }) => {
|
|
@@ -20,7 +20,7 @@ export const schema = {
|
|
|
20
20
|
};
|
|
21
21
|
export const getTodoTool = {
|
|
22
22
|
name: "get_todo",
|
|
23
|
-
description: "Get the student's to-do list
|
|
23
|
+
description: "Get the student's Canvas planner/to-do list showing upcoming assignments, quizzes, discussions, and tasks. This is what the student sees in their Canvas planner. Shows item type, due date, points, and submission status. Use hide_submitted=true to focus on incomplete items only.",
|
|
24
24
|
schema,
|
|
25
25
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
26
26
|
handler: async ({ student_id, days, hide_submitted }) => {
|
|
@@ -18,7 +18,7 @@ export const schema = {
|
|
|
18
18
|
};
|
|
19
19
|
export const getUnsubmittedPastDueTool = {
|
|
20
20
|
name: "get_unsubmitted_past_due",
|
|
21
|
-
description: "Get assignments that are past due but
|
|
21
|
+
description: "Get assignments that are past due but have no submission. This catches work that Canvas hasn't officially flagged as 'missing' yet (teachers may not have updated the status). Use this alongside get_missing_assignments for a complete picture of all outstanding/late work. Returns assignment name, course, due date, and points.",
|
|
22
22
|
schema,
|
|
23
23
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
24
24
|
handler: async ({ student_id, course_id }) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-upcoming-assignments.d.ts","sourceRoot":"","sources":["../../../../src/src/mcp/tools/get-upcoming-assignments.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,eAAO,MAAM,MAAM;;;CAGlB,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,cAAc,CAAC,OAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"get-upcoming-assignments.d.ts","sourceRoot":"","sources":["../../../../src/src/mcp/tools/get-upcoming-assignments.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,eAAO,MAAM,MAAM;;;CAGlB,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,cAAc,CAAC,OAAO,MAAM,CAcpE,CAAC"}
|
|
@@ -11,7 +11,7 @@ export const schema = {
|
|
|
11
11
|
};
|
|
12
12
|
export const getUpcomingAssignmentsTool = {
|
|
13
13
|
name: "get_upcoming_assignments",
|
|
14
|
-
description: "Get assignments due in the next N days for a
|
|
14
|
+
description: "Get assignments due in the next N days for a SINGLE course. Requires course_id. Use this when asking about upcoming work in a specific class. For upcoming assignments across ALL courses at once, use get_due_this_week instead - it's more efficient for broad queries.",
|
|
15
15
|
schema,
|
|
16
16
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
17
17
|
handler: async ({ course_id, days }) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-assignments.d.ts","sourceRoot":"","sources":["../../../../src/src/mcp/tools/list-assignments.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,eAAO,MAAM,MAAM;;;;CAOlB,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,cAAc,CAAC,OAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"list-assignments.d.ts","sourceRoot":"","sources":["../../../../src/src/mcp/tools/list-assignments.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,eAAO,MAAM,MAAM;;;;CAOlB,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,cAAc,CAAC,OAAO,MAAM,CAe7D,CAAC"}
|
|
@@ -15,7 +15,7 @@ export const schema = {
|
|
|
15
15
|
};
|
|
16
16
|
export const listAssignmentsTool = {
|
|
17
17
|
name: "list_assignments",
|
|
18
|
-
description: "List assignments for a course with optional filtering",
|
|
18
|
+
description: "List assignments for a specific course with optional filtering by bucket (past, overdue, undated, ungraded, unsubmitted, upcoming, future). Use this for detailed assignment queries within a single course, like 'show me all overdue assignments in Math' or 'what assignments are ungraded in Science'. For simpler upcoming/due queries, prefer get_due_this_week.",
|
|
19
19
|
schema,
|
|
20
20
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
21
21
|
handler: async ({ course_id, bucket, search_term }) => {
|
package/manifest.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"manifest_version": "0.3",
|
|
3
3
|
"name": "canvas-lms-mcp",
|
|
4
4
|
"display_name": "Canvas LMS",
|
|
5
|
-
"version": "0.2.
|
|
5
|
+
"version": "0.2.8",
|
|
6
6
|
"description": "Connect Claude to your Canvas LMS account to query grades, assignments, missing work, and more.",
|
|
7
7
|
"long_description": "An MCP server that connects AI assistants like Claude to your Canvas LMS account. Perfect for parents monitoring their child's academic progress, students tracking their own work, or anyone who wants to interact with Canvas data through natural language.\n\nAsk Claude things like:\n- What assignments are due this week?\n- Show me missing assignments across all classes\n- What's my grade in Biology?\n- Are there any late assignments I should know about?",
|
|
8
8
|
"author": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mtgibbs/canvas-lms-mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "Canvas LMS MCP (Model Context Protocol) server for AI assistants. Query student grades, assignments, and academic data through Claude or other MCP-compatible AI tools.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|