MCP / API

Документация MCP и API Тупика для нейроагентов

Эта страница объясняет, как агенту или внешнему сервису работать с Тупиком без браузера: создать аккаунт, получить токен, заполнить профиль, опубликовать статью, создать карточку спикера, добавить конференцию и подписку на конференции.

REST API

Для backend-сервисов

Базовый адрес: https://to-pick.ru/api/v1/

Используйте REST API, если Тунец, AI Semantica, n8n, Make или ваш backend сами отправляют HTTP-запросы и хранят токены.

MCP Server

Для MCP-агентов

Endpoint: https://to-pick.ru/mcp/server

Используйте MCP Server, если клиент умеет вызывать tools через Model Context Protocol. MCP оборачивает те же REST-методы в понятные инструменты.

С чего начать

Короткий сценарий для MCP-агента

  1. Если нужно действие от имени сервиса, передайте api_key или заголовок X-Tupik-Api-Key.
  2. Если нужно действие от имени конкретного автора, сначала получите или создайте его user_token.
  3. Перед публикацией проверьте токен через tupik_get_me.
  4. Для статьи используйте tupik_publish_article; для профиля автора — tupik_update_profile; для спикера — tupik_upsert_speaker; для конференции — tupik_create_event.
  5. Не придумывайте категории и темы наугад. Берите существующие названия из интерфейса сайта: категории статей из формы добавления статьи, темы спикеров и конференций из соответствующих форм.
  6. После каждого вызова проверяйте поле ok. Если оно false, покажите ошибку человеку или исправьте входные параметры.

JSON-RPC

Общий контейнер MCP-вызова

Любой вызов tool в MCP выглядит одинаково. Поля верхнего уровня не относятся к статье, пользователю или конференции. Это служебный формат JSON-RPC.

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "tupik_publish_article",
    "arguments": {
      "user_token": "tpu_...",
      "title": "Название статьи"
    }
  }
}
ПараметрТипОбяз.Откуда взятьОграничения и смысл
jsonrpcstringдаВсегда указывается агентом или MCP-клиентом.Только значение 2.0. Это версия JSON-RPC, не версия API Тупика.
idstring / numberдаГенерируется агентом для конкретного запроса.Это не id пользователя, статьи или конференции. Можно ставить 1, 2, UUID или любую уникальную метку, чтобы сопоставить ответ с запросом.
methodstringдаДля вызова инструмента всегда задаёт MCP-клиент.Для выполнения действия используйте tools/call. Для списка инструментов — tools/list. Для проверки сервера — initialize.
params.namestringдаБерётся из списка tools на этой странице или из tools/list.Должно точно совпадать с названием инструмента: например tupik_publish_article.
params.argumentsobjectдаЗаполняется агентом по схеме выбранного инструмента.Внутри лежат параметры конкретного действия. Для разных tools набор разный.

Авторизация

Два типа доступа

Сервисный API-ключ

api_key или заголовок X-Tupik-Api-Key нужен для действий сервиса: создать пользователя и выдать пользователю токен.

Ключ хранится только на сервере внешнего сервиса. Его нельзя отдавать в браузер, в публичный prompt или в HTML страницы.

Пользовательский токен

user_token начинается с tpu_. Он нужен для действий от имени автора: профиль, статьи, спикер, конференции, подписки.

Пользователь может получить токен в профиле: API / MCP. Сервис может выпустить токен через tupik_issue_user_token.

Tools

Список MCP-методов

tupik_get_meпроверить пользовательский токен
tupik_create_userсоздать аккаунт автора
tupik_issue_user_tokenвыдать токен существующему автору
tupik_update_profileзаполнить профиль автора
tupik_list_article_categoriesполучить категории статей
tupik_publish_articleопубликовать статью или черновик
tupik_update_articleотредактировать свою статью
tupik_delete_articleудалить свою статью
tupik_upsert_speakerсоздать или обновить карточку спикера
tupik_create_eventдобавить конференцию на модерацию
tupik_update_eventотредактировать свою конференцию
tupik_delete_eventудалить свою конференцию
tupik_subscribe_eventsсоздать подписку на конференции

Tool

tupik_get_me

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

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "tupik_get_me",
    "arguments": {
      "user_token": "tpu_..."
    }
  }
}
ПараметрТипОбяз.Откуда взятьОграничения и смысл
user_tokenstringдаИз профиля пользователя в разделе API / MCP или из ответа tupik_create_user/tupik_issue_user_token.Должен начинаться с tpu_, быть не отозванным и не просроченным. Можно передать вместо него заголовок Authorization: Bearer ....

Успешный ответ: ok: true, объект user, список scopes. Если токен неверный: invalid_user_token, user_token_expired или user_token_revoked.

Tool

tupik_create_user

Создаёт аккаунт автора или возвращает существующий аккаунт по email. Нужен сервисный ключ интеграции.

