Skip to main content
Glama
conarti

yandex-messenger-mcp

by conarti

yandex-messenger-mcp

MCP-сервер для Яндекс Мессенджера. Даёт агенту читать переписку, искать по ней, скачивать вложения и отправлять текст от вашего имени.

Работает на той же сессии, что и веб-клиент: Playwright один раз логинится в Яндекс и держит persist-профиль, дальше протокол (WebSocket + HTTP) гоняется в Node на извлечённых cookie. Публичного API у Мессенджера нет, поэтому протокол снят реверсом веб-клиента chats-web - отсюда честный раздел Ограничения внизу, его стоит прочитать до того, как полагаться на инструмент.

Инструменты

Инструмент

Что делает

list_chats

Список чатов: последнее сообщение, счётчик непрочитанных, свежие первыми

get_history

Страница сообщений чата с пагинацией по курсору

get_message

Одно сообщение по chat+message_id либо по join-ссылке, без загрузки истории

get_message_context

Окно сообщений вокруг метки: N сообщений до и N после

search

Поиск по сообщениям, людям и чатам

send_message

Отправка текста, с упоминаниями/ответом/пересылкой. Двухшаговая: draft, затем confirm

send_file

Отправка картинки или файла. Двухшаговая: draft (байты не льются), затем confirm (необратимо)

set_reaction

Поставить/снять реакцию. Одним вызовом, без confirm (реверсибельно)

list_reactions

Полный список поставивших реакцию и прочитавших (кто и когда), без обрезки

mark_read

Отметить чат прочитанным. Одним вызовом, без confirm

pin_message

Закрепить/открепить сообщение. Одним вызовом, без confirm

delete_message

Удаление своего сообщения. Двухшаговая: draft, затем confirm (необратимо)

edit_message

Правка своего сообщения. Двухшаговая: draft, затем confirm (необратимо)

get_poll

Чтение опроса: варианты, мой выбор, результаты. Одним вызовом, без confirm

vote_in_poll

Голос в опросе. Двухшаговая: draft, затем confirm. Форма подтверждена живьём

get_thread

Сообщения треда как микро-чата (по thread_id либо родительскому сообщению)

join_to_thread / leave_thread

Подписка на тред и выход. Одним вызовом, без confirm

download_attachment

Скачивает вложение по рефу в папку загрузок

list_chats

Параметр

Тип

По умолчанию

limit

1-500

50

unread_only

bool

false

include_last_message_text

bool

false

Отдаёт {chats, total_chats, unread_chats}. У чата: chat_id, name, kind (private/group), last_activity, unread_count, unread, muted, last_message.

include_last_message_text:true возвращает полный текст последнего сообщения каждого чата. По умолчанию отдаются только метаданные последнего сообщения (без текста, цитат и имён файлов) - чтобы содержимое чужих переписок не попадало в контекст модели без явного запроса.

get_history

Параметр

Тип

По умолчанию

chat

ChatId либо поисковый запрос

обязателен

limit

1-200

40

before

курсор: мкс строкой

нет

from_date

ISO-дата/время, нижняя граница включающая

нет

to_date

ISO-дата/время, верхняя граница исключающая

нет

after

ISO-дата/время, строго после метки (альтернатива from_date)

нет

Если chat задан запросом и совпадений несколько, инструмент возвращает status:"ambiguous_chat" со списком кандидатов и не гадает. Пагинация: взять next_before из выдачи и передать его в before следующего вызова.

Фильтр по времени - альтернатива курсору. from_date включает сообщения от этой даты и позже, to_date исключает сообщение ровно на границе (верхняя граница исключающая), поэтому «сообщения за сегодня» берутся одним вызовом: from_date = начало дня, to_date = начало следующего. after - то же, что from_date, но строго после метки. При совпадении обеих форм одной границы курсор before приоритетнее to_date, а after приоритетнее from_date.

Self-чат «Избранное» резолвится по имени, а не только литеральным ChatId: резолвер узнаёт его по гейту <myGuid>_<myGuid> (пара одинаковых guid, PrivateChatInfo + PartnerInfo.Guid == myGuid) и больше не выбрасывает вас самих как собеседника. Резолв не-self чатов при этом не меняется.

Вложения приходят только рефами (file_id, name, size, kind). Ничего не качается - это отдельное явное действие через download_attachment.

Каждое сообщение помимо v1-полей несёт обогащение (аддитивно, старые ключи не меняются):

Ключ

Что несёт

from_me

автор == я; null, если From срезан фильтром (автор неопределим, это не «не моё»)

reads

прочтения: {tracked, count?, recent?, seen_by_partner_mcs?}. Отсутствие read-state = {tracked:false}, не ноль

mentions

упоминания в имена; нет имени для guid - явный {guid, unresolved:true}, а не guid вместо имени

reactions

реакции сгруппированы по типу: Reaction {type, name, emoji, count?, actors[], actors_complete}; неизвестный тип - {type, name:null, emoji:null, unknown:true}. actors[] - кто поставил ({guid?, name?, timestamp?, timestamp_mcs?}), здесь усечённый сиблинг history; actors_complete - сравнение count с длиной actors[], false значит обрезку. Полный список без обрезки - инструмент list_reactions

thread

признак has_thread + корень треда root

forwarded

оригиналы пересылки: {source_author, source_chat, source_date, source_date_mcs, source_text, attachments} - отдельным ключом, не внутри context. Блок из нескольких пересылок приходит несколькими элементами

Реакции: type - id артворка, emoji - аппроксимация. Яндекс рендерит реакции PNG-артворком по id (/reactions/{type}/{size}), а не Unicode-эмодзи. Карта type -> {name, emoji} лежит данными в src/config/reaction-map.json (52 записи, перегенерируется свипом по /reactions/{type}/small). Авторитетны type (пришёл с провода) и name (имя ассета с сервера); колонка emoji - наша аппроксимация артворка, её нельзя выдавать за «эмодзи от Яндекса». Пространство типов открыто (сервер принимает любой int), поэтому карта - lookup-с-фолбэком, а не полный справочник: неизвестный тип отдаётся как unknown, chr(type) в emoji не подставляется. Акторы и actors_complete в этом обогащении - усечённый сиблинг history; полный список поставивших/прочитавших (кто и когда), без обрезки, - инструмент list_reactions (двумя WS-вызовами: Mode - дискриминатор, дефолт -> UserReactions, Mode:1 -> UserReads+ReadsCount).

Форматирование - сырая строка. Протокол не даёт структурированных entities (ranges/spans): Text несёт ровно MessageText, markdown-символы едут как есть, разметку рисует клиент (проверено живьём, §17.14). text отдаётся без разбора; структуру форматирования тут не выдумываем.

Удалённое сообщение: kind:'deleted' (изменение формы выдачи). Раньше удалённое приходило с kind:'unknown' - тем же значением, что и сообщение с нераспознанным телом, и различить их было нечем. Теперь у удалённого собственное значение, а 'unknown' означает строго «тела нет либо content-поля нет». Путь миграции: если ваш код искал удалённые по kind === 'unknown', переходите на поле deleted - оно было и есть, ничего не меняло и остаётся надёжнее любого kind.

Пересылка распознаётся не по kind, а по данным. kind пересланного сообщения - это вид его СОДЕРЖИМОГО: пересланная картинка остаётся 'image', а чистая пересылка без своего комментария приходит как 'unknown' (её тело действительно пустое, содержимое лежит в оригиналах). Признак пересылки - непустой forwarded[]; там же текст и вложения оригиналов. Канал полный: forwarded[] даётся всеми инструментами, которые отдают сообщения, включая search - он обогащается тем же слоем. mark_read сообщений не отдаёт вовсе, обогащение внутри него нужно лишь чтобы взять метку самого свежего. Дочитывать оригиналы инструмент сам не ходит: адрес каждого оригинала (source_chat + source_date_mcs) отдаётся в forwarded[], дальше по нему при желании вызывается get_message.

get_message

Параметр

Тип

По умолчанию

chat

ChatId либо поисковый запрос; нужен вместе с message_id

-

message_id

timestamp сообщения в микросекундах (строка); нужен вместе с chat

-

url

join-ссылка Мессенджера (альтернатива паре chat+message_id)

-

with_reactions

bool: тянуть детальные реакции/прочтения (2 доп. WS-вызова)

true

Одно сообщение без загрузки истории (message_info, один WS-вызов). Адресация - либо парой chat+message_id (то же резолвение чата, что у get_history), либо готовой join-ссылкой (url): из неё резолвится и чат, и метка сообщения. Трёхсегментная ссылка (сообщение внутри треда) адресуется той же деривацией thread_id, что и get_thread; для бизнес-чата (2/...), где деривация недоступна, возвращается status:"thread_unsupported" с причиной, а не тихий отказ.

with_reactions по умолчанию true: для ОДНОГО сообщения два дополнительных вызова list_reactions дёшевы, поэтому reactions_detail (полные реакции и прочтения, без обрезки) приезжает вместе с сообщением. with_reactions:false возвращает только само сообщение с обычным обогащением (усечённые сиблинги reactions/reads, как в get_history).

Ответ также несёт my_reactions (мои реакции на сообщение; ключ пропадает, если своих реакций нет) и сырой chat_info (метаданные чата с провода, отдаются как есть).

get_message_context

Параметр

Тип

По умолчанию

chat

ChatId либо поисковый запрос

обязателен

message_id

timestamp целевого сообщения в микросекундах (строка)

обязателен

before

сколько сообщений ДО метки, 0-200

10

after

сколько сообщений ПОСЛЕ метки, 0-200

10

Окно вокруг конкретного сообщения - когда важен не курсор, а то, что было сказано непосредственно до и после метки. Отдельного «context»-метода на проводе нет: окно строится теми же границами history, что и get_history. Выдача несёт три ключа: before (от старых к новым), message (само сообщение по метке, если оно ещё живо - не удалено и не отфильтровано), after (от старых к новым).

Параметр

Тип

По умолчанию

query

строка

обязателен

entities

messages, users, chats

все три

limit

стартовый limit

50

