brightspace-mcp-server 5.1.23 → 5.1.24
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.
|
@@ -23,6 +23,13 @@ function richTextHtml(field) {
|
|
|
23
23
|
const nested = typeof field.Text === "object" && field.Text !== null ? field.Text.Html : null;
|
|
24
24
|
return nested ?? field.Html ?? null;
|
|
25
25
|
}
|
|
26
|
+
/** The highest Score among attempts D2L has scored, or null when none has one. */
|
|
27
|
+
function bestAttemptScore(attempts) {
|
|
28
|
+
const scores = (attempts ?? [])
|
|
29
|
+
.map((a) => a.Score)
|
|
30
|
+
.filter((score) => typeof score === "number");
|
|
31
|
+
return scores.length > 0 ? Math.max(...scores) : null;
|
|
32
|
+
}
|
|
26
33
|
/**
|
|
27
34
|
* The grade types a student is actually scored on. D2L documents exactly four
|
|
28
35
|
* GradeObject shapes, told apart by a string GradeType; anything else a
|
|
@@ -764,9 +771,9 @@ async function fetchCourseInventory(apiClient, courseId, baseUrl) {
|
|
|
764
771
|
attemptsUsed: completedAttempts?.length ?? null,
|
|
765
772
|
attemptsRemaining,
|
|
766
773
|
attemptWarning,
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
774
|
+
// An attempt awaiting manual grading carries Score null: it is not a
|
|
775
|
+
// zero, so only scored attempts count toward the best (issue #370).
|
|
776
|
+
bestScore: bestAttemptScore(completedAttempts),
|
|
770
777
|
gracePeriodMinutes: quiz.SubmissionGracePeriod ?? null,
|
|
771
778
|
hasPassword: Boolean(quiz.Password),
|
|
772
779
|
// Additive fields, each emitted only when it has something to say.
|
|
@@ -59,6 +59,13 @@ function quickLinkFilePath(input, courseId, origin) {
|
|
|
59
59
|
function enforcedFilePath(input, courseId, origin) {
|
|
60
60
|
let path = input;
|
|
61
61
|
if (!path.startsWith("/")) {
|
|
62
|
+
// Check the raw authority before URL parsing can normalize it. The first
|
|
63
|
+
// literal slash must start the path, not occur inside a query or fragment.
|
|
64
|
+
const authorityStart = path.indexOf("//") + 2;
|
|
65
|
+
const pathStart = path.indexOf("/", authorityStart);
|
|
66
|
+
if (pathStart <= authorityStart ||
|
|
67
|
+
/[?#\\\x00-\x20\x7f]/.test(path.slice(authorityStart, pathStart)))
|
|
68
|
+
return null;
|
|
62
69
|
let link;
|
|
63
70
|
try {
|
|
64
71
|
link = new URL(path);
|
|
@@ -68,7 +75,7 @@ function enforcedFilePath(input, courseId, origin) {
|
|
|
68
75
|
}
|
|
69
76
|
if (!origin || link.origin !== new URL(origin).origin || link.username || link.password)
|
|
70
77
|
return null;
|
|
71
|
-
path = path.slice(
|
|
78
|
+
path = path.slice(pathStart);
|
|
72
79
|
}
|
|
73
80
|
if (!path.startsWith(ENFORCED_PREFIX))
|
|
74
81
|
return null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brightspace-mcp-server",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.24",
|
|
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",
|