Skip to main content
Glama

waseda-portal-mcp

Неофициальный локальный MCP-сервер только для чтения, объединяющий Waseda Moodle университета 早稲田大学, информацию об отменах занятий MyWaseda, Webシラバス и официальный академический календарь. Он не связан с 早稲田大学 и не одобрен, не гарантирован и не поддерживается университетом.

Основное предназначение — по запросу из MCP-клиента «покажи завтрашние занятия и дедлайны» предоставлять сведения о занятиях, отменах и изменениях, дедлайнах на текущий день и просроченных несданных заданиях с указанием источников.

Поддерживаемые источники данных

  • Waseda Moodle: обычные курсы, типы активностей, структурированные даты начала и дедлайнов, статусы сдачи и завершения.

  • Информация об отменах занятий MyWaseda: отмены и изменения для записанных курсов, видимые на начальном экране после входа.

  • Webシラバス: учебный год, коды курсов и классов, место проведения, преподаватель, год набора, открытые целевая аудитория и prerequisites, день и период, аудитория, формат, обзор, план, оценка, сведения об экзамене.

  • Официальный академический календарь 早稲田大学: начало и конец занятий, каникулы, занятия в праздничные дни, приостановка занятий, экзаменационные периоды.

Логотипы университета, снимки экрана, учебные материалы, полученные тексты силлабусов и реальные персональные данные в репозиторий не включаются.

Related MCP server: who-will-notify-mcp

Требования и настройка

  • Node.js 22 или выше

  • npm

  • Google Chrome, установленный в системе

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 (или waseda-portal-mcp auth после сборки) открывает выделенный профиль Chrome. Вход в Waseda Moodle и MyWaseda выполняется самим пользователем в Chrome; в конце откройте в MyWaseda пункт «Курсы → Связанное с курсом → Отмены занятий». Как только по URL подтверждается достижение страницы отмен занятий, состояние аутентификации сохраняется, и выделенный Chrome автоматически закрывается. CLI не запрашивает имя пользователя и пароль. Существующие профили Chrome и cookie из обычного использования также не копируются.

Выделенный профиль по умолчанию находится в ~/.waseda-portal-mcp/chrome-profile, а состояние аутентификации, загружаемое сервером, — в ~/.waseda-portal-mcp/auth-state.json. Оба расположены вне репозитория; файл состояния аутентификации доступен только владельцу (0600). Расположение можно изменить через WASEDA_PORTAL_PROFILE_DIR и WASEDA_PORTAL_AUTH_STATE_PATH. Chrome и MCP-сервер, использующие один и тот же выделенный профиль, не могут запускаться одновременно.

Конфигурация MCP-клиента

Замените абсолютные пути на фактический checkout.

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

Чтобы отключить кэш, добавьте "--no-cache" в args. Стандартный вывод stdio предназначен исключительно для протокола MCP; служебные сообщения выводятся в стандартный поток ошибок.

Инструменты

  • get_day_brief: объединяет занятия, изменения, дедлайны на указанную date (YYYY-MM-DD) и просроченные несданные задания.

  • list_courses: обычно только курсы, категория которых начинается с 正規科目/. С includeNonRegular включаются также ознакомительные курсы и т.п.

  • list_deadlines: перечисляет активности с дедлайнами в пределах from и to в формате ISO 8601. Обычно исключаются сданные и завершённые.

  • list_changes: перечисляет отмены и изменения за указанный диапазон дат.

  • get_syllabus: возвращает подробные сведения или неоднозначных кандидатов по courseId или syllabusKey.

  • search_syllabi: ищет в Webシラバス текущего учебного года по названию курса или содержанию, независимо от статуса записи на курс.

Параметр mode у search_syllabi: для известных названий курсов используйте course_name, для поиска по интересующему содержанию — content. При поиске по содержанию естественная фраза разбивается максимум на три слова. MCP-клиент может явно указать количество поисков и своё намерение, передав до трёх коротких связанных терминов в relatedTerms.

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

