blackboard-mcp
A read-only MCP server that lets an AI assistant look up a Syracuse Blackboard account's courses, work, and course materials — it can never submit, post, or change anything.
List courses — enumerate the student's visible Blackboard courses and get the course IDs every other tool needs.
Browse course content — list a course's folders, documents, files, assignments, tests, and links, optionally drilling into a specific folder.
Read announcements — per-course announcements, newest first, optionally filtered to those created/modified since a date.
See assignments and due dates — assignments/assessments merged and deduplicated from content, gradebook, and calendar, scopable by course and due-date window, with optional submitted/graded status.
Check grades — the student's own scores, points possible, percentages, feedback, and grading status for a course.
Plan upcoming work — everything due across all courses within the next 1–90 days (default 7), sorted by due date.
Catch up on recent activity — announcements, new or changed content, changed assignments, and newly posted grades since a point in time (default: last 7 days).
Get the full picture for one assignment — instructions, due date, points, rubric, attachments with local file paths, grade/status, and related announcements in a single call.
Download attachments — pull a course file (PDF, DOCX, PPTX, images, text, etc.) to the local machine and return its path, with a text excerpt for small text files.
Read professor-posted links (per the README) — extract content from Google Docs/Sheets/Slides, Drive files, Colab notebooks, Kaltura/Zoom/Panopto media, and other posted pages.
All tools are read-only and stay on the student's own machine; known gaps include discussion boards, course messages, quizzes, journals, attendance, and outside tools like Gradescope or McGraw Hill.
Allows reading content from Google Docs, Sheets, and Colab notebooks linked in Blackboard courses, including handling Google sign-in for private files where possible.
Retrieves metadata for YouTube videos linked in Blackboard courses, such as title, channel, length, and description. Transcripts are not available because YouTube blocks automated access.
Recognizes Zoom links posted in Blackboard courses and can open Zoom recordings after sign-in. Live Zoom meetings are recognized but never opened.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@blackboard-mcpWhat do I have due this week?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Blackboard for Claude
Ask Claude about your own Blackboard and get real answers: what's due, your grades, what your professors posted, and what's inside the files and links they share (PDFs, slides, Google Docs and Sheets, Colab notebooks, SU videos, and more).
It only sees what you can already see, and it can never submit, post, or change anything.

