Skip to main content
Glama

get_announcements

Retrieve course announcements and instructor updates from Brightspace. Filter by specific course or view recent posts across all courses to stay informed about class news.

Instructions

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.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
courseIdNoCourse ID to get announcements for. If omitted, returns recent announcements across all courses.
countNoMaximum number of announcements to return

Implementation Reference

  • Main handler implementation for get_announcements tool. Contains the registerGetAnnouncements function that registers the MCP tool and the async handler (lines 70-189) that executes the logic. Handles both single course and all courses scenarios, filters enrollments, fetches announcements from the D2L API, sorts by date, and returns results.
    export function registerGetAnnouncements( server: McpServer, apiClient: D2LApiClient, config: AppConfig ): void { server.registerTool( "get_announcements", { title: "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.", inputSchema: GetAnnouncementsSchema, }, async (args: any) => { try { log("DEBUG", "get_announcements tool called", { args }); // Parse and validate input const { courseId, count } = GetAnnouncementsSchema.parse(args); // Single course case if (courseId) { const path = apiClient.le(courseId, "/news/"); const newsItems = await apiClient.get<NewsItem[]>(path, { ttl: DEFAULT_CACHE_TTLS.announcements, }); // Map to clean objects const announcements = newsItems .map((item) => ({ id: item.Id, title: item.Title, body: item.Body.Text, createdBy: item.CreatedBy.DisplayName, createdDate: item.CreatedDate, startDate: item.StartDate, isPinned: item.IsPinned, })) .sort( (a, b) => new Date(b.createdDate).getTime() - new Date(a.createdDate).getTime() ) .slice(0, count); log( "INFO", `get_announcements: Retrieved ${announcements.length} announcements for course ${courseId}` ); return toolResponse(announcements); } // All courses case // First, fetch enrolled courses const enrollmentPath = apiClient.lp( "/enrollments/myenrollments/?orgUnitTypeId=3&isActive=true" ); const enrollmentResponse = await apiClient.get<EnrollmentResponse>( enrollmentPath, { ttl: DEFAULT_CACHE_TTLS.enrollments } ); // Apply course filter const filteredEnrollments = applyCourseFilter( enrollmentResponse.Items.map(item => ({ id: item.OrgUnit.Id, name: item.OrgUnit.Name, code: item.OrgUnit.Code, isActive: item.Access.IsActive, ...item, })), config.courseFilter ); // Fetch announcements for each course (handle 403s gracefully) const announcementPromises = filteredEnrollments.map( async (item) => { try { const path = apiClient.le(item.OrgUnit.Id, "/news/"); const newsItems = await apiClient.get<NewsItem[]>(path, { ttl: DEFAULT_CACHE_TTLS.announcements, }); return newsItems.map((newsItem) => ({ id: newsItem.Id, title: newsItem.Title, body: newsItem.Body.Text, createdBy: newsItem.CreatedBy.DisplayName, createdDate: newsItem.CreatedDate, startDate: newsItem.StartDate, isPinned: newsItem.IsPinned, courseId: item.OrgUnit.Id, courseName: item.OrgUnit.Name, })); } catch (error: any) { // 403 means no access (past course, etc) - log and skip if (error?.status === 403) { log( "DEBUG", `get_announcements: 403 Forbidden for course ${item.OrgUnit.Id} (${item.OrgUnit.Name}) - skipping` ); return []; } throw error; // Re-throw other errors } } ); const results = await Promise.allSettled(announcementPromises); const allAnnouncements = results .filter( (r): r is PromiseFulfilledResult<any> => r.status === "fulfilled" ) .flatMap((r) => r.value); // Sort by created date and slice to count const announcements = allAnnouncements .sort( (a, b) => new Date(b.createdDate).getTime() - new Date(a.createdDate).getTime() ) .slice(0, count); log( "INFO", `get_announcements: Retrieved ${announcements.length} announcements (out of ${allAnnouncements.length} total across ${enrollmentResponse.Items.length} courses)` ); return toolResponse(announcements); } catch (error) { return sanitizeError(error); } } ); }
  • Input validation schema for get_announcements tool using Zod. Defines optional courseId parameter to filter to a specific course, and count parameter (default 10, max 50) to limit the number of announcements returned.
    export const GetAnnouncementsSchema = z.object({ courseId: z.number().int().positive().optional().describe("Course ID to get announcements for. If omitted, returns recent announcements across all courses."), count: z.number().int().min(1).max(50).default(10).describe("Maximum number of announcements to return"), });
  • src/index.ts:168-168 (registration)
    Tool registration call in main server initialization. Invokes registerGetAnnouncements with the MCP server instance, D2L API client, and app configuration to make the tool available to clients.
    registerGetAnnouncements(server, apiClient, config);
  • Export statement for registerGetAnnouncements function in the tools barrel file, making it available for import in the main server file.
    export { registerGetAnnouncements } from "./get-announcements.js";

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/RohanMuppa/brightspace-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server