Files
miem_workers/README.md

7.0 KiB
Raw Permalink Blame History

MIEM Employees Server

Сервис собирает сотрудников МИЭМ с сайта ВШЭ, хранит карточки и историю обновлений в Postgres, показывает минимальную админку и отдает read-only MCP endpoint для ИИ-агентов.

Архитектура

  • api: FastAPI, REST API, HTML-админка, healthcheck.
  • worker: weekly scheduler, который запускает парсинг по CRAWL_CRON.
  • mcp: HTTP MCP endpoint с OAuth/OIDC access token для внешних агентов или legacy static token для локального режима.
  • postgres: основная БД.

Парсер использует фиксированный источник сотрудников, по умолчанию https://miem.hse.ru/persons. Для каждой карточки сохраняются ФИО, должности, год начала работы, контакты, идентификаторы, вкладки профиля, секции, публикации, курсы, ВКР, JSON-снапшот и сжатый HTML-снапшот. Ссылки обходятся только из меню профиля самого сотрудника (person-menu), например #sci, #teaching, #main.

Переменные окружения

Скопируйте .env.example в .env и поменяйте секреты:

cp .env.example .env

Основные настройки:

  • DATABASE_URL: строка подключения SQLAlchemy.
  • SOURCE_URL: список сотрудников МИЭМ.
  • CRAWL_CRON: расписание в формате crontab, по умолчанию 0 3 * * 1.
  • CRAWL_LIMIT: опциональный лимит профилей для тестового запуска.
  • ADMIN_USERNAME, ADMIN_PASSWORD: логин и пароль админки.
  • SESSION_SECRET: секрет подписи cookie.
  • MCP_TOKEN: статический bearer token для legacy/local режима MCP_AUTH_MODE=token.
  • MCP_AUTH_MODE: режим авторизации MCP: oauth для внешних агентов или token для локальной отладки.
  • MCP_RESOURCE_URL: публичный URL MCP endpoint, например https://example.com/mcp.
  • MCP_OAUTH_ISSUER: issuer внешнего OIDC-провайдера.
  • MCP_OAUTH_AUDIENCE: ожидаемый aud в OAuth access token.
  • MCP_OAUTH_JWKS_URL: JWKS endpoint; если не задан, используется <issuer>/.well-known/jwks.json.
  • MCP_OAUTH_REQUIRED_SCOPE: scope для доступа к MCP tools, по умолчанию mcp:tools.
  • PARSER_USE_PLAYWRIGHT: включение Playwright-рендера динамических вкладок.

Локальный запуск

python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
uvicorn app.main:app --reload

Админка: http://localhost:8000/admin.

В админке доступны:

  • Dashboard: общая статистика, последний добавленный сотрудник, прогресс текущего/последнего парсинга и ручной запуск.
  • Directory: настраиваемая таблица сотрудников с фильтрами, сортировкой, пагинацией и выбором колонок.
  • Employees: простая legacy-таблица сотрудников.
  • Runs: история запусков, ошибки и progress bar.

Docker Compose

docker compose up --build

По умолчанию:

  • API и админка: http://localhost:8000
  • MCP: http://localhost:8001/mcp
  • Postgres: localhost:5432

Таблицы создаются приложением при старте. SQL-миграция для ручного применения лежит в migrations/001_init.sql.

Парсинг

Weekly worker запускается по CRAWL_CRON. Ручной запуск доступен в админке на Dashboard и странице Runs или через REST:

curl -X POST http://localhost:8000/api/crawl-runs --cookie "miem_admin_session=..."

Алгоритм обновления:

  • найденные сотрудники получают статус active и обновленный last_seen_at;
  • новые сотрудники добавляются в employees;
  • количество новых сотрудников за запуск сохраняется в crawl_runs.new_count;
  • активные сотрудники, исчезнувшие из текущего списка источника, получают статус dismissed и dismissed_at;
  • каждый успешный разбор сохраняет запись в employee_snapshots.

Во время выполнения парсинга found_count, parsed_count и error_count обновляются в базе. Админка опрашивает /api/crawl-runs/latest и показывает прогресс как parsed_count + error_count / found_count.

MCP

Endpoint: POST /mcp, авторизация Authorization: Bearer <token>.

Для внешних ИИ-агентов используйте MCP_AUTH_MODE=oauth. В этом режиме статический MCP_TOKEN не принимается: клиент должен передать OAuth/OIDC access token с нужным scope.

Поддерживаемые tools:

  • search_employees(query, status?, limit?)
  • get_employee(profile_id_or_url)
  • list_employee_publications(profile_id_or_url)
  • list_employee_courses(profile_id_or_url)
  • get_crawl_status()

Пример локального legacy-режима со статическим токеном:

curl http://localhost:8001/mcp \
  -H "Authorization: Bearer change-me-mcp-token" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

Для production OAuth/OIDC настройте внешний authorization server и включите режим oauth:

MCP_AUTH_MODE=oauth
MCP_RESOURCE_URL=https://example.com/mcp
MCP_OAUTH_ISSUER=https://auth.example.com
MCP_OAUTH_AUDIENCE=miem-mcp
MCP_OAUTH_JWKS_URL=https://auth.example.com/.well-known/jwks.json
MCP_OAUTH_REQUIRED_SCOPE=mcp:tools

MCP server работает как OAuth protected resource: он не выдает токены, а проверяет JWT access token по JWKS, issuer, audience, сроку действия и scope. Metadata для MCP-клиентов доступна по GET /.well-known/oauth-protected-resource.

Обслуживание

docker compose logs -f api
docker compose logs -f worker
docker compose exec postgres pg_dump -U miem miem_workers > backup.sql
docker compose down

Версия сервиса: 0.4.0. Админка всегда показывает версии backend и frontend в footer.