Skip to main content
Glama

moodle-watch

Give your AI agents a memory of your Moodle.

Moodle can tell an agent what exists. It cannot tell it what is new to you, what changed since you last looked, or what you have already dealt with. Every Moodle MCP server out there is a stateless wrapper around the same API: ask it twice, get the same answer twice, learn nothing.

moodle-watch keeps a ledger. That one difference changes what an agent can do.


Why this matters if you work with agents

A stateless tool makes your agent a search box. You ask, it fetches, it forgets. You are still the one who remembers what you already read, notices that a lecturer silently re-uploaded a PDF, and keeps the mental list of what is left. That bookkeeping is the actual work, and no amount of prompting removes it.

With a ledger, the agent holds all three:

It can open with news instead of waiting for a question. whats_new is a delta, not a dump. "Since Tuesday: four new files in two courses, one deadline moved a week earlier, and a course you have never triaged just appeared."

It stops re-reading what it already read. Every item carries its handling state. A nightly agent can ask for the backlog, work through it, call mark_handled with a link to whatever it produced, and pick up exactly where it left off tomorrow. No "have I seen this already" heuristics, no re-summarising the same lecture four times, no burned context.

It notices the thing you would have missed. A lecturer replaces a slide deck two days before the exam. moodle-dl overwrites the file. Moodle sends nothing. Here, the item gets a new revision, and because handling is recorded per revision, it returns to your backlog by itself. You never diff anything by hand again.

A swarm can divide the work. mark_handled takes a by field. Several agents, or an agent and a human, can share one queue without stepping on each other, and history shows who did what to which revision.

It never decides behind your back. A newly discovered course lands in pending: not watched, not ignored, surfaced on every call until somebody arbitrates. Every course carries the rule that decided it, so "why is this not showing up" always has an answer. Silent whitelists are how you find out in March that a module was never being tracked.

And it is read-only against Moodle by construction, not by instruction. The web-service allowlist lives in code; submitting, grading and posting are unreachable. You can hand this to an autonomous agent without wondering what it might click.


Related MCP server: Claude Synergy

How it works

It does not reimplement moodle-dl. It imports it.

moodle-dl      what exists, what changed     mods, LTI extractors, yt-dlp
moodle-watch   since when, what you did      the clock, the ledger, MCP

Every course module type, every LTI video extractor, yt-dlp, years of awkward real-world cases: all of it comes along. moodle-watch adds the two things moodle-dl does not have.

Because moodle-dl records what it has, not when it got it. Its time_stamp column is written only on modification paths; a fresh insert leaves the default. On a real mirror of 2210 rows, and again on a fresh one of 95, every single value is 0. And once its notified flag is raised, the seen / not-seen distinction is gone for good.

So the ledger records three things:

first_seen

our own clock, on every revision

handled

who did what with an item, per revision

course_policy

why a course is watched or not, and which rule decided

Handling is keyed on moodle-dl's file_id, and moodle-dl inserts a new row whenever a file changes. The "it comes back to your backlog" behaviour is not a feature anyone maintains; it is a property of the schema.

Nothing is ever deleted. A disappearance is recorded as an observation.


Install

pipx install "moodle-watch[documents]"

You need a moodle-dl mirror directory. If you do not have one:

moodle-dl --init --sso --path ~/Moodle     # or --init -u USER -pw PASS

Then point moodle-watch at it and run a first cycle:

export MOODLE_WATCH_MIRROR=~/Moodle
moodle-watch run
moodle-watch courses

The first run discovers every course you are enrolled in and puts them all in pending. Decide with a policy file, or one tool call per course.

Tools

Tool

Answers

whats_new

what appeared, changed or vanished since last_run, 7d, a date

courses

what is watched, what is pending, and the rule that decided

deadlines

what is due, and whether a due date moved

backlog

everything not handled yet, oldest first

course_tree

sections and modules, each annotated with its state

search

accent-insensitive full text over course, section, module, file names

read_document

the text of one file, from the mirror or through the token

history

every revision of an item, and everything done with it