Результат содержит полный силлабус, слова, совпавшие в официальном поиске, сопоставленные поля и лексическую релевантность. Если задан локальный учебный профиль, profileApplied становится true, и к каждому кандидату добавляется рекомендательное сопоставление по принадлежности, году обучения и prerequisites. Поиск по содержанию не является смысловой рекомендацией по выбору курса и не гарантирует возможность зачисления.

Опциональный локальный учебный профиль

По желанию можно сохранять только минимальную учебную информацию, явно указанную пользователем; по умолчанию — в ~/.waseda-portal-mcp/academic-profile.json. Автоматическое получение имени, номера студента, принадлежности, года обучения и истории курсов из MyWaseda или Moodle не предусмотрено.

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

affiliations — до пяти официальных названий факультетов и исследовательских школ; academicLevel — undergraduate, masters, doctoral, other; year — от 1 до 6. В completedPrerequisites пользователь сам указывает только те названия курсов и prerequisites, которые хочет использовать для сопоставления, не более 30. Поскольку это фактически история обучения, при отсутствии необходимости поле можно опустить.

Родительский каталог должен иметь права 0700, файл — 0600, и он должен находиться вне репозитория. Если файл отсутствует, поиск выполняется как обычно. Для другого расположения можно указать WASEDA_PORTAL_ACADEMIC_PROFILE_PATH. Файлы со слишком широкими правами или принадлежащие другим пользователям не читаются.

Значения профиля не копируются в MCP-ответы, журналы, snapshot или кэш. Выводятся только profileApplied и основания решений consistent, conflict, review_required, unavailable без раскрытия значений. Если при каждом вызове передавать useAcademicProfile: false, профиль не используется.

Дата и время хранятся в формате ISO 8601; если на исходной странице нет часового пояса, они интерпретируются как Asia/Tokyo. Все результаты содержат URL источника и время проверки. При конфликтах приоритет следующий: MyWaseda, структурированные данные Moodle, Webシラバス, свободное описание.

Гарантия read-only

Обычное получение данных — это только отображение страницы и чтение DOM. ReadOnlyGuard блокирует известные URL для сдачи заданий, загрузки файлов, ответов на тесты и опросы, посещаемости, изменения статуса завершения, создания событий расписания, публикаций, сообщений, изменения записи на курсы, а также любые неразрешённые не-GET запросы.

Только официальная поисковая форма Webシラバス использует HTTP POST, несмотря на то что это поиск. Поэтому узко разрешены лишь поисковые POST-запросы, в которых одновременно совпадают официальный хост, /syllabus/JAA101.php и read-only контроллер JAA103SubCon. Для отложенной загрузки Moodle разрешаются только известные методы обращения к /lib/ajax/service.php, предназначенные исключительно для чтения. Страницы сведений читаются через GET. Процесс аутентификации выполняется в отдельном процессе; ввод и отправка учётных данных — это действия самого пользователя.

Оценки, баллы, отзывы преподавателей и имена загруженных файлов отсутствуют в модели и не включаются в обычные ответы. Внешние токены календаря Moodle не выпускаются, не сохраняются и не используются.

Персональные данные и кэш

Аутентифицированный HTML после разбора в памяти уничтожается и не сохраняется постоянно. Cookie и токены сессий находятся только в выделенном профиле и файле состояния аутентификации вне репозитория и не выводятся в MCP-ответы и журналы. Необязательный учебный профиль также читается один раз при запуске из файла вне репозитория с правами только для владельца; его значения не сохраняются в ответы или кэш. В памяти процесса кэшируются только минимальные нормализованные данные, по умолчанию в течение 5 минут. TTL задаётся через WASEDA_PORTAL_CACHE_TTL_MS, отключение — через --no-cache или WASEDA_PORTAL_CACHE=false.

