working on mcp

This commit is contained in:
2025-07-21 11:42:27 -06:00
parent d200c114d3
commit 9aec082467
3 changed files with 126 additions and 31 deletions

View File

@@ -0,0 +1,186 @@
import { assignmentMarkdownSerializer } from "@/models/local/assignment/utils/assignmentMarkdownSerializer";
import { groupByStartDate } from "@/models/local/utils/timeUtils";
import { fileStorageService } from "@/services/fileStorage/fileStorageService";
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
import { createMcpHandler } from "mcp-handler";
import { z } from "zod";
import { githubClassroomUrlPrompt } from "./github-classroom-prompt";
const handler = createMcpHandler(
(server) => {
server.tool(
"list_current_courses",
"gets courses for the current term",
{},
async () => {
const settingsList =
await fileStorageService.settings.getAllCoursesSettings();
const coursesByStartDate = groupByStartDate(settingsList);
const sortedDates = Object.keys(coursesByStartDate).sort().reverse();
const mostRecentStartDate = sortedDates[0];
const courseNames = coursesByStartDate[mostRecentStartDate].map(
(settings) => settings.name
);
return {
content: courseNames.map((name) => ({
type: "text",
text: JSON.stringify({
courseName: name,
}),
})),
};
}
);
server.tool(
"list_assignments_for_course",
"gets assignments and modules for a course",
{
courseName: z.string(),
},
async ({ courseName }) => {
const modules = await fileStorageService.modules.getModuleNames(
courseName
);
const assignments = (
await Promise.all(
modules.map(async (moduleName) => {
const assignments =
await fileStorageService.assignments.getAssignments(
courseName,
moduleName
);
return assignments.map((assignment) => ({
assignmentName: assignment.name,
moduleName,
}));
})
)
).flat();
console.log("mcp got assignments", assignments);
return {
//doesn't seem to work with many clients
// content: assignments.map((a) => ({
// type: "resource_link",
// uri: `canvas:///courses/${courseName}/module/${a.moduleName}/assignments/${a.assignmentName}`,
// name: `${a.assignmentName}.md`,
// mimeType: "text/markdown",
// description: "An canvas assignment",
// })),
content: assignments.map((a) => ({
type: "text",
text: JSON.stringify({
assignmentName: a.assignmentName,
moduleName: a.moduleName,
}),
})),
};
}
);
server.tool(
"get_assignment",
"gets a markdown file defining the assignment",
{
courseName: z.string(),
moduleName: z.string(),
assignmentName: z.string(),
},
async ({ courseName, moduleName, assignmentName }) => {
if (
typeof courseName !== "string" ||
typeof moduleName !== "string" ||
typeof assignmentName !== "string"
) {
throw new Error(
"courseName, moduleName, and assignmentName must be strings"
);
}
const assignment = await fileStorageService.assignments.getAssignment(
courseName,
moduleName,
assignmentName
);
console.log("mcp assignment", assignment);
return {
content: [
{
type: "text",
text: assignmentMarkdownSerializer.toMarkdown(assignment),
},
],
};
}
);
server.tool(
"get_github_classroom_url_instructions",
"gets instructions for creating a GitHub Classroom assignment, call this to get a prompt showing how to create a GitHub Classroom assignment",
{},
async () => {
return {
content: [
{
type: "text",
text: githubClassroomUrlPrompt,
},
],
};
}
);
// resources dont integrate well right now
// server.registerResource(
// "course_assignment",
// new ResourceTemplate(
// "canvas:///courses/{courseName}/module/{moduleName}/assignments/{assignmentName}",
// { list: undefined }
// ),
// {
// title: "Course Assignment",
// description: "Markdown representation of a course assignment",
// },
// async (uri, { courseName, moduleName, assignmentName }) => {
// if (
// typeof courseName !== "string" ||
// typeof moduleName !== "string" ||
// typeof assignmentName !== "string"
// ) {
// throw new Error(
// "courseName, moduleName, and assignmentName must be strings"
// );
// }
// const assignment = await fileStorageService.assignments.getAssignment(
// courseName,
// moduleName,
// assignmentName
// );
// return {
// contents: [
// {
// uri: uri.href,
// text: assignment.description,
// },
// ],
// };
// }
// );
},
{
serverInfo: {
name: "Canvas Management MCP Server",
version: "2.0.0",
},
},
{
basePath: "/api/mcp",
maxDuration: 60,
verboseLogs: true,
}
);
export { handler as GET, handler as POST };