Public log

brightspace-mcp-server

MCP server for Brightspace (D2L). Check grades, due dates, assignments, announcements, syllabus, rosters and more via Claude, ChatGPT, Cursor, Windsurf, or any MCP client.

npm · fingerprint 0900b0cc43ee6381555554c8 · repository · RSS

26tools
8recorded versions
24dtracked
unchanged 10d

What changed

Changed 2026-10-20 11:19 UTC

1 description rewritten.

--- pinned/get_server_info
+++ observed/get_server_info
  {
    "annotations": {
      "readOnlyHint": true
-   "description": "Report which version of the Brightspace MCP server is running, the Node.js runtime, platform, config file path, session state directory, configured school URL, whether a credential is stored, the server's local timezone and UTC offset, (once a browser sign-in has been saved) what Microsoft remembered: stay-signed-in and the Don't ask again MFA checkbox, (when signed in) the account's uniqueName/displayName as signedInAs, and this process's request counters (requests: responses by status class, network errors, cache hits/misses, coalesced joins, and token refreshes). Use this for troubleshooting, when the user asks which version they have, or what timezone/account dates are being computed against. Never contacts Brightspace and never returns secrets.",
+   "description": "Report which version of the Brightspace MCP server is running, the Node.js runtime, platform, config file path, session state directory, configured school URL, whether a credential is stored, the server's local timezone and UTC offset, (once a browser sign-in has been saved) what Microsoft remembered: stay-signed-in (which keeps the Microsoft sign-in but does not by itself skip 2FA) and the Don't ask again MFA checkbox, with a plain-language note on what that means for 2FA to relay to the user, (when signed in) the account's uniqueName/displayName as signedInAs, and this process's request counters (requests: responses by status class, network errors, cache hits/misses, coalesced joins, and token refreshes). Use this for troubleshooting, when the user asks which version they have, or what timezone/account dates are being computed against. Never contacts Brightspace and never returns secrets.",
    "execution": {
      "taskSupport": "forbidden"
    },

Changed 2026-10-18 10:49 UTC

1 description rewritten.

--- pinned/download_file
+++ observed/download_file
  {
-   "description": "Download a file from course content, instructor assignment attachments (source: assignmentAttachment with folderId + fileId), assignment submissions, or an announcement's attachments. Use this when the user wants a file from Brightspace course content, dropbox submissions, or an announcement (newsId + fileId, from get_announcements). Two response modes: (1) INLINE (default — omit downloadPath): the file comes back directly in the tool response — extracted text for PDFs and Office documents, an image block for jpeg/png/gif/webp, or a short description for anything else — so it can be read immediately without touching any filesystem. This is the right choice in clients like Claude Desktop, whose analysis/sandbox tools cannot see a file the MCP server writes to its own host filesystem. (2) DISK (set downloadPath to an absolute path on the HOST filesystem the MCP server runs on): the file is saved there. Ask the user where to save it before using disk mode — never guess a directory. After identifying the file, suggest a clean readable filename (e.g., 'Lecture 7 - Memory Management.pdf' instead of 'L07_CS251_2026SP_v2.pdf') and pass it as customFilename, or omit it to keep the original. If a content-topic download fails because the file isn't released yet, the response explains why when Brightspace's module/topic metadata supports it (not yet open, ended, locked, or hidden).",
+   "description": "Download a file from course content, files linked by path inside a module description (coursePath, from get_course_content's quickLink URLs with type=coursefile), instructor assignment attachments (source: assignmentAttachment with folderId + fileId), assignment submissions, or an announcement's attachments. Use this when the user wants a file from Brightspace course content, dropbox submissions, or an announcement (newsId + fileId, from get_announcements). Two response modes: (1) INLINE (default — omit downloadPath): the file comes back directly in the tool response — extracted text for PDFs and Office documents, an image block for jpeg/png/gif/webp, or a short description for anything else — so it can be read immediately without touching any filesystem. This is the right choice in clients like Claude Desktop, whose analysis/sandbox tools cannot see a file the MCP server writes to its own host filesystem. (2) DISK (set downloadPath to an absolute path on the HOST filesystem the MCP server runs on): the file is saved there. Ask the user where to save it before using disk mode — never guess a directory. After identifying the file, suggest a clean readable filename (e.g., 'Lecture 7 - Memory Management.pdf' instead of 'L07_CS251_2026SP_v2.pdf') and pass it as customFilename, or omit it to keep the original. If a content-topic download fails because the file isn't released yet, the response explains why when Brightspace's module/topic metadata supports it (not yet open, ended, locked, or hidden).",
    "execution": {
      "taskSupport": "forbidden"
    },
+       "coursePath": {
+         "description": "A file in the course's file store, for files an instructor linked inside a module or page description instead of adding as a content topic (get_course_content lists them as courseFiles on the module). Pass one of those paths (e.g. 'Notes/Lecture 1.pdf') or the whole quickLink URL. Not combined with topicId, folderId, or newsId.",
+         "maxLength": 1024,
+         "minLength": 1,
+         "type": "string"
+       },
        "customFilename": {
          "description": "Custom filename for the downloaded file (include extension). If not provided, uses the original filename from Brightspace.",
          "maxLength": 255,

Changed 2026-10-14 11:41 UTC

1 description rewritten.

--- pinned/get_assignments
+++ observed/get_assignments
  {
    "annotations": {
      "readOnlyHint": true
-   "description": "Fetch assignments and quizzes for a specific course or all enrolled courses. Shows dropbox submissions and quizzes with due dates, status, and rubric info. Use this when the user asks about assignments, homework, what to submit, quizzes, or assignment details and rubrics. Read submissionStatus/attemptStatus, not just submission/attemptsUsed, to decide whether something was turned in: some tenants deny students access to submission or attempt data, in which case the status is \"unknown\" even though submission is null or attemptsUsed is 0. Never report an \"unknown\" item as missing, unsubmitted, or not attempted - say it could not be verified and point the user to Brightspace.",
+   "description": "Fetch assignments and quizzes for a specific course or all enrolled courses. Shows dropbox submissions and quizzes with due dates, status, and rubric info. Use this when the user asks about assignments, homework, what to submit, quizzes, or assignment details and rubrics. Read submissionStatus/attemptStatus, not just submission/attemptsUsed, to decide whether something was turned in: some tenants deny students access to submission or attempt data, in which case the status is \"unknown\" even though submission is null or attemptsUsed is 0. Never report an \"unknown\" item as missing, unsubmitted, or not attempted - say it could not be verified and point the user to Brightspace. Quizzes come from the quiz list, the course content, and the gradebook; each quiz row says which in source. A quiz with id null was found only as a content topic. A quiz row with detailsStatus \"unavailable\" was shown in the course content but Brightspace would not return its details (it may be closed, not yet open, or limited to certain students), so its dates and attempts may be missing: point the user to its link. availability (notYetOpen, open, closed) is worked out from the quiz's own start and end dates and is left out when it has none. exempt: true means Brightspace marks the user exempt from that quiz's topic; the quiz is still listed. Each course also carries quizCoverage. \"complete\" means every quiz source answered, not that every quiz is guaranteed to be listed; \"incomplete\" means a quiz source could not be read, so the course may have quizzes not listed. Never conclude that a quiz was missed or not taken because it is absent, and never present the listed quizzes as all of them. A gradeOnly row named like a quiz is a quiz whose details could not be read.",
    "execution": {
      "taskSupport": "forbidden"
    },

Changed 2026-10-13 14:00 UTC

2 descriptions rewritten.

--- pinned/get_announcements
+++ observed/get_announcements
  {
    "annotations": {
      "readOnlyHint": true
-   "description": "Fetch announcements from one course with courseId, or all courses when omitted, newest first. count is 1-50 per page. Continue with offset= pagination.nextOffset until it is null. Pagination metadata is in a separate JSON text block for array responses, or the pagination field with modifiedSince. A false coverageComplete means some courses were not fetched: retry from offset 0 after recovery. Offsets reflect the current filtered list; new posts can shift pages. Attachments are listed per announcement; fetch them with download_file (newsId + fileId) or read them with get_announcement_files.",
+   "description": "Fetch announcements from one course with courseId, or all courses when omitted, newest first. count is 1-50 per page. Each body is the full announcement text as markdown (links kept); pagination.truncated only means more announcements remain, never that a body was cut. Continue with offset= pagination.nextOffset until it is null. Pagination metadata is in a separate JSON text block for array responses, or the pagination field with modifiedSince. A false coverageComplete means some courses were not fetched: retry from offset 0 after recovery. Offsets reflect the current filtered list; new posts can shift pages. Attachments are listed per announcement; fetch them with download_file (newsId + fileId) or read them with get_announcement_files.",
    "execution": {
      "taskSupport": "forbidden"
    },
--- pinned/get_dropbox_feedback
+++ observed/get_dropbox_feedback
  {
    "annotations": {
      "readOnlyHint": true
-   "description": "Retrieve the existing feedback already saved for a specific user or group in a dropbox folder, for an instructor or TA — score, graded state, feedback text, and rubric assessment detail. Use this before drafting new feedback to see what has already been recorded. Requires instructor or TA access to the course.",
+   "description": "Retrieve the feedback saved for a dropbox folder — score, graded state, feedback text, and rubric assessment detail. Students: omit entityType and entityId to read your OWN released feedback on an assignment (it is not hidden; use this when get_assignments shows feedback unavailable). Instructors and TAs: pass entityType and entityId to read what is already saved for any user or group, e.g. before drafting new feedback; reading another user's feedback requires instructor or TA access to the course.",
    "execution": {
      "taskSupport": "forbidden"
    },
-         "description": "User ID or group ID whose existing feedback to retrieve.",
+         "description": "User ID or group ID whose existing feedback to retrieve. Omit to read the signed-in user's own feedback.",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991,
          "type": "integer"
-         "description": "Whether entityId identifies an individual user or a group.",
+         "description": "Whether entityId identifies an individual user or a group. Omit both entityType and entityId to read your own feedback.",
          "enum": [
            "user",
            "group"
-       "folderId",
-       "entityType",
-       "entityId"
+       "folderId"
      ],
      "type": "object"
    },

Changed 2026-10-12 15:08 UTC

1 tool added.

+ tool added: sign_out

Changed 2026-10-11 12:34 UTC

22 schema or annotation changes with the description left byte-identical.

--- pinned/get_announcement_files
+++ observed/get_announcement_files
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Read the files an instructor attached to an announcement: prompt questions, a rubric, an updated schedule, slides. Call it with just courseId to see which announcements have attachments, then with newsId and fileId to read one. Use this when the user asks what a file attached to an announcement says. Returns the text itself. Use download_file (newsId + fileId) instead when the user wants the file saved to disk.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_announcements
+++ observed/get_announcements
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Fetch announcements from one course with courseId, or all courses when omitted, newest first. count is 1-50 per page. Continue with offset= pagination.nextOffset until it is null. Pagination metadata is in a separate JSON text block for array responses, or the pagination field with modifiedSince. A false coverageComplete means some courses were not fetched: retry from offset 0 after recovery. Offsets reflect the current filtered list; new posts can shift pages. Attachments are listed per announcement; fetch them with download_file (newsId + fileId) or read them with get_announcement_files.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_assignment_files
+++ observed/get_assignment_files
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Read the files an instructor attached to an assignment: the spec or instructions PDF, a starter workbook, a rubric document. Call it with just courseId to see which assignments have attachments, then with folderId and fileId to read one. Use this when the user asks what an assignment requires, what the instructions say, or to summarize a handout. Returns the text itself. Use download_file instead when the user wants the file saved to disk.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_assignment_rubric
+++ observed/get_assignment_rubric
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Fetch the full grading rubric for a dropbox assignment: every criteria group, criterion, and achievement level with its points and description, plus the student's own graded outcome per criterion once it has been released. Use this when the user asks what a rubric wants, how an assignment will be graded, or why they got a particular score on a criterion.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_assignments
+++ observed/get_assignments
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Fetch assignments and quizzes for a specific course or all enrolled courses. Shows dropbox submissions and quizzes with due dates, status, and rubric info. Use this when the user asks about assignments, homework, what to submit, quizzes, or assignment details and rubrics. Read submissionStatus/attemptStatus, not just submission/attemptsUsed, to decide whether something was turned in: some tenants deny students access to submission or attempt data, in which case the status is \"unknown\" even though submission is null or attemptsUsed is 0. Never report an \"unknown\" item as missing, unsubmitted, or not attempted - say it could not be verified and point the user to Brightspace.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_calendar_events
+++ observed/get_calendar_events
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Fetch course calendar events — exams, midterms, labs, recitations, review sessions, schedule changes, and deadlines instructors typed straight onto the calendar — across all your courses or one course, in a time window (default: the next 7 days). Use this when the user asks when an exam is, what's on their calendar, or what's happening this week.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_classlist_emails
+++ observed/get_classlist_emails
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Fetch all email addresses for everyone in a course — instructors, TAs, and students. Use this when the user wants a list of emails for a class, needs to email the whole class, or wants contact info for everyone enrolled.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_course_content
+++ observed/get_course_content
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Fetch the content tree for a course showing modules, topics, files, and links. Use this when the user asks about course materials, lecture slides, uploaded files, content structure, or what's in a course module. Use moduleTitle to filter to a specific module (e.g. 'Labs', 'Staff', 'Homeworks') instead of fetching the entire tree. Use maxDepth to limit recursion depth for a table-of-contents view. A module or topic that isn't currently available carries isAvailable/availabilityStatus/availabilityMessage (and startDate/endDate when known) explaining why; absence of these fields means it's available now.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_discussions
+++ observed/get_discussions
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Fetch discussion board content for a course including forums, topics, and posts. Use this when the user asks about discussion boards, forum posts, class discussions, or wants to see what's been posted. Provide just courseId to list all forums and their topics. Add forumId to get topics and posts for a specific forum. Add both forumId and topicId to get all posts in a specific discussion topic.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_dropbox_feedback
+++ observed/get_dropbox_feedback
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Retrieve the existing feedback already saved for a specific user or group in a dropbox folder, for an instructor or TA — score, graded state, feedback text, and rubric assessment detail. Use this before drafting new feedback to see what has already been recorded. Requires instructor or TA access to the course.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_dropbox_folders
+++ observed/get_dropbox_folders
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "List all assignment/dropbox folders for a course, for an instructor or TA. Returns folder ID, name, due date, start/end dates, submission type, visibility, and whether rubrics are attached. Use this to discover folderId values before calling get_dropbox_submissions, get_dropbox_user_submissions, get_dropbox_feedback, or get_rubrics_for_object. This reads the same folder listing a student's own client uses, so it is not gated to instructor/TA accounts the way get_dropbox_submissions, get_dropbox_feedback, and download_dropbox_submission_file are.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_dropbox_submissions
+++ observed/get_dropbox_submissions
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "List every student's (or group's) submission to a dropbox folder, for an instructor or TA — submitter names, submission dates, late status, file lists, and feedback/grading status. Use get_dropbox_folders first to find folderId. Requires instructor or TA access; a student account gets a clear note instead of data (a student's own download_file / get_assignments already cover their own submission). Results are capped by limit (default 100, max 1000); a truncated response says so and only fetches feedback for the returned slice.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_dropbox_user_submissions
+++ observed/get_dropbox_user_submissions
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Retrieve all submissions made by one specific student (or group) in a dropbox folder, for an instructor or TA — useful for reviewing a single student's work before drafting feedback. Use get_dropbox_submissions or get_roster to find the userId first. Requires instructor or TA access to the course.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_my_courses
+++ observed/get_my_courses
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Fetch your enrolled Brightspace courses with names, codes, and IDs. Use this when the user asks about their courses, enrolled classes, what they're taking this semester, or needs a course ID for other queries.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_my_grades
+++ observed/get_my_grades
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Fetch your grade breakdown for a specific course or all enrolled courses. Shows grade items with points, percentages, and comments. Use this when the user asks about grades, scores, marks, GPA, academic performance, or how they're doing in a class.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_my_groups
+++ observed/get_my_groups
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "List the current user's project/discussion groups in a course, with each group's members. Use this when a student asks who is in their project group, lab group, or discussion group.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_roster
+++ observed/get_roster
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Fetch the roster for a course including instructors, TAs, and optionally students with their names, emails, and roles. Use this when the user asks about classmates, instructor contact info, TA emails, professor names, or who's in a class. By default returns only instructors and TAs for privacy. Use includeStudents to get full class list.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_rubrics_for_object
+++ observed/get_rubrics_for_object
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Retrieve the full rubric table (criteria, levels, and point values) attached to a dropbox folder, for an instructor or TA. Use get_dropbox_folders first to find folderId. Like get_dropbox_folders, this reads the folder listing's embedded rubric data, so it is not gated to instructor/TA accounts the way get_dropbox_submissions and get_dropbox_feedback are.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_server_info
+++ observed/get_server_info
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Report which version of the Brightspace MCP server is running, the Node.js runtime, platform, config file path, session state directory, configured school URL, whether a credential is stored, the server's local timezone and UTC offset, (once a browser sign-in has been saved) what Microsoft remembered: stay-signed-in and the Don't ask again MFA checkbox, (when signed in) the account's uniqueName/displayName as signedInAs, and this process's request counters (requests: responses by status class, network errors, cache hits/misses, coalesced joins, and token refreshes). Use this for troubleshooting, when the user asks which version they have, or what timezone/account dates are being computed against. Never contacts Brightspace and never returns secrets.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_upcoming_due_dates
+++ observed/get_upcoming_due_dates
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Fetch upcoming due dates across all your courses, derived from the due dates on assignments (dropbox folders), quizzes, and graded discussion topics themselves, plus course calendar events such as exams and labs (type: event). Use this when the user asks about deadlines, what's due, upcoming work, or what they need to do this week.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/get_video_transcript
+++ observed/get_video_transcript
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Read the transcript of a video embedded in course content, such as a recorded lecture or explainer clip. Call it with courseId and topicId from get_course_content (typeFilter: 'video' or 'other'), or with videoUrl directly if you already have the link. Returns transcript text with timestamps, plus title and duration when available. Currently supports Kaltura (e.g. BoilerCast, including its Brightspace LTI links) and YouTube; other platforms return a clear message naming what isn't supported yet. Each call returns at most maxChars characters (up to 100000); to read a whole transcript, call again with offset set to the returned nextOffset until truncated is false. Read only — this never marks the video as watched.",
    "execution": {
      "taskSupport": "forbidden"
--- pinned/search_course
+++ observed/search_course
  {
+   "annotations": {
+     "readOnlyHint": true
+   },
    "description": "Search a course's content (modules, topics, file names), announcements, and discussion forums/topics by keyword in a single call, instead of reading the whole content tree. Use this when the user wants to find something specific, e.g. 'find the midterm review slides' or 'did anyone post about office hours'. Results are ranked: a result matching every query term ranks above one matching only some, and within that, a match in the title ranks above one only in the body text. If one source (e.g. discussions) can't be read, it's skipped and named in `note` rather than failing the whole search. This fans out over the entire content tree, announcements, and every discussion forum, so it can be slower than calling a single tool like get_course_content directly.",
    "execution": {
      "taskSupport": "forbidden"

Changed 2026-10-06 13:11 UTC

3 descriptions rewritten.

--- pinned/download_file
+++ observed/download_file
  {
-   "description": "Download a file from course content, assignment submissions, or an announcement's attachments. Use this when the user wants a file from Brightspace course content, dropbox submissions, or an announcement (newsId + fileId, from get_announcements). Two response modes: (1) INLINE (default — omit downloadPath): the file comes back directly in the tool response — extracted text for PDFs and Office documents, an image block for jpeg/png/gif/webp, or a short description for anything else — so it can be read immediately without touching any filesystem. This is the right choice in clients like Claude Desktop, whose analysis/sandbox tools cannot see a file the MCP server writes to its own host filesystem. (2) DISK (set downloadPath to an absolute path on the HOST filesystem the MCP server runs on): the file is saved there. Ask the user where to save it before using disk mode — never guess a directory. After identifying the file, suggest a clean readable filename (e.g., 'Lecture 7 - Memory Management.pdf' instead of 'L07_CS251_2026SP_v2.pdf') and pass it as customFilename, or omit it to keep the original. If a content-topic download fails because the file isn't released yet, the response explains why when Brightspace's module/topic metadata supports it (not yet open, ended, locked, or hidden).",
+   "description": "Download a file from course content, instructor assignment attachments (source: assignmentAttachment with folderId + fileId), assignment submissions, or an announcement's attachments. Use this when the user wants a file from Brightspace course content, dropbox submissions, or an announcement (newsId + fileId, from get_announcements). Two response modes: (1) INLINE (default — omit downloadPath): the file comes back directly in the tool response — extracted text for PDFs and Office documents, an image block for jpeg/png/gif/webp, or a short description for anything else — so it can be read immediately without touching any filesystem. This is the right choice in clients like Claude Desktop, whose analysis/sandbox tools cannot see a file the MCP server writes to its own host filesystem. (2) DISK (set downloadPath to an absolute path on the HOST filesystem the MCP server runs on): the file is saved there. Ask the user where to save it before using disk mode — never guess a directory. After identifying the file, suggest a clean readable filename (e.g., 'Lecture 7 - Memory Management.pdf' instead of 'L07_CS251_2026SP_v2.pdf') and pass it as customFilename, or omit it to keep the original. If a content-topic download fails because the file isn't released yet, the response explains why when Brightspace's module/topic metadata supports it (not yet open, ended, locked, or hidden).",
    "execution": {
      "taskSupport": "forbidden"
    },
-         "description": "Specific file ID within a dropbox submission, or an announcement attachment's file ID (with newsId).",
+         "description": "Specific file ID within a dropbox submission, instructor assignment attachment (with source: assignmentAttachment), or announcement attachment (with newsId).",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991,
          "type": "integer"
-         "description": "Dropbox folder ID (for submission/feedback file downloads).",
+         "description": "Dropbox folder ID. Downloads your submission by default; set source to assignmentAttachment for an instructor-provided handout.",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991,
          "type": "integer"
+       "source": {
+         "description": "For folderId + fileId: assignmentAttachment downloads an instructor-provided handout from get_assignment_files; submission (default) downloads your own submitted file. Do not combine source with topicId or newsId.",
+         "enum": [
+           "submission",
+           "assignmentAttachment"
+         ],
+         "type": "string"
+       },
        "topicId": {
          "description": "Content topic ID to download (for course content files).",
          "exclusiveMinimum": 0,
--- pinned/get_announcements
+++ observed/get_announcements
  {
-   "description": "Fetch recent announcements from your courses. Can filter to a specific course or get announcements across all courses. Use this when the user asks about announcements, news, updates from instructors, recent posts, or what professors said. Attachments are listed per announcement; fetch them with download_file (newsId + fileId) or read them with get_announcement_files.",
+   "description": "Fetch announcements from one course with courseId, or all courses when omitted, newest first. count is 1-50 per page. Continue with offset= pagination.nextOffset until it is null. Pagination metadata is in a separate JSON text block for array responses, or the pagination field with modifiedSince. A false coverageComplete means some courses were not fetched: retry from offset 0 after recovery. Offsets reflect the current filtered list; new posts can shift pages. Attachments are listed per announcement; fetch them with download_file (newsId + fileId) or read them with get_announcement_files.",
    "execution": {
      "taskSupport": "forbidden"
    },
-         "description": "Maximum number of announcements to return, newest first (1-50, default 10). There is no pagination or offset: when more announcements exist than count, only the newest are returned. To get fuller coverage, call once per course with courseId so courses do not compete for the same slots, and use modifiedSince to return only announcements changed since a cutoff.",
+         "description": "Announcements per page: 1-50 (default 10).",
          "maximum": 50,
          "minimum": 1,
          "type": "integer"
+       },
+       "offset": {
+         "default": 0,
+         "description": "Announcement offset after filtering and sorting. Continue with pagination.nextOffset; restart at 0 after a failed course becomes available.",
+         "maximum": 9007199254740991,
+         "minimum": 0,
+         "type": "integer"
        }
      },
      "type": "object"
--- pinned/get_syllabus
+++ observed/get_syllabus
  {
-   "description": "Fetch the syllabus/overview text and optional attachment for a course. Returns the course overview description as markdown. When the syllabus lives in an external LTI tool (e.g. Simple Syllabus), lists those sources in externalSyllabusSources; their contents cannot be read. If downloadPath is provided, also downloads the syllabus attachment (e.g. PDF). IMPORTANT: You MUST ask the user where they want to save the file before calling this tool with a downloadPath.",
+   "description": "Fetch the syllabus/overview text and optional attachment for a course. Returns the course overview description as markdown. When the syllabus lives in an external LTI tool (e.g. Simple Syllabus), lists those sources in externalSyllabusSources; their contents cannot be read. If some of those lookups could not be completed (e.g. permission denied), externalSyllabusDiscovery says which, and an empty result is then not proof the course has no syllabus. If downloadPath is provided, also downloads the syllabus attachment (e.g. PDF). IMPORTANT: You MUST ask the user where they want to save the file before calling this tool with a downloadPath.",
    "execution": {
      "taskSupport": "forbidden"
    },

Current tools

Show all 26 tool fingerprints
download_dropbox_submission_file
7548a0809a2e5c89
download_file
91d520821ab3a279
get_announcement_files
4f79728fc5e109b4
get_announcements
cf6810f88ca65be9
get_assignment_files
f841a63a36ad6e35
get_assignment_rubric
7ab46a041c0e23ba
get_assignments
c014ab6c138cdc7b
get_calendar_events
59e966043a824042
get_classlist_emails
54a7805719804725
get_course_content
146379e722745f29
get_discussions
6afc20138094fffa
get_dropbox_feedback
7ab46c735558cc83
get_dropbox_folders
b4058328f5a55f3e
get_dropbox_submissions
8fc4ed5ca9795f77
get_dropbox_user_submissions
c0bd3e6ba8388680
get_my_courses
af4ce153c5078e93
get_my_grades
a8ecc602c9088328
get_my_groups
bf265b4d26048371
get_roster
7cda7058c9ed5789
get_rubrics_for_object
1fea481182ec5dcf
get_server_info
76d0e9d357cc0de3
get_syllabus
3c916efbe57f3e64
get_upcoming_due_dates
acdc2e142c7cfb4b
get_video_transcript
9388a7024d910c0f
search_course
c84d12422ca24d38
sign_out
4d36c8cda6e0fc52

Watch this server yourself

If you run this server, put the proxy in front of it. It pins these exact fingerprints on first connect and stops the session if they move.

npx -y mcp-pin@0.2.3 -- <your brightspace-mcp-server command>

Or subscribe to this page's RSS feed to be told when it changes.

Badge

mcp-pin status badge for brightspace-mcp-server

The badge states one fact about time and nothing else. It never claims a server is safe.

[![mcp-pin](https://mcp-pin.gautamkhosla.com/badge/dc6db7bfc4bd4ff1.svg)](https://mcp-pin.gautamkhosla.com/servers/dc6db7bfc4bd4ff1.html)