Серверной пагинации у поиска нет (см. Ограничения), поэтому полнота достигается эскалацией limit: пока выдача насыщена, limit поднимается и запрос повторяется. Как это отработало, видно в ответе: escalation: {start_limit, final_limit, requests}. Если упёрлись в клиентский потолок, придёт truncated:true с причиной, а не молча обрезанный список.

Entity contacts невалиден и отвергается на входе.

send_message

Параметр

Тип

chat

ChatId либо поисковый запрос

text

текст сообщения

mentions

упоминания участников (опционально)

reply_to_message_id

timestamp сообщения-цели ответа, мкс строкой (опционально)

forward_from

timestamp пересылаемого сообщения, мкс строкой (опционально)

confirm

true - отправить; иначе draft

confirm_token

токен из draft, обязателен при confirm:true

Подробности двухшаговой отправки ниже: Двухшаговая отправка.

Упоминания (mentions). Двухшаговый контракт: на draft элементы mentions - это запросы (@Имя, @<guid> либо голый guid), каждый резолвится в guid участника; неоднозначность (несколько кандидатов) или отсутствие результата отклоняет весь вызов целиком, не только спорное упоминание. Ответ несёт mentions: [{guid, name?}] - уже резолвнутые. На confirm нужно предъявить РОВНО те же guid, в том же порядке, что вернул draft: изменение состава или порядка отклоняет отправку (порядок значим - он часть отпечатка нагрузки). Резолв идёт по каталогу организации (глобальный поиск людей), а НЕ по участникам конкретного чата: @Имя может найти не того тёзку. Для приватного чата есть бесплатная проверка принадлежности - оба guid собеседников лежат в самом chat_id (<guidA>_<guidB>), резолвнутый guid вне этой пары отклоняется (mention_not_in_chat). Для группового чата такой проверки нет (эндпоинта участников группы в протоколе не нашлось) - точный адрес гарантирует только явный @<guid>, а не поиск по имени.

