brightspace-mcp-server 3.9.10 → 3.9.12

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/README.md CHANGED
@@ -6,8 +6,6 @@
6
6
  [![License: MIT](https://img.shields.io/github/license/RohanMuppa/brightspace-mcp-server.svg)](LICENSE)
7
7
  [![Node >= 20](https://img.shields.io/node/v/brightspace-mcp-server.svg)](package.json)
8
8
 
9
- **Official repo:** github.com/RohanMuppa/brightspace-mcp-server · [npm](https://www.npmjs.com/package/brightspace-mcp-server) — forks of this README are not maintained.
10
-
11
9
  > **By [Rohan Muppa](https://github.com/rohanmuppa), ECE @ Purdue**
12
10
 
13
11
  Lets your AI see your Brightspace classes, so you can just ask:
@@ -73,25 +71,16 @@ School-specific quirks: [docs/sign-in.md](docs/sign-in.md#per-school-notes).
73
71
  | Lecture videos | "What did the professor say about pinch-off in Tuesday's recording?" (Kaltura and YouTube) |
74
72
  | Calendar | "When is my midterm?" · "Is lab cancelled on Thursday?" |
75
73
 
76
- Apps with a prompt picker (like Claude Desktop) also offer four ready-made prompts: `weekly_briefing`, `grade_audit`, `study_planner`, and `course_summary`.
77
-
78
- ## What it can do
79
-
80
- Nineteen read-only tools behind those questions. The ones worth knowing about:
74
+ ## Prompts
81
75
 
82
- - **Grades** — every course's gradebook with instructor comments, and the hidden "exam" items that only appear in the gradebook.
83
- - **Assignments** — due dates with a plain-words `dueIn` ("in 3 days"), your submissions and the feedback on them, rubric names, and quizzes with attempt counts. While sign-in is still pending it says so instead of returning an empty list.
84
- - **Rubrics** — the full criteria, levels, and points for an assignment, plus your own graded outcome per criterion when your school exposes it.
85
- - **Due dates and calendar** — upcoming deadlines from assignments, quizzes, graded discussions, and the course calendar (exams, labs, review sessions).
86
- - **Announcements** — with attachments you can read or save.
87
- - **Course content** — modules and topics as markdown, file download (PDF, Office, and more), and release windows: it tells you when something opens, has ended, or is hidden instead of a bare error.
88
- - **Search** — content, announcements, and discussions by keyword in one call.
89
- - **Lecture videos** — transcripts for Kaltura and YouTube embeds.
90
- - **People** — roster, instructor and TA emails, and your project or lab groups.
91
- - **Discussions** — forums and topics.
92
- - **Diagnostics** — `get_server_info`: version, timezone, who you're signed in as, whether Microsoft remembered your device, and request counters, all without touching Brightspace.
76
+ Apps with a prompt picker (like Claude Desktop) also offer four ready-made prompts, so you can start from one click instead of typing a question:
93
77
 
94
- Sign-in is automatic: silent renewal most days, the MFA number shown in-chat when needed, Duo and authenticator-code support, a visible-browser mode for anything else, an opt-in "remember this device" for Microsoft, and a browser-free mode (paste a session cookie or token) for Docker, WSL, and hardware-key accounts. Links in course content have D2L's session tokens stripped before they reach the AI.
78
+ | Prompt | Arguments | What it asks for |
79
+ |--------|-----------|------------------|
80
+ | `weekly_briefing` | — | A 7-day rollup of what's due, what's new, and what changed in your grades, across every course |
81
+ | `grade_audit` | `courseId` (optional) | Analyzes grades for one course, or all of them, and flags missing or low-scoring items |
82
+ | `study_planner` | `daysAhead` (optional, default 7) | Plans study time from upcoming due dates and calendar events |
83
+ | `course_summary` | `courseId` (required) | Syllabus, content outline, assignments, and grades for one course |
95
84
 
96
85
  ## Settings you might want
97
86
 
@@ -123,10 +112,6 @@ How often you're asked is up to your school, not this tool. Everything else abou
123
112
  - **Which version do I have?** Ask your AI "which version of the Brightspace server am I running?"
124
113
  - **Still stuck?** [Open an issue](https://github.com/RohanMuppa/brightspace-mcp-server/issues) and paste what the terminal printed.
125
114
 
126
- ## Is it safe?
127
-
128
- Your password is kept in your operating system's password store, never in a plain file. Saved sign-in state is encrypted. Your second factor (the phone tap or code) stays on your phone — this tool never sees or stores it. And it can only read your courses, never change them.
129
-
130
115
  ## For developers
131
116
 
132
117
  Tool reference, response fields, and environment variables: [LLMs.md](LLMs.md). What's safe to build against: [STABILITY.md](STABILITY.md). Licensed under the MIT License.
@@ -13,6 +13,14 @@ import { log } from "../utils/logger.js";
13
13
  // Discover by fetching classlist for a known course and inspecting RoleId values.
14
14
  const INSTRUCTOR_ROLE_ID = 109;
15
15
  const TA_ROLE_ID = 135;
16
+ // When the role-ID fast path above returns nothing — a non-Purdue tenant
17
+ // where those IDs belong to different roles or none at all — staff are found
18
+ // instead by matching the role name the tenant itself reports. Role-name
19
+ // fallback adapted from matthewliu10/brightspace-mcp-server (MIT).
20
+ const TEACHING_ROLE_NAME = /\b(instructor|professor|lecturer|teaching assistant|coordinator|grader|ta)\b/i;
21
+ function isTeachingRoleByName(user) {
22
+ return TEACHING_ROLE_NAME.test(user.ClasslistRoleDisplayName ?? "");
23
+ }
16
24
  /**
17
25
  * Fetch every classlist user matching the optional filters, across all pages.
18
26
  *
@@ -48,6 +56,7 @@ export function registerGetRoster(server, apiClient) {
48
56
  // Parse and validate input
49
57
  const { courseId, includeStudents, searchTerm, limit } = GetRosterSchema.parse(args);
50
58
  const allUsers = [];
59
+ let roleFallbackUsed = false;
51
60
  if (!includeStudents) {
52
61
  // Fetch instructors and TAs in parallel
53
62
  const [instructorResult, taResult] = await Promise.allSettled([
@@ -77,6 +86,20 @@ export function registerGetRoster(server, apiClient) {
77
86
  error: taResult.reason,
78
87
  });
79
88
  }
89
+ // Purdue's role IDs found nobody — on a non-Purdue tenant they
90
+ // likely mean a different role, or none. Fall back to one
91
+ // unfiltered classlist fetch and match on the role display name
92
+ // the tenant itself reports instead of an institution-specific ID.
93
+ // A genuine failure of this fetch is intentionally not caught
94
+ // here: it should surface as a tool error rather than silently
95
+ // producing an empty staff list.
96
+ if (allUsers.length === 0) {
97
+ const everyone = await fetchClasslistUsers(apiClient, courseId, {
98
+ searchTerm,
99
+ });
100
+ allUsers.push(...everyone.filter(isTeachingRoleByName));
101
+ roleFallbackUsed = true;
102
+ }
80
103
  }
81
104
  else {
82
105
  // Fetch all users
@@ -110,6 +133,11 @@ export function registerGetRoster(server, apiClient) {
110
133
  ...(truncated
111
134
  ? { note: `Showing ${users.length} of ${total}. Raise the limit argument to see more.` }
112
135
  : {}),
136
+ ...(roleFallbackUsed
137
+ ? {
138
+ roleFilter: "No users matched the default instructor/TA role IDs, so staff were found by matching role display names (instructor, professor, lecturer, teaching assistant, coordinator, grader, TA) instead.",
139
+ }
140
+ : {}),
113
141
  users,
114
142
  });
115
143
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brightspace-mcp-server",
3
- "version": "3.9.10",
3
+ "version": "3.9.12",
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",