Только подтверждённые соответствия courseId → syllabusKey могут сохраняться в ~/.waseda-portal-mcp/cache/course-syllabus-map.json, чтобы уменьшить число повторных поисков. Эта карта не содержит названий курсов, имён преподавателей, номеров студентов и т.п.; обновление выполняется атомарно, каталог имеет права 0700, файл — 0600. Неоднозначные кандидаты и отсутствие совпадений не сохраняются.

Все fixture являются искусственными данными. Не публикуйте реальные данные в issue, журналах, fixture или выводах тестов. Подробнее см. в SECURITY.md.

Ошибки

Различаются AUTH_REQUIRED, SESSION_EXPIRED, MAINTENANCE, SOURCE_UNAVAILABLE, PAGE_STRUCTURE_CHANGED, AMBIGUOUS_COURSE_MATCH, RATE_LIMITED, READ_ONLY_VIOLATION. Если основные селекторы исчезли, пустой массив не считается успехом — возвращается PAGE_STRUCTURE_CHANGED. Пустой массив возвращается только в случае подтверждения штатного контейнера пустого списка.

Если аутентификация не выполнена, запустите npm run auth. При изменении структуры воспроизведите минимальную структуру DOM без персональных данных в виде искусственного fixture и обновите соответствующий parser и fixture-тест. Не добавляйте аутентифицированный исходный HTML в issue или коммиты.

Разработка и проверка

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 — это псевдоним test:live:authenticated. Живая проверка, требующая аутентификации, ограничена одним одновременным запуском, интервалом между обращениями 1 секунда, одним обычным курсом, максимум тремя кандидатами силлабусов и максимум одной деталью задания. Если аутентификация не выполнена, проверка завершается ошибкой, а не засчитывается как успешная. Успех fixture, успешная аутентифицированная живая проверка и успешный E2E MCP-клиента считаются отдельными свидетельствами.

Известные ограничения

  • Из-за изменений DOM в Moodle, MyWaseda и Webシラバス может потребоваться обновление parser'ов.

  • Поиск по содержанию — это лексический поиск по ключевым словам во всех полях официального Webシラバス. Синонимы и абстрактные интересы компенсируются через relatedTerms; он ограничен максимум тремя поисками и пятью деталями.

  • Определения на основе учебного профиля носят рекомендательный характер. Год набора, выделенный в Webシラバス отдельным полем, сопоставляется структурно, но место проведения не считается ограничением по принадлежности. Если целевая аудитория, prerequisite-курсы, лимит мест и сроки регистрации указаны в свободном описании или положениях факультета, автоматическая возможность зачисления не утверждается; требуется проверка официальной информации.

  • MyWaseda предоставляет только начальное представление для записанных курсов; POST-операции для отображения всего факультета не реализованы.

  • Занятия (встречи) генерируются из подтверждённых дня и периода в силлабусе с учётом семестра и каникул. Свободные описания интенсивных курсов, дополнительных занятий и отдельных встреч не считаются точными.

  • Сопоставление Moodle и силлабуса основано на учебном годе, месте проведения, нормализованном названии курса, классе, преподавателе и, при наличии, дне и периоде. Если название в Moodle отличается от названия в силлабусе, кандидаты получаются по частичному совпадению преподавателя вплоть до максимального числа. При слабых основаниях или малой разнице между верхними кандидатами возвращаются только неоднозначные кандидаты, а аудитория и экзаменационная информация не подтверждаются.

  • Фоновые уведомления, запись, получение оценок, массовая загрузка материалов, токены календаря, расширения Chrome, облачная аутентификация, удалённый MCP и несколько университетов не поддерживаются.

Адаптеры для других университетов

Универсальным является не способ получения данных, а результаты, необходимые пользователям. Сначала реализуйте UniversityAdapter в том же пакете; специфичные для университета селекторы, ID и правила сопоставления размещаются в адаптере. Специфичные данные помещаются в extensions. До тех пор, пока реализация второго университета не подтвердит реальные границы, выделение в отдельный пакет не выполняется. Подробнее см. в docs/architecture.md.

License

MIT

Related MCP Connectors

Related MCP Servers