Skip to main content
Glama

Librus MCP Server

License: MIT PyPI

An MCP server that gives AI assistants access to the Librus Synergia school gradebook: grades, attendance, timetable, homework, calendar, announcements, messages, formative assessments, school-year history, class-free days and student information. It supports several logins at once, built on the independent librus-python-api.

Version 2.0 replaces the librus-apix backend used by every earlier version. Upgrading from 1.x? See Upgrading from 1.x.

Quick start

The commands below pin 2.3.1, using the native API 1.6.4. You need your Librus Synergia login and password. Accounts that require interactive two-factor authentication are not supported.

Pick one way to run it:

Way

Best for

Credentials

On your computer

Claude Code, Claude Desktop, Gemini CLI, Codex, OpenCode, Hermes on the same machine

a private config.json, any number of logins

Desktop bundle

one-click install in apps that support MCP Bundles

the app's settings form, one login

Self-hosted with Docker

agents on another machine of yours, connecting over HTTP

a private config.json or environment, any number of logins

MCP Registry

clients that install servers from the official registry

the client's settings form, one login

All of them run the server on a machine you control. It connects only to Librus; see Privacy.

On your computer

You do not need to clone this repository or install Python yourself. uv downloads Python 3.14 and the server automatically.

1. Install uv. On macOS or Linux, open a terminal and run:

curl -LsSf https://astral.sh/uv/install.sh | sh

On Windows, open PowerShell and run:

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Close and reopen your AI assistant afterwards.

2. Create a private configuration file. Save this as config.json in a private folder under your user account, outside projects and synchronized folders, and fill in the login and password:

{
  "accounts": [
    {"alias": "daughter", "username": "12345", "password": "YOUR_PASSWORD"}
  ]
}

The alias is the short name you use when asking about this login. For more logins, add more objects to accounts, each with its own alias:

{
  "accounts": [
    {"alias": "anna", "username": "12345", "password": "FIRST_PASSWORD"},
    {"alias": "jan", "username": "67890", "password": "SECOND_PASSWORD"}
  ]
}

Suggested locations:

  • macOS: /Users/YOUR_NAME/.config/librus-mcp/config.json

  • Linux: /home/YOUR_NAME/.config/librus-mcp/config.json

  • Windows: C:\Users\YOUR_NAME\.config\librus-mcp\config.json

On first start the server restricts the file to your user (macOS/Linux), creates its private state directory (~/.librus-mcp) and a persistent key there. There is nothing else to set up. Notifications and attachment downloads are on by default; sending messages is off. To change that, add for example:

"features": {"notifications": true, "attachments": false, "send_message": true}

For a single login you can skip the file and set environment variables instead: LIBRUS_USERNAME, LIBRUS_PASSWORD and optionally LIBRUS_ALIAS (default librus). Installers that collect settings in a form use these.

3. Connect your assistant. Replace the path with your file's absolute path.

Claude Code:

claude mcp add --scope user --transport stdio librus \
  -- uvx --python 3.14 librus-mcp==2.3.1 --config /absolute/path/to/config.json

Claude Desktop (Settings > Developer > Edit Config):

{
  "mcpServers": {
    "librus": {
      "command": "uvx",
      "args": ["--python", "3.14", "librus-mcp==2.3.1", "--config", "/absolute/path/to/config.json"]
    }
  }
}

Gemini CLI:

gemini mcp add --scope user --transport stdio \
  librus uvx --python 3.14 librus-mcp==2.3.1 --config /absolute/path/to/config.json

OpenAI Codex CLI:

codex mcp add librus \
  -- uvx --python 3.14 librus-mcp==2.3.1 --config /absolute/path/to/config.json

OpenCode:

opencode mcp add librus --global -- \
  uvx --python 3.14 librus-mcp==2.3.1 --config /absolute/path/to/config.json

Hermes Agent (~/.hermes/config.yaml):

mcp_servers:
  librus:
    command: "uvx"
    args: ["--python", "3.14", "librus-mcp==2.3.1", "--config", "/absolute/path/to/config.json"]

Check the setup without contacting Librus:

uvx --python 3.14 librus-mcp==2.3.1 --config /absolute/path/to/config.json --check-config

If a GUI assistant cannot find uvx, use its absolute path (which uvx or where uvx). Restart or reconnect the assistant after changing the file.

Desktop bundle (preview)

Each release attaches librus-mcp-2.3.1.mcpb to its GitHub release. Open it with an app that supports MCP Bundles, such as Claude Desktop. The app asks for the Librus login and password, keeps them in its settings, and installs Python 3.14 and the exact dependency versions this release was tested with. The bundle serves one login; use On your computer for several.

Self-hosted with Docker

Run the server on your own Docker host and connect agents on other machines over HTTP. Every request needs a bearer token. The server has no TLS of its own, so expose it only through a reverse proxy with TLS or a private network such as Tailscale or WireGuard. Never publish the port on a public or shared network.

1. Prepare a private folder on the Docker host with the configuration and a token. The files must belong to the user that runs the container and be readable only by it:

mkdir -p ~/librus-mcp/data && cd ~/librus-mcp
# config.json: the same format as above, any number of logins
docker run --rm ghcr.io/krzysztofbury/librus-mcp:2.3.1 --generate-token > token
chmod 600 config.json token

2. Start it with this compose.yaml, replacing 1000:1000 with the output of id -u and id -g:

services:
  librus-mcp:
    image: ghcr.io/krzysztofbury/librus-mcp:2.3.1
    command: ["--transport", "http", "--allowed-host", "librus-mcp.example.lan:*"]
    user: "1000:1000"
    environment:
      LIBRUS_CONFIG: /config/config.json
      LIBRUS_MCP_TOKEN_FILE: /config/token
    volumes:
      - ./config.json:/config/config.json:ro
      - ./token:/config/token:ro
      - ./data:/data
    ports:
      # Loopback for a reverse proxy on this host, or your VPN address instead.
      - "127.0.0.1:8000:8000"
    restart: unless-stopped
docker compose up -d
docker compose logs librus-mcp

The endpoint is /mcp at your proxy's HTTPS address, or at your VPN address on port 8000. --allowed-host lists the host names clients use; NAME:* accepts NAME with any port or none. A reverse proxy must forward the original Host header: Caddy and Traefik do by default, nginx needs proxy_set_header Host $host;. Without --allowed-host the server logs that Host header checks are off and relies on the token alone. In the image the server listens on every container interface; the ports: line decides who can reach it. ./data keeps the private state, persistent key and downloads, so back it up.

3. Connect your agent with the token as a bearer header. For Hermes Agent:

mcp_servers:
  librus:
    url: "https://librus-mcp.example.lan/mcp"
    headers:
      Authorization: "Bearer YOUR_TOKEN"

Other clients that support streamable HTTP take the same URL and header.

Things to know about HTTP mode:

  • One token grants every configured login. Run one deployment per trusted person, and replace the token if it leaks.

  • Let one agent poll notifications for each login: delivery and acknowledgement are designed for a single consumer.

  • download_attachment saves files on the Docker host under ./data/downloads. A remote agent cannot read that path; small files (up to 256 KiB) are also offered as a short-lived MCP resource.

  • If you enable send_message, anyone with the token can confirm a send preview. The server warns about this at startup.

  • Without a user: line the container runs as uid 10001; a named volume then works as is, but the configuration and token files must belong to uid 10001.

  • Instead of files, LIBRUS_ACCOUNTS (a JSON list of accounts), or LIBRUS_USERNAME and LIBRUS_PASSWORD for one login, and LIBRUS_MCP_TOKEN can be passed as environment variables.

The same image also runs over stdio for a client on the Docker host: docker run -i --rm -v librus-mcp-data:/data -e LIBRUS_USERNAME -e LIBRUS_PASSWORD ghcr.io/krzysztofbury/librus-mcp:2.3.1.

MCP Registry

The server is listed in the official MCP Registry as io.github.krzysztofbury/librus-mcp, with the PyPI package, the container image and the desktop bundle. Clients that install from the registry ask for LIBRUS_USERNAME and LIBRUS_PASSWORD, and optionally LIBRUS_ALIAS.

Related MCP server: librus-mcp

Upgrading from 1.x

Change the version in your assistant's configuration to librus-mcp==2.3.1, add --python 3.14 before it and keep your existing --config file. On first start 2.0 adapts the old setup automatically: it creates the key, restricts shared 1.x folders to your user, ignores the removed behaviour-notes setting and adopts 1.x notification history on the first check. Stop 1.x server processes that use the same folders before switching.

Notifications and attachments stay on by default, as in 1.x. Tool names and results changed on purpose (for example list_students is now list_accounts and student_alias is account_alias). Assistants read the new tool list automatically; custom scripts must follow the migration guide.

Tools and safety

