hitl-mcp
Click on "Deploy 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., "@hitl-mcpAsk a human for approval before deploying to production"
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.
hitl-mcp
Connect your AI agent to a conversation you already use. When the agent needs you, it asks there.
HITL-MCP is an ephemeral communication bridge between an AI agent execution and a human.
It is not a task manager, messaging platform, SaaS product, centralized gateway, or agent orchestration system.
The agent owns its own task state and context. HITL only provides the communication bridge.
Core idea
AGENT
↓
MCP stdio
↓
HITL Core
↓
Channel Adapter
↓
Slack / WhatsApp / …
↓
HumanWhen the agent needs a decision, confirmation, or input, it calls ask_human. The question appears in a channel you already use. Your reply resolves the call. Then the pending request disappears from memory.
Nothing about the interaction is stored by HITL.
Related MCP server: LoopIn MCP Server
Principles
Principle | Meaning |
Local-first | The MCP runs on your machine |
stdio MVP | No HTTP server for the MVP |
No central backend | No HITL cloud, no shared gateway |
No HITL account | No email, password, or centralized identity |
No task database | Agents keep their own state |
Ephemeral pending requests | In memory only; gone when the process exits |
User-owned providers | Your Slack app / your WhatsApp session |
Persistent config only | Default target + provider prefs locally |
Credentials separated | Tokens/sessions stored apart from runtime state |
Per-call overrides | Override the default target without changing config |
Architectural rule: if a feature requires HITL to remember something after the current agent execution ends, that feature probably does not belong here.
MCP tools
ask_human
Send a question and wait for a human reply.
{
"question": "Which option should I choose?",
"target": { "channel": "slack", "targetId": "C123" },
"timeoutMs": 300000
}target is optional. Without it, the configured default target is used. An override never modifies the saved default.
notify_human
One-way notification. No pending request. No wait.
{
"message": "Deploy finished successfully."
}Quick start
npm install
npm run build
# Configure a default channel + target (fake channel for MVP)
npm run setup
# or: node dist/index.js setup
# Run the MCP server (stdio)
npm startMCP client config (example)
{
"mcpServers": {
"hitl": {
"command": "node",
"args": ["/absolute/path/to/hitl-mcp/dist/index.js"]
}
}
}MVP status
The first milestone is core + FakeChannelAdapter:
MCP stdio server
ask_human/notify_humanIn-memory pending requests + reply correlation
Local config + credential store
hitl-mcp setupTests without external providers
Slack (Socket Mode) and WhatsApp adapters are scaffolded under src/channels/ and are the next implementation milestone.
Documentation
Non-goals (MVP)
No task management, databases, REST API, HTTP server, web dashboard, user accounts, analytics, billing, cloud sync, conversation history, or agent orchestration.
License
MIT
Available Tools
2 toolsask_humanA
Send a question to the human via their configured communication channel and wait for a reply. Uses the default target unless an explicit target override is provided. Nothing is persisted.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | Optional per-call target override; does not change the saved default | |
| question | Yes | The question to ask the human | |
| timeoutMs | No | Optional timeout in milliseconds (default: 5 minutes) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does disclose important behavior: it waits for a reply, uses a default target unless overridden, and explicitly states 'Nothing is persisted.' It does not cover error or timeout behavior, but the core side-effect profile is transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each carrying distinct information: purpose, target selection behavior, and persistence guarantee. The main action is front-loaded with no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the essential invocation facts: what it does, how the target is chosen, and that nothing is persisted. However, since there is no output schema, it does not state what the tool returns after receiving a reply or how failures are surfaced, which is a minor gap in an otherwise complete description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents question, target override, and timeoutMs. The description reinforces the default-vs-override distinction but adds little beyond what the structured schema provides, meriting the baseline score.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb and resource: 'Send a question to the human... and wait for a reply.' This outcome-oriented phrasing distinguishes it from the sibling notify_human, which likely implies one-way notification without a response.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this tool should be used when a human reply is needed, but it never explicitly names notify_human as the alternative or states a 'when not to use' condition. The default-target vs override guidance is useful, but usage context remains implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
notify_humanA
Send a one-way notification to the human. Does not wait for a response. Nothing is persisted.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | Optional per-call target override; does not change the saved default | |
| message | Yes | The notification message |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and covers key facts: the notification is one-way, does not wait for a response, and nothing is persisted. It does not describe delivery or error behavior, but those are less critical for a simple notification.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action and key behavioral constraints. Every clause adds information and there is no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers core semantics (one-way, no wait, no persistence) and the schema covers the target override behavior. It omits how the default target is configured and doesn't address delivery acknowledgement, but for a simple tool with no output schema this is nearly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%: message is described and the nested target object documents channel, targetId, and override semantics. The tool description adds no parameter-level detail beyond that, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description uses a specific verb ('send') and resource ('one-way notification to the human'), and explicitly distinguishes from the sibling ask_human by noting it does not wait for a response. The purpose is unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly conveys when to use the tool: when a one-way, non-blocking notification is needed. It stops short of explicitly naming ask_human as the alternative or stating when not to use this tool, so it misses full marks.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v0.1.0- First observed
ask_human - First observed
notify_human
TDQS
Scored across 2 tools
ask_human and notify_human serve clearly distinct purposes: one requests a reply, the other sends a notification without waiting. There is no overlap or ambiguity in their intent.
Both tool names follow the same verb_noun pattern, with the target 'human' consistently placed as the object. The naming is clear, predictable, and easy to pattern-match.
Two tools is slightly below the typical 3-15 range, but the server's scope is narrow and both tools earn their place. The count feels slightly minimal but not inadequate for a basic HITL utility.
The tool surface covers the two core human-in-the-loop modes: interactive question-answering and one-way notification. Minor gaps like persistence or cancellation are absent, but they are not clearly implied by the stated purpose.
Maintenance
Related MCP Connectors
Zero-setup WhatsApp notifications + human-in-the-loop for AI agents — text 'join', send in 60s.
Human approvals, notifications, inbound webhooks, wake-ups for headless agents. Free trial: /try
Human-in-the-loop for AI coding agents — ask questions, get approvals via Slack.
Ephemeral REST chatrooms for AI agents to coordinate. Share a room URL — agents talk live.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI agents to request user decisions and send notifications via Discord when human intervention is required during autonomous tasks. It supports blocking questions with custom options, progress reporting, and persistent state for seamless remote task management.8MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to pause execution at critical decision points and request human review before proceeding. Provides tools for creating interrupts, polling for decisions, and managing approvals through a simple REST API interface.4 npmMIT
- AlicenseNot gradedqualityDmaintenanceHuman-in-the-loop approvals and notifications for AI agents via WhatsApp. Enables Cursor, Claude Code, and autonomous AI agents to reach users away from their computers.54 npmISC
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to request information and clarification from humans via Slack, supporting multiple roles and transport modes.-