herald
Provides tools for sending messages, files, and structured updates to Telegram group topics, as well as capturing incoming messages from working groups into a local inbox buffer.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@heraldSend the latest report to the main topic"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
herald
Канал наружу. Ассистент отправляет готовый материал — текст, таблицу, файл, скриншот — в твой рабочий мессенджер, откуда ты пересылаешь его дальше.
Статус: 🧪 первый рабочий прототип: MCP → Telegram-топик.
Зачем
Две причины, и вторая важнее.
Очевидная. Таблицы, длинные разборы и скриншоты копируются из терминала криво. Форматирование рассыпается, картинку вообще не скопируешь. Ты говоришь «отправь это в такой-то топик» — и материал приходит целым.
Неочевидная: это чинит авторство.
Сейчас, когда ты вручную пересылаешь текст ассистента в рабочий чат, он уходит под твоим именем. В выгрузке эти сообщения неотличимы от твоих собственных — ни пометки, ни поля. Проверено на живом чате: тринадцать сообщений от одного автора, часть из которых написана машиной, и различить их можно только по стилю. Догадка по стилю — это ровно то, что запрещает mnemo: не угадывать.
Если пишет бот, а ты пересылаешь его сообщение — Telegram сохраняет
forwarded_from с именем бота. Машинный текст становится машинно опознаваемым.
Автоматически, без меток и дисциплины.
Related MCP server: Straight Connect
Устройство
Ядро — MCP-сервер с токеном и транспортом. Небольшой общий скилл поверх него учит Claude/Codex выбирать структурированную команду и соблюдать стиль.
ассистент ──MCP──> herald ──адаптер──> Telegram (топик группы)
│
└──> другие платформы, когда появятсяИнтерфейс узкий: «отправить <это> в <туда>». Внутри — один адаптер под Telegram.
Абстракцию под платформы заранее не строим. Интерфейс появляется, когда платформ становится две, а не в ожидании второй. Так вышло с парсерами в mnemo: реестр завели на втором формате, и он сразу был правильной формы, потому что опирался на два реальных случая, а не на догадку об одном.
Безопасность — свойством, а не процедурой
herald пишет только в твой стейджинг. Начальству пересылаешь ты, руками.
Это сильнее, чем «бот с подтверждением»: он физически не может отправить что-то не то в чат с заказчиком, потому что не знает туда дороги. Гарантия структурная, а не «мы договорились подтверждать».
Правило: список разрешённых адресатов задаётся в конфиге и не расширяется ассистентом.
Что нужно для запуска
токен бота (BotFather), хранится вне репозитория;
идентификатор группы-стейджинга и карта топиков «имя → id»;
бот добавлен в группу с правом писать.
Первая версия
Сейчас herald — локальный Python MCP-сервер со stdio-транспортом. Он предоставляет девять команд:
list_destinations— посмотреть разрешённые проекты и их маршруты;send_update— короткий управленческий апдейт из отдельных полей;send_file— отправка файла или изображения из разрешённого каталога;send_text— ручная отправка точного или нестандартного текста;notify_completion— уведомление о завершении задачи, когда у задачи явно установлен такой флаг или дана такая инструкция.inbox_status,inbox_fetch,inbox_export,inbox_done— состояние, чтение, выдача и подтверждение локального буфера захваченных сообщений.
Команды проходят один путь: проект → маршрут → адаптер → Telegram. Сам herald не наблюдает за задачами и не решает, когда уведомлять: это делает Codex, Claude или их lifecycle-hook.
Каждое сообщение получает компактную подпись:
— Codex · GPT · herald · MCPНастройка
Проект использует uv. Версия Python зафиксирована в .python-version, версия
пакета и зависимости — в pyproject.toml, точные версии — в uv.lock.
uv sync
mkdir -p ~/.config/herald
cp config.example.toml ~/.config/herald/config.tomlВ ~/.config/herald/config.toml задаются платформы, разрешённые маршруты,
проекты и каталоги файлов. Это SSOT: MCP-команда может выбрать только
существующий маршрут, а файл — только путь внутри allowed_roots. Конфиг
перечитывается перед каждым вызовом, поэтому после добавления проекта или топика
сервер перезапускать не нужно. Telegram-токен по умолчанию читается из отдельного
файла:
printf '%s\n' 'TOKEN_FROM_BOTFATHER' > ~/.config/herald/telegram.token
chmod 600 ~/.config/herald/telegram.tokenСам токен и рабочий конфиг не хранятся в репозитории. Вместо файла можно задать
token_env = "HERALD_TELEGRAM_BOT_TOKEN" в секции платформы.
Чтобы узнать chat_id и topic_id, добавь бота в staging-группу, отправь
сообщение в нужный топик и посмотри ответ getUpdates: message.chat.id — это
chat_id, а message.message_thread_id — topic_id.
Проект задаёт маршрут по умолчанию:
[routes.aleon]
platform = "telegram"
chat_id = "-1001234567890"
topic_id = 2
[projects.aleon]
label = "Алеон"
description = "Проект Алеон и материалы, относящиеся к нему."
route = "aleon"
[files]
allowed_roots = ["~/Herald/outbox"]
max_bytes = 50000000Создай каталог ~/Herald/outbox и клади туда только то, что разрешено
отправлять ассистенту. Не открывай ему целиком домашний каталог или все рабочие
репозитории: среди них часто лежат .env, ключи и клиентские данные.
Обычно ассистент передаёт только project = "aleon"; поле route нужно лишь
для явного переопределения. subject — краткая тема для подписи сообщения, а не
Telegram topic_id.
Форматирование
Формат нужно выбрать явно: plain либо html. Для обычного сообщения человеку
предпочтителен format = "html"; herald добавит parse_mode = "HTML".
Поддерживаются теги
Telegram вроде <b>, <i>, <u>, <s>, <tg-spoiler>, <a href="…">,
<code>, <pre> и <blockquote>. Служебная подпись и ссылка экранируются самим
herald, HTML основного текста передаётся как есть.
Если при format = "html" передать экранированные теги вроде <b>,
herald отклонит вызов и подскажет передать сырой <b>. Это не даёт ассистенту
молча прислать видимые HTML-теги вместо форматирования.
Пресеты сообщения
Для send_update сервер сам собирает HTML из полей summary, completed,
blockers, decisions_needed, client_questions и next_steps, экранирует
значения и проверяет длину каждого пункта. Это основной путь для статусов и
отчётов: модель не присылает готовую портянку.
Поле preset задаёт плотность материала:
brief— вопрос или тема и прямой короткий ответ, без простыни;standard— компактное структурированное сообщение;detailed— полный отчёт с разделами и деталями.
Для send_update и notify_completion по умолчанию используется brief.
send_text остаётся свободной формой и требует явного пресета. Перед отправкой проверяется
лимит Telegram: не более 4096 отображаемых символов с учётом HTML-разметки.
Автоматического разбиения длинного HTML в этой версии ещё нет.
send_file в режиме auto отправляет небольшие JPEG/PNG/WebP как фотографию,
остальное — как документ. Подпись ограничена 1024 отображаемыми символами;
документ — настроенным лимитом до 50 МБ.
Глобальное подключение
Используй абсолютный путь к checkout, чтобы сервер был доступен из любого проекта и любого нового чата.
Codex (пользовательский ~/.codex/config.toml):
codex mcp add herald -- uv run --directory /absolute/path/to/herald heraldClaude Code (важен scope user, а не default local):
claude mcp add --scope user herald -- \
uv run --directory /absolute/path/to/herald heraldПосле добавления перезапусти открытые клиенты. Проверка:
codex mcp get herald
claude mcp get heraldОбщий скилл лежит в skills/herald-send. Чтобы обе системы использовали один
источник без копий, установи символические ссылки:
mkdir -p ~/.claude/skills ~/.agents/skills
ln -s /absolute/path/to/herald/skills/herald-send ~/.claude/skills/herald-send
ln -s /absolute/path/to/herald/skills/herald-send ~/.agents/skills/herald-sendВ Claude он вызывается как /herald-send, в Codex — как $herald-send.
Инструкция предлагает применить доступный humanizer, но не требует и не
копирует его: если такого скилла нет, отправка продолжается по встроенному
чек-листу.
Разработка
uv run pytestТесты не обращаются к Telegram: HTTP-ответы подменяются локально, а MCP-контракт проверяется in-memory клиентом официального SDK.
Место в связке
Проект | Роль |
архив материала с провенансом + факты, решения, вопросы | |
дейлики: состояние и синк в issues | |
herald | канал наружу к людям |
herald ничего не хранит. Он отправляет то, что ему дали, и не знает, откуда это взялось. Связь с остальными — только через ссылку на запись в тексте сообщения (см. ниже): отправил разбор — вставил ссылку, по которой видно, на каком материале он стоит.
Захват рабочих чатов
Вторая половина того же канала: herald не только отправляет наружу, но и вычитывает рабочие группы в локальный буфер, откуда ассистент забирает их сам — вместо ручного копирования сообщений, файлов и скриншотов.
Смысл не в удобстве. Копипаста из Telegram подписывает пересланное сообщение тем, кто его переслал; Bot API отдаёт настоящего автора, если тот не скрыл себя. На живом рабочем чате это разница в 16 сообщениях из 21.
Захват сейчас рассчитан на Unix (flock); готовый сервис — на Linux с systemd.
Обычная отправка через MCP от systemd не зависит.
Что нужно от Telegram
бот добавлен в рабочую группу;
privacy-режим выключен у BotFather — иначе бот видит только команды и ответы себе. Настройка применяется лишь после переприглашения бота в группу;
право «отправлять сообщения» можно снять: читать это не мешает, а случайно написать в рабочий чат станет нечем.
Пределы, которые не обходятся
истории нет. Бот не прочитает ни одного сообщения, отправленного до того, как его добавили. Всё, что было раньше, вносится выгрузкой чата;
очередь живёт около суток. Простой меньше суток демон догоняет сам, дольше — сообщения потеряны. Отсюда
Restart=alwaysи heartbeat вinbox_status;скачивание до 20 МБ. Больший файл записью не теряется: остаётся строка с пометкой, что скачать не удалось, и оригинал в Telegram.
Настройка захвата
В ~/.config/herald/config.toml (или в файле, на который указывает
HERALD_CONFIG — им же удобно пробовать, не трогая боевой):
[capture]
enabled = true # в поставляемом примере false, иначе демон откажется стартовать
ttl_days = 7
capture_self = true # твои собственные сообщения тоже нужны: половина
# договорённостей звучит в твоих же ответах
# self_id = 123456789 # обязателен, только если capture_self = false
[[capture.chats]]
id = -1001234567890 # ЧИСЛО, без кавычек — в отличие от chat_id в [routes]
slug = "aleon" # войдёт в ссылки ctx: и в имя каталога буфераСекции [routes] и [projects] для захвата не нужны — конфиг может быть
только читающим. А вот [platforms.telegram] с токеном нужен всегда: читать
без токена нельзя, даже если отправлять нечего.
chat_id берётся из getUpdates, но демон опрашивает тот же токен, а двух
опросов Telegram не допускает. Поэтому узнавай id до запуска демона или
остановив его.
Запуск
uv run herald-capture --once # один опрос и выход: проверить настройку
uv run herald-capture # рабочий режимДемон один: два опроса на один токен Telegram отвергает, поэтому второй
экземпляр честно откажется стартовать. Лок берётся по токену, а не по базе, и
лежит в ~/.local/share/herald/locks: это общий путь для systemd с PrivateTmp
и ручного --once.
Отправка при этом не мешает — конфликтует только опрос с опросом.
Готовый юнит — herald-capture.service в корне репозитория:
cp herald-capture.service ~/.config/systemd/user/
$EDITOR ~/.config/systemd/user/herald-capture.service
systemctl --user daemon-reload
systemctl --user enable --now herald-captureВ юните поправь под себя:
ExecStart— путь к клону (в файле стоит%h/GitHub/herald);ReadWritePaths— если менялdatabaseилиfiles_dir, иначеProtectSystem=strictне даст туда писать;Environment=HERALD_CONFIG=…— если конфиг лежит не по умолчанию.
Пути в конфиге меняются только с рестартом. Демон открывает базу и каталог
файлов один раз; подхватывать их на лету значило бы, что он пишет в старую базу,
пока ассистент читает новую и видит пустой буфер. Про смену пути в логе будет
предупреждение. Всё остальное — список чатов, enabled, TTL — действует сразу.
Что видит ассистент
Команда | Что делает |
| объём буфера по чатам и heartbeat демона, без содержимого |
| основной путь: самодостаточный каталог для импорта в архив |
— |
|
— |
|
| только строки, без копирования файлов — почитать текст |
| зафиксировано в архиве → удаляет скачанные копии, строка живёт TTL |
Инструменты видны всегда, но при capture.enabled = false отвечают отказом.
Как захваченное попадает в архив
inbox_export пишет каталог такого вида:
bundle/
├── inbox.json строки сообщений; local_path — ОТНОСИТЕЛЬНЫЙ путь
└── files/<slug>/… сами вложенияОтносительность здесь не деталь: архив обязан отвергать источник, который адресует что-либо вне своего каталога, — правило существует потому, что выгрузки приходят от третьих лиц. Отдавать сырые строки с абсолютными путями значит получить все вложения в статусе «пропало» при живых файлах на диске.
Дальше — обычный импорт в mnemo:
python3 …/mnemo/scripts/mnemo_import.py --export _chat-export --source bundle
python3 …/mnemo/scripts/mnemo_import.py --export _chat-export --source bundle --applyСтрока сообщения. Обязательные поля — без любого из них архив откажется
принять каталог, и это намеренно: без author_name импорт прошёл бы, подписав
все сообщения как «неизвестно», а тихая порча хуже честного отказа.
Поле | Обяз. | Значение |
| да | числовой id чата |
| да | номер сообщения; уникален внутри чата |
| да | тема; из него берётся slug экспорта |
| да | ISO-8601 с зоной |
| да | кто отправил (не обязательно автор — см. |
| нет → написал отправитель; | |
| показанное имя; автором не считается, когда | |
| нет | id и время оригинала пересылки |
| нет |
|
| нет | есть вложение; вместе с пустым |
| нет | как прислал Telegram |
| нет | путь внутри каталога выгрузки либо |
| нет | почему файла нет — попадает в архив, а не теряется |
| нет | как есть |
Один каталог — один чат: номера сообщений в разных чатах повторяются, и
смешение молча теряло бы часть. inbox_export отказывается собирать пачку из
нескольких чатов.
Буфер — не архив. Он неполон (нет истории, нет удалений) и живёт неделю; разбираться, что из этого нужно, — работа архива, а не буфера.
Ссылки на записи
Единый формат цитирования для всей связки:
ctx:<slug>#<id> ctx:aleon#i004 ctx:sozvony#q012ctx — от «context», а не от имени инструмента. Программа, которая ведёт архив,
может смениться; ссылка не должна от этого умирать. slug — тема (экспорт),
id — запись внутри неё: i материал, q вопрос, t требование,
r изъятие.
Нормативное описание —
mnemo/SPEC/CITATION.md.
Общего у трёх проектов — три опубликованных версионированных формата: ссылка, манифест и контракт чтения. Ничего исполняемого: ни библиотеки, ни базы, ни общего процесса. Тот, кому нужны данные архива, вызывает команду mnemo и получает JSON — так же, как herald вызывает Telegram.
Лицензии
Репозиторий лицензирован по частям:
Путь | Лицензия |
| |
всё остальное — сервер, capture, MCP, навык, конфиг и тесты |
Для производных редакций документации нужны указание авторства, отметка об изменениях и та же лицензия. Для изменённой сетевой версии Herald пользователям должен быть доступен соответствующий исходный код. Сообщения, файлы и другие пользовательские материалы, проходящие через Herald, этими лицензиями не перелицензируются.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityCmaintenanceAn MCP server that enables interaction with Telegram to send, read, and search messages across chats and dialogs. It supports waiting for incoming messages and retrieving conversation history through natural language commands.194MIT
- Flicense-qualityDmaintenanceAn MCP server for communication service connectors that currently provides multi-account Telegram integration with granular tool access and security controls. It allows AI models to manage messages, chats, and media across various accounts through a flexible, extensible routing architecture.1
- Alicense-qualityBmaintenanceMCP server for Telegram integration with Command Code, enabling AI agents to send messages, photos, files, and read updates via Telegram.1MIT
- Alicense-qualityDmaintenanceAn MCP server enabling AI agents to interact with users via Telegram, supporting message and image sending, inline quick replies, and waiting for user responses.7MIT
Related MCP Connectors
Telegram bridge for your MCP-compatible agent. Bidirectional, no LLM in our stack.
Driflyte MCP server which lets AI assistants query topic-specific knowledge from web and GitHub.
MCP server for Gainium — manage trading bots, deals, and balances via AI assistants
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/ZenonEl/herald'
If you have feedback or need assistance with the MCP directory API, please join our Discord server