The default catalog has 31 typed tools:

  • Accounts/profile: list_accounts, get_student_information.

  • Grades: get_grades, get_final_grades, get_grades_window.

  • Attendance: get_attendance, get_attendance_window, get_attendance_detail, get_attendance_frequency, get_subject_frequency.

  • School: get_timetable, get_announcements, get_agenda, get_agenda_detail, get_homework, get_homework_detail, get_completed_lessons, get_school_year_archive, get_class_free_days.

  • Communication: get_messages, get_message_content, get_recipient_types, get_recipient_choices, get_recipients, get_message_correspondents, get_teacher_subjects, get_message_unread_counts.

  • Notifications: get_new_notifications, get_notification_status, acknowledge_notifications (feature notifications).

  • Files: download_attachment and runtime-only attachment resources (feature attachments).

Enabling the send_message feature adds preview_message, send_message, get_send_outcome and get_send_history, for 35 tools. Disabling notifications and attachments leaves 27 tools.

Collections are paged with limit and a cursor. Every login is independent, including logins for the same student. Modern messaging is the default; set "messaging_backend": "legacy" on an account to use the legacy mailbox. Behaviour notes remain unavailable. Observation cards are supported as formative grades.

What's new in 2.1

Keep your existing 2.0 configuration, context key and durable state; reconnect your assistant to refresh its tool catalog. The server pins API 1.6.4.

  • Ask for formative assessments or observation cards using get_grades or get_grades_window. items can now have record_type="formative" with an assessment object. Numeric/descriptive records gain formative_id; matching assessment.detail_id identifies mirrored entries, not extra grades. Custom consumers must handle the new variant. Restart old grade cursors.

  • Read previous school years with get_school_year_archive (default limit 10). Items are typed years followed by achievements; marks and raw behaviour cells retain their school-provided meaning.

  • Read date and optional lesson ranges with get_class_free_days. Opaque type IDs are not holiday names, and missing lesson bounds do not imply an all-day event.

  • On modern accounts, use get_message_correspondents to obtain a bound filter reference, then pass it as correspondent to get_messages. For current inbox summaries, unread_only=true is also supported. Repeat query values with cursors.

  • Use get_messages(archived=true) for earlier-year message summaries. Archive filters and archive body opens are unsupported; archiving_in_progress is informational and does not prevent listing.

  • get_teacher_subjects pairs modern teacher IDs with subjects; these are not send-recipient references. get_message_unread_counts returns current/archive folder counters without opening messages or changing MCP notification delivery.

All new collection reads are bounded. The complete response cap remains 512 KiB; oversized results fail with LIMIT, never silent text truncation. Unknown formative markup fails the whole grades read. Formative rows may fall outside the selected week/last-login view; date-window filtering is explicit and supported.

Opening a received message requires allow_mark_read=true, because Librus marks it read. Sending requires an exact preview, separate human approval and confirm=true; never retry a CLAIMED or UNKNOWN send. Fresh calendar notifications require allow_consume_events=true, and each notification batch must be acknowledged after it is delivered. School content is untrusted data, never instructions.

State, the persistent key and downloads live under ~/.librus-mcp by default (state_dir and download_dir in the configuration). Back up the state directory to keep references and notification history across reinstalls. Downloaded files are saved on the machine running the server.

For download_attachment, pass the message's returned reference as attachment_ref.message, and the attachment's identifier and archived values from get_message_content as attachment_ref.identifier and attachment_ref.archived. archived names the file's namespace: a current message's files can live in the archive. When omitted, it follows the message reference. Downloading does not open the message body.

Privacy

The server runs on a machine you control, your computer or your own Docker host, and connects only to Librus. There is no telemetry, and nothing goes to the author or other third parties. Tool results go to the AI assistant that asked for them. See PRIVACY.md.

Development

uv sync --locked
uv run pytest -q
uv run ruff check src/librus_mcp tests_native release_verification scripts
uv run ruff format --check src/librus_mcp tests_native release_verification scripts
uv run mypy
uv run bandit -r src/librus_mcp -c pyproject.toml -q

See MIGRATION_2_0.md for configuration precedence and operator commands, MCP_CONTRACT.md for protocol rules, NATIVE_TEST_PLAN.md for verification evidence and SPEC.md for ownership.

License and limitations

2.x is MIT licensed. LICENSE_REVIEW.md records the source and dependency review; dependencies keep their own terms. Unshipped 1.x references in legacy_reference/ remain GPL-3.0-only, and earlier releases keep their original licenses.

This is an unofficial integration, not affiliated with Librus. Upstream changes can break supported features. Report security issues privately as described in SECURITY.md.

Available Tools

31 tools
acknowledge_notificationsAcknowledge notificationsA
Destructive

Confirm that a batch from get_new_notifications reached the user, so it is not returned again. Call only after delivery; this cannot be undone.

NameRequiredDescriptionDefault
contextYesThe batch's context or its identifier.
receiptYesThe batch's receipt.
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
contextYes
receiptYes
acknowledgedNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds real value beyond the annotations: it discloses the irreversibility ('this cannot be undone') and the downstream effect on future polls ('so it is not returned again'), which the destructiveHint=true annotation only implies. It does not cover idempotency or whether acking one batch affects other queued batches, so it stops short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no filler. The purpose and its consequence come first, and the call precondition plus irreversibility warning follow — correctly front-loaded in priority order.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists and annotations declare the destructive profile, so the description needn't explain returns or safety. What it supplies — purpose, ordering, irreversibility — closes most gaps; only edge-case behavior (retry after failed delivery, idempotency) is unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all three parameters (account_alias, receipt, context) are already documented in the schema, including the note that context is accepted verbatim from a poll. The description adds nothing parameter-specific, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (acknowledge/confirm) against a specific resource (a batch from get_new_notifications) and names the producing sibling, so the agent can tell it apart from get_notification_status and get_new_notifications. The stated effect ('so it is not returned again') makes the operation's outcome concrete.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly gates invocation with 'Call only after delivery', which implies the correct predecessor tool (get_new_notifications) and an ordering constraint. It lacks a full exclusions statement (e.g., what to do if delivery failed, or whether an already-acknowledged batch can be re-sent), but the positive trigger is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

download_attachmentDownload attachmentA

Save one message attachment to the server's private download folder and return its local path, size and SHA-256. Never overwrites a file or opens the message. On Linux and macOS, files up to 256 KiB are may also be offered as a 15-minute MCP resource.

NameRequiredDescriptionDefault
filenameYesName to save as, e.g. its filename.
max_bytesNoRefuse larger files.
account_aliasYesLogin alias from list_accounts.
attachment_refYesmessage: the message_ref you opened; identifier, archived: from the attachment.

Output Schema

NameRequiredDescription
sha256Yes
filenameYes
local_pathYes
size_bytesYes
content_typeYes
resource_uriYes
resource_ttl_secondsYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=false and openWorldHint=true, so the safety profile is partly given. The description nevertheless adds real behavioral detail beyond that: it never overwrites an existing file, does not open the message, and on Linux/macOS offers small files as a 15-minute MCP resource. It stops short of describing permissions, error conditions, or what happens if the file exceeds max_bytes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the action and return values, followed by safety guarantees and the resource offer. The only blemish is the grammar error 'files up to 256 KiB are may also be offered', which slightly interrupts an otherwise efficient structure.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With annotations covering the safety profile and an output schema covering the return value, the description fills the remaining gaps: destination folder, no-overwrite guarantee, no message opening, and resource TTL behavior. It is nearly complete, missing only failure/limit behavior when max_bytes is exceeded and the prerequisite of obtaining message_ref via get_message_content.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter (filename, max_bytes, account_alias, attachment_ref) is already documented in the schema. The description adds no parameter-level meaning beyond 'one message attachment', leaving this at the baseline for a fully-covered schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific verb and resource ('Save one message attachment'), the destination ('server's private download folder'), and the return payload ('local path, size and SHA-256'). No sibling tool does this, so the agent can distinguish it immediately from get_message_content or get_messages.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied by the name and the 'never opens the message' remark; there is no explicit 'use this when you need X instead of get_message_content' routing or when-not guidance. The agent can infer the purpose but is not told how to choose among the messaging siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_agendaCalendarA

List one month of school calendar events such as tests, trips and days off. Pass an event's reference, when present, to get_agenda_detail. Selecting the month also changes the month this login's Librus session remembers.

NameRequiredDescriptionDefault
yearYesCalendar year.
monthYesMonth, 1 to 12.
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
yearYes
itemsYes
monthYes
identityYes
timezoneNo
paginationNo
observationYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses a non-obvious side effect that annotations alone would not explain: selecting the month 'changes the month this login's Librus session remembers,' which accounts for readOnlyHint=false. No auth, rate-limit, or pagination details, but the state-mutation disclosure is the material fact an agent needs before calling this.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, each doing distinct work: purpose, routing, and side effect. The most surprising fact (session month mutation) is placed last rather than front-loaded, but nothing is padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, and all three parameters are documented. Combined with the sibling routing and the session-state caveat, an agent has what it needs to call this correctly; only operational details like error behavior are absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% (year, month 1-12, account_alias from list_accounts), so the schema already carries parameter meaning. The description reinforces the one-month scope but adds no format or constraint detail beyond what the schema provides — baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List one month of school calendar events') with concrete examples of contents (tests, trips, days off) and an explicit scope of one month. This clearly separates it from get_agenda_detail, which is named as the follow-up for a single event.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: use this for the monthly list, then 'pass an event's reference, when present, to get_agenda_detail.' The when-not guidance is implicit rather than stated (nothing says when to skip this tool), but the alternative is named and the handoff condition is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_agenda_detailCalendar event detailsA
Read-only

