npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

moodle-mcp

v0.2.0

Published

MCP server for Moodle — give Claude access to your courses, files, grades, and more. Build Obsidian study vaults from lecture notes in one command.

Readme

moodle-mcp

npm version npm downloads GitHub stars TypeScript Node Cloudflare Workers MIT License

Give Claude full access to your Moodle — courses, files, assignments, grades, quizzes, calendar, and more. Build Obsidian study vaults from your lecture notes in one command.

📦 moodle-mcp on npmnpx moodle-mcp

14 tools · 5 prompts · MCP Resources


Install

Step 1 — Get your Moodle token

See Getting Your Token below. You'll need this for any install method.

Step 2 — Pick your delivery mode

Option A — Local (zero hosting): Runs npx moodle-mcp on your machine each time your MCP client starts. No server, no cost, nothing to deploy.

Option B — Hosted (Cloudflare Worker): Deploy once, get a permanent URL. Your MCP client connects to the URL — no npx on the client side.

Deploy to Cloudflare Workers

After deploying, set MOODLE_URL and MOODLE_TOKEN as secrets in the CF dashboard or via:

npx wrangler secret put MOODLE_URL
npx wrangler secret put MOODLE_TOKEN
npm run deploy

Your URL will be https://moodle-mcp.<your-subdomain>.workers.dev.

Step 3 — Configure your MCP client

Config file:

  • Mac: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Option A — Local:

{
  "mcpServers": {
    "moodle": {
      "command": "npx",
      "args": ["-y", "moodle-mcp"],
      "env": {
        "MOODLE_URL": "https://moodle.yourschool.edu",
        "MOODLE_TOKEN": "your_token_here"
      }
    }
  }
}

Option B — Hosted:

{
  "mcpServers": {
    "moodle": {
      "url": "https://moodle-mcp.your-subdomain.workers.dev"
    }
  }
}

Option A — Local:

claude mcp add moodle npx -- -y moodle-mcp \
  -e MOODLE_URL=https://moodle.yourschool.edu \
  -e MOODLE_TOKEN=your_token_here

Option B — Hosted:

claude mcp add moodle --transport http https://moodle-mcp.your-subdomain.workers.dev

Config file: ~/.cursor/mcp.json (global) or .cursor/mcp.json (project)

Option A — Local:

{
  "mcpServers": {
    "moodle": {
      "command": "npx",
      "args": ["-y", "moodle-mcp"],
      "env": {
        "MOODLE_URL": "https://moodle.yourschool.edu",
        "MOODLE_TOKEN": "your_token_here"
      }
    }
  }
}

Option B — Hosted:

{
  "mcpServers": {
    "moodle": {
      "url": "https://moodle-mcp.your-subdomain.workers.dev"
    }
  }
}

Config file: .vscode/mcp.json in your project, or settings.json globally.

Option A — Local:

{
  "servers": {
    "moodle": {
      "command": "npx",
      "args": ["-y", "moodle-mcp"],
      "env": {
        "MOODLE_URL": "https://moodle.yourschool.edu",
        "MOODLE_TOKEN": "your_token_here"
      }
    }
  }
}

Option B — Hosted:

{
  "servers": {
    "moodle": {
      "url": "https://moodle-mcp.your-subdomain.workers.dev"
    }
  }
}

Config file: ~/.codeium/windsurf/mcp_config.json

Option A — Local:

{
  "mcpServers": {
    "moodle": {
      "command": "npx",
      "args": ["-y", "moodle-mcp"],
      "env": {
        "MOODLE_URL": "https://moodle.yourschool.edu",
        "MOODLE_TOKEN": "your_token_here"
      }
    }
  }
}

Option B — Hosted:

{
  "mcpServers": {
    "moodle": {
      "url": "https://moodle-mcp.your-subdomain.workers.dev"
    }
  }
}

Config file: ~/.config/zed/settings.json

Option A — Local:

{
  "context_servers": {
    "moodle": {
      "command": {
        "path": "npx",
        "args": ["-y", "moodle-mcp"],
        "env": {
          "MOODLE_URL": "https://moodle.yourschool.edu",
          "MOODLE_TOKEN": "your_token_here"
        }
      }
    }
  }
}

Option B — Hosted:

{
  "context_servers": {
    "moodle": {
      "url": "https://moodle-mcp.your-subdomain.workers.dev"
    }
  }
}

