import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { Config } from '../config.ts'; import { ServerContext } from '../context.ts'; import type { Services } from '../services.ts'; import { registerContentTools } from './tools/content.ts'; import { registerFileTools } from './tools/files.ts'; import { registerOverviewTools } from './tools/overview.ts'; import { registerRawTool } from './tools/raw.ts'; import { registerIndexTools } from './tools/index-tools.ts'; import { registerSearchTool } from './tools/search.ts'; import { registerRoomTools } from './tools/rooms.ts'; import { registerSubmissionTools } from './tools/submissions.ts'; export const SERVER_NAME = 'schulcloud-mcp'; export const SERVER_VERSION = '0.1.0'; const INSTRUCTIONS = `Read-only access to a Schulcloud (HPI Schul-Cloud / Schulcloud-Verbund-Software) account. How the content is organised, and the usual path through it: - **Courses** ("Kurse") are the top level — list_courses, or get_dashboard for the ones the user has pinned. - A course page (get_course) holds three kinds of thing: - **Column boards** — where most current teaching material lives. get_board returns every column, card, text block, link and attached file in one call. - **Topics / lessons** ("Themen") — the older format. get_lesson. - **Tasks** ("Aufgaben") — homework. list_tasks across all courses, get_task for one. - **Files** hang off boards, lessons and tasks. Every listing shows file ids; download_file fetches one and extracts its text (PDF, Word, Excel, PowerPoint, OpenDocument) or returns an image inline. - **Submissions** ("Abgaben") — what the user handed in. get_task shows that task's submission: the files, the graded flag, the grade, what the user wrote, and the teacher's written feedback. A grade is a percentage (0-100) or absent — there is no textual grade — and teachers often grade with the written feedback alone, so "graded by feedback" is a complete result, not missing data. list_submissions surveys them across tasks ("what is still ungraded?"). The written parts are read from the web page because no API exposes them, so they can be missing even when feedback exists — if none is shown for a graded submission, say it was not found rather than that none was given. On a teacher account these tools report other people's submissions too. When the user names a topic rather than a course, use search — the API has no search endpoint, so it walks the courses and matches client-side, which takes a few seconds but covers board text and file names. Everything here is read-only; nothing in this server can modify the account.`; export function createServer(config: Config, services?: Services): { server: McpServer; context: ServerContext } { const context = new ServerContext(config, services); const server = new McpServer( { name: SERVER_NAME, version: SERVER_VERSION }, { capabilities: { tools: {}, logging: {} }, instructions: INSTRUCTIONS }, ); registerOverviewTools(server, context); registerContentTools(server, context); registerRoomTools(server, context); registerFileTools(server, context); registerSearchTool(server, context); registerSubmissionTools(server, context); registerIndexTools(server, context); registerRawTool(server, context); return { server, context }; }