A small MCP delivery service for AI assistants that sends messages and attachments to configured destinations
Herald demonstrates strong naming conventions (verb-first: send_*, list_*) and comprehensive parameter schemas with proper types and descriptions. Tool descriptions are detailed and context-rich, exceeding the 194-char baseline. However, output schemas are not explicitly documented in the visible code, responses are returned as dicts without formal schema declarations. Error handling guidance is minimal. Security considerations around file path validation are present but not fully documented. Overall, a solid B-grade implementation with good intent but incomplete schema documentation.
List allowed projects and their default Telegram destinations.
Send copy-ready text addressed directly to the client. This is the default tool when a manager should be able to copy the body without understanding the project or rewriting it. Each topic title must be a concrete subject taken from the client message or current project, such as "Оплата" or "Фотографии". Never use fixed report headings such as "Проблемы", "Нужно решить", or "Вопросы". Preserve all subjects raised by the client that are inside the requested scope; brevity removes internal reasoning, not necessary facts. Put concrete facts, proposals, and next actions in details. Address the client directly. Add question only when its answer blocks the next action now, and ask only the earliest unresolved dependency. Omit question when no answer is needed. Do not shorten by a fixed word or item count. Keep all facts the client needs; the only hard content limit is Telegram's 4096 visible characters.
Send a file attachment with caption and provenance metadata. Use for explicitly requested local attachments; paths must be allowed by the Herald config. The file must exist, be readable, and be within configured allowed_roots. File size is checked against the configured limit.
Send a formatted message with provenance metadata. Prefer format='html' for human-facing text. Use raw Telegram HTML tags: <b>, <i>, <u>, <s>, <code>, <pre>, <blockquote>, <tg-spoiler>, and <a href='...'> Never encode tags as <b>. brief is the default: concise, self-contained, client-ready copy without process or internal technical details. For an explanation, structure the text by named objects and list their concrete steps, properties, result, and limits. Do not replace details with a general conclusion or a prose comparison. standard adds necessary context; detailed is used only when explicitly requested and must still fit Telegram's 4096-character limit.
Output schemas not formally documented. Tools return dict/asdict(receipt) without explicit schema declarations. LLMs cannot reliably predict response structure for downstream chaining.
Error handling lacks recovery guidance. No documented error codes, retryability classification, or actionable next steps for common failures (invalid project, file not found, Telegram API errors).
File path validation (send_file) relies on config-based allowed_roots but validation logic is not visible in source. No documented constraints on file size, type, or path traversal prevention in the tool description.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 64 | 2026-07-28+ | v2 |
Send a concise, client-ready structured update. brief is the default. Write for a recipient who has not followed the project: put the concrete subject and current result in one self-contained summary using plain everyday language. Replace jargon and internal names with their practical meaning. Add only blockers, decisions, questions, or the next action needed now; completed is omitted when the summary already says what was done. Keep every field inside the exact subject requested by the user; never append unrelated project health. Include a client question only if the answer is not already available, the recipient controls it, and progress on the subject stops without it now. Build the dependency chain internally and ask only the first unresolved dependency, not questions about later steps. Omit the question section when nothing passes this test. Address the recipient directly. For client copy, put a required choice in client_questions, not the internal decisions_needed section. Do not include chronology, review or test logs, implementation details, tool names, or internal reasoning unless they change a client decision, risk, cost, or deadline. The server enforces preset-specific length and item limits and renders safe Telegram HTML.
Telegram token injection via environment variables (token_env, token_file) is secure, but no audit logging or permission scoping documented. No per-tool scope declarations (e.g., 'write:telegram', 'read:config').
send_update and send_client_copy accept optional arrays (completed, blockers, etc.) but no documented limits on array length or item count. Unbounded arrays could exceed Telegram's 4096-char limit.