Config file: ~/.continue/config.json

Option A — Local:

{
  "mcpServers": [
    {
      "name": "moodle",
      "command": "npx",
      "args": ["-y", "moodle-mcp"],
      "env": {
        "MOODLE_URL": "https://moodle.yourschool.edu",
        "MOODLE_TOKEN": "your_token_here"
      }
    }
  ]
}

Option B — Hosted:

{
  "mcpServers": [
    {
      "name": "moodle",
      "url": "https://moodle-mcp.your-subdomain.workers.dev"
    }
  ]
}

Open the Cline sidebar in VS Code → MCP Servers → Add Server → paste the JSON:

Option A — Local:

{
  "moodle": {
    "command": "npx",
    "args": ["-y", "moodle-mcp"],
    "env": {
      "MOODLE_URL": "https://moodle.yourschool.edu",
      "MOODLE_TOKEN": "your_token_here"
    }
  }
}

Option B — Hosted:

{
  "moodle": {
    "url": "https://moodle-mcp.your-subdomain.workers.dev"
  }
}

OpenAI has announced MCP support for ChatGPT. Check the OpenAI blog for the release date. Once available, the hosted URL option (Option B) will work directly.


Getting Your Token

Option A — Moodle profile page (works everywhere)

  1. Log in to your school's Moodle in a browser
  2. Go to Profile → Security keys (URL: https://moodle.yourschool.edu/user/managetoken.php)
  3. Find the Moodle mobile web service token and copy it
  4. Set MOODLE_TOKEN=<token> in your MCP config

Option B — Get the token from

https://moodle.yourschool.edu/login/token.php?username=<YOURUSERNAME>&password=<YOURPASSWORD>&service=moodle_mobile_app

Option C — Username + password (not SSO schools)

If your school uses a regular username/password (not Microsoft/Google/SSO), you can skip the token step entirely:

"env": {
  "MOODLE_URL": "https://moodle.yourschool.edu",
  "MOODLE_USERNAME": "your_username",
  "MOODLE_PASSWORD": "your_password"
}

⚠️ SSO schools: If your school login page redirects to Microsoft, Google, or another identity provider, Option B won't work. Use Option A or C.

Option D — Extract from Moodle mobile app (SSO schools)

  1. Install the Moodle app on your phone and log in with SSO
  2. Go to App settings → About
  3. Tap the version number 5 times to enable developer mode
  4. Go to Developer options → Copy token and copy it
  5. Use that token as MOODLE_TOKEN in Option A

Tools

| Tool | Description | Params | |------|-------------|--------| | moodle_get_site_info | School name, Moodle version, which APIs are enabled | — | | moodle_list_courses | All your enrolled courses | — | | moodle_get_course | Sections and all activities in a course | courseId | | moodle_list_resources | Files and links grouped by section — returns opaque fileIds | courseId | | moodle_download_file | Read a file by its fileId — returns text for text/JSON/XML, base64 for PDFs/DOCX/images | fileId | | moodle_list_assignments | Assignments with due dates, grouped by section | courseId | | moodle_get_assignment | Submission status and grade feedback | assignmentId | | moodle_get_grades | Full grade report with categories and feedback | courseId | | moodle_get_calendar_events | Upcoming events across courses | courseId?, daysAhead? | | moodle_list_quizzes | Quizzes with time limits and open dates | courseId | | moodle_get_quiz_attempts | Your past attempt grades and states | quizId | | moodle_list_forums | Forum activities in a course | courseId | | moodle_get_forum_discussions | Recent discussions in a forum | forumId | | moodle_get_notifications | Recent notifications (grades, feedback, replies) | limit? |


Prompts

Use these in any MCP client that supports prompts (Claude Desktop, VS Code with Copilot, etc.):

| Prompt | Use case | Example | |--------|----------|---------| | summarize-course | Full course overview organized by section | /summarize-course courseId=42 | | whats-due | Prioritized due dates this week / next week | /whats-due or /whats-due courseId=42 | | build-study-notes | Build a linked Obsidian vault from course materials | /build-study-notes courseId=42 vaultPath=~/obsidian/finals | | exam-prep | Topic-by-topic study guide based on grades and quiz results | /exam-prep courseId=42 | | search-notes | Natural language search across all course files | /search-notes courseId=42 query="derivatives and limits" |


Obsidian Finals Prep

Turn your entire semester into a linked knowledge graph in one command.

Setup

  1. Install Obsidian (free, works on Mac/Windows/Linux)
  2. Create a new vault, e.g. ~/obsidian/finals
  3. Make sure moodle-mcp is connected to your MCP client

Build the vault

Use the /build-study-notes prompt in Claude Desktop:

/build-study-notes courseId=42 vaultPath=~/obsidian/finals

Or paste this directly into Claude:

Pull my [Course Name] (course ID 42), read all the lecture notes and slides,
and build a linked Obsidian vault at ~/obsidian/finals — one note per topic,
with [[wikilinks]] between related concepts, a MOC.md index, and tags for each section.

Claude will:

  1. Pull all your course sections, files, assignments, and grades
  2. Read each PDF and document directly via the MCP resources protocol
  3. Write one .md file per section with key concepts, definitions, and examples
  4. Add [[wikilinks]] between related terms across notes
  5. Create a MOC.md (Map of Content) index linking everything

See the graph

Option A — Obsidian Graph View (built-in, free)

  1. Open the vault in Obsidian
  2. Click Graph View (sidebar icon or Cmd+G)
  3. Your entire course appears as a knowledge graph — linked concepts cluster together, isolated topics stand out as things to review

Option B — Graphify (richer visual graph)

  1. Install Graphify — it reads the same .md files Obsidian writes
  2. Point it at your vault folder (~/obsidian/finals)
  3. Drag to explore connections; click any node to open the note and ask Claude about it

Both tools read the same Markdown vault — you can use both.

Knowledge Graph preview

Query the graph with Claude

Once the vault exists on disk, you can ask Claude Code or Claude Desktop questions like:

Explain the relationship between [[topic A]] and [[topic B]] in my course notes at ~/obsidian/finals
Based on my notes in ~/obsidian/finals, which topics do I need to review most before the exam?

Claude reads your .md files directly and reasons across the full linked graph.

Natural language search

Once the vault is built, you can ask Claude to find specific content:

/search-notes courseId=42 query="the central limit theorem and when to use it"

Claude will look through all your course materials, find the relevant files, read them, and synthesize a direct answer.


Compatibility

Some tools require your Moodle admin to enable specific web services. Run moodle_get_site_info to see which tools are available on your school's Moodle.

| Tool | Required | Notes | |------|----------|-------| | moodle_list_courses, moodle_get_course, moodle_list_resources, moodle_download_file | Always available | Core Moodle WS | | moodle_list_assignments, moodle_get_assignment | Admin must enable | mod_assign service | | moodle_get_grades | Admin must enable | gradereport_user service | | moodle_get_calendar_events | Usually available | core_calendar service | | moodle_list_quizzes, moodle_get_quiz_attempts | Admin may need to enable | mod_quiz service | | moodle_get_forum_discussions | Admin may need to enable | mod_forum service | | moodle_get_notifications | Admin may need to enable | message_popup service |

If a tool isn't available, it returns a helpful message explaining what your admin needs to enable — it won't crash the server.


Security & file access (v0.2)

Tool responses never contain raw or authenticated Moodle file URLs. Instead, moodle_list_resources returns opaque fileIds — AES-GCM-sealed envelopes bound to your Moodle account via the access token. Pass a fileId to moodle_download_file, and the server:

  1. Decrypts the fileId and checks it was issued to you (not another user).
  2. Re-checks with Moodle that the file is still visible to you (catches unenrolment, hidden modules, removed files).
  3. Refuses anything that isn't a pluginfile.php URL on your Moodle host (no SSRF relay).
  4. Fetches the file server-side with the token attached to the outbound request only — the token never appears in anything returned to the MCP client.
  5. Returns text for text/JSON/XML MIMEs, or the bytes as an MCP embedded resource (base64) for PDFs/DOCX/images.

This fixes the "domain not in the list of allowed fetch" error seen with Claude.ai's beta connectors when a chat tried to open a Moodle-hosted PDF: Claude no longer has to fetch anything cross-origin, because the content arrives inside the MCP response.

Limits: 25 MB per file by default (override with MOODLE_MCP_MAX_FILE_MB=<positive number>). File IDs expire after 24 hours. Rotating your Moodle token invalidates all outstanding IDs.


Contributing

Issues and PRs welcome. Open an issue first for large changes.

MIT License — © 2026 Alexandre Ribeiro