mark_handled

record that items were dealt with

set_course_policy

answer a pending course

sync / sync_status

start a cycle in the background, poll it

Watching and mirroring are the same code with a different argument: moodle-watch run detects only, moodle-watch run --fetch also downloads, forums and videos included.

The policy

~/.config/moodle-watch/policy.toml, written for you on first run. Rules are evaluated in order, first match wins, like a firewall.

default = "ask"          # ask | watch | ignore

[[rule]]
match  = { startdate_after = "2026-08-01" }   # this year only
action = "watch"

[[rule]]
match  = { shortname = "*2025*" }
action = "ignore"

[exclude]
extensions  = ["mp4"]
larger_than = "500MB"
filenames   = ["department-logo.png"]    # moodle-dl cannot filter by name

Criteria: course, shortname, fullname, startdate_after, startdate_before. The [exclude] block is written into moodle-dl's own config.json, so there is one source of truth. A decision you make by hand is never overwritten by a rule afterwards.

Running it

Over stdio, for a local client:

{ "mcpServers": { "moodle-watch": {
    "command": "moodle-watch-server",
    "env": { "MOODLE_WATCH_MIRROR": "/home/you/Moodle" } } } }

Over HTTP, behind your own reverse proxy:

MOODLE_WATCH_HOSTS=moodle.example.org moodle-watch-server --http

It binds loopback only. MOODLE_WATCH_HOSTS feeds the SDK's DNS-rebinding guard, which validates the Host header; the public name must be listed there or the proxy gets a 421. See docs/deployment.md and the templates in deploy/.

Environment

Variable

Meaning

MOODLE_WATCH_MIRROR

the moodle-dl directory. Required.

MOODLE_WATCH_DB

ledger path. Default: <mirror>/moodle_watch.db

MOODLE_WATCH_POLICY

policy file. Default: ~/.config/moodle-watch/policy.toml

MOODLE_WATCH_PORT

HTTP port. Default: 3041

MOODLE_WATCH_HOSTS

comma-separated public host names

MOODLE_WATCH_BASE_URL, MOODLE_WATCH_SEGMENT

only for doctor --remote

No secret lives in this repository. The Moodle token stays in the mirror's config.json, where moodle-dl put it.

Diagnosing

moodle-watch doctor              # layers 1 to 3
moodle-watch doctor --remote     # and the public door

Four layers, deepest to most exposed. Layer 3 is not a health check: it opens a real MCP session and asserts the answers are coherent with each other. A server returning 200 while reporting empty courses is not a server that works. The output never prints the secret URL segment.

When the token expires

Moodle web-service tokens expire, and an SSO-issued one is renewed by hand:

moodle-dl -nt -sso --path ~/Moodle

moodle-watch names this failure mode rather than dying quietly: the tools return a token_expired payload carrying that exact command, doctor gives it its own line, and a failed run records it in the ledger.


Honest status

This works. It is also vibe-coded. It was built in one sitting, with an AI, by someone who is a teacher and not a software maintainer. It is verified rather than merely hoped for: every claim above was checked against a live Moodle 4.5 instance, there are 40 tests, and the load-bearing behaviours (idempotence, revisions returning to the backlog, nothing ever deleted, the Host guard) each have one. Two real design bugs were caught by those tests and fixed. But there is no roadmap, no support, and no promise of a second sitting.

One thing in particular deserves a warning: moodle-watch drives moodle-dl through internal classes of a command-line application, which carry no stability guarantee. That is why the version is pinned, why every import is confined to engine.py, and why doctor asserts each call site still exists. It is a deliberate and contained bet, not an oversight, but it is a bet.

So: shared gladly, take it, fork it, do whatever you like with it. If you think the idea is good, the right move is to maintain your own copy, not to wait on this one. Issues may go unanswered. A fork that outgrows this repo would be a happy outcome, not a slight.

Licence

GPL-3.0-or-later, inherited from moodle-dl, which is imported rather than reimplemented.

Available Tools

12 tools
backlogB

