isu-moodle-mcp
isu-moodle-mcp
Moodle을 Claude에 연결하는 MCP server입니다. 두 계층으로 나뉩니다:
API 계층(18개, 주력): 공식 Web Service REST API. HTML을 크롤링하지 않고, 브라우저를 열 필요가 없습니다.
CDP 계층(6개, 구멍 메우기) + 구시스템 계층(4개): API로 정말 얻을 수 없을 때만 debug Chrome을 사용합니다. 가장 중요한 것은
probe_course_access()입니다. "더 이상 보이지 않는 강의가 있다"는 것을 발견할 수 있는 유일한 방법입니다.
평소에는 API 계층만으로 충분합니다. CDP 계층은 "내가 가르친 강의가 모두 목록에 있나?" 같은 질문을 위해 준비된 것입니다.
이수대학 AIEA "교과설계 AI 실무" 워크숍(2026-08-21) 단원 3에서 사용합니다. 바로 pull 받아서 자신의 것으로 수정하세요. GitHub 계정은 필요 없습니다.
이것은 무엇인가
수업에서 시연한 flipclass-mcp는 남타이과기대학(南臺科大) FlipClass의 MCP server입니다. 그 시스템에는 API가 없어서 두 가지 방법으로 데이터를 가져옵니다: HTML 크롤링(32곳 xpath) + debug Chrome(성적 매트릭스, 구성원 명단처럼 순수 HTTP로는 읽을 수 없는 페이지). 이것은 "시스템이 아무리 폐쇄적이어도 계정과 비밀번호만 있으면 완전히 리버스 엔지니어링할 수 있다"는 시연입니다.
이번 것은 같은 일의 나머지 절반입니다: 상대방에게 API가 있을 때, 동일한 MCP tool 계약으로 백엔드를 통째로 교체할 수 있습니다.
flipclass-mcp | moodle-mcp | |
데이터 가져오기 | HTML 크롤링 + lxml xpath | 공식 REST API |
인증 | 계정/비밀번호 + anticsrf token + cookie 캐시 | 토큰 하나, 무상태 |
다중 로그인 상호 강제 로그아웃 | 발생함(알려진 문제) | 발생하지 않음 |
구성원 명단 / 성적 매트릭스 | debug Chrome을 열어 CDP 사용 | 일반 API로 가능 |
학생 email | 학번으로 문자열 조합 추론 | 명단에 바로 제공 |
인증 관련 코드 | 약 247줄 | 약 15줄 |
debug Chrome | 매번 열어야 함(없으면 성적 매트릭스 없음) | 수강 관계를 조회할 때만 필요 |
tool 이름과 docstring은 양쪽 모두 일부러 동일하게 유지했습니다. 이를 통해 같은 요구사항이 "API 있음"과 "API 없음" 두 경우에 각각 어떤 모습인지 바로 대조해 볼 수 있습니다.
Related MCP server: Moodle MCP Server
빠른 시작
1. 프로그램 받기
git clone https://github.com/scatjay/isu-moodle-mcp.gitgit이 없어도 GitHub 페이지에서 Code → Download ZIP을 누르면 됩니다.
2. 의존 패키지 설치
pip install -r requirements.txt두 개뿐입니다: requests와 mcp.
3. token 교체
python get_token.py https://moodle.你的學校.edu.twMoodle 계정 비밀번호를 묻고, 성공하면 token을 .env에 기록합니다.
이 단계는 자신의 터미널에서 실행하세요. AI 대화창에서 실행하지 마세요. 대화 내용이 저장되거나 백업될 수 있으며, 비밀번호와 token이 거기에 나타나면 곧 유출된 것입니다.
왜 계정/비밀번호가 아니라 token인가요? token은 철회할 수 있고, 자신의 권한에만 묶여 있으며, 비밀번호처럼 한 번 유출되면 전부 잃는 일이 없습니다. Moodle의 token은 기본적으로 12주 후 만료됩니다. 학기 중에 도구가 갑자기 고장 나서 invalidtoken이라고 나오면, 돌아와서 이 스크립트를 다시 실행하면 됩니다.
4. Claude에 연결
Claude Desktop의 설정 파일(claude_desktop_config.json)에 추가합니다:
{
"mcpServers": {
"moodle": {
"command": "python",
"args": ["C:/你的路徑/isu-moodle-mcp/server.py"],
"env": {
"MOODLE_URL": "https://moodle.你的學校.edu.tw",
"MOODLE_TOKEN": "貼上 .env 裡那一串",
"MOODLE_LEGACY_URL": "https://舊站網址(沒有舊站就整行刪掉)"
}
}
}
}5. 먼저 상태 점검 실행
연결한 후, 첫 명령으로 Claude에게 diagnose()를 실행하라고 하세요. token이 유효한지, 실제로 호출할 수 있는 함수가 무엇인지, 무엇이 빠졌는지 알려줍니다. 연결이 안 될 때 가장 먼저 실행해야 하는 것이 이것입니다.
어떤 도구들이 있나
Tool | 하는 일 |
| 연결 상태 점검. 연결이 안 되면 먼저 실행 |
| 진행 중인 강의 |
| 현재 보이는 모든 강의(아래의 알려진 제한 사항 참고) |
| 키워드로 자신의 강의 찾기 |
| 강의에 단원 몇 개, 교재 몇 개, 과제 몇 개인지 |
| 교재 목록(다운로드 URL 포함) |
| 과제 목록 |
| 전체 학생 제출 현황 |
| 수강 명단(이름 / email / 역할) |
| 성적 매트릭스: 각 학생 × 각 평가 항목 |
| 활동 완료도 |
| 교재 파일 다운로드 |
| 임의의 Moodle 함수 직접 호출(탐색용) |
| 제출 보고서: 제출 시간, 지각 제출, 재제출 횟수 포함 |
| 단일 학생의 항목별 성적 |
| 특정 학생의 email 조회 |
| 한 강의의 교재+과제+명단+성적을 한 번에 패키지로 가져오기 |
| 보이는 모든 강의를 일괄 가져오기 |
CDP 계층(먼저 python start_debug_chrome_moodle.py를 실행하고 그 창에서 로그인해야 함)
Tool | 하는 일 |
| debug Chrome 연결 상태, 로그인 여부 |
| 이 강의에 아직 들어갈 수 있는가 — API가 답할 수 없는 문제 |
| 각 수강 신청의 상태, 방법, 추가 신청 시간, 시작/종료일 |
| "존재하지만 더 이상 보이지 않는" 강의를 스캔하여 찾기 |
| 어떤 서비스에 어떤 함수가 묶여 있는지, 누가 스스로 token을 발급받을 수 있는지 |
| 역할의 capability 매트릭스(300+개, API로는 얻을 수 없음) |
구시스템 계층(학교가 플랫폼을 교체했을 때 사용)
.env에 MOODLE_LEGACY_URL=https://구사이트주소 한 줄을 추가해야 합니다.
Tool | 하는 일 |
| 구사이트가 살아 있는지, API를 쓰는지 CDP를 쓰는지. 데이터를 파기 전에 먼저 실행 |
| 구사이트 대시보드에서 보이는 강의 |
| 구사이트 버전의 "이 강의에 아직 들어갈 수 있는가" |
| 구사이트 특정 강의의 단원과 교재 링크 |
이 버전은 일부러 어떤 쓰기 도구도 포함하지 않습니다(예: 성적을 수정하는 mod_assign_save_grade). 읽기 전용을 잘못 건드리면 기껏해야 데이터가 틀어지는 정도지만, 쓰기를 잘못하면 실제로 학생 성적이 바뀝니다. 정말 필요하면 직접 추가하되, 먼저 테스트 사이트에서 연습하세요.
알려진 제한 사항(이 절을 반드시 끝까지 읽으세요)
🔴 옛 강의는 조용히 사라집니다 — 하지만 조건은 생각보다 좁습니다
core_enrol_get_users_courses는 현재 수강 관계가 남아 있는 강의만 반환합니다.
2026-08-20에 두 대의 로컬 Moodle 4.1.18로 실제 테스트하여 항목별로 검증했습니다:
학교에서 한 일 | 강의가 목록에 남아 있나요? |
강의를 숨김으로 설정( | 그대로 보임 |
강의 종료일이 지남 | 그대로 보임 |
교사의 수강 관계가 "비활성화"로 설정됨 | 사라짐. 그리고 전혀 오류를 보고하지 않음 |
이 표는 매우 흔한 주장(이 README의 이전 버전도 포함)을 뒤집습니다: "옛 강의를 숨기거나 보관하면 사라진다". 실측 결과 성립하지 않습니다. 실제로 강의를 사라지게 하는 것은 마지막 행뿐입니다. 여기에 적어 두는 이유는: 실측으로 반증된 주장이 문서에 남아 있으면, 아예 없는 것보다 나쁘기 때문입니다. 그 말을 믿고 관리자에게 엉뚱한 것을 요구하게 될 테니까요.
강의, 학생, 과제는 모두 데이터베이스에 그대로 있지만, 보이지 않을 뿐입니다. 그리고 API는 "보이지 않는 강의가 있다"는 것을 알려주지 않고, 그저 언급하지 않을 뿐입니다.
그러므로 장기간 분석을 하기 전에 find_hidden_courses()나 probe_course_access(course_id)로 하나씩 탐지하세요. list_history_courses()의 목록만 믿지 마세요. 그 함수는 반드시 caveat 필드를 반환하여 경고하므로, 그것을 무시하지 마세요.
Moodle의 오류는 HTTP 200입니다
Moodle이 오류를 반환할 때도 HTTP 상태 코드는 여전히 200이며, 오류는 body의 exception 필드에 숨어 있습니다. raise_for_status()로는 전혀 잡을 수 없습니다. 이 server는 이미 처리했지만, 직접 코드로 Moodle을 호출할 때는 기억해 두세요.
accessexception은 추적하기 어렵습니다
공식적으로 나열된 원인은 일곱여덟 가지인데, 관리자가 debug를 NORMAL 이상으로 켜지 않는 한 오류 메시지는 어느 것인지 알려주지 않습니다. 이 server는 그것을 쉬운 말로 바꾸고 가장 가능성 높은 세 가지 원인을 제시하지만, 실제로 어느 것인지 확정하려면 diagnose()를 실행하여 token에 실제로 어떤 함수가 포함되어 있는지 확인해야 합니다.
자신의 강의만 볼 수 있습니다
이것은 Moodle에 내장된 보장이며, 이 도구의 제한이 아닙니다. token은 사용자 본인의 권한을 그대로 상속하며, 호출할 때마다 context 수준의 권한 검사를 수행합니다. 이것은 동시에 안전 보장이자 제한입니다.
배열 매개변수는 JSON을 사용할 수 없습니다
Moodle REST는 PHP의 $_POST로 파싱하므로, 배열은 courseids[0]=5&courseids[1]=7처럼 작성해야 합니다. JSON 문자열을 보내면 단일 문자열로 취급되어 invalidparameter 오류가 납니다. 이 server는 자동으로 펼쳐서 처리합니다.
파일 다운로드의 매개변수 이름이 다릅니다
REST 엔드포인트는 wstoken을 사용하지만, webservice/pluginfile.php는 **token**을 사용합니다. 포팅할 때 가장 놓치기 쉬운 부분입니다. 또한 서비스의 downloadfiles가 켜져 있어야 합니다.
get_token.py가 실패하는 경우
오류 | 의미 | 어떻게 할까 |
| 계정/비밀번호가 틀림 | Moodle 계정이 이메일과 같지 않을 수 있음 |
| 사이트에 모바일 서비스가 켜져 있지 않음 | 관리자에게 |
| 계정에 token을 직접 만들 권한이 없음 | 학교가 기본 권한을 변경한 경우, 관리자에게 token 발급 요청 |
| 사이트 점검 중 | 잠시 후 다시 시도 |
Moodle 기본값은 moodle/webservice:createmobiletoken을 모든 로그인 사용자에게 부여하므로, 교사는 보통 관리자 없이도 스스로 token을 교체할 수 있습니다. 하지만 학교가 이 기본값을 변경할 수 있습니다. 변경했다면 실제로 교체하려고 할 때만 알 수 있으며, 외부에서 탐지할 수 없습니다.
개발 노트
이것은 flipclass-mcp에서 포팅한 것입니다. 포팅할 때 가장 아팠던 절반은 잘라내고, 가장 가치 있는 절반은 남겼습니다:
잘라냄(약 247줄):
_login, anticsrf 처리, cookie 캐시,checkMultiLogin다중 로그인 처리, 32곳 lxml xpath 파싱, CDP(debug Chrome) 연결유지: FastMCP 뼈대, 각
@mcp.tool()의 시그니처와 docstring ——이것이 진짜 자산입니다. LLM이 보는 계약이기 때문입니다.
이렇게 한 이유는 기성 Moodle Python 패키지 중 쓸 수 있는 것이 하나도 없기 때문입니다: moodlepy는 거의 2년째 업데이트가 중단되었고 의존성을 attrs<23(2022년 버전)에 고정했습니다. moodle_api.py는 3년째 업데이트가 중단되었고 PyPI에 없습니다. python-moodle은 아직 유지보수되지만 사실상 HTML을 크롤링하는 것이지 REST client가 아닙니다. Moodle REST는 열 줄 남짓이면 작성할 수 있는데, 업데이트가 중단된 패키지를 도입하는 것은 기술 부채만 더 지는 것입니다.
라이선스
MIT. 가져다가 자신의 학교 버전으로 수정해도 됩니다. 물어볼 필요 없습니다.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables interaction with Moodle learning management systems through the Moodle REST API. Supports course management, user enrollment, assignments, forums, quizzes, and file operations through natural language.14MIT
- AlicenseNot gradedqualityDmaintenanceEnables interaction with Moodle learning management systems through the REST API. Supports course management, user enrollment, assignment handling, and forum operations through natural language.14MIT
- AlicenseNot gradedqualityCmaintenanceProvides Claude with full access to Moodle learning management systems, enabling interaction with courses, files, assignments, grades, and calendar events. It also supports building Obsidian study vaults from course materials through automated knowledge graph creation.1416MIT
- FlicenseAqualityCmaintenanceEnables read-only querying of Moodle as a student, including courses, assignments, grades, forums, and files, using a personal web services token.11
Related MCP Connectors
Read-only MCP server for ClassQuill, a tutoring-business-management platform.
WHOOP recovery, strain, sleep and workouts in Claude via official WHOOP OAuth. Free, open source.
Read-only tools over the Safer Agentic AI framework: 238 patterns + 14 heuristics.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/scatjay/isu-moodle-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server