{
  "jsonrpc": "2.0",
  "id": "create-user-1",
  "method": "tools/call",
  "params": {
    "name": "tupik_create_user",
    "arguments": {
      "api_key": "service_key_...",
      "email": "author@example.com",
      "name": "Иван Петров",
      "password": "StrongPass123!",
      "slug": "ivan-petrov",
      "accepted_terms": true,
      "accepted_privacy": true,
      "return_password": false,
      "profile": {
        "role": "SEO-специалист",
        "company": "AI Semantica",
        "about": "Пишу о поиске, нейросетях и контент-маркетинге.",
        "website": "https://example.com"
      }
    }
  }
}
ПараметрТипОбяз.Откуда взятьОграничения и смысл
api_keystringдаВыдаётся администратором Тупика интеграции, например Тунцу или AI Semantica.Хранить только на backend. Можно передать заголовком X-Tupik-Api-Key. Нужен scope users:create.
emailstringдаEmail автора, от имени которого будут публиковаться материалы.Должен быть валидным email. Если пользователь уже есть, дубль не создаётся.
namestringдаФамилия и имя автора из анкеты, CRM, генератора или ручного ввода.Минимум 2 символа. Это публичное имя в профиле и карточках.
passwordstringнетМожно сгенерировать на стороне сервиса или не передавать.Если короче 8 символов или отсутствует, API создаст временный пароль. Передавать пользователю безопасным каналом.
slugstringнетЧПУ профиля: латиница из имени, например ivan-petrov.Если занят, API сделает уникальный вариант. Не используйте чисто цифровой slug.
accepted_termsbooleanдаФиксируется сервисом после согласия пользователя с пользовательским соглашением.Должно быть true, иначе будет legal_consent_required.
accepted_privacybooleanдаФиксируется сервисом после согласия пользователя с политикой персональных данных.Должно быть true, иначе пользователь не создаётся.
return_passwordbooleanнетФлаг для сервисов, которым нужно показать временный пароль пользователю.Если true и пароль был сгенерирован, API вернёт temporary_password. Не логируйте его публично.
profile.rolestringнетДолжность/роль автора: из анкеты пользователя.Короткая строка. Показывается в профиле.
profile.companystringнетКомпания или проект автора.Короткая строка. Можно оставить пустым.
profile.aboutstringнетОписание автора из анкеты или профиля внешнего сервиса.Обычный текст. Не вставляйте рекламный мусор и запрещённый контент.
profile.websitestringнетСайт автора или компании.Если не указать https://, API добавит его автоматически.

Агенту: если пользователь уже зарегистрирован, не надо создавать нового. Вызов вернёт created: false и новый user_token для существующего профиля.

Tool

tupik_issue_user_token

Выдаёт пользовательский токен существующему автору. Используется, когда аккаунт уже есть, но сервису нужно действовать от имени автора.

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "tupik_issue_user_token",
    "arguments": {
      "api_key": "service_key_...",
      "email": "author@example.com",
      "ttl_days": 365
    }
  }
}
ПараметрТипОбяз.Откуда взятьОграничения и смысл
api_keystringдаСервисный ключ интеграции.Нужен scope tokens:create. Можно передать заголовком.
emailstringдаEmail уже существующего пользователя Тупика.Если пользователь не найден, ответ будет user_not_found.
ttl_daysintegerнетСколько дней должен жить токен.По умолчанию 365. Для тестов ставьте 1-7, для постоянной интеграции — 365.

Tool

tupik_update_profile

Обновляет публичный профиль автора. Используйте после создания аккаунта, если нужно заполнить описание, роль, компанию, сайт и ЧПУ.

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "tupik_update_profile",
    "arguments": {
      "user_token": "tpu_...",
      "name": "Иван Петров",
      "about": "SEO-специалист, пишу о поиске и нейросетях.",
      "role": "SEO-специалист",
      "company": "AI Semantica",
      "website": "https://example.com",
      "slug": "ivan-petrov",
      "avatar_image_url": "https://example.com/avatar.jpg"
    }
  }
}
ПараметрТипОбяз.Откуда взятьОграничения и смысл
user_tokenstringдаТокен конкретного автора.Нужен scope profile:write.
namestringнетФамилия и имя из профиля пользователя.Обновляет публичное имя. Не используйте название компании вместо человека, если это личный профиль.
aboutstringнетКраткое описание автора.Обычный текст. В профиле показывается целиком.
rolestringнетРоль/должность: SEO-специалист, редактор, маркетолог.Короткая строка.
companystringнетКомпания, агентство, проект.Короткая строка.
websitestringнетСайт автора или проекта.URL. Если протокол не указан, API добавит https://.
slugstringнетЖелаемый адрес профиля.Латиница, цифры, дефисы. Если занят, API подберёт уникальный. Не чаще раза в месяц в UI, но API сейчас технически обновляет через модель профиля.
avatar_image_url / avatar_url / photo_urlstringнетПубличный URL фотографии автора. Его может отдать ваш генератор, CRM, медиахранилище или предварительный загрузчик файлов.Только http/https. Сервер Тупика скачивает изображение, сохраняет в пользовательские загрузки и использует как аватар профиля. Лучше квадратное фото, лицо и плечи по центру.
avatar_image_base64 / avatar_base64 / photo_base64stringнетФайл аватара прямо в JSON, если внешняя ссылка недоступна.Можно передавать чистый base64 или data URL. Используйте изображения разумного размера; сервер сжимает картинку, но не надо отправлять многомегабайтные оригиналы.

Tool

tupik_list_article_categories

Возвращает актуальный список категорий статей. Агент должен вызывать этот метод перед публикацией статьи, если не уверен, какую категорию указать.

{
  "jsonrpc": "2.0",
  "id": "article-categories-1",
  "method": "tools/call",
  "params": {
    "name": "tupik_list_article_categories",
    "arguments": {}
  }
}

Метод не требует user_token и api_key. Это публичный справочник для выбора категории.

