hisinone-mcp
# hisinone-mcp
An MCP server that reads study data from a [HISinOne](https://www.his.de) campus
portal and downloads the documents of the signed-in account.
The server targets the portal of Reutlingen University, but the base URL is a
setting. Other HISinOne installations use the same page structure.
## What the server can do
HISinOne has no public API for study data. The server signs in with the ordinary
web form and reads the rendered pages. It exposes nine tools.
| Tool | Purpose |
| --- | --- |
| `hisinone_get_profile` | Name, subjects and contact values of the account |
| `hisinone_get_achievements` | Full grade tree with credit points and status |
| `hisinone_list_semesters` | The terms that the portal offers, with their keys |
| `hisinone_get_enrollments` | Course and exam registrations of one term |
| `hisinone_get_timetable` | Personal appointments with room and repeat rule |
| `hisinone_list_documents` | Certificates and reports that the portal can produce |
| `hisinone_download_document` | Produce one document and store it on disk |
| `hisinone_download_url` | Store one portal file by its address |
| `hisinone_search_courses` | Search the course catalogue |
`hisinone_list_documents` gives the key that `hisinone_download_document` needs.
A portal usually offers the enrolment certificate, the fee certificate, the
transcript of records and the study history.
## Setup
1. Copy `.env.example` to `.env`.
2. Put your portal account and password into `.env`.
3. Start the development shell with `nix develop`.
The shell installs Python 3.14, `uv`, `ruff` and `basedpyright`. It also creates
a virtual environment in `.venv`, which Zed and its language servers find.
Without Nix, run `uv sync --all-groups` instead.
## Settings
Each setting is an environment variable. The server also reads a `.env` file in
the working directory.
| Variable | Default | Purpose |
| --- | --- | --- |
| `HISINONE_USERNAME` | — | Portal account name |
| `HISINONE_PASSWORD` | — | Portal account password |
| `HISINONE_BASE_URL` | `https://hisinone.reutlingen-university.de` | Portal root |
| `HISINONE_DOWNLOAD_DIR` | `downloads` | Directory for downloaded files |
| `HISINONE_TIMEOUT` | `45.0` | HTTP timeout in seconds |
## Run the server
```sh
uv run hisinone-mcp
```
The server speaks the MCP stdio transport. To add it to Claude Code:
```sh
claude mcp add hisinone -- uv run --directory /path/to/hisinone-mcp hisinone-mcp
```
## Layout
```
src/hisinone_mcp/
config/ Settings
errors/ One error class per file
parsing/ Document, JsfForm and CalendarFeed
session/ The signed-in HTTP client
model/ Result models, one domain per directory
service/ One reader per portal area
server.py The MCP tool definitions
```
Each file holds exactly one class.
## How the portal reading works
The portal runs on JavaServer Faces. A page keeps its state in hidden fields. A
button press is a form POST that repeats every field and adds the `name` of the
button. `JsfForm` does this work.
Three details decide whether a reader works:
- The grade page shows its tree collapsed. The reader presses the expand control
before it parses the table.
- A certificate is a server job. The reader presses the document button, waits
for the job and follows the download link that carries a document id.
- The timetable page needs JavaScript, but it also publishes an iCalendar feed.
The reader takes the feed address from the page and parses the feed.
A portal update can change a page. A tool then reports that the page layout
changed, and the parser needs an update.
## Checks
```sh
ruff check .
ruff format --check .
basedpyright
```
## Limits
- The server acts as one account. It holds no multi-user session.
- It reads data and downloads files. It does not register for exams or courses.
- Reutlingen University does not use the course registration module. The
registration tool therefore reports an empty term for that portal.
## License
MIT
TDQS
Scored across 9 tools
Each tool targets a distinct resource and action: profile, achievements, semesters, enrollments, timetable, courses, and documents. Even the two download tools are clearly separated by description (portal-generated documents vs arbitrary portal file links).
All tools follow the same hisinone_ prefix with a consistent verb_noun pattern (list_, get_, download_, search_). This makes the tool surface predictable and easy to navigate.
Nine tools is well-scoped for a university portal domain. Each tool covers a meaningful capability without redundancy or bloat.
The surface covers the main read-oriented workflows: profile, academic achievements, enrollments, timetable, course search, and document retrieval. It lacks write operations, but for a self-service portal read access is the primary expected scope.