Личный кабинет

Для человека

Правила для ИИ-агента

Чтобы ChatGPT, Cursor или другой ИИ писал материалы в синтаксисе Демонстратора — скачайте пакет правил и отдайте его агенту.

Внутри: как писать блоки, какой блок выбрать, темы, виджеты, типографика. Распакуйте и приложите файлы к агенту — до просьбы «напиши урок».

Как пользоваться

В Cursor / Claude Code / VS Code

Агент сможет сам создавать и править материалы
  1. Распакуйте zip в правила проекта (Cursor Skills, .cursor/rules, AGENTS.md — как принято у вас).
  2. В личном кабинете возьмите API-токен.
  3. Подключите MCP по конфигу ниже.
{
  "mcpServers": {
    "demonstrator-mcp": {
      "url": "https://app.longread.agency/mcp/demonstrator/mcp",
      "headers": {
        "Authorization": "Bearer ВСТАВЬ_ТОКЕН_ИЗ_ЛК"
      }
    }
  }
}
Адрес: /mcp/demonstrator/mcp (не /sse). Без токена подключение не сработает.

В ChatGPT / Gemini / NotebookLM

Без подключения к аккаунту — только текст на выходе
  1. Загрузите файлы из zip в Knowledge / файлы проекта / вложение чата.
  2. Попросите написать материал.
  3. Скопируйте готовый markdown в редактор Демонстратора.
Без MCP бот сам ничего в ваш аккаунт не запишет.

Дополнительно (не обязательно)

Нужны, если готовите исходники из Word/PowerPoint или заливаете медиа с диска через helper-скрипт. Для обычной работы с материалами хватает основного zip.

Что внутри пакета

Полный текст — во вкладках ниже и в файлах .md. Если правила уже лежат у вас локально — сверьте дату обновления: если на сайте новее, скачайте zip снова.

Для агента и даты файлов

Primary-источник правил — raw .md на этом origin: начни с SKILL.md и README.md, затем 0106. Вкладки ниже — зеркало. Не меняй план без подтверждения пользователя. Без MCP — отдай готовый markdown, не вызывай API; медиа — CDN-заполнитель или URL от пользователя.

Даты обновления

Сравни updated: в своих копиях с таблицей. Если старше — заново возьми zip или raw .md. Не сравнивай по mtime.

Основной пакет

ФайлОбновлён
README.mdupdated: 2026-08-10 14:30 GMT+3
SKILL.mdupdated: 2026-08-10 14:30 GMT+3
01-syntax.mdupdated: 2026-08-06 19:20 GMT+3
02-methodology.mdupdated: 2026-08-06 14:19 GMT+3
03-mcp-tools.mdupdated: 2026-08-10 14:30 GMT+3
04-css-generation.mdupdated: 2026-08-06 13:15 GMT+3
05-html-widget-rules.mdupdated: 2026-08-06 23:20 GMT+3
06-russian-typography.mdupdated: 2026-08-06 17:35 GMT+3

Помощники (отдельный zip)

ФайлОбновлён
helpers/README.mdupdated: 2026-08-07 11:45 GMT+3
helpers/source-cleanup.mdupdated: 2026-08-07 11:45 GMT+3
helpers/upload-local-media.ps1mtime: 2026-08-07 11:44:35 MSK

Страница собрана: 2026-08-10 15:19:27 MSK

Справочник правил

Синтаксис Демонстратора

Материал — один Markdown-файл. Интерактив — блоки :::тип:::/тип.

Жёсткие правила

1. Открытие: :::имя в начале строки. Закрытие: только :::/имя в начале строки. Для каждого открытого блока — своё закрытие. Без исключений. 2. URL и текст тела — со следующей строки после :::имя. На строке :::имя — только имя, вариант и модификаторы. 3. Не выдумывай имена, варианты и модификаторы вне таблицы ниже. 4. %% в начале строки — комментарий. При рендере отбрасывается. 5. GFM-таблицы и автолинки поддерживаются. 6. Блок многострочный: :::имя, пункты ===, тело и :::/имяотдельные строки. Не склеивай в одну строку (:::steps === … === … :::/steps — запрещено). 7. :::important — короткая врезка (обычно несколько предложений). Не оборачивай в important весь урок, статью или файл с # заголовками и несколькими разделами. 8. Русский текст — по 06-russian-typography.md: тире —, кавычки «ёлочки», многоточие …; не - и не "..." в прозе.

Полная таблица блоков

БлокВарианты (после имени)МодификаторыРазмеры на строке :::Закрытие
acc:::/acc
tab / tabs:::/tab
flip:::/flip
test:::/test
stepsgrid:::/steps
checklistduo:::/checklist
compare:::/compare
buttongroup:::/button
importantidea, problem, solution, info, rule:::/important
tmpvideo, sim, dialog, hotspot, hint:::/tmp
embedwide— (размеры в теле):::/embed
audio:::/audio
videowideWxH (напр. 960x540):::/video
file:::/file
web_archivewideWxH:::/web_archive
ai_widgetwideWxH:::/ai_widget
picfontchat, right:::/picfont
sliderduowide:::/slider
hotspotwide:::/hotspot
columnswide:::/columns

