ZHAW Moodle MCP Server
Provides tools for working with ZHAW Moodle: list courses, retrieve course structure and content, find and download learning resources, sync local copies, and see deadlines, assignments, announcements, and recent changes.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ZHAW Moodle MCP ServerWhat do I need to submit this week?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ZHAW Moodle MCP Server
MCP server that lets Claude (Claude Desktop, Claude Code or any other MCP client) work with
your ZHAW Moodle (moodle.zhaw.ch): list courses, find and download learning materials, keep
a local copy in sync, and see deadlines, assignments, announcements and what is new.
You log in yourself with SWITCH edu-ID in a normal browser window. The server never sees or stores your password; it reuses the authenticated browser session, and everything stays on your computer.
Unofficial student project, not affiliated with or endorsed by ZHAW. Use it in line with the ZHAW ICT usage rules; downloaded course material is for your personal study only.
Requirements and roadmap: REQUIREMENTS.md · Technical findings: docs/spike-findings.md
Quick start
You need Claude Desktop or Claude Code and a Chromium-based browser (Chrome, Edge, Brave or Vivaldi — on Windows Edge is always there).
1. Install uv (runs the server and brings its own Python):
Windows (PowerShell):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"macOS / Linux:
curl -LsSf https://astral.sh/uv/install.sh | sh
2. Add the server to Claude
Claude Desktop: Settings → Developer → Edit Config, paste this into claude_desktop_config.json
(merge it if the file already has mcpServers) and restart Claude Desktop completely:
{
"mcpServers": {
"zhaw-moodle": {
"command": "uvx",
"args": ["zhaw-moodle-mcp@latest"]
}
}
}Claude Code:
claude mcp add zhaw-moodle -- uvx zhaw-moodle-mcp@latest3. Use it: ask "Which Moodle courses do I have?". The first time, a browser window opens —
log in with SWITCH edu-ID there and the window closes by itself.
Files are downloaded to the ZHAW folder in your home directory.
More ideas: "Sync all my courses", "What do I need to submit this week?", "What is new in Moodle since Monday?", "Summarise the slides of lecture 1 in Software Engineering".
Troubleshooting:
Claude Desktop can't find
uvx: quit Claude Desktop completely (also from the tray) and start it again. If that doesn't help, use the full path ascommand, e.g.C:/Users/<you>/.local/bin/uvx.exe.No browser opens: see
[browser]in Configuration.Updates are installed automatically the next time Claude starts (
@latest).
Related MCP server: mydy-lms
Status: v0.3
Tool | Purpose |
| Is there a valid Moodle session? |
| Open the browser for SWITCH edu-ID login (other tools do this automatically when needed) |
| End the session and delete local cookies/browser profile |
| Courses, marked |
| Sections, subsections and all activities of a course, incl. the text of text blocks |
| Text of a Moodle page or text block as Markdown, with its links |
| Files (pdf, powerpoint, word, …), folders (incl. their files), links, pages |
| Download a file, a whole folder or the files linked in a page/text block, returns local paths |
| Download new/changed files, report renamed/removed ones ( |
| Sync all current courses, per-course summary |
| Find courses, sections, materials, assignments, quizzes by name (umlaut/typo tolerant); falls back to Moodle full-text search |
| Open to-dos with deadlines (assignments, quizzes) across all courses |
| Assignments with dates, submission and grading status, description |
| Lecturer announcements with message text |
| New/updated materials, announcements and deadlines since a date ( |
Development setup
Requires uv and a Chromium-based browser (Chrome, Edge, Brave or Vivaldi). The login opens in your default browser if it is one of these, otherwise in another installed one (Firefox and Safari can't be automated; on Windows Edge is always available).
uv syncLog in once (opens the browser, finishes automatically after the SWITCH edu-ID login):
uv run zhaw-moodle-mcp loginAdd the server to Claude Code:
claude mcp add zhaw-moodle -- uv --directory C:/path/to/zhaw-moodle-mcp run zhaw-moodle-mcpAlternatively the repository contains a .mcp.json, so Claude Code opened in this folder offers the
server automatically.
Study assistant (Claude Code)
.claude/agents/study-assistant.md is a Claude Code subagent that uses this server as a tutor:
explaining lectures, guiding exercises without handing out solutions, exam preparation,
flashcards and deadline planning. It is available automatically when Claude Code runs in this
folder; to use it everywhere, copy the file to ~/.claude/agents/.
CLI
With the PyPI package, prefix the commands with uvx (e.g. uvx zhaw-moodle-mcp login).
zhaw-moodle-mcp run the MCP server (stdio); also: python -m zhaw_moodle_mcp
zhaw-moodle-mcp login log in via browser
zhaw-moodle-mcp status check the stored session
zhaw-moodle-mcp logout end session, delete local auth data
zhaw-moodle-mcp config-path where the config file is expectedHow it works
SWITCH edu-ID login in a Chromium-based browser (Playwright, visible window)
↓ storage_state.json (cookies)
httpx client ── Moodle AJAX service (/lib/ajax/service.php, session + sesskey):
│ courses, course structure, calendar to-dos, module updates, forum posts
── HTML pages: file types, folder contents, assignment status, announcement lists,
│ Moodle full-text search
── pluginfile.php for downloads, HEAD + ETag for change detection
↓
SQLite metadata (course index for search/changes, known files, ETags, local paths, sync history)The browser is used only for login. A persistent browser profile keeps the edu-ID "remember this browser" state, so re-login usually needs no MFA.
If the session expires during a request, the login window opens and the request is retried.
Files are stored as
<download_directory>/<course>/<NN section>/<subsection>/<folder>/<file>.Sync never deletes local files; files removed from Moodle are only reported.
Search uses a local index of names that is refreshed from Moodle when older than an hour. Files inside folders become searchable once
moodle_list_resourcesor a sync has seen them.Recent changes can only distinguish new from updated for courses the server already knew before the requested date; otherwise changes are reported as
changed.Reading assignments or pages opens them in Moodle, which is logged as a view (and may mark a page as completed if the course tracks page views).
Files linked inside pages or text blocks get a
resource_id(<activity id>/<file>) formoodle_download_resource; the id of the page/block itself downloads all its linked files into<course>/<section>/<page name>/. These files are not part ofmoodle_sync_course.
Configuration
Optional TOML file (see zhaw-moodle-mcp config-path, or set ZHAW_MOODLE_MCP_CONFIG).
All keys are optional; defaults shown:
[moodle]
base_url = "https://moodle.zhaw.ch"
download_directory = "~/ZHAW"
request_timeout = 60
max_concurrent_requests = 4
timezone = "Europe/Zurich" # how dates shown by Moodle are interpreted
[browser]
name = "auto" # "auto", "chrome", "msedge", "brave", "vivaldi" or "chromium"
# ("chromium" needs: uvx --from zhaw-moodle-mcp playwright install chromium)
# executable_path = "C:/path/to/browser.exe" # any other Chromium-based browser, overrides name
login_timeout = 300 # seconds to wait for the user to finish login
auto_login = true # open the login window automatically when the session expired
# profile_directory = "<data dir>/browser-profile" # one subfolder per browser
[session]
# storage_state = "<data dir>/auth/storage_state.json"
validation_ttl = 120 # seconds a successful session check is trusted
[sync]
# database = "<data dir>/moodle.db"
[search]
index_max_age_minutes = 60 # re-read current courses before searching if the index is older<data dir> is %LOCALAPPDATA%\zhaw-moodle-mcp on Windows, ~/Library/Application Support/zhaw-moodle-mcp
on macOS and ~/.local/share/zhaw-moodle-mcp on Linux.
Security
No passwords, API tokens or manually copied cookies.
Session data lives outside the repository and is restricted to the current user (
icaclson Windows,chmod 600/700elsewhere).Tool results and error messages never contain cookies or session keys; logs go to stderr with cookies, sesskeys and SSO parameters redacted.
moodle_logoutremoves the stored session and the browser profile.
Development
uv run pytest
uv run ruff check src testsTests run against an in-memory fake Moodle (tests/fake_moodle.py), no network needed.
spike/ contains the original exploration scripts; their output (spike/output/) is git-ignored
because it contains personal Moodle data.
Available Tools
15 toolsmoodle_auth_statusARead-onlyIdempotent
Check whether a valid ZHAW Moodle session exists. Never returns credentials.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| state | Yes | |
| message | Yes | |
| moodle_url | Yes | |
| authenticated | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and openWorldHint, so the safety profile is covered. The description adds valuable behavioral context by stating 'Never returns credentials,' which is a meaningful guarantee beyond what annotations provide, especially for an authentication-related tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two short sentences with zero filler. The primary function is stated first, and the security-relevant caveat about credentials is a meaningful second sentence that earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only status-check tool with an output schema and rich annotations, the description is fully adequate. An agent has everything it needs to select and invoke this tool correctly without additional detail.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero parameters and 100% schema coverage, so there are no parameter semantics for the description to explain. The baseline of 4 applies because the schema fully handles an empty parameter set and the description has nothing to add.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Check') and a precise resource ('valid ZHAW Moodle session'), making the tool's purpose immediately clear. It also distinguishes itself from moodle_login and moodle_logout by focusing on session status rather than session creation or destruction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool should be used when an agent needs to verify session validity before acting, but it does not explicitly state when to use it versus alternatives like moodle_login or moodle_logout, nor does it mention any exclusions. The usage context is reasonably clear from the purpose, but no explicit routing guidance is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
moodle_download_resourceAIdempotent
Download a file, all files of a folder, or files linked in a page/text block, and return the local paths.
By default files go to the managed directory <download_directory>/<course>/<section>/,
which moodle_sync_course also uses.
Args:
resource_id: id from moodle_list_resources ("<cmid>" or "<folder cmid>/<path>"),
or a file link's resource_id from moodle_get_content ("<page/label id>/<file>");
the id of a page or text block downloads all files linked in it
destination: optional target directory; relative paths are resolved
against the configured download directory
overwrite: replace an existing local file (otherwise it is left as is)
| Name | Required | Description | Default |
|---|---|---|---|
| overwrite | No | ||
| destination | No | ||
| resource_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| files | Yes | |
| failed | No | Linked files that could not be loaded |
| resource_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds valuable behavioral details beyond the annotations: it explains the default destination path, the overwrite behavior ('replace an existing local file (otherwise it is left as is)'), and that it returns local paths. It also clarifies the resource_id format. The annotations already indicate non-read-only (readOnlyHint=false) and non-destructive (destructiveHint=false), and the description aligns without contradiction. It doesn't discuss permissions or error handling, but the core behaviors are transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a clear first sentence stating the purpose, followed by a brief note on default behavior, then a concise Args section. It front-loads the key information and avoids redundancy. Every sentence earns its place, and the format is easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (3 parameters, one required) and the presence of an output schema (which likely documents return values), the description covers the essential operational details: input sources, default destination, overwrite behavior, and parameter formats. It does not cover error conditions or prerequisites (like authentication), but those may be handled by sibling tools or the output schema. Overall, it is sufficiently complete for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. The Args section thoroughly explains each parameter: resource_id (with specific formats from other tools), destination (optional, relative paths resolved against the configured download directory), and overwrite (boolean behavior). This goes far beyond the bare schema, providing essential meaning and context for correct usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a precise action: 'Download a file, all files of a folder, or files linked in a page/text block, and return the local paths.' It names the resource types and the output, and it clearly distinguishes from sibling tools like moodle_get_content (which likely retrieves content without downloading) and moodle_sync_course (which is a broader sync operation). This is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides contextual guidance by specifying where resource_ids come from ('id from moodle_list_resources...' or 'file link's resource_id from moodle_get_content') and notes that moodle_sync_course uses the same download directory. However, it does not explicitly state when to use this tool over alternatives (e.g., 'use this instead of moodle_get_content when you need local files') or provide exclusion criteria. The usage is implied but not fully spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
moodle_get_announcementsARead-onlyIdempotent
Recent announcements ("Ankündigungen") posted by lecturers, newest first, with the message text of the most recent ones.
Args:
course_id: restrict to one course (default: all current courses)
since: only announcements newer than this: ISO date/datetime (2026-09-14) or relative (7d, 12h, 2w)
limit: maximum number of announcements
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| since | No | ||
| course_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| announcements | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and openWorldHint=true, covering safety and idempotency. The description adds behavioral specifics: announcements are sorted newest first, and the most recent ones include message text. It also clarifies the 'since' parameter accepts ISO dates or relative formats. This adds value beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is efficient and front-loaded with the core purpose. The Args section is logically structured and each parameter is explained in a single line. While slightly verbose with the example format, it avoids redundancy and is not overly long. The content earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that an output schema exists (as indicated) and annotations cover safety, the description covers the essential aspects: what the tool returns (announcements with message text), ordering, and parameter semantics. It does not mention error handling or edge cases, but for a read-only retrieval tool this is acceptable. The description is complete enough for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description fully carries the burden of explaining parameters. It explicitly defines course_id (restrict to one course, default all current courses), since (only newer than, with ISO or relative examples), and limit (maximum number). This is thorough and compensates completely for the lack of schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves recent announcements posted by lecturers, ordered newest first, and includes the message text of the most recent ones. This is a specific verb+resource with clear scope and distinguishes it from sibling tools like moodle_get_recent_changes (which likely covers broader changes) and moodle_get_content (generic content retrieval). The mention of 'Ankündigungen' adds context for the Moodle domain.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no explicit guidance on when to use this tool versus alternatives, nor any exclusions. It lists parameters but does not state typical use cases, prerequisites, or contrast with similar tools like moodle_get_recent_changes or moodle_get_deadlines. An agent would need to infer usage from the name and purpose.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
moodle_get_contentARead-onlyIdempotent
Read the text of a Moodle page ("Textseite") or text block ("Textfeld"/label) as Markdown, with the links it contains. Such texts often hold instructions, rules for assignments and exams, or reading lists. Opening a page counts as a view in Moodle.
Args:
activity_id: id (cmid) of a page or label from moodle_get_course or moodle_search
| Name | Required | Description | Default |
|---|---|---|---|
| activity_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| url | No | |
| name | Yes | |
| note | No | |
| text | Yes | Content as Markdown |
| links | No | |
| module | Yes | page or label |
| section | Yes | |
| course_id | Yes | |
| accessible | No | |
| course_name | Yes | |
| modified_at | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already convey readOnly, idempotent, and openWorld behavior. The description adds genuinely useful behavioral context beyond those annotations: opening the page counts as a view in Moodle, and the output is Markdown containing links. This is valuable and not contradictory.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core purpose, followed by relevant use context and parameter guidance. Every sentence earns its place; there is no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has only one parameter, an output schema, and safety-relevant annotations, the description covers the essential workflow, input provenance, and a subtle behavioral caveat. Nothing critical is missing for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema only exposes an integer named activity_id. The description adds essential meaning: it is a cmid of a page or label, and it should be sourced from moodle_get_course or moodle_search. With 0% schema coverage, this fully compensates.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific action ('Read the text'), a concrete resource type ('Moodle page or text block'), and the output format ('as Markdown, with the links it contains'). This clearly distinguishes it from list/download/sync sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear usage context by noting these texts often contain instructions, rules, and reading lists, and it tells the caller where to obtain the correct activity_id ('from moodle_get_course or moodle_search'). It does not explicitly contrast with moodle_list_resources or moodle_download_resource, so it falls just short of full alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
moodle_get_courseARead-onlyIdempotent
Get the structure of a course: sections, nested subsections and all activities/materials (files, folders, links, pages, quizzes, assignments, ...). Text blocks (labels) include their text.
Args:
course_id: course id from moodle_list_courses
| Name | Required | Description | Default |
|---|---|---|---|
| course_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| course | Yes | |
| sections | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, covering safety and idempotency. The description adds behavioral detail by specifying that text blocks (labels) include their text and enumerating the activity types included. It does not contradict annotations. It also does not mention pagination or size limits, but the output schema likely 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded with the primary purpose. It uses a list to enumerate included content and then explains the parameter. Every sentence adds value; there is no fluff. Slightly longer than necessary but acceptable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that an output schema exists, the description need not detail return values. It covers the tool's function, parameter semantics, and includes a prerequisite hint. It does not mention potential errors or rate limits, but for a read-only getter with annotations covering safety, it is sufficiently complete for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides only the parameter name and type with no description (0% coverage). The description compensates by explaining that course_id is a 'course id from moodle_list_courses', giving the agent a source for the value. This is meaningful guidance beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: to retrieve the structure of a course including sections, subsections, and all activity types. It differentiates from siblings like moodle_list_courses (which lists courses) and moodle_get_content (which likely retrieves specific content). The verb 'Get' and specific resource 'course structure' make it unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for exploring a course's structure, and mentions that course_id comes from moodle_list_courses, giving a prerequisite. However, it does not explicitly state when to prefer this over alternative tools like moodle_get_content or moodle_sync_course, nor does it provide exclusions. The usage is implied rather than explicitly guided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
moodle_get_deadlinesARead-onlyIdempotent
Open to-dos with deadlines across all courses (assignment due dates, quiz closing times, ...), sorted by date. Answers "What do I need to submit this week?". Activities already completed are not listed.
Args:
days_ahead: how far to look ahead (days)
course_id: restrict to one course
include_overdue: also list overdue to-dos from the last 30 days
| Name | Required | Description | Default |
|---|---|---|---|
| course_id | No | ||
| days_ahead | No | ||
| include_overdue | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| now | Yes | |
| note | No | |
| until | Yes | |
| deadlines | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only, idempotent, and open-world behavior, so the description adds valuable behavioral details: results are sorted by date, completed activities are omitted, and overdue items are drawn from the last 30 days when enabled. This goes beyond what annotations provide without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: a one-sentence purpose statement, a clarifying example query, a succinct filtering note, and a clean parameter list. Every sentence earns its place and there is no redundant restatement of the tool name or schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple, read-only tool with three optional parameters and an output schema, the description covers scope, filtering behavior, sorting, and the overdue window. Nothing essential is missing to help an agent select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description fully compensates with an Args block explaining all three parameters in plain language: days_ahead, course_id, and include_overdue. Each parameter's meaning is clear and directly usable by an agent.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns open to-dos with deadlines across all courses, sorted by date, with concrete examples like assignment due dates and quiz closing times. It also frames the purpose with a natural-language question, which distinguishes it from sibling tools like moodle_list_assignments or moodle_get_recent_changes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent when to use the tool by tying it to the query 'What do I need to submit this week?' and clarifies that completed activities are excluded. It does not explicitly discuss when not to use it or alternatives, but the usage context is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
moodle_get_recent_changesARead-onlyIdempotent
What changed in Moodle since a point in time: new or updated materials and activities, new announcements, and new or changed deadlines, grouped by course. Answers "What is new in Moodle since Monday?".
Args:
since: ISO date/datetime (2026-09-14, 2026-09-14T08:00) or relative (7d, 12h, 2w)
course_id: restrict to one course (default: all current courses)
| Name | Required | Description | Default |
|---|---|---|---|
| since | No | 7d | |
| course_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| since | Yes | |
| until | Yes | |
| courses | Yes | |
| unchanged_courses | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, and idempotentHint=true, covering safety and idempotency. The description adds the scope of changes (materials, activities, announcements, deadlines) and grouping by course, but doesn't detail output format or limits. Since an output schema exists, this is adequate but not rich; the description adds some value beyond annotations but not extensive behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short paragraphs: the first front-loads the purpose with a clear question, the second lists parameters concisely. No filler; every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With only 2 optional params and an output schema present, the description covers the main use case and parameter semantics. It doesn't mention pagination, limits, or performance implications, but for a read-only aggregate query this is acceptable given the output schema covers return values. Slightly incomplete for edge cases, hence a 4.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It explains 'since' with ISO formats and relative strings (7d, 12h, 2w) and clarifies 'course_id' restricts to one course with a default of all current courses. This is helpful and goes beyond the schema's type/default, though it could mention timezone handling or validation edge cases.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('What changed') and resource ('in Moodle'), enumerating concrete change types (materials, activities, announcements, deadlines) and grouping by course. It clearly answers the intended question and differentiates itself from siblings like moodle_get_announcements or moodle_get_deadlines by being an aggregate overview.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a concrete use case ('Answers What is new in Moodle since Monday?') and implies it's for a broad overview across course content. However, it doesn't explicitly contrast with alternatives (e.g., 'for announcements only, use moodle_get_announcements'), so it misses explicit when-not guidance, preventing a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
moodle_list_assignmentsARead-onlyIdempotent
Assignments with opening date, deadline, submission and grading status and description. Without course_id all current courses are included (one request per assignment).
Args:
course_id: restrict to one course
| Name | Required | Description | Default |
|---|---|---|---|
| course_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| failed | No | Assignments that could not be read |
| assignments | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, covering safety and result variability. The description adds a useful behavioral detail: 'one request per assignment' when course_id is omitted, which informs the agent about potential multiple API calls. It does not contradict the annotations and provides additional context beyond them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, with two main sentences and a separate Args line. The first sentence front-loads the purpose, and the second explains default behavior. The structure is slightly fragmented but not overly verbose; every sentence contributes meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the key behavior (listing assignments, scope control via course_id, and the multi-request implication). An output schema exists, so return structure need not be described. No critical missing information for a tool of this complexity, though it does not mention error handling or edge cases (e.g., invalid course_id), which are minor.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must fully explain the parameter. It does: 'course_id: restrict to one course' clearly conveys the meaning and effect. For a single optional parameter, this is sufficient and adds value beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the tool lists assignments with specific fields (opening date, deadline, submission, grading status, description). The verb 'list' and resource 'assignments' are clear and distinguish it from siblings like moodle_list_courses or moodle_list_resources.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains the default behavior when course_id is omitted ('all current courses are included') and the effect of providing course_id ('restrict to one course'), giving context for usage. However, it does not explicitly mention when to prefer this tool over alternatives like moodle_get_deadlines or moodle_get_course, so usage guidance is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
moodle_list_coursesARead-onlyIdempotent
List the user's ZHAW Moodle courses.
Args:
status: "active" (current semester, default), "past", "future" or "all"
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | active |
Output Schema
| Name | Required | Description |
|---|---|---|
| courses | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, so no safety disclaimer is needed. The description adds the status-scoping behavior ('active' means current semester and is the default) and the available filters, which is useful but not extensive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
At two short lines, the description is tight and front-loaded, with no filler or repetition of the schema. Every sentence contributes meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the single optional parameter, a default value, and an output schema, the description is nearly sufficient for correct invocation. The main omissions are an explicit note that authentication is required and a pointer to alternative list tools, but these are minor for such a simple read-only operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides the status enum and default but has no descriptions, so the schema description coverage is 0%. The description compensates by clarifying that 'active' means the current semester and is the default; however, 'past', 'future', and 'all' are left to be inferred from their names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'List the user's ZHAW Moodle courses,' giving a concrete verb, resource, and scope. It does not explicitly distinguish itself from sibling tools like moodle_list_resources or moodle_get_course, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to choose this tool over siblings such as moodle_get_course, moodle_list_resources, or moodle_search, and no prerequisites are stated. The status parameter and its default are parameter semantics rather than usage strategy, so the tool offers no when-to-use or when-not-to-use context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
moodle_list_resourcesARead-onlyIdempotent
List learning materials of a course: files (pdf, powerpoint, word, excel, zip, ...), folders, external links and Moodle pages, with their section.
Args:
course_id: course id from moodle_list_courses
include_folder_contents: also list the individual files inside folders
(one extra request per folder)
| Name | Required | Description | Default |
|---|---|---|---|
| course_id | Yes | ||
| include_folder_contents | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| course_id | Yes | |
| resources | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint, openWorldHint, and idempotentHint, so the agent knows the tool is safe and non-mutating. The description adds that listing folder contents requires an extra request per folder, which is useful but doesn't deeply describe other behaviors like performance or error handling. Given annotations cover safety, the description does not need to repeat it, but could add more on side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is succinct and front-loaded with the core purpose. The parameter details are listed in a clear, bullet-like format without redundancy. Every sentence serves a purpose, making it efficient and easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is relatively simple with just two parameters and an output schema present, so the description doesn't need to explain return values. It covers the main functionality and parameter semantics. The only missing piece is explicit guidance on when to use this vs. alternatives, but that's a minor gap given the clear purpose.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 0% description coverage, so parameters are only defined by their types and names. The description clarifies that course_id should come from moodle_list_courses, adding value beyond the schema. For include_folder_contents, it explains the meaning and the cost of an extra request per folder. This is helpful but could be even more detailed on the outcome of setting it to false.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: listing learning materials (files, folders, links, pages) with their section. It specifies the resource types and the context (course). This distinguishes it from siblings like moodle_get_content and moodle_download_resource, which are for retrieval and download, not listing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage: call this when you need an overview of a course's materials, and mentions the optional flag to include folder contents. However, it does not explicitly state when not to use it or name alternatives like moodle_get_content for specific content retrieval, or moodle_download_resource for downloading. The context 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.
moodle_loginAIdempotent
Log in to ZHAW Moodle. Opens a browser window where the USER signs in with SWITCH edu-ID (incl. MFA) themselves; returns once login is detected. Never ask the user for their password. Other tools log in automatically when needed.
Args:
force: open the login browser even if the current session is still valid
| Name | Required | Description | Default |
|---|---|---|---|
| force | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| state | Yes | |
| message | Yes | |
| moodle_url | Yes | |
| authenticated | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the annotations by explaining the browser-window behavior, MFA involvement, return condition ('returns once login is detected'), and the explicit prohibition against asking for the user's password. This gives the agent a clear mental model of the tool's interactive side effects. No contradiction with readOnlyHint false, openWorldHint true, or idempotentHint true.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loaded with the core purpose, and every sentence adds necessary detail. The Args section is clearly formatted and directly explains the only parameter.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an interactive login tool, the description covers the key operational facts: what triggers login, who performs authentication, when to use force, what causes a return, and what the agent must never do. An output schema exists, so return-value details are not needed here.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema only provides a title and default for 'force', but the description's Args section explains it precisely: 'open the login browser even if the current session is still valid'. This fully compensates for the 0% schema description coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and resource: 'Log in to ZHAW Moodle', and clarifies the interaction model with 'Opens a browser window where the USER signs in with SWITCH edu-ID (incl. MFA) themselves'. It clearly distinguishes this from sibling tools by noting that other tools log in automatically when needed.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context: this tool performs interactive user login, the user must sign in themselves, and the agent must never ask for a password. It also conveys that other tools handle their own authentication, which implies this tool is for explicit interactive login rather than routine use, though it does not name specific sibling alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
moodle_logoutADestructiveIdempotent
Log out: end the Moodle session and delete the locally stored browser session and cookies. The next Moodle request will require a new login.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| message | Yes | |
| logged_out | Yes | |
| server_session_invalidated | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as destructive and non-read-only; the description adds meaningful context that the local browser session and cookies are deleted and that the next request requires a new login. This goes beyond the structured annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler. The action and consequences are front-loaded and every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter logout tool with output schema, annotations, and a clear behavior description, an agent has everything needed to invoke it correctly. No important gaps remain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4. There is nothing for the description to add about parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states a specific verb ('Log out') and resource ('Moodle session'), and clarifies what happens ('delete locally stored browser session and cookies'). It clearly distinguishes from siblings like moodle_login and moodle_auth_status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided about when to use logout versus alternatives such as moodle_login or moodle_auth_status. The description implies use when ending a session, but it does not explicitly state context, prerequisites, or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
moodle_searchARead-onlyIdempotent
Search Moodle by name: courses, sections, materials (files, folders, links, pages), assignments, quizzes and files inside folders. Case- and umlaut-insensitive, tolerant to small typos; all words must match (e.g. "OR ZGB", "Übung 3", "Semesterprogramm").
Args:
query: words to look for
course_id: restrict to one course
kinds: restrict result kinds: course, section, module (activities/materials), file (in folders)
source: "index" = local index of names (fast; current courses are refreshed automatically),
"moodle" = Moodle's full-text search (also finds words inside text areas),
"auto" = index first, Moodle full-text search if nothing matches
limit: maximum number of hits
refresh: re-read the courses from Moodle before searching
| Name | Required | Description | Default |
|---|---|---|---|
| kinds | No | ||
| limit | No | ||
| query | Yes | ||
| source | No | auto | |
| refresh | No | ||
| course_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| hits | Yes | |
| note | No | |
| query | Yes | |
| source | Yes | |
| indexed_courses | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the operation read-only, idempotent, and open-world. The description adds meaningful behavioral context: case/umlaut-insensitivity, typo tolerance, the all-words-must-match rule, refresh behavior, and the fallback logic of 'auto'. This goes beyond the annotation-provided safety profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: purpose first, then matching behavior, then a clean Args list. Every sentence earns its place and no irrelevant detail is included.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema, read-only annotations, and six parameters, the description covers matching semantics, source selection, scoping by course and kind, limit, and refresh. It provides everything an agent needs to invoke the tool correctly without requiring further inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema description coverage at 0%, the description fully compensates by explaining all six parameters: query, course_id, kinds, source, limit, and refresh. Each parameter gets a concise, meaningful explanation that the bare schema does not provide.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states a specific verb ('Search') and resource ('Moodle by name') and enumerates the exact kinds of entities covered, plus the special case of files inside folders. This is distinct from sibling list/get tools and conveys exactly what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear context for when to use the tool and, importantly, explains the three source modes ('index', 'moodle', 'auto') and when each is appropriate. It does not explicitly name sibling alternatives or exclusion conditions, but the source-selection guidance is strong enough to guide an agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
moodle_sync_allAIdempotent
Synchronise all active (current semester) courses into the local download directory and return a per-course summary. Same rules as moodle_sync_course.
Args:
dry_run: only report what would change, download nothing
update_changed: re-download files that changed on Moodle
| Name | Required | Description | Default |
|---|---|---|---|
| dry_run | No | ||
| update_changed | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| courses | Yes | |
| dry_run | Yes | |
| download_directory | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare non-read, idempotent, and non-destructive behavior. The description usefully adds that dry_run only reports changes without downloading, that update_changed controls re-download of changed files, and that a per-course summary is returned. The vague 'Same rules as moodle_sync_course' reference prevents 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the main purpose, followed by two brief parameter explanations. The only slight weakness is the cryptic 'Same rules as moodle_sync_course', though it does not add bulk.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists, the return summary does not need detailed explanation. The description covers action, scope, target directory, and flag semantics. The main gap is that 'Same rules as moodle_sync_course' leaves important behavioral details dependent on another tool's description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description fully carries the burden for parameter meaning. It clearly explains dry_run ('only report what would change, download nothing') and update_changed ('re-download files that changed on Moodle'), which is exactly what an agent needs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Synchronise'), a clear scope ('all active (current semester) courses'), a target ('local download directory'), and a return value ('per-course summary'). It is easily distinguished from moodle_sync_course by the 'all' scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this is for syncing all active courses and refers to moodle_sync_course for the underlying rules, but it never explicitly says when to use this tool versus syncing a single course. 'Same rules as moodle_sync_course' gives context but not a clear routing decision.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
moodle_sync_courseAIdempotent
Synchronise all files of a course into the local download directory. Downloads new files, re-downloads changed ones and reports what changed. Files removed from Moodle are reported but never deleted locally.
Args:
course_id: course id from moodle_list_courses
dry_run: only report what would change, download nothing
update_changed: re-download files that changed on Moodle
| Name | Required | Description | Default |
|---|---|---|---|
| dry_run | No | ||
| course_id | Yes | ||
| update_changed | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| new | No | |
| failed | No | |
| dry_run | Yes | |
| removed | No | Gone from Moodle; local files are kept |
| renamed | No | |
| updated | No | |
| restored | No | Known files missing locally, re-downloaded |
| course_id | Yes | |
| unchanged | No | |
| course_name | Yes | |
| download_directory | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses key behavioral traits: it never deletes files locally, it reports changes, and it can perform a dry run. This goes beyond the annotations, which only state readOnlyHint=false, openWorldHint=true, idempotentHint=true, destructiveHint=false. The description adds context about what the tool does and doesn't do, which is valuable. However, it doesn't mention potential side effects like network usage or disk space, but the core behavior is well covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured. It starts with a clear one-sentence summary, then elaborates on behavior, and finally lists parameter explanations. The parameter descriptions are formatted as a list, making them easy to scan. It could be slightly more concise by removing the Args section since the schema already lists parameters, but the added semantics justify the length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the tool's purpose, behavior, and parameter semantics. It also has an output schema, so return values are likely documented there. The description doesn't mention prerequisites like being logged in, but that's likely handled by other tools (moodle_login) and the annotations. Overall, it's complete enough for an agent to use correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description explains the meaning of all three parameters: course_id (from moodle_list_courses), dry_run (only report, download nothing), and update_changed (re-download changed files). This adds value beyond the schema, which only provides types and defaults. The description clarifies the semantics of each parameter, especially dry_run and update_changed, which are not self-explanatory from the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: synchronise all course files into a local download directory. It specifies the action (synchronise), the resource (course files), and the target (local download directory). It also distinguishes itself from siblings by mentioning it reports changes and never deletes locally, which differentiates it from moodle_download_resource and moodle_sync_all.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains the tool's behavior in detail: downloads new files, re-downloads changed ones, reports changes, and never deletes locally. It also explains the dry_run parameter's effect. However, it doesn't explicitly state when to use this tool versus alternatives like moodle_sync_all or moodle_download_resource, though the behavior description implies its use case.
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.
15 tool updates
v0.3.0- First observed
moodle_auth_status - First observed
moodle_download_resource - First observed
moodle_get_announcements - First observed
moodle_get_content - First observed
moodle_get_course - First observed
moodle_get_deadlines - First observed
moodle_get_recent_changes - First observed
moodle_list_assignments - First observed
moodle_list_courses - First observed
moodle_list_resources - First observed
moodle_login - First observed
moodle_logout - First observed
moodle_search - First observed
moodle_sync_all - First observed
moodle_sync_course
TDQS
Scored across 15 tools
Most tools target a distinct resource and action (auth, courses, files, deadlines, announcements), but a few have overlapping territory: get_recent_changes also surfaces announcements and deadlines, and get_course/list_resources/get_content all touch course content and text blocks. Descriptions are detailed enough that an agent can usually pick correctly, but there is some ambiguity.
All tool names follow the moodle_ prefix with a clear verb_noun convention: login, list_courses, get_content, download_resource, sync_course, get_announcements. The pattern is consistent and predictable.
Fifteen tools is at the upper edge of the ideal range but each one covers a distinct part of Moodle usage: session auth, course browsing, content/resource retrieval, syncing, search, and deadline/announcement queries. The count fits the scope of a Moodle assistant well.
The surface covers the main read-side workflows: exploring courses, reading materials, downloading/syncing files, searching, and checking deadlines/announcements. Minor gaps such as forum posts, grades, and assignment submission are absent, but agents can still accomplish most common Moodle tasks without dead ends.
Related MCP Connectors
Notes, files, GitHub, and Drive through one MCP connection.
Notes, files, GitHub, and Drive through one MCP connection.
Notes, files, GitHub, and Drive through one MCP connection.
Read-only MCP server for ClassQuill, a tutoring-business-management platform.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceMoodle REST API client with batch downloading and MCP protocol support for Claude Code and OpenCode, enabling course management, grade checking, assignment tracking, file downloads, and more.6MIT
- FlicenseNot gradedqualityCmaintenanceAn MCP server for interacting with the MyDy (Moodle-based) LMS, enabling attendance viewing, course browsing, assignment and grade checking, announcement reading, and material downloading.7-
- FlicenseAqualityCmaintenanceEnables MCP-compatible clients to read courses, assignments, announcements, files, and grades from a Canvas LMS instance.10-
- FlicenseNot gradedqualityAmaintenanceEnables MCP hosts to query NTULearn courses, announcements, calendar events, and grades, and to download course files into organized folder hierarchies.3-