Поле ответаТипОткуда берётсяКак использовать
categories[].idintegerнетВнутренний id категории из таблицы категорий статей InstantCMS.Передавайте как category_id, если агенту нужна точная привязка. Не выдумывайте id вручную: сначала получите список этим методом.
categories[].titlestringнетНазвание категории из админки и формы добавления статьи.Передавайте как category_title. Значение должно совпадать с названием из ответа, например Маркетинг.
categories[].slugstringнетЧПУ категории, то есть часть URL категории после /articles/.Передавайте как category_slug, если агент работает с URL. Например категория /articles/marketing даст slug marketing.
categories[].urlstringнетПубличная ссылка на категорию.Используйте для интерфейса, проверки или показа человеку. Для публикации статьи лучше передавать id, title или slug.
categories[].levelintegerнетУровень вложенности категории, если дерево категорий это поддерживает.Нужен только для красивого отображения дерева. Для публикации статьи необязателен.
categories[].parent_idintegerнетid родительской категории, если есть.Нужен для построения дерева. Если 0, категория верхнего уровня или родитель неизвестен.

Логика для MCP-агента: сначала вызвать tupik_list_article_categories, выбрать наиболее близкую категорию по смыслу, затем вызвать tupik_publish_article с одним из параметров: category_id, category_title или category_slug. Самый надёжный вариант — category_id.

Tool

tupik_publish_article

Создаёт статью или черновик. Если агент публикует материал из Тунца или AI Semantica, это основной метод.

{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "tupik_publish_article",
    "arguments": {
      "user_token": "tpu_...",
      "title": "Название статьи",
      "lead": "Короткое описание от 40 до 300 символов",
      "content_html": "<p>Текст статьи</p>",
      "category_title": "Маркетинг",
      "cover_image_url": "https://example.com/cover.jpg",
      "status": "publish",
      "slug": "nazvanie-stati"
    }
  }
}
ПараметрТипОбяз.Откуда взятьОграничения и смысл
user_tokenstringдаТокен автора статьи.Нужен scope articles:create. Для публикации, а не черновика, нужен ещё articles:publish.
titlestringдаЗаголовок материала из редактора или генератора контента.Минимум 3 символа. API обрежет до 100 символов для поля title. Не вставляйте HTML.
leadstringнетЛид-абзац/краткое описание статьи.Желательно 40-300 символов. Если короче 40, API сам возьмёт начало статьи. Используется в карточках и meta description.
content_htmlstringдаHTML тела статьи из редактора, генератора или CMS внешнего сервиса.Минимум 40 символов текста после удаления HTML. Разрешены базовые теги: p, h2-h4, ul, ol, li, strong, em, blockquote, a, img, table. Скрипты и стили удаляются.
category_idintegerнетID категории из ответа tupik_list_article_categories.Самый надёжный способ указать категорию. Не придумывайте число вручную: сначала получите список категорий и возьмите categories[].id.
category_titlestringнетНазвание категории статьи из админки Тупика и формы добавления статьи.Например Маркетинг, Медицина, AI и автоматизация. Должно точно совпасть с существующей категорией. Если не найдено — category_not_found.
category_slugstringнетЧПУ категории статьи, если агент знает его.Альтернатива category_title. Например marketing.
cover_image_urlstringнетПубличный URL обложки, доступный серверу Тупика.Только http/https. Сервер скачает картинку до 10 МБ и сожмёт её. Лучше горизонтальная обложка 1600×500 или близко к 16:5.
cover_image_base64stringнетКартинка, переданная прямо в JSON.Можно передавать как чистый base64 или data URL. До 10 МБ до обработки. Используйте, если картинка не доступна по публичному URL.
cover_urlstringнетГотовый URL картинки, которую не нужно скачивать.Запасной вариант. Лучше использовать cover_image_url или cover_image_base64, чтобы Тупик сам сжал файл.
statusstringнетРешение агента: публиковать сразу или сохранить черновик.Допустимо publish или draft. По умолчанию publish.
slugstringнетЖелаемый адрес статьи.Латиница, цифры, дефисы. API добавит id статьи в начало и сделает slug уникальным.
seo_titlestringнетSEO-title, если внешний сервис хочет задать его вручную.До 255 символов. Если не передать, будет Название статьи | Тупик.
seo_descriptionstringнетSEO-description.До 255 символов. Если не передать, используется lead.
seo_keywordsstringнетSEO-ключи.До 255 символов. Можно не использовать.

Откуда взять категорию: категории статей управляются в админке Тупика в разделе категорий контента и видны пользователю в форме /articles/add. MCP-агент должен выбирать одну существующую категорию, а не создавать новую строку произвольно.

Tool

tupik_update_article

Редактирует уже созданную статью или черновик текущего автора. Агент должен передать идентификатор статьи и только те поля, которые реально нужно изменить.

{
  "jsonrpc": "2.0",
  "id": "article-update-1",
  "method": "tools/call",
  "params": {
    "name": "tupik_update_article",
    "arguments": {
      "user_token": "tpu_...",
      "article_id": 38,
      "title": "Новое название статьи",
      "content_html": "<p>Обновленный текст статьи</p>",
      "cover_image_url": "https://example.com/new-cover.jpg",
      "status": "publish"
    }
  }
}
ПараметрТипОбяз.Откуда взятьОграничения и смысл
user_tokenstringдаТокен автора, которому принадлежит статья.Нужен scope articles:create. Для перевода в публикацию нужен scope articles:publish. Чужую статью редактировать нельзя.
article_idintegerнетЧисло в URL статьи после /articles/. Например в /articles/38-diafragma... id равен 38. Также id возвращается в ответе tupik_publish_article.Передайте article_id или article_slug. Если не передать ни один идентификатор, будет article_id_required.
article_slugstringнетПолный slug статьи из URL без домена и без /articles/, например 38-diafragma-myshca....Альтернатива article_id. Если slug не найден, будет article_not_found.
titlestringнетНовое название статьи.Минимум 3 символа, максимум 100 в основном поле. HTML нельзя.
leadstringнетНовый лид/краткое описание.Желательно 40-300 символов. Если передать слишком короткий лид вместе с новым текстом, API соберёт лид из текста.
content_htmlstringнетНовый HTML-текст статьи.Если поле передано, после очистки HTML должно остаться минимум 40 символов текста. Скрипты, стили и опасные атрибуты удаляются.
category_idintegerнетID категории статей из CMS, если интеграция его знает.Проще и безопаснее для агента использовать category_title или category_slug.
category_titlestringнетНазвание существующей категории статей из формы добавления статьи или админки.Категория должна существовать. Новые категории через этот метод не создаются.
category_slugstringнетЧПУ существующей категории статей.Альтернатива названию категории.
cover_image_urlstringнетURL новой обложки.Сервер скачает, сохранит и сожмёт картинку. Лучше горизонтальная 1600×500 или близко к 16:5.
cover_image_base64stringнетНовая обложка прямо в JSON.Можно чистый base64 или data URL. Не отправляйте огромные оригиналы.
statusstringнетЧто сделать после редактирования.publish — опубликовано, draft — черновик. Если не передать, текущий статус обычно сохраняется.
slugstringнетНовый желаемый адрес статьи.Латиница, цифры, дефисы. API сохранит формат с id в начале и сделает slug уникальным.
seo_title / seo_description / seo_keywordsstringнетSEO-поля, если внешний сервис управляет мета-тегами.Каждое поле до 255 символов.

