Skip to main content
Glama

waseda-portal-mcp

An unofficial, local, read-only MCP server that consolidates Waseda University's Waseda Moodle, MyWaseda class cancellation information, Web Syllabus, and the official academic calendar. It is unrelated to Waseda University and is not approved, guaranteed, or supported by the university.

Its main use is to ask an MCP client "show me tomorrow's classes and deadlines" and check classes, cancellations/changes, same-day deadlines, and unsubmitted overdue assignments with sources.

Supported data sources

  • Waseda Moodle: regular courses, activity types, structured start/deadline times, submission/completion status

  • MyWaseda class cancellation information: cancellations and changes for enrolled courses shown on the initial post-login screen

  • Web Syllabus: academic year, course/class codes, offering location, instructors, target year, published audience/prerequisites, day-period, classroom, format, overview, plan, assessment, exam notes

  • Waseda University official academic calendar: class start/end, holidays, holiday classes, class suspension, exam periods

University logos, screen captures, teaching materials, retrieved syllabus text, and real personal data are not included in the repository.

Requirements and setup

  • Node.js 22 or later

  • npm

  • Google Chrome installed on the system

git clone https://github.com/TakeruF/waseda-portal-mcp.git
cd waseda-portal-mcp
npm install
npm run build
npm run auth

npm run auth (or waseda-portal-mcp auth after building) opens a dedicated Chrome profile. The user logs in to Waseda Moodle and MyWaseda themselves in Chrome, and finally opens MyWaseda's "Classes → Class-related → Cancellations". Once arrival at the cancellation page is confirmed by URL alone, the authentication state is saved and the dedicated Chrome is closed automatically. The CLI does not ask for a username or password. It does not copy existing Chrome profiles or cookies from normal browsing.

The default dedicated profile is at ~/.waseda-portal-mcp/chrome-profile, and the authentication state the server reads is at ~/.waseda-portal-mcp/auth-state.json. Both are outside the repository, and the authentication state file is owner-only (0600). The locations can be changed with WASEDA_PORTAL_PROFILE_DIR and WASEDA_PORTAL_AUTH_STATE_PATH. Chrome and the MCP server using the same dedicated profile cannot be started at the same time.

MCP client configuration

Replace the absolute paths with your actual checkout.

{
  "mcpServers": {
    "waseda-portal": {
      "command": "node",
      "args": ["/absolute/path/to/waseda-portal-mcp/dist/cli.js"]
    }
  }
}

To disable the cache, add "--no-cache" to args. stdio standard output is reserved for the MCP protocol; operational messages go to standard error.

Tools

  • get_day_brief: integrates classes, changes, same-day deadlines, and unsubmitted overdue items for date (YYYY-MM-DD)

  • list_courses: normally only courses whose category starts with 正規科目/. includeNonRegular also includes guidance courses, etc.

  • list_deadlines: lists activities with deadlines within the ISO 8601 from and to range. Normally excludes submitted/completed items

  • list_changes: lists cancellations and changes for the specified date range

  • get_syllabus: returns details or ambiguous candidates from courseId or syllabusKey

  • search_syllabi: searches the current year's Web Syllabus by course name or content, regardless of enrollment status

The mode of search_syllabi is course_name for known course names, or content for searching by what you want to learn. Content search breaks natural language into up to 3 words. MCP clients can pass up to 3 short related terms to relatedTerms to make the number of searches and intent explicit.

{
  "query": "日本の貨幣の歴史を学びたい",
  "mode": "content",
  "relatedTerms": ["貨幣", "通貨", "経済史"],
  "maxResults": 3,
  "useAcademicProfile": true
}

Results include the full syllabus, terms matched in the official search, fields that could be matched, and lexical relevance. If a local academic profile is set, profileApplied becomes true, and each candidate also gets advisory matching for affiliation, year, and prerequisites. Content search is not a guarantee of semantic course recommendation or eligibility.

Optional local academic profile

Only minimal academic information explicitly provided by the user can optionally be saved, by default to ~/.waseda-portal-mcp/academic-profile.json. There is no feature to automatically retrieve name, student number, affiliation, grade level, or enrollment history from MyWaseda or Moodle.

{
  "schemaVersion": 1,
  "affiliations": ["例示学部"],
  "academicLevel": "undergraduate",
  "year": 3,
  "completedPrerequisites": ["合成基礎科目"]
}

affiliations accepts up to 5 official faculty/graduate school names, academicLevel is undergraduate, masters, doctoral, or other, and year is 1-6. completedPrerequisites lists only course names or prerequisites the user personally selects for matching, up to 30 items. Since this corresponds to enrollment history, omit it if not needed.

Set the parent directory to 0700 and the file to 0600, and place it outside the repository. If the file does not exist, search proceeds as before. To use a different location, specify WASEDA_PORTAL_ACADEMIC_PROFILE_PATH. Files with overly permissive permissions or files owned by other users are not read.

Profile values are not replicated into MCP responses, logs, snapshots, or caches. Only profileApplied and the masked consistent, conflict, review_required, and unavailable determination reasons are output. Setting useAcademicProfile: false per call disables its use.

Dates and times are kept in ISO 8601, and if the source page has no timezone, they are interpreted as Asia/Tokyo. All results include the source URL and retrieval time. On conflicts, the order is MyWaseda, Moodle structured information, Web Syllabus, then free text.