Подстановка токена и поле text_preview. Упоминание рендерится клиентом только тогда, когда в самом MessageText стоит токен @<guid>; одного MentionedUserIds недостаточно (#15). Поэтому на draft каждая названная в mentions строка заменяется в тексте на канонический токен, и draft.text возвращается уже подставленным - именно он предмет отпечатка и именно его надо вернуть эхом на confirm. Подстановка идёт по строкам, которые назвал вызывающий, а не по позиции: порядок массива mentions с порядком вхождений в тексте не связан, и позиционное сопоставление подставило бы guid не того человека. Плейсхолдер, присутствующий в тексте, но не названный в mentions, не трогается; petr@Имя тоже не трогается (левая граница). Рядом отдаётся text_preview - читаемая проекция того же текста, где guid развёрнуты обратно в имена: только для чтения, в отпечаток не входит, эхо превью вместо text отправку отклонит. Оно существует потому, что по строке с 37-символьными guid человек не видит, кто упомянут в каком месте. Форма токена на исходящем подтверждена живьём (2026-08-28, self-чат: отправленное перечитано с провода, в сыром тексте ровно один @<guid>, совпадающий с обогащённым mentions[]); а вот факт пуш-уведомления адресату живьём не наблюдался - для этого нужен второй аккаунт.

Правка и упоминания. edit_message принимает необязательный mentions с той же семантикой запросов, что send_message. Без поля правка сохраняет упоминания цели, как раньше. С полем это заявленный ПОЛНЫЙ состав: запросы резолвятся, токены @<guid> подставляются в new_text до отпечатка, и на confirm возвращается эхом will_text, а не исходная строка. Рядом отдаётся will_text_preview с именами вместо guid - только для чтения, в отпечаток не входит. Пустой массив и отсутствие поля - РАЗНЫЕ вещи: первый стирает упоминания, второе их сохраняет, и отпечаток эти случаи различает, иначе draft одного режима подтверждался бы другим.

Ответ (reply_to_message_id). Timestamp цели входит в отпечаток нагрузки - его изменение между draft и confirm отклонит отправку. Цитата цели (reply_quote в draft) перечитывается с сервера отдельным запросом и в отпечаток НЕ входит: правка текста цели между draft и confirm отправку не отклоняет, потому что цитата на confirm берётся заново с сервера, а не из draft. Цитата обрезается до 200 символов (quote_truncated:true, если обрезана) - число выведено из реверса, живого случая цитаты длиннее 200 символов не было.

Пересылка (forward_from). Timestamp пересылаемого сообщения, тоже часть отпечатка. В отличие от ответа, пересылка идёт без цитаты.

send_file

Параметр

Тип

chat

ChatId либо поисковый запрос

path

абсолютный путь к файлу или картинке на диске

confirm

true - залить и отправить; иначе draft (байты не льются)

confirm_token

токен из draft, обязателен при confirm:true

Отправка картинки (image) или произвольного файла (file); тип определяется по расширению. Voice и gallery не отправляются - для них закрыт только долг чтения (см. [Non-Goals]). Двухшаговая: draft показывает имя/размер/тип/чат и НЕ льёт байты - заливка и все 3 шага (§12.1: upload_to_disk → PUT сырых байт → add_files) идут только на confirm. После confirm уходит обычное сообщение с file_info.id, и его можно прочитать обратно по file_id и скачать через download_attachment. Ошибки загрузки разделены: 507/403 → квота, 413 → размер, не «upload failed». Ответ без числового Status = отказ, как и у send_message.

Перезаливка при повторном confirm после рестарта. Локальная память токена живёт в процессе. Если процесс рестартовал между draft и confirm, повторный confirm пройдёт 3 шага загрузки заново - байты уйдут повторно. Дубля сообщения при этом нет: PayloadId зафиксирован в токене на draft и переживает рестарт, поэтому повтор придёт серверу тем же id и вернётся DUPLICATE (нового сообщения не создаст). Потери - только повторно израсходованные байты, и они ограничены квота-ошибкой. Не блокер, но знать полезно.

set_reaction

Параметр

Тип

chat

ChatId либо поисковый запрос

message_id

timestamp сообщения в микросекундах (строка)

type

целочисленный id реакции (артворк, не emoji) из поля reactions сообщения

remove

true - снять реакцию (Action:REMOVE); иначе поставить

Реверсибельно, поэтому без confirm: снятие откатывает постановку тем же вызовом. Подтверждено живьём (US-009, self-чат): постановка (Reaction без Action) -> реакция видна через list_reactions; снятие (Action:REMOVE) -> реакция исчезает; Status:1 в обоих случаях. type валидируется по карте reaction-map.json ДО отправки - неизвестный тип отвергается на входе со status: invalid_type и на провод не уходит (сервер Type не валидирует и принял бы любой int, включая мусор). Реакция уходит полным конвертом ClientMessage (плоский push({Reaction}) дал бы ложный NO_SUCH_CHAT).

list_reactions

Параметр

Тип

По умолчанию

chat

ChatId либо поисковый запрос для резолва чата

обязателен

message_id

timestamp целевого сообщения в микросекундах (строка)

обязателен

limit

лимит на провод в обоих вызовах

50

invite_hash

для чтения по join-ссылке

нет

Без confirm (чтение). Полный список «кто и когда» по сообщению - реакции (сгруппированы по типу, actors_complete:true ВСЕГДА, в отличие от get_history/get_message/get_message_context/get_thread, где акторы реакций - усечённый сиблинг агрегата) и прочтения. Стоит ДВА WS-вызова (UserReactions + UserReads/Mode:1) - дороже обогащения на сиблингах, зато без обрезки: сиблинги history обрезаны и источником истины не служат (живьём видено ReadsCount:10 при RecentUserReads длиной 3). limit обязателен на проводе в обоих вызовах - без него сервер отвечает BACKEND_CALL_ERROR(2).

mark_read

Параметр

Тип

chat

ChatId либо поисковый запрос

message_id

опционально: timestamp (мкс), до которого отметить прочитанным; без него - до самого свежего сообщения

seqno

опционально: SeqNo той же границы

Без confirm (безобидно). Без message_id тянет последнюю страницу истории и отмечает прочитанным до самого свежего сообщения. Форма и эффект подтверждены живьём (US-009): маркер SeenMarker бэкенд принимает, и именно он пишет seen-позицию, обнуляя непрочитанное (перебором: в уже прочитанном self-чате SeenMarker отвечает DUPLICATE, а ReadMarker/UnseenMarker коммитят заново; на чате с реальным непрочитанным от другого аккаунта unread_count ушёл с 2 до 0). В выдаче form_status: verified (см. Ограничения).

pin_message

Параметр

Тип

chat

ChatId либо поисковый запрос

message_id

опционально: timestamp (мкс) закрепляемого сообщения; без него - открепить

Без confirm (легко откатить). Семантика подтверждена живьём (US-009): закреп с меткой добавляет PinnedMessageInfo на это сообщение, а Pin без метки его убирает (открепление) - проверено на проводе через ChatData. В выдаче form_status: verified.

delete_message

Параметр

Тип

chat

ChatId либо поисковый запрос

message_id

timestamp (мкс) удаляемого сообщения

confirm

true - удалить; иначе draft

confirm_token

токен из draft, обязателен при confirm:true

Двухшаговая (удаление необратимо). Шаг 1 (без confirm): резолвит чат, перечитывает удаляемое (автор/время/текст) и возвращает превью с confirm_token. В сокет не уходит ничего - превью строится чтением. Шаг 2 (confirm:true + токен): удаляет пустым Plain{ChatId, Timestamp} (§9.3). На confirm chat и message_id сверяются с подтверждёнными; расхождение - отказ. Форма подтверждена живьём (US-009, self-чат): Status:1, повторное чтение даёт deleted:true и пустой текст. Серверного дедупа на повторе нет: сырой replay того же удаления дважды на уже удалённом вернул снова FULLY_COMMITTED (переприменяет), от повтора защищает локальная память confirm-слоя. Удаление чужого сообщения отклоняет сервер (внятный commit-статус вроде NO_PERMISSION) - своего ограничения тут нет.

edit_message

Параметр

Тип

chat

ChatId либо поисковый запрос

message_id

timestamp (мкс) правимого сообщения

new_text

новый текст

mentions

новый ПОЛНЫЙ состав упоминаний (опционально)

confirm

true - применить правку; иначе draft

confirm_token

токен из draft, обязателен при confirm:true

Двухшаговая (правка необратима). Шаг 1: резолвит чат, перечитывает сообщение и возвращает превью was_text -> will_text с confirm_token, ничего не меняя. Шаг 2: правит через convertMessageToPlain + Timestamp (§9.3). На confirm сверяются chat, message_id, new_text и состав mentions (смена любого инвалидирует токен). Упоминания: без поля mentions правка сохраняет упоминания цели, как раньше; с полем это заявленный ПОЛНЫЙ состав - запросы резолвятся, токены @<guid> подставляются в текст, и эхом на confirm возвращается will_text, а не исходная строка. Пустой массив и отсутствие поля - РАЗНЫЕ вещи: первый стирает упоминания, второе их сохраняет, и отпечаток эти случаи различает. Рядом отдаётся will_text_preview с именами вместо guid: только для чтения, в отпечаток не входит. Подробности - Упоминания. Форма подтверждена живьём (US-009, self-чат): Status:1, после правки сообщение читается с новым текстом, edited:true и непустым edited_at (LastEditTimestamp). Повторный confirm тем же токеном отдаёт запомненный результат, второго push не шлёт. Правку чужого отклоняет сервер.

get_poll

Параметр

Тип

chat

ChatId либо поисковый запрос

message_id

timestamp (мкс) сообщения-опроса

Без confirm (чтение). message_info даёт вопрос/варианты/лимит выбора, poll_info (§14.3) - агрегат: {is_poll, answers, my_choices, is_anonymous, voted_count, recent_voters, results} плюс сырой ответ. answers[i] несёт votes и, для не-анонимного опроса с голосами, voters (имя+время из AnswerVotes); у анонимного опроса сервер скрывает список голосующих даже по явному запросу - это отражено флагом voters_hidden:true (виден только агрегат и свой выбор). Признак «это опрос» виден и здесь (is_poll), и в обычной выдаче сообщения (kind:'poll'). Не опрос - статус not_a_poll. Чтение разрешено против любого реального опроса в любом чате.

vote_in_poll

Параметр

Тип

chat

ChatId либо поисковый запрос

message_id

timestamp (мкс) сообщения-опроса

choices

массив выбранных вариантов (индексы/id)

confirm

true - проголосовать; иначе draft

confirm_token

токен из draft, обязателен при confirm:true

Двухшаговая. Форма Vote{ChatId, Timestamp, Action:0, Choices} (§9.3/§11.4) подтверждена живьём (2026-07-17, commit_status:1 FULLY_COMMITTED): Action:0 обязателен (без него - BACKEND_CALL_ERROR(2)), Results не шлётся, Choices - 0-based индексы в Poll.Answers[] и полный набор выбора. Голос публичен и меняемый: повторная отправка заменяет прежний выбор целиком (несколько вариантов - все индексы в одном Choices) - это подтверждено повторным чтением, где my_choices сменился с [0] на [1] после повторной отправки. form_status в выдаче - verified (AC-29 закрыт). Почему confirm сохранён, хотя голос меняемый: сам факт голоса необратим - voted_count растёт, а в не-анонимном опросе голосующий попадает в список голосовавших; отменить голос до нуля протоколом не подтверждено (единственный оставшийся мелкий вопрос).

download_attachment

Параметр

Тип

file_id

из file_info рефа сообщения

chat_id

опционально, только контекст вызывающего: в запрос не идёт

size

SMALL, SMALL48, MIDDLE2048, ORIGINAL - превью для картинок; без него скачивается оригинал

Возвращает {path, bytes, content_type}. Повторный вызов не идемпотентен: имена вложений не уникальны (photo.jpg у всех), затирать чужой файл нельзя, поэтому повтор кладёт рядом копию с суффиксом.

Related MCP server: mcp-max-messenger

Треды

Тред - это чат: у него собственный ChatId, и всё, что умеет обычный чат (чтение, отправка, реакции, прочтения), работает в треде тем же способом - паритет с обычным чатом, а не отдельная механика.

  • Чтение: get_thread открывает тред по готовому thread_id либо по паре chat + message_id родительского сообщения. Пагинация та же, что у get_history: limit (1-200, по умолчанию 40) и курсор before (мкс строкой - вернуть сообщения строго старше него; значение для следующей страницы - next_before из выдачи). Пустой (ещё не материализованный) тред приходит с empty:true, а не ошибкой доступа.

  • Создание = деривация, без сети. Отдельного серверного «создать тред» нет. thread_id выводится строкой из родительского сообщения (§17.10, radix 10), и тред материализуется первым отправленным в него сообщением. «Обсудить» из веб-клиента - ровно эта деривация, реверса не требует. Бизнес-чаты (2/...) недоступны для деривации - это зафиксировано, а не забыто.

  • Отправка в тред идёт обычным send_message, где в поле chat передан thread_id (тред = валидный ChatId) - с той же двухшаговой отправкой draft->confirm.

  • Подписка: join_to_thread / leave_thread по thread_id - вступление и выход, обратимы, поэтому без confirm.

Требования

  • Node.js >= 22

  • Chromium для Playwright

Установка

Через npx (рекомендуется)

Отдельно устанавливать пакет не нужно - npx скачивает его из реестра по требованию и запускает. Разово нужен только браузерный движок, которым сервер управляет для входа:

npx playwright install chromium

Дальше сервер запускает MCP-клиент командой npx yandex-messenger-mcp - см. Подключение к MCP-клиенту. Руками её запускать не требуется.

Из исходников (для разработки)

git clone https://github.com/conarti/yandex-messenger-mcp.git
cd yandex-messenger-mcp
npm install
npx playwright install chromium
npm run build

Скрипты сборки, тестов и typecheck - в разделе Разработка.

Первый запуск и авторизация

Отдельного шага логина нет: авторизация ленивая и случается на первом вызове инструмента, который реально идёт к серверу. tools/list отвечает и без сессии.

Как это выглядит:

  1. Первый вызов. Поднимается headed-браузер Playwright на странице Мессенджера. Войдите обычным способом: QR-код, пароль, что настроено у вас. Сервер ждёт появления сессии до 5 минут.

  2. Сессия сохраняется в persist-профиле (~/.config/yandex-messenger-mcp/profile/). Дальше браузер не нужен: cookie извлекается, протокол гоняется в Node.

  3. Последующие запуски работают на сохранённом профиле, ручной вход не требуется.

  4. Протухание. Когда Яндекс отвергает cookie, профиль поднимается headless и даёт Паспорту рефрешнуть сессию (обычно пара секунд, незаметно). Если рефреш не помог, происходит эскалация в headed-логин, и вас снова попросят войти руками.

Единственный канал хрупкости здесь - сама cookie-сессия: долгий простой может потребовать ре-логина. Ничего другого не истекает.

Профиль и загрузки - это ваши личные данные. Каталог ~/.config/yandex-messenger-mcp/ содержит живую сессию Яндекса: он не должен попадать в git, синхронизацию или бэкапы, из которых его кто-то достанет.

Конфигурация

Файл: ~/.config/yandex-messenger-mcp/config.json. Целиком опционален - без него всё работает на дефолтах. Переопределять можно точечно, любую секцию и любое поле.

Ключ

Дефолт

Смысл

paths.profileDir

profile

Persist-профиль Playwright. Относительный путь резолвится от каталога конфига

paths.downloadsDir

downloads

Папка загрузок, туда же

downloads.ttlDays

7

TTL автоочистки загрузок. 0 или меньше - выключить подметание

limits.listChatsDefaultLimit

50

Дефолтный limit для list_chats

limits.searchDefaultLimit

50

Стартовый limit эскалации в search

protocol.*

см. ниже

Протокольные константы: на случай, если Яндекс их поменяет

Секция protocol существует ради устойчивости к ротации: если новая версия chats-web уедет на другие хосты, их можно поправить в конфиге, не трогая код. Значения по умолчанию и полный пример - в config.example.json.

Пример минимального конфига:

{
  "downloads": { "ttlDays": 3 },
  "limits": { "listChatsDefaultLimit": 100 }
}

Уровень логов задаётся переменной YANDEX_MESSENGER_MCP_LOG_LEVEL (debug/info/warn/error, по умолчанию info). Лог идёт в stderr: stdout принадлежит MCP stdio-транспорту. Секреты сессии и содержимое переписки в логах редактируются.

Подключение к MCP-клиенту

Сервер говорит по stdio. Путь до dist/index.js - абсолютный.

Таймаут вызова инструмента у MCP-клиента - минимум 5 минут. Первый вызов, идущий к серверу, поднимает браузерный вход и ждёт логина до 5 минут (см. Первый запуск). Дефолтные таймауты многих клиентов (30-60 секунд) короче этого ожидания и оборвут первый вызов молчаливым таймаутом ещё до того, как вы успеете войти - авторизация при этом выглядит «сломанной», хотя дело в таймауте. Поднимите таймаут вызова инструмента до >= 5 минут. Запас нужен и после первого входа: худший легальный read доходит до ~90 секунд, что тоже длиннее дефолтов.

Claude Code

Через npx (основной способ, после установки пакета из npm - см. Установка):

claude mcp add yandex-messenger -- npx -y yandex-messenger-mcp

Из собранных исходников (разработка):

claude mcp add yandex-messenger -- node /абсолютный/путь/yandex-messenger-mcp/dist/index.js

Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.json (macOS), через npx:

{
  "mcpServers": {
    "yandex-messenger": {
      "command": "npx",
      "args": ["-y", "yandex-messenger-mcp"]
    }
  }
}

Из собранных исходников (разработка) - тот же конфиг с command: "node" и путём до dist/index.js:

{
  "mcpServers": {
    "yandex-messenger": {
      "command": "node",
      "args": ["/абсолютный/путь/yandex-messenger-mcp/dist/index.js"]
    }
  }
}

Первый вызов любого инструмента откроет окно браузера для входа - это ожидаемо, см. Первый запуск.

Автоочистка загрузок (TTL)

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

  • Что удаляется: файлы в downloads/, у которых mtime старше TTL (дефолт 7 дней). Строго старше: файл ровно на границе остаётся.

  • Когда: на старте сервера и перед каждым скачиванием. Второе важнее первого - сервер может месяцами не рестартовать, и старт как единственная точка очистки не сработал бы.

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

  • Выключить: downloads.ttlDays: 0. Это именно «не подметать», а не «удалить всё разом».

Confirm-политика

Подтверждение (draft->confirm) стоит только у необратимых мутаций. Критерий один: откатывается ли последствие тем же инструментом за один вызов. Раньше необратимой была только отправка текста; с добавлением файлов, правки, удаления и голоса необратимых операций стало пять, и политика обобщена под общий критерий.

  • С confirm (двухшаговые, необратимые): send_message, send_file, delete_message, edit_message, vote_in_poll. Сообщение или файл уходят живому собеседнику, правка перезаписывает текст, удаление стирает, голос не снимается - отменить одним вызовом нельзя.

  • Без confirm (одним вызовом, обратимые или безобидные): set_reaction (Action:REMOVE откатывает тем же вызовом), pin_message (легко открепить), mark_read (безобидна). Read-пути (get_*, search, list_chats) и подписка на тред (join_to_thread/leave_thread) confirm тоже не требуют.

Почему confirm не раздан всем мутациям: дешёвый confirm обесценивает дорогой. Если подтверждать приходится и обратимую реакцию, его начинают жать не глядя - и тогда прожмут на delete_message. Подтверждение бережётся для того, что действительно необратимо.

Токен confirm несёт дискриминатор операции (op): токен, выданный одной операции, при предъявлении другой отвергается как op_mismatch - перепутать draft удаления с draft правки нельзя. На confirm заново резолвится чат и заново считается отпечаток нагрузки; любое расхождение - отказ, а не отправка «наиболее вероятного».

Двухшаговая отправка (send_message как образец)

Шаг 1 - draft. Обычный вызов резолвит чат и возвращает превью:

{
  "status": "draft",
  "chat_id": "...",
  "chat_name": "Имя чата",
  "text": "текст",
  "confirm_token": "...",
  "next_step": "Ничего не отправлено. ..."
}

В сокет не уходит ничего.

Шаг 2 - confirm. Повторный вызов с confirm:true, тем же confirm_token и неизменёнными chat и text.

Почему на confirm идёт повторная сверка, а не «отправить то, что в токене»: между draft и confirm может смениться всё. Тот же запрос chat завтра резолвится в другой чат - человек переименовался, появился однофамилец. Или к старому токену подставили другой текст. Поэтому токен несёт резолвнутый ChatId и хэш текста, на confirm чат резолвится и текст хэшируется заново, и результаты сверяются. Расхождение - отказ, а не отправка «наиболее вероятного».

Токен намеренно не подписан: подделывать его бессмысленно. Он не полномочие, а память о драфте - отправка всё равно идёт в заново проверенный чат.

Идемпотентность держится двумя слоями, потому что ретрая у отправки нет:

  1. Локально: израсходованный токен возвращает запомненный результат, второй push не уходит.

  2. На сервере: PayloadId фиксируется в токене на шаге 1, поэтому даже если локальная память потерялась (рестарт), повтор придёт как DUPLICATE - тоже успех, но нового сообщения не создаст.

Неоднозначный чат отправку блокирует: наружу уходят кандидаты, push не отправляется.

Ограничения и пробелы в доказательствах

Раздел честный. Часть протокола подтверждена живыми прогонами, часть - только фикстурами по реверсу веб-клиента, и это разные уровни уверенности.

Чего нет по решению (отложено)

  • Real-time. Никаких подписок на LIVE-события: новые сообщения, typing, seen, presence. Инструмент отвечает на запрос, а не слушает поток. Бота и автоответы на нём не построить.

  • Отправка вложений - только image и file. Картинки и произвольные файлы отправляются (send_file); voice и gallery отправлять нельзя (только читать). Голосовые и галереи читаются, но не создаются.

  • Мутации - частично. Реализованы реверсибельные (реакции set_reaction, отметка прочтения mark_read, закреп pin_message - одним вызовом, без confirm) и необратимые (отправка файла send_file, правка edit_message, удаление delete_message, голос vote_in_poll - двухшаговые draft->confirm). Чтение опроса - get_poll. Пока НЕ реализованы: отправка voice/gallery, звонки, управление чатами, мульти-аккаунт.

  • Только cookie-авторизация. OAuth не поддержан: в бандле это другой транспорт с другим форматом кадров, а не «второй режим», и он потребует отдельного WS-клиента.

Что не подтверждено живьём

  • Сборка приватного chat_id подтверждена живьём (2026-08-28, долг закрыт). Пара guid склеивается отсортированной по кодовым единицам UTF-16, а не в порядке «собеседник, я». Проверено на всей живой выдаче list_chats: 12 приватных чатов из 12 согласуются с сортировкой, причём представлены оба направления (у восьми собеседников guid больше моего, у трёх меньше, плюс self-чат). Прежняя конструкция промахивалась на тех чатах, где guid собеседника сортируется раньше моего - это и был баг #16. Резолв по имени прогнан живьём на обоих направлениях и в обоих случаях попал в цель.

  • Токен упоминания на исходящем подтверждён живьём; пинг адресату - нет (2026-08-28). Отправка в self-чат с упоминанием, перечитанная с провода, несёт в сыром MessageText ровно один токен @<guid>, совпадающий с обогащённым mentions[]. Это закрывает форму. Клиент адресата рендерит токен именем - наблюдено на втором аккаунте 2026-08-28: упоминание пришло кликабельной ссылкой с отображаемым именем, а не сырым guid. Это закрывает половину баг-репорта #15 («выглядит как обычный текст, без ссылки на пользователя»). Отдельного пуш-уведомления об упоминании в приватном чате не наблюдалось, и это принято как рабочее поведение, а не как дефект. Рабочая гипотеза владельца: в приватном чате уведомление приходит на ЛЮБОЕ сообщение, поэтому упоминанию нечего добавить, и пинг имеет смысл только в групповом чате. Проверить это нельзя: групповые чаты выведены за границы живого тестирования. Формально это РЕШЕНИЕ, а не доказательство; если поведение окажется другим, заводится отдельный issue. См. #15.

  • Reply на исходящем подтверждён живьём; чтение пересылки - подтверждено, отправка пересылки - нет (US-010 2026-07-21, дополнено спайком #22 2026-08-28). Отправка ответа (reply_to_message_id) даёт Status:1, и перечитывание возвращает context.is_reply:true с непустым quotes - цитата и признак ответа работают. Чтение входящей пересылки закрыто живым кадром (docs/spikes/v2/SPIKE-FORWARD-FRAME.md): сиблинг ForwardedMessages приходит и в history, и в message_info, элемент имеет обёртку {Payload, ServerMessageInfo} (Payload - это тело), блок из нескольких пересылок приходит массивом. До этой правки обёртка была угадана неверно, и forwarded[] молча оставался пустым - это и был баг #22. ForwardedMessageRefs не приходят вовсе - ни у пересылки, ни у reply, поэтому context у пересылки не строится, и reply держится на Quote. Отправка пересылки (forward_from) по-прежнему не подтверждена: она уходит с Status:1, но на self-чате форма не отрендерилась, см. issue #13. Пересылка с вложением проверена живьём в двух видах: картинка и обычный файл. В обоих случаях forwarded[].attachments[] отдал реф с file_id, именем и размером, то есть формы Payload.Image и Payload.MiscFile подтверждены, обёртка элемента одна и та же.

  • Чтение вложений: image, file и gallery проверены живьём; voice - долг. Скачивание типо-агностично (voice/gallery_image - это те же file_id, тянутся тем же generic-путём). Живьём (US-009) скачана настоящая галерейная картинка с аккаунта (gallery_image, непустые байты + content_type) - долг по галерее закрыт. Реального голосового на профиле нет, поэтому voice живьём по-прежнему не проверено - долг остаётся дословно, фикстура доказательством не объявляется.

  • Отправка вложений: путь не подтверждён до конца, но 403→квота поймана живьём (US-010, 2026-07-21). 3 шага загрузки (upload_to_disk → PUT → add_files) и обычное сообщение с Plain.Image/Plain.MiscFile + FileInfo.Id2 взяты из реверса веб-клиента: входящие вложения живьём наблюдались, а исходящий путь - нет. Width/Height картинки намеренно не проставляются (для доставки достаточно file_info). Живой прогон в self-чате упёрся в upload_to_disk HTTP 403, и код классифицировал его как upload quota (не generic «upload failed») - ветка 403→квота подтверждена живьём. Полный трёхшаговый путь и ветка 413→размер остаются доко-выведенными (заливка отклонена сервером до конца), см. issue #5. Билдеры в src/protocol/push.ts, загрузка в src/attachments/uploader.ts.

  • Форма ответа на отправку подтверждена живьём (US-009). Успешный push текста вернул { Status:1, MessageInfo:{TimestampMcs, PrevTimestampMcs, SeqNo, Version}, DebugInfo } - имена контейнера MessageInfo/PrevTimestampMcs/TimestampMcs/SeqNo/Version теперь наблюдены, а не реконструированы. DebugInfo (адреса/тайминги/попытки) сервер тоже отдаёт - не парсится, безвреден. RateLimit на успешной отправке не приходит. Парсер по-прежнему принимает оба написания; ответ без числового Status трактуется как отказ. Инвариант распространён и на путь вложений.

  • Постановка/снятие реакции подтверждены живьём (US-009, долг закрыт). Постановка (Reaction без поля Action, серверный дефолт ADD) -> реакция появляется в list_reactions; снятие (Action:REMOVE=1) -> реакция исчезает; Status:1 в обоих случаях. REPLACE(2) живьём не гонялся.

  • Голос vote_in_poll: отмена до нуля не подтверждена. Форма Vote{ChatId, Timestamp, Action:0, Choices} (§9.3/§11.4) закрыта живьём (2026-07-17, commit_status:1 FULLY_COMMITTED): Action:0 обязателен, Results не шлётся, Choices - 0-based индексы в Poll.Answers[], полный набор выбора. Голос публичен и меняемый - повторная отправка заменяет выбор целиком (подтверждено повторным чтением: my_choices сменился с [0] на [1]). form_status в выдаче - verified, AC-29 закрыт. Confirm сохранён, потому что сам факт голоса необратим: voted_count растёт, а в не-анонимном опросе голосующий попадает в список голосовавших. Единственный оставшийся мелкий вопрос - отмена голоса до нуля (пустой Choices либо иной Action) протоколом не подтверждена (кнопки в веб-UI нет).

Известные грубости

  • Единица rate_limit.wait_for неизвестна. Ни в доке, ни в живом захвате она не встретилась (на успешной отправке rate_limit не приходит вовсе). Гадать не стали: сырое значение трактуется как миллисекунды и зажимается в 1-60 секунд. Кламп ограничивает ущерб при любой из трёх гипотез: если это секунды, минимум не даст устроить ретрай-шторм; если микросекунды, максимум не даст зависнуть на часы; если миллисекунды, значение проходит как есть. Точность здесь принесена в жертву осознанно. В лог пишется сырое значение - первый живой случай позволит определить единицу.

  • У поиска нет серверной пагинации. Параметры page/offset/from/skip сервером игнорируются, поля page/pages в ответе вестигиальны (всегда 1), а total - это число возвращённых элементов, а не общее число совпадений. Полнота достигается эскалацией limit, то есть несколькими запросами вместо одного. Серверного потолка limit найти не удалось (1000 отвечает штатно), поэтому потолок эскалации клиентский: при упоре - truncated:true.

  • Автоматизация личного аккаунта. Это личный инструмент на неофициальном протоколе. Риски по ToS вы принимаете на себя. Отправка не распараллеливается, массовых рассылок здесь нет.

  • Протокол может уехать. Он снят с конкретной версии chats-web. Обновление веб-клиента может сломать инструмент; протокольные константы вынесены в protocol.* конфига, чтобы часть таких поломок чинилась без правки кода.

Границы доверия

Сводка открытых пунктов из разделов выше - для быстрой сверки, без деталей (детали в тексте по ссылке-issue или в самом разделе).

Пункт

Статус

Issue

Чтение voice не подтверждено живьём

долг

#4

Разделение ошибок загрузки 507/403 (квота) / 413 (размер) не проверено живьём

долг

#5

REPLACE(2) у реакции объявлен, но не используется и не наблюдался на проводе

долг

#6

Отмена голоса в опросе до нуля не подтверждена (кнопки в UI нет)

долг

#7

Единица rate_limit.wait_for неизвестна, сырое значение зажато в 1-60 секунд

долг

#8

Обрезка цитаты reply до 200 символов (QUOTE_MAX_LENGTH, src/protocol/push.ts)

выведено

-

actors_complete реакций в обогащении get_history/get_message/get_message_context/get_thread - сравнение count с числом акторов (src/protocol/enrichMessage.ts), случай расхождения живьём не наблюдался

выведено

-

Форма выдачи изменилась: у удалённого сообщения kind:'deleted' вместо прежнего 'unknown'. 'unknown' теперь означает строго «тела нет либо content-поля нет». Миграция - через поле deleted, оно не менялось

ломающее изменение

#22

Форма выдачи изменилась: search отдаёт сообщения обогащёнными, как read-инструменты: reads, mentions, reactions, thread, forwarded, from_me. Прежде он отдавал голый v1-объект, и пересылка в его выдаче приходила пустой. Цена размера: пустое обогащение стоит около 116 байт на сообщение даже когда обогащать нечего, насыщенное - до килобайта (замер в #19)

ломающее изменение

#22

Разбор вложения в оригинале пересылки подтверждён живьём (2026-08-28) для ОБОИХ видов: forwarded[].attachments[] отдал kind:'image' и kind:'file' с file_id, именем и размером. Обёртка элемента одна и та же, отдельной ветки для файлов нет

наблюдено живьём

#22

Форма выдачи изменилась: отказ резолва чата несёт reason, candidates[] и next_step. Литерал status:'chat_not_found' сохранён, поля добавлены. reason различает «имя не нашлось», «человек нашёлся, чата нет» и «бэкенд ответил ENTITY_NOT_FOUND». При причине «имя не нашлось» candidates[] пуст структурно, всегда: до этой ветки доходит только состояние с двумя пустыми бакетами, поэтому нагрузку там несёт next_step, а не список

ломающее изменение

#18

Форма выдачи изменилась: search отдаёт chat_id для найденного человека плюс chat_id_via:'user_search'. Значение guid наблюдено сервером, а chat_id сконструирован из пары guid - метка это и фиксирует

аддитивное изменение

#17

Форма выдачи изменилась: send_message на draft отдаёт text_preview (имена вместо guid, только для чтения)

аддитивное изменение

#15

Поле via не является сквозным дискриминатором «наблюдено против сконструировано»: toSelfChatCandidate тоже конструирует chat_id из пары guid (src/chat/resolveChat.ts), но помечает его via:'chat_search'. Надёжен только chat_id_via в выдаче search

выведено

-

Отдельное пуш-уведомление об упоминании в приватном чате не наблюдалось. Форма токена на проводе подтверждена, рендер у адресата наблюдён (кликабельное имя вместо guid), а уведомление - нет. Принято как рабочее поведение по гипотезе «в приватном чате уведомляет само сообщение, пинг осмыслен только в групповом»; групповые чаты вне границ тестирования

решение, не доказательство

#15

search возвращает вас самих, а резолв чата - нет. toUserCandidate (src/chat/resolveChat.ts) отбрасывает кандидата с вашим guid («сам себе собеседником не бываю»), потому что у резолва есть отдельная ветка self-чата. У toUserHit в search такой ветки нет, и гард там сознательно не повторён: chat_id вида <мой>_<мой> - это корректный адрес self-чата. Итог: в выдаче search вы можете найти себя, в кандидатах резолва - нет

осознанное расхождение

#17

edit_message принимает состав упоминаний. Поля mentions нет - поведение прежнее, упоминания цели читаются и переотправляются. Поле есть - это НОВЫЙ ПОЛНЫЙ состав: запросы резолвятся, токены подставляются в текст, старый состав не подмешивается. Пустой массив, в отличие от отсутствия поля, СТИРАЕТ упоминания, и отпечаток эти два случая различает

аддитивное изменение

#15

Код ENTITY_NOT_FOUND(4) означает «чата нет», а не «по запросу нет данных»: проверено живьём на несуществующем чате против пустого ОКНА ДАТ в существующем. Случай «чат существует и пуст всю жизнь» отдельно не проверялся - такого чата в профиле не нашлось

наблюдено для пустого диапазона, выведено для пустого чата

#18

Разработка

npm run build       # tsc
npm run typecheck   # tsc с тестами
npm test            # vitest, e2e при этом скипается
npm run test:watch

E2E

Живой smoke-тест ходит на реальный аккаунт и по умолчанию скипается. Запуск явный:

YMCP_E2E=1 npm test

Он намеренно только читает (whoami, list_chats, get_history): ничего не отправляет и ничего не качает, чтобы его можно было безопасно гонять повторно. Ассерты идут только по числам и булям - живые данные не попадают ни в вывод, ни в диагностику падений.

Available Tools

19 tools
delete_messageDelete messageA
Destructive

Удаление своего сообщения в два шага: без confirm возвращает превью удаляемого (draft, автор/время/текст) и НЕ удаляет; с confirm:true и confirm_token из превью удаляет. Удаление необратимо, поэтому чат и message_id на шаге confirm сверяются с подтверждёнными; расхождение отклоняется. Удаление чужого сообщения отклоняет сервер. После удаления сообщение читается с deleted:true.

ParametersJSON Schema
NameRequiredDescriptionDefault
chatYesChatId либо поисковый запрос для резолва чата
confirmNofalse/отсутствует - вернуть draft-превью; true - удалить (необратимо)
message_idYesTimestamp удаляемого сообщения в микросекундах (строка)
confirm_tokenNoТокен из draft-превью. Обязателен при confirm:true

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite destructiveHint:true already signaling danger, the description adds crucial behavioral context: the first step does not delete, deletion is irreversible, chat and message_id are revalidated, mismatches are rejected, and the message becomes readable with deleted:true afterward. This goes well beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and information-dense: every sentence contributes either workflow, safety, or post-condition detail. The two-step behavior is front-loaded, and there is no redundant filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is complete for a destructive tool with no output schema: it explains the preview payload, the confirmation mechanism, irreversibility, ownership restriction, and the resulting message state. An agent has enough information to invoke both steps correctly and understand failure conditions.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already documents all four parameters with 100% coverage, so the baseline is 3. The description adds meaningful semantic context by explaining the two-phase flow, the role of confirm_token from the preview, and the validation of chat/message_id on the confirm step, which supplements the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool deletes the user's own message using a two-step confirmation workflow, and explicitly notes that deleting another user's message is rejected. This distinguishes it from sibling tools like edit_message and send_message with a specific verb, resource, and scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains exactly when to use the tool and how to sequence calls: first without confirm to get a preview, then with confirm:true and the token to actually delete. It clearly excludes deleting other users' messages, though it does not explicitly contrast with alternatives like edit_message.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

download_attachmentDownload attachmentA

Скачивает вложение по file_id в папку загрузок (/root/.config/yandex-messenger-mcp/downloads) и возвращает локальный путь.

ParametersJSON Schema
NameRequiredDescriptionDefault
sizeNoРазмер превью для КАРТИНОК. ВНИМАНИЕ: живьём этот параметр сервером ИГНОРИРУЕТСЯ - download-путь отдаёт оригинал независимо от size (проверено на картинке 4080px). Оставлен для совместимости.
chat_idNoChatId источника - только контекст вызывающего, в запрос скачивания не идёт
file_idYesИдентификатор файла из file_info рефа сообщения

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide only false hints (not readOnly, not idempotent, not destructive). The description adds the download path and return value but lacks details on overwrite behavior, error handling, or side effects beyond saving the file.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence that front-loads the action and includes essential detail (download path). No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description reports the return value (local path). It covers the core functionality but omits edge cases like missing file or permission issues.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with detailed parameter descriptions, so the description does not need to add much. It does not elaborate on parameters, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description uses specific verb 'скачивает' (downloads) and resource 'вложение' (attachment) with explicit destination folder. It clearly states what the tool does and is distinct from sibling tools, none of which perform downloads.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implicitly tells when to use (when you have a file_id) and there are no alternative download tools among siblings. However, it does not explicitly state prerequisites or contrast with other tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

edit_messageEdit messageA
Destructive

Правка своего сообщения в два шага: без confirm возвращает превью «было -> станет» (draft) и НЕ правит; с confirm:true и confirm_token из превью правит. Правка необратима, поэтому чат, message_id, new_text и состав mentions на шаге confirm сверяются с подтверждёнными; расхождение отклоняется. Правку чужого сообщения отклоняет сервер. После правки сообщение читается с новым текстом и непустым LastEditTimestamp.

ParametersJSON Schema
NameRequiredDescriptionDefault
chatYesChatId либо поисковый запрос для резолва чата
confirmNofalse/отсутствует - вернуть draft-превью; true - применить правку (необратимо)
mentionsNoНОВЫЙ ПОЛНЫЙ состав упоминаний. БЕЗ этого поля упоминания правимого сообщения переотправляются как есть; с ним старый состав не подмешивается, а пустой массив стирает упоминания. На DRAFT - запросы: @Имя, @<guid> или голый guid; резолвятся по каталогу организации (неоднозначность отклоняет правку). На CONFIRM предъявляются РОВНО те guid, что вернул draft, в том же порядке: изменение состава/порядка отклонит правку
new_textYesНовый текст сообщения. На шаге draft названные в mentions строки заменяются в тексте на токены @<guid>; на confirm верните draft.will_text эхом без изменений
message_idYesTimestamp правимого сообщения в микросекундах (строка)
confirm_tokenNoТокен из draft-превью. Обязателен при confirm:true

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say destructiveHint=true, but the description discloses far more: the draft step is non-mutating, the confirm step is irreversible, chat/message_id/new_text/mentions are cross-validated at confirm and discrepancies rejected, foreign-message edits are server-rejected, and the edited message reads back with a non-empty LastEditTimestamp. This meaningfully extends what the annotations already provide, and there is no contradiction with destructiveHint=true.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences arranged as cause-and-effect: draft behavior, confirm behavior with irreversibility and validation, then post-edit state. It is front-loaded with the most critical fact (two-step process, draft does not edit), and every clause earns its place — nothing repeats the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex six-parameter tool with no output schema, the description covers the whole call sequence, irreversibility, mismatch rejection, the own-message restriction, and the observable post-edit state (new text plus LastEditTimestamp). Small gaps remain: the confirm step's return value and error shapes are not described, and the draft preview's exact structure is only partially sketched — though the schema's detailed parameter documentation partially compensates.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema descriptions are already unusually rich — mentions documents the draft/confirm resolution and ordering rules, confirm explains the boolean switch, and confirm_token ties to the draft. The description contributes flow-level context (draft first, then confirm with token) but adds no parameter-specific meaning beyond the schema, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource+scope constraint: 'Правка своего сообщения' (editing one's own message), and immediately explains the two-step draft/confirm mechanism. This distinguishes it from sibling tools like send_message, delete_message, and pin_message without needing to open their schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The usage context is explicit: a mandatory two-step sequence where 'без confirm возвращает превью ... и НЕ правит' but 'с confirm:true и confirm_token из превью правит'. It also states an exclusion — 'Правку чужого сообщения отклоняет сервер' — signaling not to use it on messages the agent didn't author. It falls short of explicitly naming alternatives (e.g., send_message for new messages), so it earns a 4 rather than a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_historyGet chat historyA
Read-only

Страница сообщений конкретного чата с пагинацией по курсору.

ParametersJSON Schema
NameRequiredDescriptionDefault
chatYesChatId либо поисковый запрос (имя собеседника/чата) для резолва
afterNoISO-дата/время: сообщения строго ПОСЛЕ этого момента (альтернатива from_date)
limitNoМаксимум сообщений на страницу (по умолчанию 40)
beforeNoКурсор: timestamp в микросекундах (строка, точность BigInt). Вернуть сообщения строго старше него; значение для следующей страницы - next_before из предыдущей выдачи
to_dateNoISO-дата/время верхней границы (ИСКЛЮЧАЮЩАЯ): сообщение ровно на to_date не попадает. Для «сообщений за сегодня» передайте from_date=сегодня, to_date=завтра
from_dateNoISO-дата/время нижней границы (включающая): сообщения от этой даты и позже. Пример: 2026-07-17

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so the read-only nature is covered. The description adds that the tool returns a page of messages with cursor pagination, which is useful but does not disclose additional behavioral traits like rate limits or sorting order.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that immediately states the core functionality (get chat history with pagination). No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, and the description does not explain the return format (e.g., message fields, cursor structure). Given the complexity of parameters (date range, cursor), the description is incomplete for an agent to fully understand the tool's behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so all parameters have descriptions in the schema. The tool description does not add new meaning beyond the schema; it only mentions pagination. Baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it retrieves a page of messages from a specific chat with cursor pagination. The verb 'get' and resource 'history' are specific, and the pagination detail distinguishes it from siblings like get_message (single message) and search (query-based).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for retrieving chat messages with pagination but does not explicitly state when to use this tool versus alternatives like get_thread or search. No 'when not to use' guidance is provided, though the context of cursor pagination hints at its purpose.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_messageGet single messageA
Read-only

Одно сообщение по chat_id + message_id (message_id = timestamp в микросекундах) ЛИБО по join-ссылке. Без загрузки истории. Возвращает обогащённое сообщение и детальные реакции/прочтения.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNojoin-ссылка Мессенджера (альтернатива паре chat + message_id)
chatNoChatId либо поисковый запрос; нужен вместе с message_id
message_idNoTimestamp сообщения в микросекундах (строка); нужен вместе с chat
with_reactionsNoТянуть детальные реакции/прочтения (2 доп. вызова). По умолчанию true

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true. Description adds that it returns enriched message with detailed reactions/read receipts and that with_reactions triggers additional calls, providing useful behavioral context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences convey all essential information efficiently without fluff, with critical details front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, but description mentions return of enriched message and reactions. However, it does not explain the structure of enriched message or reactions, leaving some ambiguity despite covering usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. Description adds context about alternative usage (join link) and explains message_id as timestamp in microseconds, but parameter descriptions in schema are already adequate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the tool retrieves a single message by two alternative methods (chat+message_id or join link) and specifies it does not load history, distinguishing it from sibling tools like get_history and get_message_context.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implies when to use (single message retrieval without history) and provides two identification methods, but does not explicitly state when not to use or compare with siblings beyond noting history exclusion.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_message_contextGet message contextA
Read-only

Окно сообщений вокруг метки: N сообщений до и N после указанного message_id (timestamp в микросекундах).

ParametersJSON Schema
NameRequiredDescriptionDefault
chatYesChatId либо поисковый запрос для резолва чата
afterNoСколько сообщений ПОСЛЕ метки (по умолчанию 10)
beforeNoСколько сообщений ДО метки (по умолчанию 10)
message_idYesTimestamp целевого сообщения в микросекундах (строка)

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already indicate readOnlyHint=true, so the safety profile is known. The description adds that the tool uses a timestamp in microseconds as the marker and returns a window of messages with configurable before/after counts, which goes beyond the annotation. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, clear sentence that efficiently conveys the core functionality. No extraneous information; it is front-loaded with the key concept.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description explains the input parameters well but does not describe the output format or what fields the returned messages contain. Since there is no output schema, more detail on the return structure would improve completeness for an agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with each parameter described. The description provides a high-level overview but does not add significant new details beyond the schema. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves a window of messages around a specified message_id, with N messages before and after. It uses specific verb ('get') and resource ('message context'), and distinguishes from siblings like get_message (single message) and get_history (possibly whole history).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the use case: when you need context around a specific message. However, it does not explicitly say when to use this vs alternatives (e.g., get_history for broader range, get_message for single). No when-not or alternative guidance is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_pollGet pollA
Read-only

Читает опрос по chat + message_id (message_id = timestamp в микросекундах), без confirm. Возвращает вопрос (title), варианты (answers, с title/votes и, для не-анонимного опроса, voters - кто голосовал), лимит выбора (max_choices), мой выбор (my_choices), признак анонимности (is_anonymous), число проголосовавших (voted_count) и результаты (results). У анонимного опроса сервер скрывает список голосующих даже по явному запросу - voters_hidden:true, доступен только агрегат и свой выбор. Признак «это опрос» виден полем is_poll (в обычной выдаче сообщения - kind:poll). Если сообщение не опрос - статус not_a_poll.

ParametersJSON Schema
NameRequiredDescriptionDefault
chatYesChatId либо поисковый запрос для резолва чата
message_idYesTimestamp сообщения-опроса в микросекундах (строка)

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Detailed explanation of anonymous poll behavior (voters_hidden: true) and error case 'not_a_poll'. Annotations already declare readOnlyHint=true, and description adds valuable behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is somewhat lengthy but every sentence adds value, front-loading purpose. Could be slightly more concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema, but description fully enumerates return fields and explains behavior for anonymous polls. Complete for a read-only tool with clear input.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and description adds meaning: chat can be a ChatId or search query, message_id is a timestamp in microseconds as a string. Adds value beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states 'Reads a poll by chat + message_id' and lists all return fields. Distinguishes from siblings like get_message or vote_in_poll by being specific to polls.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States 'без confirm' (without confirmation) indicating a read operation. Implicitly contrasts with vote_in_poll but lacks explicit 'when not to use' guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_threadGet threadB
Read-only

Сообщения треда как микро-чата. Адресуется либо готовым thread_id, либо парой chat + message_id родительского сообщения (деривация thread_id, «Обсудить»). Пустой тред (ещё не материализован) возвращается с empty:true - первое сообщение в него отправляется через send_message с этим thread_id как ChatId.

ParametersJSON Schema
NameRequiredDescriptionDefault
chatNoРодительский чат: ChatId либо поисковый запрос; нужен вместе с message_id
limitNoМаксимум сообщений треда (по умолчанию 40)
beforeNoКурсор: timestamp в микросекундах (строка). Вернуть сообщения строго старше него
thread_idNoГотовый ChatId треда (альтернатива паре chat + message_id)
message_idNoTimestamp родительского сообщения в микросекундах (строка); нужен вместе с chat

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds behavioral context beyond annotations, such as the empty thread case (empty:true) and that the first message is sent via send_message. This complements the readOnlyHint annotation without contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise but dense, mixing key usage info with a tangential note about send_message. It could be better structured and front-loaded with the core purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Since there is no output schema, the description should explain the return structure. It only mentions empty:true for empty threads, leaving pagination, message fields, and other details unspecified, which is inadequate for a retrieval tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage, the baseline is 3. The description adds minimal extra meaning by clarifying the two addressing modes, but does not deepen understanding beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states that the tool retrieves thread messages as a micro-chat and explains two addressing modes (thread_id or chat+message_id). It differentiates from siblings like get_message or get_history, but could be more explicit about contrasts.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for fetching thread messages but does not provide explicit guidance on when to use this tool versus alternatives like get_message_context or get_history. No when-not or exclusion criteria are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

join_to_threadJoin threadA
Idempotent

Подписка на тред по thread_id (§17.10). Это вступление в тред, не создание и не отправка. Легко откатывается leave_thread, поэтому confirm не требует.

ParametersJSON Schema
NameRequiredDescriptionDefault
thread_idYesChatId треда (дериватив get_thread)

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotent and non-destructive. Description adds context about easy rollback and no confirmation needed, which complements the annotations without contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences with key information front-loaded: action, parameter, and important nuances (rollback, no confirm). No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given simple tool with one parameter, no output schema, and ample annotations, the description covers purpose, usage, behavior, and parameter completely. No gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and schema describes thread_id as 'ChatId треда (дериватив get_thread)'. Description repeats the parameter usage but adds no new semantics beyond what schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states the tool subscribes/joins a thread by thread_id, distinguishes from creating or sending messages, and differentiates from sibling tools like leave_thread and get_thread.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly mentions when to use (thread_id), what it is not (creation/sending), and notes easy rollback via leave_thread. Lacks explicit comparison with all siblings but provides sufficient guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

leave_threadLeave threadA
Idempotent

Выход из треда по thread_id (§17.10). Отписка; ничего не разрушает, confirm не требует.

ParametersJSON Schema
NameRequiredDescriptionDefault
thread_idYesChatId треда (дериватив get_thread)

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true and destructiveHint=false. The description adds that no confirmation is needed and nothing is destroyed, which is consistent but not significantly beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single concise sentence that immediately conveys the action and key constraints. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has a single parameter, no output schema, and annotations provide safety profile, the description covers purpose and behavioral traits sufficiently.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with a clear description for thread_id. The tool description does not add additional parameter semantics beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb (leave/unsubscribe) and the resource (thread), with reference to a specification section. It distinguishes from sibling tools like join_to_thread.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description says it does not destroy anything and does not require confirmation, but does not explicitly state when to use this tool versus alternatives or provide exclusion criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_chatsList chatsA
Read-only

Список чатов с метаданными (последнее сообщение, флаг непрочитанных), отсортированный по свежести. Текст последнего сообщения по умолчанию НЕ отдаётся (только метаданные) - включите include_last_message_text, если он действительно нужен.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoМаксимум чатов (по умолчанию 50)
unread_onlyNoВернуть только чаты с непрочитанными сообщениями
include_last_message_textNoВернуть полный текст последнего сообщения каждого чата. По умолчанию false: отдаются только метаданные (без текста, цитат и имён файлов), чтобы не тащить содержимое чужих переписок в контекст модели.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No contradiction with readOnlyHint annotation. Adds behavioral detail about excluding message text by default for privacy, which is beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with purpose, no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Describes metadata returned (last message, unread flag) but lacks full output structure details. Given no output schema, more explicit fields would help completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds context for include_last_message_text (privacy rationale) and implies defaults for limit. This adds value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it lists chats with metadata and sort order. It distinguishes from siblings by specifying the resource and scope, but doesn't explicitly contrast with tools like search or get_history.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains default behavior (no last message text) and when to enable include_last_message_text. Lacks explicit when-not-to-use or alternatives among siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_reactionsList reactions and readsA
Read-only

Полный список «кто и когда» по сообщению: реакции (сгруппированы по типу, actors_complete:true - ВСЕГДА полный список, в отличие от get_history/get_message_context/get_thread, где актёры реакций могут быть усечённым сиблингом агрегата) и прочтения. Стоит ДВА WS-вызова (UserReactions + UserReads/Mode:1, §17.12) - дороже сиблингов, зато без обрезки.

ParametersJSON Schema
NameRequiredDescriptionDefault
chatYesChatId либо поисковый запрос для резолва чата
limitNoЛимит на провод в обоих вызовах (по умолчанию 50)
message_idYesTimestamp целевого сообщения в микросекундах (строка)
invite_hashNoДля чтения по join-ссылке (§17.11)

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate readOnlyHint=true, and description adds significant context: always returns complete actor lists, uses two WS calls (UserReactions + UserReads/Mode:1), and is more expensive. No contradictions, full transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is a single paragraph with no wasted words; each sentence adds value (purpose, differentiation, cost). Front-loaded with intent. Clear and efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 4 parameters, read-only annotation, and no output schema, description covers purpose, distinction from siblings, and behavioral details (complete list, two calls). Could briefly mention return structure, but overall adequately complete for agent use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so baseline is 3. Description does not add parameter-level details beyond schema; mentions output behavior (actors_complete:true) but not parameters. No extra semantic value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the tool lists reactions and reads for a message, with specific verb+resource. It explicitly distinguishes from siblings like get_history/get_message_context/get_thread by noting completeness, earning a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly tells when to use this tool (for complete list) versus alternatives (which may truncate). It also notes higher cost (two WS calls), providing clear usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mark_readMark chat readA
Idempotent

Отмечает чат прочитанным ОДНИМ вызовом, без confirm (безобидно). Без message_id отмечает прочитанным до самого свежего сообщения (тянет последнюю страницу истории). Семантика маркера (SeenMarker) подтверждена живьём: обнуляет непрочитанное (form_status: verified в выдаче).

ParametersJSON Schema
NameRequiredDescriptionDefault
chatYesChatId либо поисковый запрос для резолва чата
seqnoNoSeqNo той же границы (необязателен)
message_idNoTimestamp (мкс), до которого включительно отметить прочитанным; без него - до самого свежего

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations say it is a non-read-only, idempotent, non-destructive action; the description adds meaningful behavior beyond that: one-call confirmation-free execution, fetching the last history page when message_id is omitted, and the verified SeenMarker effect that resets unread state. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact (three sentences) and front-loaded with the core action. The third sentence on SeenMarker verification is useful but slightly implementation-detail heavy; overall every sentence contributes.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple 3-parameter tool with no output schema, the description covers the action, optional behavior, safety profile, and side effects (history fetch, unread reset). Nothing critical is missing for an agent to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents chat, seqno, and message_id. The description only restates the message_id optional behavior and adds no new parameter syntax or resolution detail, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Отмечает чат прочитанным' (marks chat as read). The 'ОДНИМ вызовом' qualifier and the SeenMarker semantic detail clearly distinguish the action from sibling tools like get_history or delete_message.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no direct sibling that marks chats read, so the description instead gives practical usage context: it is safe ('без confirm (безобидно)') and explains the two modes — with or without message_id. This is clear context, though it stops short of explicit exclusions or alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pin_messagePin or unpin messageA

Закрепляет или открепляет сообщение ОДНИМ вызовом, без confirm (легко откатить). С message_id закрепляет это сообщение; без message_id открепляет. Семантика Pin.Timestamp подтверждена живьём (form_status: verified).

ParametersJSON Schema
NameRequiredDescriptionDefault
chatYesChatId либо поисковый запрос для резолва чата
message_idNoTimestamp (мкс) закрепляемого сообщения; без него - открепить

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses that the operation is reversible ('easy to roll back') and that the semantics are verified. Annotations already indicate the tool is not read-only, idempotent, or destructive, and the description adds value by confirming the single-call behavior and the conditional pin/unpin logic.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is very concise, consisting of two short sentences that contain no redundant information. Every word adds value, and the structure is front-loaded with the main action.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the low parameter count, full schema coverage, and presence of annotations, the description provides sufficient context for an agent to correctly select and invoke the tool. The behavior for both cases is clearly explained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with descriptions for both parameters. The description adds meaning by explaining that providing message_id pins the message and omitting it unpins, which goes beyond the schema's individual parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (pin or unpin a message) and the resource (message) with a specific verb. It distinguishes from sibling tools as no other sibling performs pinning. The Russian language may be a barrier for non-Russian agents, but given the tool name and title are English, it's assumed the agent understands.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear guidance on when to use the tool: to pin or unpin a message in a single call. It explains the behavior based on the presence of message_id. However, it does not explicitly mention when not to use it or suggest alternatives, though no direct competitors exist among siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_fileSend file or imageA

Отправка картинки или файла в два шага: без confirm возвращает превью (draft: имя/размер/тип/чат) и НЕ заливает байты; с confirm:true и confirm_token из превью заливает (3 шага §12.1) и отправляет. Отправка необратима, поэтому чат и файл на шаге confirm сверяются с подтверждёнными; расхождение отклоняется. Тип определяется по расширению (image или file); voice/gallery не отправляются (только чтение). После отправки сообщение читается обратно по file_id и вложение скачивается download_attachment.

ParametersJSON Schema
NameRequiredDescriptionDefault
chatYesChatId либо поисковый запрос для резолва чата
pathYesАбсолютный путь к файлу или картинке на диске
confirmNofalse/отсутствует - вернуть draft-превью (байты НЕ льются); true - залить и отправить (необратимо)
confirm_tokenNoТокен из draft-превью. Обязателен при confirm:true

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses all important behavioral traits: initial call returns draft without uploading bytes, confirm call uploads and sends irreversibly; verification of chat and file against confirmed values; type determination by extension; post-send behavior (reading message and downloading attachment). No contradiction with annotations (destructiveHint=false is consistent with creating a message).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single paragraph in Russian is information-dense but well-organized. Every sentence adds new information. Could be slightly improved with bullet points or clearer separation of steps, but it remains efficient and front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (two-step, irreversible, verification), the description covers all necessary aspects: workflow, constraints (no voice/gallery), and post-send retrieval. No output schema, but description compensates by explaining how to download the attachment after sending.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers all 4 parameters with descriptions. The description adds significant value by explaining the two-step workflow for confirm and confirm_token, clarifying that path is absolute, and linking parameters to the behavioral steps. It goes beyond what schema alone provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states it sends files/images in a two-step process, distinct from siblings like send_message (text) and download_attachment (retrieval). It specifies the verb (send) and resource (file or image) with precise scope (two-step, irreversible).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Describes when to use (sending files/images) and the two-step workflow. It explicitly mentions that voice/gallery types are not sent (only reading). However, it does not explicitly state when not to use this tool in favor of a sibling, though the distinction is clear from context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_messageSend messageA

Отправка текстового сообщения в два шага: без confirm возвращает превью (draft) и НЕ отправляет; с confirm:true и confirm_token из превью отправляет. Отправка необратима, поэтому чат и текст на шаге confirm сверяются с подтверждёнными; расхождение отклоняется.

ParametersJSON Schema
NameRequiredDescriptionDefault
chatYesChatId либо поисковый запрос для резолва чата
textYesТекст сообщения. На шаге draft названные в mentions строки заменяются в тексте на токены @<guid> - именно так упоминание пингует адресата; на confirm верните draft.text эхом без изменений
confirmNofalse/отсутствует - вернуть draft-превью; true - отправить (необратимо)
mentionsNoУпоминания участников. На DRAFT - запросы: @Имя, @<guid> или голый guid; резолвятся по каталогу организации (неоднозначность отклоняет отправку). На CONFIRM предъявляются РОВНО те guid, что вернул draft, в том же порядке: изменение состава/порядка отклонит отправку. Формат guid проверяется при сборке отпечатка; точный адрес гарантирует только guid
forward_fromNoПереслать сообщение: timestamp пересылаемого в микросекундах (строка). Пересылка без цитаты (в отличие от reply). Входит в отпечаток: изменение между draft и confirm отклонит отправку
confirm_tokenNoТокен из draft-превью. Обязателен при confirm:true
reply_to_message_idNoОтветить на сообщение: timestamp цели в микросекундах (строка). Цитата перечитывается с сервера на confirm и показывается в draft (reply_quote); в отпечаток она НЕ входит, поэтому правка текста цели между draft и confirm отправку не отклоняет. Сам message_id в отпечаток входит: его изменение между draft и confirm отклонит отправку

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations, the description discloses critical behavioral traits: the preview step does NOT send, sending is irreversible, and chat/text are re-verified against the confirmed values at the confirm step, with mismatches rejected. This is richer than the annotations alone and helps an agent understand side effects and safety.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two dense sentences with front-loaded behavioral scope: the two-step mechanism, the non-sending draft step, and the irreversible confirm step. Every sentence carries essential information with no redundancy, making it efficient for an agent to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complex two-step flow and no output schema, the description adequately explains the draft/confirm contract and the need to return confirm_token from the draft. It does not describe the full draft response structure or error conditions, but the rich parameter schema compensates. Minor gap in return-value detail makes it slightly below complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema already documents all seven parameters in detail, including mention resolution rules, fingerprinting, and confirm_token requirements. The description adds workflow-level context but no per-parameter semantics beyond what the schema provides, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description states a specific verb and resource: 'Отправка текстового сообщения' (sending a text message). It further specifies the two-step draft/confirm behavior, which clearly distinguishes this tool from sibling send_file and other message tools. An agent can tell what it does and how it differs from a plain send.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear workflow guidance: first call without confirm to get a draft that is not sent, then call with confirm:true and confirm_token to send. It does not explicitly name alternatives or exclusion conditions relative to siblings, but the 'text message' scope and two-step confirmation make the intended usage clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_reactionSet or remove reactionA

Ставит или снимает реакцию на сообщение ОДНИМ вызовом, без confirm (реверсибельно). type - целочисленный id реакции (артворк, НЕ emoji) из поля reactions прочитанного сообщения. Тип валидируется по карте ДО отправки: неизвестный отвергается на входе и на провод не уходит. remove:true снимает ранее поставленную реакцию тем же инструментом.

ParametersJSON Schema
NameRequiredDescriptionDefault
chatYesChatId либо поисковый запрос для резолва чата
typeYesЦелочисленный id реакции (артворк) из reactions сообщения; НЕ emoji
removeNotrue - снять реакцию (Action:REMOVE); по умолчанию поставить
message_idYesTimestamp целевого сообщения в микросекундах (строка)

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses validation before sending, reversibility, and that remove:true removes previously set reaction. Annotations provide no behavioral details, so description adds significant value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with key action. Slightly dense but no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple mutation tool with no output schema, description covers validation, reversibility, and core behavior. Adequate for the complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but description adds context: type is integer id (not emoji) from reactions field, and remove removes a previously set reaction by same tool.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the tool sets or removes reactions in one call. Title and name align. Distinguishes from sibling tools like list_reactions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implicitly describes usage (set/remove reaction) but lacks explicit guidance on when to use vs alternatives or when not to use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

vote_in_pollVote in pollA

Голос в опросе в два шага (draft->confirm). Форма Vote{ChatId,Timestamp,Action:0,Choices} подтверждена живьём (2026-07-17, commit_status:1 FULLY_COMMITTED), включая смену выбора: повторная отправка ЗАМЕНЯЕТ голос, choices - ПОЛНЫЙ набор (несколько вариантов - все индексы в одном choices). Без confirm возвращает draft и НЕ голосует; с confirm:true и confirm_token голосует. Confirm сохранён, потому что сам факт голоса необратим (voted_count растёт, в не-анонимном опросе голосующий попадает в список голосовавших); отменить голос до нуля протоколом не подтверждено. Choices на шаге confirm сверяются с подтверждёнными. После голоса проверяйте myChoices через get_poll.

ParametersJSON Schema
NameRequiredDescriptionDefault
chatYesChatId либо поисковый запрос для резолва чата
choicesYesВыбранные варианты (индексы/id). Единица доко-выведена (§11.4)
confirmNofalse/отсутствует - вернуть draft; true - проголосовать (необратимо)
message_idYesTimestamp сообщения-опроса в микросекундах (строка)
confirm_tokenNoТокен из draft. Обязателен при confirm:true

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the sparse annotations (all false), detailing the irreversibility of voting, replacement semantics, draft-confirm mechanism, and that canceling to zero is not supported. Annotations only indicate non-read-only, non-idempotent, non-destructive, so the description adds critical behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single coherent paragraph with minimal waste. It front-loads the key mechanism and each sentence adds behavioral information. Slightly dense but effective.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the main workflow and key constraints (irreversibility, replace behavior, two-step process). It lacks explicit return value details and error conditions, but given no output schema, it provides sufficient context for usage. The reference to checking myChoices via get_poll helps close the loop.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

All 5 parameters are described in the schema (100% coverage), but the description adds extra meaning: choices must be a full set, confirm token origin, and verification at confirm step. This adds moderate value beyond the schema's descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool is for voting in a poll via a two-step draft->confirm process. It uses specific verbs and distinguishes the mechanism from simple voting. The name and title align, and the description explains the unique behavior of replacing votes and the confirm token.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implicitly tells when to use the tool (to vote in a poll) and describes the two-step flow, but it does not explicitly state when to use this tool versus alternatives like get_poll. No exclusions or alternatives are mentioned, though the sibling context suggests get_poll for reading results.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A3.9/5.0
Disambiguation4/5

Each tool has a distinct operational purpose, and the descriptions carefully clarify boundaries (e.g. full reactions vs. embedded reaction summaries, history pagination vs. context window). However, the cluster of message-reading tools (get_history, get_message_context, get_thread, list_reactions) could still cause some misselection without close reading.

Naming Consistency4/5

Most tools follow a clear verb_noun snake_case pattern: list_chats, send_message, delete_message, get_poll. Minor deviations like mark_read, vote_in_poll, and bare search break the strict pattern but are still predictable and readable.

Tool Count4/5

At 19 tools, the server is above the typical sweet spot but not bloated: each tool addresses a concrete messaging capability (chat listing, history, threads, reactions, polls, file handling, moderation). The breadth is justified by the messenger domain, though a few read variants could arguably be consolidated.

Completeness4/5

Core messaging lifecycles are covered: send, read, edit, delete, react, pin, search, poll voting, and attachment download. Notable gaps like creating chats, creating polls, forwarding messages, and sending voice/gallery media exist, but they are workable gaps for an assistant operating on existing conversations.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    F
    maintenance
    An MCP server for MAX Messenger (Russia's national messenger by VK) that enables AI clients to send and read messages, manage chats and members, send media, and more through 21 tools.
    21
    75
    7
    Unlicense - libtelnet variant
  • A
    license
    A
    quality
    A
    maintenance
    MCP server that acts as a gateway to Telegram, providing AI-optimized tools for messaging, search, and chat management via MTProto. Supports multi-user authentication with QR login and HTTP/stdio transports.
    8
    2
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server that controls WhatsApp Desktop via Chrome DevTools Protocol using the user's real session, enabling tools to list chats, read messages, search contacts, and send messages with simulated typing and rate limiting.
    39
    1
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/conarti/yandex-messenger-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server