Everything not handled yet, oldest first. The work queue.

An item leaves this list when mark_handled records a read, ingested or ignored action for it. Marking it todo keeps it here on purpose.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
courseNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.3/5.0
Behavior4/5

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

With no annotations, the description carries the burden of behavioral disclosure, and it does well: it explains list membership, ordering, and the lifecycle rules around `mark_handled` actions. It doesn't mention potential side effects, but this is clearly a read-only list tool and no mutation is implied.

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 concise, front-loaded, and every sentence adds meaningful context. The first sentence establishes the core purpose, and the second clarifies the lifecycle behavior without any wasted words.

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?

The core backlog concept is clear, but the description omits any explanation of the two input parameters, which are both undocumented in the schema as well. An agent cannot be fully confident about how filtering by course or limiting the list behaves, so the description is not complete enough for correct invocation.

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

Parameters1/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 for the undocumented `limit` and `course` parameters. It does not mention either parameter, nor how they affect the results. The schema only provides names and defaults, leaving the agent to guess that `course` filters and `limit` caps the output.

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 clearly identifies the resource as the work queue/backlog and states that it contains unhandled items ordered oldest first. It does not use an explicit verb like 'list' or 'retrieve,' and it doesn't directly contrast itself with sibling tools, but the intent is unmistakable.

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 when to use this tool: to see unhandled work, since items leave when `mark_handled` records a `read`, `ingested`, or `ignored` action. However, it never explicitly says when to use it versus alternatives like `history`, `whats_new`, or `deadlines`, leaving that to inference.

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

coursesA

List watched courses, with unhandled counts and the next deadline.

Each course carries the rule that decided its state, so "why does this course not show up" always has an answer. state is one of watch, ignore, or pending; a pending course has never been arbitrated by anyone.

ParametersJSON Schema
NameRequiredDescriptionDefault
include_ignoredNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior3/5

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

With no annotations provided, the description carries the full burden. It discloses the state values and the meaning of 'pending', which is helpful, but it does not explicitly state whether the operation is read-only, nor does it describe any side effects, pagination, or error behavior. The 'List' verb implies read-only, but it is not stated explicitly.

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 concise and front-loaded with the main action, followed by valuable context about state and rule. Every sentence adds meaning, with no filler. The structure is clear and easy to parse.

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?

Given the tool's simplicity and the presence of an output schema, the description covers the core purpose and state semantics. However, it omits any explanation of the 'include_ignored' parameter, which is a gap. It also doesn't mention any ordering or pagination, but that may be covered by the output schema.

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 only parameter, 'include_ignored', is a boolean with a default of false, and its name is self-explanatory. However, the description does not mention it at all, and since the schema has no description coverage, the agent must infer its meaning from the name alone. This leaves ambiguity about how it interacts with the 'watched courses' filter.

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 verb 'list' and resource 'watched courses', with additional details about unhandled counts and next deadline. This distinguishes it from siblings like 'deadlines' and 'backlog' by specifying the scope as watched courses. The mention of 'rule' and 'state' adds depth to what the tool provides.

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 does not explicitly state when to use this tool versus alternatives, but it implies usage for understanding course states via the 'rule' and 'state' fields. It does not name any sibling tools or provide exclusions, so the guidance is only implied. This is acceptable but not explicit.

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

course_treeA

Sections and modules of one course, each item annotated with its state.

Use this to navigate a course rather than to search it. For a whole-space lookup by name, use search.

ParametersJSON Schema
NameRequiredDescriptionDefault
courseYes
only_unhandledNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior3/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It communicates that each returned item has a state and implies read-only navigation, but it does not explicitly state that the operation is non-mutating, how state is represented, or how errors/edge cases behave. Adequate for a simple navigation tool, but not rich.

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

Conciseness5/5

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

