
EduPage MCP Server
io.github.oliverhruby由 GitHub 帳號 oliverhruby 發布v0.7.0更新於 Oct 24, 2026
EduPage MCP: timetables, grades, homework, meals, messages, 2FA, multi-school, role-aware.
概覽
非官方 MCP 伺服器,讓助理讀取並操作學生、家長或教師的 EduPage 學校帳號:課表、成績、作業、餐食與訊息。
- 可以做什麼
- 登入一所或多所學校,支援完成兩步驟驗證與以工作階段 Cookie 登入,並列出可用學校及各校角色
- 查詢本人、學生、教師、班級或教室的課表,以及鐘聲時間表、下週課表和學年
- 讀取成績、時間軸通知、作業內文與附件、調課資訊、缺席教師和名冊
- 一次呼叫產生某日的日報,涵蓋課表、成績、餐食、作業、缺席、新聞與活動
- 訂餐、取消或評價餐食,傳送訊息,在家長與學生帳號間切換,並將附件下載到本機磁碟
- 適用情境
- 適合家長、學生或教師用自然語言向助理詢問在校情況、查看成績與作業,或在不開啟 EduPage 的情況下處理訂餐和訊息。多個孩子就讀不同學校的情況可透過自動探索學生來支援。
- 執行需求
- 以 stdio 在本機執行,通常透過 uvx 啟動 PyPI 套件 edupage-mcp-full(需要 uv,或用 pip 時需 Python 3.10+)。需要 EduPage 帳號:EDUPAGE_USERNAME 與 EDUPAGE_PASSWORD,多校時可設 EDUPAGE_SUBDOMAINS。需要連線至 EduPage 的網路;兩步驟驗證需人工確認或提供驗證碼。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 EduPage MCP Server,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
EduPage MCP Server
[GitHub release] [Glama Grade] [Quality gates] [Security] [Container security] [Coverage drift]
Project
A Model Context Protocol (MCP) server that exposes the full functionality of the
edupage-api Python library to AI
agents such as opencode, Claude, Cursor and any other MCP client.
EduPage is a school information system used across Europe. This server lets you query and operate a student / teacher / parent EduPage account directly from your agent: timetables, grades, homework, substitutions, meals (including ordering), messages, rosters, parent child-switching and more — including multiple schools (e.g. two children attending different schools).
⚠️ Unofficial API. Like all EduPage MCP servers, this relies on the community-maintained
edupage-apilibrary, which talks to EduPage's undocumented endpoints. Use read-only features freely; use the write features (send_message, meal ordering, child switching) carefully.
Table of Contents
- Why another EduPage MCP server?
- What it provides
- Getting started
- Prompt examples
- Multiple schools (subdomains)
- Tool reference
- Data & safety notes
- Contributing
- Limitations
- Support
- License
Why another EduPage MCP server?
Two other EduPage MCP servers already exist:
mrtineu/edupage-mcp— also published on PyPI asedupage-mcpmhlavac/edupage-mcp
Both are good and I have no affiliation with them — they are simply referenced here for honest comparison. They primarily focus on the read-only surface of the API.
This project deliberately goes further:
Key differentiators:
- Multi-school automatic discovery. Set
EDUPAGE_SUBDOMAINSwith one shared login and the server auto-discovers students across all schools — no need to maintain a manual "Student → school1, Student → school2" mapping. A student at two schools (e.g. Student atschool1+school2) is found automatically with separate per-school results. - Role-aware tools. The server detects whether you're a parent, student, or
teacher at each school and behaves accordingly —
get_student_timetableswitches to the student account for parents, returns direct timetables for students. No tool duplication. - Full write surface. Meal ordering/rating, message sending, student switching — the other servers don't cover these.
Comparison checked 2026-09-28. If a row is wrong, please open an issue.
What it provides
A single stdio MCP server exposing 31 tools (published on PyPI as
edupage-mcp-full):
- Authentication —
login(by credentials, portal auto-detect, or aPHPSESSIDcookie viamethod=),login_all(multi-school, one call),two_factor_finish(complete a pending 2FA),get_subdomains(schools available to the account with role/user id per school + env config, live subdomain discovery for parents). The formerauth_status,user_id,login_auto,login_from_session, andtwo_factor_check_confirmedtools are folded into these. - Timetables —
get_my_timetable,get_timetable(teacher/student/class/ classroom;end_datefor a range, formerlyget_timetable_range),get_student_timetable(student by name, cross-school),get_next_week_timetable,get_next_ringing_time,get_periods,get_school_year - Students —
find_student(name → person_id, cross-school),get_student_timetable(cross-school, role-aware),scan_students(auto-discover all students across schools),get_my_students(classmates or school-wide for parents),switch_to_student(by id or name, parent only),switch_to_parent,clear_student_cache(force refresh cached student lists) - Schools —
get_subdomains(subdomains available to the account — live-discovered for parents, limited byEDUPAGE_SUBDOMAINSwhen set — plus session state per school) - Grades —
get_grades - Timeline / notifications —
get_timeline(category=for homework, assignments, absences, events, news, or full history since a date) - Homework —
get_timeline(category='homework')to list assignments (ids inadditional_data.superid),get_homework_materialto read one assignment's body text, dates and attachment list (the notification alone only carries the title and due date),download_attachmentto save one attachment to disk - Substitutions —
get_timetable_changes,get_missing_teachers - Meals —
get_meals,choose_meal,sign_off_meal,rate_meal - Day summaries —
get_day_summary(one call: timetable, substitutions, missing teachers, grades, meals, homework, assignments, absences, news, events, notifications for a date — "what happened yesterday at school" in a single round trip; each section is isolated so one failure doesn't kill the report). A bundled agent skill (school-day-summary) turns that JSON into a human-readable daily report — install it withedupage-mcp-full install-skill(see Skills); every client can also callget_day_summarydirectly and read the JSON. - Rosters —
get_roster(roster_type=for students, all students, teachers, classes, classrooms, or subjects),get_my_students - Actions —
send_message,switch_to_student,switch_to_parent,custom_request
Getting started
You need an MCP-capable client (opencode, Claude Desktop, Cursor, etc.).
1. Install
If you are using an AI coding client, a simple prompt is often enough to get started, for example: "Install the EduPage MCP as described in this GitHub repository oliverhruby/edupage-mcp". Most MCP-capable clients can then guide you through the available setup options.
Option A — as an agent plugin (recommended: the server and the skill in one install)
For VS Code, GitHub Copilot and Claude Code this repo ships a plugin that
installs the server together with the school-day-summary agent skill:
Claude Code reads the same marketplace:
opencode, Cursor and Windsurf read Agent Skills but not plugins — for those, and for every other install route, see docs/PLUGINS.md.
Option B — one-shot with APM (the server and the skill in one command, optional, emerging standard)
APM (Agent Package Manager) is an emerging open standard for distributing agent context — think npm for agent skills, MCP servers and instructions. This route is optional: Option A and every route below work exactly as before. If you already use APM (or want to try it), it is the only cross-harness one-shot install here.
-
Install the CLI once. Requirements:
git, plusuvfor the server runtime.- Windows:
winget install --id Microsoft.APM -e(orscoop bucket add apm https://github.com/microsoft/scoop-apm; scoop install apm) - macOS / Linux:
brew install apm - Any platform with Python 3.10+:
pip install apm-cli - Other options: installation docs
- Windows:
-
Install this package:
One command does both:
- deploys the
school-day-summaryskill into the harness's skills directory (.claude/skills/,.agents/skills/, ...); - writes the
uvx edupage-mcp-fullstdio server entry into the MCP config of every harness APM detects (Claude Code, GitHub Copilot, Cursor, opencode, Codex, Gemini, Windsurf, Kiro, ...); add--target claude(or another target) to force one harness.
- deploys the
-
Verify:
apm uninstall oliverhruby/edupage-mcpremoves the package and the deployed skill files, but leaves the MCP server entry it wrote into.mcp.json(and other harness configs) — delete that entry yourself if you want it gone.
Credentials are never embedded in the package: set EDUPAGE_USERNAME /
EDUPAGE_PASSWORD (and EDUPAGE_SUBDOMAINS for multi-school accounts) before
running apm install — see 2. Configure credentials.
Pinning. Append #<sha> (or #<tag> once a release contains apm.yml) to
pin an exact revision and silence APM's "dependency unpinned" warning; without
a pin, APM records the resolved commit in apm.lock.yaml. Releases up to
v0.7.0 predate the manifest, so use a commit sha until the next release.
The Claude Code plugin/marketplace install (Option A) remains supported and
unchanged — APM is an additional install route, declared in this repo's
apm.yml.
Option C — from MCP Registry (one-click, server only, no skill)
The server is listed in the MCP Registry.
In VS Code or GitHub Copilot, search for "EduPage MCP" and install with one click.
Or use the direct deeplink: mcp://install/io.github.oliverhruby/edupage-mcp
Option D — from PyPI
Use this for normal usage with a released version.
Requirements: uv for uvx, or Python 3.10+ for pip.
uvx runs the package without a persistent install. If uvx is unavailable,
install uv first (pip install uv or winget install astral-sh.uv).
Option E — from GitHub (latest source)
Use this if you want the latest changes before a PyPI release.
Requirements: uv for uvx, or Python 3.10+ for pip.
Option F — Docker
Use this for an isolated container runtime.
Requirements: Docker.
Pull a prebuilt image (recommended):
Version tags are also available (for example v0.4.0) if you prefer pinned
images.
Build locally from source (fallback):
The container uses the same environment variables described in
Configure credentials. It also includes a
HEALTHCHECK (stdio process liveness by default; local TCP check in HTTP
transport modes).
For HTTP transports, set optional runtime vars:
MCP_TRANSPORT:stdio(default),sse, orstreamable-httpMCP_HOST: bind host (default127.0.0.1)MCP_PORT: bind port (default8000)MCP_API_KEY: optional bearer token for HTTP auth
When MCP_API_KEY is set, HTTP requests must include Authorization: Bearer <key>.
If MCP_API_KEY is not set, HTTP endpoints are unauthenticated. For production,
prefer proper authentication and TLS via a reverse proxy or API gateway.
pyproject.tomlpinsmcp<2(the stable FastMCP v1 API).mcp 2.xrenamedFastMCPtoMCPServerand changed the API surface; this server targets the FastMCP v1 API for simplicity and stability.
Option G — development from source
Use this if you are contributing or debugging locally.
Requirements: Python 3.10+.
2. Configure credentials
Either set environment variables or pass credentials to login (see
Prompt examples).
Single school? Just set EDUPAGE_USERNAME + EDUPAGE_PASSWORD. The server
auto-discovers your school via the EduPage portal on startup — no subdomain needed.
Multiple schools? Add EDUPAGE_SUBDOMAINS (comma-separated). The server
logs into all of them on startup with your shared credentials.
3. Register with your MCP client
opencode — add to ~/.config/opencode/opencode.json (or opencode.jsonc):
Put credentials in your shell/environment (or a
.env) and reference them with{env:VAR}, or hardcode them underenv:directly.uvxwill auto-provision the package the first time; it must be on yourPATH.
Claude Desktop / Cursor — use claude_desktop_config.json /
.mcp.json with a mcpServers entry in the standard shape, pointing
command/args at the venv python and the edupage_mcp.py path, plus an
env block with your credentials.
After editing client config, restart the client so the MCP server is loaded.
Prompt examples
Multiple schools & automatic student discovery
Each subdomain (school) keeps its own logged-in session. There are two ways to log in to several schools at once:
A) Automatic on startup (recommended). Set EDUPAGE_SUBDOMAINS (a
comma-separated list) plus the shared EDUPAGE_USERNAME / EDUPAGE_PASSWORD —
the server logs into all of them when it launches, so every tool is immediately
ready and students are discoverable across all schools with no login call and
no student→school mapping:
B) On demand with login_all. Authenticate several schools at once, then pass
subdomain to any data tool (it defaults to the last active subdomain when
omitted):
You can also call login once per school to add/lookup sessions incrementally.
Single school? No
EDUPAGE_SUBDOMAINSneeded — the server auto-discovers your school via the portal on startup. For two or more schools, setEDUPAGE_SUBDOMAINS(auto-login) or uselogin_all/ repeatedlogincalls.
Students by name (e.g. "timetable for Student A")
Because the server auto-discovers students across the configured
EDUPAGE_SUBDOMAINS (or every logged-in school when the variable is unset),
you don't need to know or state which school a student is in. Just ask for the
timetable by name and the server searches every school in scope:
get_student_timetable (with no subdomain):
- searches every school in the discovery scope — the configured
EDUPAGE_SUBDOMAINS, or all logged-in schools when unset — for a student whose first/last/full name matches (scan_studentsdoes just the discovery step), - for each school where the student is found, switches to the student account if you're logged in as a parent, returns that student's timetable for the date, and switches back to the parent account afterwards,
- returns one result per school.
A student attending more than one school (e.g. Student at school1 +
school2) therefore yields a list of two per-school timetables — separate
results, never merged. This is the built-in replacement for maintaining a
manual "Student → school1" mapping: with EDUPAGE_SUBDOMAINS set, discovery is
fully automatic.
Tool reference
Data & safety notes
- Most tools are read-only. The ones marked Writes? ✅ mutate EduPage state (sent messages, ordered meals, switched accounts). Use them with care.
download_attachmentis the one tool that writes to local disk: it saves intodest_dir(default<tempdir>/homework), takes the name from the server'scontent-dispositionwhen present, and appends(1),(2), ... rather than overwriting anything. An HTML login/error page is refused instead of being written out as an attachment.custom_requestreturns text only: a binary body is refused with a pointer todownload_attachment, and a text body over 60000 characters comes back truncated with an explicittruncated: true.get_timelinecategorieshomework,assignments,absences,eventsandnewsderive their data from the timeline notifications — if the school doesn't push certain event types, those categories may return empty lists.get_missing_teachersis marked experimental upstream (parses HTML from the substitution page) and can raise if a teacher's name no longer matches.- Meal
rate_mealand ordering depend on the school publishing menus with the matching identifiers; not all schools expose ratings. get_mealsfirst tries the per-student meal-ordering endpoint (needed for ordering/ratings). When a school doesn't enable that, it falls back to the school's public canteen menu widget (/menu/?wid=menu_CanteenMenu_1). All five slots (breakfast/snack/lunch/afternoon_snack/dinner) are always returned; slots the school doesn't publish areNone.
Skills
The package ships one agent skill (school-day-summary). It teaches a
coding agent how to turn get_day_summary JSON into a human-readable daily
school report — "what happened yesterday for my kids?"
Installing the plugin ships this skill together with the server. To install the skill on its own:
Each agent it touches prints one line:
Restart your agent afterwards so it picks the skill up.
Options
Where it goes
Re-running is safe: a file that is already identical is reported as
skipped (identical), and one that differs is left alone unless you pass
--force, so a skill you edited locally is never silently clobbered.
Prefer to place the file yourself? edupage-mcp-full install-skill --print
prints the exact path of the bundled SKILL.md in the installed package.
Other MCP clients (Claude, Cursor, or any client without a skill system) can
just call get_day_summary directly — they receive the full structured JSON.
Formatting is client-specific. The base MCP protocol has no skill concept (an
io.modelcontextprotocol/skills extension is specified, but this server does not
implement it yet), which is why distribution goes through the plugin and the
installer above. See docs/PLUGINS.md for every install route.
Contributing
Contributor and maintainer guidance is in CONTRIBUTING.md.
- Contribution workflow and local setup
- Architecture and implementation details
- Release process (PyPI, GitHub Releases, GHCR)
- CI quality gates and upstream coverage drift checks
Limitations
- Unofficial/read-mostly by design. EduPage can change its endpoints at any
time; reliability ultimately depends on
edupage-api, not this wrapper. - No CAPTCHA bypass. If EduPage presents a CAPTCHA during login, log in via
browser first, then use
login method="session"with the resultingPHPSESSID. - 2FA requires human interaction (approve on device or provide a code).
- Parent/teacher accounts are only partially verified upstream; some parent methods are best-effort.
- The auth session lives for the lifetime of the MCP server process; restarting the client means logging in again.
- Cross-school student discovery depends on being logged into all relevant
schools (via
EDUPAGE_SUBDOMAINS,login_all, or repeatedlogincalls). If a school is not logged in, that student's results from that school cannot be discovered.
Support
If you like this project and want to support or request a feature, send me a beer, it keeps my mind relaxed and ideas will come :-)
License
MIT © Oliver Hrubý
This project is not affiliated with or endorsed by Ascora (EduPage) or by
the authors of edupage-api. EduPage is a registered trademark of its
respective owner(s).
來源:README.md,提交 b35ce65
工具
0版本歷史
7- v0.7.0最新Oct 12, 2026
- v0.6.0Oct 2, 2026
- v0.5.5Oct 2, 2026
- v0.5.4Oct 1, 2026
- v0.5.3Sep 30, 2026
- v0.5.2Sep 30, 2026
- v0.4.11Sep 16, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分