Install (about 5 minutes, one time)
Works on a Mac or a Windows PC. Four steps:
Get Claude Desktop. Download it from claude.ai/download, install it, open it, and sign in. (It's free for Syracuse students.)
Download this file: blackboard-mcp.mcpb It goes into your Downloads folder.
Open your Downloads folder and double-click
blackboard-mcp.mcpb. Claude opens a screen called Blackboard (Syracuse).Click the black Install button. You will see a red box saying the extension "has not been verified by Anthropic" and can access your computer. That is normal for any tool not made by Anthropic itself; this one is a student project. It only reads your Blackboard and the links your professors post, and it never submits or changes anything.
That's it. The tool also needs Google Chrome or Microsoft Edge on your computer. Windows already has Edge, and most Macs already have Chrome. If yours doesn't, Claude will tell you and link you to the free Chrome download.
Double-click didn't open Claude? In Claude, open Settings, click Extensions, and drag
blackboard-mcp.mcpbfrom your Downloads folder into that window.
Related MCP server: canvas-scholar-mcp
The first time you use it
In Claude, ask: "What do I have due this week?"
A new browser window opens with a red banner across the top. It may open behind Claude: if you don't see it, look for a new browser icon in your Dock (Mac) or taskbar (Windows) and click it.
Sign in there with your NetID and approve Duo, like you always do. The window closes by itself when you're done.
Ask your question again.
You're done. You only sign in again when Blackboard logs you out, and when that happens the same red-banner window pops up by itself.
Your password and Duo codes go only into that browser window. Claude never sees them, and this tool never saves them.
Things you can ask
"What's due in the next 7 days?"
"Anything new in my classes this week?"
"What are my grades in Oceanography?"
"Pull up the HW 3 assignment: instructions and attached files."
"Summarize the Week 3 lecture slides."
"What's in the Google Sheet my professor linked in the last announcement?"
"Read the Colab notebook for Lab 0 and explain the first exercise."
Some links need you to be signed in to that site (for example a private Google file or a Zoom recording). When that happens, a red-banner window opens on the link. Sign in there, close that tab, and ask again.
What it can't see
If an answer is missing something, Claude will tell you in that answer, and tell you what to do instead. The known gaps:
Discussion boards, course messages, quiz and test questions, journals, groups, attendance. Not read at all. Open Blackboard for these.
Outside tools launched from Blackboard (McGraw Hill Connect, Gradescope, and similar). Their work and deadlines live in that tool, not in Blackboard.
Deadlines that exist only in class or in a syllabus file. "What's due" only knows what is posted in Blackboard. Ask it to read the syllabus file if you want those too.
YouTube transcripts. YouTube refuses to give transcripts to automated tools, so you get the video's title, channel, length and description. To get the transcript yourself: open the video, click "...more" under it, click "Show transcript", and paste it into the chat.
Live Zoom meetings. A class or office-hours link is recognised but never opened.
Some grades. Only grades your instructor has released are visible. "What's new" can miss a grade entered on an older assignment; ask for a course's grades to be sure.
Google sign-in may be refused. Google sometimes blocks sign-in from automated browser windows. If that happens, ask the professor to share the file as "anyone with the link".
Links from outside your courses. It only opens links a professor posted in one of your courses (see Safety below).
If something goes wrong
What you see | What to do |
Claude doesn't seem to know about Blackboard | Quit Claude completely and open it again (Mac: Cmd + Q. Windows: right-click the Claude icon near the clock and choose Quit). Then check Settings → Extensions shows Blackboard turned on. |
"Sign in in the window with the red banner" | Find that window (it may be behind Claude), sign in with your NetID and Duo, and ask again. |
"This computer has neither Google Chrome nor Microsoft Edge" | Install Google Chrome (free), then ask again. |
"Blackboard is already open in another app" | Another app (like Claude Code) is using Blackboard. Wait a few minutes, or quit that app. |
A course looks empty | Courses from past terms are locked by the university. New courses may have nothing posted yet. |
Something else | Ask again. Blackboard has short hiccups sometimes. |
Update, remove, and privacy
Update: download the file again and double-click it.
Remove: in Claude, open Settings → Extensions, find Blackboard, and remove it.
Erase your login: delete the
.blackboard-mcpfolder in your home folder. It holds your sign-in and any course files it downloaded, and nothing else. Never share that folder.Everything stays on your computer. Nothing is sent anywhere except to Blackboard and the sites your professors link to.
Only your courses' links. It only opens links a professor posted in one of your courses. A web page can hide instructions aimed at the AI; this rule means such a page can never send the AI, or your data, somewhere else. Links to your own computer or home network are refused.
Being a good citizen
Use it for yourself, at a human pace, and check the university's acceptable-use policy before using any automation with your student account. Not affiliated with or endorsed by Syracuse University or Anthology/Blackboard.
Using Claude Code, or setting it up by hand
You need Node.js 22 or newer and git. Then:
Mac
git clone https://github.com/alanwtom/blackboard-mcp.git ~/blackboard-mcp
cd ~/blackboard-mcp
npm run setupWindows (PowerShell)
git clone https://github.com/alanwtom/blackboard-mcp.git ~\blackboard-mcp
cd ~\blackboard-mcp
npm run setupnpm run setup checks for a browser (and offers to download one), connects Claude Desktop and
Claude Code, and opens the sign-in window. To update later: git pull, then npm run setup.
If you already installed the one-click extension, don't also connect Claude Desktop here, or Blackboard will show up twice.
Other commands: npm run login (sign in again), npm run status, npm run courses,
npm run connect -- google (sign in to a site for links), and npm run logout.
Doing every step by hand instead:
Install what it needs (the project comes ready-built, so there is nothing to compile)
npm install --omit=devLog in to Blackboard
npm run loginA browser window opens with a red banner. Sign in with your NetID and approve Duo there. When you land back on Blackboard, the window closes by itself.
Check that it worked
npm run coursesConnect your AI app
For Claude Desktop: open Settings, then Developer, then Edit Config, and add this block inside the outer braces.
On macOS the config lives at ~/Library/Application Support/Claude/claude_desktop_config.json:
"mcpServers": {
"blackboard": {
"command": "node",
"args": ["/Users/yourname/blackboard-mcp/dist/index.js"]
}
}On Windows it lives at %APPDATA%\Claude\claude_desktop_config.json:
"mcpServers": {
"blackboard": {
"command": "C:\\Program Files\\nodejs\\node.exe",
"args": ["C:\\Users\\yourname\\blackboard-mcp\\dist\\index.js"]
}
}Two Windows details matter: every backslash has to be doubled (that is how JSON works; a
single backslash makes the file invalid), and giving the full path to node.exe avoids the
common case where an app launched from the Start menu cannot find node by itself. To print
the two paths you need, run this from the project folder:
(Get-Command node).Source; "$PWD\dist\index.js"On macOS, to print both paths, run this from the project folder:
which node; echo "$PWD/dist/index.js"If Claude Desktop shows no tools even after a full restart, put the which node output in
place of "node" above: an app opened from Finder does not always inherit the PATH your
Terminal has, which is most likely when Node came from nvm or Homebrew.
Save the file, quit Claude Desktop completely (Cmd + Q on a Mac; on Windows right-click the tray icon and choose Quit), and reopen it.
For Claude Code on macOS, run:
claude mcp add --scope user blackboard -- "$(which node)" /path/to/blackboard-mcp/dist/index.jsFor Claude Code on Windows, run this from the project folder:
claude mcp add --scope user blackboard -- "$((Get-Command node).Source)" "$PWD\dist\index.js"For the technically curious
Stack: TypeScript (ESM), Node 22+, Playwright driving Chrome, else Edge, else a downloaded Chromium (remembered per machine, one dedicated profile folder per browser), MCP TypeScript SDK over stdio, Zod, Vitest.
Data access: Blackboard Learn REST API, called as same-origin requests from a page on the Blackboard host, so requests match what the Ultra web app itself sends. Both
blackboard.syr.eduandblackboard.syracuse.edu(separate cookie domains) are supported.Session resilience: Learn's session cookie does not survive a browser restart, so the authenticated cookie set is snapshotted to
~/.blackboard-mcp/browser-state.json(mode 0600 where the OS honours POSIX modes; on Windows the per-user ACL onC:\Users\<name>does that job) and restored on launch. While the institution SSO session lasts, the SAML entry is followed silently to re-authenticate with no interaction.Endpoints (verified against Syracuse, Aug 2026):
users/me,users/{id}/courses?expand=course, course contents (flat listings withparentId; file data oncontentHandler.file), course announcements,calendars/items, and the v2 gradebook (columns,columns/{id}/users/me; due dates atgrading.due, points atscore.possible). Paging caps at 100. Attachment downloads follow the item'srel=alternate/ultra/redirectlink.Tools:
list_courses,get_course_content,get_announcements,get_assignments,get_grades,get_attachment,get_upcoming_work,get_recent_updates,get_assignment_context,read_link. All read-only. Errors are short coded messages with sensitive values masked. Long texts come back in pages (offset/next_offset).Links: every content item, announcement and assignment carries a
linkslist (anchors, iframes and plain-text URLs in its HTML, classified by service).read_linkopens one through the same dedicated browser: Google exports (docx/xlsx/pptx), Drive downloads and folder listings, Colab via Drive, Kaltura captions captured from the player, Zoom recording transcripts from the player's info API (not yet verified against a real recording), Panopto SRT, SharePointdownload=1, GitHub raw/README, and rendered text for everything else. Only links seen in the student's own Blackboard data (plus same-site links on an opened page) are allowed; private and loopback addresses are refused on every redirect hop.File text: PDF (pdf.js via
unpdf), DOCX, PPTX with notes, XLSX with dates (viafflate), notebooks, and plain text formats, all extracted locally.Low volume: TTL caching, a 200 ms delay between pages of the same listing, hard request caps, and the shared browser closes after 5 idle minutes. Independent work (one course versus another, one gradebook column versus another) runs at most four requests deep via
mapWithConcurrency, so the request count is unchanged — they are simply no longer queued behind each other. Courses that answerPERMISSION_DENIEDare remembered for 15 minutes, which removes them from later sweeps entirely: past-term enrolments are reported as available and only refuse when their contents are asked for, and Blackboard publishes no end date to tell them apart beforehand.Configuration:
BB_BROWSER_CHANNEL,BB_HEADLESS=0,BLACKBOARD_MCP_HOME,BB_BASE_URL,BB_SSO_ENTRY_URL, andBLACKBOARD_HOSTSinsrc/blackboard/hosts.tsfor other institutions.One-click extension:
npm run bundlebuildsrelease/blackboard-mcp.mcpb(about 7 MB): the built code, runtime packages only, andextension/manifest.json. Claude Desktop runs it with its own built-in Node (24 as of Sep 2026; the manifest requires 22+). Attach it to a GitHub release under exactly that file name so the "latest" download link keeps working. With no sign-in, the server itself opens the NetID window. With no Chrome or Edge, a terminal install downloads Playwright's Chromium in the background; inside Claude Desktop (which runs extensions in its own Electron process, where spawning "node" would start the Claude app itself) the student is asked to install Chrome instead.BB_PRETEND_NO_BROWSERS=1simulates a machine with neither.Shipped build:
dist/is committed so terminal installs get only runtime packages (about 44 MB) and never compile anything. After changingsrc/, runnpm run buildand commitdist/too; a test fails if it is out of date.npm run setupremoves dev tools fromnode_modules, so runnpm installagain before developing.Development:
npm run typecheck,npm test(fully mocked),npm run build,npm start, andnpm run discover(records real Blackboard traffic while you browse, to verify endpoints).Platforms: macOS and Windows 10/11 are both supported; Linux should work but is untested. Everything OS-specific lives in
src/platform.ts(Chrome and Claude Desktop locations, PATH lookup, spawning.cmdshims). Three Windows behaviours the code handles explicitly:Downloaded file names are sanitized to Windows rules on every platform. A Blackboard file called
Week 3: Notes.pdfwould otherwise land in an NTFS alternate data stream on a file namedWeek 3— reported as a successful download the student can never open.A locked browser profile announces itself differently: Windows Chrome exits with code 21 and Playwright only sees the control pipe close, so that signature maps to
BROWSER_PROFILE_BUSYalongside the POSIXSingletonLockmessage.wherelists the extensionless npm shim ahead of the runnable.cmd, so PATH lookups prefer a PATHEXT match, and.cmdshims are spawned throughcmd.exewith quoted arguments (project paths often contain spaces).
Compatibility: built for Syracuse University Blackboard Ultra, Aug 2026. Other schools need the configuration above plus small parser checks.
License
MIT. Made for students, by a student.
Available Tools
10 toolsget_announcementsGet Blackboard course announcementsARead-only
List announcements for one Blackboard course, newest first. Optionally filter to items created or modified after a date. Links inside an announcement are listed under "links"; open one with read_link. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| since | No | ISO date (e.g. "2026-08-01") — only announcements created/modified on or after this instant. | |
| course_id | Yes | Blackboard course id from list_courses, e.g. "_26184_1" (course code also accepted). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, and the description reinforces read-only. The description adds useful structure context about the 'links' field and newest-first ordering. It doesn't disclose pagination behavior or result limits, so it's adequate but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the core purpose, followed by the optional filter then the link-handling note. Zero waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, ordering, filtering, and link navigation for a read-only list tool with full schema coverage and no output schema. Pagination/limits are unaddressed but are minor gaps for a read operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both course_id and since are fully documented in the schema. The description reiterates the date-filtering semantics but adds no syntax or format detail beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (list announcements) scoped to one Blackboard course, with ordering (newest first) and an explicit filtering option. An agent can distinguish it from siblings like get_course_content or get_assignments immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear context: filter to items created/modified after a date, and routes to read_link for opening links inside an announcement. It doesn't explicitly state when NOT to use it (e.g., across multiple courses, for content types other than announcements), so it's not a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_assignment_contextGet full assignment contextARead-only
One package describing a Blackboard assignment: instructions, due date, points, rubric (when available), attached files, links in the instructions (open them with read_link), the student’s grade and submission status, and related course announcements. Use this instead of many low-level calls. status: graded, submitted, in_progress (started or saved as a draft, NOT handed in), not_submitted, or unknown (Blackboard did not say — never treat unknown as missing work). Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| course_id | No | Required only when assignment_id is a bare content id. | |
| assignment_id | Yes | Assignment reference "ref" from get_assignments (format "<course_id>:<content_id>"), or a bare Blackboard content id. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so 'Read-only' is redundant. What the description genuinely adds is the status vocabulary: in_progress means started or saved as a draft and NOT handed in, and unknown must never be treated as missing work. That prevents a costly misinterpretation. It does not cover auth requirements, rate limits, or response size.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Content enumeration is front-loaded in the first sentence, then the status glossary, then the read-only note. Dense with no filler, though the single long opening sentence packs a lot before the agent reaches the operational status guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an aggregation tool with no output schema, the description compensates by itemizing exactly what comes back (instructions, rubric, attachments, links, grade, status, announcements) and disambiguating the status enum values. An agent needs nothing further to call it and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both parameters (course_id, assignment_id) are documented there, including the <course_id>:<content_id> format. The description adds no parameter-level detail beyond what the schema provides, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb+resource ('one package describing a Blackboard assignment') and enumerates its contents: instructions, due date, points, rubric, attachments, links, grade, submission status, announcements. An agent can immediately distinguish it from get_assignments (a list) or get_attachment (a single file).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent to prefer it over 'many low-level calls' and routes link handling to the sibling read_link by name. It gives clear usage context but stops short of stating when not to use it (e.g. when only the due date is needed, get_upcoming_work may suffice).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_assignmentsGet Blackboard assignmentsARead-only
List assignments and assessments with due dates, combined and deduplicated from Blackboard course content, the gradebook, and the calendar. Optionally scope to one course and/or a due-date window. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| course_id | No | Blackboard course id from list_courses. Omit to include all courses. | |
| due_after | No | ISO date or date-time. A bare date ("2026-09-30") means the start of that day, Syracuse time. | |
| due_before | No | ISO date or date-time. A bare date ("2026-09-30") includes that whole day, Syracuse time. | |
| include_status | No | Also resolve submitted/graded status (slower: 1-2 extra Blackboard requests per item). Status is "in_progress" for a started or saved draft that was NOT handed in, and "unknown" when Blackboard does not report an attempt either way — treat unknown as undetermined, never as missing work. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so the "Read-only" sentence is largely redundant. The description does add genuine behavioral context beyond annotations: the result is merged and deduplicated across three upstream sources, which tells the agent to expect canonicalized output rather than raw per-source records.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences: what it returns and from where, then the optional scoping, then the safety profile. Nothing is repeated and the most distinctive information (deduplication across sources) leads.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description should ideally hint at the shape of returned items (fields, ordering, status presence), which it does not. Everything needed to invoke the tool correctly is present, though, so the gap is modest.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are already fully documented, including the Syracuse-timezone semantics and the include_status cost/"unknown" caveat. The description only restates course and due-date scoping at a high level, adding no syntax the schema lacks, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("List assignments and assessments with due dates") and adds a distinctive mechanism (combined and deduplicated from course content, gradebook, and calendar) that separates it from get_course_content or get_grades. It stops short of naming the closest siblings, get_upcoming_work and get_assignment_context, so an agent must still infer the boundary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Optionally scope to one course and/or a due-date window" implies when the filters matter, but there is no explicit guidance on when to prefer this tool over get_upcoming_work or get_assignment_context, which appear to overlap. Usage is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_attachmentGet Blackboard course attachmentARead-only
Download a course file (PDF, Word, PowerPoint, Excel, notebooks, text, images, ...) from Blackboard and return its contents as text, plus the local path where it was saved (~/.blackboard-mcp/downloads). PDFs come back page by page, slides with speaker notes, spreadsheets as CSV per sheet. Long files come in pages: pass next_offset back as offset to keep reading. Nothing is sent anywhere. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| offset | No | Character offset to continue a long file (from next_offset). | |
| file_id | No | Which file, when a content item has several (a file_id or file_name from available_files). | |
| course_id | Yes | Blackboard course id from list_courses, e.g. "_26184_1" (course code also accepted). | |
| content_id | Yes | Blackboard content id from get_course_content or get_assignments, e.g. "_3001_1". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, yet the description still adds real value: the save location (~/.blackboard-mcp/downloads), per-format extraction semantics (pages, speaker notes, CSV per sheet), pagination via next_offset, and the privacy note that nothing is sent anywhere. Only 'Read-only' is redundant with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and return shape, then format specifics and pagination. Four sentences, all relevant, with no filler; slightly dense but nothing that should be cut.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the return-value burden and does so: it describes the text payload, the saved path, per-format structure, and how to continue long files. An agent can call this correctly and interpret the result without further documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so parameters are already documented; the description goes further by explaining the offset/next_offset continuation loop and the multi-file case (file_id/file_name from available_files). It adds semantics the schema cannot, though it references a 'next_offset' field not present in the input schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Download') and resource ('a course file ... from Blackboard') plus the return form (text contents + local save path). This is clearly distinguishable from siblings like read_link or get_course_content, which fetch pages/links rather than file bodies.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear operating context: the supported file types, the local path where files land, and the pagination contract ('pass next_offset back as offset to keep reading'). It never names when to prefer this over a sibling such as read_link, so it stops short of explicit alternatives/exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_course_contentGet Blackboard course contentARead-only
List a course’s content items (folders, documents, files, assignments, tests, links) from Blackboard. Hierarchy is expanded a couple of folder levels; pass folder_id to go deeper into one folder. Each item lists its "links" (Google Docs/Sheets, Zoom, YouTube, readings...): open one with read_link. Files open with get_attachment. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| course_id | Yes | Blackboard course id from list_courses, e.g. "_26184_1" (course code also accepted). | |
| folder_id | No | Content id of a folder to list instead of the course root. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation covers safety, and the description goes beyond it by disclosing the lazy-expansion behavior (only a couple folder levels returned, folder_id required for deeper traversal) plus the structure of each item's 'links' array. This is real behavioral context not present in the annotations, though it doesn't discuss result size, limits, or error cases.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with what is returned, then traversal mechanics, then next-step tools. Every sentence earns its place with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description still conveys the shape of returned items and their links, and points to read_link/get_attachment for consuming them. It is nearly complete for an agent's needs, though it does not mention pagination, item counts, or ordering.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds meaning the schema doesn't: folder_id is framed as a way to 'go deeper into one folder' relative to the auto-expanded root, which clarifies the traversal semantics rather than just restating the param.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (a course's content items) and enumerates the item types returned (folders, documents, files, assignments, tests, links), which distinguishes it from siblings like get_assignments and get_announcements. An agent can tell what this returns without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clearly explains the traversal model — hierarchy is auto-expanded a couple levels and folder_id drills deeper — and routes to the right siblings for continuation (read_link for links, get_attachment for files). No explicit 'when not to use' or coverage of how it relates to get_assignments/get_grades, but the context is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_gradesGet Blackboard gradesARead-only
List the student’s own grades for one Blackboard course: assignment, score, points possible, percentage, feedback, and grading status. Only grades visible to the signed-in student are returned. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| course_id | Yes | Blackboard course id from list_courses, e.g. "_26184_1" (course code also accepted). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint and openWorldHint, and the description adds meaningful behavioral context: results are scoped to grades visible to the signed-in student and include feedback and grading status. This goes beyond the annotation by clarifying the visibility/auth boundary, though it omits details like pagination or possible empty results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler; the core purpose and returned fields are front-loaded, and the visibility note is placed second. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with one parameter and no output schema, the description adequately covers what the agent needs to know: what is returned, whose grades, and the visibility constraint. No critical information is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides 100% coverage for course_id, including format and an example. The description adds only minor context by framing the course as the grade source, so it meets the baseline but does not significantly enrich parameter understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('List'), a specific resource ('the student's own grades for one Blackboard course'), and enumerates the returned fields. This clearly distinguishes it from siblings like get_assignments or get_course_content, which cover different course data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes it clear the tool is for retrieving a single student's own grades for a specific course, which implies when to use it. It does not explicitly name alternatives or state when not to use it, but the context is strong enough for an agent to select it appropriately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recent_updatesGet recent Blackboard updatesARead-only
Recent Blackboard activity across current courses since a point in time (default: the last 7 days): announcements (with their links), new or changed content items, changed assignments, and grades on gradebook items that changed. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| since | No | ISO date (e.g. "2026-08-21"). Defaults to 7 days ago. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so the 'Read-only' clause is largely redundant, but the description adds real behavioral value by disclosing that it reports only *changed* items and grades on *changed* gradebook items, plus announcement links. It omits any note on result volume, ordering, or pagination.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One dense sentence with the aggregation scope front-loaded, followed by a short qualifier. Every clause contributes (scope, time window, contents), and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-optional-parameter read tool with no output schema, the description adequately covers what is returned and the default time window. Minor gaps are the treatment of 'current courses' (enrollment scope) and result ordering or size limits.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single 'since' parameter is fully documented with format and default in the schema. The description restates the default but adds no syntax or edge-case detail beyond it, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (gets/aggregates) and resource (recent Blackboard activity across current courses), then enumerates exactly which activity types are captured: announcements, content changes, assignment changes, and gradebook changes. This aggregate scope cleanly distinguishes it from the single-resource siblings get_announcements, get_grades, and get_assignments.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The time window is explained ('since a point in time, default last 7 days'), which implies the tool is for a recent-activity sweep, but no alternative or exclusion is named. It never says when to prefer this over get_announcements/get_grades or how to follow up after receiving results, leaving routing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_upcoming_workGet upcoming Blackboard workARead-only
Upcoming assignments and assessments across ALL Blackboard courses, sorted by due date, with submission status. Also lists anything due in the last few days that has not been handed in. This is the one call to answer “what do I have due?”. The window runs to the end of the last day, Syracuse time. status: graded, submitted, in_progress (started or saved as a draft, NOT handed in), not_submitted, or unknown (Blackboard did not say — never treat unknown as missing work). Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | How many days ahead to look (default 7). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnlyHint annotation: it discloses sort order, the window boundary ('end of the last day, Syracuse time'), inclusion of recently overdue unhanded-in work, and an interpretation rule for the 'unknown' status ('never treat unknown as missing work'). That last point materially changes how an agent should reason about the results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose, and the routing statement follows immediately. The trailing 'Read-only' repeats the readOnlyHint annotation and is the one sentence that does not fully earn its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the burden of explaining returns, and it does: due-date ordering, submission status, and the full status vocabulary with edge-case handling. Minor omissions remain (result size limits or pagination), but an agent has what it needs to call and interpret this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single 'days' parameter is fully described in the schema, so the baseline is 3. The description adds genuine meaning by specifying that the window terminates at the end of the last day in Syracuse time, which clarifies how the integer is actually interpreted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource plus scope: 'Upcoming assignments and assessments across ALL Blackboard courses, sorted by due date, with submission status.' The ALL-courses scope and the 'what do I have due?' framing distinguish it from course-scoped siblings like get_assignments and get_course_content.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly positions itself as 'the one call to answer "what do I have due?"', which is clear routing guidance. It also notes it recovers recent unsubmitted items from the past few days. It does not name an alternative tool or state when NOT to use it, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_coursesList Blackboard coursesARead-only
List the student’s currently visible Blackboard (Syracuse University) courses. Returns course ids needed by every other blackboard tool. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the 'Read-only' sentence adds little beyond the annotation. The description does add value by specifying that only 'currently visible' courses are returned, and that the output consists of course ids used by other tools. This goes beyond the structured annotations, though it does not clarify open-world semantics explicitly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences with the primary action and scope front-loaded, followed by purpose and read-only status. Every sentence earns its place with no redundant or filler wording.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only list tool, the description is complete: it names the resource, institutional context, output type (course ids), and why that output matters. The absence of an output schema is mitigated by the explicit statement that it returns course ids. Minor ambiguity around 'currently visible' is acceptable given the tool's simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no properties, so the baseline is 4. The description does not need to explain parameter meanings because there are none; it appropriately focuses on output and purpose instead.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List'), resource ('courses'), and scope ('student’s currently visible Blackboard (Syracuse University)'). It also says the output is course ids needed by every other blackboard tool, which distinguishes it as the foundational listing tool among the get_* siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly implies usage context: call this first to obtain course ids needed by other tools. However, it does not explicitly name sibling alternatives or state when not to use it, so it falls just short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_linkRead a link posted in BlackboardARead-only
Open a link a professor posted in Blackboard and return what is behind it as text: Google Docs, Sheets (every tab), Slides (with speaker notes), Drive files and folders, Colab notebooks, YouTube videos (title and description; YouTube refuses transcripts), Zoom recordings (transcript, when the host enabled one), Kaltura/Panopto videos (captions), Microsoft 365 and OneDrive files, Google/Microsoft Forms (questions only), GitHub files, PDFs, and ordinary web pages. Links come from the "links" field of get_course_content, get_announcements and get_assignment_context. Only links that appear in the student’s own courses can be opened. Never submits, joins, or types anything. Long results come in pages: pass next_offset back as offset to keep reading. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | The link, exactly as returned in a "links" list or item "url". | |
| offset | No | Character offset to continue a long result (from next_offset). | |
| course_id | No | Course the link was posted in. Needed if the link has not been listed in this conversation yet. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and openWorldHint=true, but the description adds crucial context: it states it 'never submits, joins, or types anything' and explains pagination behavior with next_offset. It also notes limitations like YouTube refusing transcripts. The main omission is that it doesn't describe error conditions or rate limits, but for a read-only tool with annotations, this is well-covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but front-loaded with the core action and supported types. It could be slightly trimmed, but every sentence contributes information about capabilities, input sources, or constraints. It remains focused despite its length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of resolving various link types, the description provides a comprehensive list of supported content, input sources, access restrictions, pagination details, and note about no output schema. It fully equips an agent to invoke the tool correctly, with no significant gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema fully documents all three parameters. The description mentions next_offset and offset in its pagination note, and implies course_id via the access constraint, but does not add syntax or format details beyond the schema. Baseline 3 is appropriate when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (open) and resource (a link posted in Blackboard), and enumerates the content types it resolves (Google Docs, Slides, PDFs, etc.). This clearly distinguishes it from siblings like get_attachment or get_course_content, which reference links but do not open them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly specifies the source of its inputs ('Links come from the "links" field of get_course_content, get_announcements and get_assignment_context') and the access constraint ('Only links that appear in the student's own courses can be opened'). This provides clear when-to-use versus when-not-to-use guidance without relying on inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.2.0- Changed
get_assignments3 fields changed- changed
Input schema / properties / due_after / descriptionPrevious value: -"ISO date — only items due on/after this instant."New value: +"ISO date or date-time. A bare date (\"2026-09-30\") means the start of that day, Syracuse time." - changed
Input schema / properties / due_before / descriptionPrevious value: -"ISO date — only items due on/before this instant."New value: +"ISO date or date-time. A bare date (\"2026-09-30\") includes that whole day, Syracuse time." - changed
Input schema / properties / include_status / descriptionPrevious value: -"Also resolve submitted/graded status (slower: one extra Blackboard request per item)."New value: +"Also resolve submitted/graded status (slower: 1-2 extra Blackboard requests per item). Status is \"in_progress\" for a started or saved draft that was NOT handed in, and \"unknown\" when Blackboard does not report an attempt either way — treat unknown as undetermined, never as missing work."
- Changed
get_attachment2 fields changed- changed
Input schema / properties / file_id / descriptionPrevious value: -"Specific file id when a content item has several attachments (see available_files in the result)."New value: +"Which file, when a content item has several (a file_id or file_name from available_files)." - added
Input schema / properties / offsetAdded value: +{ + "description": "Character offset to continue a long file (from next_offset).", + "minimum": 0, + "type": "integer" +}
- Added
read_link
9 tool updates
v0.1.0- First observed
get_announcements - First observed
get_assignment_context - First observed
get_assignments - First observed
get_attachment - First observed
get_course_content - First observed
get_grades - First observed
get_recent_updates - First observed
get_upcoming_work - First observed
list_courses
TDQS
Scored across 10 tools
Most tools have clearly distinct purposes, but there is some overlap: get_assignments, get_upcoming_work, get_course_content, and get_assignment_context all surface assignment-related data with different scopes. The descriptions do a good job clarifying when to use each, but an agent could still hesitate between them for certain queries.
All tool names follow a consistent verb_noun snake_case pattern: get_course_content, get_announcements, get_assignments, get_attachment, get_upcoming_work, get_recent_updates, get_assignment_context, get_grades, list_courses, read_link. The verbs get_, list_, and read_ are standard and predictable.
Ten tools is well-scoped for a read-only Blackboard student access server. Each tool earns its place by covering a distinct resource or view (courses, content, announcements, assignments, attachments, links, grades, upcoming work, recent updates, assignment context).
The read-only surface covers the core student workflows: listing courses, browsing content, reading announcements and assignments, opening files and links, checking grades, and tracking due work. A notable gap is discussion/forum reading, and there is no cross-course grade summary, but agents can work around these limitations.
Maintenance
Related MCP Connectors
Your personal data for AI — Telegram, bank, courses, Zoom & more, scoped to you.
Build study flashcards and exam-prep decks from your AI chat, all stored locally.
Read-only bank access for your AI agent. Connects Claude, ChatGPT, Cursor, Gemini, Codex.
Connect your Moodle to AI assistants: courses, content, grading and reports from the chat.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to access Canvas LMS course content, including assignments, modules, announcements, and files, to help students manage their coursework.12 npmISC
- AlicenseAqualityAmaintenanceEnables students to ask an AI assistant about their Canvas LMS data, including assignments, grades, missing submissions, discussions, and upcoming items, while keeping access read-only and private.43MIT
- AlicenseBqualityBmaintenanceEnables AI assistants to access IE Connects community and Blackboard coursework through guided local sign-in, with tools for classes, events, deadlines, grades, and more.34MIT
- FlicenseBqualityBmaintenanceEnables local, read-only access to IE Blackboard, IE Connects, and IE Careers within AI assistants, with 49 tools for deadlines, readings, events, grades, internships, and more.49-