Get every detail of one calendar event. Use the same account_alias that get_agenda used.

NameRequiredDescriptionDefault
event_refYesAn event's reference from get_agenda, unchanged.
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
dataYes
identityYes
observationYes

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds the cross-call consistency requirement on account_alias, which is genuinely useful behavioral context, but says nothing about failure modes (stale or foreign event_ref) or the fact that returned detail may reflect live upstream data.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, purpose first, constraint second, with zero boilerplate. Every clause carries information the agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value detail needn't be restated, and both parameters are fully described in the schema. The description supplies the missing piece — the dependency on a prior get_agenda call and alias reuse — making this callable without guessing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both fields are already documented ('An event's reference from get_agenda, unchanged', 'Login alias from list_accounts'). The description's only addition is the requirement that account_alias match the earlier get_agenda call, which is a marginal but real constraint beyond the schema — baseline 3 fits.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get every detail of one calendar event'), which distinguishes it from the list-level sibling get_agenda and parallels get_homework_detail. It stops short of naming the sibling it complements explicitly, but the singular 'one calendar event' plus 'detail' makes the distinction readable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The second sentence establishes the prerequisite workflow: use the same account_alias that get_agenda used, which tells the agent this tool is a follow-up call to get_agenda. It does not state when NOT to use it or what to do with an event_ref from a different account, leaving a small inference gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_announcementsAnnouncementsA
Read-only

Get all school announcements with their full text. Does not mark them read in Librus.

NameRequiredDescriptionDefault
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
itemsYes
identityYes
paginationNo
observationYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the read-only and open-world profile, so the description's real contribution is the side-effect disclosure that retrieving announcements does not mark them as read in Librus — non-obvious context an agent would otherwise lack. It also signals the response includes full bodies. It omits ordering, volume, and pagination behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, no filler, with the core capability stated first and the side-effect caveat second. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and a single fully documented parameter, the description need only cover intent and side effects, which it does. The remaining gap is minor: nothing about result size, ordering, or whether announcements are filtered by date or read state.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is a single parameter with 100% schema coverage, including an explicit pointer to list_accounts, so the schema carries the semantics. The description adds nothing about account_alias, which is the correct baseline for fully documented parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

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 all school announcements') plus a payload qualifier ('with their full text'), which is more than a restatement of the name. It does not explicitly distinguish itself from nearby read tools like get_messages or get_new_notifications, so it stops short of full sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: an agent can infer this is the tool for announcement content, and 'Does not mark them read' hints at a contrast with notification-acknowledging tools. There is no explicit when-to-use/when-not statement or named alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_attendanceAttendanceA

List attendance records. For a date range use get_attendance_window; for totals use get_attendance_frequency. scope also changes the view this login's Librus session remembers.

NameRequiredDescriptionDefault
limitNoMaximum items in this page.
scopeNoLibrus view: all, or its week or last_login recent-changes filter; not dates.all
cursorNonext_cursor from the previous page; omit for the first page.
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
itemsYes
scopeYes
identityYes
semestersYes
paginationYes
observationYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations declare readOnlyHint=false, which would otherwise puzzle an agent for a 'List' tool; the description resolves this by disclosing that scope mutates the persisted view in this login's Librus session. It does not say how long that remembered view persists or what else it affects, so a small gap remains. No contradiction with annotations — the disclosure actually explains them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core action and followed by routing and side-effect notes; nothing is padding. The session-memory sentence is slightly opaque in phrasing ('the view this login's Librus session remembers'), costing a little clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, annotations cover the safety profile, and pagination is documented on the cursor/limit params, so the description only needs routing and side effects — both delivered. Ordering of returned records and what 'all' vs 'week' actually contain are left to the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description earns one above baseline by adding the session-persistence meaning of scope, which the schema text does not convey. It adds nothing for limit, cursor, or account_alias, but those are already fully documented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List attendance records') and immediately distinguishes itself from the two nearest siblings, get_attendance_window and get_attendance_frequency. An agent can pick this tool over its siblings without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Two explicit alternative routes are given with their selecting conditions: date ranges go to get_attendance_window, totals go to get_attendance_frequency. This is a near-complete decision rule for the attendance family, leaving only the trivial default case implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_attendance_detailAttendance detailsA
Read-only

Get every field Librus shows for one attendance record, such as date and topic. The id comes from get_attendance, get_attendance_window or get_completed_lessons.

NameRequiredDescriptionDefault
account_aliasYesLogin alias from list_accounts.
attendance_idYesA record's detail_id, or a lesson's attendance_detail_id.

Output Schema

NameRequiredDescription
dataYes
identityYes
observationYes

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds that the response is exhaustive ('every field Librus shows') and single-record scoped, but says nothing about failure modes (invalid id, record deleted) or cost. Adequate given annotations, not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences: the capability first, the provenance of the required id second. Nothing redundant with the name or schema text repeated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists, so return values needn't be described; the description correctly focuses on purpose and id provenance. For a two-param read tool this is nearly complete, with only error/edge-case behavior left implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and documents both parameters, including that attendance_id is a detail_id or a lesson's attendance_detail_id. The description adds value beyond the schema by naming the three sibling tools that produce a valid id, which the schema does not say.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: fetch every field for one attendance record, with examples of the fields (date, topic). It is clearly distinguishable from get_attendance and get_attendance_window (list/window-level), though it doesn't explicitly name those as the bulk alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says where the id must come from (get_attendance, get_attendance_window, get_completed_lessons), which effectively tells the agent this is a follow-up call after one of those. No explicit 'do not call for listing' exclusion, so just short of 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_attendance_frequencyAttendance frequencyA
Read-only

Get attendance totals for each semester and the year: attended, total, excluded and unknown lessons, with ratios from 0 to 1 (null when undefined). For a per-subject breakdown use get_subject_frequency.

NameRequiredDescriptionDefault
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
dataYes
identityYes
observationYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds genuinely useful data semantics beyond the annotations: ratios span 0 to 1 and are null when undefined, which prevents misinterpretation of empty values. It stops short of mentioning pagination or performance characteristics, but the output schema covers return structure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with no filler. The core capability and the returned fields come first, and the sibling routing note comes second, which is the right ordering for a reader deciding whether to keep reading.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With only one parameter, full schema coverage, and an output schema present, the description need only establish scope and routing. It does both, and the null-ratio note resolves the one ambiguity an agent would otherwise hit when reading results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is a single required parameter with 100% schema description coverage, and the schema states it is the login alias from list_accounts. The description adds nothing about account_alias, so the baseline of 3 applies since the schema carries the full burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Get attendance totals') and resource scope ('for each semester and the year'), then enumerates the returned measures (attended, total, excluded, unknown). It also explicitly names the sibling it is not for per-subject data, making selection unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the alternative explicitly: 'For a per-subject breakdown use get_subject_frequency.' That is a clear routing condition. It does not, however, distinguish itself from other attendance siblings such as get_attendance, get_attendance_window, or get_attendance_detail.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_attendance_windowAttendance by dateA

List attendance records dated within date_from..date_to. Use this instead of get_attendance for a date range. scope also changes the view this login's Librus session remembers.

NameRequiredDescriptionDefault
limitNoMaximum items in this page.
scopeNoLibrus view: all, or its week or last_login recent-changes filter; not dates.all
cursorNonext_cursor from the previous page; omit for the first page.
date_toNoLast day, YYYY-MM-DD, inclusive; at most 370 days after the first.
date_fromNoFirst day, YYYY-MM-DD, inclusive.
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
itemsYes
scopeYes
date_toYes
identityYes
date_fromYes
paginationYes
observationYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false, which is surprising for a list operation; the description explains why by disclosing that 'scope' mutates the session-remembered view. That is exactly the kind of side effect annotations alone can't convey. It doesn't cover pagination behavior or the 370-day window, though the schema does.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, the scoping definition front-loaded and the disambiguation second. Every clause carries unique information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return format needn't be described, and all parameters are documented in the schema. The description covers the one non-obvious behavioral hazard (session view mutation); only minor gaps like pagination flow remain.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3; the description adds genuine meaning beyond the schema by explaining that scope changes the login's remembered Librus view, not just the returned slice. It doesn't add anything for date_from/date_to or cursor beyond what the schema already documents.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (List) and resource (attendance records) plus the exact scope ('dated within date_from..date_to'). The second sentence names the sibling it replaces and the condition, so an agent can distinguish it from get_attendance without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit routing: 'Use this instead of get_attendance for a date range' gives both the alternative and the selecting condition. It also warns that scope alters the remembered session view, which affects repeat calls.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_class_free_daysClass-free daysA
Read-only

List the class's days and lesson ranges without classes, such as holidays and school free days. type_id is an opaque code, not a name; a day without lesson numbers is not necessarily free all day.

