Skip to main content
Glama

moodle-mcp

Let your AI assistant read your Moodle courses. Ask things like:

What do I have to hand in this week? Anything new on Moodle since last time? Summarize the latest slides of INFO-F403. Download the new exercise sheets of the crypto course into my OneDrive course folder.

moodle-mcp is an MCP server: a small program that AI apps (Claude Code, Claude Desktop, Codex, Cursor, Gemini CLI, Windsurf…) launch in the background to get extra tools. It talks to Moodle with your own token, through the same API as the official Moodle mobile app, and only reads.

Made for the ULB (uv.ulb.ac.be, the default), but it works with any Moodle site that allows the mobile app.

Install (5 minutes)

1. Install uv (a Python tool installer). Skip this step if you already have it.

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

  • Windows (PowerShell): powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Then open a new terminal.

2. Install moodle-mcp

uv tool install git+https://github.com/Nicolas-Prn/moodle-mcp

3. Run the setup

moodle-mcp setup

It asks for your Moodle token (see below), checks it, then offers to register the server in every AI app it finds on your computer. Restart Claude Desktop (or other open apps) afterwards. That's it.

Getting your Moodle token

The token gives read access to your courses, as the Moodle app has. Keep it private.

Option A: Security keys page (easiest)

  1. Log in to Moodle in your browser.

  2. Open https://uv.ulb.ac.be/user/managetoken.php (profile picture → Preferences → Security keys).

  3. Copy the key in the Moodle mobile web service row and paste it into moodle-mcp setup.

