icampus-mcp
Read-only access to your own SKKU iCampus data over MCP — courses, deadlines/tasks, announcements, lectures and grades — plus the ability to kick off a fresh sync.
sync_status— data freshness per dataset, whether recent runs worked, and any login problem; call it first when answers look stale or empty.list_courses— this term's courses: id, code, name, instructors, current grade if visible.list_tasks— merged to-do list (iCampus remaining list + Canvas submission status + lecture completion), soonest first, undated items last; filters:course,kind,due_within_days(14),past_days,include_done,limit.list_announcements— recent announcements (title, date, author, read state, preview), newest first; filters:course,since_days(14),unread_only.read_announcement— full text of one announcement by its numeric id.list_lectures— lecture videos/materials with completion and attendance, soonest deadline first; default shows open, incomplete, not-yet-expired items; filters:course,week,kind,incomplete_only,include_upcoming,include_overdue,include_attendance,limit.get_grades— course totals and per-assignment scores as Canvas shows them (hidden grades stay hidden); optionalcoursefilter.refresh— ask the collector to sync from iCampus now (the one non-read-only tool; idempotent, non-destructive). Returns immediately, takes ~1 minute, limited to once every few minutes — checksync_statusafter.
Every tool is read-only except refresh. Course arguments accept an ID, a course code (e.g. CSE1001) or part of the name.
Reads your own SKKU iCampus data through Canvas's API, providing access to courses, tasks, assignments, announcements, lectures, attendance, and grades.
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., "@icampus-mcp What assignments are due this week?"
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.
skku-icampus
Keeps a copy of your own SKKU iCampus data and serves it to other programs over a REST API, and to AI assistants over MCP. That covers tasks and deadlines, assignment submission status, announcements, lectures and attendance, grades, and the files attached to announcements and assignments.
icampus (FastAPI :9013) logs in by itself, syncs 4×/day, stores everything in SQLite
icampus-mcp (:8724/mcp) MCP tools; only talks to the API, never sees your passwordUnofficial, not affiliated with Sungkyunkwan University. It only reads your own account; follow your university's rules when you use it.
How it works
Login. A headless Chromium signs in through the normal SSO page, but only when the saved session has expired. Everything after that is plain GET requests: Canvas
/api/v1and the LearningX JSON API that My Page, 강의콘텐츠 and 출결현황 use themselves (notes).Read-only. The browser works from an allowlist of pages and never loads item pages, because opening a lecture item in iCampus marks it complete. It never submits anything, starts quizzes or marks anything read.
Attachments, on request only. A sync records which files an announcement or assignment has (names, sizes, IDs), never the files. A file is downloaded only when someone asks for it, with the saved login, and only if a synced announcement or assignment points at it; lecture items are never opened. iCampus records a download as you opening the file, and if a linked file also sits in a course module, as viewing it there. Copies are kept in
var/filesand reused until a sync sees a new version (for 12 hours when iCampus gives none). A child process with a memory cap and a time limit reads the text out of them.Careful with logins. At most 3 password logins a day. A rejected password, a locked account or a password-expiry notice stops automatic logins until you retry with an admin token (
POST /api/v1/sync?retry_login=true).Schedule. Syncs run at 07:30, 12:30, 18:00 and 22:30 KST (±10 min), plus on request. They show up as normal account activity in Canvas.
Failures. If part of a sync fails, the old data for that part is kept and its
synced_atstays at the last good sync.staleturns true once that is older than 12 hours (ICAMPUS_STALE_HOURS); from then on/api/v1/status(and the Uptime Kuma push) reports unhealthy and names the datasets left behind, and a task status resting on that data says it is outdated./api/v1/statusshows per-run errors. An item that drops off the iCampus to-do list is not marked "done".
Related MCP server: mos-diary-mcp
Run it locally
uv sync
uv run playwright install chromium
cp .env.example .env && chmod 600 .env # your 킹고ID + tokens (openssl rand -hex 24)
uv run icampus sync --headed # one sync, watching the browser
uv run icampus serve # API on 127.0.0.1:9013 (+ the schedule)
uv run pytestSwagger UI: http://127.0.0.1:9013/docs. icampus probe is a one-off read-only check of what the
iCampus pages load. It writes its report to var/probe/, which is gitignored and holds personal data.
REST API
Send Authorization: Bearer <token> on every call. Tokens come from ICAMPUS_API_TOKENS
(label:token,...). List responses look like {synced_at, stale, count, items}; when a list is cut
short they add total and truncated. course accepts an ID, a course code or part of a name.
Endpoint | Notes |
| no auth |
| last runs, freshness per dataset, login state, next run |
| Returns 202 started, 409 running, 429 cooldown or 423 blocked. |
| codes, instructors, current grade |
| merged to-do list: |
|
|
|
|
| an announcement or assignment attachment and its text: |
| the file itself |
|
|
|
|
| everything as one JSON document |
A few fields to read carefully:
statussums up a task or lecture item:todo,done,missed(deadline and any late period passed),upcoming(not open yet) orunknown(iCampus can't tell, e.g. handed in on paper or through an external tool). Canvas decides for what you hand in, LearningX for what you watch or read.status_reasonsays which, andstatus_checked_atwhen that source last confirmed it.in_remaining_listis what My Page shows. It does not mean you haven't submitted.completedandsubmissionare only filled in when iCampus reported them.nullmeans unknown.attendanceis one ofattendance(present),late,absentornone(not decided yet).Attachment text comes out of PDF, Word, PowerPoint, Excel, HWPX, notebooks and text files.
extractsays when there is none: a picture, a scanned PDF, or the binary HWP format.
MCP
Tools: sync_status, list_courses, list_tasks, list_announcements, read_announcement,
read_assignment, read_attachment, list_lectures, get_grades, refresh. All are read-only except
refresh, which asks for a sync, and read_attachment, whose first read of a file downloads it from iCampus
(so clients may ask before running it). It returns text, or the picture itself for images.
# over HTTP (icampus-mcp --http), with a token from ICAMPUS_MCP_TOKENS
claude mcp add --transport http icampus http://<server>:8724/mcp --header "Authorization: Bearer <token>"
# or locally over stdio against the API
claude mcp add icampus --env ICAMPUS_MCP_API_URL=http://<server>:9013 \
--env ICAMPUS_MCP_API_TOKEN=<api token> -- uv run --directory "$PWD" icampus-mcpOver HTTP, a request gets in with either a bearer token from ICAMPUS_MCP_TOKENS or a Cloudflare
Access JWT. Without either one configured, the server won't start.
The Access route is how claude.ai and the mobile apps reach it:
Put a public hostname behind an Access app with Managed OAuth, and proxy it to
:8724.Set these variables:
ICAMPUS_MCP_ACCESS_TEAM, for examplemyteam.cloudflareaccess.com;ICAMPUS_MCP_ACCESS_AUD, the app's AUD tag or tags, comma-separated;ICAMPUS_MCP_ACCESS_EMAILS, the emails allowed in;ICAMPUS_MCP_ALLOWED_HOSTS, which must include the public hostname.
Deploy with Docker
cp .env.example .env && chmod 600 .env # fill it in
docker compose up -d --build # ports on 127.0.0.1 onlyTo expose the ports on a server, copy compose.homelab.example.yaml to compose.homelab.yaml
(gitignored), put in your addresses, and add COMPOSE_FILE=compose.yaml:compose.homelab.yaml to
.env. Keep the API off the public internet, and put only the MCP port behind Cloudflare Access.
The MCP container never gets your SSO password.
License
MIT — see LICENSE.
Repo
Path | What |
| the program ( |
| how iCampus behaves: login flow, endpoints, side effects |
| offline tests; one runs a local Chromium against a fake login page, one downloads from a local server |
var/ (the database, saved session, downloaded attachments, probe output), .env and private/ hold
personal data and are gitignored.
Available Tools
8 toolsget_gradesBRead-only
Course totals and per-assignment scores as Canvas shows them to you (hidden grades stay hidden).
Inputs: course.
list_announcementsARead-only
Recent course announcements (title, date, author, read state, a short preview), newest first.
Use read_announcement with an id for the full text.
Inputs: course, since_days, unread_only.
list_coursesARead-only
This term's courses: id, code (e.g. CSE1001), name, instructors and the current grade if visible.
Inputs: no named parameters.
list_lecturesARead-only
Lecture videos/materials with completion and attendance as iCampus shows them, soonest deadline first. By default: items already open, not completed, whose deadline (incl. late period) has not passed.
Args:
course: course ID, code or part of the name.
week: week number (1 = 1주차).
kind: e.g. video or material.
incomplete_only: only items reported as not completed (unknown completion is left out).
include_upcoming: also items that have not opened yet.
include_overdue: also items whose deadline has passed (missed, possibly still viewable).
include_attendance: add each course's official per-lesson attendance summary.
limit: maximum items returned.
Inputs: kind, week, limit, course, +4 more.
list_tasksARead-only
Things to do across courses, soonest first: the iCampus remaining list merged with Canvas assignment/quiz submission status and lecture completion. Items with no due date come last.
Args:
course: course ID, code (CSE1001) or part of the name. Omit for all courses.
kind: only this kind of item.
due_within_days: items due in the next N days (items without a due date are always included).
past_days: also include items whose due date passed in the last N days (overdue/late window).
include_done: also include submitted/completed items.
limit: maximum items returned; `total` shows how many matched when truncated.
Inputs: kind, limit, course, past_days, +2 more.
read_announcementARead-only
Full text of one announcement (by the numeric id from list_announcements).
Inputs: announcement_id (required).
refreshAIdempotent
Ask the collector to sync from iCampus now. Returns immediately; a sync takes about a minute. Limited to once every few minutes. Check sync_status afterwards.
Inputs: no named parameters.
sync_statusARead-only
When the data was last refreshed (per dataset), whether the last runs worked, and any login problem. Call this first if answers look stale or empty.
Inputs: no named parameters.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 8 tools
Most tools clearly target distinct resources: announcements, courses, tasks, lectures, grades, and sync status. The only mild overlap is list_tasks including lecture completion while list_lectures also reports completion, but their primary purposes are still distinguishable. refresh and sync_status are complementary rather than competing.
The dominant list_* prefix creates a mostly readable pattern, and read_announcement and get_grades fit loosely within it. However, refresh and sync_status break the verb_noun style, and pluralization is inconsistent with list_announcements vs. read_announcement. The naming is understandable but not fully predictable.
Eight tools is well within the ideal range for a campus portal integration. Each tool covers a distinct area—announcements, courses, tasks, lectures, grades, and sync—without redundancy or bloat.
The read-only scope is well covered: announcements have list/detail, the major coursework views have dedicated list endpoints, grades are exposed, and sync status is handled. Minor gaps exist such as no per-course detail or task/lecture detail endpoints, but common workflows around due work, lectures, and grades are fully supported.
Maintenance
Related MCP Connectors
Read-only MCP tools for AI agent discovery, structured resources, and NIULAI information.
Your org's AI agents, tasks, runs, search, and brain files as MCP tools and resources.
Read-only search of 2,189 AI agent tools (MCP servers, x402 APIs) with daily automated trust scores.
Your memory, everywhere AI goes. Build knowledge once, access it via MCP anywhere.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to access Canvas LMS academic data such as courses, assignments, grades, and events via MCP tools.-
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to retrieve and work with Moscow Electronic School data, including schedules, homework, grades, rankings, school info, meals, passes, olympiads, and portfolio, via authenticated MCP tools.MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to read courses, upcoming deadlines, assignment details, grades, announcements, modules, files, inbox, and timetable from U of T Quercus and ACORN through read-only tools.1MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to browse your own university courses by downloading files, slides, announcements, deadlines, grades and lecture transcripts to your machine, then answering questions and searching across them through MCP tools. It logs in with your own account and refreshes only what changed.MIT