The description is two sentences with no filler. It front-loads the core purpose and then immediately provides routing to the alternative. Every sentence earns its place.

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 simple two-parameter tool with an output schema present, the description covers the core navigation purpose and sibling distinction. However, it leaves a meaningful gap around `only_unhandled`, which an agent would need to understand to invoke the tool correctly in all cases.

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 the description does not explain either parameter. 'Course' is vaguely implied by 'one course', but the meaning of `only_unhandled` and the expected format of `course` are completely absent. The description adds almost no value beyond the raw schema names.

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 identifies the resource: 'Sections and modules of one course', and clarifies it is a navigation tool rather than a search tool. It distinguishes itself from the sibling `search` by contrasting course-tree navigation with whole-space lookup.

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

Usage Guidelines5/5

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

The description gives explicit when-to-use guidance: 'Use this to navigate a course rather than to search it' and names the specific alternative for the opposite case: 'For a whole-space lookup by name, use `search`.' This fully routes the agent to the correct tool.

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

deadlinesC

Upcoming deadlines, soonest first.

moved is true when the due date changed since it was first seen, and moved_from gives the previous one. No Moodle API reports this; it is known only because the ledger saw the earlier value.

ParametersJSON Schema
NameRequiredDescriptionDefault
withinNo30d
include_pastNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

C2.9/5.0
Behavior3/5

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

With no annotations, the description must carry the burden of behavioral disclosure. It adds context about the 'moved' field and its origin (ledger observation), which is useful, but it does not state whether the operation is read-only, has side effects, or any other behavioral traits. Partial transparency.

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 sentences, with the main purpose front-loaded in the first sentence. It is concise without waste, and the additional note about 'moved' is clearly separated.

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?

While an output schema exists (so return values need not be explained), the description omits any explanation of the input parameters, which are non-trivial with defaults. This leaves a significant gap for correct invocation, making the description incomplete for a tool with these context signals.

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

Parameters1/5

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

Schema description coverage is 0%, and the description does not mention either parameter ('within' or 'include_past'). An agent receives no explanation of what these parameters mean or how to use them, so the description fails to compensate for the schema 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 description states the tool lists upcoming deadlines sorted soonest first, which is a clear verb and resource. It does not explicitly differentiate from siblings like backlog or whats_new, but the purpose is specific enough that an agent can infer its use.

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 on when to use this tool versus alternatives. The description does not mention scenarios, exclusions, or prerequisites, leaving the agent to guess whether this is the right choice for a given request.

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

historyA

Every revision of one item, and everything that was done with it.

item_key comes from any other tool's output. Revisions follow the file across changes and moves, so this is the honest answer to "has this been updated since I read it".

ParametersJSON Schema
NameRequiredDescriptionDefault
item_keyYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It reveals a non-obvious behavior: revisions follow the item across changes and moves, so the history stays accurate over time. This is genuinely useful context beyond what the schema or tool name communicates.

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 sentences with no filler. The core purpose is front-loaded, and the second sentence earns its place by explaining how to obtain the parameter and why the tool is valuable for a common question.

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 tool with an output schema, the description provides enough to invoke it correctly: what it returns, where the parameter comes from, and its key tracking behavior. It could be more explicit about ordering, pagination, or read-only guarantees, but those are not critical given the output schema and low complexity.

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 provides only a name and type for item_key with 0% description coverage. The description adds useful provenance—'item_key comes from any other tool's output'—which tells an agent where to source the value. However, it does not clarify the format, constraints, or what qualifies as a valid item_key, so it only partially compensates for the schema 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 description clearly identifies the resource as the revision history of a single item ('Every revision of one item'), which is distinct from sibling tools like read_document or search. It lacks an explicit action verb like 'retrieves' or 'lists', and its phrasing is more definitional than operational, so it stops 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 Guidelines4/5

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

The description gives concrete guidance: item_key should be obtained from any other tool's output, and this is positioned as the reliable way to answer 'has this been updated since I read it'. It does not explicitly name alternative tools or list exclusion criteria, but the use case and prerequisite are clear.

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

mark_handledA

Record that these items were dealt with. Writes the ledger, not Moodle.

action is one of read, ingested, ignored, todo. by is free text naming who did it, for example nightly or alice. note is the right place for a link to whatever was produced.

Handling is per revision: if the file changes later, it returns to the backlog on its own.

ParametersJSON Schema
NameRequiredDescriptionDefault
byYes
noteNo
actionYes
file_idsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations, the description carries the full burden. It clearly discloses a write operation ('Writes the ledger'), states it does not affect Moodle, and explains the non-obvious per-revision behavior: if the file changes later, it returns to the backlog. It also gives guidance on `note`. It stops short of idempotency or error behavior, but the key side effects are explicit.

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 entire description is three sentences, each earning its place: purpose/scope, parameter semantics, and the per-revision behavioral caveat. No filler, front-loaded purpose, and markdown formatting improves scannability.

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 complexity (4 params, 0% schema descriptions, no annotations), the description covers the essential contract: what it does, the write target, parameter formats, and a surprising behavioral rule. It doesn't address idempotency or prerequisites, but the presence of an output schema reduces the need to document return values, leaving few critical gaps.

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 must compensate. It defines `action` as one of read, ingested, ignored, todo; explains `by` as free text with examples; and positions `note` as the place for a link. `file_ids` is only implied via 'these items,' but the first sentence ties it to the target items, which is sufficient given the bare 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 begins with a specific verb and resource: 'Record that these items were dealt with.' It further narrows scope with 'Writes the ledger, not Moodle,' which distinguishes it from any Moodle-facing sibling tools. Enumeration of the `action` values adds concrete definition.

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—use this when items have been dealt with—and the per-revision caveat gives context, but it never names an alternative tool or explicit when-not-to-use condition. The 'not Moodle' line hints at an exclusion without offering a replacement tool, leaving some routing to inference.

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

read_documentA

Extract the text of one file, by its file_id.

Reads the local copy when the mirror has it, and downloads through the Moodle token otherwise. pages selects PDF pages, for example 1-5 or 3. Media files return their metadata and no text: a video is not summarised here.

ParametersJSON Schema
NameRequiredDescriptionDefault
pagesNo
file_idYes
max_charsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

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

With no annotations provided, the description carries the behavioral burden and does it well: it discloses the local-mirror vs Moodle-download fallback, PDF page selection, and the media-file metadata-only behavior. This gives agents meaningful expectations beyond 'read a file,' though edge cases like truncation or auth are not covered.

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 well-structured: purpose first, then source behavior, page selection, and media limitation. Every sentence adds useful information without redundancy or fluff. It is easy to scan and fully digest.

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 and no annotations are provided, the description supplies the key behavioral context needed for correct invocation: single-file scope, page range selection, and media file handling. Minor omissions like `max_chars` semantics are acceptable because the parameter name and default carry that meaning.

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 must compensate. It clearly explains `file_id` and `pages` with examples ('1-5' or '3'), but it does not mention `max_chars` at all. The name is self-explanatory, but the description partially fills the gap rather than completely covering all 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?

The description opens with a specific verb and resource: 'Extract the text of one file, by its `file_id`.' This clearly states the tool's scope and differentiates it from siblings like search or courses. The focus on a single file by ID leaves no ambiguity about the operation.

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 when to use the tool: when you need the text of a specific file. It also provides useful usage context for `pages` and warns that media files return no text. However, it does not explicitly mention alternatives or state when not to use this tool, so the guidance relies on inference.

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

set_course_policyA

Decide whether a course is watched. Use this to answer a pending course.

state is watch, ignore or pending. A decision made with a by other than policy is never overwritten by a policy rule afterwards, so the user's answer sticks.

ParametersJSON Schema
NameRequiredDescriptionDefault
byYes
stateYes
reasonNo
course_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior3/5

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

No annotations are provided, so the description must carry behavioral disclosure. It does reveal a meaningful rule: decisions made with a 'by' other than 'policy' are never overwritten by a policy rule. However, it does not discuss side effects, response behavior, or whether an existing non-policy decision can be changed directly.

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

Conciseness5/5

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

