moodle_local
This MCP server lets you manage and synchronize UNNC Moodle course materials locally via Codex.
Check Moodle connection and dedicated login session without exposing credentials.
List enrolled My Modules courses; only explicitly approved IDs can be synchronized.
List visible resources for an approved course with IDs, titles, types, and format metadata.
Download discovered file/folder modules in approved courses to the approved materials directory, keeping old versions.
Perform manual incremental sync for approved courses;
forceContentCheckbypasses ETag validation.View approved course IDs and local output directories without authentication data.
Select or replace approved course IDs after user approval; empty IDs clear selection without deleting files.
Confirm setup by persisting the displayed course list and current data root after explicit user confirmation.
Supports automatic course/section folders or existing folder mappings, preserving previous versions and local annotations.
Provides tools for accessing and synchronizing selected UNNC Nottingham Moodle courses, including checking login status, listing courses and resources, selecting course whitelists, downloading course materials, and performing incremental syncs while preserving version history.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@moodle_localcheck Moodle login status, then sync my selected course files"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Overview
Download materials from selected courses, organize them by course and Moodle section, and keep them up to date through Codex. Previous versions and local annotations are preserved.
Requirements: macOS + Google Chrome, or experimental Windows + Microsoft Edge, and Node.js 24+. This is an unofficial project for UNNC / Nottingham Moodle. Synchronization is manual. Windows + Edge has experimental adaptations, pending real Windows validation; other Moodle installations have not been verified.
Related MCP server: smu-elearn
Installation
To human
Download the ZIP attachment with the highest version number from Releases, then extract it to a permanent program directory.
On macOS open
scripts/setup.command; on Windows openscripts/setup.cmd(experimental). The launcher checks prerequisites, installs dependencies with your confirmation, builds the server, and starts setup.Sign in to Moodle in the dedicated browser, complete MFA, select your courses, and choose how to save materials: automatic course/section folders or your existing folders. The final step recommends installing the Codex skill; press Enter to accept or enter n to skip.
Follow Connect to Codex, then restart Codex and choose a usage mode.
Setup does not download course materials. Existing-folder mappings are confirmed in Codex before downloading unclassified resources.
To agent
Open Codex in the extracted program directory and send:
Help me install and connect this UNNC Moodle MCP. Read the README first, check my environment, and install the project dependencies and bundled skill. Preserve my existing Codex configuration. Ask me to choose courses and the saving mode; I will complete Moodle login and MFA myself. Show me the MCP configuration change for confirmation before applying it. Do not start downloading until I confirm the courses, directories, and any classification rules.
For the agent: locate the downloaded project; if it is absent, guide the user to the ZIP installation above. Check Node.js 24+ and the required browser, then run these commands in the program directory after installation authorization:
npm run doctor
npm ci
npm run buildHave the user run npm run setup in an interactive terminal and complete login/MFA. Explain the two saving modes in Usage. Unless the user opts out, include skill installation; if setup skipped it and installation is authorized, run npm run install-skill -- --yes and check the result. Do not overwrite a conflicting installed skill. Finish Connect to Codex separately, preserving other MCP entries; skill installation alone does not connect MCP. After restarting Codex, read settings and login status back before the first synchronization.
Update
Run this command in your existing program directory:
npm run updateThe updater downloads the newest published release, installs dependencies, and builds it before replacing the existing program. The installation path, settings, login session, and downloaded materials are retained. A failed replacement rolls back to the previous program.
Stop all old Moodle MCP/CLI processes before updating. On first startup, version 0.4.5 moves legacy management files into _moodle beside materials; see storage migration and recovery. Reconnect the Moodle MCP server or restart Codex after updating. Then continue synchronization in Codex. Program updates preserve separately installed skills; run npm run install-skill if you previously skipped installation.
Reinstalling older versions: if npm run update is unavailable or the installed version cannot be upgraded directly, stop the old MCP server and reinstall using the installation steps above. Preserve the materials directory, _moodle (or legacy state and courses.json), and existing settings; remove only the program files. If program and data share a directory, back up the data separately before removing it. Use the previous program path where possible; otherwise update the MCP configuration to the new path. Existing materials do not need to be downloaded again.
The updater supports ZIP installations. Git checkouts must be updated through Git. Published prereleases are included in version selection; drafts are excluded. Network failures should be retried after connectivity is restored.
Connect to Codex
From the program directory, run:
npm run codex-configAdd the printed [mcp_servers.moodle_local] block to your Codex MCP configuration, preserving other entries. This command prints configuration; it does not edit it. The server starts with node /absolute/project/dist/src/server.js.
Setup offers the recommended skill installation on macOS and Windows. Existing users can run npm run install-skill separately; it does not require school login. The installer uses ~/.agents/skills/unnc-moodle, reuses an existing legacy ~/.codex/skills/unnc-moodle, or uses CODEX_HOME/skills/unnc-moodle when configured. Identical installations are left alone; differing or unsafe existing skills are not overwritten. Back up a differing skill outside the skills directory and review it before replacing it. A skill conflict does not undo completed MCP setup. The supplied skill instructions are in Chinese; the MCP tools accept the same requests in English or Chinese.
Restart Codex, then check get_sync_settings and check_connection. Downloads require a confirmed materials directory and selected courses. If login has expired, ask Codex to open the dedicated login browser using the login MCP tool. Complete sign-in and MFA in that browser; Codex verifies the result before continuing. The tool waits up to five minutes. npm run login remains a fallback for clients without the tool.
Usage
Choose either saving mode below. New users choose during setup; existing users can ask Codex to change the mode without reinstalling.
1. Create course folders automatically
Choose the automatic course/section mode during setup, then tell Codex:
Check my Moodle connection and settings, then synchronize my selected courses using automatic course/section folders.
Materials appear under materials/Course name/Moodle section/Resource title.ext. Single-file resources use Moodle titles, such as Seminar 1.pdf and Seminar 1 (Solutions).pdf; folder children retain their filenames and nested structure.
2. Use your existing folders
Choose the existing-folder mode during setup and enter the shared root of your course folders. If already installed, tell Codex:
My course materials are already organized at “PASTE YOUR FOLDER PATH”. Use the existing structure, with lectures in Lecture and seminars in Seminar. First inspect the folders and my selected Moodle resources, then show me the proposed mapping. Save the rules and download only after I confirm. Preserve existing files and notes.
Codex reviews actual resource titles, available page descriptions, and the folders you authorize it to inspect. Confirm or correct the proposed mapping once; saved rules are reused on later synchronizations and after restarting. Different resources within the same Moodle section can go into different folders. Unmatched or ambiguous new resources are skipped for confirmation; after a file is classified, its folder is retained even if the resource is renamed. To correct its classification, confirm an explicit resource assignment.
Target folders must already exist under a shared root. Moving a mapped folder causes a reported failure until the rule is updated. Rules match user-confirmed keywords or specific resources; they do not infer categories from page order or file type, or analyze PDF contents. Existing-folder mode initially has no rules, so unclassified materials are not downloaded.
Existing files are not automatically adopted or deduplicated. A newly downloaded file with the same name receives a suffix, which can leave duplicates; original files and annotations are preserved. Changing the output root does not migrate old materials. Historical versions remain in the original materials/.history.
After either mode is configured, use these requests:
Task | Codex request |
Synchronize materials | “Synchronize my selected Moodle courses.” |
Download newly discovered materials | “Run a quick synchronization of my Moodle courses.” |
Organize existing downloads | “Organize my existing Moodle materials without downloading them again.” |
Add a course | “Show my Moodle courses so I can select another course to synchronize.” |
Quick synchronization discovers new files but does not check remote changes to previously recorded files. Full synchronization checks updates. Organize mode refreshes tracked local copies without downloading materials; it can rename unedited legacy files using Moodle titles, while keeping annotated copies separately. Additional courses require your approval. Check failures and skipped resources before treating a synchronization as complete.
The data root normally contains materials and _moodle. Course settings, sync state, classification rules and recognized legacy upgrade backups live in _moodle, which stays visible for recovery. Stop old MCP/CLI processes before upgrading, reconnect the new server, and read settings back.
Documentation
Testing and limitations — Chinese maintainer documentation
Release process — Chinese maintainer documentation
The server reads only selected courses that your account can access. It does not submit assignments, send messages, or modify school content. Authentication uses a dedicated browser profile; passwords and MFA codes are entered by the user. Keep login sessions, downloaded materials, and personal course configuration out of public repositories.
Style references
The following projects guide this project's documentation and presentation style:
Magenta CLI: distinct Installation and Update sections, prominent commands, and actionable upgrade guidance.
Levis: an English landing page with visible language switching, concise introductions, and consistent multilingual documentation.
Future documentation changes should follow these conventions: formal, concise wording; two primary entry points for installation and updates; and equivalent English and Chinese instructions. Commands and support claims must reflect this project's verified implementation.
License
MIT. The license covers this project's code, not university materials, branding, or third-party content.
Windows (experimental)
Use Node.js 24+ and Microsoft Edge, without WSL. Open scripts/setup.cmd or run the npm installation commands in PowerShell / CMD. Generate correctly escaped MCP paths with npm run codex-config. The same setup wizard offers skill installation; its paths and standalone command are described above.
Settings and the dedicated Edge profile live under %LOCALAPPDATA%/moodle-mcp, falling back to AppData/Local under the user directory. Materials default to Documents/MoodleSync. Paste the materials path from get_sync_settings into File Explorer. Windows permissions depend on the user directory ACL; POSIX mode flags do not provide equivalent macOS protection.
Automatic updating remains macOS-only. On Windows stop MCP and dedicated Edge, keep the old program directory, install/build in a new program directory, update the MCP entry, and recheck settings. Preserve configuration and materials.
The shared core and manifest schema remain unchanged. Real Windows installation, school login/MFA, file locking, long paths, ACL, and synchronization still require validation. Deep paths can encounter Windows path limits. macOS test results do not establish Windows support.
Windows uses a new dedicated edge-profile directory. Existing Windows Chrome profiles are preserved and are not imported; sign in again with Edge. Course settings and materials remain unchanged. If you explicitly set MOODLE_PROFILE_DIR, point it at a new dedicated Edge directory rather than the old Chrome profile. macOS retains its Chrome profile.
Available Tools
8 toolscheck_connectionBRead-onlyIdempotent
Check Moodle connection and dedicated login session; never return credentials.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered structurally. The description adds one genuinely useful behavioral fact beyond that: credentials are never returned, which tells the agent the output is safe to surface. It says nothing about failure behavior or what a failed connection check looks like, so it adds context but not rich detail.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tight sentence with the credential-safety clause placed after the core purpose, so the operation is front-loaded. No filler, though "dedicated login session" is slightly vague phrasing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no parameters, the description is the only place a caller could learn what a successful or failed check returns (status, error signaling). It covers scope and the credential guarantee but leaves the return contract unstated, which is a real gap for a diagnostic tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the schema carries no semantic burden and there is nothing for the description to disambiguate. Baseline of 4 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ("Check") and resource ("Moodle connection and dedicated login session"), which is a diagnostic/health-check operation distinct from the sibling tools (list_courses, download_resource, sync_courses), none of which perform connectivity checks. It is clear what the tool does, though it never explicitly contrasts itself with those siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to call this versus other tools, no prerequisites, and no exclusions. The only hint is the implied 'verify before acting' role, which the agent must infer from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
confirm_setupAIdempotent
After explicit user confirmation of the displayed course list and current data root, persist setup approval. dataDir must match current settings. For a different root use npm run setup; this tool never migrates data.
| Name | Required | Description | Default |
|---|---|---|---|
| dataDir | Yes | ||
| confirmed | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the write/idempotent/non-destructive profile, and the description adds genuinely new context: it requires prior explicit user confirmation and it never migrates data, which is a meaningful scope boundary for an approval-persisting write. It does not describe failure behavior if dataDir mismatches, but that is a minor gap given annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the precondition, then the constraint, then the exclusion. Every sentence adds distinct information with no repetition of the tool name or schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter mutation with no output schema, the description supplies the precondition, the constraint on dataDir, and the alternative tool. The only omission is what happens on a mismatched dataDir (error vs. no-op), which is not essential for selection.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the burden. It does clarify dataDir semantics ('must match current settings'), which is valuable, but the 'confirmed' parameter is only implicit in the prose and its const:true constraint is left to the schema. Partial compensation warrants a baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource ('persist setup approval') and clarifies the boundary ('never migrates data'), which separates it from a full setup/migration flow. It is clear but does not explicitly position itself against the sibling tools (list_courses, sync_courses, etc.), which are read/selection oriented.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states the precondition precisely ('After explicit user confirmation of the displayed course list and current data root') and names the alternative path for a different root ('use npm run setup'). Both when-to-use and when-not-to-use are covered with the routing condition spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
download_resourceAIdempotent
Download a discovered file/folder module in an approved course to the approved materials directory. Keep old versions.
| Name | Required | Description | Default |
|---|---|---|---|
| courseId | Yes | ||
| moduleId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=true and destructiveHint=false; the description adds the non-obvious behavioral fact that existing versions are retained ('Keep old versions'), which explains the non-destructive profile. It does not describe overwrite semantics, required permissions, or failure handling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, zero filler, with the action and destination front-loaded and the versioning caveat placed last. Every clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter write tool with no output schema and no parameter documentation, the description covers the operation and its non-destructive behavior but omits where ids originate, what the 'approved materials directory' resolves to, and what happens on re-download of an existing module. Adequate but with visible gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the description supplies no parameter information at all. The names courseId and moduleId are largely self-explanatory, but the description never clarifies accepted id forms (they come from list_courses/list_resources) or what a 'module' scope means for a file/folder download.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb (Download) plus the exact resource (a discovered file/folder module in an approved course) and destination (the approved materials directory). This clearly separates it from read-only siblings like list_resources, but it never names an alternative tool to complete the routing decision.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrases 'discovered' and 'approved course' imply prerequisites (discovery/selection must have happened first), which is useful implicit guidance. However, there is no explicit when-to-use versus sync_courses or list_resources, and no stated exclusions or preconditions for the call itself.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_sync_settingsBRead-onlyIdempotent
Show approved course IDs and local output directories without authentication data.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds a useful disclosure that authentication data is excluded from the response, but says nothing about return format or completeness of the settings view.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single compact sentence with the main content front-loaded. The trailing 'without authentication data' qualifier is slightly awkward but earns its place as a scoping disclosure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the burden of explaining returns and only partially does so: it names course IDs and output directories but omits other settings fields an agent might expect. Adequate but incomplete for a settings-reading tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4. The description correctly implies no inputs are needed and instead spends its words describing the output content.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Show) and a specific resource (sync settings, realized as approved course IDs and local output directories). It is clear what the tool returns, though it never names or contrasts with siblings such as list_courses or check_connection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance and no alternatives are named. The phrase 'without authentication data' hints that this is a scoped/redacted variant of a settings view, but the agent is left to infer when to prefer it over the other seven siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_coursesBRead-onlyIdempotent
List enrolled My Modules courses including hidden courses. Only explicitly approved IDs may be synchronized.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint, so the safety profile is covered. The description usefully adds that hidden courses are included, but the 'only explicitly approved IDs may be synchronized' sentence is ambiguous about whether it constrains this read call at all.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with the core capability front-loaded and no padding. The trailing sentence about approved IDs is terse but does not clearly belong to a list operation, which slightly weakens the structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no parameters, no output schema and full annotation coverage, the description only needs to convey what is enumerated and the scope. It does that, though the cryptic sync/approval sentence leaves a small ambiguity unresolved.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so per the rubric the baseline is 4. There is nothing parameter-level for the description to clarify, and it does not mislead about inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (list enrolled My Modules courses) and adds a scope detail (including hidden courses) that an agent could not infer from the name. It does not, however, distinguish this list tool from siblings like list_resources or sync_courses.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use or when-not-to-use guidance, and no alternative is named. The second sentence hints at a sync-approval workflow but never says how it relates to calling this tool versus sync_courses or select_courses.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_resourcesBRead-onlyIdempotent
List visible resources for an approved course, with observed IDs, titles, types and available format metadata.
| Name | Required | Description | Default |
|---|---|---|---|
| courseId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and openWorld behavior, so the safety profile is covered. The description usefully adds the 'visible'/'approved' scoping qualifier and the shape of the returned fields, but says nothing about pagination, result size, or auth requirements beyond the annotation hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tight sentence that front-loads the action and scope, with no filler. Slightly awkward phrasing ('observed IDs') costs it nothing materially.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 1-parameter read-only list tool with annotations covering safety and no output schema, the description tells the agent what it gets back and the scope. Gaps around pagination and how 'visible' is determined remain, so it is adequate but not fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the burden, and it only weakly compensates: 'for an approved course' implies courseId must reference an approved course but gives no format or validation detail. The parameter name courseId is self-evident, so meaning is not lost, but no real added semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (resources) scoped to an approved course, and even enumerates the returned fields (IDs, titles, types, format metadata). It is clearly separable from list_courses and download_resource by resource type, though it never names a sibling explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'for an approved course' implies the context in which this applies, so usage is inferable. However, there is no explicit when-to-use guidance and no mention of the obvious alternative (download_resource) for actually fetching content, leaving the agent to infer routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
select_coursesAIdempotent
After user approval, replace the local course selection with observed My Modules IDs. Empty courseIds clears selection without deleting files. Local change only.
| Name | Required | Description | Default |
|---|---|---|---|
| courseIds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes meaningfully beyond the annotations: it discloses that the operation is a replacement, that an empty array clears without deleting files, that it is a local-only change, and that user approval is required. The annotations already cover idempotency and destructiveHint=false; the only unexplained point is openWorldHint=true, which sits in mild tension with 'Local change only' but reasonably reads as 'no remote mutation' rather than a true conflict.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, each carrying a distinct fact (precondition, effect, edge case, scope), with the primary action front-loaded. No filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter, no-output-schema tool with annotations present, the description covers precondition, mutation semantics, empty-input behavior, and scope. It leaves unaddressed what happens with invalid or unmatched IDs and whether the new selection is returned, which would be the only remaining gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, yet the description explains what courseIds contains ('observed My Modules IDs') and what an empty array means, which is the key semantic the schema cannot convey. It stops short of noting constraints like the 200-item cap or positive-integer requirement, but those are already in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and target state: 'replace the local course selection with observed My Modules IDs'. The phrases 'Local change only' and 'without deleting files' distinguish it behaviorally from write/transfer siblings like sync_courses and download_resource, so an agent can tell what this mutates without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear precondition ('After user approval') and an explicit edge-case usage ('Empty courseIds clears selection'). It does not, however, name an alternative tool or state when to prefer this over sync_courses, so the routing guidance is incomplete rather than absent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sync_coursesAIdempotent
Perform one manual incremental sync for the locally approved courses. forceContentCheck bypasses ETag validation.
| Name | Required | Description | Default |
|---|---|---|---|
| forceContentCheck | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnly=false, idempotent=true, destructive=false, openWorld=true). The description adds real behavioral context beyond that: the sync is incremental (not full), is manual/one-shot, and operates on locally approved courses. The ETag bypass detail is the kind of hidden behavior an agent could not infer from the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler, and the core action is front-loaded ahead of the parameter detail. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-required-parameter, single-boolean tool with no output schema and annotations already declaring safety and idempotency, the description covers the essentials: what runs, on what scope, and what the flag does. Only the default behavior of forceContentCheck and any result semantics are unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and the single boolean parameter has no schema description, so the description carries the burden. 'forceContentCheck bypasses ETag validation' fully explains the parameter's effect, which is the key semantic an agent needs. It does not state the default when omitted, keeping it short of a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('sync') and resource ('courses'), scoped to 'locally approved courses' with 'one manual incremental sync'. This distinguishes it from list/select siblings by making clear it performs an actual sync rather than a listing or selection, though it never explicitly names the alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'Perform one manual incremental sync' implies this is an on-demand trigger rather than a scheduled/automatic sync, which gives some usage context. However, it does not say when an agent should invoke it versus check_connection, get_sync_settings, or confirm_setup, nor any prerequisite state.
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.
8 tool updates
v0.3.0- First observed
check_connection - First observed
confirm_setup - First observed
download_resource - First observed
get_sync_settings - First observed
list_courses - First observed
list_resources - First observed
select_courses - First observed
sync_courses
TDQS
Scored across 8 tools
Each tool targets a fairly distinct action: connectivity check, course/resource discovery, single download, bulk sync, settings read, course selection, and setup confirmation. Minor overlap exists between sync_courses and download_resource (both fetch content) and between select_courses and confirm_setup (both touch setup state), but descriptions clarify the boundaries.
All eight tools follow a consistent snake_case verb_noun pattern (check_connection, list_courses, download_resource, sync_courses, select_courses, confirm_setup, etc.). No mixing of conventions or vague verbs.
Eight tools is well-scoped for a Moodle course-sync server, with each tool earning its place across connection, discovery, sync, and setup concerns. No redundant or trivial tools pad the set.
The surface covers connection, discovery, download, sync, settings, and setup lifecycle well. Minor gaps like cleanup of old versions or removing downloaded materials exist, but core workflows are covered.
Maintenance
Related MCP Connectors
- scrapa.appOAuthapp.scrapa
Read web pages as markdown, search the web, list a site's URLs and run a real Chrome.
Manage your Canvas coursework with quick access to courses, assignments, and grades. Track upcomin…
Browser-local and CLI static evidence for deployed AI model artifacts.
Academic literature search, retrieval, and private library management on top of OpenAlex.
Related MCP Servers
- FlicenseNot gradedqualityBmaintenanceEnables browser-based login to approved UTN Moodle sites and read-only access to the user's profile, course list, and course activities via local Chromium automation.2-
- FlicenseAqualityBmaintenanceEnables local, read-only access to SMU's D2L Brightspace eLearn, allowing users to list courses, browse weekly modules and documents, search content, retrieve metadata, and download files after authenticating through Chrome.111-
- AlicenseAqualityCmaintenanceEnables automated interaction with the Moodle platform, allowing users to list courses and modules, retrieve assignment details, and download course files via browser automation.6ISC
- AlicenseAqualityAmaintenanceLets MCP clients access a student's ZHAW Moodle account to list courses, find and download learning materials, sync local copies, and track deadlines, assignments, and announcements.16MIT