brightspace-mcp-server 5.1.32 → 5.1.33
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/build/tools/get-roster.js +34 -8
- package/package.json +1 -1
|
@@ -21,6 +21,15 @@ const TEACHING_ROLE_NAME = /\b(instructor|professor|lecturer|teaching assistant|
|
|
|
21
21
|
function isTeachingRoleByName(user) {
|
|
22
22
|
return TEACHING_ROLE_NAME.test(user.ClasslistRoleDisplayName ?? "");
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Whether a failed role route must be reported rather than skipped. A 403
|
|
26
|
+
* means the classlist is restricted for that role: nothing was missed.
|
|
27
|
+
* Anything else (a 404, a 5xx, a dropped connection) leaves a hole the caller
|
|
28
|
+
* would read as "this course has no TAs".
|
|
29
|
+
*/
|
|
30
|
+
function isReportableFailure(error) {
|
|
31
|
+
return error?.status !== 403;
|
|
32
|
+
}
|
|
24
33
|
/**
|
|
25
34
|
* Fetch every classlist user matching the optional filters, across all pages.
|
|
26
35
|
*
|
|
@@ -60,6 +69,7 @@ export function registerGetRoster(server, apiClient) {
|
|
|
60
69
|
const allUsers = [];
|
|
61
70
|
let authFailure;
|
|
62
71
|
let roleFallbackUsed = false;
|
|
72
|
+
let unavailable = [];
|
|
63
73
|
if (!includeStudents) {
|
|
64
74
|
// Fetch instructors and TAs in parallel
|
|
65
75
|
const [instructorResult, taResult] = await Promise.allSettled([
|
|
@@ -87,6 +97,10 @@ export function registerGetRoster(server, apiClient) {
|
|
|
87
97
|
allUsers.push(...instructorResult.value);
|
|
88
98
|
}
|
|
89
99
|
else {
|
|
100
|
+
if (!isAuthUnavailable(instructorResult.reason) &&
|
|
101
|
+
isReportableFailure(instructorResult.reason)) {
|
|
102
|
+
unavailable.push("instructors");
|
|
103
|
+
}
|
|
90
104
|
log("WARN", "get_roster: Failed to fetch instructors", {
|
|
91
105
|
error: instructorResult.reason,
|
|
92
106
|
});
|
|
@@ -95,6 +109,9 @@ export function registerGetRoster(server, apiClient) {
|
|
|
95
109
|
allUsers.push(...taResult.value);
|
|
96
110
|
}
|
|
97
111
|
else {
|
|
112
|
+
if (!isAuthUnavailable(taResult.reason) && isReportableFailure(taResult.reason)) {
|
|
113
|
+
unavailable.push("TAs");
|
|
114
|
+
}
|
|
98
115
|
log("WARN", "get_roster: Failed to fetch TAs", {
|
|
99
116
|
error: taResult.reason,
|
|
100
117
|
});
|
|
@@ -112,6 +129,9 @@ export function registerGetRoster(server, apiClient) {
|
|
|
112
129
|
});
|
|
113
130
|
allUsers.push(...everyone.filter(isTeachingRoleByName));
|
|
114
131
|
roleFallbackUsed = true;
|
|
132
|
+
// The unfiltered fetch covered every role, so nothing the
|
|
133
|
+
// failed role routes would have returned is missing any more.
|
|
134
|
+
unavailable = [];
|
|
115
135
|
}
|
|
116
136
|
}
|
|
117
137
|
else {
|
|
@@ -139,6 +159,17 @@ export function registerGetRoster(server, apiClient) {
|
|
|
139
159
|
}));
|
|
140
160
|
log("INFO", `get_roster: Retrieved ${users.length} users for course ${courseId}` +
|
|
141
161
|
(authFailure ? " (sign-in pending for one route)" : ""));
|
|
162
|
+
const notices = [];
|
|
163
|
+
if (unavailable.length > 0) {
|
|
164
|
+
notices.push(`The ${unavailable.join(" and ")} for this course could not be read from ` +
|
|
165
|
+
"Brightspace, so they may be missing from this list. Do not report this " +
|
|
166
|
+
`course as having no ${unavailable.join(" or ")}; call get_roster again to retry.`);
|
|
167
|
+
}
|
|
168
|
+
if (authFailure) {
|
|
169
|
+
notices.push("Sign-in to Brightspace is still in progress, so part of the roster for this " +
|
|
170
|
+
`course could not be fetched yet. ${authPendingNotice(authFailure.reason)} Call ` +
|
|
171
|
+
"get_roster again once sign-in finishes.");
|
|
172
|
+
}
|
|
142
173
|
return toolResponse({
|
|
143
174
|
courseId,
|
|
144
175
|
total,
|
|
@@ -153,14 +184,9 @@ export function registerGetRoster(server, apiClient) {
|
|
|
153
184
|
}
|
|
154
185
|
: {}),
|
|
155
186
|
users,
|
|
156
|
-
...(
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
notice: "Sign-in to Brightspace is still in progress, so part of the roster for this " +
|
|
160
|
-
`course could not be fetched yet. ${authPendingNotice(authFailure.reason)} Call ` +
|
|
161
|
-
"get_roster again once sign-in finishes.",
|
|
162
|
-
}
|
|
163
|
-
: {}),
|
|
187
|
+
...(unavailable.length > 0 ? { unavailable } : {}),
|
|
188
|
+
...(authFailure ? { authPending: true } : {}),
|
|
189
|
+
...(notices.length > 0 ? { notice: notices.join(" ") } : {}),
|
|
164
190
|
});
|
|
165
191
|
}
|
|
166
192
|
catch (error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brightspace-mcp-server",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.33",
|
|
4
4
|
"mcpName": "io.github.RohanMuppa/brightspace",
|
|
5
5
|
"description": "MCP server for Brightspace (D2L). Check grades, due dates, assignments, announcements, syllabus, rosters and more via Claude, ChatGPT, Cursor, Windsurf, or any MCP client.",
|
|
6
6
|
"type": "module",
|