{
  "markdown": "# EduPage MCP Server\n\n<!-- mcp-name: io.github.oliverhruby/edupage-mcp -->\n\n[![GitHub release](https://img.shields.io/github/v/tag/oliverhruby/edupage-mcp.svg?sort=semver&label=release)](https://github.com/oliverhruby/edupage-mcp/releases)\n[![Quality gates](https://img.shields.io/github/actions/workflow/status/oliverhruby/edupage-mcp/quality-gates.yml.svg?label=quality%20gates)](https://github.com/oliverhruby/edupage-mcp/actions/workflows/quality-gates.yml)\n[![Security](https://img.shields.io/github/actions/workflow/status/oliverhruby/edupage-mcp/security.yml.svg?label=security)](https://github.com/oliverhruby/edupage-mcp/actions/workflows/security.yml)\n[![Container security](https://img.shields.io/github/actions/workflow/status/oliverhruby/edupage-mcp/container-security.yml.svg?label=container%20security)](https://github.com/oliverhruby/edupage-mcp/actions/workflows/container-security.yml)\n[![Coverage drift](https://img.shields.io/github/actions/workflow/status/oliverhruby/edupage-mcp/upstream-coverage.yml.svg?label=coverage%20drift)](https://github.com/oliverhruby/edupage-mcp/actions/workflows/upstream-coverage.yml)\n\n## Project\n\nA Model Context Protocol (MCP) server that exposes the full functionality of the\n[`edupage-api`](https://github.com/EdupageAPI/edupage-api) Python library to AI\nagents such as opencode, Claude, Cursor and any other MCP client.\n\nEduPage is a school information system used across Europe. This server lets you\nquery and operate a student / teacher / parent EduPage account directly from\nyour agent: timetables, grades, homework, substitutions, meals (including\nordering), messages, rosters, parent child-switching and more — including\n**multiple schools** (e.g. two children attending different schools).\n\n> **⚠️ Unofficial API.** Like all EduPage MCP servers, this relies on the\n> community-maintained [`edupage-api`](https://github.com/EdupageAPI/edupage-api)\n> library, which talks to EduPage's undocumented endpoints. Use read-only\n> features freely; use the write features (`send_message`, meal ordering, child\n> switching) carefully.\n\n---\n\n## Table of Contents\n\n- [Why another EduPage MCP server?](#why-another-edupage-mcp-server)\n- [What it provides](#what-it-provides)\n- [Getting started](#getting-started)\n  - [Prerequisites](#prerequisites)\n  - [1. Install](#1-install)\n  - [2. Configure credentials](#2-configure-credentials)\n  - [3. Register with your MCP client](#3-register-with-your-mcp-client)\n- [Prompt examples](#prompt-examples)\n- [Multiple schools (subdomains)](#multiple-schools-subdomains)\n- [Tool reference](#tool-reference)\n- [Data & safety notes](#data--safety-notes)\n- [Contributing](#contributing)\n- [Limitations](#limitations)\n- [Support](#support)\n- [License](#license)\n\n---\n\n## Why another EduPage MCP server?\n\nTwo other EduPage MCP servers already exist:\n\n- [`mrtineu/edupage-mcp`](https://github.com/mrtineu/edupage-mcp) — also\n  published on PyPI as [`edupage-mcp`](https://pypi.org/project/edupage-mcp/)\n- [`mhlavac/edupage-mcp`](https://github.com/mhlavac/edupage-mcp)\n\nBoth are good and I have **no affiliation** with them — they are simply\nreferenced here for honest comparison. They primarily focus on the **read-only**\nsurface of the API.\n\nThis project deliberately goes further:\n\n| Capability | mhlavac | mrtineu (PyPI) | **this project** |\n|---|---|---|---|\n| **Advanced login** — portal auto-detect, **2FA**, **session id** (`PHPSESSID`) | partial (portal) | basic only | ✅ |\n| Timetables (own + any teacher/class/room) | ✅ | ✅ | ✅ |\n| Grades (all / by term & year) | ✅ | ✅ | ✅ |\n| Substitutions / timetable changes | ✅ | ✅ | ✅ |\n| Meals — **read menu** | ✅ | ✅ | ✅ |\n| Meals — **choose / sign-off / rate** | ❌ | ❌ | ✅ |\n| Send messages (`send_message`) | ✅ | ❌ | ✅ |\n| Parent **student switching** (switch to/from student) | partial (list) | ❌ | ✅ |\n| Next ringing time / bell schedule | ❌ | ❌ | ✅ |\n| Raw session **custom request** | ❌ | ❌ | ✅ |\n| **Multiple schools** (auto-login + discovery) | ❌ | ❌ | ✅ |\n| **Role-aware** (parent / student / teacher) | ❌ | ❌ | ✅ |\n| **Day summaries** (one-call daily report) | ❌ | ❌ | ✅ |\n\n**Key differentiators:**\n\n- **Multi-school automatic discovery.** Set `EDUPAGE_SUBDOMAINS` with one shared\n  login and the server auto-discovers students across all schools — no need to\n  maintain a manual \"Student → school1, Student → school2\" mapping. A student at\n  two schools (e.g. Student at `school1` + `school2`) is found automatically\n  with separate per-school results.\n- **Role-aware tools.** The server detects whether you're a parent, student, or\n  teacher at each school and behaves accordingly — `get_student_timetable`\n  switches to the student account for parents, returns direct timetables for\n  students. No tool duplication.\n- **Full write surface.** Meal ordering/rating, message sending, student switching\n  — the other servers don't cover these.\n\n---\n\n## What it provides\n\nA single stdio MCP server exposing **46 tools** (published on PyPI as\n[`edupage-mcp-full`](https://pypi.org/project/edupage-mcp-full/)):\n\n- **Authentication** — `login`, `login_auto`, `login_all`, `login_from_session`,\n  `two_factor_check_confirmed`, `two_factor_finish`, `auth_status`, `user_id`\n- **Timetables** — `get_my_timetable`, `get_timetable` (teacher/student/class/\n  classroom), `get_student_timetable` (student by name, cross-school),\n  `get_next_week_timetable`, `get_next_ringing_time`, `get_periods`, `school_year`\n- **Students** — `find_student` (name → person_id, cross-school),\n  `get_student_timetable` (cross-school, role-aware), `scan_students`\n  (auto-discover all students across schools), `get_my_students` (classmates or\n  school-wide for parents), `switch_to_student` (by id **or** name, parent only),\n  `switch_to_parent`, `clear_student_cache` (force refresh cached student lists)\n- **Schools** — `get_schools` (logged-in schools with role per school)\n- **Grades** — `get_grades`\n- **Notifications / timeline** — `get_notifications`, `get_notification_history`,\n  `get_homework`, `get_assignments`, `get_absences`, `get_upcoming_events`, `get_news`\n- **Substitutions** — `get_timetable_changes`, `get_missing_teachers`\n- **Meals** — `get_meals`, `choose_meal`, `sign_off_meal`, `rate_meal`\n- **Day summaries** — `get_day_summary` (one call: timetable, substitutions,\n  missing teachers, grades, meals, homework, assignments, absences, news,\n  events, notifications for a date — \"what happened yesterday at school\" in a\n  single round trip; each section is isolated so one failure doesn't kill the\n  report). Includes an OpenCode skill (`school-day-summary`) for human-readable\n  formatting in OpenCode; other clients use the raw JSON directly.\n- **Rosters** — `get_students`, `get_all_students`, `get_teachers`, `get_classes`,\n  `get_classrooms`, `get_subjects`, `get_my_students`\n- **Actions** — `send_message`, `switch_to_student`, `switch_to_parent`, `custom_request`\n\n---\n\n## Getting started\n\nYou need an MCP-capable client (opencode, Claude Desktop, Cursor, etc.).\n\n### 1. Install\n\nIf you are using an AI coding client, a simple prompt is often enough to get\nstarted, for example: \"Install the EduPage MCP as described in this GitHub\nrepository oliverhruby/edupage-mcp\". Most MCP-capable clients can then guide\nyou through the available setup options.\n\n**Option A — from MCP Registry (recommended, one-click in VS Code / GitHub Copilot)**\n\nThe server is listed in the [MCP Registry](https://registry.modelcontextprotocol.io/).\nIn VS Code or GitHub Copilot, search for \"EduPage MCP\" and install with one click.\nOr use the direct deeplink: `mcp://install/io.github.oliverhruby/edupage-mcp`\n\n**Option B — from PyPI**\n\nUse this for normal usage with a released version.\n\nRequirements: `uv` for `uvx`, or Python **3.10+** for `pip`.\n\n```bash\nuvx edupage-mcp-full\n# or, if you prefer pip (into whatever environment your MCP client uses):\npip install edupage-mcp-full\n```\n\n`uvx` runs the package without a persistent install. If `uvx` is unavailable,\ninstall `uv` first (`pip install uv` or `winget install astral-sh.uv`).\n\n**Option C — from GitHub (latest source)**\n\nUse this if you want the latest changes before a PyPI release.\n\nRequirements: `uv` for `uvx`, or Python **3.10+** for `pip`.\n\n```bash\nuvx --from \"git+https://github.com/oliverhruby/edupage-mcp.git\" edupage-mcp-full\n# or\npip install \"git+https://github.com/oliverhruby/edupage-mcp.git\"\n```\n\n**Option D — Docker**\n\nUse this for an isolated container runtime.\n\nRequirements: Docker.\n\nPull a prebuilt image (recommended):\n\n```bash\ndocker pull ghcr.io/oliverhruby/edupage-mcp:latest\n\ndocker run --rm -i \\\n  -e EDUPAGE_USERNAME=your_username \\\n  -e EDUPAGE_PASSWORD=your_password \\\n  ghcr.io/oliverhruby/edupage-mcp:latest\n```\n\nVersion tags are also available (for example `v0.4.0`) if you prefer pinned\nimages.\n\nBuild locally from source (fallback):\n\n```bash\ndocker build -t edupage-mcp-full .\n\ndocker run --rm -i \\\n  -e EDUPAGE_USERNAME=your_username \\\n  -e EDUPAGE_PASSWORD=your_password \\\n  edupage-mcp-full\n```\n\nThe container uses the same environment variables described in\n[Configure credentials](#2-configure-credentials). It also includes a\n`HEALTHCHECK` (stdio process liveness by default; local TCP check in HTTP\ntransport modes).\n\nFor HTTP transports, set optional runtime vars:\n\n- `MCP_TRANSPORT`: `stdio` (default), `sse`, or `streamable-http`\n- `MCP_HOST`: bind host (default `127.0.0.1`)\n- `MCP_PORT`: bind port (default `8000`)\n- `MCP_API_KEY`: optional bearer token for HTTP auth\n\nWhen `MCP_API_KEY` is set, HTTP requests must include `Authorization: Bearer <key>`.\nIf `MCP_API_KEY` is not set, HTTP endpoints are unauthenticated. For production,\nprefer proper authentication and TLS via a reverse proxy or API gateway.\n\n> `pyproject.toml` pins `mcp<2` (the stable FastMCP v1 API). `mcp 2.x` renamed\n> `FastMCP` to `MCPServer` and changed the API surface; this server targets the\n> FastMCP v1 API for simplicity and stability.\n\n**Option C — development from source**\n\nUse this if you are contributing or debugging locally.\n\nRequirements: Python **3.10+**.\n\n```bash\ngit clone https://github.com/oliverhruby/edupage-mcp.git\ncd edupage-mcp\nuv sync               # or: python -m venv .venv && .venv/bin/python -m pip install -e .\nuv run edupage-mcp-full\n```\n\n**Option D — Docker**\n\nUse this for an isolated container runtime.\n\nRequirements: Docker.\n\nPull a prebuilt image (recommended):\n\n```bash\ndocker pull ghcr.io/oliverhruby/edupage-mcp:latest\n\ndocker run --rm -i \\\n  -e EDUPAGE_USERNAME=your_username \\\n  -e EDUPAGE_PASSWORD=your_password \\\n  ghcr.io/oliverhruby/edupage-mcp:latest\n```\n\nVersion tags are also available (for example `v0.4.0`) if you prefer pinned\nimages.\n\nBuild locally from source (fallback):\n\n```bash\ndocker build -t edupage-mcp-full .\n\ndocker run --rm -i \\\n  -e EDUPAGE_USERNAME=your_username \\\n  -e EDUPAGE_PASSWORD=your_password \\\n  edupage-mcp-full\n```\n\nThe container uses the same environment variables described in\n[Configure credentials](#2-configure-credentials). It also includes a\n`HEALTHCHECK` (stdio process liveness by default; local TCP check in HTTP\ntransport modes).\n\nFor HTTP transports, set optional runtime vars:\n\n- `MCP_TRANSPORT`: `stdio` (default), `sse`, or `streamable-http`\n- `MCP_HOST`: bind host (default `127.0.0.1`)\n- `MCP_PORT`: bind port (default `8000`)\n- `MCP_API_KEY`: optional bearer token for HTTP auth\n\nWhen `MCP_API_KEY` is set, HTTP requests must include `Authorization: Bearer <key>`.\nIf `MCP_API_KEY` is not set, HTTP endpoints are unauthenticated. For production,\nprefer proper authentication and TLS via a reverse proxy or API gateway.\n\n> `pyproject.toml` pins `mcp<2` (the stable FastMCP v1 API). `mcp 2.x` renamed\n> `FastMCP` to `MCPServer` and changed the API surface; this server targets the\n> FastMCP v1 API for simplicity and stability.\n\n### 2. Configure credentials\n\nEither set environment variables **or** pass credentials to `login` (see\n[Prompt examples](#prompt-examples)).\n\n```bash\n# Windows (persistent, per-user)\nsetx EDUPAGE_USERNAME \"your_username\"\nsetx EDUPAGE_PASSWORD \"your_password\"\nsetx EDUPAGE_SUBDOMAINS \"s1,s2,s3\"       # optional: multiple schools (auto-login + discovery)\n\n# macOS / Linux\nexport EDUPAGE_USERNAME=\"your_username\"\nexport EDUPAGE_PASSWORD=\"your_password\"\nexport EDUPAGE_SUBDOMAINS=\"s1,s2,s3\"     # optional\n```\n\n**Single school?** Just set `EDUPAGE_USERNAME` + `EDUPAGE_PASSWORD`. The server\nauto-discovers your school via the EduPage portal on startup — no subdomain needed.\n\n**Multiple schools?** Add `EDUPAGE_SUBDOMAINS` (comma-separated). The server\nlogs into all of them on startup with your shared credentials.\n\n### 3. Register with your MCP client\n\n**opencode** — add to `~/.config/opencode/opencode.json` (or `opencode.jsonc`):\n\n```jsonc\n{\n  \"mcp\": {\n    \"edupage\": {\n      \"type\": \"local\",\n      \"enabled\": true,\n      \"command\": [\"uvx\", \"edupage-mcp-full\"],\n      \"env\": {\n        \"EDUPAGE_USERNAME\": \"{env:EDUPAGE_USERNAME}\",\n        \"EDUPAGE_PASSWORD\": \"{env:EDUPAGE_PASSWORD}\",\n        \"EDUPAGE_SUBDOMAINS\": \"{env:EDUPAGE_SUBDOMAINS}\"\n      }\n    }\n  }\n}\n```\n\n> Put credentials in your shell/environment (or a `.env`) and reference them with\n> `{env:VAR}`, or hardcode them under `env:` directly. `uvx` will auto-provision\n> the package the first time; it must be on your `PATH`.\n\n**Claude Desktop / Cursor** — use `claude_desktop_config.json` /\n`.mcp.json` with a `mcpServers` entry in the standard shape, pointing\n`command`/`args` at the venv python and the `edupage_mcp.py` path, plus an\n`env` block with your credentials.\n\nAfter editing client config, **restart the client** so the MCP server is loaded.\n\n---\n\n## Prompt examples\n\n| User prompt | Likely tool call(s) | Expected response |\n|---|---|---|\n| \"Are we connected and logged in?\" | `auth_status` | Connected status, active school/subdomain, and login state per school. |\n| \"What classes do I have today?\" | `get_my_timetable` | A short timetable summary for today. |\n| \"Show me the 9.A schedule for 2026-09-10\" | `get_timetable target_type=\"class\" target_id=\"9.A\" date_str=\"2026-09-10\"` | Class timetable for that date. |\n| \"What grades do I have this term?\" | `get_grades term=\"FIRST\" year=2026` | Subject-by-subject grade overview for the selected term/year. |\n| \"Any substitutions today?\" | `get_timetable_changes` | Changes, cancellations, and replacements for today. |\n| \"What is for lunch and order option 2 for tomorrow\" | `get_meals` → `choose_meal date_str=\"2026-09-10\" meal_type=\"lunch\" number=2` | Meal menu and order confirmation (or a clear error if unavailable). |\n| \"Find Student A's timetable for tomorrow\" | `get_student_timetable name=\"Student A\" date_str=\"2026-09-10\"` | Student A's timetable; if found in multiple schools, one result per school. |\n| \"List teachers and send a hello to Teacher456\" | `get_teachers` → `send_message recipient_id=\"Teacher456\" body=\"Hello!\"` | Teacher list plus message sent confirmation. |\n| **\"What happened at school yesterday for my kids?\"** | `get_day_summary date_str=\"2026-09-09\"` (discovery index) → `get_day_summary date_str=\"2026-09-09\" name=\"Student A\" subdomain=\"school-a\"` → `... name=\"Student B\" subdomain=\"school-b\"` | **Discovery-first**: the no-name call lists each child per school; then one complete daily report call per child (timetable, substitutions, missing teachers, grades, meals, homework, assignments, absences, news, events, notifications). Keeps each response small and avoids mixing schools/students. |\n| **\"How was school today for Student A?\"** | `get_day_summary name=\"Student A\"` (defaults to today) | Human-readable summary via the bundled OpenCode skill `school-day-summary`. |\n\n---\n\n## Multiple schools & automatic student discovery\n\nEach subdomain (school) keeps its **own** logged-in session. There are two ways\nto log in to several schools at once:\n\n**A) Automatic on startup (recommended).** Set `EDUPAGE_SUBDOMAINS` (a\ncomma-separated list) plus the shared `EDUPAGE_USERNAME` / `EDUPAGE_PASSWORD` —\nthe server logs into all of them when it launches, so every tool is immediately\nready and students are discoverable across all schools with **no login call and\nno student→school mapping**:\n\n```bash\nsetx EDUPAGE_SUBDOMAINS \"school1,school2,school3\"   # Windows\nexport EDUPAGE_SUBDOMAINS=\"school1,school2,school3\" # macOS / Linux\n```\n\n```text\nget_schools        # lists school1, school2, school3 (logged in, with role)\nscan_students      # discovers Student A and Student B across those schools\nget_student_timetable name=\"Student A\"   # is found at school1 AND school2\n```\n\n**B) On demand with `login_all`.** Authenticate several schools at once, then pass\n`subdomain` to any data tool (it defaults to the last active subdomain when\nomitted):\n\n```text\nlogin_all subdomains=\"school1,school2\" usernames=\"u1,u2\" passwords=\"p1,p2\"\n\nget_my_timetable subdomain=\"school1\"\nget_my_timetable subdomain=\"school2\"\nauth_status          # shows all logged-in subdomains + which is active\n```\n\nYou can also call `login` once per school to add/lookup sessions incrementally.\n\n> **Single school?** No `EDUPAGE_SUBDOMAINS` needed — the server auto-discovers\n> your school via the portal on startup. For two or more schools, set\n> `EDUPAGE_SUBDOMAINS` (auto-login) or use `login_all` / repeated `login` calls.\n\n---\n\n## Students by name (e.g. \"timetable for Student A\")\n\nBecause the server **auto-discovers students across the configured\n`EDUPAGE_SUBDOMAINS`** (or every logged-in school when the variable is unset),\nyou don't need to know or state which school a student is in. Just ask for the\ntimetable by name and the server searches every school in scope:\n\n```text\n\"timetable for Student A\"  ->  get_student_timetable name=\"Student A\"\n```\n\n`get_student_timetable` (with no `subdomain`):\n\n1. searches **every school in the discovery scope** — the configured\n   `EDUPAGE_SUBDOMAINS`, or all logged-in schools when unset — for a student\n   whose first/last/full name matches (`scan_students` does just the discovery\n   step),\n2. for each school where the student is found, switches to the student account if\n   you're logged in as a parent, returns that student's timetable for the date, and\n   switches back to the parent account afterwards,\n3. returns **one result per school**.\n\nA student attending **more than one school** (e.g. Student at `school1` +\n`school2`) therefore yields a list of two per-school timetables — separate\nresults, never merged. This is the built-in replacement for maintaining a\nmanual \"Student → school1\" mapping: with `EDUPAGE_SUBDOMAINS` set, discovery is\nfully automatic.\n\n---\n\n## Tool reference\n\n| Tool | Description | Writes? |\n|---|---|---|\n| `login` | Log in with username/password/subdomain (env vars supported) | ✅ session |\n| `login_auto` | Log in via the EduPage portal (auto-detect school) | ✅ session |\n| `login_all` | Log in to multiple schools in one call | ✅ session |\n| `login_from_session` | Create a session from an existing `PHPSESSID` cookie | ✅ session |\n| `two_factor_check_confirmed` | Check if 2FA was approved on a device |  |\n| `two_factor_finish` | Finish 2FA (email/app code or device confirmation) | ✅ session |\n| `auth_status` | Which subdomains are logged in + active one |  |\n| `user_id` | Logged-in user id |  |\n| `school_year` | Current school year |  |\n| `get_my_timetable` | Logged-in user's timetable for a date |  |\n| `get_timetable` | Timetable of a teacher/student/class/classroom |  |\n| `get_student_timetable` | Student's timetable by name or id (role-aware, cross-school) | ✅ session |\n| `get_next_week_timetable` | Mon–Fri timetable for next week |  |\n| `get_next_ringing_time` | Next bell (break/lesson) at a given time |  |\n| `get_periods` | Bell schedule (period start/end times) |  |\n| `get_grades` | Grades, optionally by year & term |  |\n| `get_notifications` | Timeline notifications |  |\n| `get_notification_history` | Timeline notifications since a date |  |\n| `get_homework` | Homework from the timeline |  |\n| `get_assignments` | Homework/tests/exams from the timeline |  |\n| `get_absences` | Absence records from the timeline |  |\n| `get_upcoming_events` | Trips/excursions/meetings/holidays |  |\n| `get_news` | School news |  |\n| `get_timetable_changes` | Substitutions / timetable changes for a date |  |\n| `get_missing_teachers` | Teachers missing on a date |  |\n| `get_day_summary` | One-call daily report (timetable, substitutions, teachers, grades, meals, homework, assignments, absences, news, events, notifications) for a date; student by name/id (role-aware). **Discovery-first**: parent without `name`/`student_id` returns a lightweight per-school student index (`mode:\"discovery\"`); pass `full=True` to build full reports for every child. Bundles OpenCode skill `school-day-summary` for human-readable output. |  |\n| `get_meals` | Meal menu (snack/lunch/afternoon snack; `include_breakfast`/`include_dinner` add extras) |  |\n| `choose_meal` | Order a meal | ✅ |\n| `sign_off_meal` | Cancel an ordered meal | ✅ |\n| `rate_meal` | Rate a meal (quality/quantity) | ✅ |\n| `get_students` | Students in the logged-in user's class |  |\n| `get_all_students` | All students in the school (short list) |  |\n| `get_teachers` | All teachers |  |\n| `get_classes` | All classes |  |\n| `get_classrooms` | All classrooms |  |\n| `get_subjects` | All subjects |  |\n| `get_my_students` | Students visible to the logged-in account (one school) |  |\n| `find_student` | Look up a student's person_id by name (cross-school) |  |\n| `scan_students` | Auto-discover students across the configured `EDUPAGE_SUBDOMAINS` (or all logged-in schools when unset) |  |\n| `clear_student_cache` | Clear cached student rosters (one school or all schools) | ✅ cache |\n| `get_schools` | List logged-in schools + role per school |  |\n| `send_message` | Send a message to a user | ✅ |\n| `switch_to_student` | Switch to a student account by id or name (parent only) | ✅ session |\n| `switch_to_parent` | Switch back to the parent account | ✅ session |\n| `custom_request` | Raw request through the active session (GET/POST) | ✅ |\n\n---\n\n## Data & safety notes\n\n- Most tools are **read-only**. The ones marked **Writes? ✅** mutate EduPage\n  state (sent messages, ordered meals, switched accounts). Use them with care.\n- `get_homework`, `get_assignments`, `get_absences`, `get_upcoming_events` and\n  `get_news` derive their data from the **timeline notifications** — if the\n  school doesn't push certain event types, those tools may return empty lists.\n- `get_missing_teachers` is marked **experimental** upstream (parses HTML from\n  the substitution page) and can raise if a teacher's name no longer matches.\n- Meal `rate_meal` and ordering depend on the school publishing menus with the\n  matching identifiers; not all schools expose ratings.\n- `get_meals` first tries the per-student meal-ordering endpoint (needed for\n  ordering/ratings). When a school doesn't enable that, it falls back to the\n  school's **public canteen menu widget** (`/menu/?wid=menu_CanteenMenu_1`),\n  which is read-only (no ordering) and may include extra meals — pass\n  `include_breakfast=true` / `include_dinner=true` to also get Raňajky/Večera.\n\n---\n\n## Skills\n\nThe package includes an **OpenCode skill** (`school-day-summary`) at\n`<site-packages>/edupage_mcp/skills/school-day-summary/SKILL.md`. It teaches\nOpenCode agents how to turn `get_day_summary` JSON into a human-readable daily\nschool report.\n\n**OpenCode only:** To register it:\n```bash\nmkdir -p ~/.config/opencode/skills/school-day-summary\ncp <site-packages>/edupage_mcp/skills/school-day-summary/SKILL.md \\\n   ~/.config/opencode/skills/school-day-summary/SKILL.md\n```\nRestart OpenCode; the agent can then answer *\"what happened at school yesterday\nfor my kids?\"* by calling `get_day_summary` per child.\n\n**Other MCP clients (Copilot, Claude, Cursor, etc.)** — call `get_day_summary`\ndirectly; they receive the full structured JSON. Formatting is client-specific\n(no skill system in the MCP protocol).\n\n---\n\n## Contributing\n\nContributor and maintainer guidance is in [CONTRIBUTING.md](CONTRIBUTING.md).\n\n- Contribution workflow and local setup\n- Architecture and implementation details\n- Release process (PyPI, GitHub Releases, GHCR)\n- CI quality gates and upstream coverage drift checks\n\n---\n\n## Limitations\n\n- **Unofficial/read-mostly by design.** EduPage can change its endpoints at any\n  time; reliability ultimately depends on `edupage-api`, not this wrapper.\n- **No CAPTCHA bypass.** If EduPage presents a CAPTCHA during login, log in via\n  browser first, then use `login_from_session` with the resulting `PHPSESSID`.\n- **2FA requires human interaction** (approve on device or provide a code).\n- **Parent/teacher accounts** are only partially verified upstream; some parent\n  methods are best-effort.\n- The auth session lives for the lifetime of the MCP server process; restarting\n  the client means logging in again.\n- Cross-school student discovery depends on being logged into all relevant\n  schools (via `EDUPAGE_SUBDOMAINS`, `login_all`, or repeated `login` calls).\n  If a school is not logged in, that student's results from that school cannot\n  be discovered.\n\n---\n\n## Support\n\nIf you like this project and want to support or request a feature, send me a\nbeer, it keeps my mind relaxed and ideas will come :-)\n\n[![Support via PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.me/oliverhruby/)\n\n---\n\n## License\n\n[MIT](LICENSE) © Oliver Hrubý\n\nThis project is **not affiliated with or endorsed by** Ascora (EduPage) or by\nthe authors of `edupage-api`. EduPage is a registered trademark of its\nrespective owner(s).\n",
  "bytes": 25620,
  "sha": "e3ed194ba72cc4dc69e79cf1ea17bc7c6dde6930a958d8f8f31d01ce23093a55",
  "repo_slug": "oliverhruby/edupage-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_oliverhruby_edupage_mcp_502d932e/readme"
}