Movie Planner — интеграции и агенты

Публичный контракт: OpenAPI (YAML). Эндпоинты /v1/* и OAuth /oauth/* проксируются с домена на бэкенд (см. Worker).

MCP и Cursor / ассистент

MCP не «подключается» самой нейросетью. Протокол MCP обслуживает только те клиенты, которые явно зарегистрировали сервер: в Cursor это настройки MCP (URL https://…/mcp и заголовок Authorization: Bearer …), в Claude Desktop — свой конфиг. Модель в чате получает только те инструменты, которые хост приложения передал в сессию; без записи в настройках Cursor инструментов mp_v1_* не существует для агента — это не баг Movie Planner. Тот же доступ даёт обычный REST /v1 с тем же Bearer.

Авторизация

  1. Уже есть сессия (JWT мобильного приложения или Bearer site session) → POST /oauth/authorize с client_id, redirect_uri, PKCE code_challenge (S256).
  2. POST /oauth/token с grant_type=authorization_code, code, code_verifier, client_id (+ client_secret если задан у клиента).
  3. Дальше вызовы API с Authorization: Bearer <access_token> (opaque OAuth).
  4. Обновление: grant_type=refresh_token + refresh_token, client_id, client_secret.
  5. Отзыв: POST /oauth/revoke с JSON {"token":"..."} или тем же Bearer.

Регистрация OAuth-клиента (сервер)

POST /oauth/clients с заголовком X-OAuth-Admin-Secret = переменная окружения OAUTH_CLIENT_REGISTRATION_SECRET. Тело: name, redirect_uris (строка с URI через запятую). В ответе один раз приходит client_secret.

OAuth scopes (для внешних токенов)

В POST /oauth/authorize передайте поле scope через пробел, например: profile.read movies.read movies.write plans.read plans.write calendar.read groups.read groups.write tv.launch. JWT и site session на это не смотрят. Если у OAuth-токена scope пустой — доступ к /v1 как раньше (полный). Если scope указан — для каждого эндпоинта нужен свой scope:

Сценарий для ИИ: план на завтра + билеты + Google Календарь

Цепочка REST (тот же Bearer, что для /v1). Перед push в Google пользователь один раз привязывает аккаунт в миниаппе или приложении (OAuth Google Calendar на стороне Movie Planner).

Билеты — только у планов plan_type: cinema. Если пользователь просит «добавить билет» / «в кино с билетом», сначала создайте кино-план, затем POST .../tickets. Адрес кинотеатра передавайте в POST /v1/plans (cinema_address / cinema_name); при отсутствии координат сервер может нормализовать адрес через геокодер (см. OpenAPI).

  1. POST /v1/movies — добавить фильм в базу по kp_id (или найти существующий через библиотеку / поиск).
  2. POST /v1/plans — создать план: для кино plan_type: cinema, дата/время сеанса (ISO 8601), кинотеатр (имя/адрес, опционально lat/lon).
  3. POST /v1/plans/<id>/tickets — прикрепить билет (изображение в base64 по описанию API); тот же список, что GET .../tickets, и вложения в Google читают эти файлы.
  4. POST /v1/plans/<id>/calendar/google/push — создать событие в Google Календаре (описание с ссылкой на Кинопоиск, кинотеатр, Яндекс.Карты; тело запроса пустое).
  5. Без Google: GET /v1/plans/<id>.ics — универсальный файл для Apple Calendar, Outlook и др.

MCP (stdio или /mcp): те же шаги инструментами mp_v1_movies_add, mp_v1_plans_create, mp_v1_plan_tickets_add, затем mp_v1_plan_google_calendar_push — билеты на диске прикрепятся к событию в Google (OAuth с правами Calendar + Drive). См. moviebot/mcp_server/tools_core.py.

Полезные пути

Черновики tool schemas (репозиторий)

docs/tool-schemas/openai_v1_me_plans.json, docs/tool-schemas/anthropic_v1_tools.json, docs/tool-schemas/generic_tools_v1.json, заготовка Zapier/Make: docs/automation/zapier_make_http.json.

Rate limit

In-memory лимиты на процесс: API_RATE_LIMIT_ENABLED (по умолчанию 1), API_RATE_LIMIT_RPM_V1, API_RATE_LIMIT_RPM_OAUTH. Исключения без лимита: /v1/capabilities, /v1/health.

MCP (stdio)

pip install -r requirements.txt -r requirements-dev.txt
export MP_BASE_URL="https://…railway…"
export MP_BEARER_TOKEN="…"
python -m moviebot.mcp_server