TUMonline student MCP server
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., "@TUMonline student MCP server Show me my grades for this semester"
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.
TUMonline student MCP server
Self-hosted Model Context Protocol server for a TUMonline student. It reads identity, the personal calendar, registered courses, grades, exams, tuition status, and the person directory through the Campus token API (wbservicesbasic). It also reads the public course catalogue, public exam dates, and NavigaTUM rooms, including Heilbronn. NavigaTUM and the public catalogue do not use the token.
It does not register for exams or courses, download an enrollment certificate, open a curriculum, book a room, or talk to Moodle. It does not scrape pages, automate TUM single sign-on, or call terminCreate / terminDelete.
This is an unofficial server. It is not affiliated with, endorsed by, or maintained by the Technical University of Munich.
Automated tests use in-process mocks of the TUMonline XML and JSON APIs and of NavigaTUM. They do not sign in with a TUM account.
Requirements
Node.js 22 or newer. The server has no runtime dependencies.
Related MCP server: librus-mcp
Install
git clone https://github.com/dxwil/tumonline-student-mcp.git
cd tumonline-student-mcp
chmod +x ./bin/tumonline-student-mcp
node --versionplugin.json, .cursor-plugin/plugin.json, mcp.json, and cursor-mcp.json sit next to src/ and bin/.
Cursor
Cursor loads .cursor-plugin/plugin.json, which points at cursor-mcp.json. That file starts ./bin/tumonline-student-mcp with cwd set to ${CURSOR_PLUGIN_ROOT}.
Agent Plugins
An Agent Plugins 1.0.0 host loads root plugin.json and mcp.json. mcp.json starts ./bin/tumonline-student-mcp and does not set cwd. Do not point that host at cursor-mcp.json. ${CURSOR_PLUGIN_ROOT} is only valid in the Cursor file.
A client that loads neither manifest can start the same process:
export TUMONLINE_MCP_STATE_DIR="$HOME/.local/share/tumonline-student-mcp"
./bin/tumonline-student-mcpStdout is MCP JSON-RPC only. Diagnostics go to stderr and do not include tokens.
Tools
Personal tools need the Campus token stored for this MCP user. They never take a token as an argument. Public tools do not send one.
Tool | Source | Token |
|
| yes |
|
| yes |
|
| yes |
|
| yes |
|
| yes |
|
| only for |
|
| yes |
|
| yes |
|
| yes |
|
| yes |
|
| yes |
|
| no |
|
| no |
|
| no |
|
| no |
search_rooms searches every NavigaTUM campus unless campus is set. heilbronn is the Heilbronn site id. get_room reports parent campuses, so a Heilbronn room stays visible as one.
get_token_status reports whether a token is stored and whether TUMonline says it is active. It never returns the token. With probe: true (the default) it tries calendar, lectures, grades, exam results, tuition fees, identity, and persons, and records ok or missing.
If TUMonline says Keine Rechte für Funktion ..., the tool error names the right to enable. Request-Rate überschritten and Token-Limit are returned as their own errors with the next step. A token that is not activated says so and points at Token-Management.
Profile images are omitted. No tool returns a file body. If a later tool needs a file, the HTTP server mints a one-time downloadUrl at /files/<token> and streams the bytes when that URL is opened. The link is not written into an MCP resource.
Sign-in
Stdio is the default and uses one local account under TUMONLINE_MCP_STATE_DIR (default /var/lib/tumonline-student-mcp).
export TUMONLINE_MCP_STATE_DIR="$HOME/.local/share/tumonline-student-mcp"
./bin/tumonline-student-mcp connect request ab12cde
./bin/tumonline-student-mcp connect statusconnect request calls wbservicesbasic.requestToken and stores the token encrypted. It prints activation steps and does not print the token. connect paste reads one token from stdin. The token name defaults to tumonline-student-mcp (TUMONLINE_MCP_TOKEN_NAME).
HTTP mode is the multi-user server. Each MCP client opens https://<your-domain>/mcp, discovers this server's OAuth 2.1 authorization server, and sends the person to /authorize. The page accepts a TUM ID (the server requests a token) or an existing activated token. The token is encrypted with AES-256-GCM, bound to that MCP user, and never shown. The page then asks them to activate it in TUMonline under Visitenkarte or Services, then Token-Management, and to enable calendar, lectures, grades, exam results, tuition fees, identity, and persons. Check activation calls isTokenConfirmed.
Access tokens last 15 minutes. Refresh tokens last 30 days, are stored as SHA-256 hashes, and rotate on use. Reusing an old refresh token revokes that grant. Scope is mcp:tools. The authorize page is sent with Referrer-Policy: same-origin, and a form POST must come from this origin.
There is no TUM password and no SSO redirect.
Setup for a Debian 12 unprivileged Proxmox LXC is in docs/self-hosting.md. A map of features to tools is in docs/coverage.md.
Configure
Variable | Default |
|
|
|
|
|
|
|
|
| unset; required for a public HTTPS issuer |
|
|
|
|
|
|
| unset; a 32-byte key is created in the state directory |
|
|
|
|
|
|
TUMONLINE_MCP_ALLOWED_HOSTS and TUMONLINE_MCP_ALLOWED_ORIGINS extend the loopback and public-origin allowlists. Requests with no Origin are allowed so native clients work. A browser form post to /authorize must send this site's Origin.
An optional static bearer (tumonline-student-mcp token create) is for an admin client that cannot run OAuth. The secret is printed once. Personal tools still need a Campus token on that account (connect request or connect paste --user <id>).
Tests
npm testnpm test runs Node's built-in test runner. It covers XML fixtures shaped like the Campus clients, error mapping, AES-256-GCM binding, the OAuth code flow with PKCE S256, refresh rotation, allowlists, NavigaTUM including Heilbronn, and the one-time file stream. Nothing in the suite contacts campus.tum.de with a real account.
Limits
TUMonline's token web service is not a documented public API. Field names follow TUM-Dev Campus-Android, campus_flutter, and the tum-mcp client. A live response can contain extra columns; string fields are passed through with image and token-like values removed.
The German labels in the Token-Management screen are not fetched. A missing-right error names the right this server maps from the function (
calendar,lectures,grades,exam results,tuition fees,identity,persons).list_public_examsreads at most three pages of 50. It does not scan the whole catalogue.Calls to TUMonline are spaced per user, capped per minute, and limited to two at a time. A
Request-Rate überschrittenresponse pauses that user for a minute.Logs are status and path only. Tokens and TUM IDs are not written to the journal.
License
MIT. Copyright 2026 dxwil. See LICENSE.
Available Tools
19 toolsget_calendarARead-onlyIdempotent
Read wbservicesbasic.kalender and filter events to a date range. Dates are YYYY-MM-DD in Europe/Berlin. Defaults to today through 14 days. Requires the calendar right. Read-only. Does not create or delete events.
Inputs: to, from.
get_courseBRead-onlyIdempotent
Read one public course from ee/rest/slc.tm.cp/student/courses/{courseId}. No token.
Inputs: courseId (required), language.
get_course_datesARead-onlyIdempotent
List course dates. Pass courseId for the public catalogue (ee/rest course groups, no token). Pass lvNumber for wbservicesbasic.veranstaltungenTermine (token, lectures right). Pass only one of them.
Inputs: limit, groupId, courseId, language, +2 more.
get_course_detailsARead-onlyIdempotent
Read wbservicesbasic.veranstaltungenDetails for one LV number, and veranstaltungenTermine when includeDates is true (the default). Requires the lectures right. Read-only.
Inputs: lvNumber (required), includeDates.
get_course_groupsBRead-onlyIdempotent
List public course groups from ee/rest/slc.tm.cp/student/courseGroups. No token.
Inputs: courseId (required), language.
get_fee_statusARead-onlyIdempotent
Read wbservicesbasic.studienbeitragsstatus: semester, open amount, and deadline. Requires the tuition fees right. Read-only.
Inputs: no named parameters.
get_gradesBRead-onlyIdempotent
Read wbservicesbasic.noten. includeAverages defaults to true and also reads absNoten. Requires the grades right. Read-only.
Inputs: includeAverages.
get_identityARead-onlyIdempotent
Read wbservicesbasic.id for this user: TUM ID, name, and obfuscated ids. Requires the identity right. Read-only.
Inputs: no named parameters.
get_personBRead-onlyIdempotent
Read wbservicesbasic.personenDetails. Profile images are omitted. Requires the persons right. Read-only.
Inputs: personId (required).
get_roomARead-onlyIdempotent
Read one NavigaTUM location from /api/locations/{id}, including parents so a Heilbronn room is visible as such. No TUMonline token.
Inputs: id (required), language.
get_token_statusARead-onlyIdempotent
Report whether a TUMonline token is stored for this user, whether isTokenConfirmed says it is active, and, when probe is true, which rights answer. Never returns the token. Rights are calendar, lectures, grades, exam results, tuition fees, identity, and persons.
Inputs: probe, refresh.
list_my_coursesARead-onlyIdempotent
List courses from wbservicesbasic.veranstaltungenEigene: LV number, title, type, semester, and lecturers. Requires the lectures right. Read-only.
Inputs: no named parameters.
list_my_examsARead-onlyIdempotent
List exams from wbservicesbasic.pruefungenEigene. Requires the exam results right. Read-only. Does not register for an exam.
Inputs: no named parameters.
list_public_examsBRead-onlyIdempotent
List public exam dates from ee/rest/slc.xm.exd/exExamOffer. No token. Reads at most three pages so it does not walk the whole catalogue. Does not register for an exam.
Inputs: to, from, limit, courseNumbers.
list_semestersBRead-onlyIdempotent
List public TUMonline semesters from ee/rest/slc.lib.tm/semesters/student. No token. The selected semester is the current default.
Inputs: language.
search_coursesARead-onlyIdempotent
Search the public course catalogue at ee/rest/slc.tm.cp/student/courses. No token. semester is a key such as 26W or a semester id.
Inputs: query (required), limit, offset, language, +1 more.
search_lecturesARead-onlyIdempotent
Search lectures with the token service wbservicesbasic.veranstaltungenSuche. Use search_courses for the public catalogue. Requires the lectures right. Read-only.
Inputs: query (required).
search_personsARead-onlyIdempotent
Search people with wbservicesbasic.personenSuche. Returns ids for get_person. Requires the persons right. Read-only.
Inputs: query (required).
search_roomsARead-onlyIdempotent
Search rooms, buildings, and sites on NavigaTUM (https://nav.tum.de/api/search). No TUMonline token. The default search includes every campus, including Heilbronn. Pass campus heilbronn, garching, or another NavigaTUM parent id to filter.
Inputs: query (required), limit, campus.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 19 tools
Most tools target distinct resources or actions, but the course-related cluster (search_lectures, search_courses, get_course, get_course_details, get_course_dates) has overlapping-sounding names that require careful description reading. The descriptions explicitly separate token vs public endpoints, and get_course_dates' dual mode (courseId or lvNumber) is documented but still slightly ambiguous.
All tools follow a consistent snake_case verb_noun pattern (get_*, list_*, search_*). Scope prefixes like list_my_ vs. list_public_ and token vs. public naming reinforce meaning without breaking the convention.
19 tools are on the heavier side but justified by the broad student-information domain spanning identity, calendar, courses, grades, exams, fees, persons, semesters, and rooms. Some consolidation among the course lookup tools might be possible, but each tool has a clear role.
The surface provides solid read-only coverage of core student data: identity, calendar, own and public courses, dates, grades, exams, fees, persons, semesters, and rooms. Write operations such as exam registration and calendar creation are explicitly out of scope, and there are minor gaps like detailed exam or grade breakdowns, but agents can accomplish most informational workflows.
Maintenance
Related MCP Connectors
Search university course materials, your flashcards, quizzes, streak and quota. All tools read-only.
Read pretix events, tickets and orders; check attendees in or out with your own account.
Read Kisi places, doors, users, groups, access rights and access logs (no unlocking).
Read users, groups, departments, courses, content and enrollments in iSpring Learn.
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables read-only querying of Moodle as a student, including courses, assignments, grades, forums, and files, using a personal web services token.1137 npmMIT
- FlicenseAqualityCmaintenanceEnables read-only access to a Librus Portal account, letting users list linked Synergia accounts and retrieve grades, attendance, timetable, homework, notices, and school information.3-
- FlicenseAqualityCmaintenanceEnables read-only interaction with CMU Student Information Online data, including student context, schedules, grades, enrollment, account activity, and campus life through MCP tools.8-
- AlicenseAqualityCmaintenanceEnables reading study data and downloading documents from HISinOne campus portals using the signed-in account.91MIT