Read-only guarantee

Normal retrieval is only page display and DOM reading. ReadOnlyGuard rejects known URLs for assignment submission, uploads, quiz/survey responses, attendance, completion changes, calendar creation, posts, messages, course registration changes, and other disallowed non-GET requests.

Only the official Web Syllabus search form uses HTTP POST despite being a search. For this reason, only search POSTs where the official host, /syllabus/JAA101.php, and the read-only controller JAA103SubCon all match are narrowly allowed. Moodle lazy loading also only allows known reference-only methods against /lib/ajax/service.php. Detail pages are read with GET. The authentication flow runs in a separate process, and entering and submitting credentials is the user's own action.

Grades, scores, instructor feedback, and submitted file names do not exist in the model and are not included in normal responses. Moodle external calendar tokens are not issued, stored, or used.

Personal information and cache

Authenticated HTML is parsed in memory and then discarded; it is not persisted. Cookies and session tokens exist only in the dedicated profile and authentication state file outside the repository, and are not exposed in MCP responses or logs. The optional academic profile is also read once at startup from an owner-only file outside the repository, and its values are not stored in responses or caches. Only normalized minimal data is cached in process memory for 5 minutes by default. The TTL is WASEDA_PORTAL_CACHE_TTL_MS, and it can be disabled with --no-cache or WASEDA_PORTAL_CACHE=false.

Only confirmed courseId → syllabusKey mappings can be saved to ~/.waseda-portal-mcp/cache/course-syllabus-map.json to reduce re-searches. This mapping table does not include course names, instructor names, student numbers, etc., and is updated atomically with directory 0700 and file 0600. Ambiguous candidates and no matches are not saved.

All fixtures are synthetic data. Do not paste real data into issues, logs, fixtures, or test output. See SECURITY.md for details.

Errors

AUTH_REQUIRED, SESSION_EXPIRED, MAINTENANCE, SOURCE_UNAVAILABLE, PAGE_STRUCTURE_CHANGED, AMBIGUOUS_COURSE_MATCH, RATE_LIMITED, and READ_ONLY_VIOLATION are distinguished. If a major selector disappears, an empty array is not treated as success; PAGE_STRUCTURE_CHANGED is returned. An empty array is returned only when a legitimate empty-list container is confirmed.

If unauthenticated, run npm run auth. For structural changes, reproduce the minimal DOM structure without personal information as a synthetic fixture, and update the target parser and fixture tests. Do not add authenticated raw HTML to issues or commits.

Development and verification

npm test             # 外部アクセスなしの人工fixtureテスト
npm run typecheck
npm run lint
npm run format:check
npm run build
npm run test:live:auth-state     # 新規一時プロファイルでAUTH_REQUIREDを確認
npm run test:live:authenticated  # 認証必須。AUTH_REQUIRED/SESSION_EXPIREDは失敗
npm run test:live:catalog        # 公開シラバスの内容検索と科目名検索
npm run test:e2e:authenticated   # ビルド後、MCPクライアントからstdio E2E
npm run test:e2e:catalog         # search_syllabiのstdio E2E

test:live is an alias for test:live:authenticated. Authenticated live verification is limited to 1 concurrent run, 1-second access intervals, 1 regular course, up to 3 syllabus candidates, and up to 1 assignment detail. If unauthenticated, it fails rather than being treated as success. Fixture success, authenticated live success, and MCP client E2E success are treated as separate evidence.

Known limitations

  • DOM changes in Moodle, MyWaseda, and Web Syllabus may require parser updates.

  • Content search is a lexical search using the official Web Syllabus full-field keyword search. Synonyms and abstract interests are supplemented with relatedTerms, limited to 3 searches and up to 5 details.

  • Academic profile-based determinations are advisory. Target years that appear as independent fields in Web Syllabus are matched structurally, but the offering location is not treated as an affiliation restriction. If audience, prerequisite courses, capacity, or registration timing appear only in free text or faculty regulations, automatic eligibility is not asserted and official information must be confirmed.

  • MyWaseda only covers the initial view for enrolled courses; POST operations for the full faculty view are not implemented.

  • Class sessions are generated from the confirmed syllabus day-period and semester/holiday dates. Intensive, make-up, and individual session free text is not asserted.

  • Moodle-syllabus matching is based on academic year, offering location, normalized course name, class, instructor, and day-period when available. If the Moodle name and syllabus name differ, candidates are retrieved up to the maximum count via partial instructor name matching. If the evidence is weak or the top candidates are too close, only ambiguous candidates are returned and classroom/exam information is not confirmed.

  • Resident notifications, writing, grade retrieval, bulk material download, calendar tokens, Chrome extensions, cloud authentication, remote MCP, and multiple universities are out of scope.

Adapters for other universities

What is shared is not the retrieval method but the results users need. First implement UniversityAdapter within the same package, keeping university-specific selectors, IDs, and matching rules under the adapter. University-specific information goes into extensions. Do not split into a separate package until a second university implementation confirms the actual boundaries. See docs/architecture.md for details.

License

MIT

-
license - not tested
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Read-only MCP server for ClassQuill, a tutoring-business-management platform.

  • An MCP server for deep research or task groups

  • MCP-native open-source Notion alternative: read & write pages, databases and kanban boards.

View all MCP Connectors

Latest Blog Posts

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/TakeruF/waseda-portal-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server