Three short sentences, front-loaded with purpose, then concrete parameter semantics and an important behavioral caveat. Every sentence earns its place with 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 4-parameter mutation tool with no annotations and no enums, the description covers the usage trigger, state values, and the key overwrite rule. The optional reason parameter is not explained, but the required parameters are substantially addressed and an output schema exists, making it mostly complete.

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 description adds real meaning by enumerating state values (watch, ignore, pending) and explaining the effect of 'by' versus 'policy'. Since schema description coverage is 0%, this helps, but course_id and especially the optional reason parameter receive no semantic explanation.

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

Purpose4/5

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

The description states a concrete action ('Decide whether a course is watched') and a target resource, and adds 'Use this to answer a pending course' to clarify intent. It does not explicitly contrast with sibling tools like mark_handled, so it stops short of full differentiation.

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 a clear trigger: use this tool when there is a pending course to answer. It does not name alternatives or exclusions, but the usage context is explicit enough for an agent to select the tool.

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

syncA

Start a watch cycle in the background and return at once.

A full cycle takes minutes, so it never runs inside a tool call. Poll sync_status for the result. With download true it also fetches files, which takes considerably longer.

ParametersJSON Schema
NameRequiredDescriptionDefault
downloadNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

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

With no annotations, the description carries the full behavioral burden and does well by disclosing asynchronous execution, immediate return, background duration, and the added file-fetching behavior when download is true. It does not mention potential side effects or permission requirements, but the core asynchronous trait is clearly communicated.

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 tightly written: the first sentence front-loads the core behavior, and the second adds necessary temporal and parameter context. Every sentence earns its place with no redundant or filler wording.

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 single-optional-parameter async tool, the description covers what the tool does, when it returns, how long work takes, how to retrieve results, and the parameter's effect. The presence of an output schema means return-value details need not be repeated, and the guidance to poll sync_status closes the loop for the agent.

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 must add meaning beyond the bare boolean type and title. It explicitly explains that download=true triggers file fetching and longer runtime, implying the default is metadata-only sync. This compensates for the schema gap, though it could have also stated what happens when download is 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 uses a specific verb-resource pair ('Start a watch cycle') and clearly states that the tool returns immediately after launching background work. It also distinguishes itself from the sibling sync_status by framing sync as the initiation step and sync_status as the polling step.

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

Usage Guidelines5/5

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

The description explicitly tells the agent when to expect completion ('takes minutes', 'never runs inside a tool call') and directs it to poll sync_status for the result. It also explains the conditional usage of the download parameter and its time impact, leaving no ambiguity about invocation flow.

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

sync_statusA

The state of the most recent sync, running or finished.

finished null means it is still going. A non-null error starting with token_expired means the Moodle token must be renewed by hand; report the command rather than retrying.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.9/5.0
Behavior4/5

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

With no annotations provided, the description carries the full behavioral burden and delivers meaningfully: it documents that 'finished: null' means the sync is still running, and that a 'token_expired'-prefixed error requires manual token renewal instead of a retry. This goes beyond what an agent could infer from the schema, though it could also mention auth expectations or side-effect-free guarantees.

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 dense paragraphs with no filler: the first sentence front-loads the purpose, and the second adds only the interpretive semantics that an agent actually needs. 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?

For a zero-parameter status query with an output schema present, the description covers the essential return-value interpretation and the critical error case. The only real gap is that it doesn't situate the check within the sync workflow, e.g., by saying to consult this before deciding to retry or trigger a sync.

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 description correctly adds nothing here; the baseline of 4 for a parameterless tool applies.

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

Purpose4/5

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

States clearly that the tool reports the state of the most recent sync ('running or finished'), which adds specificity beyond the bare name. However, it is a noun phrase rather than a verb+resource and does not explicitly differentiate itself from the sibling 'sync' tool, though the read-vs-trigger distinction is fairly inferable.

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?

Provides actionable guidance on interpreting results and handling the 'token_expired' error ('report the command rather than retrying'). But it never says when to call this tool versus alternatives such as 'sync' or 'history' — the selection context is left implicit, and the guidance is about reacting to output rather than choosing the tool.

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