Option B: if there is no such page or row

  1. Log in to Moodle in Chrome, Edge or Firefox.

  2. Open the developer tools (F12, or Cmd+Option+I on a Mac) and select the Network tab.

  3. In the same tab, go to https://uv.ulb.ac.be/admin/tool/mobile/launch.php?service=moodle_mobile_app&passport=1&urlscheme=moodlemobile

  4. Click the launch.php request (it shows as failed, that's expected). Under Response Headers, copy the whole location value (moodlemobile://token=…) and paste it into moodle-mcp setup, which decodes it.

For another university, replace uv.ulb.ac.be with your Moodle address and run moodle-mcp setup --url <address>.

Related MCP server: Moodle Student MCP

Using it

Just ask your assistant in plain language, in any conversation and any folder. It picks the right tools:

Tool

What it does

list_courses

Your courses (current ones, or past ones too)

get_course_outline

Sections, activities, links and files of a course, with file references

get_deadlines

Upcoming and overdue things to do (assignments, quizzes…)

get_announcements

Recent announcements and forum posts, across all courses or one

read_discussion

A full forum thread

check_updates

What is new / changed / removed since you last marked a course as seen

mark_updates_seen

Marks the current content as seen (the assistant does it once you've dealt with the changes)

read_file

Reads a file as text so the assistant can explain or summarize it (PDF, Word, PowerPoint, HTML, code…)

download_files

Saves chosen files into a folder you name, optionally renamed or sorted into sub-folders

mirror_course

Saves a whole course, mirroring its Moodle structure (dry_run shows the size first)

A course can be named by its code (F403, info-h417), part of its name, or its id.

Downloads never overwrite a file that already exists, so annotating or editing downloaded files is safe. When Moodle has a newer version of a file you already have, the assistant can save it next to yours as name (2).pdf. check_updates compares Moodle with what it saw last time, not with your local files.

Supported apps

moodle-mcp setup (or moodle-mcp install later) registers the server automatically in: Claude Code (all projects), Claude Desktop, Codex, Cursor, Gemini CLI and Windsurf.

For any other app that supports local (stdio) MCP servers, add a server with the command that moodle-mcp status prints, for example:

{ "mcpServers": { "moodle": { "command": "/Users/you/.local/bin/moodle-mcp", "args": ["serve"] } } }

Use the full path: desktop apps do not see your terminal's PATH.

Not supported yet: ChatGPT and the claude.ai website or mobile app. They can only reach MCP servers hosted on the internet, while this one runs on your computer (which is also why your token never leaves it).

Commands

moodle-mcp setup              # save or replace your token, then register in your AI apps
moodle-mcp status             # check the token and see which apps were detected
moodle-mcp install [apps...]  # register again (e.g. after installing a new app): claude-code, claude-desktop, codex, cursor, gemini, windsurf
moodle-mcp uninstall          # unregister from the apps
uv tool upgrade moodle-mcp    # update to the latest version

To remove everything: moodle-mcp uninstall, uv tool uninstall moodle-mcp, then delete ~/.config/moodle-mcp.

Privacy and security

  • The token is stored only on your computer, in ~/.config/moodle-mcp/config.json (readable by you only). App configurations contain just the command, never the token. You can also provide it through the MOODLE_TOKEN (and MOODLE_URL) environment variables instead.

  • The server never changes anything on Moodle: no submissions, no posts, no messages.

  • The token is only ever sent to your Moodle site, and is removed from error messages.

  • Forum posts, descriptions and files are written by other people. The server tells the assistant to treat them as information, not as instructions.

  • To revoke access, use Reset on the Security keys page, then run moodle-mcp setup --new-token.

Troubleshooting

  • The assistant doesn't see the Moodle tools: restart the app, then run moodle-mcp status. In Claude Code, /mcp lists connected servers.

  • "invalidtoken" or "No Moodle token configured": run moodle-mcp setup --new-token.

  • A big mirror_course times out: some apps stop waiting after a minute or two. Downloads already finished are kept, so asking again resumes where it stopped.

Development

git clone https://github.com/Nicolas-Prn/moodle-mcp && cd moodle-mcp
uv sync
uv run pytest
uv run moodle-mcp status
npx @modelcontextprotocol/inspector uv run moodle-mcp serve   # try the tools in a web UI

Code layout (src/moodle_mcp/): server.py defines the MCP tools, courses.py the course and file model (including file references), client.py the Moodle Web Service client, updates.py change detection, downloads.py saving files, text.py text extraction, config.py settings and cli.py the commands.

License: MIT.

Available Tools

10 tools
check_updatesA
Read-only

What is new, changed or removed on Moodle since the courses were last marked as seen.

The first call for a course records a baseline (everything currently there counts as seen).

ParametersJSON Schema
NameRequiredDescriptionDefault
courseNo

TDQS

A3.8/5.0
Behavior4/5

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

Annotations only declare readOnlyHint and openWorldHint, so the description earns credit by disclosing the stateful baseline behavior: the first call per course silently records a baseline and returns nothing useful. That is non-obvious and important for correct invocation. It still doesn't say whether subsequent calls return a diff list or counts.

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

Conciseness5/5

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

Two tight sentences, front-loaded with the purpose and followed by the one behavioral fact an agent must know. No filler.

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

Completeness4/5

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

For a single-parameter, read-only, open-world tool with no output schema, the description covers the core semantics and the baseline side effect. The remaining gap is the scope of the omitted-course default, which the richer plural framing muddies rather than resolves.

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?

Only one parameter ('course') with 0% schema description coverage and a null default. The description implies per-course scoping ('the first call for a course'), but never explains what happens when 'course' is omitted, despite the first sentence's plural 'courses' framing.

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

Purpose4/5

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

States a specific outcome: what is new, changed or removed on Moodle relative to the last-seen state. This clearly separates it from mutation siblings like mark_updates_seen, though it never names that sibling or any other alternative explicitly.

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

Usage Guidelines3/5

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

The baseline sentence implies usage context (call this to discover changes, then mark them seen), but the pairing with mark_updates_seen is left to inference and there is no explicit when-to-use/when-not guidance.

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

download_filesA
Idempotent

Download course files into a local folder. Existing files are never overwritten.

- files: refs from get_course_outline / get_announcements / check_updates (or Moodle pluginfile URLs).
- dest_dir: absolute local folder (or ~/...), created if needed.
- save_as: optional {ref: "relative/path/name.pdf"} to choose where each file goes inside dest_dir;
  by default a file keeps its Moodle name (and its sub-folder, for files inside folder modules).
- on_conflict: "skip" (default) leaves an existing file alone; "rename" saves the new one as "name (2).ext".
ParametersJSON Schema
NameRequiredDescriptionDefault
filesYes
courseYes
save_asNo
dest_dirYes
on_conflictNoskip

TDQS

A4.2/5.0
Behavior5/5

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

The description discloses behavior the annotations cannot express: dest_dir is created if missing, nested folder-module structure is preserved by default, and the exact conflict policy (skip vs. rename to 'name (2).ext'). This usefully extends the annotations' idempotentHint/destructiveHint rather than repeating 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?

Front-loaded with purpose and the overwrite guarantee, then a tight bullet list where each entry maps to a parameter or decision. Slightly dense but no filler sentences.

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?

For a write-to-disk tool with no output schema, the description covers naming, destination handling, and conflict resolution well. Missing only the meaning of the required 'course' argument and any mention of how download results/errors are reported.

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 description coverage is 0%, so the description carries the full burden, and it documents four of the five parameters (files, dest_dir, save_as, on_conflict) with formats, defaults, and examples. The required 'course' parameter is left completely unexplained, which is the one real gap.

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 first sentence gives a specific verb and resource ('Download course files into a local folder') plus an immediate behavioral fact ('existing files are never overwritten'). It does not, however, distinguish itself from siblings that also touch files, notably read_file and mirror_course, so an agent still has to infer the boundary.

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 'files' bullet tells the agent exactly where the input refs come from (get_course_outline / get_announcements / check_updates), which is real routing guidance. It stops short of when-not to use it or naming mirror_course as the whole-course alternative.

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

get_announcementsA
Read-only

Recent forum discussions (announcements and other course forums), newest first, with attachment refs.

Messages are shortened; use read_discussion for a full thread.
ParametersJSON Schema
NameRequiredDescriptionDefault
daysNo
limitNo
courseNo

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare readOnlyHint and openWorldHint, so safety is covered; the description adds genuinely useful behavioral context that annotations cannot: results are truncated/shortened, ordered newest-first, and carry attachment refs rather than content. It does not disclose pagination behavior or the effective lookback window, which keeps it off a 5.

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

Conciseness5/5

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

Two short sentences, fully front-loaded: what you get first, the escape hatch to read_discussion second. No filler and nothing repeated from the schema or annotations.

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

Completeness3/5

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

There is no output schema, and the description does cover the shape of the return (shortened messages, ordering, attachment refs), which is the main thing it needed to do. However, with three parameters at 0% schema coverage and no annotation coverage of them, an agent still lacks the information required to set days/limit/course correctly.

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

Parameters2/5

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

Schema description coverage is 0% — days, limit, and course carry no descriptions in the schema — and the description never mentions any of the three parameters. An agent cannot tell whether 'days' is a lookback window, what format 'course' takes (ID vs name), or how 'limit' interacts with truncation, so the description fails to compensate for the coverage gap.

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

Purpose5/5

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

States a concrete resource (recent forum discussions), clarifies the scope extends beyond announcements to other course forums, and specifies ordering (newest first) plus attachment refs. It also names the sibling it is not — read_discussion for full threads — so an agent can separate the two without opening a schema.

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

Usage Guidelines4/5

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

Explicitly routes the full-thread case to read_discussion, which is the key decision point between these two siblings. It does not address overlap with check_updates or state any exclusion on the primary 'recent scan' use case, so it falls short of a full when/when-not treatment.

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

get_course_outlineA
Read-only

Sections, activities, links and files of a course, with the file refs used by read_file/download_files.

Modules with many files are truncated; pass module_id to list every file of one module.
ParametersJSON Schema
NameRequiredDescriptionDefault
courseYes
module_idNo

TDQS

A3.7/5.0
Behavior4/5

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

Annotations only declare readOnlyHint and openWorldHint, so the description adds real value by disclosing the truncation behavior for file-heavy modules and the module_id escape hatch. It does not say whether truncation is flagged in the response, which is the one gap.

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

Conciseness4/5

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

Two dense sentences, front-loaded with what is returned and followed immediately by the truncation caveat. Nothing is wasted, though the telegraphic noun-phrase opening is slightly less scannable than an explicit verb statement.

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 no output schema, the description does the work of describing return values (sections, activities, links, files, file refs) and a key limitation (truncation). The remaining hole is the meaning/format of the required 'course' argument.

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

Parameters3/5

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

Schema coverage is 0%, so the description must carry both parameters. It explains module_id well (pass it to list every file of one module), but the required 'course' parameter is left entirely undefined — no indication whether it takes an ID, slug, or name. Partial compensation justifies a 3.

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?

Names a specific resource (course outline) and enumerates its contents: sections, activities, links, files, plus the file refs that feed read_file/download_files. That cross-reference distinguishes it from siblings like list_courses and read_file. It stops short of a clean verb+resource statement, but an agent can tell what it returns.

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?

It implies a workflow role by tying the returned file refs to read_file/download_files, and it gives a concrete workaround for truncated modules via module_id. However, it never says when to prefer this over list_courses or mirror_course, and gives no prerequisites or exclusions.

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

get_deadlinesC
Read-only

Upcoming deadlines and actions to do (assignments, quizzes...), including overdue ones from the last 2 weeks.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNo
courseNo

TDQS

C2.9/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds real scope detail — overdue items are included but capped at the last 2 weeks — which is behavior beyond the annotations. It says nothing about return shape, ordering, or how the days window interacts with the fixed 2-week lookback.

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?

A single front-loaded sentence with no filler; the parenthetical examples are the only mild redundancy. Efficient and easy to scan.

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

Completeness2/5

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

With no output schema and 0% parameter coverage, the description should explain what the two parameters do and roughly what is returned. It gives a rough sense of contents but leaves both parameters and the returned fields undocumented, so an agent cannot call it precisely.

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

Parameters2/5

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

Schema description coverage is 0%, so the description carries the full burden for the two parameters and largely fails: 'days' (default 30) is never explained, and 'course' (nullable filter) is never mentioned. The 'last 2 weeks' phrase relates to a fixed overdue window, not to the days parameter, so an agent gets no help sizing the query.

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?

Names a concrete resource (deadlines/actions to do) with examples (assignments, quizzes) and states the time scope, so an agent can distinguish it from list_courses or get_announcements without opening a schema. It is clear but does not explicitly contrast itself with any sibling tool.

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 on when to call this versus get_announcements, check_updates, or get_course_outline, and no mention of how the days/course parameters change the scope. Usage can only be inferred from the phrase 'upcoming deadlines'.

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

list_coursesA
Read-only

List the courses the user is enrolled in (id, code, name). Past courses are hidden unless include_past.

ParametersJSON Schema
NameRequiredDescriptionDefault
include_pastNo

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already establish readOnlyHint=true and openWorldHint=true, so safety is covered. The description adds a genuinely useful behavioral fact beyond the schema: results are silently filtered to current courses unless include_past is set, which an agent could not infer from default=false alone. Return format and volume/pagination are still unaddressed.

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?

One sentence, front-loaded with the core action and followed by the output shape and the sole caveat. Nothing is wasted and nothing essential is deferred.

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?

For a simple, annotation-covered read tool with one parameter and no output schema, the description supplies purpose, returned fields, and the default filtering behavior. It stops just short of describing ordering, pagination, or what happens with zero enrollments.

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 description coverage is 0% for the single parameter, so the description carries the burden, and it does: it explains that include_past controls whether historical enrollments appear. That is the full semantic of the only parameter, though no format or edge-case detail is given.

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

Purpose4/5

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

States a specific verb and resource ('List the courses the user is enrolled in') and even names the returned fields (id, code, name). It is clearly distinct from siblings like get_announcements or get_deadlines, though it never explicitly contrasts with the closest sibling get_course_outline.

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

Usage Guidelines3/5

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

Usage is implied by the name and the enrollment framing, and the note about past courses being hidden gives one behavioral condition. However, there is no explicit 'use this when' guidance and no mention of alternatives such as get_course_outline for a deeper view of a single course.

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

mark_updates_seenA
Idempotent

Record the current Moodle content as seen, so check_updates stops reporting it. Only touches local state.

ParametersJSON Schema
NameRequiredDescriptionDefault
courseNo

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare idempotentHint=true, destructiveHint=false and readOnlyHint=false; the description adds the meaningful clarification that it 'only touches local state', i.e., it does not modify Moodle content, which is real context beyond the annotations. The tension with openWorldHint=true is minor and openWorldHint semantics are debatable, but the description does not mention return behavior.

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

Conciseness5/5

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

Two short, front-loaded sentences; the purpose leads and the side-effect clarification follows. Nothing is wasted.

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

Completeness4/5

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

For a low-complexity, no-output tool with annotations covering the safety profile, the description covers purpose, effect and locality. The only real gap is the unaddressed 'course' parameter's scoping behavior.

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

Parameters2/5

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

Schema description coverage is 0% for the single optional 'course' parameter, and the description never mentions it or explains what omitting it does (all courses vs current course). The description provides no parameter-level meaning to compensate.

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

Purpose5/5

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

States a specific verb and resource ('Record the current Moodle content as seen') and explicitly describes the effect on a named sibling ('so check_updates stops reporting it'), letting an agent separate it from check_updates and mirror_course without reading schemas.

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?

Clear context for when to call it: after reviewing content, to clear what check_updates reports. It names the dependent sibling and its effect, but offers no explicit when-not or alternative (e.g., what to do for a single course vs all).

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

mirror_courseA
Idempotent

Download every file of a course into dest_dir, mirroring Moodle's structure. Never overwrites.

Layout: `<NN section>/<file>` for single-file resources, `<NN section>/<activity>/<file>` otherwise
(folders, multi-file resources, assignment statements), `Forum: <name>/<discussion>/` for attachments.
Use dry_run=True first on large courses to see what would be downloaded and how much.
ParametersJSON Schema
NameRequiredDescriptionDefault
courseYes
dry_runNo
dest_dirYes
include_forumsNo

TDQS

A3.5/5.0
Behavior4/5

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

Annotations already declare the safety profile (readOnlyHint=false, idempotentHint=true, destructiveHint=false), and the description usefully adds 'Never overwrites' plus the exact on-disk layout, which is behavior an agent cannot derive from the schema. It does not say what happens on partial failures or whether existing files are skipped silently.

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

Conciseness5/5

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

Three tight sentences: purpose first, then the layout contract, then the dry_run tip. The layout block is the only elaboration and it directly serves correct invocation; nothing is redundant with the schema.

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

Completeness3/5

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

For a 4-parameter write tool with no output schema, the description covers the core purpose and filesystem layout well but leaves include_forums and the course identifier format entirely undocumented. An agent could call it successfully for the defaults but would have to guess about forum inclusion.

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

Parameters2/5

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

Schema description coverage is 0% and none of the four parameters are documented in the description itself. dest_dir and dry_run are only indirectly implied, while include_forums (default false) and course are never explained — notably the layout mentions 'Forum: <name>/<discussion>/' although forums are excluded by default, which an agent could misread.

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

Purpose4/5

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

States a concrete verb+resource+target ('Download every file of a course into dest_dir, mirroring Moodle's structure'), which clearly separates it from the flat download_files sibling via the directory-mirroring behavior. It never names that sibling or explicitly contrasts with it, so sibling differentiation is implicit rather than stated.

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 only guidance is 'Use dry_run=True first on large courses to see what would be downloaded and how much,' which is a workflow tip rather than when-to-use-this-vs-alternatives guidance. There is no statement of when not to use it, nor any routing to download_files or read_file for single-file needs.

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

read_discussionB
Read-only

Every post of a forum discussion (ids come from get_announcements).

ParametersJSON Schema
NameRequiredDescriptionDefault
discussion_idYes

TDQS

B3.4/5.0
Behavior2/5

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

Annotations already declare readOnlyHint=true and openWorldHint=true, so safety is covered by structured data. The description adds no behavioral context at all: no pagination behavior, no error handling for an invalid or inaccessible discussion_id, no auth requirements, and no indication of how much content is returned.

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?

A single short sentence with no filler, and the scope statement comes before the parenthetical hint about parameter sourcing. It is slightly under-specified rather than padded, so nothing wasted but little provided.

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 phrase 'every post' communicates that the full discussion is returned without filtering, which covers the return-shape question in the absence of an output schema, and annotations handle the safety profile. Auth/permission expectations are the only real gap for a tool this simple.

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 description coverage is 0% for the single parameter, yet the description supplies the one fact the schema omits: where discussion_id values originate (get_announcements). That provenance note is the key semantic need for this tool, though it doesn't clarify the expected id format.

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 names a specific resource and scope: all posts of a single forum discussion, which is distinct from sibling reads like read_file or get_course_outline. It lacks an explicit verb, reading as a fragment, but the resource and scope are unambiguous enough for an agent to select it.

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 parenthetical '(ids come from get_announcements)' tells the agent how to obtain the required parameter, which is real usage guidance, but it never states when to prefer this tool over siblings such as read_file or get_course_outline, nor any precondition beyond the id source.

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

read_fileA
Read-only

Text content of a course file (PDF, Word, PowerPoint, HTML, code, plain text).

`file` is a ref from get_course_outline/get_announcements (or a Moodle pluginfile URL).
`pages` selects PDF pages or PowerPoint slides, e.g. "1-5" or "2,7-9".
ParametersJSON Schema
NameRequiredDescriptionDefault
fileYes
pagesNo
courseYes
max_charsNo

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds useful capability context (which file formats yield text, that pages apply to PDF/PPT), but says nothing about truncation behavior tied to max_chars (default 60000) or what happens when a document exceeds it.

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?

Very short and front-loaded: the capability comes first, then per-parameter notes. Every sentence earns its place, with only the opening noun phrase being slightly terse rather than a full verb statement.

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 no output schema, the description correctly focuses on what comes back ('text content') and format applicability. For a 4-parameter read tool it covers the operation adequately, though the unexplained max_chars/course and unstated truncation caveat leave a gap.

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

Parameters3/5

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

Schema description coverage is 0%, so the description carries the full burden. It explains 'file' (ref source) and 'pages' with a concrete syntax example ('1-5', '2,7-9'), but leaves 'course' and 'max_chars' entirely undocumented in both schema and description, so half the parameters remain opaque.

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 names the concrete resource and scope — extracting text content from a course file — and enumerates supported formats (PDF, Word, PowerPoint, HTML, code, plain text), so an agent can tell it retrieves readable text. It does not explicitly contrast with the sibling download_files, but the operation is 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?

It gives provenance guidance ('file is a ref from get_course_outline/get_announcements') which tells the agent where to get the required input, a real usage hint. However, there is no when-not guidance and no mention of the alternative download_files for retrieving the raw file rather than its text.

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. 10 tool updatesv0.1.0
    • First observedcheck_updates
    • First observeddownload_files
    • First observedget_announcements
    • First observedget_course_outline
    • First observedget_deadlines
    • First observedlist_courses
    • First observedmark_updates_seen
    • First observedmirror_course
    • First observedread_discussion
    • First observedread_file

TDQS

A3.7/5.0

Scored across 10 tools

Disambiguation4/5

Tools are mostly distinct, but get_announcements and check_updates both surface new course content, and download_files and mirror_course both download files; descriptions clarify boundaries, but an agent could occasionally misselect.

Naming Consistency5/5

All tool names use a consistent snake_case verb_noun pattern (get_, list_, read_, check_, mark_, download_, mirror_), making the set predictable and easy to scan.

Tool Count5/5

10 tools is well-scoped for a Moodle course-access client, with no redundant or trivial tools; each covers a distinct capability.

Completeness4/5

The surface covers core read workflows (courses, outline, deadlines, announcements, discussions, files, updates, mirroring), but lacks search, grades, or assignment interaction, which are minor gaps for a read-only client.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers