MCP server for human-in-the-loop approvals and questions via Slack or Telegram
This server defines 2 human-in-the-loop tools with clear, well-written descriptions that explicitly state what each tool does and when to use it. Both tools have properly typed input schemas with parameter descriptions. However, there are significant gaps in output schema documentation, error handling guidance, and parameter constraints that prevent a higher score. The naming is verb-based and unambiguous. Tool descriptions are 150 - 250 characters, which falls within the production baseline (p10=34, p90=392). Both parameters across tools have descriptions and inferred types. The critical weakness is lack of documented output schemas, ask_human returns a string but the contract is implicit; request_approval returns a dict but the structure and field types are not formally documented in the code sample provided.
Ask the human a free-form question and wait for their text reply. Use this when you need information only a human can provide: a preference, a clarification, credentials, or a decision on an ambiguous situation. The tool blocks until the human replies or the timeout expires.
Ask the human to approve or deny a proposed action before executing it. Call this before any irreversible or high-stakes action (deleting data, sending messages, modifying production systems, spending money, etc.). The tool blocks until the human approves/denies or the timeout expires. Returns {"approved": bool, "reason": str} where reason is the human's username or name if available.
Output schema not formally documented. ask_human returns str but no type annotation in FastMCP decorator; request_approval returns dict but the structure (approved: bool, reason: str) is only documented in the docstring, not in a schema field. LLMs cannot plan downstream calls or extract fields reliably without a formal output contract.
No error recovery guidance in tool descriptions. Both tools mention timeout behavior ('The tool blocks until the human replies or the timeout expires') but do not tell the LLM what to do if timeout occurs. For request_approval, the description does not clarify what happens if the human denies approval, does the agent retry, escalate, or abort? This violates the recovery-guide pattern.
No input validation constraints documented. The 'question' and 'action' parameters accept free-form strings with no stated length limits, character restrictions, or format guidance. If question exceeds Slack's message length, the tool silently fails. Parameter descriptions should include constraints like 'max 500 characters' or 'no newlines'.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 58 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 57 | - | v1 |
No timeout value documented. The code mentions 'CALL_HUMAN_TIMEOUT' but the descriptions do not state what the timeout is (e.g., 300 seconds, 1 hour). LLMs cannot reason about whether to use the tool if they don't know how long to wait.
Implicit request_approval return structure. The docstring says 'Returns {"approved": bool, "reason": str}' but this is embedded in prose, not a formal output schema. If the agent expects a different field name or type, it will fail silently. A JSON Schema definition in the tool metadata would prevent this.