NameRequiredDescriptionDefault
limitNoMaximum items in this page.
cursorNonext_cursor from the previous page; omit for the first page.
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
itemsYes
identityYes
paginationYes
observationYes

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, so the safety profile is covered. The description adds genuinely useful behavioral caveats beyond that: type_id is an opaque code rather than a name, and a day lacking lesson numbers is not necessarily free all day — both prevent misinterpretation of results.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the purpose and followed by the interpretive caveats. Every clause earns its place, with only minor room to be tighter.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and the description still supplies the key semantic caveats about type_id and partial-day freedom. Complete enough for a read-only listing tool; only the lack of guidance versus sibling day/timetable tools leaves a small gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with limit, cursor, and account_alias all documented in the schema, so baseline is 3. The description mentions type_id, which is a response field rather than an input parameter, and does not add syntax or format detail for the actual inputs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'List the class's days and lesson ranges without classes,' with concrete examples (holidays, school free days). The resource is distinct enough from siblings like get_timetable and get_attendance that an agent can separate them, though the description never names an alternative explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The use case is implied clearly — query this to find holidays and class-free days — but there is no explicit when-to-use/when-not guidance and no reference to sibling tools such as get_timetable or get_completed_lessons that also touch scheduled days.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_completed_lessonsCompleted lessonsA

List lessons already held between two dates: subject, teacher, topic and attendance mark. Continue with the returned cursor and the same dates. The range also changes what this login's Librus session remembers.

NameRequiredDescriptionDefault
limitNoMaximum items in this page.
cursorNonext_cursor from the previous page; omit for the first page.
date_toYesLast day, YYYY-MM-DD, inclusive; at most 370 days after the first.
date_fromYesFirst day, YYYY-MM-DD, inclusive.
max_pagesNoMaximum Librus pages fetched by this call.
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
itemsYes
date_toYes
identityYes
date_fromYes
paginationYes
observationYes

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations mark this as not read-only and open-world; the description adds the non-obvious side effect that the date range changes what the Librus session remembers. That is consistent with readOnlyHint=false, though the phrase 'remembers' is vague about exactly what changes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the resource and date-range scope. The session-memory sentence is slightly opaque but still carries behavioral information, so the description is appropriately sized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given full schema coverage, an output schema, and annotations, the definition gives enough to call this paginated list correctly and warns of its session side effect. It is not fully self-contained about alternatives, but that gap belongs mainly to usage guidance.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with date, cursor, limit, max_pages, and account_alias documented in the schema. The description adds the useful constraint to reuse the same dates with the cursor, but it does not clarify limit, max_pages, or account_alias beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: list lessons already held between two dates, with the fields returned. It is clear about what this tool returns, but it does not distinguish itself from siblings such as get_timetable or get_attendance.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains cursor continuation and that the same dates should be reused, which is useful invocation guidance. It does not say when to choose this tool over timetable, attendance, or date-window siblings, so usage is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_final_gradesFinal gradesA
Read-only

Get midterm, predicted and annual grades per subject as the school published them. A column the school does not show is unavailable; an empty or - raw value is not given yet. For individual grades use get_grades or get_grades_window.

NameRequiredDescriptionDefault
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
itemsYes
identityYes
paginationNo
observationYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, so safety is covered. The description goes beyond them by disclosing data-availability semantics ('a column the school does not show is unavailable; an empty or - raw value is not given yet'), which tells the agent how to interpret nulls/dashes rather than misreading them as zeros. Lacks any note on freshness or caching.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences: what it returns, how to read gaps, and where to go instead. Front-loaded with the resource and zero filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists so return values needn't be described, and the null/unavailable-column caveat fills the main interpretive gap. Slightly short of 5 because openWorldHint implications (external school system, possible staleness) go unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Single required parameter with 100% schema description coverage ('Login alias from list_accounts'), so the schema already carries the semantics. The description adds nothing about the parameter, but with one fully-documented param the baseline of 4 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names the exact resource (midterm, predicted and annual grades per subject) and its provenance ('as the school published them'), which distinguishes it from the raw per-grade siblings. An agent can tell this is the aggregated/summary view.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: 'For individual grades use get_grades or get_grades_window.' That is a clear when-not with named alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_gradesGradesA

List grades with averages: numeric, descriptive and formative assessments, including observation cards. For a date range use get_grades_window. scope also changes the view this login's Librus session remembers and may not apply to formative rows. A grade whose formative_id equals a formative row's assessment.detail_id is one assessment, not two.

NameRequiredDescriptionDefault
limitNoMaximum items in this page.
scopeNoLibrus view: all, or its week or last_login recent-changes filter; not dates.all
cursorNonext_cursor from the previous page; omit for the first page.
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
itemsYes
scopeYes
averagesYes
identityYes
paginationYes
observationYes
descriptive_summariesYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations by disclosing a non-obvious side effect: the scope argument changes the remembered view of this login's Librus session, which explains why readOnlyHint is false despite this being a listing call. It also gives a deduplication rule (formative_id == assessment.detail_id means one assessment, not two) that prevents an agent from double-counting rows. A 4 rather than 5 because the session-side-effect warning is terse and its persistence/expiry is not stated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each doing distinct work: what is returned, which sibling to use instead, and two non-obvious data-shape caveats. The scope clause is dense and slightly cryptic ('the view this login's Librus session remembers'), but nothing is padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and the annotations plus full schema coverage carry the mechanical contract. The description closes the two real gaps an agent would trip on: picking the wrong grade tool and miscounting formative/observation rows. Missing only a note on how the session-scoped view resets.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so limit, cursor, scope and account_alias are all documented in structured fields; the baseline is 3. The description adds genuinely useful semantics for scope (it is a remembered session view, not a date filter) and for the formative-id overlap, but says nothing extra about cursor or limit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List grades with averages') and enumerates the grade kinds returned: numeric, descriptive, formative, plus observation cards. It clearly separates itself from get_grades_window, though it never contrasts with the sibling get_final_grades, leaving one obvious ambiguity for an agent choosing among grade tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes date-range needs to get_grades_window ('For a date range use get_grades_window'), which is exactly the alternative an agent would otherwise confuse this with. It also warns that scope may not apply to formative rows. No guidance on when to prefer get_final_grades, so not a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_grades_windowGrades by dateA

List grades and formative assessments dated within date_from..date_to, without averages (see get_grades). scope also changes the view this login's Librus session remembers and may not apply to formative rows. A grade whose formative_id equals a formative row's assessment.detail_id is one assessment.

NameRequiredDescriptionDefault
limitNoMaximum items in this page.
scopeNoLibrus view: all, or its week or last_login recent-changes filter; not dates.all
cursorNonext_cursor from the previous page; omit for the first page.
date_toNoLast day, YYYY-MM-DD, inclusive; at most 370 days after the first.
date_fromNoFirst day, YYYY-MM-DD, inclusive.
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
itemsYes
scopeYes
date_toYes
identityYes
date_fromYes
paginationYes
observationYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds useful behavior beyond the annotations: scope changes the Librus session's remembered view and may not apply to formative rows. This explains a stateful side effect that aligns with the non-read-only annotation, though it does not discuss permissions, rate limits, or pagination behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and avoids filler. The second sentence about scope and formative rows is somewhat dense, but every sentence carries relevant operational information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema and detailed input schema, the description is largely complete: it covers date filtering, the sibling relationship, scope behavior, and formative identity. Minor gaps around pagination or account context are handled by the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the parameters are already documented. The description still adds meaning by explaining the date range, the session-affecting caveat for scope, and the formative_id/detail_id relationship for identifying assessments.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource: 'List grades and formative assessments dated within date_from..date_to.' It also distinguishes this tool from get_grades by noting it returns results 'without averages,' so an agent can select it without guessing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The date-window use case is clear, and the parenthetical '(see get_grades)' points to the alternative for averages. However, it does not explicitly state when to prefer this tool versus get_grades beyond that single contrast, so it falls short of full when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_homeworkHomeworkA

List homework in a date range; give both dates or neither (today to 14 days ahead, Warsaw time). Pass an item's reference to get_homework_detail. The range also changes what this login's Librus session remembers.

NameRequiredDescriptionDefault
date_toNoLast day, YYYY-MM-DD, inclusive; at most 370 days after the first.
date_fromNoFirst day, YYYY-MM-DD, inclusive.
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
itemsYes
date_toYes
identityYes
date_fromYes
paginationNo
observationYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false with destructiveHint=false, which is counterintuitive for a list operation. The description explains why by disclosing the non-obvious side effect: the range alters what the login's Librus session remembers. That is real value beyond the annotations. It stops short of describing errors, rate limits, or what an invalid range does.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short clauses, front-loaded with purpose, then constraint, then handoff, then the side-effect note. Efficient overall, though the session-memory clause is compressed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers default window, timezone, date pairing, sibling handoff, and the session side effect, which is enough for a 3-param read tool with an output schema. Slightly less than fully complete because error and auth behavior remain unstated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so both date fields and the alias are already documented, setting the baseline at 3. The description adds the pairing constraint and the meaning of the null default, but not much else residual. Baseline 3 fits.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("List homework in a date range") and immediately distinguishes itself from the natural sibling by naming get_homework_detail as the follow-up call. An agent can tell which of the homework tools is the entry point without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives the concrete rule for the date parameters ("give both dates or neither") and explains how to reach detail records, plus what happens when omitted (today to 14 days ahead, Warsaw time). It doesn't state exclusions or when another sibling (e.g. agenda) would be preferable, so it falls short of a full when/when-not treatment.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_homework_detailHomework detailsA
Read-only