whats_newA

What appeared, changed or vanished since since. The main tool.

since accepts last_run (the default), all, a duration like 7d or 48h, an ISO date like 2026-09-01, or an epoch integer.

Already handled items are hidden unless include_handled is true: the question asked is what remains, not what happened. The reply also carries deadline changes (a moved_from means the due date was shifted) and pending_courses, which need the user's arbitration.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
sinceNolast_run
courseNo
include_handledNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden and delivers: it reveals that handled items are hidden unless `include_handled` is true, that the reply carries deadline shifts (`moved_from`) and `pending_courses` needing user arbitration, and it documents the accepted forms of `since`. It does not explain `course`/`limit` behavior or explicitly state this is a read-only operation, but those are secondary gaps here.

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

Conciseness5/5

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

Three short paragraphs, each earning its place: a front-loaded purpose sentence, the critical `since` grammar, and the handled-items/reply semantics. No filler or repetition; dense but readable.

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?

An output schema exists, so return shape is covered elsewhere, and the description usefully adds semantics for `moved_from` and `pending_courses`. But with 0% schema coverage and no annotations, the unexplained `course` and `limit` parameters are a notable gap for a tool positioned as 'the main tool'.

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

Parameters3/5

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

Schema description coverage is 0%, so the description must compensate. It richly documents `since` (full grammar: `last_run`, `all`, durations like `7d`/`48h`, ISO dates, epoch integers) and clarifies the intent of `include_handled`, but `limit` and `course` receive no explanation, leaving half the parameters under-documented.

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

Purpose4/5

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

The description states a specific purpose: reporting what 'appeared, changed or vanished since `since`', a change-detection/diff view that is distinct from siblings like `history`, `backlog`, or `search`. Calling itself 'The main tool' signals its role as the primary entry point, though it does not explicitly name the siblings it is not.

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 main tool' implies this is the default starting point, and the 'what remains, not what happened' framing explains when the tool fits (current open/relevant changes vs. history). However, there are no explicit exclusions or redirects to alternatives such as `history`, `deadlines`, or `search`, so an agent must infer when to choose a sibling instead.

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. 12 tool updatesv0.1.0
    • First observedbacklog
    • First observedcourse_tree
    • First observedcourses
    • First observeddeadlines
    • First observedhistory
    • First observedmark_handled
    • First observedread_document
    • First observedsearch
    • First observedset_course_policy
    • First observedsync
    • First observedsync_status
    • First observedwhats_new

TDQS

A3.6/5.0

Scored across 12 tools

Disambiguation4/5

The tools are mostly distinct in purpose—listing courses, diffing changes, showing deadlines, searching, reading, handling, and syncing. A few overlaps exist, such as whats_new also surfacing deadline changes and pending courses, and backlog overlapping with whats_new's unhandled view, but the descriptions are explicit enough to resolve ambiguity.

Naming Consistency3/5

All names are lowercase and use underscores, but the convention is mixed: plural nouns (courses, deadlines), bare verbs (search, sync), and verb+noun compounds (read_document, mark_handled, set_course_policy) coexist. The names are readable but not predictable from a single pattern.

Tool Count5/5

Twelve tools is well-scoped for a Moodle change-watching service, covering distinct phases from course policy and syncing to change discovery, reading, history, and handling. Each tool earns its place without obvious bloat or trivial additions.

Completeness4/5

The core workflow is covered end-to-end: sync, see what changed, inspect course structure and content, read files, mark items handled, and set course policy. Minor workarounds exist, such as no explicit undo of a handling action, but they do not block the main use case.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Change tracking for AI-era codebases. AI agents call it to log structured change events (entity + diff + reasoning) before the session ends, then query history with diff, blame, history, changeset, and search. Captures the intent that would otherwise evaporate.
    8
    433 PyPI
    23
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for structured reflection and self-modeling over Everlog diary exports, enabling agents to query local diary evidence and maintain versioned artifacts of threads, moments, beliefs, and decisions.
    MIT