EduPage MCP Server
This server is an MCP interface to EduPage that lets AI agents authenticate, read school data, and perform actions across one or multiple schools.
Authentication: login with credentials, portal auto-detection, PHPSESSID session, 2FA completion, multi-school login_all, and subdomain/session status via get_subdomains.
Timetables: get your own timetable, timetables by teacher/student/class/classroom, student timetables by name or id across schools, next week's timetable, bell schedule and next ringing time.
Grades: view grades, optionally filtered by school year and term.
Timeline/notifications: get recent updates, history, homework, assignments, absences, events, and news.
Substitutions: view timetable changes and missing teachers for a date.
Meals: read the full menu (breakfast, snack, lunch, afternoon snack, dinner), order meals, cancel orders, and rate meals.
Day summaries: get a one-call daily report covering timetable, substitutions, teachers, grades, meals, homework, assignments, absences, news, events, and notifications; for parents it can discover children per school and report per child.
Rosters/students: find students by name, scan/discover students across schools, get visible students, list teachers/classes/classrooms/subjects, and clear cached student data.
Actions: send messages, switch to/from a student account (parent only), and make raw custom requests to EduPage endpoints.
Multi-school support: maintain separate sessions per school, auto-discover students across schools, and use one shared login for multiple subdomains.
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., "@EduPage MCP ServerWhat is my timetable for tomorrow?"
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.
EduPage MCP Server
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.
Related MCP server: edookit-mcp
Table of Contents
Why another EduPage MCP server?
Two other EduPage MCP servers already exist:
mrtineu/edupage-mcp— also published on PyPI asedupage-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:
Capability | mhlavac | mrtineu (PyPI) | this project |
Advanced login — portal auto-detect, 2FA, session id ( | partial (portal) | basic only | ✅ |
Timetables (own + any teacher/class/room) | ✅ | ✅ | ✅ |
Grades (all / by term & year) | ✅ | ✅ | ✅ |
Substitutions / timetable changes | ✅ | ✅ | ✅ |
Meals — read menu | ✅ | ✅ | ✅ |
Meals — choose / sign-off / rate | ❌ | ❌ | ✅ |
Send messages ( | ✅ | ❌ | ✅ |
Parent student switching (switch to/from student) | partial (list) | ❌ | ✅ |
Next ringing time / bell schedule | ❌ | ❌ | ✅ |
Raw session custom request | ❌ | ❌ | ✅ |
Multiple schools (auto-login + discovery) | ❌ | ❌ | ✅ |
Role-aware (parent / student / teacher) | ❌ | ❌ | ✅ |
Day summaries (one-call daily report) | ❌ | ❌ | ✅ |
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.
What it provides
A single stdio MCP server exposing 29 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_yearStudents —
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_gradesTimeline / notifications —
get_timeline(category=for homework, assignments, absences, events, news, or full history since a date)Substitutions —
get_timetable_changes,get_missing_teachersMeals —
get_meals,choose_meal,sign_off_meal,rate_mealDay 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). Includes an OpenCode skill (school-day-summary) for human-readable formatting in OpenCode; other clients use the raw JSON directly.Rosters —
get_roster(roster_type=for students, all students, teachers, classes, classrooms, or subjects),get_my_studentsActions —
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 — from MCP Registry (recommended, one-click in VS Code / GitHub Copilot)
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 B — from PyPI
Use this for normal usage with a released version.
Requirements: uv for uvx, or Python 3.10+ for pip.
uvx edupage-mcp-full
# or, if you prefer pip (into whatever environment your MCP client uses):
pip install edupage-mcp-fulluvx runs the package without a persistent install. If uvx is unavailable,
install uv first (pip install uv or winget install astral-sh.uv).
Option C — 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.
uvx --from "git+https://github.com/oliverhruby/edupage-mcp.git" edupage-mcp-full
# or
pip install "git+https://github.com/oliverhruby/edupage-mcp.git"Option D — Docker
Use this for an isolated container runtime.
Requirements: Docker.
Pull a prebuilt image (recommended):
docker pull ghcr.io/oliverhruby/edupage-mcp:latest
docker run --rm -i \
-e EDUPAGE_USERNAME=your_username \
-e EDUPAGE_PASSWORD=your_password \
ghcr.io/oliverhruby/edupage-mcp:latestVersion tags are also available (for example v0.4.0) if you prefer pinned
images.
Build locally from source (fallback):
docker build -t edupage-mcp-full .
docker run --rm -i \
-e EDUPAGE_USERNAME=your_username \
-e EDUPAGE_PASSWORD=your_password \
edupage-mcp-fullThe 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 C — development from source
Use this if you are contributing or debugging locally.
Requirements: Python 3.10+.
git clone https://github.com/oliverhruby/edupage-mcp.git
cd edupage-mcp
uv sync # or: python -m venv .venv && .venv/bin/python -m pip install -e .
uv run edupage-mcp-fullOption D — Docker
Use this for an isolated container runtime.
Requirements: Docker.
Pull a prebuilt image (recommended):
docker pull ghcr.io/oliverhruby/edupage-mcp:latest
docker run --rm -i \
-e EDUPAGE_USERNAME=your_username \
-e EDUPAGE_PASSWORD=your_password \
ghcr.io/oliverhruby/edupage-mcp:latestVersion tags are also available (for example v0.4.0) if you prefer pinned
images.
Build locally from source (fallback):
docker build -t edupage-mcp-full .
docker run --rm -i \
-e EDUPAGE_USERNAME=your_username \
-e EDUPAGE_PASSWORD=your_password \
edupage-mcp-fullThe 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.
2. Configure credentials
Either set environment variables or pass credentials to login (see
Prompt examples).
# Windows (persistent, per-user)
setx EDUPAGE_USERNAME "your_username"
setx EDUPAGE_PASSWORD "your_password"
setx EDUPAGE_SUBDOMAINS "s1,s2,s3" # optional: multiple schools (auto-login + discovery)
# macOS / Linux
export EDUPAGE_USERNAME="your_username"
export EDUPAGE_PASSWORD="your_password"
export EDUPAGE_SUBDOMAINS="s1,s2,s3" # optionalSingle 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):
{
"mcp": {
"edupage": {
"type": "local",
"enabled": true,
"command": ["uvx", "edupage-mcp-full"],
"env": {
"EDUPAGE_USERNAME": "{env:EDUPAGE_USERNAME}",
"EDUPAGE_PASSWORD": "{env:EDUPAGE_PASSWORD}",
"EDUPAGE_SUBDOMAINS": "{env:EDUPAGE_SUBDOMAINS}"
}
}
}
}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
User prompt | Likely tool call(s) | Expected response |
"Are we connected and logged in?" |
| Available school subdomains (live-discovered for parents), active school/subdomain, env config, and login state per school. |
"What classes do I have today?" |
| A short timetable summary for today. |
"Show me the 9.A schedule for 2026-09-10" |
| Class timetable for that date. |
"What grades do I have this term?" |
| Subject-by-subject grade overview for the selected term/year. |
"Any substitutions today?" |
| Changes, cancellations, and replacements for today. |
"What is for lunch and order option 2 for tomorrow" |
| Meal menu and order confirmation (or a clear error if unavailable). |
"Find Student A's timetable for tomorrow" |
| Student A's timetable; if found in multiple schools, one result per school. |
"List teachers and send a hello to Teacher456" |
| Teacher list plus message sent confirmation. |
"What happened at school yesterday for my kids?" |
| 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. |
"How was school today for Student A?" |
| Human-readable summary via the bundled OpenCode skill |
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:
setx EDUPAGE_SUBDOMAINS "school1,school2,school3" # Windows
export EDUPAGE_SUBDOMAINS="school1,school2,school3" # macOS / Linuxget_subdomains # lists school1, school2, school3 (logged in, with role)
scan_students # discovers Student A and Student B across those schools
get_student_timetable name="Student A" # is found at school1 AND school2B) 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):
login_all subdomains="school1,school2" usernames="u1,u2" passwords="p1,p2"
get_my_timetable subdomain="school1"
get_my_timetable subdomain="school2"
get_subdomains # shows all logged-in subdomains + which is activeYou 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:
"timetable for Student A" -> get_student_timetable name="Student A"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
Tool | Description | Writes? |
| Log in with username/password; | ✅ session |
| Log in to multiple schools in one call | ✅ session |
| Finish a pending 2FA login (email/app | ✅ session |
| Subdomains available to the account (live-discovered for parents; limited to | |
| Current school year | |
| Logged-in user's timetable for a date | |
| Timetable of a teacher/student/class/classroom; | |
| Student's timetable by name or id (role-aware, cross-school) | ✅ session |
| Mon–Fri timetable for next week | |
| Next bell (break/lesson) at a given time | |
| Bell schedule (period start/end times) | |
| Grades, optionally by year & term | |
| Timeline notifications, one | |
| Substitutions / timetable changes for a date | |
| Teachers missing on a date | |
| One-call daily report (timetable, substitutions, teachers, grades, meals incl. breakfast/dinner when published, homework, assignments, absences, news, events, notifications) for a date; student by name/id (role-aware). Discovery-first: parent without | |
| Meal menu (all 5 slots: breakfast, snack, lunch, afternoon snack, dinner) | |
| Order a meal | ✅ |
| Cancel an ordered meal | ✅ |
| Rate a meal (quality/quantity) | ✅ |
| One | |
| Students visible to the logged-in account (one school) | |
| Look up a student's person_id by name (cross-school) | |
| Auto-discover students across the configured | |
| Clear cached student rosters (one school or all schools) | ✅ cache |
| Available school subdomains + role/session per school | |
| Send a message to a user | ✅ |
| Switch to a student account by id or name (parent only) | ✅ session |
| Switch back to the parent account | ✅ session |
| Raw request through the active session (GET/POST) | ✅ |
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.
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 includes an OpenCode skill (school-day-summary) at
<site-packages>/edupage_mcp/skills/school-day-summary/SKILL.md. It teaches
OpenCode agents how to turn get_day_summary JSON into a human-readable daily
school report.
OpenCode only: To register it:
mkdir -p ~/.config/opencode/skills/school-day-summary
cp <site-packages>/edupage_mcp/skills/school-day-summary/SKILL.md \
~/.config/opencode/skills/school-day-summary/SKILL.mdRestart OpenCode; the agent can then answer "what happened at school yesterday
for my kids?" by calling get_day_summary per child.
Other MCP clients (Copilot, Claude, Cursor, etc.) — call get_day_summary
directly; they receive the full structured JSON. Formatting is client-specific
(no skill system in the MCP protocol).
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).
Available Tools
29 toolschoose_mealAInspect
Order/choose a meal. Writes: books the selected menu for the date.
Args:
date_str: YYYY-MM-DD to order for.
meal_type: 'snack' | 'lunch' | 'afternoon_snack'.
number: 1-based menu choice among the chooseable menus (see get_meals).
subdomain: School to query (defaults to the active subdomain).
Returns: dict: {'ordered': True, meal_type, date, number}.
Notes:
- Read get_meals first for the date to pick a valid number.
- To cancel, use sign_off_meal.
| Name | Required | Description | Default |
|---|---|---|---|
| number | Yes | ||
| date_str | Yes | ||
| meal_type | Yes | ||
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It clearly discloses that this is a write operation ('Writes: books the selected menu'), specifies the return dict, and gives operational notes. It omits details like permissions and failure modes, but the core side effect is transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and structured with Args, Returns, and Notes sections. The write nature is front-loaded, and every sentence adds relevant information with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a write tool with no annotations and no output schema, the definition covers all parameters, the return format, and cross-tool prerequisites. The agent has enough to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must fully explain the parameters. It does: date_str format, meal_type allowed values, number's 1-based semantics tied to get_meals, and subdomain default. This adds meaning the schema completely lacks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Order/choose a meal' and clarifies 'Writes: books the selected menu for the date,' giving a specific verb and resource. It also distinguishes itself from siblings by naming get_meals as the read prerequisite and sign_off_meal as the cancellation alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly tells the agent to read `get_meals` first to obtain a valid `number`, and says to use `sign_off_meal` to cancel. This is clear context and an alternative, though it does not enumerate conditions for every sibling tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
clear_student_cacheAInspect
Force refresh of cached student data. Writes: drops the local cache so the
next student lookup re-fetches from EduPage. Call this after students are
added/removed from a school, or if scan_students/find_student seems stale.
Args: subdomain: School whose cache to clear. Without it, clears ALL schools.
Returns: dict: {'cleared': <subdomain|'all'>, 'entries_removed': }.
| Name | Required | Description | Default |
|---|---|---|---|
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it succeeds: it discloses that this is a write operation that drops cache, affects the next lookup by forcing a refetch, and can clear all schools. The return shape is also described, giving a complete picture of side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and efficient: purpose first, then usage trigger, then argument semantics, then return format. Every sentence earns its place without redundant filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though there is no output schema, the description includes the return dict format. Combined with argument explanation and usage guidance, the description gives an agent everything needed to invoke the tool correctly and understand its consequences.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and the subdomain parameter has no schema description, but the tool description fully explains it: 'School whose cache to clear. Without it, clears ALL schools.' This adds critical meaning beyond the raw schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and resource: it drops the local student data cache so the next lookup re-fetches from EduPage. This makes the tool's purpose unambiguous and clearly distinguishes it from read-only lookup tools like scan_students and find_student.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit trigger conditions are provided: call this after students are added/removed or when scan_students/find_student appears stale. It also warns about the default behavior of clearing ALL schools when subdomain is omitted, which is essential guidance for correct use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
custom_requestAInspect
Send a raw request to the Edupage server using the active session. Can perform writes depending on the endpoint — treat as write-capable.
Args:
url: Absolute URL, or a path like '/export/ajax_prevedene_meno.php'
(resolved against https://<subdomain>.edupage.org).
method: 'GET' or 'POST'.
data: Request body (for POST).
headers: JSON string of extra headers, e.g. '{"Accept": "application/json"}'.
subdomain: School whose session to use (defaults to the active).
Returns: dict: {'status_code': int, 'text': body}.
Notes: - Low-level escape hatch for endpoints not covered by the dedicated tools — prefer those when available. Parse the returned text yourself; fields are not pre-serialized.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| data | No | ||
| method | Yes | ||
| headers | No | {} | |
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description correctly carries the full burden. It discloses the most critical traits: write capability ('treat as write-capable'), use of the active session, and that responses are raw text ('Parse the returned text yourself; fields are not pre-serialized'). It falls short only on error/edge-case behavior (e.g., network failures, non-2xx handling, auth expiry) which would be useful for a low-level tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The summary line is front-loaded with the critical warning about write capability, followed by tight Args/Returns/Notes sections where every line earns its place. Though longer than minimal descriptions, the length is justified by the 0% schema coverage that forces parameter documentation into the description. No redundant text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no annotations and no output schema, the description covers all the essential operational context: what it does, all parameter formats, the return shape, session behavior, and the write risk. The only meaningful gap is absence of error/disaster behavior (what happens on network failure, invalid session, or non-2xx status codes), which an agent invoking raw HTTP should reasonably expect to know.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description wholly compensates — and does so exceptionally. It documents all 5 parameters with meaningful detail: URL resolution rules ('resolved against https://<subdomain>.edupage.org'), allowed method values, body applicability, header JSON format with an example, and subdomain session semantics including its default.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Send a raw request to the Edupage server using the active session') and immediately flags the key behavioral caveat ('Can perform writes depending on the endpoint'). The Notes section explicitly frames this as the low-level fallback for endpoints not covered by dedicated tools, which clearly differentiates it from the 27 sibling tools without needing to compare schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly instructs when to use: 'Low-level escape hatch for endpoints not covered by the dedicated tools — prefer those when available.' This gives the agent a clear selection rule versus alternatives. It could name specific siblings, but the class of dedicated tools is well-understood and the general routing instruction is actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_studentAInspect
Look up a student by first/last/full name using tiered matching. Read-only.
Without a subdomain, searches ALL logged-in schools and returns one result
per school where the student is found.
Args: name: First, last or full student name (also 'Novák V.' short names). subdomain: Restrict the search to one school (default: all logged-in schools in scope).
Returns:
dict with results: [{name, student_id, class_id, subdomain, tier,
confidence}] sorted by confidence. Tiers: 1=exact, 2=first name,
3=last name, 4=substring.
Notes:
- Use a student_id from the results with get_student_timetable /
get_day_summary for unambiguous lookups.
- Ambiguous matches surface all candidates instead of guessing.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full disclosure burden and meets it: it states read-only behavior, search scope across schools, tier semantics, confidence sorting, and ambiguity handling. This is rich behavioral context beyond what the schema alone shows.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, then organized into Args, Returns, and Notes with zero filler. Every sentence contributes either parameter meaning, return-shape detail, or usage guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter read-only lookup with no output schema, this description is complete: it specifies the return dict and fields, explains matching tiers, and tells the agent how to use the result. No critical operational detail is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description fully compensates: `name` is explained with format variants including short forms, and `subdomain` is given a clear restriction and default behavior. This adds real meaning beyond the bare schema field names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Look up') plus resource ('student') and method ('tiered matching'), and states the read-only nature and multi-school behavior. This clearly differentiates find_student from broader listing tools like scan_students.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explains when subdomain should be used versus omitted, and advises using the returned student_id with get_student_timetable/get_day_summary for unambiguous lookups. It does not explicitly name sibling alternatives or when-not-to-use conditions, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_day_summaryAInspect
One-call daily school report for a date (default today): timetable, substitutions, missing teachers, grades received that day, meals, homework, assignments, absences, news, events, and timeline notifications.
Composes the individual section tools so you don't need to fire 8-10 calls to answer "what happened yesterday at school" or "what's coming tomorrow".
If
name/student_idis provided: report for that specific student (found across all schools unlesssubdomainscopes it).If omitted: discovery-first — for a parent this returns a lightweight per-school index of the account's children (no per-child section fetching), so you can then call per child with
name/student_id. Setfull=Trueto instead build the full report for every child.If omitted and logged in as student/teacher: report on the logged-in account. Every section is isolated — a failure in one section yields {"ok": false, "error": ...} without failing the report.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | ||
| name | No | ||
| date_str | No | ||
| subdomain | No | ||
| student_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden and mostly succeeds: it discloses the discovery-first default behavior, the full=True escape hatch, and the section-isolation contract (a failed section returns {'ok': false, 'error': ...} without failing the report). It does not state auth/permission requirements or rate limits, leaving a small gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose and the section list, then bulleted conditions for each parameter mode; every bullet carries distinct routing information. The section enumeration is long but earns its place by telling the agent exactly what is aggregated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no annotations and no output schema, the description does the necessary work: it explains return semantics (per-school child index vs full report vs logged-in account report) and the degradation behavior on section failure. It stops short of describing the concrete report schema, but given the isolation contract that is a minor omission.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate, and it does for four of five params: date_str (default today), name/student_id (student selection, cross-school unless subdomain scopes it), subdomain (scoping), and full (full report per child instead of index). Only minor ambiguity remains, e.g. the exact name vs student_id precedence.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific composite action (one-call daily school report for a date) and enumerates the exact sections it aggregates (timetable, substitutions, grades, meals, etc.). It explicitly distinguishes itself from the many sibling section tools by saying it 'composes the individual section tools' so the agent needn't fire 8-10 calls.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit branching conditions: with name/student_id it reports for that student; omitted for a parent it returns a lightweight per-school child index (discovery-first); omitted for student/teacher it uses the logged-in account; full=True builds the full report for every child. This is precisely the when-to-use/when-not guidance an agent needs against siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_gradesAInspect
Get grades for the logged-in student. Read-only.
Args: year: School-year start year to filter by (e.g. 2025 for 2025/26). term: 'FIRST' or 'SECOND' to restrict the term. subdomain: School to query (defaults to the active subdomain).
Returns: dict: {'subdomain', 'grades': [serialized grades with subject, teacher, percent, ...]}.
Notes:
- When both year and term are omitted returns the current gradebook.
- Use get_school_year to resolve the current school-year start.
| Name | Required | Description | Default |
|---|---|---|---|
| term | No | ||
| year | No | ||
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses read-only behavior, describes the return format (dict with subdomain and grades list), and explains the default behavior when parameters are omitted. It doesn't mention error handling or permission requirements, but for a simple getter this is adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is tightly structured with Args, Returns, and Notes sections. The purpose and read-only note are front-loaded, and every sentence adds value—no filler or repetition. It is concise while covering all essential aspects.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the low complexity (3 optional parameters) and no output schema, the description provides everything needed to call the tool correctly: parameter explanations, return format, and default behavior. It also references a helper tool for resolving the school year, rounding out the context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, yet the description fully compensates by explaining each parameter in the Args section: year with an example (2025 for 2025/26), term as 'FIRST' or 'SECOND', and subdomain with a default (active subdomain). This adds meaningful semantics beyond the bare schema properties.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Get') and resource ('grades') for a clearly scoped subject ('the logged-in student'), and explicitly labels the operation as read-only. This distinguishes it from sibling tools that handle timetables, meals, or student scans without ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides concrete usage context: notes that omitting year and term returns the current gradebook, and points to get_school_year to resolve the current school-year start. While it doesn't explicitly list when not to use it or compare against alternatives, the default behavior and helper guidance give the agent clear direction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_mealsAInspect
Get the meal menu for a date. Read-only. Always returns all five meal
slots (breakfast, snack, lunch, afternoon_snack, dinner) — slots not
published by the school are None.
Args: date_str: YYYY-MM-DD (default today). subdomain: School to query (defaults to the active subdomain).
Returns:
dict: {'date', 'subdomain', 'meals': {breakfast/snack/lunch/
afternoon_snack/dinner: menus}}. Each menu carries chooseable/ordered
info usable with choose_meal / sign_off_meal.
Notes: - Tries the personal ordering endpoint first; when the school hasn't enabled it, falls back to the school's public canteen menu widget.
| Name | Required | Description | Default |
|---|---|---|---|
| date_str | No | ||
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full behavioral burden and does so thoroughly. It discloses read-only safety, the guaranteed shape of the response, handling of unpublished slots as None, and the endpoint fallback behavior. This goes well beyond a basic summary and gives the agent accurate expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a front-loaded purpose, then Args, Returns, and Notes sections. Every sentence adds necessary information, and the formatting makes it easy to scan. Despite its length, nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for this tool's complexity. It has no annotations or output schema, so the description covers return values, parameter defaults, edge cases for unpublished meal slots, fallback behavior, and integration with related meal tools. An agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description fully compensates. It documents both parameters with format and defaults: date_str as YYYY-MM-DD defaulting to today, and subdomain as the school to query defaulting to the active subdomain. This adds meaning the schema lacks entirely.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a specific, unambiguous statement: 'Get the meal menu for a date.' It further clarifies the resource and behavior by listing the five meal slots and explicitly marking the operation as read-only. This clearly differentiates it from sibling mutation tools like choose_meal and sign_off_meal.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context by noting the return data is usable with choose_meal and sign_off_meal, implying when to fetch before acting. Read-only status signals not to use it for modifications, though it does not explicitly name alternatives or state when-not-to-use cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_missing_teachersAInspect
Get teachers missing on a date (default today). Read-only.
Args: date_str: YYYY-MM-DD (default today). subdomain: School to query (defaults to the active subdomain).
Returns: dict: {'date', 'subdomain', 'teachers': [serialized missing teachers]}. Empty list when no teacher is missing.
Notes:
- Pair with get_timetable_changes for the full substitution picture.
| Name | Required | Description | Default |
|---|---|---|---|
| date_str | No | ||
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the behavioral burden. It explicitly states 'Read-only', documents the return shape, and notes the empty-list behavior. This covers the key behavioral concerns for a simple read tool, though it doesn't mention error cases or authentication requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-organized with clear Args, Returns, and Notes sections. Every sentence adds value, and the most important facts are front-loaded in the first sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with two optional parameters and no output schema, the description is complete: it documents defaults, input format, return structure, empty-list behavior, and a complementary sibling. Nothing essential is missing for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description fully compensates: date_str is given the YYYY-MM-DD format and a default of today, and subdomain is explained as the school to query with a default of the active subdomain. Both parameters become unambiguous.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource ('Get teachers missing on a date'), states the default date, and explicitly marks it as read-only. It is clearly distinct from sibling tools like get_timetable_changes, and the purpose is immediately comprehensible.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context: optional date and subdomain defaults, and pairs with get_timetable_changes for the full substitution picture. It doesn't explicitly list when not to use it, but the pairing note gives an agent a concrete way to combine it with an alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_my_studentsAInspect
Get the students visible to the logged-in account. Read-only: parent accounts see their linked children (parsed from the school homepage); student/teacher accounts see classmates. Uses cached data.
Args: subdomain: School to query (defaults to the active subdomain).
Returns:
dict: {'subdomain', 'students': [{person_id, name, class_id, ...}]}
usable with switch_to_student and get_student_timetable.
Notes:
- Prefer get_my_students over get_roster to see your children /
classmates; get_roster(roster_type='all_students') lists the whole
school.
- Cache is refreshed by clear_student_cache; scan_students returns
the same visibility across all schools.
| Name | Required | Description | Default |
|---|---|---|---|
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden. It discloses that the tool is read-only, uses cached data, and that the cache can be refreshed by clear_student_cache. It also explains account-type visibility differences and the relationship to scan_students, going well beyond a simple operation statement.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is organized into Args, Returns, and Notes sections, each earning its place. The key behavior is front-loaded, and the alternative guidance is compactly presented in the Notes. No redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-optional-parameter tool with no annotations and no output schema, the description is remarkably complete: it explains purpose, visibility rules, caching behavior, return shape, related functions, and how this tool differs from its sibling. An agent has everything needed to select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description compensates by explaining the only parameter, subdomain: 'School to query (defaults to the active subdomain).' This adds meaningful semantic context beyond the bare string type, though it does not specify the exact format or expected value shape of a subdomain.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Get the students visible to the logged-in account.' It clearly communicates the scoped visibility (children/classmates) and differentiates itself from the school-wide get_roster sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The notes explicitly state when to prefer this tool over get_roster and what each alternative provides: get_my_students shows your own children/classmates, while get_roster lists the whole school. It also names related operations like switch_to_student and get_student_timetable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_my_timetableAInspect
Get the timetable for the logged-in user on a date. Read-only.
Args: date_str: YYYY-MM-DD (default today). subdomain: School to query (defaults to the active subdomain).
Returns: dict: {'date', 'subdomain', 'lessons': [serialized lessons]}.
Notes:
- For another student use get_student_timetable (by name/id);
for a teacher/class/room on a date or a range use get_timetable.
- Next week for yourself: get_next_week_timetable.
| Name | Required | Description | Default |
|---|---|---|---|
| date_str | No | ||
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and it does so well: it states 'Read-only', specifies the return shape as a dict with date, subdomain, and lessons, and notes default behaviors. It does not discuss errors or authentication requirements, but the 'logged-in user' phrasing and read-only nature make the behavioral profile clear enough.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is neatly organized into Args, Returns, and Notes with no filler. Every sentence contributes either parameter details, return contract, or sibling routing, and the most important scope information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter read-only getter with no output schema, the description covers the input format, defaults, return structure, and sibling alternatives. Nothing essential is missing for an agent to select and invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must fully compensate, and it does. date_str is defined with format and default, and subdomain is defined with its default and meaning. This is complete parameter documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Get the timetable for the logged-in user on a date.' It is clearly differentiated from siblings through notes that explicitly name get_student_timetable, get_timetable, and get_next_week_timetable, so an agent can distinguish this tool without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is explicit: it is for the logged-in user on a single date, with defaults explained. The Notes section gives concrete when-not-to-use guidance and names the alternative tools for another student, for teacher/class/room/range, and for next week.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_next_ringing_timeAInspect
Get the type (break/lesson) and time of the next school-bell ringing. Read-only.
Args: date_time_str: ISO datetime to search onward from (default: now). subdomain: School to query (defaults to the active subdomain).
Returns: Serialized ringing: type (break/lesson) and time.
Notes:
- See get_periods for the full bell schedule.
| Name | Required | Description | Default |
|---|---|---|---|
| subdomain | No | ||
| date_time_str | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full responsibility for behavioral disclosure. It explicitly labels the operation as 'Read-only' and describes the output as a serialized ringing with type and time. This gives the agent confidence about side effects and expected results, though it doesn't mention error behavior or timezone handling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is tightly structured with a one-line purpose, clearly separated 'Args', 'Returns', and 'Notes' sections. Every sentence adds value, including the useful pointer to get_periods. No filler or redundancy exists.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with two optional parameters and no output schema, the description covers the essential context: what the tool does, how to call it, what it returns, and how it relates to the sibling get_periods. It lacks edge-case details like handling of past dates or timezone implications, but these are not critical for basic invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate entirely. It does so by giving each parameter a one-line explanation with default values: date_time_str is 'ISO datetime to search onward from (default: now)' and subdomain is 'School to query (defaults to the active subdomain)'. This fully compensates for the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Get'), a precise resource ('the next school-bell ringing'), and the exact information returned (type and time). It also distinguishes itself from the sibling tool get_periods by describing its scope as the next single ringing versus the full schedule.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'Args' section explains how to use the tool, including defaults for date_time_str and subdomain, giving clear operational context. It also points to get_periods for the full bell schedule, suggesting an alternative for a different need, though it doesn't explicitly state 'use this when you only need the next ringing'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_next_week_timetableAInspect
Get the Mon-Fri timetable for next week for the logged-in user, grouped by weekday. Read-only.
Args: subdomain: School to query (defaults to the active subdomain).
Returns: dict: {'monday', 'subdomain', 'week': [{weekday, date, lessons} x5]}.
Notes:
- Weekdays are 'Po','Ut','St','Št','Pi'.
- For the logged-in user on a single day use get_my_timetable; for
any target (teacher/class/room/student) over a range use
get_timetable with end_date.
| Name | Required | Description | Default |
|---|---|---|---|
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and handles it well by stating 'Read-only', specifying grouping by weekday, describing the return dict structure, and listing weekday abbreviations. It also discloses that subdomain defaults to active subdomain, which is important invocation behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and organized into Args, Returns, and Notes. Every element adds operational value without repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema or annotation support, yet the description covers scope, auth context, parameters, return shape, weekday codes, and sibling routing. This is complete enough for an agent to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema only declares a subdomain string with a default, but the description adds meaning: 'School to query (defaults to the active subdomain).' Since schema description coverage is 0%, this is necessary and sufficient for the sole optional parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Get the Mon-Fri timetable for next week for the logged-in user, grouped by weekday.' It also names sibling tools in the notes, distinguishing when get_my_timetable and get_timetable are appropriate instead.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The Notes section explicitly routes alternatives: 'For the logged-in user on a single day use get_my_timetable; for any target ... over a range use get_timetable with end_date.' This gives clear when-not-to-use guidance so an agent can select this tool correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_periodsAInspect
Get the bell schedule (periods with start/end times). Read-only.
Args: subdomain: School to query (defaults to the active subdomain).
Returns: dict: {'periods': [{'starttime', 'endtime'}, ...]}.
Notes:
- Combine with get_next_ringing_time for live bell timing.
| Name | Required | Description | Default |
|---|---|---|---|
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description takes on the behavioral disclosure burden. It clearly labels the operation as 'Read-only', explains the default subdomain behavior, and describes the return dictionary, covering the main behavioral facts an agent needs. It does not discuss auth or error conditions, but for a simple read-only lookup these are not critical gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a compact, front-loaded summary followed by a structured Args/Returns/Notes breakdown. There is little waste; the only slight flaw is the informal return notation using {'starttime', 'endtime'}, which is minor and does not undermine comprehension.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-optional-parameter, read-only query with no output schema, the description supplies the essential information: what is returned, the shape of the return value, and the default behavior. The cross-reference to get_next_ringing_time adds useful integration context. No critical missing information remains.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides only the property name 'Subdomain' with no description, so the description is the sole source of parameter meaning. The Args section explains that subdomain selects a school and defaults to the active subdomain, which fully compensates for the 0% schema description coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Get the bell schedule (periods with start/end times)', which names a specific action and resource. The parenthetical clarifies the output granularity and implicitly separates it from the live-time sibling get_next_ringing_time, and the Notes line makes that relationship explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states the tool's purpose clearly and notes that it should be combined with get_next_ringing_time for live timing, giving an agent context on where this fits. It does not explicitly list exclusions or alternative tools, so it stops short of the top score.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_rosterAInspect
Get a school roster: students, teachers, classes, classrooms or subjects. Read-only.
Args:
roster_type: Which roster to return:
- 'students' — students in the logged-in user's class
(formerly get_students).
- 'all_students' — a short list of all students in the school
(formerly get_all_students).
- 'teachers' — all teachers (formerly get_teachers).
- 'classes' — all classes (formerly get_classes).
- 'classrooms' — all classrooms (formerly get_classrooms).
- 'subjects' — all subjects (formerly get_subjects).
subdomain: School to query (defaults to the active subdomain).
Returns: dict keyed by the roster name, e.g. {'subdomain': ..., 'teachers': [...], ...}.
Notes:
- For the students visible to the logged-in account (parents: their
linked children; students: classmates) prefer get_my_students.
- To look one student up by name use find_student.
- Returned person/class ids feed get_timetable (target_type/target_id)
and switch_to_student.
| Name | Required | Description | Default |
|---|---|---|---|
| subdomain | No | ||
| roster_type | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations at all, the description carries the behavioral burden. It explicitly states the tool is read-only and describes the return shape as a dict keyed by roster name with an example, which goes beyond minimal disclosure. It does not cover auth or rate limits, but for a read-only roster lookup the provided transparency is strong.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized with clear Args, Returns, and Notes sections. Each sentence contributes either parameter semantics, return behavior, or routing to alternatives, with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given only two parameters, no output schema, and no annotations, this description is complete: it documents all parameter values, default behavior, return shape, read-only nature, and important relationships to sibling tools. An agent has everything needed to select and call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must fully compensate, and it does. Every roster_type option is explicitly listed with its meaning and former tool name, and subdomain is described as the school to query with a default to the active subdomain.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description begins with a specific verb and resource, 'Get a school roster', and immediately enumerates the exact roster types: students, teachers, classes, classrooms or subjects. The inline values and formerly-named tool references make it easy to distinguish this from related roster tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The Notes section explicitly tells the agent when to prefer alternatives: use get_my_students for students visible to the logged-in account, and use find_student for a single student lookup. It also explains how returned IDs connect to get_timetable and switch_to_student, giving clear contextual routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_school_yearAInspect
Return the current school year (starting year). Read-only.
Args: subdomain: School to query (defaults to the active subdomain).
Returns: dict: {'school_year': , 'subdomain': ...}.
| Name | Required | Description | Default |
|---|---|---|---|
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It explicitly discloses 'Read-only', clarifies the default subdomain behavior, and states the return format. It could add error or authentication context, but for a trivial read operation this is sufficient transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core purpose, then uses a clear Args/Returns structure. Every sentence adds distinct value without repetition or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though there is no output schema, the description provides the exact return dict format and explains the only parameter's behavior. For a one-parameter, read-only getter, nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It defines 'subdomain' as 'School to query' and specifies it 'defaults to the active subdomain', adding meaningful semantics beyond the bare string type and null default in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'Return' with a clear resource 'current school year (starting year)' and explicitly states 'Read-only'. This precisely distinguishes the tool from its siblings and leaves no ambiguity about its function.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use the tool (when the current school year is needed) and explains the subdomain parameter, but it does not explicitly compare against sibling tools or state when not to use it. For a simple getter with no close sibling overlap, this is acceptable but still mostly implicit guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_student_timetableAInspect
Get a student's timetable by first/last name OR person_id. Read-only.
Without a subdomain, searches every school in the discovery scope (the
configured EDUPAGE_SUBDOMAINS, or all logged-in schools when unset) and
returns one result per school where the student is found — so a student
attending multiple schools yields separate per-school timetables.
Args:
name: Student's first/last/full name.
student_id: person_id (preferred — unambiguous, see find_student).
date_str: YYYY-MM-DD (default today).
subdomain: Restrict to one school (default: all logged-in schools).
Returns:
dict: {'results': [{student, student_id, class_id, date, subdomain,
lessons}]}; with a query/matched_schools summary when more than one
school is searched.
Notes:
- If logged in as a parent this resolves the child agent-side and
queries their timetable directly (no session switching). For your own
timetable use get_my_timetable.
- Use the student_id from find_student / get_my_students for
unambiguous lookups.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| date_str | No | ||
| subdomain | No | ||
| student_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It clearly states read-only, describes the multi-school one-result-per-school behavior, parent child-agent resolution without session switching, and the return summary when multiple schools are searched. This is richly transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized with Args, Returns, and Notes sections. It front-loads the core purpose and terse behavior, then packs parameter semantics and parent-specific behavior into clearly labeled blocks without repetition or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers invocation parameters, defaults, return format, and parent behavior. Minor gap: it doesn't state what happens if neither name nor student_id is supplied or if no student is found, but the description is otherwise sufficient for correct invocation given the lack of an output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the description documents every parameter with meaningful detail: name accepts first/last/full, student_id is the preferred person_id, date_str uses YYYY-MM-DD with default today, and subdomain restricts to one school. This fully compensates for the schema's lack of descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: 'Get a student's timetable by first/last name OR person_id' and identifies itself as read-only. Distinguishes from sibling get_my_timetable by noting the parent/child handling, so an agent can immediately tell which timetable tool to use.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes to get_my_timetable for the caller's own timetable and recommends student_id from find_student/get_my_students for unambiguous lookups. Also explains the multi-school search behavior and the subdomain restriction, which helps the agent decide when to supply subdomain.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_subdomainsAInspect
List the school subdomains available to the logged-in account and the server's session status per school, plus overall login state. Read-only.
Args: (none)
Returns:
dict with:
- subdomains: list of school subdomains available to the account.
For a logged-in parent account this is live-discovered (via
edupage-api's get_subdomains, read from the profile page) and
includes schools with no session yet; it is limited to
EDUPAGE_SUBDOMAINS when that is set (allowlist), otherwise every
accessible school is listed. For student/teacher accounts or when
not logged in it falls back to the configured / current sessions.
- schools: per subdomain {subdomain, logged_in, role
(student/parent/teacher), user_id, two_factor_pending, active}.
When EDUPAGE_SUBDOMAINS is set it contains only the in-scope
schools (sessions for unconfigured schools are never listed).
- active_subdomain: the school used by tools without an explicit
subdomain argument.
- failed_logins: subdomain → error for login attempts that failed or
are blocked (e.g. pending 2FA at startup).
- env_*_set: whether EDUPAGE_USERNAME / EDUPAGE_PASSWORD /
EDUPAGE_SUBDOMAINS are configured.
Notes:
- Use this instead of the former auth_status / user_id tools.
- To connect to a discovered subdomain that has no session yet, pass
it to login_all.
- A school with two_factor_pending: True needs two_factor_finish.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It explicitly declares 'Read-only.' and thoroughly details return structure, edge cases (parent vs student/teacher, allowlist behavior), failed logins, and environment variable flags. This is transparent and goes beyond the basics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although lengthy, the description is well-structured with clear sections (Purpose, Args, Returns, Notes) and front-loads the core purpose. Every sentence adds value, covering complex return semantics and usage notes without redundancy. The detail is justified given the tool's rich output.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully explains the return values and their nuances, including conditional behavior, environment variables, and integration with sibling tools. It covers all information an agent needs to correctly interpret results and decide next actions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there is nothing for the description to clarify beyond the schema (which is trivially 100% covered). Per instructions, a baseline of 4 is appropriate when there are no parameters, and the description does not need to add parameter-specific meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'List the school subdomains available to the logged-in account and the server's session status per school, plus overall login state.' It specifies a distinct verb and resource, and differentiates from siblings by noting it replaces the former auth_status/user_id tools. This makes its purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells when to use it ('Use this instead of the former auth_status / user_id tools') and provides actionable follow-up steps: passing discovered subdomains to login_all and handling two_factor_pending with two_factor_finish. This is clear contextual guidance that distinguishes it from alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_timelineAInspect
Get EduPage timeline notifications, filtered by category. Read-only.
Args:
category: Which event types to return:
- 'recent' (default) — all currently visible notifications
(homework, tests, messages, grades, events...).
- 'history' — all notifications since date_from (incl. older ones).
- 'homework' — homework assignments (formerly get_homework).
- 'assignments' — homework, tests, exams and projects
(formerly get_assignments).
- 'absences' — absence records (formerly get_absences).
- 'events' — upcoming events: trips, excursions, meetings, holidays...
(formerly get_upcoming_events).
- 'news' — school news (formerly get_news).
date_from: YYYY-MM-DD. Only meaningful for category='history'.
subdomain: School to query (defaults to the active subdomain).
Returns: dict with subdomain and the matching notifications, e.g. {'subdomain': ..., 'notifications': [...]} (key is the category name).
Notes:
- Categories are derived from timeline notifications; a school that
doesn't publish a given event type returns an empty list.
- For a whole-day report (timetable, substitutions, meals, homework,
events, news, grades) prefer get_day_summary — one call.
| Name | Required | Description | Default |
|---|---|---|---|
| category | No | recent | |
| date_from | No | ||
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so well. It declares 'Read-only,' describes the return shape with an example, notes that date_from only matters for history, and explains that missing categories yield empty lists. These are meaningful behavioral details beyond the raw schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized into Args, Returns, and Notes. Each section adds necessary information: parameter semantics, return contract, and edge-case behavior. The mention of formerly separate tools is useful context, and the alternative get_day_summary is clearly highlighted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema and no annotations, the description is complete enough for an agent to call it correctly: it defines all parameters, explains the return format, notes the read-only nature, and points to the more appropriate sibling for whole-day summaries. No critical information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description fully compensates. It explains every parameter: category values with defaults and meanings, date_from format ('YYYY-MM-DD') and scope, and subdomain behavior including the default. This is more informative than an enum-based schema would be.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Get EduPage timeline notifications, filtered by category.' It also enumerates the distinct category values and explicitly references former tool names, making the tool's scope easy to distinguish from siblings like get_day_summary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to prefer an alternative: 'For a whole-day report ... prefer get_day_summary — one call.' It also implies when this tool is appropriate by categorizing event types and noting that missing event types return empty lists, which helps an agent decide between timeline-specific queries and the summary endpoint.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_timetableAInspect
Get the timetable for a teacher, student, class or classroom on a date
(or a date range, see end_date). Read-only.
Args:
target_type: 'teacher' | 'student' | 'class' | 'classroom'.
target_id: person/class/classroom id as returned by get_roster.
date_str: Single day, YYYY-MM-DD (default today). Ignored when
end_date is given.
end_date: When set, returns the timetable for every day from
date_str (default today) to end_date inclusive, keyed by date
— the equivalent of the former get_timetable_range.
subdomain: School to query (defaults to the active subdomain).
Returns: Single-day shape: {'target', 'date', 'subdomain', 'lessons'}. Range shape: {'subdomain', 'range': {: single-day result}}. Days with no published data get an empty lessons list.
Notes:
- For the logged-in user's own timetable prefer get_my_timetable;
for a student by name/id use get_student_timetable.
- Any school's whole-week plan for yourself: get_next_week_timetable.
| Name | Required | Description | Default |
|---|---|---|---|
| date_str | No | ||
| end_date | No | ||
| subdomain | No | ||
| target_id | Yes | ||
| target_type | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It clearly states 'Read-only', explains the two return shapes (single-day vs. range keyed by date), defaults for date_str, and the empty-lessons behavior for days without published data. It also notes that date_str is ignored when end_date is given, providing complete behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections for Args, Returns, and Notes. It front-loads the purpose, then provides details in a scannable format. Despite length, every sentence adds value and avoids redundancy – an optimal structure for a complex multi-mode tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (5 parameters, two return shapes, sibling differentiations) and the absence of both annotations and output schema, the description covers all necessary aspects: parameter semantics, defaults, edge cases (empty lessons), and tool alternatives. Nothing an agent needs to correctly invoke and interpret the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must explain every parameter. It does: target_type enumerates allowed values, target_id links to get_roster, date_str specifies format and default plus interaction with end_date, end_date defines range behavior, and subdomain defaults to the active one. All five parameters are clearly defined beyond their schema names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb 'Get', a resource 'timetable', and enumerates valid target types (teacher, student, class, classroom). It precisely differentiates from siblings like get_my_timetable and get_student_timetable by naming them and their intended use cases.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs when to use alternatives: 'For the *logged-in user's own* timetable prefer `get_my_timetable`; for a student by name/id use `get_student_timetable`.' It also mentions `get_next_week_timetable` for a whole-week plan, leaving no ambiguity about tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_timetable_changesAInspect
Get substitution/timetable changes for a date (default today). Read-only.
Args: date_str: YYYY-MM-DD (default today). subdomain: School to query (defaults to the active subdomain).
Returns: dict: {'date', 'subdomain', 'changes': [serialized substitutions]}. Empty list when nothing changed or the school publishes none.
Notes:
- Pair with get_missing_teachers for the full substitution picture.
- For one student's plan on a day use get_student_timetable / get_timetable.
| Name | Required | Description | Default |
|---|---|---|---|
| date_str | No | ||
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden and it does disclose the key traits: read-only, empty list when nothing changed or school publishes none, and return shape. It does not detail errors/auth/rate limits or what 'serialized substitutions' looks like, but the core call behavior is transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is organized into clear Args/Returns/Notes sections, front-loads the core purpose, and every sentence adds information. It is compact despite covering defaults, return values, and sibling routing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description supplies the return contract (dict with date, subdomain, changes, empty-list behavior), which is sufficient for invoking and interpreting the result. Combined with usage alternatives, the context is complete for selecting this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must carry parameter meaning; it fully does. date_str gets format YYYY-MM-DD and default today, and subdomain gets 'School to query' and default active subdomain, adding real semantics beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence names a specific verb+resource: 'Get substitution/timetable changes for a date' with a default of today and explicitly labels it read-only. The Notes section differentiates it from get_student_timetable/get_timetable, which are for one student's plan, so an agent can distinguish it from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-use context: pair with get_missing_teachers for the full substitution picture, and use get_student_timetable/get_timetable instead for a single student's daily plan. The read-only marker and date/subdomain defaults further clarify when it can be used.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
loginAInspect
Log in to Edupage for a school. Writes: establishes (or replaces) the server-side session for that subdomain.
Args:
username: EduPage account login. Falls back to EDUPAGE_USERNAME.
password: Account password. Falls back to EDUPAGE_PASSWORD.
subdomain: School subdomain (e.g. 'school'). Falls back to the first
value of EDUPAGE_SUBDOMAINS; for method='auto' it is optional and
tags the detected school's session.
method: How to authenticate:
- 'credentials' (default) — username/password for a known subdomain.
- 'auto' — portal auto-detect of the school (formerly login_auto).
- 'session' — build a session from an existing PHPSESSID cookie
(formerly login_from_session); pass it in session_id.
session_id: PHPSESSID cookie value, required when method='session'.
Returns:
dict with logged_in status, subdomain, user_id, role and whether 2FA
is pending. When two_factor_required is true, finish with
two_factor_finish.
Notes:
- Each login call adds/replaces that subdomain's session; call
login_all to log into several schools in one call.
- When EDUPAGE_SUBDOMAINS is set it is a strict allowlist: login into
a school outside it is refused.
- Prefer setting EDUPAGE_USERNAME / EDUPAGE_PASSWORD (and
EDUPAGE_SUBDOMAINS for multi-school) — the server then logs in
automatically at startup.
| Name | Required | Description | Default |
|---|---|---|---|
| method | No | credentials | |
| password | No | ||
| username | No | ||
| subdomain | No | ||
| session_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does so well. It discloses that login writes/replaces the server-side session, that EDUPAGE_SUBDOMAINS acts as a strict allowlist, that 2FA may be pending, and that environment-variable-based automatic login happens at startup.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but organized into clear sections (Args, Returns, Notes), with the core purpose front-loaded. Some details about environment variable fallbacks could be considered extra, but they are directly relevant to correct invocation and the structure prevents confusion.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has five parameters, no annotations, and no output schema, the description covers all necessary context: parameter semantics, return values, side effects, related tool routing, and 2FA follow-up. Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must document parameters, and it does. Each parameter is explained with defaults, fallback environment variables, and method-specific requirements, including the special role of session_id and when subdomain is optional.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Log in to Edupage for a school' and clearly states the behavioral effect: 'establishes (or replaces) the server-side session for that subdomain.' It also distinguishes itself from the sibling login_all by noting that one call logs into one school while login_all handles several.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance through method options: 'credentials', 'auto', and 'session', each with conditions. It explicitly points to login_all when multiple schools are needed and mentions two_factor_finish for the 2FA continuation case, plus explains the EDUPAGE_SUBDOMAINS allowlist behavior.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
login_allAInspect
Log in to one or more schools in a single call. Writes: establishes (or replaces) the server-side session for each subdomain.
Args: subdomains: Comma-separated school subdomains, e.g. 'school1,school2'. Falls back to EDUPAGE_SUBDOMAINS. usernames: Comma-separated usernames, one per school (or a single one). Falls back to EDUPAGE_USERNAME. passwords: Comma-separated passwords, one per school (or a single one). Falls back to EDUPAGE_PASSWORD.
Returns: dict: {'results': [{subdomain, ok, user_id, role, two_factor_required}], 'active_subdomain': ...}. A failed school is reported per-entry with its error.
Notes:
- Add schools one at a time with login.
- When EDUPAGE_SUBDOMAINS is set it is a strict allowlist: schools
outside it are refused per-entry without creating a session.
- Finish any pending 2FA with two_factor_finish.
| Name | Required | Description | Default |
|---|---|---|---|
| passwords | No | ||
| usernames | No | ||
| subdomains | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description takes on the full transparency burden and does well: it labels the call as 'Writes', says it establishes or replaces sessions, explains per-entry failure reporting, and documents the EDUPAGE_SUBDOMAINS allowlist refusal behavior. It does not cover all side effects (e.g., rate-limit implications or complete session-destruction semantics), but the key mutation and failure behavior is disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well organized with Args, Returns, and Notes sections; the most important facts (batch scope and session-write behavior) are front-loaded. Every included sentence adds value, and the bullet-style notes make the failure and 2FA behavior easy to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and no annotations, the description covers parameter fallbacks, return shape, per-entry errors, allowlist enforcement, and 2FA next step. It falls slightly short by not explaining the meaning of `active_subdomain` or how the returned `two_factor_required` field connects to `two_factor_finish` parameters, which a caller would need to fully complete the flow.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description is the only source of parameter meaning. It explains comma-separated formats, per-school cardinality, and fallback to environment variables for every parameter. The only weakness is the ambiguous 'or a single one' phrasing, which does not fully define whether one username/password applies to all schools or only to a single-school call.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Log in to one or more schools in a single call', which names the exact verb, resource, and batch scope. It further distinguishes itself from the sibling `login` by saying schools should be added one at a time with `login`, and it clarifies the side effect: establishing or replacing server-side sessions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear alternative in Notes: 'Add schools one at a time with `login`' and instructs to finish 2FA with `two_factor_finish`, which tells the agent when the sibling tools are appropriate. It does not explicitly spell out 'use this for bulk login, use `login` for a single school', but the intended usage is strongly implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rate_mealAInspect
Rate a meal. Writes: submits quality/quantity ratings for a date and meal type.
Args: date_str: YYYY-MM-DD of the meal. meal_type: 'snack' | 'lunch' | 'afternoon_snack'. quality: Taste rating, 1-5. quantity: Portion-size rating, 1-5. subdomain: School to query (defaults to the active subdomain).
Returns: dict: {'rated': True, meal_type, date}.
| Name | Required | Description | Default |
|---|---|---|---|
| quality | Yes | ||
| date_str | Yes | ||
| quantity | Yes | ||
| meal_type | Yes | ||
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must disclose behavioral traits. It only states 'Writes:' and mentions the return dict, but it does not discuss side effects, whether ratings are overwritten, authentication requirements, error handling, or any constraints. This is minimal disclosure for a mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, with a clear top line ('Rate a meal. Writes:...') and a structured Args/Returns layout. Every sentence provides needed information; there is no fluff or redundancy. It is well-organized and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple write operation with no annotations and no output schema, the description covers all parameters and the success return, but it lacks details about error conditions, whether existing ratings are overwritten, or any required context like being logged in. These gaps could lead an agent to misuse the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has zero descriptions (0% coverage), so the description fully compensates. It provides specific semantics for every parameter: date_str format (YYYY-MM-DD), meal_type enum ('snack' | 'lunch' | 'afternoon_snack'), quality and quantity ranges (1-5), and subdomain default (active subdomain). This adds essential meaning beyond the bare types in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Rate a meal. Writes: submits quality/quantity ratings for a date and meal type.' This is a specific verb (rate) and resource (meal), and it distinguishes itself from sibling tools like get_meals (retrieval), choose_meal (selection), and sign_off_meal (sign-off) by focusing on rating.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage: it is for rating a meal, but it does not explicitly state when to use it over alternatives or mention any prerequisites (e.g., must be logged in). It does not say 'Use this when you want to submit ratings' or exclude other meal-related operations, so guidance is only implied, not explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scan_studentsAInspect
Discover all students visible to the logged-in account across the discovery
scope (the configured EDUPAGE_SUBDOMAINS, or every school when unset).
Read-only; uses cached data to avoid redundant API calls.
Returns: dict: {'students': [{name, student_id, class_id, subdomain}], 'total': n}. For a parent account: their linked children in each school; for a student/teacher: classmates. One entry per student per school.
Notes:
- get_my_students returns the same view for the active subdomain;
clear_student_cache refreshes it.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully carries the behavioral burden. It discloses that the tool is read-only, uses cached data to avoid redundant API calls, and varies behavior by account type (parent versus student/teacher). It also documents the exact return format and the one-entry-per-student-per-school rule.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded: the core purpose and scope appear first, followed by behavioral notes and return format. Every sentence earns its place, and the notes section cleanly separates alternative-tool guidance from cache behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though there is no output schema, the description provides the full return dict shapeeding, the 'total' key, per-account behavior, and cross-school duplication. It also covers cache semantics, configuration influence, and related tools, leaving no significant gap for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and 100% schema coverage, so the schema is complete by construction; the description is not required to explain parameter meaning. It still adds useful context around the output and scope, which is appropriate for a zero-parameter tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a precise verb and resource ('Discover all students visible to the logged-in account') and defines the scope via the discovery configuration or all schools when unset. It also distinguishes the tool from get_my_students by explicitly mentioning the same view but restricted to the active subdomain.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description names concrete alternatives and their appropriate conditions: get_my_students for the active subdomain only, and clear_student_cache to refresh the cached data. This gives an agent clear routing guidance without needing to inspect other tool schemas.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_messageAInspect
Send a message to a recipient. Writes: posts a new message on the recipient's timeline.
Args:
recipient_id: EduPage id like 'Student123' or 'Teacher456' (see
get_roster).
body: Message text. Must not be empty.
subdomain: School to query (defaults to the active subdomain).
Returns: dict: {'sent': True, 'timeline_id': }.
Notes:
- Recipient ids come from get_roster(roster_type='students'|'teachers')
or get_my_students.
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | ||
| subdomain | No | ||
| recipient_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It clearly states the write operation ('Writes'), the non-empty body constraint, and the exact return format ({'sent': True, 'timeline_id': <id>}). It does not mention potential error conditions or side effects beyond the core write, but for a simple send operation this is adequate. No contradiction with annotations exists (none present).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a clear main sentence, an Args section, Returns, and Notes. Every sentence adds value: the main verb, parameter details, return format, and source guidance. No fluff or redundancy. The critical information (write behavior and parameter constraints) is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema and no annotations, the description covers all necessary context: what it does, parameter semantics, where to obtain recipient IDs, default behavior, and return format. There is no missing information an agent would need to invoke it correctly. The only minor gap is absence of error scenarios, but that is not critical for a simple send operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides only type/title with no descriptions (0% coverage), so the description must fully compensate. It does: each parameter (recipient_id, body, subdomain) is explained, including the expected format for recipient_id and the default for subdomain. This goes well beyond the schema and gives an agent everything needed to construct valid arguments.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action: 'Send a message to a recipient' and specifies the resource and effect: 'Writes: posts a new message on the recipient's timeline.' This distinguishes it from read-oriented sibling tools (e.g., get_timeline, get_grades) and clearly conveys its write nature. The verb and object are specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides practical guidance on sourcing recipient IDs via get_roster or get_my_students, and notes the subdomain default. It does not explicitly state when to avoid this tool, but given no competing messaging sibling exists, the context is clear enough. It could be slightly more explicit about when this tool is the appropriate choice, but it's not misleading.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sign_off_mealAInspect
Cancel an ordered meal for a date. Writes: releases the booking.
Args: date_str: YYYY-MM-DD to cancel. meal_type: 'snack' | 'lunch' | 'afternoon_snack'. subdomain: School to query (defaults to the active subdomain).
Returns: dict: {'ordered': False, meal_type, date}.
| Name | Required | Description | Default |
|---|---|---|---|
| date_str | Yes | ||
| meal_type | Yes | ||
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and it does disclose that this is a write operation that releases the booking, and that the result has ordered=False. It does not cover edge cases like already-cancelled meals or auth requirements, but the core mutating behavior is explicit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is tightly structured with a one-line purpose, args, and returns, and contains no filler. Every line adds necessary invocation or outcome information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple cancellation tool with no annotations or output schema, it provides sufficient invocation details and the return shape. Minor gaps, such as error behavior and whether cancellation can be repeated, keep it from being fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, yet the description documents every parameter: date_str format and meaning, the meal_type allowed values, and subdomain defaulting. This fully compensates for the schema's lack of descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Cancel an ordered meal for a date,' which immediately distinguishes it from meal selection/rating/listing siblings like choose_meal, rate_meal, and get_meals. The action and target are unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly states the trigger: cancel a previously ordered meal on a specific date. It does not explicitly name sibling alternatives or exclusion conditions, but 'cancel an ordered meal' provides enough contextual guidance to select it over get_meals/choose_meal.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
switch_to_parentAInspect
Switch the session back to the parent account (parent accounts only). Writes: changes which account subsequent tools operate as.
Args: subdomain: School whose session to restore (defaults to the active).
Returns: dict: {'switched_to_parent': True, 'user_id': ...}.
Notes:
- Pair with switch_to_student; only relevant after a parent session
was switched to a child.
| Name | Required | Description | Default |
|---|---|---|---|
| subdomain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden, and it does so well by disclosing the write-like side effect: 'changes which account subsequent tools operate as.' It also describes the return value shape, clarifying that switching back yields `{'switched_to_parent': True, 'user_id': ...}`. A small gap remains around error behavior when not in a parent-active session, but the core behavioral contract is clearly stated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is tightly structured with a one-sentence summary, a Writes note, an Args section, a Returns section, and a short Notes section. Every line earns its place, and the most important information about side effects and pairing is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter, no-output-schema tool, the description covers purpose, side effects, return type, parameter semantics, and the companion tool. An agent has enough information to call it correctly and know what will happen. No critical behavioral detail is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does. The only parameter, `subdomain`, is explained as 'School whose session to restore (defaults to the active)', adding meaningful semantics beyond the bare schema title 'Subdomain'. The default behavior is also clarified, which is valuable for a non-required parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Switch the session back to the parent account', identifying the exact verb and resource, and immediately qualifies it with '(parent accounts only)'. It is also distinct from the sibling `switch_to_student`, so an agent can tell which direction the session switch operates.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says to pair with `switch_to_student` and notes it is 'only relevant after a parent session was switched to a child.' This gives clear when-to-use guidance and implicitly warns against using it in other contexts, which is strong framing for the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
switch_to_studentAInspect
Switch the session to a student account (parent accounts only). Writes: changes which account subsequent tools operate as.
Args:
student_id: person_id of the child (from get_my_students).
name: first/last/full name of the child, used when student_id is omitted.
subdomain: School to query (defaults to the active subdomain).
Returns: dict: {'switched_to_student': , 'user_id': ...}.
Notes:
- Revert with switch_to_parent. Prefer the stateless
get_student_timetable (name/student_id) over switching when you
only need a timetable.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| subdomain | No | ||
| student_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It explicitly discloses the stateful side effect—'Writes: changes which account subsequent tools operate as'—and explains how to revert. This makes the mutation behavior clear to the agent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is tightly organized into Args, Returns, and Notes. The main purpose is front-loaded, and every section earns its place without redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers purpose, parameters, return value, side effects, reversion, and a relevant alternative. The only notable gap is that, although student_id and name are described as alternatives, it never explicitly states that at least one is required—especially since the schema marks all parameters optional.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description fully compensates: student_id is defined as the child's person_id from get_my_students, name is positioned as a fallback when student_id is omitted, and subdomain is documented with its default. All three parameters gain meaningful semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a direct verb and resource: 'Switch the session to a student account (parent accounts only).' It then clarifies the operative effect: subsequent tools act as that student. This clearly distinguishes the tool from siblings like switch_to_parent and get_student_timetable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states the parent-only precondition and explicitly names the alternative for a common case: prefer the stateless get_student_timetable when only a timetable is needed. It also tells the agent how to undo the switch using switch_to_parent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
two_factor_finishAInspect
Finish a pending 2FA login. Writes: completes the pending auth flow.
Only needed after a login that returned two_factor_required: True.
Args:
code: Optional email/app verification code. When given it is used
directly; otherwise the device-confirmation flow is polled.
subdomain: School subdomain whose pending login to complete (defaults
to the active subdomain).
poll_seconds: How long (seconds) to wait for approval on a device when
code is not given. Defaults to 60; on timeout the caller can
call two_factor_finish again later.
Returns: dict: {'confirmed': True, 'logged_in': True, subdomain, user_id, role} on success, or a pending status when the confirmation wasn't approved within the poll window.
| Name | Required | Description | Default |
|---|---|---|---|
| code | No | ||
| subdomain | No | ||
| poll_seconds | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does so well. It discloses that the tool writes by completing the pending flow, describes polling behavior when no code is given, explains the timeout, and notes the caller can call it again later. This goes well beyond a minimal description.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized into purpose, arguments, and return value. The trigger condition is front-loaded, and every section earns its place without redundant filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema or annotations, the description covers success return fields, pending status, polling mechanics, and retry guidance. It provides all operational details needed to invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must fully explain each parameter. It does: code's optionality and direct-use behavior, subdomain's default, and poll_seconds' timeout and retry semantics. This fully compensates for the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Finish a pending 2FA login,' and clarifies it 'completes the pending auth flow.' This clearly distinguishes it from sibling tools like login by tying it to a prior two_factor_required response.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states the trigger condition: 'Only needed after a `login` that returned `two_factor_required: True`.' This gives an unambiguous when-to-use signal and prevents premature invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v0.5.1- Removed
get_schools - Added
get_subdomains
27 tool updates
v0.5.0- Removed
auth_status - Removed
get_absences - Removed
get_all_students - Removed
get_assignments - Removed
get_classes - Removed
get_classrooms - Removed
get_homework - Changed
get_meals2 fields changed- removed
Input schema / properties / include_breakfastRemoved value: -{ - "default": false, - "title": "Include Breakfast", - "type": "boolean" -} - removed
Input schema / properties / include_dinnerRemoved value: -{ - "default": false, - "title": "Include Dinner", - "type": "boolean" -}
- Removed
get_news - Removed
get_notification_history - Removed
get_notifications - Added
get_roster - Added
get_school_year - Removed
get_students - Removed
get_subjects - Removed
get_teachers - Added
get_timeline - Changed
get_timetable1 field changed- added
Input schema / properties / end_dateAdded value: +{ + "default": null, + "title": "End Date", + "type": "string" +}
- Removed
get_timetable_range - Removed
get_upcoming_events - Changed
login2 fields changed- added
Input schema / properties / methodAdded value: +{ + "default": "credentials", + "title": "Method", + "type": "string" +} - added
Input schema / properties / session_idAdded value: +{ + "default": null, + "title": "Session Id", + "type": "string" +}
- Removed
login_auto - Removed
login_from_session - Removed
school_year - Removed
two_factor_check_confirmed - Changed
two_factor_finish1 field changed- added
Input schema / properties / poll_secondsAdded value: +{ + "default": 60, + "title": "Poll Seconds", + "type": "integer" +}
- Removed
user_id
1 tool update
v0.4.10- Changed
get_day_summary1 field changed- added
Input schema / properties / fullAdded value: +{ + "default": false, + "title": "Full", + "type": "boolean" +}
46 tool updates
v0.4.6- First observed
auth_status - First observed
choose_meal - First observed
clear_student_cache - First observed
custom_request - First observed
find_student - First observed
get_absences - First observed
get_all_students - First observed
get_assignments - First observed
get_classes - First observed
get_classrooms - First observed
get_day_summary - First observed
get_grades - First observed
get_homework - First observed
get_meals - First observed
get_missing_teachers - First observed
get_my_students - First observed
get_my_timetable - First observed
get_news - First observed
get_next_ringing_time - First observed
get_next_week_timetable - First observed
get_notification_history - First observed
get_notifications - First observed
get_periods - First observed
get_schools - First observed
get_student_timetable - First observed
get_students - First observed
get_subjects - First observed
get_teachers - First observed
get_timetable - First observed
get_timetable_changes - First observed
get_timetable_range - First observed
get_upcoming_events - First observed
login - First observed
login_all - First observed
login_auto - First observed
login_from_session - First observed
rate_meal - First observed
scan_students - First observed
school_year - First observed
send_message - First observed
sign_off_meal - First observed
switch_to_parent - First observed
switch_to_student - First observed
two_factor_check_confirmed - First observed
two_factor_finish - First observed
user_id
TDQS
Scored across 29 tools
Timetable and student-discovery tools genuinely overlap (get_student_timetable vs get_timetable; get_my_students vs scan_students vs get_roster), but the descriptions use explicit 'prefer X' cross-references and distinct argument patterns to steer agents correctly. Meal, auth, messaging, and timeline tools are sharply distinct. A few pairs could still be confused on first glance, but the documentation manages the ambiguity well.
Read-only tools uniformly follow get_<noun> (get_timetable, get_grades, get_day_summary, get_timetable_changes), and write tools mostly follow verb_noun (choose_meal, sign_off_meal, send_message, switch_to_student). Minor deviations exist: bare-verb login/login_all, the reversed two_factor_finish, and the noun-like custom_request break the pattern slightly.
At 29 tools the surface exceeds the comfortable range even for a broad school platform, and several tools are near-duplicates or conveniences rather than necessities (scan_students duplicates get_my_students across schools, get_my_timetable wraps get_timetable, custom_request is an escape hatch). The authors consolidated former tools into get_timeline, get_roster, and get_timetable, which helps, but the count remains heavy.
The read surface is exceptionally broad — timetables, grades, meals, substitutions, rosters, timeline categories, and a composite day summary — and writes cover meal booking, messaging, session switching, and cache management. Missing pieces like a message inbox or absence-excuse submission are minor for the apparent parent/student use case and are mitigated by the custom_request escape hatch.
Maintenance
Related MCP Connectors
Manage an EasyWeek business from AI: bookings, availability, customers, services, orders, messaging.
Messaging tools for AI agents: send messages, manage chats, groups and channels.
Email inboxes and calendars for AI agents: send, receive, search, draft and schedule.
Email inboxes and calendars for AI agents: send, receive, search, draft and schedule.
Related MCP Servers
- AlicenseAqualityFmaintenanceMCP server that connects Claude to Edupage, a school information system used across Europe. Provides access to timetables, grades, homework, messages, students, teachers, and more.251GPL 3.0
- FlicenseCqualityCmaintenanceEnables interaction with the Edookit school management system API, exposing attendance, lessons, people, grades, payments, courses, timetable, and individual goals as MCP tools.46-
- FlicenseNot gradedqualityBmaintenanceConnects AI agents to the École Directe API to access grades, homework, timetables, school life, messages, and documents.-
- FlicenseNot gradedqualityCmaintenanceEnables AI clients to access and query WebUntis school data, including timetables, homework, exams, absences, and more via MCP tools.-