Get the full text of one homework assignment. Does not mark it read in Librus.

NameRequiredDescriptionDefault
homework_refYesAn item's reference from get_homework, unchanged.
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
dataYes
identityYes
observationYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, but the description adds genuinely non-obvious context: this does not mark the homework as read in Librus. That read-receipt side effect is exactly the kind of behavioral detail annotations cannot convey. It omits any note about error cases or missing IDs, keeping it short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, purpose front-loaded, with the side-effect caveat second. No filler and nothing repeated from the title or schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, and both parameters are fully documented in the schema. The description covers purpose and the mutation-free read-receipt behavior, which is enough to call it correctly; only the listing-to-detail flow is left implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% — `homework_ref` is documented as "an item's reference from get_homework, unchanged" and `account_alias` as coming from `list_accounts`. The description adds nothing beyond that, so baseline 3 applies for a 2-parameter tool whose schema does the work.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb and resource ("Get the full text of one homework assignment"), which distinguishes it from the bulk `get_homework` sibling by emphasizing single-item, full-text retrieval. It stops short of naming the sibling or the precondition, so differentiation is implied rather than explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied: fetch one assignment's body after locating it via `get_homework`, and the `homework_ref` parameter description reinforces that chain. There is no explicit when/when-not statement or named alternative, so the agent must infer the workflow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_message_contentRead messageA
Destructive

Get a message's full text and attachments. Librus marks a received message read when it is opened, so that needs allow_mark_read=true with the user's consent; sent messages do not. Archived messages cannot be opened.

NameRequiredDescriptionDefault
message_refYesA message's reference from get_messages.
account_aliasYesLogin alias from list_accounts.
allow_mark_readNoConsent to mark a received message read.

Output Schema

