MCP server that connects AI agents to humans via Discord threads (Human-Agent Loop Over Bot). Provides both low-level Discord access and a high-level, thread-based human-in-the-loop conversation model with user whitelisting.
halobot has 9 tools with clear verb-noun naming (list_*, send_*, get_*, start_*, halo_*). All tools have descriptions (avg ~120 chars, within baseline 34-392). Input schemas are present with type definitions and parameter descriptions. However, output schemas are completely undocumented, no tool specifies what fields it returns, forcing LLMs to infer structure. Error handling is minimal; no recovery guidance or actionable error messages. The halo_* tools form a coherent human-in-the-loop pattern but lack idempotency guarantees and confirmation steps for destructive operations (send_message, start_thread). Parameter descriptions are adequate but lack format constraints (e.g., no regex for IDs, no min/max for timeout_seconds). Missing: pagination for list_channels/list_guilds, batch operations, and field-level output documentation.
Returns the most recent messages from the in-memory message cache (event-driven, no API calls). Useful for monitoring incoming messages in real-time.
Sends a message from the agent to the human in an active conversation thread. Messages longer than MAX_MESSAGE_LENGTH are automatically chunked.
Initiates a new human-in-the-loop conversation thread. Creates a thread in the specified channel, tags the user, and returns the thread ID for use in subsequent halo_* calls. Requires DISCORD_ALLOWED_USERS to be configured.
Polls for a reply from the human in an active conversation thread. Uses event-driven message cache (no API calls). Blocks until a reply is received or the timeout is reached.
Lists all text-based channels in a given guild (server), including their IDs and names.
Returns a list of all Discord servers (guilds) the bot is a member of, including their IDs and names.
Output schemas completely undocumented. No tool specifies return fields, types, or structure. LLMs cannot plan downstream calls or extract required data (e.g., what does list_guilds return? guild_id + name only, or more fields?). Violates pattern:tool and pattern:response-shaper.
No pagination support on list_* tools. list_guilds and list_channels accept no limit/offset/cursor parameters. If a bot is in 100+ guilds or a guild has 50+ channels, results will blow context window. Violates pattern:paginated-result.
Destructive operations (send_message, start_thread, halo_send) lack confirmation or dry-run support. Agents can accidentally spam channels or create unwanted threads. No idempotency guarantees documented. Violates pattern:confirmation-request and pattern:idempotent-operation.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | F | 44 | 2026-07-28+ | v2 |
Sends a message to a specified channel. Messages longer than MAX_MESSAGE_LENGTH are automatically chunked.
Sends a message to a thread. Messages longer than MAX_MESSAGE_LENGTH are automatically chunked.
Creates a new thread in a specified channel with an optional name.
Parameter descriptions lack format constraints. timeout_seconds has no min/max (default 300, but what's valid range?). channel_id, guild_id, thread_id, user_id have no format hints (are they numeric, alphanumeric, snowflake IDs?). Violates pattern:constrained-input.
Error handling is silent. No tool description explains what errors can occur, how to recover, or what the LLM should do next. E.g., if send_message fails due to permission denied, should the agent retry, ask the user, or try a different channel? Violates pattern:recovery-guide and pattern:error-classification.