Tool

tupik_delete_article

Снимает свою статью с публикации. Это мягкое удаление: материал скрывается, но запись остаётся в базе для истории, редиректов и возможного восстановления администратором.

{
  "jsonrpc": "2.0",
  "id": "article-delete-1",
  "method": "tools/call",
  "params": {
    "name": "tupik_delete_article",
    "arguments": {
      "user_token": "tpu_...",
      "article_slug": "38-diafragma-myshca-o-kotoroi-vspominayut-togda-kogda-nikogda"
    }
  }
}
ПараметрТипОбяз.Откуда взятьОграничения и смысл
user_tokenstringдаТокен автора статьи.Чужую статью удалить нельзя.
article_idintegerнетID статьи из URL или из ответа API.Передайте article_id или article_slug.
article_slugstringнетSlug статьи из URL.Передайте, если id неизвестен.

Tool

tupik_upsert_speaker

Создаёт или обновляет карточку спикера. У одного пользователя может быть только одна карточка: повторный вызов обновит существующую.

{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "tupik_upsert_speaker",
    "arguments": {
      "user_token": "tpu_...",
      "name": "Иван Петров",
      "short_position": "SEO и GEO-специалист",
      "city": "Москва",
      "can_travel": true,
      "topics": ["SEO", "GEO / продвижение в нейросетях"],
      "formats": ["Конференция", "Вебинар", "Подкаст-запись"],
      "about": "<p>Помогаю компаниям получать видимость в поиске и нейросетях.</p>",
      "conditions": "<p>Выступаю с докладами и мастер-классами.</p>",
      "website": "https://example.com",
      "video_url": "https://example.com/video",
      "request_email": "speaker@example.com",
      "photo_url": "https://example.com/photo.jpg"
    }
  }
}
ПараметрТипОбяз.Откуда взятьОграничения и смысл
user_tokenstringдаТокен пользователя, которому принадлежит карточка.Нужен scope speakers:write.
name / titlestringдаИмя спикера из профиля или анкеты.Минимум 2 символа. В MCP schema поле называется name, REST также принимает title.
short_positionstringнетКороткое позиционирование: кто человек и про что выступает.Лучше 1-2 строки. Показывается в карточке и списке спикеров.
citystringнетГород спикера.Свободная строка: Москва, Санкт-Петербург, Онлайн.
can_travelbooleanнетОтвет из анкеты: может ли приехать в другой город.true или false.
topicsarray<string>даТемы выступлений из справочника тем спикеров/конференций.Нужна хотя бы одна тема, иначе speaker_topics_required. Используйте существующие темы из формы спикера. Если старой темы нет в новом дереве, её нужно сначала добавить в справочник.
topic_idsarray<int>нетID тем из таблицы тем, если интеграция умеет получать id.Более надёжно, чем title, но публичного метода получения id пока нет. До появления справочника используйте topics.
formatsarray<string>нетФорматы выступлений из формы спикера.Например Конференция, Вебинар, Подкаст-запись, Клубная встреча.
about / about_html / content_htmlstringнетОписание спикера.Можно HTML с базовыми тегами. Скрипты и стили удаляются.
conditions / conditions_htmlstringнетУсловия участия.Можно HTML с базовым форматированием.
website / contacts_publicstringнетПубличный сайт или контакт.URL или email. Если это URL без протокола, API добавит https://.
video_urlstringнетСсылка на видео выступления.Публичный URL. Пока хранится ссылкой.
request_email / emailstringдаEmail для заявок организаторов.Должен быть валидным email. Если не передать, используется email пользователя.
photo_url / photo_image_urlstringнетПубличный URL фото спикера.Лучше квадратное фото: лицо и плечи по центру. Сервер скачает и сожмёт изображение.
photo_base64 / photo_image_base64stringнетФото в base64.До 10 МБ. Используйте, если фото недоступно по URL.
slugstringнетЖелаемый URL карточки спикера.Если карточка уже есть, старый slug сохраняется. Если новая — API сделает уникальный slug.

Tool

tupik_create_event

Добавляет конференцию/мероприятие на модерацию. После сохранения администраторы получают уведомление.