NameRequiredDescription
dataYes
backendYes
contextYes

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite readOnlyHint=false and destructiveHint=true, the description explains exactly what the side effect is (Librus marks a received message read on open) and how to gate it behind user consent. It also discloses a hard failure mode (archived messages cannot be opened), which annotations alone could not convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core action, then the consent requirement, then the failure condition. No filler and no repetition of schema content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists so return values need not be explained, and the mutation/consent and archived constraints are covered. It leaves mild ambiguity about whether attachment bytes are included or must be fetched via download_attachment, which matters given the sibling tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaning the schema lacks: allow_mark_read only matters for received messages and is a no-op for sent ones. The archived constraint also implicitly constrains the nested archived flag.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (retrieves a message's full text and attachments), clearly distinct from get_messages (listing) and download_attachment (binary fetch). An agent can immediately tell what this returns.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete conditional guidance: allow_mark_read=true is required for received messages but not sent ones, and archived messages cannot be opened. It does not explicitly name sibling alternatives or state that a message_ref must first come from get_messages, but that prerequisite is documented in the schema.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_message_correspondentsMessage correspondentsA
Read-only

Modern accounts: list the people in a mailbox folder, to filter get_messages by correspondent. These references cannot address a new message; use get_recipients for that.

NameRequiredDescriptionDefault
limitNoMaximum items in this page.
cursorNonext_cursor from the previous page; omit for the first page.
folderNoreceived or sent mail.received
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
itemsYes
identityYes
paginationYes
observationYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, so safety is covered. The description still adds real behavioral context beyond annotations: the returned references are address-only-unsuitable and are meant as filter inputs, not as recipients. Pagination behavior is left to the cursor/limit schema fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with no filler, and the positive use case is front-loaded ahead of the exclusion. The leading 'Modern accounts:' fragment is an unexplained gate that costs a little clarity for its brevity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and pagination is handled by the schema's cursor semantics. For a simple read-only list tool, the description covers purpose, consumer, and the key sibling distinction; only the account-type qualifier is left dangling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so account_alias, folder, limit and cursor are all documented in the schema. The description only loosely gestures at the folder parameter via 'in a mailbox folder' and adds no syntax or semantics beyond what the schema states. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'list the people in a mailbox folder', and names the downstream use (filtering get_messages by correspondent). The unexplained 'Modern accounts:' qualifier slightly muddies the scope, since an agent cannot tell what a non-modern account would mean or whether it applies.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the alternative and the exclusion: these references cannot address a new message, use get_recipients for that. It also names the consumer (get_messages), which routes the agent well. The remaining ambiguity is the unexplained 'modern accounts' condition, which is not resolved by any alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_messagesMessagesA

List message summaries (correspondent, subject, date, read state) without opening them; use get_message_content for the text. On legacy accounts the folder choice changes the view Librus remembers. Modern accounts can list the archive or filter current mail by correspondent or unread_only; archives cannot be filtered. Repeat the same filters with cursor.

NameRequiredDescriptionDefault
limitNoMaximum items in this page.
cursorNonext_cursor from the previous page; omit for the first page.
folderNoreceived or sent mail.received
archivedNoModern only: list earlier years' archive.
max_pagesNoMaximum Librus pages fetched by this call.
page_sizeNoMessages per Librus page; legacy accepts only 50.
unread_onlyNoModern only: unread received mail only.
account_aliasYesLogin alias from list_accounts.
correspondentNoModern only: a reference from get_message_correspondents.

Output Schema

NameRequiredDescription
itemsYes
folderYes
backendYes
archivedNo
identityYes
paginationYes
observationYes
unread_onlyNo
correspondentNo
archiving_in_progressNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations (readOnlyHint=false, openWorldHint=true) are non-obvious for a mail-listing tool, and the description supplies the reason: on legacy accounts the folder choice mutates the view Librus remembers. It also discloses the filtering limitation on archives and the cursor-repetition contract. It stops short of describing pagination cost (limit/max_pages interplay) or which behaviors differ under open-world access, so it lands just below a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences with no filler, and the distinction from get_message_content is front-loaded. It is slightly compressed in the middle, where legacy and modern behavior are packed into one long clause, but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a full output schema and 100% schema description coverage, the remaining burden is behavior and routing, both of which are covered (read-state fields, backend differences, cursor contract). The only substantive omission is how limit and max_pages jointly determine how much mail one call retrieves.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description earns above that by giving scoping semantics the schema does not: archived and the correspondent/unread_only filters are modern-only, archive results are unfilterable, and cursor must carry the same filters. The interaction between limit and max_pages remains unexplained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb and resource ('list message summaries') and enumerates the returned fields (correspondent, subject, date, read state), which defines both what it does and what it does not do ('without opening them'). It explicitly routes the full-text need to the sibling get_message_content, so an agent can separate the two without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the alternative (get_message_content) and the condition that selects it. It also gives per-backend usage rules: legacy folder choice has a remembered-state side effect, modern accounts may list archive or filter by correspondent/unread_only, archives cannot be filtered, and cursors must repeat the same filters. That is when/when-not guidance at the level of individual parameters.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_message_unread_countsUnread message countsA
Read-only

Modern accounts: get unread message counts for the current and archive folders without opening messages. Independent of get_new_notifications.

NameRequiredDescriptionDefault
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
dataYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is known. The description adds meaningful behavior beyond that: counts are produced 'without opening messages', i.e., no read-state side effects, and the results are independent of the notification tool. It doesn't address account-type eligibility implied by 'Modern accounts'.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, with the capability and its folder scope stated first and the sibling disambiguation second. Nothing is redundant with the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation, and the single parameter is fully specified in the schema. The only unresolved gap is the unexplained 'Modern accounts' qualifier, which leaves the agent unsure which accounts this applies to.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is a single required parameter and schema description coverage is 100%, with the schema itself pointing to list_accounts for the alias. The description adds no additional parameter meaning, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb and resource ('get unread message counts') and adds scope the name omits: current and archive folders. It also explicitly separates itself from the sibling get_new_notifications, so an agent can choose between the two without reading either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Independent of get_new_notifications' tells the agent these two tools do not overlap and should not be chained or substituted for one another. What is missing is an explicit directive on when to call this one (e.g., for inbox badge counts) versus get_messages.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_new_notificationsNew notificationsA
Destructive

Check a login for new grades, attendance, messages, announcements, calendar events or homework. The batch is stored and returned again, for the same categories, until acknowledge_notifications. Librus reports new calendar events only once, so they need allow_consume_events=true. Changes the grade, attendance and homework views Librus remembers; never opens messages.

NameRequiredDescriptionDefault
categoriesYesWhich kinds of news to check.
account_aliasYesLogin alias from list_accounts.
allow_consume_eventsNoConsent to fetch read-once calendar news.

Output Schema

NameRequiredDescription
dataYes
delivery_semanticsNo
acknowledgement_requiredNo

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations by disclosing that the call mutates server-side remembered views for grades, attendance and homework, that results are deduplicated/batched until acknowledged, and that events are read-once unless consented. It also clarifies 'never opens messages', a side-effect boundary the agent could not infer. This is exactly the context needed to reconcile a 'get_' name with destructiveHint=true.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four dense sentences, each carrying unique information (scope, batch lifecycle, read-once consent, side effects). The primary purpose is front-loaded and the caveats follow logically with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described. The description covers everything an agent needs to call this correctly: category scope, the acknowledge lifecycle, the read-once event caveat, and the state mutation. Nothing material is missing for a 3-parameter tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds real meaning for allow_consume_events by explaining Librus reports new calendar events only once and that the flag is consent to consume them. That is a genuine semantic addition beyond 'Consent to fetch read-once calendar news'. Categories and account_alias are left to the schema, which already documents them.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('check a login for new grades, attendance, messages, announcements, calendar events or homework') that maps cleanly to the category enum. It implicitly separates itself from the raw fetchers (get_grades, get_attendance) by the word 'new' and references acknowledge_notifications as the clearing step. It stops short of naming a sibling it should replace, so it is clear but not maximally differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains the lifecycle: the batch is re-returned for the same categories until acknowledge_notifications, which tells the agent when this tool is the right entry point versus the raw category getters. It also gives conditional guidance for allow_consume_events ('need allow_consume_events=true'). No explicit when-not/exclusion is stated, keeping it at 4.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_notification_statusNotification statusB
Read-only

Show whether a login has an unacknowledged notification batch or an uncertain delivery to resolve. Offline: it does not check Librus or acknowledge anything.

NameRequiredDescriptionDefault
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
dataYes
has_pending_workYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the read-only and offline profile is pre-known; the description largely corroborates this with "Offline: it does not check Librus or acknowledge anything." That is useful confirmation but adds little new behavioral detail, and terms like "uncertain delivery to resolve" are left undefined.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with the state check front-loaded and the negative scope (offline, non-acknowledging) immediately after. No filler, though the second sentence could be slightly more concrete about what it does instead of Librus checks.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and a single fully-described parameter, most of the informational burden is carried elsewhere. Still, key domain concepts ("unacknowledged notification batch", "uncertain delivery") are unexplained and the relationship to the notification siblings is not stated, so an agent may not know what to do with the returned state.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single account_alias parameter is fully documented in the schema (including the list_accounts provenance), so the description carries little burden. "Whether a login" merely echoes the parameter; nothing new is added about alias resolution or failure modes.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb ("Show whether") plus a well-scoped resource: the notification state of one login, covering both an unacknowledged batch and an uncertain delivery. It is distinguishable from get_new_notifications (fetches) and acknowledge_notifications (mutates), though it never names those siblings explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The clause "it does not check Librus or acknowledge anything" implies when this tool is the wrong choice and that acknowledge_notifications is the follow-up, but no sibling is named and no explicit condition selects this over get_new_notifications. Usage is inferable rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_recipient_choicesRecipient choicesA
Read-only

Legacy accounts only: list the sub-choices of a hierarchical recipient group, such as classes. Put the chosen item's reference.selection_id into recipient_type for get_recipients. Modern accounts return UNSUPPORTED_CAPABILITY.

NameRequiredDescriptionDefault
account_aliasYesLogin alias from list_accounts.
recipient_typeYesA group's reference from get_recipient_types.

Output Schema

NameRequiredDescription
itemsYes
backendNo
contextYes
identityYes
paginationNo
observationYes

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this is a safe read operation with openWorldHint, so the description does not need to restate safety. It adds useful behavior beyond annotations: legacy-only availability and a specific error code for modern accounts. It does not discuss pagination or rate-limit behavior, but the output schema covers return values.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the legacy-only constraint and tool purpose. Every sentence carries useful information: the resource, the chaining instruction, and the modern-account error behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that annotations cover safety, the schema fully documents parameters, and an output schema exists, the description supplies everything else an agent needs: availability constraints, the intended follow-up call, and the error case. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds workflow semantics by explaining that the chosen item's reference.selection_id should be placed into recipient_type for get_recipients, which clarifies how this tool's output feeds the next call. That is meaningful beyond the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource: listing sub-choices of a hierarchical recipient group, such as classes. It immediately distinguishes this from sibling tools by scoping it to legacy accounts and by linking the result to get_recipients. An agent can understand exactly what this tool returns without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the precondition (legacy accounts only) and gives an explicit next step: put the chosen item's reference.selection_id into recipient_type for get_recipients. It also explains the modern-account outcome (UNSUPPORTED_CAPABILITY), so the agent knows both when to call it and what happens when it should not.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_recipientsRecipientsA

List the people in one recipient group, to address a message. Modern students and parents groups include virtual accounts only with include_virtual=true in recipient_type. On legacy accounts the lookup changes this login's Librus form state. Nothing is sent.

NameRequiredDescriptionDefault
account_aliasYesLogin alias from list_accounts.
recipient_typeYesA group's reference from get_recipient_types.

Output Schema

NameRequiredDescription
itemsYes
backendYes
contextYes
identityYes
paginationNo
observationYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false, which is counterintuitive for a listing tool; the description resolves this by disclosing that on legacy accounts the lookup mutates the login's Librus form state, and reassures with "Nothing is sent." That is exactly the kind of side-effect context annotations cannot express, though rate limits and whether modern backends mutate are left unstated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core action, and the closing "Nothing is sent." is a deliberate, load-bearing safety note. The include_virtual sentence is slightly compressed/dense but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation, and the description covers the two things an agent could otherwise get wrong: the group-vs-types scope and the legacy form-state side effect that justifies readOnlyHint=false. Nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description does add real meaning for include_virtual by scoping it to modern students/parents groups, but it says nothing about selection_id, backend, account, or identifier beyond what the schema already carries.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb and resource: "List the people in one recipient group, to address a message," which cleanly separates it from get_recipient_types (groups) and get_message_correspondents. It stops short of naming an alternative sibling explicitly, so it lands just below top marks.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The purpose clause ("to address a message") implies the compose-a-message context, and the include_virtual conditional is a genuine usage rule. However, there is no explicit statement of when not to use it versus get_recipient_types/get_recipient_choices, so routing guidance is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_recipient_typesRecipient typesA
Read-only

List the recipient groups this login can message and whether each can be looked up. Pass a group's reference to get_recipients, or on legacy accounts to get_recipient_choices. Sends nothing.

NameRequiredDescriptionDefault
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
itemsYes
backendYes
identityYes
paginationNo
observationYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, so the security profile is known. "Sends nothing" adds real reassurance that this discovery call cannot dispatch a message, a non-obvious property for a messaging tool. It does not mention pagination or behavior for accounts with zero messageable groups, keeping it short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences: what it returns, how to use the result, and a safety note. The core purpose is front-loaded and every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and the usage routing to sibling tools is fully covered. Only edge-case behavior (invalid alias, empty group list) is left implicit, which is minor for a one-parameter read tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single account_alias parameter is fully documented with format constraints and a pointer to list_accounts. The description adds no parameter-level detail beyond the schema, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb and resource: "List the recipient groups this login can message and whether each can be looked up." It also scopes to the current login, which distinguishes it from get_recipients/get_recipient_choices that operate on the groups themselves.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: pass a group's reference to get_recipients, and on legacy accounts to get_recipient_choices. Both alternatives and the condition that selects between them are stated, leaving nothing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_school_year_archiveSchool year archiveA
Read-only

List earlier school years with their marks and behaviour, then achievements. Cells keep Librus's exact text; a year's year_end mark may differ from that year's annual grade. Each page rereads the archive.

NameRequiredDescriptionDefault
limitNoMaximum items in this page.
cursorNonext_cursor from the previous page; omit for the first page.
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
itemsYes
identityYes
paginationYes
observationYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint and openWorldHint annotations, the description discloses meaningful behavior: cells preserve Librus's exact text, year_end marks may differ from annual grades, and each page rereads the archive. That last point is especially useful context about pagination consistency, though return-shape details are left to the output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tightly packed sentences with no filler. The core purpose is front-loaded, and the following sentences add distinct, useful clarifications about raw text, mark discrepancies, and pagination behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 100% schema coverage, an output schema, and safety annotations, the definition is largely complete. The main remaining ambiguity is exactly which years count as 'earlier' and whether any filtering or ordering applies, but the essential invocation context is present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so account_alias, cursor, and limit are already well documented in the schema. The description only indirectly references pagination via 'Each page rereads the archive' and does not add parameter-level semantics beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'List earlier school years with their marks and behaviour, then achievements.' This clearly identifies the archival/historical scope and distinguishes it from current-grade tools, though it does not explicitly name a sibling alternative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'earlier school years' implies this is for historical archive data rather than current grades, but there is no explicit when-to-use guidance, no stated exclusions, and no named alternative such as get_final_grades or get_grades.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_student_informationStudent informationA
Read-only

Get the profile of the student a login represents: name, class, register number, tutor, school and lucky number. Each login is an independent parent or student account.

NameRequiredDescriptionDefault
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
dataYes
observationYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, so safety is covered. The description adds genuinely useful context: each login is an independent parent or student account, explaining why the tool returns a single profile rather than a roster and why data isn't shared across logins.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences: the first front-loads purpose and returned fields, the second supplies the account-model context. No filler or restatement of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values needn't be explained, and the single parameter is fully documented. The one gap is that the description omits error behavior for aliases that aren't student logins, which matters for a parent-account-oriented tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the alias parameter is fully described including its provenance (from list_accounts), so baseline 3 applies. The description adds that the alias identifies a login representing a student or parent, but no format guidance beyond the schema pattern.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb (get) and resource (student profile) with an enumerated field list (name, class, register number, tutor, school, lucky number). It also clarifies the resource is the login's own student, distinguishing it from sibling grade/attendance tools that assume a student context.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The second sentence implies you must know which account a login represents, and the schema points to list_accounts as the source of account_alias. However, it never explicitly says when to call this versus get_grades or other per-student tools that also need identity context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_subject_frequencyAttendance by subjectA
Read-only

Get attendance counts and ratios per subject, optionally within a window of up to 371 days. For overall totals use get_attendance_frequency.

NameRequiredDescriptionDefault
date_toNoLast day, YYYY-MM-DD, inclusive; at most 370 days after the first.
date_fromNoFirst day, YYYY-MM-DD, inclusive.
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
itemsYes
date_toYes
identityYes
date_fromYes
paginationNo
observationYes

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, so the safety profile is covered. The description adds the optional date window and its 371-day cap, but says nothing about permissions on account_alias, the default range when dates are omitted, or result ordering/size — modest added value against a lower bar.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no filler, with the core purpose front-loaded and the sibling routing placed last where it belongs as a fallback.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation, and parameters are fully described in the schema. Minor gap: it doesn't say what range is used when date_from/date_to are both omitted, which matters for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all three parameters are already documented in the schema; the description only re-states that the window is optional. Baseline 3 is appropriate since the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb and resource plus the unit of aggregation: 'attendance counts and ratios per subject.' It also explicitly contrasts itself with get_attendance_frequency ('For overall totals use...'), so an agent can distinguish it from siblings without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit routing rule: use get_attendance_frequency for overall totals, this tool for per-subject breakdowns. It doesn't address the other nearby siblings (get_attendance, get_attendance_window, get_attendance_detail), so the guidance is clear but not exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_teacher_subjectsTeacher subjectsA
Read-only

Modern accounts: list teachers with the subjects they teach. The IDs are informational and cannot address a message; use get_recipients for that.

NameRequiredDescriptionDefault
limitNoMaximum items in this page.
cursorNonext_cursor from the previous page; omit for the first page.
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
itemsYes
identityYes
paginationYes
observationYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, so safety is covered. The description adds genuinely non-obvious behavior: the returned IDs are informational only and cannot be used to address a message — a caveat that prevents a real downstream error. It says nothing about paging, but the cursor/limit params document that.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, purpose first, misuse caveat second — nothing wasted and nothing buried. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return shape need not be described, and annotations cover the read-only profile. The description supplies the purpose plus the key ID-usage caveat; only the 'modern accounts' qualifier is left unexplained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so account_alias, limit and cursor are already fully documented. The description adds no parameter-level meaning beyond the schema; baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: list teachers together with the subjects they teach, scoped to 'modern accounts'. It names get_recipients as the contrasting tool, so an agent can distinguish it from at least one sibling, though the difference from get_recipient_choices/get_recipient_types is left implicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly rules out a tempting misuse ('the IDs cannot address a message') and routes that need to get_recipients. It gives a clear exclusion plus an alternative, but doesn't say when to prefer this over the other recipient-listing siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_timetableTimetableA

Get the lesson plan for one week, with substitutions and cancellations, in school local time. Selecting the week also changes the week this login's Librus session remembers.

NameRequiredDescriptionDefault
mondayYesMonday of the week, YYYY-MM-DD.
account_aliasYesLogin alias from list_accounts.

Output Schema

NameRequiredDescription
itemsYes
mondayYes
identityYes
timezoneNo
paginationNo
observationYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses a non-obvious side effect: selecting the week mutates the remembered week in the Librus session, which explains why readOnlyHint is false for a seemingly read-only tool. That is exactly the kind of context annotations cannot convey, though it could go further on the durability or risk of that session change.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with zero filler; the core purpose is front-loaded and the side-effect caveat follows immediately. Every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and full schema coverage, the description need not explain return values, and it covers the main behavioral surprise (session week change). Minor gap: no mention of ordering/which week is default or how ambiguous weeks are handled, but nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so both parameters (monday, account_alias) are already documented in the schema. The description reinforces the temporal semantics ('one week', 'school local time') but adds no format or edge-case detail beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get the lesson plan for one week') and adds scope detail: substitutions, cancellations, and school local time. It is clear what the tool returns, but it does not explicitly distinguish itself from nearby siblings like get_agenda or get_completed_lessons.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: the agent can infer 'use this for a single week's lessons' from the week parameter, but there is no explicit when-to-use versus get_agenda/get_homework guidance and no prerequisites mentioned (e.g., that account_alias comes from list_accounts).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_accountsList accountsA
Read-only

List the configured login aliases. Call this first: every other tool takes one as account_alias. Offline.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
itemsYes

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover readOnly and closed-world, and an output schema exists, so the description is not burdened with return details. 'Offline' adds behavior the annotations don't convey (no live/network dependency), and the ordering dependency is a real operational constraint. Slightly terse, but adds genuine context beyond structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core action, then the ordering rule, then the environment note. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter read tool with an output schema and readOnly annotations, nothing an agent needs is missing: what it returns, when to call it, and that it works offline are all covered.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters sets the baseline at 4. The description goes slightly beyond by explaining that the returned value is consumed as 'account_alias' elsewhere, which clarifies the parameter's meaning in sibling tools.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List the configured login aliases'), which is distinct from every sibling tool that fetches actual data. An agent immediately knows this produces aliases, not content.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Call this first' gives explicit ordering, and the clause 'every other tool takes one as account_alias' explains why, so the agent knows this is a prerequisite step. Both when to use and how it relates to alternatives are stated.

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.

  1. 30 tool updatesv2.3.1
    • Changedacknowledge_notifications5 fields changed
      • changedInput schema / $defs / BatchContextInput / properties / alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / context / description
        Added value: +"The batch's context or its identifier."
      • addedInput schema / properties / receipt / description
        Added value: +"The batch's receipt."
    • Changeddownload_attachment6 fields changed
      • changedInput schema / $defs / MessageReferenceInput / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / attachment_ref / description
        Added value: +"message: the message_ref you opened; identifier, archived: from the attachment."
      • addedInput schema / properties / filename / description
        Added value: +"Name to save as, e.g. its filename."
      • addedInput schema / properties / max_bytes / description
        Added value: +"Refuse larger files."
    • Changedget_agenda5 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / month / description
        Added value: +"Month, 1 to 12."
      • addedInput schema / properties / year / description
        Added value: +"Calendar year."
      • changedOutput schema / $defs / SchoolReferenceInput / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
    • Changedget_agenda_detail4 fields changed
      • changedInput schema / $defs / SchoolReferenceInput / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / event_ref / description
        Added value: +"An event's reference from get_agenda, unchanged."
    • Changedget_announcements2 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
    • Changedget_attendance4 fields changed
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / cursor / description
        Added value: +"next_cursor from the previous page; omit for the first page."
      • addedInput schema / properties / limit / description
        Added value: +"Maximum items in this page."
      • addedInput schema / properties / scope / description
        Added value: +"Librus view: all, or its week or last_login recent-changes filter; not dates."
    • Changedget_attendance_detail3 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / attendance_id / description
        Added value: +"A record's detail_id, or a lesson's attendance_detail_id."
    • Changedget_attendance_frequency2 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
    • Changedget_attendance_window7 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / cursor / description
        Added value: +"next_cursor from the previous page; omit for the first page."
      • addedInput schema / properties / date_from / description
        Added value: +"First day, YYYY-MM-DD, inclusive."
      • addedInput schema / properties / date_to / description
        Added value: +"Last day, YYYY-MM-DD, inclusive; at most 370 days after the first."
      • addedInput schema / properties / limit / description
        Added value: +"Maximum items in this page."
      • addedInput schema / properties / scope / description
        Added value: +"Librus view: all, or its week or last_login recent-changes filter; not dates."
    • Changedget_class_free_days4 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / cursor / description
        Added value: +"next_cursor from the previous page; omit for the first page."
      • addedInput schema / properties / limit / description
        Added value: +"Maximum items in this page."
    • Changedget_completed_lessons9 fields changed
      • changedInput schema / $defs / LessonsCursorInput / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / cursor / description
        Added value: +"next_cursor from the previous page; omit for the first page."
      • addedInput schema / properties / date_from / description
        Added value: +"First day, YYYY-MM-DD, inclusive."
      • addedInput schema / properties / date_to / description
        Added value: +"Last day, YYYY-MM-DD, inclusive; at most 370 days after the first."
      • addedInput schema / properties / limit / description
        Added value: +"Maximum items in this page."
      • addedInput schema / properties / max_pages / description
        Added value: +"Maximum Librus pages fetched by this call."
      • changedOutput schema / $defs / LessonsCursorInput / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
    • Changedget_final_grades1 field changed
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
    • Changedget_grades4 fields changed
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / cursor / description
        Added value: +"next_cursor from the previous page; omit for the first page."
      • addedInput schema / properties / limit / description
        Added value: +"Maximum items in this page."
      • addedInput schema / properties / scope / description
        Added value: +"Librus view: all, or its week or last_login recent-changes filter; not dates."
    • Changedget_grades_window7 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / cursor / description
        Added value: +"next_cursor from the previous page; omit for the first page."
      • addedInput schema / properties / date_from / description
        Added value: +"First day, YYYY-MM-DD, inclusive."
      • addedInput schema / properties / date_to / description
        Added value: +"Last day, YYYY-MM-DD, inclusive; at most 370 days after the first."
      • addedInput schema / properties / limit / description
        Added value: +"Maximum items in this page."
      • addedInput schema / properties / scope / description
        Added value: +"Librus view: all, or its week or last_login recent-changes filter; not dates."
    • Changedget_homework5 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / date_from / description
        Added value: +"First day, YYYY-MM-DD, inclusive."
      • addedInput schema / properties / date_to / description
        Added value: +"Last day, YYYY-MM-DD, inclusive; at most 370 days after the first."
      • changedOutput schema / $defs / SchoolReferenceInput / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
    • Changedget_homework_detail4 fields changed
      • changedInput schema / $defs / SchoolReferenceInput / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / homework_ref / description
        Added value: +"An item's reference from get_homework, unchanged."
    • Changedget_message_content5 fields changed
      • changedInput schema / $defs / MessageReferenceInput / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / allow_mark_read / description
        Added value: +"Consent to mark a received message read."
      • addedInput schema / properties / message_ref / description
        Added value: +"A message's reference from get_messages."
    • Changedget_message_correspondents6 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / cursor / description
        Added value: +"next_cursor from the previous page; omit for the first page."
      • addedInput schema / properties / folder / description
        Added value: +"received or sent mail."
      • addedInput schema / properties / limit / description
        Added value: +"Maximum items in this page."
      • changedOutput schema / $defs / CorrespondentReferenceInput / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
    • Changedget_message_unread_counts2 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
    • Changedget_messages17 fields changed
      • changedInput schema / $defs / CorrespondentReferenceInput / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • changedInput schema / $defs / LegacyCursor / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • changedInput schema / $defs / ModernCursor / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / archived / description
        Added value: +"Modern only: list earlier years' archive."
      • addedInput schema / properties / correspondent / description
        Added value: +"Modern only: a reference from get_message_correspondents."
      • addedInput schema / properties / cursor / description
        Added value: +"next_cursor from the previous page; omit for the first page."
      • addedInput schema / properties / folder / description
        Added value: +"received or sent mail."
      • addedInput schema / properties / limit / description
        Added value: +"Maximum items in this page."
      • addedInput schema / properties / max_pages / description
        Added value: +"Maximum Librus pages fetched by this call."
      • addedInput schema / properties / page_size / description
        Added value: +"Messages per Librus page; legacy accepts only 50."
      • addedInput schema / properties / unread_only / description
        Added value: +"Modern only: unread received mail only."
      • changedOutput schema / $defs / CorrespondentReferenceInput / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • changedOutput schema / $defs / LegacyCursor / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • changedOutput schema / $defs / MessageReferenceInput / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • changedOutput schema / $defs / ModernCursor / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
    • Changedget_new_notifications4 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / allow_consume_events / description
        Added value: +"Consent to fetch read-once calendar news."
      • addedInput schema / properties / categories / description
        Added value: +"Which kinds of news to check."
    • Changedget_notification_status2 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
    • Changedget_recipient_choices4 fields changed
      • changedInput schema / $defs / RecipientTypeInput / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / recipient_type / description
        Added value: +"A group's reference from get_recipient_types."
    • Changedget_recipient_types3 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • changedOutput schema / $defs / RecipientTypeInput / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
    • Changedget_recipients4 fields changed
      • changedInput schema / $defs / RecipientTypeInput / properties / account / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / recipient_type / description
        Added value: +"A group's reference from get_recipient_types."
    • Changedget_school_year_archive4 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / cursor / description
        Added value: +"next_cursor from the previous page; omit for the first page."
      • addedInput schema / properties / limit / description
        Added value: +"Maximum items in this page."
    • Changedget_student_information1 field changed
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
    • Changedget_subject_frequency4 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / date_from / description
        Added value: +"First day, YYYY-MM-DD, inclusive."
      • addedInput schema / properties / date_to / description
        Added value: +"Last day, YYYY-MM-DD, inclusive; at most 370 days after the first."
    • Changedget_teacher_subjects4 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / cursor / description
        Added value: +"next_cursor from the previous page; omit for the first page."
      • addedInput schema / properties / limit / description
        Added value: +"Maximum items in this page."
    • Changedget_timetable3 fields changed
      • addedInput schema / properties / account_alias / description
        Added value: +"Login alias from list_accounts."
      • changedInput schema / properties / account_alias / pattern
        Previous value: -"^(?:[^\\s\\x00-\\x1f\\x7f]|[^\\s\\x00-\\x1f\\x7f](?:[^\\s\\x00-\\x1f\\x7f]| )*[^\\s\\x00-\\x1f\\x7f])$"New value: +"^[^\\s\\x00-\\x1f\\x7f](?: *[^\\s\\x00-\\x1f\\x7f])*$"
      • addedInput schema / properties / monday / description
        Added value: +"Monday of the week, YYYY-MM-DD."
  2. 31 tool updates
    • First observedacknowledge_notifications
    • First observeddownload_attachment
    • First observedget_agenda
    • First observedget_agenda_detail
    • First observedget_announcements
    • First observedget_attendance
    • First observedget_attendance_detail
    • First observedget_attendance_frequency
    • First observedget_attendance_window
    • First observedget_class_free_days
    • First observedget_completed_lessons
    • First observedget_final_grades
    • First observedget_grades
    • First observedget_grades_window
    • First observedget_homework
    • First observedget_homework_detail
    • First observedget_message_content
    • First observedget_message_correspondents
    • First observedget_message_unread_counts
    • First observedget_messages
    • First observedget_new_notifications
    • First observedget_notification_status
    • First observedget_recipient_choices
    • First observedget_recipient_types
    • First observedget_recipients
    • First observedget_school_year_archive
    • First observedget_student_information
    • First observedget_subject_frequency
    • First observedget_teacher_subjects
    • First observedget_timetable
    • First observedlist_accounts

TDQS

A3.7/5.0

Scored across 31 tools

Disambiguation4/5

Most tools target distinct resource/action combinations, and paired tools such as get_grades/get_grades_window, get_attendance/get_attendance_detail, and get_messages/get_message_content are explicitly differentiated. However, the large surface includes subtle overlaps in notification and message-recipient tools such as get_new_notifications vs get_message_unread_counts and get_recipients vs get_message_correspondents, relying on description text rather than obvious naming.

Naming Consistency5/5

All tool names use snake_case and start with a clear verb (list_, get_, download_, acknowledge_), producing a predictable verb_noun pattern. The semantic split between get_ for single/aggregate results and list_ for collections is consistent and readable.

Tool Count2/5

At 31 tools, the server is above the rubric's heavy threshold, and the surface is inflated by window/detail/frequency variants plus legacy/modern recipient paths. The broad school-register domain justifies many operations, but several tools could be consolidated into fewer parameterized operations.

Completeness3/5

The surface broadly covers read access: accounts, grades, attendance, timetable, calendar, homework, archive, messages, attachments and notifications. However, recipient lookup tools are explicitly framed as preparing to address a message, yet no send_message tool exists, leaving a notable lifecycle gap; message and announcement read-state management is also only partially exposed.

Maintenance

ActivityActive
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables accessing IServ school platform features such as timetable, exercises, messenger, and more via natural language, without exposing credentials to agents.
    1
    MIT
  • F
    license
    A
    quality
    C
    maintenance
    Enables read-only access to a Librus Portal account, letting users list linked Synergia accounts and retrieve grades, attendance, timetable, homework, notices, and school information.
    3
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Connects AI agents to the École Directe API to access grades, homework, timetables, school life, messages, and documents.
    -
  • A
    license
    A
    quality
    A
    maintenance
    Enables AI agents to query and manage EduPage school accounts, including timetables, grades, homework, meals, messages, multi-school discovery, role-aware student switching, and 2FA login.
    31
    100 PyPI
    4
    MIT