Nexus MCP
A read-only MCP server for Union College's Nexus (Moodle 4.5, hosted by Open LMS). Connect it to Claude and ask:
"What's due this week?" · "What's overdue?" · "Did I submit Lab 3?" · "What's my grade in CSC-385?" · "What changed in my courses today?" · "Find the lecture notes on shaders." · "Give me my daily briefing." · "What should I work on next?"
It uses Moodle's official web-service API with your own student token. It never scrapes the website and never writes anything. Unofficial: not affiliated with or endorsed by Union College or Open LMS.
Tools
| Area | Tools |
|---|---|
| Courses | list_courses (active/past/future, term, teacher), get_course (sections, materials, activities), nexus_status |
| Assignments | upcoming_assignments, overdue_assignments, assignment_details, submission_status |
| Grades | current_grades, course_grade, grade_history |
| Materials | search_course_materials, get_material (pages, books, links, text files; PDFs with the pdf extra) |
| Calendar | upcoming_events |
| Announcements | recent_announcements, course_updates |
| Intelligence | daily_briefing, weekly_briefing, workload_analysis, what_should_i_do_next |
Times are in your academic timezone (America/New_York). Errors carry a code: NEXUS_AUTH_ERROR, NEXUS_PERMISSION_ERROR, NEXUS_UNSUPPORTED, NEXUS_RESOURCE_NOT_FOUND, NEXUS_API_ERROR.
Setup (2 minutes)
You need uv (one-line installer below) and a Union student account.
curl -LsSf https://astral.sh/uv/install.sh | sh # skip if you already have uv
uvx union-nexus-mcp setup
setup does everything: it opens Nexus in your browser for the Okta sign-in, registers the server with every AI client it finds on your machine (Claude Desktop, Claude Code, Cursor, Windsurf, VS Code, Gemini CLI, Codex CLI), and runs the connection test. Restart the client and ask it what's due.
On the Nexus page that says "Your registration has been confirmed", click "Click here if the app does not open automatically." and allow Open Nexus MCP Login. That hands the token to the terminal; it is stored in your OS keyring. No password is ever typed into this tool. If no prompt appears, right-click that link → Copy Link Address → paste it into the terminal. Details: docs/AUTHENTICATION.md.
Pick clients explicitly with uvx union-nexus-mcp setup --client claude-desktop --client cursor, or add a client later with uvx union-nexus-mcp install --client <key> (clients lists the keys). install --dry-run prints the snippet if you'd rather edit a config by hand:
{ "mcpServers": { "nexus": { "command": "uvx", "args": ["union-nexus-mcp", "serve"] } } }
GUI apps often can't see uvx on their PATH; install writes the absolute path for you (which uvx if editing manually).
Commands
uvx union-nexus-mcp setup # login + client config + test
uvx union-nexus-mcp login # sign in again (token expired / new machine)
uvx union-nexus-mcp test-connection # reachability, auth, identity, capability matrix
uvx union-nexus-mcp list-courses # --all includes past terms
uvx union-nexus-mcp install --client cursor --dry-run
uvx union-nexus-mcp logout
Working from a clone instead: uv sync, then uv run nexus-mcp <command>; setup/install then register the checkout itself. uv run pytest runs the mocked test-suite; uv run scripts/test_moodle_api.py --all is the verbose API diagnostic. Releases: docs/RELEASING.md.
Configuration
Copy .env.example to .env if you need to change anything. Defaults target nexus.union.edu. Notable keys: NEXUS_TOKEN (use an explicit token), NEXUS_TOKEN_STORAGE=keyring|file, NEXUS_TIMEZONE, and the NEXUS_CACHE_*_TTL lifetimes. Cached grade and submission data is always labelled cached with an as_of time.
Security
- Read-only: no submission, grading, posting, messaging or enrolment functions exist in this codebase.
- The only secret is your Moodle token: Keychain (or a 0600 file), sent in POST bodies, never logged.
.envand credential files are git-ignored. Revoke the token on Nexus under Preferences → Security keys.
Responsible use
- Personal use only, on your own account, reading your own data. Union's Acceptable Use Policy applies; access to a system is not by itself authorization, so ask ITS if you want that confirmed.
- Never share your token or credential file. Revoke it on Nexus (Preferences → Security keys) if in doubt.
- What your AI client does with course content is governed by each course's AI policy and Union's Honor Code. Use this for planning and finding materials; don't use it to have an AI complete graded work unless the instructor allows it.
- Course materials belong to instructors and publishers. Don't redistribute them.
Limitations
- Login needs you at the keyboard (Okta/MFA). If Union expires the token, run
loginagain. - Moodle has no grade-history API;
grade_historyreturns current grades with dates and says so. - Material search is a text match over titles, filenames, descriptions and sections. PDF text needs
uv sync --extra pdf. - Third-party activities (Turnitin, H5P, LTI) appear as modules without readable content.
- Non-academic enrolments (trainings, campus resources) never end, so they count as "in progress"; use
academic_onlyto hide them.
More: docs/API_FEASIBILITY.md (what Nexus exposes and why) · docs/ARCHITECTURE.md.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file union_nexus_mcp-0.1.0.tar.gz.
File metadata
- Download URL: union_nexus_mcp-0.1.0.tar.gz
- Upload date:
- Size: 160.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
91740ba3d78d37a8b1759b15e6ccdef14d72cf9f7bf6e34e03b0e2a5c5070ab9
|
|
| MD5 |
5ae24c5c80bb33a29e5b7c37343e27b4
|
|
| BLAKE2b-256 |
9827995ef9bacdd4a5f1d2113b731d6c0ebcc23c1e2fa2945966325ac36c1e7d
|
Provenance
The following attestation bundles were made for union_nexus_mcp-0.1.0.tar.gz:
Publisher:
publish.yml on linboxin/nexus-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
union_nexus_mcp-0.1.0.tar.gz -
Subject digest:
91740ba3d78d37a8b1759b15e6ccdef14d72cf9f7bf6e34e03b0e2a5c5070ab9 - Sigstore transparency entry: 2803491071
- Sigstore integration time:
-
Permalink:
linboxin/nexus-mcp@1943241b7f25e40868571dae15433333f774d4fa -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/linboxin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1943241b7f25e40868571dae15433333f774d4fa -
Trigger Event:
push
-
Statement type:
File details
Details for the file union_nexus_mcp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: union_nexus_mcp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 77.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
515bfa280c8804d1542d27e41b40059e6280e3f6cef41b340db482602c57e06b
|
|
| MD5 |
5f579b367cacf8399044bbbc14f53915
|
|
| BLAKE2b-256 |
1e9192ab9cfac0ed483509f4aeb9f2ccb12ec90b4ee6f75d1911c699e86c84fb
|
Provenance
The following attestation bundles were made for union_nexus_mcp-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on linboxin/nexus-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
union_nexus_mcp-0.1.0-py3-none-any.whl -
Subject digest:
515bfa280c8804d1542d27e41b40059e6280e3f6cef41b340db482602c57e06b - Sigstore transparency entry: 2803491185
- Sigstore integration time:
-
Permalink:
linboxin/nexus-mcp@1943241b7f25e40868571dae15433333f774d4fa -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/linboxin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1943241b7f25e40868571dae15433333f774d4fa -
Trigger Event:
push
-
Statement type: