Skip to main content
Glama
Dathis

ZHAW Moodle MCP Server

by Dathis

ZHAW Moodle MCP Server

PyPI CI License: MIT

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@latest

3. 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 as command, 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

moodle_auth_status

Is there a valid Moodle session?

moodle_login

Open the browser for SWITCH edu-ID login (other tools do this automatically when needed)

moodle_logout

End the session and delete local cookies/browser profile

moodle_list_courses

Courses, marked active / past / future

moodle_get_course

Sections, subsections and all activities of a course, incl. the text of text blocks

moodle_get_content

Text of a Moodle page or text block as Markdown, with its links

moodle_list_resources

Files (pdf, powerpoint, word, …), folders (incl. their files), links, pages

moodle_download_resource

Download a file, a whole folder or the files linked in a page/text block, returns local paths

moodle_sync_course

Download new/changed files, report renamed/removed ones (dry_run supported)

moodle_sync_all

Sync all current courses, per-course summary

moodle_search

Find courses, sections, materials, assignments, quizzes by name (umlaut/typo tolerant); falls back to Moodle full-text search

moodle_get_deadlines

Open to-dos with deadlines (assignments, quizzes) across all courses

moodle_list_assignments

Assignments with dates, submission and grading status, description

moodle_get_announcements

Lecturer announcements with message text

moodle_get_recent_changes

New/updated materials, announcements and deadlines since a date (2026-09-14, 7d)

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 sync

Log in once (opens the browser, finishes automatically after the SWITCH edu-ID login):

uv run zhaw-moodle-mcp login

Add the server to Claude Code:

claude mcp add zhaw-moodle -- uv --directory C:/path/to/zhaw-moodle-mcp run zhaw-moodle-mcp

Alternatively 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 expected

How 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_resources or 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>) for moodle_download_resource; the id of the page/block itself downloads all its linked files into <course>/<section>/<page name>/. These files are not part of moodle_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 (icacls on Windows, chmod 600/700 elsewhere).

  • Tool results and error messages never contain cookies or session keys; logs go to stderr with cookies, sesskeys and SSO parameters redacted.

  • moodle_logout removes the stored session and the browser profile.

Development

uv run pytest
uv run ruff check src tests

Tests 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 tools
moodle_auth_statusA
Read-onlyIdempotent

Check whether a valid ZHAW Moodle session exists. Never returns credentials.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
stateYes
messageYes
moodle_urlYes
authenticatedYes

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness5/5

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.

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-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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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_resourceA
Idempotent

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)
    
ParametersJSON Schema
NameRequiredDescriptionDefault
overwriteNo
destinationNo
resource_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
filesYes
failedNoLinked files that could not be loaded
resource_idYes

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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_announcementsA
Read-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
    
ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
sinceNo
course_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
announcementsYes

TDQS

A4/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines2/5

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_contentA
Read-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
    
ParametersJSON Schema
NameRequiredDescriptionDefault
activity_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
urlNo
nameYes
noteNo
textYesContent as Markdown
linksNo
moduleYespage or label
sectionYes
course_idYes
accessibleNo
course_nameYes
modified_atNo

TDQS

A4.6/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_courseA
Read-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
    
ParametersJSON Schema
NameRequiredDescriptionDefault
course_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
courseYes
sectionsYes

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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_deadlinesA
Read-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
    
ParametersJSON Schema
NameRequiredDescriptionDefault
course_idNo
days_aheadNo
include_overdueNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
nowYes
noteNo
untilYes
deadlinesYes

TDQS

A4.6/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_changesA
Read-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)
    
ParametersJSON Schema
NameRequiredDescriptionDefault
sinceNo7d
course_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
sinceYes
untilYes
coursesYes
unchanged_coursesNo

TDQS

A4.2/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_assignmentsA
Read-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
    
ParametersJSON Schema
NameRequiredDescriptionDefault
course_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
failedNoAssignments that could not be read
assignmentsYes

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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_coursesA
Read-onlyIdempotent

List the user's ZHAW Moodle courses.

    Args:
        status: "active" (current semester, default), "past", "future" or "all"
    
ParametersJSON Schema
NameRequiredDescriptionDefault
statusNoactive

Output Schema

ParametersJSON Schema
NameRequiredDescription
coursesYes

TDQS

A3.5/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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_resourcesA
Read-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)
    
ParametersJSON Schema
NameRequiredDescriptionDefault
course_idYes
include_folder_contentsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
course_idYes
resourcesYes

TDQS

A4/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_loginA
Idempotent

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
    
ParametersJSON Schema
NameRequiredDescriptionDefault
forceNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
stateYes
messageYes
moodle_urlYes
authenticatedYes

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_logoutA
DestructiveIdempotent

Log out: end the Moodle session and delete the locally stored browser session and cookies. The next Moodle request will require a new login.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageYes
logged_outYes
server_session_invalidatedYes

TDQS

A4.1/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines2/5

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_sync_allA
Idempotent

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
    
ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNo
update_changedNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
coursesYes
dry_runYes
download_directoryYes

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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_courseA
Idempotent

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
    
ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNo
course_idYes
update_changedNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
newNo
failedNo
dry_runYes
removedNoGone from Moodle; local files are kept
renamedNo
updatedNo
restoredNoKnown files missing locally, re-downloaded
course_idYes
unchangedNo
course_nameYes
download_directoryYes

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

  1. 15 tool updatesv0.3.0
    • First observedmoodle_auth_status
    • First observedmoodle_download_resource
    • First observedmoodle_get_announcements
    • First observedmoodle_get_content
    • First observedmoodle_get_course
    • First observedmoodle_get_deadlines
    • First observedmoodle_get_recent_changes
    • First observedmoodle_list_assignments
    • First observedmoodle_list_courses
    • First observedmoodle_list_resources
    • First observedmoodle_login
    • First observedmoodle_logout
    • First observedmoodle_search
    • First observedmoodle_sync_all
    • First observedmoodle_sync_course

TDQS

A4.1/5.0

Scored across 15 tools

Disambiguation4/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness4/5

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

Related MCP Servers