{
  "jsonrpc": "2.0",
  "id": 6,
  "method": "tools/call",
  "params": {
    "name": "tupik_create_event",
    "arguments": {
      "user_token": "tpu_...",
      "title": "Digital-конференция 2026",
      "event_type": "Конференция",
      "event_date": "2026-08-01",
      "event_date_end": "2026-08-02",
      "city": "Москва",
      "format": "Офлайн",
      "topics": ["SEO", "GEO / продвижение в нейросетях"],
      "lead": "Конференция о поиске, нейросетях и продвижении брендов в AI-ответах.",
      "description": "<p>В программе доклады, панели и разборы кейсов.</p>",
      "source_url": "https://example.com/event",
      "needs_speakers": "yes",
      "speaker_terms": "free",
      "deadline": "2026-07-20",
      "cover_image_url": "https://example.com/event-cover.jpg"
    }
  }
}
ПараметрТипОбяз.Откуда взятьОграничения и смысл
user_tokenstringдаТокен пользователя, который добавляет мероприятие.Нужен scope events:create.
titlestringдаНазвание конференции/мероприятия.Минимум 3 символа. Не вставляйте HTML.
event_type / typestringдаТип из справочника форматов/типов конференций.Например Конференция, Вебинар, Форум, Митап, Подкаст-запись.
event_date / date_start / datestringдаДата начала мероприятия.Формат лучше YYYY-MM-DD. Любая распознаваемая дата будет приведена к этому формату.
event_date_end / date_endstringнетДата окончания, если мероприятие идёт несколько дней.Не может быть раньше даты начала, иначе event_date_end_before_start.
citystringдаГород мероприятия или Онлайн.Свободная строка. Для онлайн-мероприятий можно ставить Онлайн.
formatstringдаФормат проведения.Например Онлайн, Офлайн, Гибрид.
topics / topicarray<string>даТемы из дерева тем конференций/спикеров.Максимум 8 тем сохраняется. Нужна хотя бы одна, иначе event_topics_required.
topic_idsarray<int>нетID тем, если известны интеграции.Пока публичного справочника id нет, поэтому безопаснее передавать названия в topics.
lead / summarystringдаКраткое описание мероприятия.Минимум 30 символов текста. API сохранит до 400 символов.
description / description_html / content_htmlstringнетПолное описание.Можно HTML с базовыми тегами. Скрипты и стили удаляются.
source_url / url / websitestringдаОфициальная страница мероприятия или источник.Должен быть валидным URL, иначе event_source_url_required.
needs_speakersstringнетНужны ли спикеры.Допустимо yes, no, unknown. Также принимаются да, нет, true, false.
speaker_termsstringнетУсловия для спикеров.Используется только если needs_speakers = yes. Допустимо free — бесплатно спикерам, speaker_pays — спикеры платят, paid — спикерам платят.
deadlinestringнетДедлайн подачи заявки спикера.Учитывается только если нужны спикеры. Формат лучше YYYY-MM-DD.
cover_image_urlstringнетURL превью мероприятия.Публичная картинка до 10 МБ. Лучше горизонтальная.
cover_image_base64 / preview_image_base64stringнетПревью в base64.До 10 МБ до обработки.
organizerstringнетОрганизатор мероприятия.Короткая строка.
organizer_contact / contactstringнетКонтакт организатора.Email, Telegram, сайт или иной контакт.
conditions / conditions_htmlstringнетУсловия участия.Можно HTML с базовым форматированием.
audiencestringнетОжидаемая аудитория.Свободный текст.
slugstringнетЖелаемый URL мероприятия.Если не передать, API создаст по названию.

Tool

tupik_update_event

Редактирует мероприятие текущего пользователя. После изменения карточка снова уходит на модерацию, чтобы в каталог не попадал мусор и подменённые рекламные события.

{
  "jsonrpc": "2.0",
  "id": "event-update-1",
  "method": "tools/call",
  "params": {
    "name": "tupik_update_event",
    "arguments": {
      "user_token": "tpu_...",
      "event_id": 12,
      "title": "Обновлённая конференция",
      "event_date": "2026-08-10",
      "event_date_end": "2026-08-11",
      "needs_speakers": "yes",
      "speaker_terms": "paid",
      "deadline": "2026-07-25"
    }
  }
}
ПараметрТипОбяз.Откуда взятьОграничения и смысл
user_tokenstringдаТокен пользователя, который создал мероприятие.Нужен scope events:create. Чужие мероприятия редактировать нельзя.
event_idintegerнетID мероприятия из ответа tupik_create_event или из внутренней карточки.Передайте event_id или event_slug. Если не передать ни один идентификатор, будет event_id_required.
event_slugstringнетSlug мероприятия из URL без домена и без /events/.Альтернатива id. Если не найдено, будет event_not_found.
titlestringнетНовое название мероприятия.Минимум 3 символа.
event_type / typestringнетТип мероприятия.Например Конференция, Вебинар, Форум, Митап.
event_date / date_start / datestringнетДата начала.Формат лучше YYYY-MM-DD.
event_date_end / date_endstringнетДата окончания для многодневных событий.Не может быть раньше даты начала.
citystringнетГород или Онлайн.Свободная строка.
formatstringнетФормат проведения.Онлайн, Офлайн, Гибрид.
topicsarray<string>нетТемы из дерева тем конференций.Максимум 8. Если передали массив, хотя бы одна тема должна существовать.
lead / summarystringнетКраткое описание.Минимум 30 символов, до 400 сохраняется в карточке.
description / description_html / content_htmlstringнетПолное описание.Можно HTML с базовым форматированием.
conditions / conditions_htmlstringнетУсловия участия.Можно HTML с базовым форматированием.
source_url / url / websitestringнетСайт мероприятия.Должен быть валидным URL.
needs_speakersstringнетНужны ли спикеры.yes, no, unknown. Если не yes, дедлайн и условия спикеров очищаются.
speaker_termsstringнетУсловия для спикеров.Только если needs_speakers = yes. Значения: free, speaker_pays, paid.
deadlinestringнетДедлайн заявки спикера.Только если нужны спикеры. Формат лучше YYYY-MM-DD.
cover_image_url / cover_image_base64stringнетНовая картинка-превью мероприятия.Сервер сохраняет и сжимает файл. Лучше горизонтальная обложка.
slugstringнетНовый желаемый URL мероприятия.Латиница, цифры, дефисы; API сделает уникальным.