Пиши :::columns:::/columns.

:::comments — служебный. Не создавай вручную.

Картинка в обычном Markdown — ![подпись](URL). Не оборачивай в ![…](…) URL внутри блоков, где синтаксис требует голый URL (:::audio / :::video / :::picfont / аватары в :::picfont chat и т.п.). Исключение: кадры :::slider и фон :::hotspot — там как раз ![…](URL).

Вложенность

Заголовки

Только ATX уровней 1–3:

Заголовок H1

Заголовок H2

Заголовок H3

H4–H6 и setext не используй.

Текст

НазначениеСинтаксисЗапрещено
Жирный**текст** или __текст__
Курсив*текст* или _текст_
Код` код `
Ссылка[текст](URL)
Картинка![подпись](URL)[текст](URL) без ! — это ссылка, не картинка

Списки: - пункт или * пункт; нумерованные 1. 2.. Маркер + в обычном списке не используй (в чеклисте + — отдельный синтаксис).

Цитата: >, >>, >>> в начале строки.

Разделитель: строка из минимум трёх дефисов ---.

Изображение

Канон:

!Подпись под картинкой

Важное

Краткая форма (одна строка):

!!! Текст замечания.

Блочная форма:

:::important
Текст замечания.
:::/important

С вариантом:

:::important rule
Не храните пароли в чате.
:::/important
ВариантКогдаЧто рисует система
*(без)*ЗамечаниеИконка info, серый фон
ideaСоветЛампочка, жёлтый фон
problemОшибкаТреугольник, красный фон
solutionРешениеГалочка, зелёный фон
infoСправкаInfo, синий фон
ruleНорма / принципПараграф §, акцентный фон

Иконку система добавляет сама. Не вставляй эмодзи и символы иконок в текст блока.