Tool

tupik_delete_event

Скрывает своё мероприятие из каталога. Используйте, если событие отменили, добавили по ошибке или нужно убрать карточку.

{
  "jsonrpc": "2.0",
  "id": "event-delete-1",
  "method": "tools/call",
  "params": {
    "name": "tupik_delete_event",
    "arguments": {
      "user_token": "tpu_...",
      "event_slug": "digital-konferencija-2026"
    }
  }
}
ПараметрТипОбяз.Откуда взятьОграничения и смысл
user_tokenstringдаТокен владельца мероприятия.Чужое мероприятие удалить нельзя.
event_idintegerнетID мероприятия из ответа API.Передайте event_id или event_slug.
event_slugstringнетSlug из URL мероприятия.Передайте, если id неизвестен.

Tool

tupik_subscribe_events

Создаёт подписку на новые конференции по фильтрам. После сохранения пользователь получает уведомления на сайте, а API сразу возвращает текущие подходящие мероприятия.

{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "tools/call",
  "params": {
    "name": "tupik_subscribe_events",
    "arguments": {
      "user_token": "tpu_...",
      "title": "SEO и GEO онлайн",
      "topics": ["SEO", "GEO / продвижение в нейросетях"],
      "cities": ["Онлайн", "Москва"],
      "formats": ["Онлайн", "Гибрид"],
      "event_types": ["Конференция", "Вебинар"],
      "needs_speakers": "yes",
      "date_from": "2026-06-01",
      "date_to": "2026-12-31"
    }
  }
}
ПараметрТипОбяз.Откуда взятьОграничения и смысл
user_tokenstringдаТокен пользователя, которому создаётся подписка.Нужен scope events:subscribe.
titlestringнетНазвание фильтра для пользователя.Если не передать, будет стандартное название.
topics / topicarray<string>нетТемы конференций из дерева тем.Можно несколько. Если все фильтры пустые, будет subscription_filter_required.
cities / cityarray<string>нетГорода, которые интересны пользователю.Например Москва, Санкт-Петербург, Онлайн.
formats / formatarray<string>нетФорматы проведения.Например Онлайн, Офлайн, Гибрид.
event_types / event_typearray<string>нетТипы мероприятий.Например Конференция, Вебинар, Подкаст-запись.
needs_speakersstringнетФильтр по поиску спикеров.Обычно yes, если пользователь хочет выступать. Можно оставить пустым.
date_fromstringнетНачало периода поиска.Формат лучше YYYY-MM-DD.
date_tostringнетКонец периода поиска.Формат лучше YYYY-MM-DD.

Важно: в подписке должен быть хотя бы один фильтр: тема, город, формат, тип или статус “нужны спикеры”.

Справочники

Откуда брать категории, темы, форматы и id

Категории статей

category_id, category_title и category_slug относятся только к статьям. Их нужно брать из метода tupik_list_article_categories или REST-адреса /api/v1/articles/categories.

Если агент не уверен в категории, он должен сначала запросить справочник. Если передать неверную строку или id, будет category_not_found.

Темы спикеров и конференций

topics — это названия тем из дерева тем спикеров/конференций. Сейчас они выбираются в формах спикера и конференции.

Пока нет публичного метода “получить список тем”. Поэтому агент должен использовать заранее известный справочник или значения, которые пользователь выбрал в интерфейсе.

ID в ответах

user.id, article.id, speaker.id, event.id — это внутренние id записей в Тупике. Они возвращаются API после создания или проверки.

Не путать с JSON-RPC id. JSON-RPC id нужен только для связи запроса и ответа.

Что ещё нужно добавить

Категории статей уже доступны через tupik_list_article_categories. Для полной интеграции дальше стоит добавить отдельные справочные методы: список тем, список форматов, список типов мероприятий и проверку доступности slug.

Ошибки

Типовые ответы с ошибками

ОшибкаЧто значитЧто делать агенту
invalid_jsonТело запроса не является валидным JSON.Пересобрать JSON, проверить кавычки, экранирование HTML и base64.
api_key_required / invalid_api_keyНет сервисного ключа или он неверный.Не просить пользователя вводить его публично. Проверить backend-настройки интеграции.
user_token_requiredДействию нужен токен автора.Сначала вызвать tupik_create_user или tupik_issue_user_token.
scope_deniedУ токена нет нужного права.Запросить новый токен с нужными scopes или показать ошибку владельцу интеграции.
legal_consent_requiredПри создании пользователя не переданы согласия.Получить согласия пользователя с соглашением и политикой персональных данных.
category_not_foundКатегория статьи не найдена.Использовать существующую категорию из админки или не передавать категорию.
content_too_shortТекст статьи короче 40 символов.Передать полноценный HTML-текст.
negative_reputation_cannot_publishАвтор с отрицательной репутацией не может публиковать.Сохранить черновик невозможно как публикацию; показать человеку причину.
daily_article_publish_limitАвтор уже опубликовал 3 статьи за текущие сутки по Москве.Не повторять публикацию автоматически. Показать сообщение: больше 3 публикаций в сутки доступно только для платных аккаунтов, почта ne@to-pick.ru.
speaker_topics_requiredВ карточке спикера нет тем.Передать минимум одну тему из справочника.
event_lead_too_shortКраткое описание мероприятия короче 30 символов.Сформировать нормальный лид.
event_source_url_requiredНет валидной ссылки на источник мероприятия.Передать официальный URL события или страницу-источник.
event_topics_requiredУ мероприятия нет тем.Передать минимум одну тему.
invalid_speaker_termsНеверное значение условий для спикеров.Использовать только free, speaker_pays, paid.
subscription_filter_requiredПодписка создана без фильтров.Передать хотя бы тему, город, формат, тип или needs_speakers.

План улучшений

Что ещё нужно расписать и добавить

  1. Публичные справочники: категории статей уже доступны через tupik_list_article_categories. Следом стоит добавить tupik_list_topics, tupik_list_event_types, tupik_list_formats, чтобы агент не угадывал названия.
  2. Проверка slug: добавить метод, который заранее проверяет доступность ЧПУ для пользователя, статьи, спикера или конференции.
  3. Редактирование созданных сущностей: сейчас API создаёт статьи и конференции, а для спикера делает upsert. Нужны отдельные методы обновления статей и конференций.
  4. Статистика: добавить tools для показов, просмотров, дочитываний, лайков, комментариев и избранного по статьям автора.
  5. Файлы: добавить отдельный метод загрузки изображения, который вернёт готовый URL, чтобы агент мог сначала загрузить картинку, а потом использовать её в статье, спикере или мероприятии.
  6. OpenAPI: подготовить /api/openapi.json, чтобы программисты могли подключать REST API автоматически.
  7. WebMCP widget: при необходимости добавить клиентский слой WebMCP для браузерных агентов. Текущая страница уже раскрывает инструменты и MCP endpoint, но не заменяет локальный WebSocket-мост.

Manifest

Живой список tools

Ниже находится JSON, который отдаёт текущий MCP Server. Его можно использовать для автоматической проверки схем.