Не используй important как обёртку всего материала. Каркас урока — обычный Markdown (# / ## / абзацы); important — точечный акцент внутри.

Медиа: единый формат тела

БлокСтрока 1 телаСтрока 2+Пример открытия
audioURLподпись (необязательно):::audio
videoURLподпись (необязательно):::video или :::video wide или :::video 960x540
fileURLимя файла (обязательно для подписи):::file
web_archiveURLподпись (необязательно):::web_archive / wide / WxH
ai_widgetURLподпись (необязательно):::ai_widget / wide / WxH
embedURL === WxH одной строкой:::embed или :::embed wide
picfontURLтекст рядом:::picfont или :::picfont right
picfont chatпосле === Имяголый URL аватара, затем текст реплики:::picfont chat
:::audio
https://cdn.longread.agency/demo/audio-sample.mp3
:::/audio
:::video
https://cdn.longread.agency/demo/video-sample.mp4
:::/video
:::file
https://cdn.longread.agency/demo/file-demo.pdf
Раздаточный материал
:::/file
:::web_archive
https://cdn.longread.agency/demo/archive-demo/index.html
:::/web_archive
:::ai_widget
https://cdn.longread.agency/demo/widget-demo.html
:::/ai_widget

Имя блока — ai_widget (не ai-widget). Голый URL HTML в абзаце или «ссылка в чат» не заменяют блок.

ИИ-HTML через MCP: create-widgetsave-widget-draftbake-widgetinsert-ai-widget-block (fence = id) → poll archives/ по маркеру. Не сдавай по draft. Без вставки в материал задача не сдана. Правила — 05-html-widget-rules.md. Внешние картинки без расширения файла на CDN блокируются при bake.

:::embed
https://longread.media === 640x360
:::/embed

По умолчанию для embed без размеров в теле — 640×360.

:::picfont
https://cdn.longread.agency/demo/picfont-icon.webp
Короткий факт рядом с картинкой.
:::/picfont
:::picfont chat
=== Ассистент
https://cdn.longread.agency/demo/avatar-bot.webp
Ответ ассистента.

=== Пользователь
https://cdn.longread.agency/demo/avatar-user.webp
Вопрос пользователя.
:::/picfont

В :::picfont chat у каждой реплики:

1. === Имя (имя собеседника) 2. Следующая строка — только голый HTTPS-URL аватара (без !, без […], без подписи) 3. Далее текст сообщения

Нельзя (ломает чат — аватар становится огромной картинкой в пузыре):

=== Новичок
![Новичок](https://cdn.longread.agency/images/….webp)
Текст реплики.

Нужно:

=== Новичок
https://cdn.longread.agency/images/….webp
Текст реплики.

При замене локальных путей / CDN-URL внутри :::picfont chat меняй только строку URL. Не превращай её в markdown-картинку ![…](url).

Обычный :::picfont (не chat): тоже голый URL на первой строке тела, текст — со второй. Не ![…](url).

Слайдер

:::slider
=== Кадр 1
![Кадр 1](https://cdn.longread.agency/demo/slider-1.webp)
Текст первого кадра.

=== Кадр 2
![Кадр 2](https://cdn.longread.agency/demo/slider-2.webp)
Текст второго кадра.
:::/slider
:::slider duo
=== Было
![До правки](https://cdn.longread.agency/demo/slider-before.webp)
Интерфейс до изменений.

=== Стало
![После правки](https://cdn.longread.agency/demo/slider-after.webp)
Новый интерфейс.
:::/slider

:::slider wide и :::slider duo wide допустимы.

Интерактивы

Аккордеон

:::acc
=== Заголовок пункта
Содержимое пункта.

=== Второй заголовок
Содержимое второго пункта.
:::/acc

Вкладки

:::tab
=== Вкладка 1
Содержимое первой вкладки.

=== Вкладка 2
Содержимое второй вкладки.
:::/tab

Карточки flip

:::flip
=== Термин
Определение на обороте.

=== Второй термин
Второй ответ.
:::/flip

Допустимо однострочно: лицо === оборот.

Хотспот

:::hotspot
![Схема](https://cdn.longread.agency/demo/hotspot-demo.webp)
=== 30% 40% Зона A
Пояснение зоны A.

=== 1 70% 55% Зона B
Маркер с цифрой 1.
:::/hotspot

Кнопка

Кнопки — только внешние ссылки. Не используй их как навигацию по материалу или проекту: у экспорта проекта есть встроенный плеер.

:::button
Подробнее на Longread.Media === https://longread.media
:::/button
:::button group
=== Longread.Media === https://longread.media
=== Ecourse.Studio === https://ecourse.studio
:::/button

Шаги

:::steps
=== Откройте файл
Дважды щёлкните по ярлыку.
=== Сохраните файл
Ctrl+S.
:::/steps

:::steps — столбец со стрелками ↓. :::steps grid — сетка без стрелок.

Чеклист

Маркер в начале строки задаёт тон пункта:

МаркерВидКогда
+Зелёная галочка ✓Плюс, возможность, «как надо», факт-преимущество
-Красный крест ✗Минус, ошибка, «как не надо»

Список возможностей / фич / преимуществ — только +. Не ставь - «по привычке списка»: - в чеклисте = негатив.

:::checklist
+ Правильный пункт
- Неправильный пункт
Пояснение без маркера
:::/checklist
:::checklist duo
=== + Правильно
Верный подход.
=== - Неправильно
Ошибочный подход.
:::/checklist

Сравнение

Ровно две секции ===:

:::compare
=== Плохо
Неструктурированный текст.
=== Хорошо
Текст с заголовками.
:::/compare

Тест

Открытие — только строка :::test. Режим — следующая строка тела: [test] / [verification] или [think] / [narrative].

НельзяНадо
:::test[test]:::test затем строка [test]
:::test testто же
режим на одной строке с :::режим внутри тела

Режим [test] / [verification]: нужен минимум один + и один -.

:::test
[test]
===
Вопрос?
+ Правильный вариант
- Неправильный вариант
ye: Верно!
no: Подумайте ещё.
:::/test

Режим [think] / [narrative]: вариантов с + нет.

:::test
[think]
===
Что вы думаете?
- Вариант 1
- Вариант 2
- Вариант 3
ok: Спасибо за ответ!
:::/test

Строки ye:, no:, ok: необязательны: если их нет, система подставит дефолтный текст. Пиши их явно, когда нужен свой текст обратной связи.

Заглушка

ОткрытиеВид заглушки
:::tmpКарточка 2:1, подпись «Заглушка»
:::tmp videoПодпись «Видео»
:::tmp simПодпись «Симулятор»
:::tmp dialogПодпись «Диалог»
:::tmp hotspotПодпись «Маркеры»
:::tmp hintТекстовая плашка без картинки
:::tmp
Скоро здесь будет схема
:::/tmp

Колонки

:::columns
70-30
===
Первая колонка.
===
Вторая колонка.
:::/columns
НельзяНадо
50/5050-50 или 1:1
=== Заголовок как разделитель=== пустой; заголовок — ###

Служебное

Строка <<текст>> — метка задачи. Рендерится как текст в угловых кавычках.

CDN-заполнители

БлокURL
Изображениеhttps://cdn.longread.agency/demo/image-demo.webp
Хотспотhttps://cdn.longread.agency/demo/hotspot-demo.webp
Аудиоhttps://cdn.longread.agency/demo/audio-sample.mp3
Видеоhttps://cdn.longread.agency/demo/video-sample.mp4
Файлhttps://cdn.longread.agency/demo/file-demo.pdf
Веб-архивhttps://cdn.longread.agency/demo/archive-demo/index.html
ИИ-HTMLhttps://cdn.longread.agency/demo/widget-demo.html
Picfonthttps://cdn.longread.agency/demo/picfont-icon.webp
Аватар ботhttps://cdn.longread.agency/demo/avatar-bot.webp
Аватар пользовательhttps://cdn.longread.agency/demo/avatar-user.webp
Слайдер…/slider-1.webp, slider-2.webp, slider-3.webp
Слайдер duo…/slider-before.webp, …/slider-after.webp
Обложка проектаhttps://cdn.longread.agency/demo/project-cover.webp

Методика: какой блок выбрать

Используйте эту таблицу для выбора блока под задачу.

Быстрый выбор

ЗадачаБлок
FAQ, глоссарий, однородные пункты «заголовок → текст»:::acc
Равнозначные панели, сценарии:::tab
Термин ↔ определение, самопроверка:::flip
Проверка знаний:::test
Процесс с порядком, инструкция:::steps
Критерии, плюсы/минусы, «как надо»:::checklist
Контраст «плохо ↔ хорошо»:::compare
Важная оговорка, идея, правило!!! или :::important
Кликабельные точки на схеме:::hotspot
Две–три колонки вёрстки:::columns

Когда что использовать

Аккордеон (:::acc)

Используйте для однородных пунктов: заголовок открывает пояснение по клику.

Подходит для:

Не путайте с :::steps. Аккордеон не нумерует пункты.

Вкладки (:::tab)

Используйте для равнозначных панелей с короткими ярлыками.

Подходит для:

Не используйте вкладки для контраста «плохо/хорошо». Для этого — :::compare или :::checklist duo.

Карточки (:::flip)

Используйте для самопроверки: вспомнил → перевернул → проверил.

Лицо — тезис. Оборот — развёрнутый ответ.

Глоссарий из 10+ терминов лучше делать аккордеоном.

Тест (:::test)

Не ставьте [test] с искусственным + там, где подходит [think].

Шаги (:::steps)

Используйте для процесса с порядком: инструкция, алгоритм, «сначала → потом».

Не используйте :::steps для норм без последовательности. Для этого — :::important rule или чеклист.

Чеклист (:::checklist)

Используйте для критериев, требований, списка «что проверить» или списка возможностей.

Отличие от :::compare: чеклист — набор пунктов с ✓/✗. Сравнение — ровно 2 текстовые колонки.

Тест (:::test)

Сравнение (:::compare)

Используйте для контраста подходов. Ровно 2 колонки с заголовками.

Важное (:::important)

Хотспот (:::hotspot)

Используйте для схемы или фото с кликабельными точками.

Требуется реальная картинка ![…](url). Без маркеров блок ведёт себя как обычное изображение.

Колонки (:::columns)

Используйте для параллельной вёрстки: текст + врезка, две равные колонки.

Пишите :::columns:::/columns.

Соотношение: пресет (2:1, 1:1:1) или проценты через дефис (70-30). Не 50/50. Разделитель — пустой ===. Заголовки внутри — ###.

Не заменяйте колонками :::compare или :::checklist duo. В колонках нет семантики «плохо/хорошо».

Не путать

ХотелиНе ставьтеСтавьте
Последовательность шагов:::acc с «Шаг 1» в заголовках:::steps
Норма / принцип:::steps:::important rule
Контраст «плохо / хорошо»Две вкладки:::compare
Много пунктов ✓/✗:::compare:::checklist или :::checklist duo
Глоссарий 10+ терминовПачка :::flip:::acc
Опрос без верного ответа[test] с искусственным +[think]
Две колонки50/50 в первой строке50-50 или 1:1

Anti-patterns: wrong → right

Шаги как аккордеон — нельзя

Так нельзя:

:::acc
=== Шаг 1
Откройте файл.
=== Шаг 2
Сохраните файл.
:::/acc

Так надо:

:::steps
=== Откройте файл
Дважды щёлкните по ярлыку.
=== Сохраните файл
Ctrl+S или меню «Файл».
:::/steps

Норма как steps — нельзя

Так нельзя:

:::steps
=== Правило 1
Не храните пароли в чате.
:::/steps

Так надо:

:::important rule
Не храните пароли в чате.
:::/important

Плохо/хорошо вкладками — нельзя

Так нельзя:

:::tab
=== Плохо
Длинный абзац без структуры.
=== Хорошо
Список и заголовки.
:::/tab

Так надо:

:::compare
=== Плохо
Длинный абзац без структуры.
=== Хорошо
Список и заголовки.
:::/compare

Колонки со слэшем — нельзя

Так нельзя:

:::columns
50/50
===
Левая.
===
Правая.
:::/columns

Так надо:

:::columns
50-50
===
Левая.
===
Правая.
:::/columns

Опрос с фейковым «верным» — нельзя

Так нельзя:

:::test
[test]
===
Как вам курс?
+ Отлично
- Нормально
ye: Верно!
no: Неверно.
:::/test

Так надо:

:::test
[think]
===
Как вам курс?
- Отлично
- Нормально
- Сложно
ok: Спасибо за ответ!
:::/test

Режим теста на строке открытия — нельзя

Так нельзя:

:::test[test]
===
Вопрос?
+ Да
- Нет
:::/test

Так надо:

:::test
[test]
===
Вопрос?
+ Да
- Нет
:::/test

Фичи чеклистом с минусами — нельзя

Так нельзя (все пункты красные ✗):

:::checklist
- Поддерживает мультимодальные запросы
- Использует Query Fan-Out
:::/checklist

Так надо (зелёные ✓):

:::checklist
+ Поддерживает мультимодальные запросы
+ Использует Query Fan-Out
:::/checklist

Весь урок в important — нельзя

Так нельзя: открыть :::important idea в начале файла и закрыть :::/important в конце, а внутри — #, ##, steps, compare.

Так надо: обычный Markdown-каркас; :::important только на короткий акцент (несколько предложений).

Блок в одну строку — нельзя

Так нельзя:

:::steps === Шаг 1 Текст. === Шаг 2 Текст. :::/steps

Так надо:

:::steps
=== Шаг 1
Текст.
=== Шаг 2
Текст.
:::/steps

То же для :::compare и :::checklist duo.

Размещение и объём

Не выдумывайте несуществующих типов блоков. Используйте только идентификаторы из допустимого списка.

MCP-инструменты Демонстратора

Карта инструментов (имя → зачем). Полные схемы параметров не дублируются здесь.

Параметры инструментов

После подключения MCP клиент вызывает tools/list. Сервер отдаёт канонические inputSchema (required, типы, enums, лимиты).

Подключение к MCP

Подпишись на remote MCP-шлюз на сервере Демонстратора. Клонировать репозиторий и запускать node локально не нужно.

Токен — в Личном кабинете Демонстратора (раздел MCP / API-токен).

{
  "mcpServers": {
    "demonstrator-mcp": {
      "url": "https://app.longread.agency/mcp/demonstrator/mcp",
      "headers": {
        "Authorization": "Bearer ВСТАВЬ_ТОКЕН_ИЗ_ЛК"
      }
    }
  }
}

Эндпоинты шлюза:

МетодURLНазначение
GEThttps://app.longread.agency/mcp/demonstrator/healthПроверка живости
GEThttps://app.longread.agency/mcp/demonstrator/sseSSE (keepalive; Cursor сюда url не ставь)
POSThttps://app.longread.agency/mcp/demonstrator/mcpJSON-RPC / streamable HTTP — это URL для IDE

Happy path: материал с нуля

1. list-projectsproject_id (или create-project). 2. create-materialtitle + project_id. 3. Markdown по 01-syntax.md / 02-methodology.md. 4. Запись тела — только через Yjs collab-мост, не прямым PATCH в БД:

или save-material-content (тот же POST /api/collab/materials/:id/patch);

5. Проверить verify.ok / get-material. В ответе смотри source: yjs_room (комната открыта) или db_fallback.

Запрещено писать markdown через raw PATCH /api/materials с полем content (tool update-material-content удалён): открытый редактор перезапишет старым Yjs-документом.

Полный маршрут и сценарий без MCP — в README.md.

Каталог (обзор)

Ниже — имя и краткое действие. Схемы полей — в tools/list.

Проекты и пространства

ИнструментДействие
list-projectsПолучить список проектов
create-projectСоздать проект
update-projectОбновить проект
list-spacesПолучить список пространств
get-spaceПолучить пространство
update-spaceПереименовать пространство
list-space-membersСписок участников (только чтение)

Создание пространства, приглашения, смена состава/ролей, permanent delete-project — только через UI, не через MCP.

Структура

ИнструментДействие
list-sectionsСписок разделов (с sort_order, среди разделов)
create-sectionСоздать раздел
update-sectionОбновить раздел (в т.ч. одиночный sort_order)
reorder-sectionsПорядок только среди разделов (sort_order)
delete-sectionУдалить раздел (soft delete)
list-materialsСписок материалов (с sort_order)
search-materialsПолнотекстовый поиск по материалам
create-materialСоздать материал
duplicate-materialКлонировать материал (суффикс «(копия)»)
update-material-placementПереместить материал / один sort_order
reorder-materialsПорядок уроков внутри раздела (или среди корневых)
get-project-sequenceСмешанный порядок карточек проекта: раздел ↔ корневой прототип
patch-project-sequenceЗадать смешанный порядок (как DnD в ЛК)
delete-materialУдалить материал (soft delete)

Порядок: три разных оси (не путать)

Что меняешьToolГде видно
Раздел ↔ корневой прототип вперемешкуget-project-sequence / patch-project-sequenceсетка карточек проекта в ЛК
Порядок разделов между собойreorder-sections (sort_order)среди разделов
Порядок уроков внутри разделаreorder-materials + section_idвнутри раздела

Можно чередовать: раздел → прототип → раздел → прототип. Это штатный project_sequence, не запрет продукта.

Стартовый/пустой sequence (миграция + UI-fallback) часто выглядит как «сначала все разделы, потом корневые» — дефолт, не закон. Не сочиняй «разделы всегда сверху» / «без разделов только плоский список».

Дерево слева sequence почти не отражает: смешанный список — в сетке карточек.

patch-project-sequence: items: [{ "item_type": "section"|"material", "item_id": N }, …] сверху вниз. В items только корневые материалы (без section_id). Перед вызовом — подтверждение пользователя (см. СТОП в README.md).

reorder-sections / reorder-materials не умеют смешивать типы — для этого только sequence.

Медиа

ИнструментДействие
list-resourcesСписок ресурсов (фильтр: projectid, materialid, q)
presign-media-uploadInit upload audio/video/file/web_archive → resource_id + upload_url (PUT с машины клиента)
complete-media-uploadComplete после PUT → id, status, full_url (CDN), markdown_snippet
upload-media-from-fsЗагрузка по file_url (HTTPS) или file_path уже на сервере MCP — не Windows-path клиента
get-resource-statusСтатус обработки медиа (poll до ready / failed)
insert-media-blockВставить медиа-блок; display_name / name → имя в медиатеке
rename-resourceПереименовать ресурс

Permanent удаление ресурса — только UI (delete-resource в MCP нет).

Upload и insert: осмысленный filename / display_name. «Без названия» в медиатеке — брак; сразу rename-resource.

Как загрузить локальный файл → Object Storage → CDN

MCP не читает файлы с диска агента (C:\…). Не вызывай upload-media-from-fs с Windows-path. insert-media-block файл не загружает. Сначала upload, потом insert.

Запрещено

#### Выбор пути

Что на диске агентаКак
Картинка (image)Shell curl multipart (ниже)
audio / video / file / web_archiveMCP presign-media-upload → Shell PUT → MCP complete-media-upload
Уже HTTPS URLMCP upload-media-from-fs с file_url + material_id/project_id

После upload вызови MCP insert-media-block или вставь ![…](full_url) в content. Processing-медиа: get-resource-status до ready / failed. На каждом upload передай material_id или project_id.

ASCII-only на диске. Путь и имя файла для upload — только латиница/цифры (C:\work\media\fig-01.png). Кириллица в папках или имени файла ломает curl у агентов. Русское имя в медиатеке — после upload: rename-resource или display_name / name в insert-media-block.

#### Картинка — curl

Токен — из ЛК (тот же Bearer, что у MCP). Prod API: https://app.longread.agency.

curl.exe -sS -X POST "https://app.longread.agency/api/resources" `
  -H "Authorization: Bearer TOKEN_FROM_LK" `
  -H "Accept: application/json" `
  -F "file=@C:\work\media\fig-01.png;filename=fig-01.png;type=image/png" `
  -F "material_id=123" `
  -F "original_name=fig-01.png"

1. Из JSON возьми id и full_url (или url). 2. Вызови insert-media-block или вставь ![подпись](full_url). 3. Задай читаемое имя. Иначе вызови rename-resource.

Для image нет presign-media-upload. Нет MCP-tool, который читает локальный png. Если upload-local-media.ps1 уже лежит в текущем workspace — можно вызвать его вместо curl. Иначе делай curl. Не сканируй диск.

#### audio / video / file / web_archive

1. MCP presign-media-upload (kind, filename, size, material_id или project_id). 2. Shell: curl.exe -sS -X PUT "<upload_url>" -H "Content-Type: …" --data-binary "@C:\path\to\file". 3. MCP complete-media-upload (тот же material_id / project_id). 4. MCP insert-media-block.

#### Уже публичный HTTPS

MCP upload-media-from-fs: только file_url (https://…). Не C:\….

Медиатека проекта

Медиатека = resource_links на project_id / material_id.

Что не делать

ИИ-HTML (:::ai_widget)

ИнструментДействие
create-widgetСоздать черновик ИИ-HTML. Обязательно name (или caption / original_name) — имя в медиатеке
get-widgetПолучить ИИ-HTML; у linear_dialog — ещё archetype + scenario
save-widget-draftСохранить HTML в черновик (свободная вёрстка). Не для правок линейного диалога
assemble-linear-dialogСобрать или обновить линейный диалог из полного scenario JSON (без Studio AI). Фича ai_widget_templates (тестеры)
bake-widgetСобрать ИИ-HTML в готовый архив
fork-widgetФоркнуть ИИ-HTML в другой материал
insert-ai-widget-blockВставить :::ai_widget в материал

Имя в медиатеке

Ресурс без нормального original_name в UI выглядит как «Без названия» / бессмысленный дефолт. Это брак.

Не готово: виджет/файл в медиатеке без читаемого имени.

Путь создания ИИ-HTML (только IDE + MCP)

локальный .html + маркер + отладка → вопрос «bake на CDN?» → «да» →
create-widget → save-widget-draft → bake-widget (ready) →
insert-ai-widget-block (fence = id, не draft) →
poll archives/ до совпадения маркера → get-material

1. Запиши и отладь HTML в workspace (widgets/<slug>.html). Добавь уникальный маркер. 2. Спроси пользователя про bake/insert. Жди прямого «да». Не вызывай bake-widget на каждой правке. 3. create-widgetsave-widget-draft (HTML с диска) → bake-widget. 4. insert-ai-widget-block — в блок только CDN entry_url после bake (ready). Draft URL и bare id в материал запрещены. 5. Poll: get-resource-status / archive-info → HTML с archives/ (entry_url, учти ?v=). Маркер должен совпасть с локальным файлом. get-widget и draft — не критерий сдачи. 6. get-material — fence на месте. Путь к локальному файлу — пользователю.

В create-widget всегда передай name (имя в медиатеке). Без имени — не готово; при ошибке — rename-resource.

Шаблон: линейный диалог (assemble-linear-dialog)

Когда нужен диалоговый плеер, не пиши HTML с нуля — собери сценарий JSON и вызови assemble-linear-dialog. Shell канонический; агент заполняет данные (пул портретов, локации, реплики с парой слотов).

scenario.json на диске → create-widget → assemble-linear-dialog →
вопрос «bake на CDN?» → «да» → bake-widget → insert-ai-widget-block (CDN URL)

1. Сохрани scenario локально (widgets/<slug>-scenario.json). Поля: characters[] (пул портретов), steps[] с leftPortraitId / rightPortraitId / speakerSide, опционально locations[]. Эталон: docs/templates/linear-dialog/scenario.example.json. 2. На сцене всегда два слота картинок; characters[] — N вариаций (ракурсы/эмоции). На каждой реплике задай пару портретов и кто говорит (speakerSide: left|right). 3. Демо-медиа CDN: avatar-bot.webp, avatar-user.webp, slider-1.webp на cdn.longread.agency/demo/. 4. create-widget с nameassemble-linear-dialog (widget_id + scenario). Не нужен save-widget-draft. 5. Bake/insert — только после прямого «да» (как у свободного HTML). Insert пишет CDN entry_url, не id. 6. При 403 ai_widget_templates_forbidden — шаблоны только у тестеров; не обходи через свободный HTML без согласования.

Правка существующего линейного диалога

Тот же assemble-linear-dialogсоздаёт и обновляет. Отдельного «refine» в MCP нет (Studio AI через MCP не вызываем).

get-widget → взять scenario → править JSON (локально или в ответе) →
assemble-linear-dialog (полный scenario) → при необходимости снова bake после «да»

1. get-widget (widget_id) → поля archetype: linear_dialog и scenario. 2. Если scenario пуст — вытащи из HTML #vn-scenario или восстанови из локального widgets/<slug>-scenario.json. 3. Внеси правки в полный scenario (реплики, портреты пула, leftPortraitId/rightPortraitId/speakerSide, локации, порядок steps / next). Не отправляй diff / SEARCH-REPLACE по shell. 4. Обнови локальный widgets/<slug>-scenario.json. 5. assemble-linear-dialog с тем же widget_id и полным scenario — пересоберёт draft. 6. Запрещено для диалога: save-widget-draft с ручным HTML плеера; правка CSS/JS shell; вызов /api/ai/widgets/*/refine*. 7. Повторный bake-widget / insert — только после прямого «да» пользователя (как при создании).

Чат-боты без MCP этот путь не используют. Они отдают HTML/markdown кодом и bake не делают.

Не готово (IDE): только bare id в fence; bake без «да»; bake без локального файла; bake без insert; сдача по draft при отстающем archive; fence с draft_url; ресурс в медиатеке без читаемого имени.

Серверный контракт — 05-html-widget-rules.md.

Корзина

ИнструментДействие
list-project-trashСписок удалённого
restore-project-trashВосстановить (items: [{type, id}] или all: true)

Share-ссылки

Создание и обновление — да. Снятие / unpublish ссылок через MCP нельзя (только UI).

ИнструментДействие
get-material-share-linksСсылки материала
create-material-share-linkСоздать ссылку материала
update-material-share-linkОбновить уже созданную ссылку материала (auto_update)
get-project-share-linksСсылки проекта
create-project-share-linkСоздать или обновить (refresh_only: true — без ротации токенов)
get-section-share-linksСсылки раздела
create-section-share-linkСоздать или обновить (refresh_only)
republish-comments-snapshotОбновить HTML-snapshot для публичной ссылки с правками. Не пишет тело урока (content)

Ответ create/get содержит url — полный канонический URL.

Типы ссылок: preview (просмотр), preview_comments (с комментариями).

Comment/share ≠ editor body. republish-comments-snapshot, share-links с preview_comments и get-material-preview-with-comments — про публичный review/HTML. Текст урока в редакторе правят только save-material-content / apply-material-point-patch. В ответах материала нет внутренних publish-кэшей — только content.

Чтение и экспорт

ИнструментДействие
get-materialid, title, content, theme, version, placement (whitelist)
get-material-export-dataMarkdown + тема материала
get-section-export-dataРаздел + все материалы с контентом
get-project-export-dataДерево проекта для HTML-ZIP
get-material-preview-with-commentsRead-only HTML snapshot+overlay; не источник для правки markdown

Предложения правок

Сейчас вне MCP (недоделано; вернём позже). Пиши тело сразу через collab (save-material-content / apply-material-point-patch).

Запись контента

Источник правды при открытом редакторе — Yjs collab, не строка в БД. Все правки тела материала — через collab-мост.

ИнструментДействие
apply-material-point-patchКанон. replace_all / range_patch / find_replace_once/api/collab/materials/:id/patch
save-material-contentПолная замена тела тем же collab-мостом (replace_all) + опционально title/theme. По умолчанию verify_readback: true
apply-material-themeТема (palette / contentStyle / customOverlayCss)

Режимы apply-material-point-patch

РежимКогда использовать
replace_allЗамена всего контента (основной путь «записать материал»)
range_patchПравка по смещению: operations: [{ start, delete_count, insert_text }]
find_replace_onceЗамена по тексту: find_text + replace_text. Самый надёжный для кириллицы

Все write-операции используют expected_version (tool подставит сам, если не передан).

Ответ содержит source:

Если материал открыт в редакторе, а запись в Yjs невозможна, API вернёт 409 (editor_open_room_not_ready / collab_room_push_failed). Не считай это успехом. Закрой вкладку или повтори, когда комната готова. Тихого db_fallback при открытом редакторе больше нет — иначе открытая вкладка затрёт правки агента.

После записи проверяйте verify.ok и source. Не пишите тело через raw PATCH «в базу». Вторичных «workspace»/publish body-полей в ответах нет — править нечего, кроме content через collab.

Темы

ИнструментДействие
list-themesСписок пресетов: minimalism, draft, journal, neon, airy, modern
apply-material-themeПрименить тему. Поддерживает contentStyle: "custom" + customOverlayCss
inherit-project-themesСбросить темы разделов/уроков проекта на наследование от темы проекта

Правила CSS для customOverlayCss — см. раздел «Правила CSS-генерации».

Правила CSS-генерации тем

Вы пишете CSS для apply-material-theme с параметром customOverlayCss. Этот CSS изменяет внешний вид материала. Соблюдайте правила ниже.

CSS-переменные

Материалу гарантированно доступны переменные в :root. Используйте их для цветов. Не хардкодьте цвета.

ПеременнаяПо умолчаниюНазначение
--longread-bg#f8f8f8Фон страницы
--longread-text#222Цвет текста
--longread-surface#fffФон карточек
--longread-surface-text#222Текст на карточках
--longread-headings#222Цвет заголовков
--longread-accent#1f3249Акцентный цвет
--longread-accent-pale#e0e0e0Бледный акцент
--longread-bordervar(--longread-accent-pale)Цвет границ
--longread-positive#20a020Зелёный (хорошо)
--longread-negative#d04040Красный (плохо)
--longread-important-bg#f5f5f5Фон блока important
--longread-content-padding1.5em 1.25emОтступ контента
--longread-block-padding1em 1.25emОтступ внутри блоков
--longread-block-margin1.65emОтступ между блоками

Селекторный контекст

Каждое правило начинайте с .longread-theme-custom.

Запрещены селекторы: body, html, :root.

/* Верно */
.longread-theme-custom h1 { color: var(--longread-accent); }

/* Запрещено */
body { background: #fff; }

Опасные CSS-свойства

Эти свойства могут сломать вёрстку блоков Демонстратора:

display, position, flex, grid, width, height, overflow.

Если задача требует одного из этих свойств — сначала предупреди пользователя: объясни, что свойство может поломать вёрстку. Меняй только после прямого подтверждения пользователя.

Безопасные CSS-свойства

По умолчанию используй эти свойства — они не ломают вёрстку:

border, border-radius, border-color, background, font-family, font-size, font-weight, color, text-shadow, box-shadow, padding, margin, transform, letter-spacing.

Псевдоэлементы ::before и ::after разрешены везде, кроме селекторов ниже.

Селекторы с высоким риском

Эти селекторы управляют критичной вёрсткой блоков. Если задача требует их стилизации — сначала предупреди пользователя, что возможна поломка. Меняй только после прямого подтверждения.

Селекторы с ограничениями

.block.important

.flip-front и .flip-back

blockquote

Три уровня цитат. Используйте эти селекторы.

Уровень 1:

.longread-theme-custom > blockquote:not(:has(blockquote)),
.longread-theme-custom :not(blockquote) > blockquote:not(:has(blockquote)) {
  /* стили уровня 1 */
}

Контейнер цитаты (сброс):

.longread-theme-custom blockquote:has(> blockquote) {
  border: none;
  background: none;
  box-shadow: none;
  padding-left: 0;
}

Уровень 2:

.longread-theme-custom blockquote:not(:has(> blockquote > blockquote)) > blockquote:not(:has(blockquote)) {
  /* только color, font-style, font-size */
  /* без border, без ::before */
}

Уровень 3:

.longread-theme-custom blockquote blockquote blockquote {
  /* border, border-radius, background, padding */
  /* ::before { content: none } */
}