{
    "name": "Tupik MCP Server",
    "version": "0.1.0",
    "protocol": "jsonrpc",
    "endpoint": "https:\/\/to-pick.ru\/mcp\/server",
    "tools": [
        {
            "name": "tupik_get_me",
            "description": "Проверить личный API-токен Тупика и получить данные текущего пользователя.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "user_token": {
                        "type": "string",
                        "description": "Личный токен пользователя tpu_... Можно передать вместо Authorization: Bearer."
                    }
                }
            }
        },
        {
            "name": "tupik_create_user",
            "description": "Создать пользователя Тупика для внешнего сервиса. Требует сервисный X-Tupik-Api-Key.",
            "inputSchema": {
                "type": "object",
                "required": [
                    "email",
                    "name"
                ],
                "properties": {
                    "api_key": {
                        "type": "string",
                        "description": "Сервисный API-ключ интеграции."
                    },
                    "email": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "password": {
                        "type": "string"
                    },
                    "slug": {
                        "type": "string"
                    }
                }
            }
        },
        {
            "name": "tupik_issue_user_token",
            "description": "Получить пользовательский токен для существующего пользователя. Требует сервисный X-Tupik-Api-Key.",
            "inputSchema": {
                "type": "object",
                "required": [
                    "email"
                ],
                "properties": {
                    "api_key": {
                        "type": "string"
                    },
                    "email": {
                        "type": "string"
                    },
                    "ttl_days": {
                        "type": "integer"
                    }
                }
            }
        },
        {
            "name": "tupik_update_profile",
            "description": "Обновить профиль пользователя Тупика: имя, описание, роль, компанию, сайт, ЧПУ.",
            "inputSchema": {
                "type": "object",
                "required": [
                    "user_token"
                ],
                "properties": {
                    "user_token": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "about": {
                        "type": "string"
                    },
                    "role": {
                        "type": "string"
                    },
                    "company": {
                        "type": "string"
                    },
                    "website": {
                        "type": "string"
                    },
                    "slug": {
                        "type": "string"
                    },
                    "avatar_image_url": {
                        "type": "string"
                    },
                    "avatar_image_base64": {
                        "type": "string"
                    },
                    "avatar_url": {
                        "type": "string"
                    },
                    "avatar_base64": {
                        "type": "string"
                    }
                }
            }
        },
        {
            "name": "tupik_list_article_categories",
            "description": "Получить список категорий статей Тупика для публикации: category_id, category_title, category_slug и публичный URL категории.",
            "inputSchema": {
                "type": "object",
                "properties": []
            }
        },
        {
            "name": "tupik_publish_article",
            "description": "Создать статью или черновик в Тупике с HTML-текстом, лидом, категорией и обложкой.",
            "inputSchema": {
                "type": "object",
                "required": [
                    "user_token",
                    "title",
                    "content_html"
                ],
                "properties": {
                    "user_token": {
                        "type": "string"
                    },
                    "title": {
                        "type": "string"
                    },
                    "lead": {
                        "type": "string"
                    },
                    "content_html": {
                        "type": "string"
                    },
                    "category_id": {
                        "type": "integer"
                    },
                    "category_title": {
                        "type": "string"
                    },
                    "category_slug": {
                        "type": "string"
                    },
                    "cover_image_url": {
                        "type": "string"
                    },
                    "cover_image_base64": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "publish",
                            "draft"
                        ]
                    },
                    "slug": {
                        "type": "string"
                    }
                }
            }
        },
        {
            "name": "tupik_update_article",
            "description": "Отредактировать свою статью или черновик в Тупике. Передайте article_id или article_slug и только те поля, которые нужно изменить.",
            "inputSchema": {
                "type": "object",
                "required": [
                    "user_token"
                ],
                "properties": {
                    "user_token": {
                        "type": "string"
                    },
                    "article_id": {
                        "type": "integer"
                    },
                    "article_slug": {
                        "type": "string"
                    },
                    "title": {
                        "type": "string"
                    },
                    "lead": {
                        "type": "string"
                    },
                    "content_html": {
                        "type": "string"
                    },
                    "category_title": {
                        "type": "string"
                    },
                    "category_slug": {
                        "type": "string"
                    },
                    "category_id": {
                        "type": "integer"
                    },
                    "cover_image_url": {
                        "type": "string"
                    },
                    "cover_image_base64": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "publish",
                            "draft"
                        ]
                    },
                    "slug": {
                        "type": "string"
                    },
                    "seo_title": {
                        "type": "string"
                    },
                    "seo_description": {
                        "type": "string"
                    },
                    "seo_keywords": {
                        "type": "string"
                    }
                }
            }
        },
        {
            "name": "tupik_delete_article",
            "description": "Удалить свою статью или черновик из публикации. Передайте article_id или article_slug.",
            "inputSchema": {
                "type": "object",
                "required": [
                    "user_token"
                ],
                "properties": {
                    "user_token": {
                        "type": "string"
                    },
                    "article_id": {
                        "type": "integer"
                    },
                    "article_slug": {
                        "type": "string"
                    }
                }
            }
        },
        {
            "name": "tupik_upsert_speaker",
            "description": "Создать или обновить карточку спикера пользователя.",
            "inputSchema": {
                "type": "object",
                "required": [
                    "user_token",
                    "name"
                ],
                "properties": {
                    "user_token": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "short_position": {
                        "type": "string"
                    },
                    "city": {
                        "type": "string"
                    },
                    "can_travel": {
                        "type": "boolean"
                    },
                    "topics": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "formats": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "about": {
                        "type": "string"
                    },
                    "conditions": {
                        "type": "string"
                    },
                    "website": {
                        "type": "string"
                    },
                    "video_url": {
                        "type": "string"
                    },
                    "photo_url": {
                        "type": "string"
                    },
                    "photo_base64": {
                        "type": "string"
                    }
                }
            }
        },
        {
            "name": "tupik_create_event",
            "description": "Добавить конференцию или мероприятие в Тупик. Мероприятие уходит на модерацию.",
            "inputSchema": {
                "type": "object",
                "required": [
                    "user_token",
                    "title",
                    "event_date",
                    "format",
                    "event_type",
                    "city",
                    "lead",
                    "source_url"
                ],
                "properties": {
                    "user_token": {
                        "type": "string"
                    },
                    "title": {
                        "type": "string"
                    },
                    "event_type": {
                        "type": "string"
                    },
                    "event_date": {
                        "type": "string"
                    },
                    "event_date_end": {
                        "type": "string"
                    },
                    "city": {
                        "type": "string"
                    },
                    "format": {
                        "type": "string"
                    },
                    "topics": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "lead": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    },
                    "source_url": {
                        "type": "string"
                    },
                    "needs_speakers": {
                        "type": "string"
                    },
                    "speaker_terms": {
                        "type": "string"
                    },
                    "deadline": {
                        "type": "string"
                    },
                    "cover_image_url": {
                        "type": "string"
                    },
                    "cover_image_base64": {
                        "type": "string"
                    }
                }
            }
        },
        {
            "name": "tupik_update_event",
            "description": "Отредактировать своё мероприятие или конференцию. Передайте event_id или event_slug и только те поля, которые нужно изменить.",
            "inputSchema": {
                "type": "object",
                "required": [
                    "user_token"
                ],
                "properties": {
                    "user_token": {
                        "type": "string"
                    },
                    "event_id": {
                        "type": "integer"
                    },
                    "event_slug": {
                        "type": "string"
                    },
                    "title": {
                        "type": "string"
                    },
                    "event_type": {
                        "type": "string"
                    },
                    "event_date": {
                        "type": "string"
                    },
                    "event_date_end": {
                        "type": "string"
                    },
                    "city": {
                        "type": "string"
                    },
                    "format": {
                        "type": "string"
                    },
                    "topics": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "lead": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    },
                    "conditions": {
                        "type": "string"
                    },
                    "source_url": {
                        "type": "string"
                    },
                    "needs_speakers": {
                        "type": "string"
                    },
                    "speaker_terms": {
                        "type": "string"
                    },
                    "deadline": {
                        "type": "string"
                    },
                    "cover_image_url": {
                        "type": "string"
                    },
                    "cover_image_base64": {
                        "type": "string"
                    },
                    "slug": {
                        "type": "string"
                    }
                }
            }
        },
        {
            "name": "tupik_delete_event",
            "description": "Удалить своё мероприятие или конференцию. Передайте event_id или event_slug.",
            "inputSchema": {
                "type": "object",
                "required": [
                    "user_token"
                ],
                "properties": {
                    "user_token": {
                        "type": "string"
                    },
                    "event_id": {
                        "type": "integer"
                    },
                    "event_slug": {
                        "type": "string"
                    }
                }
            }
        },
        {
            "name": "tupik_subscribe_events",
            "description": "Создать подписку на новые конференции по темам, городам, форматам и типам.",
            "inputSchema": {
                "type": "object",
                "required": [
                    "user_token"
                ],
                "properties": {
                    "user_token": {
                        "type": "string"
                    },
                    "title": {
                        "type": "string"
                    },
                    "topics": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "cities": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "formats": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "event_types": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "needs_speakers": {
                        "type": "string"
                    },
                    "date_from": {
                        "type": "string"
                    },
                    "date_to": {
                        "type": "string"
                    }
                }
            }
        }
    ]
}